1(function ($) { 2 'use strict'; 3 var mdModalWrap = $("#tlp-modal"); 4 var elementThumbInstances = []; 5 window.initTlpTeam = function () { 6 $(".rt-team-container").each(function (index) { 7 // The Elementor editor re-renders a widget on every edit, so this can run 8 // many times over containers that are already wired up. Bind each one once, 9 // otherwise every re-render stacks another set of handlers (and another 10 // Swiper) on the same markup. On the frontend this runs once anyway. 11 if ($(this).data("tlpTeamInit")) { 12 return; 13 } 14 $(this).data("tlpTeamInit", true); 15 16 var container = $(this), 17 str = container.attr("data-layout"), 18 popupBg = container.attr("data-popup-bg"), 19 id = $.trim(container.attr('id')), 20 randId = id.replace("rt-team-container-", ""), 21 scID = $.trim(container.attr("data-sc-id")), 22 mdPopup = $('.ttp-single-md-popup', container), 23 multiPopup = $('.ttp-multi-popup', document), 24 $default_order_by = $('.rt-order-by-action .order-by-default', container), 25 $default_order = $('.rt-sort-order-action .rt-sort-order-action-arrow', container), 26 $taxonomy_filter = $('.rt-filter-item-wrap.rt-tax-filter', container), 27 $pagination_wrap = $('.rt-pagination-wrap', container), 28 $loadmore = $('.rt-loadmore-action', container), 29 $infinite = $('.rt-infinite-action', container), 30 $page_prev_next = $('.rt-cb-page-prev-next', container), 31 $page_numbers = $('.rt-page-numbers', container), 32 html_loading = '<div class="rt-loading-overlay"></div><div class="rt-loading rt-ball-clip-rotate"><div></div></div>', 33 preLoader = container.find('.ttp-pre-loader'), 34 loader = container.find(".rt-content-loader"), 35 contentLoader = container.children(".rt-row.rt-content-loader"), 36 search_wrap = container.find(".rt-search-filter-wrap"), 37 ttp_order = '', 38 ttp_order_by = '', 39 ttp_taxonomy = '', 40 ttp_term = '', 41 ttp_search = '', 42 ttp_paged = 1, 43 temp_total_pages = parseInt($pagination_wrap.attr('data-total-pages'), 10), 44 ttp_total_pages = typeof (temp_total_pages) != 'undefined' && temp_total_pages != '' ? temp_total_pages : 1, 45 temp_posts_per_page = parseInt($pagination_wrap.attr('data-posts-per-page'), 10), 46 ttp_posta_per_page = typeof (temp_posts_per_page) != 'undefined' && temp_posts_per_page != '' ? temp_posts_per_page : 3, 47 infinite_status = 0, 48 paramsRequest = {}, 49 mIsotopeWrap = '', 50 IsotopeWrap = '', 51 // `ttp-masonry`, not `tpg-masonry` (that is The Post Grid's prefix, and no 52 // markup here ever carries it). While this looked for the wrong class it 53 // was always empty, so every `isMasonry.length` branch below was dead: 54 // AJAX-loaded items were appended without ever being handed to Isotope, 55 // so they kept `position: relative` and stacked on top of the absolutely 56 // positioned cards already on the page. 57 isMasonry = $('.rt-row.rt-content-loader.ttp-masonry', container), 58 isIsotope = $(".tlp-team-isotope", container), 59 IsoButton = $(".ttp-isotope-buttons", container), 60 IsoDropDownFilter = $("select.isotope-dropdown-filter", container), 61 isCarousel = $('.rt-carousel-holder', container), 62 caroThumb = $('.rttm-carousel-main', container), 63 isSpecial = $('.rt-special-wrapper', container), 64 placeholder_loading = function () { 65 if (loader.find('.rt-loading-overlay').length == 0) { 66 loader.addClass('ttp-pre-loader'); 67 loader.append(html_loading); 68 } 69 }, 70 remove_placeholder_loading = function () { 71 loader.find('.rt-loading').fadeOut(300); 72 loader.removeClass('ttp-pre-loader'); 73 $loadmore.removeClass('rt-lm-loading'); 74 $page_numbers.removeClass('rt-lm-loading'); 75 $infinite.removeClass('rt-active-elm'); 76 search_wrap.find('input').prop("disabled", false); 77 }, 78 check_query = function () { 79 if ($taxonomy_filter.length > 0) { 80 ttp_taxonomy = $taxonomy_filter.attr('data-taxonomy'); 81 var term; 82 if ($taxonomy_filter.hasClass('rt-filter-button-wrap')) { 83 term = $taxonomy_filter.find('.rt-filter-button-item.selected').attr('data-term'); 84 } else { 85 term = $taxonomy_filter.find('.term-default').attr('data-term'); 86 } 87 if (typeof (term) != 'undefined' && term != '') { 88 ttp_term = term; 89 } 90 } 91 if ($default_order_by.length > 0) { 92 var order_by_param = $default_order_by.attr('data-order-by'); 93 if (typeof (order_by_param) != 'undefined' && order_by_param != '' && (order_by_param.toLowerCase())) { 94 ttp_order_by = order_by_param; 95 } 96 } 97 if ($default_order_by.length > 0) { 98 var order_param = $default_order.attr('data-sort-order'); 99 if (typeof (order_param) != 'undefined' && order_param != '' && (order_param == 'DESC' || order_param == 'ASC')) { 100 ttp_order = order_param; 101 } 102 } 103 if (search_wrap.length > 0) { 104 ttp_search = $.trim(search_wrap.find('input').val()); 105 } 106 paramsRequest = { 107 'ttp_post__not_in': [20], 108 'scID': scID, 109 'order': ttp_order, 110 'order_by': ttp_order_by, 111 'taxonomy': ttp_taxonomy, 112 'term': ttp_term, 113 'paged': ttp_paged, 114 'action': 'ttp_Layout_Ajax_Action', 115 'search': ttp_search, 116 'tlp_nonce': ttp.nonce 117 }; 118 }, 119 infinite_scroll = function () { 120 if (infinite_status == 1 || $infinite.hasClass('rt-hidden-elm') || $pagination_wrap.length == 0) { 121 return; 122 } 123 var ajaxVisible = $pagination_wrap.offset().top, 124 ajaxScrollTop = $(window).scrollTop() + $(window).height(); 125 126 if (ajaxVisible <= (ajaxScrollTop) && (ajaxVisible + $(window).height()) > ajaxScrollTop) { 127 infinite_status = 1; //stop inifite scroll 128 ttp_paged = ttp_paged + 1; 129 $infinite.addClass('rt-active-elm'); 130 ajax_action(true, true); 131 } 132 }, 133 generateData = function (number) { 134 var result = []; 135 for (var i = 1; i < number + 1; i++) { 136 result.push(i); 137 } 138 return result; 139 }, 140 createPagination = function () { 141 if ($page_numbers.length > 0) { 142 $page_numbers.pagination({ 143 dataSource: generateData(ttp_total_pages * parseFloat(ttp_posta_per_page)), 144 pageSize: parseFloat(ttp_posta_per_page), 145 autoHidePrevious: true, 146 autoHideNext: true, 147 prevText: '<i class="fa fa-angle-double-left" aria-hidden="true"></i>', 148 nextText: '<i class="fa fa-angle-double-right" aria-hidden="true"></i>' 149 }); 150 $page_numbers.addHook('beforePaging', function (pagination) { 151 infinite_status = 1; 152 ttp_paged = pagination; 153 $page_numbers.addClass('rt-lm-loading'); 154 $page_numbers.pagination('disable'); 155 ajax_action(true, false); 156 }); 157 if (ttp_total_pages <= 1) { 158 $page_numbers.addClass('rt-hidden-elm'); 159 } else { 160 $page_numbers.removeClass('rt-hidden-elm'); 161 } 162 } 163 }, 164 getItemsArray = function (contentLoader) { 165 return contentLoader.find('.rt-grid-item').map(function () { 166 var _self = $(this); 167 if (_self.is(":visible")) { 168 return _self.attr("data-id"); 169 } 170 }).get(); 171 }, 172 animateAction = function () { 173 var $postItem = $('.rt-grid-item:not(.rt-ready-animation, .isotope-item)', container); 174 $postItem.addClass('rt-ready-animation animated fadeIn'); 175 }, 176 ajax_action = function (page_request, append) { 177 page_request = page_request || false; 178 append = append || false; 179 if (!page_request) { 180 ttp_paged = 1; 181 } 182 check_query(); 183 if (page_request == true && ttp_total_pages > 1 && paramsRequest.paged > ttp_total_pages) { 184 remove_placeholder_loading(); 185 return; 186 } 187 $.ajax({ 188 url: ttp.ajaxurl, 189 type: 'POST', 190 data: paramsRequest, 191 cache: false, 192 beforeSend: function () { 193 placeholder_loading(); 194 }, 195 success: function (data) { 196 if (!data.error) { 197 ttp_paged = data.paged; 198 ttp_total_pages = data.total_pages; 199 if (data.paged >= ttp_total_pages) { 200 if ($loadmore.length) { 201 $loadmore.addClass('rt-hidden-elm'); 202 } 203 if ($infinite.length) { 204 infinite_status = 1; 205 $infinite.addClass('rt-hidden-elm'); 206 } 207 if ($page_prev_next.length) { 208 if (!page_request) { 209 $page_prev_next.addClass('rt-hidden-elm'); 210 } else { 211 $page_prev_next.find('.rt-cb-prev-btn').removeClass('rt-disabled'); 212 $page_prev_next.find('.rt-cb-next-btn').addClass('rt-disabled'); 213 } 214 } 215 } else { 216 if ($loadmore.length) { 217 $loadmore.removeClass('rt-hidden-elm'); 218 } 219 if ($infinite.length) { 220 infinite_status = 0; 221 $infinite.removeClass('rt-hidden-elm'); 222 } 223 if ($page_prev_next.length) { 224 if (!page_request) { 225 $page_prev_next.removeClass('rt-hidden-elm'); 226 } else { 227 if (data.paged == 1) { 228 $page_prev_next.find('.rt-cb-prev-btn').addClass('rt-disabled'); 229 $page_prev_next.find('.rt-cb-next-btn').removeClass('rt-disabled'); 230 } else { 231 $page_prev_next.find('.rt-cb-prev-btn').removeClass('rt-disabled'); 232 $page_prev_next.find('.rt-cb-next-btn').removeClass('rt-disabled'); 233 } 234 } 235 } 236 } 237 if (append) { 238 if (isIsotope.length) { 239 // Parse ONCE â append(html) and isotope('appended', html) 240 // each parse the string separately, so Isotope was 241 // registering a detached copy of the new cards. 242 var $isoAppended = $(data.data); 243 244 // No reloadItems()/updateSortData(): they rebuild every Item 245 // and discard the positions `appended` just assigned, so the 246 // arrange that followed animated each new card in from the 247 // grid's origin. They are only for sort/filter data. 248 // 249 // Put the markup in the DOM but hand it to Isotope only once 250 // the images are in â registering earlier measures cards 251 // that have not finished loading, so they land at the wrong 252 // y and then visibly slide when the arrange corrects them. 253 // transitionDuration 0 keeps that correction from animating. 254 IsotopeWrap.append($isoAppended); 255 IsotopeWrap.imagesLoaded(function () { 256 preFunction(); 257 IsotopeWrap.isotope({ transitionDuration: 0 }); 258 IsotopeWrap.isotope('appended', $isoAppended); 259 IsotopeWrap.isotope(); 260 IsotopeWrap.isotope({ transitionDuration: '0.4s' }); 261 262 // preFunction() -> HeightResize() pins every 263 // .even-grid-item to the tallest card, from its OWN 264 // async imagesLoaded pass on the row. That lands after 265 // the arrange above, so if the cards just loaded are 266 // taller than the ones already there, the rows stay 267 // spaced by the old height and the new row overlaps the 268 // one above it. Registering on the same row queues this 269 // settle behind HeightResize's write. 270 contentLoader.imagesLoaded(function () { 271 IsotopeWrap.isotope({ transitionDuration: 0 }); 272 IsotopeWrap.isotope(); 273 IsotopeWrap.isotope({ transitionDuration: '0.4s' }); 274 }); 275 }); 276 } else if (isMasonry.length) { 277 // Parse the markup ONCE. `append(html)` and 278 // `isotope('appended', html)` each parse the string 279 // separately, so Isotope would end up tracking a second, 280 // detached copy instead of the cards actually on screen. 281 var $appended = $(data.data); 282 283 // No reloadItems()/updateSortData() here. `appended` 284 // already places the new cards instantly, in their slot; 285 // reloadItems() rebuilds every Item and throws those 286 // positions away, so the relayout below animated each new 287 // card in from the grid's top-left corner. Those two are 288 // only needed when sort/filter data changes. 289 mIsotopeWrap.append($appended).isotope('appended', $appended); 290 mIsotopeWrap.imagesLoaded(function () { 291 mIsotopeWrap.isotope('layout'); 292 }); 293 } else if (isSpecial.length) { 294 // Special paginates the thumbnail grid only - the stage 295 // and the feature panel have to survive the swap. 296 container.find('.special-items-wrapper').append(data.data);
297 syncSpecialActive(); 298 } else { 299 contentLoader.append(data.data); 300 } 301 } else { 302 if (isMasonry.length) { 303 // Filter / sort / search / AJAX pagination replace the 304 // whole row. reloadItems() is REQUIRED here (the exact 305 // opposite of the append case above): Isotope still holds 306 // Item objects for the elements html() just destroyed, so 307 // laying out without it positions detached nodes, sets the 308 // container to height 0 and leaves the new cards in normal 309 // flow spilling over whatever follows on the page. 310 // `.isotope()` with no args re-runs arrange, which is what 311 // actually measures and places items â `isotope('layout')` 312 // alone leaves item.size undefined and collapses the row. 313 mIsotopeWrap.html(data.data); 314 mIsotopeWrap.imagesLoaded(function () { 315 mIsotopeWrap.isotope('reloadItems').isotope(); 316 }); 317 } else if (isSpecial.length) { 318 container.find('.special-items-wrapper').html(data.data); 319 syncSpecialActive(); 320 } else { 321 contentLoader.html(data.data); 322 } 323 } 324 contentLoader.imagesLoaded(function () { 325 preFunction(); 326 remove_placeholder_loading(); 327 }); 328 if (!page_request) { 329 createPagination(); 330 } 331 animateAction(); 332 } else { 333 remove_placeholder_loading(); 334 } 335 }, 336 error: function () { 337 remove_placeholder_loading(); 338 } 339 }); 340 if ($('.paginationjs-pages .paginationjs-page', $page_numbers).length > 0) { 341 $page_numbers.pagination('enable'); 342 } 343 }, 344 syncSpecialActive = function () { 345 var activeId = container.find('#special-selected-wrapper').attr('data-id'), 346 cells = container.find('.special-items-wrapper .rt-grid-item'); 347 cells.removeClass('selected'); 348 if (activeId) { 349 cells.filter('[data-id="' + activeId + '"]').addClass('selected'); 350 } 351 }, 352 scrollToTopMember = function () { 353 // below 992 the stage stacks with the details BELOW the thumbnails, 354 // so bring the freshly loaded profile into view after a tap 355 if ($(window).width() < 992) { 356 $('html, body').animate({ 357 scrollTop: $('#special-selected-wrapper').offset().top - 35 358 }, 200); 359 } 360 }; 361 362 switch ($pagination_wrap.attr('data-type')) { 363 case 'load_more': 364 $loadmore.on('click', function () { 365 $(this).addClass('rt-lm-loading'); 366 ttp_paged = ttp_paged + 1; 367 ajax_action(true, true); 368 }); 369 break; 370 case 'pagination_ajax': 371 createPagination(); 372 break; 373 case 'pagination': 374 break; 375 case 'load_on_scroll': 376 $(window).on('scroll load', function () { 377 infinite_scroll(); 378 }); 379 break; 380 case 'page_prev_next': 381 if (ttp_paged == 1) { 382 $page_prev_next.find('.rt-cb-prev-btn').addClass('rt-disabled'); 383 } 384 if (ttp_paged == ttp_total_pages) { 385 $page_prev_next.find('.rt-cb-next-btn').addClass('rt-disabled'); 386 } 387 if (ttp_total_pages == 1) { 388 $page_prev_next.addClass('rt-hidden-elm'); 389 } 390 break; 391 } 392 393 if (str) { 394 var qsRegex, buttonFilter; 395 if (preLoader.find('.rt-loading-overlay').length == 0) { 396 preLoader.append(html_loading); 397 } 398 399 if (isCarousel.length) { 400 isCarousel.imagesLoaded(function () { 401 if (str === "carousel10") { 402 var carouselOptions = caroThumb.data('options'); 403 404 RTElementThumbCarousel(container, carouselOptions, elementThumbInstances, index); 405 remove_placeholder_loading(); 406 } else { 407 rtSliderInit($); 408 } 409 410 $(document).on('rttm_slider_loaded', function () { 411 remove_placeholder_loading(); 412 }); 413 }); 414 } else if (isIsotope.length) { 415 if (!buttonFilter) { 416 buttonFilter = IsoButton.find('button.selected').data('filter'); 417 } 418 IsotopeWrap = isIsotope.imagesLoaded(function () { 419 preFunction(); 420 // Grid Style. Isotope defaults to masonry AND passing a `masonry` 421 // option pins it there, so the hardcoded option below used to make 422 // "Even" render as masonry on every isotope layout. `ttp-even` is 423 // written on the row by the renderer; its absence means masonry 424 // (the shortcode path adds no class at all in that case). 425 IsotopeWrap.isotope($.extend({ 426 itemSelector: '.isotope-item', 427 filter: function () { 428 return buttonFilter ? $(this).is(buttonFilter) : true; 429 } 430 }, isIsotope.closest('.rt-row').hasClass('ttp-even') 431 ? { layoutMode: 'fitRows' } 432 : { layoutMode: 'masonry', masonry: { columnWidth: '.isotope-item' } })); 433 setTimeout(function () { 434 IsotopeWrap.isotope(); 435 remove_placeholder_loading(); 436 }, 100); 437 }); 438 439 IsoButton.on('click touchstart', 'button', function (e) { 440 e.preventDefault(); 441 buttonFilter = $(this).attr('data-filter'); 442 IsotopeWrap.isotope(); 443 $(this).parent().find('.selected').removeClass('selected'); 444 $(this).addClass('selected'); 445 }); 446 447 } else if (isSpecial.length) { 448 // Every member stays in the grid;
448 clicking one promotes it to the 449 // active thumbnail and loads that profile into the feature panel. 450 target = container.find('#special-selected-wrapper'); 451 452 var loadSpecialMember = function (id) { 453 if (!id) { 454 remove_placeholder_loading(); 455 return; 456 } 457 $.ajax({ 458 url: ttp.ajaxurl, 459 type: 'POST', 460 data: { memberId: id, scID: scID, action: 'rtGetSpecialLayoutData', tlp_nonce: ttp.nonce }, 461 cache: false, 462 beforeSend: function () { 463 placeholder_loading(); 464 }, 465 success: function (data) { 466 if (!data.error) { 467 target.attr('data-id', id); 468 target.html(data.data); 469 } 470 remove_placeholder_loading(); 471 }, 472 error: function () { 473 remove_placeholder_loading(); 474 } 475 }); 476 }; 477 478 var activeCell = container.find('.special-items-wrapper .rt-grid-item.selected').first(); 479 if (!activeCell.length) { 480 activeCell = container.find('.special-items-wrapper .rt-grid-item').first().addClass('selected'); 481 } 482 loadSpecialMember(activeCell.attr('data-id')); 483 484 container.on('click', '.special-items-wrapper .single-team-item.image-wrapper', function (e) { 485 e.preventDefault(); 486 var self = $(this), 487 cell = self.closest('.rt-grid-item'), 488 id = self.attr('data-id'); 489 490 if (!id || cell.hasClass('selected')) { 491 return; 492 } 493 494 container.find('.special-items-wrapper .rt-grid-item.selected').removeClass('selected'); 495 cell.addClass('selected'); 496 loadSpecialMember(id); 497 scrollToTopMember(); 498 }); 499 500 } else if (container.find('.rt-row.rt-content-loader.ttp-masonry').length) { 501 var masonryTarget = $('.rt-row.rt-content-loader.ttp-masonry', container); 502 mIsotopeWrap = masonryTarget.imagesLoaded(function () { 503 preFunction(); 504 mIsotopeWrap.isotope({ 505 itemSelector: '.masonry-grid-item', 506 masonry: { columnWidth: '.masonry-grid-item' }, 507 // Fade only. Isotope reveals appended items from 508 // `scale(0.001)` by default, which makes a card loaded by 509 // "Load more" balloon out of the centre of its slot on top of 510 // the fadeIn the cards already do for themselves. Overriding 511 // both styles drops the scale and leaves the card to simply 512 // appear where it belongs. 513 hiddenStyle: { opacity: 0 }, 514 visibleStyle: { opacity: 1 } 515 }); 516 remove_placeholder_loading(); 517 }); 518 } else { 519 var target = $('.rt-row.rt-content-loader.ttp-masonry', container); 520 target.imagesLoaded(function () { 521 preFunction(); 522 remove_placeholder_loading(); 523 }); 524 } 525 } 526 527 $('#' + id).on('click', '.rt-search-filter-wrap .rt-action', function (e) { 528 search_wrap.find('input').prop("disabled", true); 529 ajax_action(); 530 }); 531 $('#' + id).on('keypress', '.rt-search-filter-wrap .rt-search-input', function (e) { 532 if (e.which == 13) { 533 search_wrap.find('input').prop("disabled", true); 534 ajax_action(); 535 } 536 }); 537 $('#' + id).on('click', '.rt-filter-dropdown-wrap', function (event) { 538 var self = $(this); 539 self.toggleClass('active-dropdown'); 540 });// Dropdown click 541 $('#' + id).on('click', '.term-dropdown-item', function (event) { 542 $loadmore.addClass('rt-lm-loading'); 543 var $this_item = $(this), 544 default_target = $taxonomy_filter.find('.rt-filter-dropdown-default'), 545 old_param = default_target.attr('data-term'), 546 old_text = default_target.find('.rt-text').html(); 547 $this_item.parents('.rt-filter-dropdown-wrap').removeClass('active-dropdown'); 548 $this_item.parents('.rt-filter-dropdown-wrap').toggleClass('active-dropdown'); 549 default_target.attr('data-term', $this_item.attr('data-term')); 550 default_target.find('.rt-text').html($this_item.html()); 551 $this_item.attr('data-term', old_param); 552 $this_item.html(old_text); 553 ajax_action(); 554 });//term 555 $('#' + id).on('click', '.order-by-dropdown-item', function (event) { 556 $loadmore.addClass('rt-lm-loading'); 557 var $this_item = $(this), 558 old_param = $default_order_by.attr('data-order-by'), 559 old_text = $default_order_by.find('.rt-text-order-by').html(); 560 561 $this_item.parents('.rt-order-by-action').removeClass('active-dropdown'); 562 $this_item.parents('.rt-order-by-action').toggleClass('active-dropdown'); 563 $default_order_by.attr('data-order-by', $this_item.attr('data-order-by')); 564 $default_order_by.find('.rt-text-order-by').html($this_item.html()); 565 $this_item.attr('data-order-by', old_param); 566 $this_item.html(old_text); 567 ajax_action(); 568 });//Order By 569 570 //Sort Order 571 $('#' + id).on('click', '.rt-sort-order-action', function (event) { 572 $loadmore.addClass('rt-lm-loading'); 573 var $this_item = $(this), 574 $sort_order_elm = $('.rt-sort-order-action-arrow', $this_item), 575 sort_order_param = $sort_order_elm.attr('data-sort-order'); 576 if (typeof (sort_order_param) != 'undefined' && sort_order_param.toLowerCase() == 'desc') { 577 $default_order.attr('data-sort-order', 'ASC'); 578 } else { 579 $default_order.attr('data-sort-order', 'DESC'); 580 } 581 ajax_action(); 582 });//Sort Order 583 584 $taxonomy_filter.on('click touchstart', '.rt-filter-button-item', function () { 585 var self = $(this); 586 self.parents('.rt-filter-button-wrap').find('.rt-filter-button-item').removeClass('selected'); 587 self.addClass('selected'); 588 ajax_action(); 589 }); 590 591 $page_prev_next.on('click', '.rt-cb-prev-btn', function (event) { 592 if (ttp_paged <= 1) { 593 return; 594 } 595 ttp_paged = ttp_paged - 1; 596 ajax_action(true, false); 597 }); 598 $page_prev_next.on('click', '.rt-cb-next-btn', function (event) { 599 if (ttp_paged >= ttp_total_pages) { 600 return; 601 } 602 ttp_paged = ttp_paged + 1; 603 ajax_action(true, false); 604 }); 605 606 // md Popup 607 // The redesigned single popup can page between MEMBERS, so the open call is 608 // a named function and the member order is read from the triggers already in 609 // this container (deduped â a card usually has several triggers: the photo, 610 // the name and the Read More link). 611 var singleMemberIds = []; 612 613 function ttpCollectSingleMembers() { 614 singleMemberIds = []; 615 container.find('.ttp-single-md-popup[data-id]').each(function () { 616 var mid = String($(this).attr('data-id')); 617 if (mid && singleMemberIds.indexOf(mid) === -1) { 618 singleMemberIds.push(mid); 619 } 620 }); 621 } 622 623 function ttpOpenSinglePopup(id, isStep) { 624 id = String(id); 625 var data = "action=tlp_md_popup_single&id=" + id + "&tlp_nonce=" + ttp.nonce; 626 627 $.ajax({ 628 type: "post", 629 url: ttp.ajaxurl, 630 data: data, 631 beforeSend: function () { 632 mdModalWrap.addClass("tlp-modal-" + scID); 633 mdModalWrap.addClass('md-show'); 634 // Paging between members must NOT tear the card out: `.tlp-md-loading` is 635 // absolutely positioned, so replacing the holder with it leaves the shell 636 // with no in-flow content and the modal collapses to height 0 (measured: 637 // 583 -> 0 -> 538 across one click). Keep the outgoing card, drop 638 // `is-ready` so the existing CSS fades it to the spinner, and pin the 639 // height so it cannot collapse while the next member loads. 640 var $pop = mdModalWrap.find('.rttm-pop'); 641 if (isStep && $pop.length) { 642 ttpPopLockHeight(); 643 $pop.removeClass('is-ready'); 644 } else { 645 mdModalWrap.find('.tlp-md-content-holder').html('<div class="tlp-md-loading">Loading...</div>'); 646 } 647 // The visible card is `.rttm-pop` INSIDE .md-content, so painting the 648 // holder put the colour behind an opaque surface and the control 649 // appeared to do nothing. Set the surface token on the shell instead 650 // â every surface the popup owns reads it. 651 if (popupBg) { 652 mdModalWrap[0].style.setProperty('--rttm-pop-surface', popupBg); 653 } 654 // Carry the opening container's Primary Color onto the shared modal so 655 // the popup's pills, icon chips, skill bars and buttons use the same 656 // accent as the cards instead of the design's fallback blue. 657 var rttmPrim = (getComputedStyle(container[0]).getPropertyValue('--l1-primary') || '').trim(); 658 if (rttmPrim) { 659 mdModalWrap[0].style.setProperty('--rttm-pop-primary', rttmPrim); 660 } else { 661 mdModalWrap[0].style.removeProperty('--rttm-pop-primary'); 662 } 663 664 }, 665 success: function (data) { 666 mdModalWrap.find('.tlp-md-content-holder').html(data.data); 667 // The modal is shared by every shortcode on the page, so the member
668 // list travels ON it rather than in a per-container closure. 669 mdModalWrap.data('rttmMember', id); 670 mdModalWrap.data('rttmMembers', singleMemberIds); 671 ttpSyncPager(); 672 ttpRefreshGallery(); 673 ttpPopReady(ttpPopReleaseHeight); 674 }, 675 error: function (e) { 676 console.log(e); 677 } 678 }); 679 } 680 681 // Hide the pager when there is nothing to page to; otherwise it is a wrap-around 682 // so neither button is ever disabled. 683 // Reveal the card as ONE piece, only once its photos have decoded. The AJAX 684 // lands ~60ms after the open animation starts, so without this the modal 685 // scales in empty and the content then the image snap in mid-flight. 686 // The 8s guard means a blocked image can never leave the card hidden. 687 function ttpPopShell() { 688 return mdModalWrap.find('.md-content').first(); 689 } 690 691 // Pin the shell to its current height so the swap cannot collapse the modal. 692 function ttpPopLockHeight() { 693 var $el = ttpPopShell(); 694 if ($el.length) { 695 $el.css('height', $el.outerHeight() + 'px'); 696 } 697 } 698 699 // Ease from the pinned height to whatever the new member needs, then hand the 700 // box back to auto so nothing is left inline-styled. 701 function ttpPopReleaseHeight() {
702 var $el = ttpPopShell(); 703 if (!$el.length || !$el[0].style.height) { 704 return; 705 } 706 var from = $el[0].style.height; 707 $el.css('height', ''); 708 var to = $el.outerHeight(); 709 $el.css('height', from); 710 void $el[0].offsetWidth; 711 $el.css({ transition: 'height .35s cubic-bezier(.4, 0, .2, 1)', height: to + 'px' }); 712 setTimeout(function () { 713 $el.css({ transition: '', height: '' }); 714 }, 400); 715 } 716 717 function ttpPopReady(onReady) { 718 var pop = mdModalWrap.find('.rttm-pop'); 719 if (!pop.length) { 720 return; 721 } 722 pop.removeClass('is-ready'); 723 724 var imgs = pop.find('.rttm-pop-gallery img').get(), 725 pending = imgs.length, 726 reveal = function () { 727 // Force a style flush, then flip on the next frame. Adding the class 728 // in the same frame as the insert lets the browser collapse the 729 // before/after states into one, so the cross-fade never runs and the 730 // card just appears â which is what made the open look snappy/janky. 731 void pop[0].offsetWidth; 732 window.requestAnimationFrame(function () { 733 pop.addClass('is-ready'); 734 if (typeof onReady === 'function') { 735 onReady(); 736 } 737 }); 738 }; 739 740 if (!pending) { 741 reveal(); 742 return; 743 } 744 745 var settle = function () { 746 pending -= 1; 747 if (pending <= 0) { 748 reveal(); 749 } 750 }; 751 752 $.each(imgs, function (i, img) { 753 if (img.complete && img.naturalWidth) { 754 settle(); 755 } else { 756 $(img).one('load error', settle); 757 } 758 }); 759 760 setTimeout(reveal, 8000); 761 } 762 763 // Swiper measures the gallery while the modal is still mid open-transition 764 // (scaled down), so slide widths come out wrong and two part-slides show. 765 // Re-measure once the transition has settled. 766 function ttpRefreshGallery() { 767 setTimeout(function () { 768 mdModalWrap.find('.rttm-pop-gallery .swiper').each(function () { 769 if (this.swiper) { 770 this.swiper.update(); 771 } 772 }); 773 }, 450); 774 } 775 776 function ttpSyncPager() { 777 var pager = mdModalWrap.find('.rttm-pop-pager'); 778 if (!pager.length) { 779 return; 780 } 781 if (singleMemberIds.length < 2) { 782 pager.hide(); 783 } else { 784 pager.show(); 785 } 786 } 787 788 function ttpStepMember(step) { 789 var ids = mdModalWrap.data('rttmMembers') || []; 790 var open = mdModalWrap.data('rttmOpen'); 791 if (ids.length < 2 || typeof open !== 'function') { 792 return; 793 } 794 var cur = String(mdModalWrap.data('rttmMember') || ''); 795 var i = ids.indexOf(cur); 796 if (i === -1) { 797 i = 0; 798 } 799 open(ids[(i + step + ids.length) % ids.length], true); 800 } 801 802 $(document).on('click', '.ttp-single-md-popup', function (e) { 803 // This handler is bound once PER CONTAINER, so on a page with more than 804 // one shortcode every copy fires. Only the container that actually owns 805 // the clicked trigger may respond â otherwise the last copy to run wins 806 // and overwrites the member list with its own (often empty) one. 807 if (!container.has(this).length) { 808 return; 809 } 810 e.preventDefault(); 811 ttpCollectSingleMembers(); 812 // Hand the pager THIS container's opener, so paging keeps using the 813 // scID / popup background of the shortcode that was actually clicked. 814 mdModalWrap.data('rttmOpen', ttpOpenSinglePopup); 815 ttpOpenSinglePopup($(this).attr("data-id")); 816 return false; 817 }); 818 819 // Bind the pager ONCE. `#tlp-modal` is a single shared element, so binding 820 // inside this per-container loop would fire the handler once per shortcode 821 // on the page and race between their member lists. 822 if (!mdModalWrap.data('rttmPagerBound')) { 823 mdModalWrap.data('rttmPagerBound', true); 824 mdModalWrap.on('click', '.rttm-pop-prev', function (e) { 825 e.preventDefault(); 826 ttpStepMember(-1); 827 }); 828 mdModalWrap.on('click', '.rttm-pop-next', function (e) { 829 e.preventDefault(); 830 ttpStepMember(1); 831 }); 832 } 833 834 // ---------- smart popup ---------- 835 // A right-hand drawer over a blurred backdrop. The shell is built once per 836 // open and survives every member step; only `.rt-smart-modal-main-content` is 837 // swapped. The state the stepper needs travels ON the shell via .data(), so 838 // the delegated handlers bound at build time keep working after each swap. 839 $(document).on('click', '.ttp-smart-popup', function (e) { 840 e.preventDefault(); 841 842 var self = $(this); 843 844 // Bound inside the per-container .each(), so on a page with two widgets 845 // both copies run; without this the last one wins and opens the drawer 846 // with the wrong member list. 847 if (!container.has(this).length) { 848 return false;
849 } 850 851 var current = String(self.attr('data-id')), 852 contentLoader = $('.rt-row.rt-content-loader', container), 853 itemArray = $.map(getItemsArray(contentLoader), function (v) { return String(v); }), 854 $wrap = ttpSpBuild(scID); 855 856 $wrap.data('rttmList', itemArray); 857 858 // The drawer paints every surface it owns from --rttm-pop-surface, so the 859 // token covers the panel and the scrolling body together. The gradient bar 860 // is deliberately left alone â it follows Primary Color, exactly as the 861 // Elementor path keeps PopUp Header Background separate from PopUp 862 // Background. 863 if (popupBg) { 864 $wrap[0].style.setProperty('--rttm-pop-surface', popupBg); 865 } 866 867 // Carry the opening container's Primary Color onto the drawer â the shell 868 // lives outside the widget wrapper, so no per-widget selector reaches it. 869 var rttmPrim = (getComputedStyle(container[0]).getPropertyValue('--l1-primary') || '').trim(); 870 if (rttmPrim) { 871 $wrap[0].style.setProperty('--rttm-pop-primary', rttmPrim); 872 } else { 873 $wrap[0].style.removeProperty('--rttm-pop-primary'); 874 } 875 876 ttpSpLoad($wrap, current, false); 877 878 return false; 879 }); 880 881 // ---------- multiple popup ---------- 882 // One shared viewer element; the state it needs to step between members 883 // travels ON it via .data(), so the delegated handlers built with the shell 884 // keep working after every panel swap. 885 $(document).on('click', '.ttp-multi-popup', function () { 886 var self = $(this); 887 888 // `.ttp-multi-popup` is bound inside the per-container .each(), so on a 889 // page with two widgets both copies run; without this the last one wins 890 // and opens the viewer with the wrong member list. 891 if (!container.has(this).length) { 892 return; 893 } 894 895 var current = String(self.attr('data-id')), 896 contentLoader = self.parents('.rt-team-container').children('.rt-row.rt-content-loader'), 897 itemArray = $.map(getItemsArray(contentLoader), function (v) { return String(v); }), 898 $wrap = ttpMpopBuild(); 899 900 $wrap.addClass('tlp-popup-wrap-' + scID); 901 $wrap.data('rttmList', itemArray); 902 $wrap.data('rttmContainer', container); 903 904 // This used to paint only the top BAR, so the viewer's stage â the surface 905 // the control is named for â stayed white. The token covers the stage and 906 // the thumbnail strip; the bar follows Primary Color. 907 if (popupBg) { 908 $wrap[0].style.setProperty('--rttm-pop-surface', popupBg); 909 } 910 911 // Carry the opening container's Primary Color onto the viewer, exactly as 912 // the single popup does â the shell lives outside the widget wrapper, so 913 // no per-widget selector can reach it. 914 var rttmPrim = (getComputedStyle(container[0]).getPropertyValue('--l1-primary') || '').trim(); 915 if (rttmPrim) { 916 $wrap[0].style.setProperty('--rttm-pop-primary', rttmPrim); 917 } else { 918 $wrap[0].style.removeProperty('--rttm-pop-primary'); 919 } 920 921 ttpMpopLoad($wrap, current, 0); 922 923 return false; 924 }); 925 926 927 }); 928 }; 929 initTlpTeam(); 930 function preFunction() { 931 HeightResize(); 932 } 933 934 function equalHeight4Layout4() { 935 var $maxH = $(".rt-row.rt-content-loader.layout4 .layout4item").height(); 936 $(".rt-row.rt-content-loader.layout4 .layout4item .layoutInner .rt-img-holder img,.rt-row.rt-content-loader.layout4 .layout4item .layoutInner.layoutInner-content").height($maxH + "px"); 937 } 938 939 function HeightResize() { 940 if($(".rt-team-container[data-layout*='layout']").length > 0) { 941 return; 942 } 943 944 var wWidth = $(window).width(); 945 $(".rt-team-container").each(function () { 946 var self = $(this), 947 dCol = self.data('desktop-col'), 948 tCol = self.data('tab-col'), 949 mCol = self.data('mobile-col'), 950 target = $(this).find('.rt-row.rt-content-loader.ttp-even'); 951 if ((wWidth >= 992 && dCol > 1) || (wWidth >= 768 && tCol > 1) || (wWidth < 768 && mCol > 1)) { 952 target.imagesLoaded(function () { 953 var tlpMaxH = 0; 954 target.find('.even-grid-item').height('auto'); 955 target.find('.even-grid-item').each(function () { 956 var $thisH = $(this).outerHeight(); 957 if ($thisH > tlpMaxH) { 958 tlpMaxH = $thisH; 959 } 960 }); 961 target.find('.even-grid-item').height(tlpMaxH + "px"); 962 }); 963 } else { 964 target.find('.even-grid-item').height('auto'); 965 } 966 967 }); 968 if ($(".rt-row.rt-content-loader.layout4").length) { 969 equalHeight4Layout4(); 970 } 971 } 972 973 /* ---------- smart popup: the right-hand drawer ---------- 974 The shell keeps every legacy hook class (.rt-smart-modal-main, 975 .rt-smart-modal-header, .rt-smart-modal-nav, .rt-smart-nav-item, 976 .rt-smart-modal-close, .rt-smart-modal, .rt-smart-modal-main-content-wrapper) 977 because user Style controls are wired to them â see 978 ElementorFilters::colorControls() "PopUp Colors" and the smart-modal arms in 979 Fns::layoutStyleGenerator() and templates/sc-css.php. */ 980 981 function ttpSpClose() { 982 var $wrap = $('#rt-smart-modal-container'); 983 if (!$wrap.length) { 984 return; 985 } 986 $('html').removeClass('rt-smart-modal-on'); 987 $wrap.removeClass('open'); 988 setTimeout(function () { 989 $wrap.remove(); 990 }, 450); 991 } 992 993 function ttpSpBuild(scID) { 994 $('#rt-smart-modal-container').remove(); 995 996 var html = 997 '<div id="rt-smart-modal-container" class="rt-modal-' + scID + ' rttm-sp">' + 998 '<div class="rt-smart-modal-main">' + 999 '<div class="rt-smart-modal-header">' + 1000 '<span class="rt-smart-modal-nav">' + 1001 '<a href="#" class="rt-smart-nav-left rt-smart-nav-item" aria-label="Previous member"><i class="fa fa-chevron-left" aria-hidden="true"></i></a>' + 1002 '<a href="#" class="rt-smart-nav-right rt-smart-nav-item" aria-label="Next member"><i class="fa fa-chevron-right" aria-hidden="true"></i></a>' +
1003 '</span>' + 1004 '<a href="#" class="rt-smart-modal-close" aria-label="Close"><i class="fa fa-times" aria-hidden="true"></i></a>' + 1005 '</div>' + 1006 '<div class="rt-smart-modal"><div class="rt-smart-modal-main-content-wrapper"></div></div>' + 1007 '</div>' + 1008 '</div>'; 1009 1010 $('body').append(html); 1011 $('html').addClass('rt-smart-modal-on'); 1012 1013 var $wrap = $('#rt-smart-modal-container'); 1014 1015 // Adding the reveal class in the same frame as the insert collapses both states 1016 // and the drawer just appears; force a style flush first. 1017 void $wrap[0].offsetWidth; 1018 requestAnimationFrame(function () { 1019 $wrap.addClass('open'); 1020 }); 1021 1022 $wrap.on('click', '.rt-smart-modal-close', function (e) { 1023 e.preventDefault(); 1024 ttpSpClose(); 1025 return false; 1026 }); 1027 $wrap.on('click', '.rt-smart-nav-right', function (e) { 1028 e.preventDefault(); 1029 ttpSpStep($wrap, 1); 1030 return false; 1031 }); 1032 $wrap.on('click', '.rt-smart-nav-left', function (e) { 1033 e.preventDefault(); 1034 ttpSpStep($wrap, -1); 1035 return false; 1036 }); 1037 $wrap.on('click', '.rttm-sp-garrow', function () { 1038 ttpSpShot($wrap, $(this).hasClass('next') ? 1 : -1, false); 1039 return false; 1040 }); 1041 $wrap.on('click', '.rttm-sp-dot', function () { 1042 ttpSpShot($wrap, parseInt($(this).attr('data-i'), 10), true); 1043 return false; 1044 }); 1045 // clicking the dimmed backdrop closes; clicks inside the drawer must not 1046 $wrap.on('click', function (e) { 1047 if (e.target === this) { 1048 ttpSpClose(); 1049 } 1050 }); 1051 1052 return $wrap; 1053 } 1054 1055 /* hero slider â a plain cross-fade, so nothing has to measure a drawer that is 1056 still sliding in */ 1057 function ttpSpShot($wrap, value, absolute) { 1058 var $slides = $wrap.find('.rttm-sp-slide'), 1059 $dots = $wrap.find('.rttm-sp-dot'); 1060 1061 if (!$slides.length) { 1062 return; 1063 } 1064 1065 var cur = $slides.index($slides.filter('.is-active')); 1066 if (cur < 0) { 1067 cur = 0; 1068 } 1069 1070 var i = absolute ? value : cur + value; 1071 i = ((i % $slides.length) + $slides.length) % $slides.length; 1072 1073 $slides.removeClass('is-active').eq(i).addClass('is-active'); 1074 $dots.removeClass('is-active').eq(i).addClass('is-active'); 1075 } 1076 1077 function ttpSpStep($wrap, delta) { 1078 var list = $wrap.data('rttmList') || [], 1079 cur = String($wrap.data('rttmCurrent')); 1080 1081 if (list.length < 2) { 1082 return; 1083 } 1084 1085 var i = $.inArray(cur, list); 1086 if (i < 0) { 1087 i = 0; 1088 } 1089 i = (i + delta + list.length) % list.length; 1090 1091 ttpSpLoad($wrap, list[i], true); 1092 } 1093 1094 /* Loads one member. `swap` is false on first open (spinner) and true when stepping, 1095 which fades the outgoing panel out and the new one back in. */ 1096 function ttpSpLoad($wrap, id, swap) { 1097 var $body = $wrap.find('.rt-smart-modal'), 1098 $holder = $wrap.find('.rt-smart-modal-main-content-wrapper'), 1099 $old = $holder.find('.rttm-sp-panel'), 1100 list = $wrap.data('rttmList') || []; 1101 1102 $wrap.data('rttmCurrent', String(id)); 1103 // hide the stepper when there is only one member to step to 1104 $wrap.find('.rt-smart-modal-nav').css('display', list.length > 1 ? '' : 'none'); 1105 1106 var data = { 1107 action: 'tlp_team_smart_popup', 1108 id: id 1109 }; 1110 data[ttp.nonceID] = ttp.nonce; 1111 1112 var fire = function () { 1113 $.ajax({ 1114 type: 'post', 1115 url: ttp.ajaxurl, 1116 data: data, 1117 beforeSend: function () { 1118 if (!swap) { 1119 $wrap.addClass('loading'); 1120 $holder.html('<span class="rt-spinner"></span>'); 1121 } 1122 }, 1123 success: function (response) { 1124 $wrap.removeClass('loading').addClass('ready'); 1125 $holder.html(response.data); 1126 $body.scrollTop(0); 1127 1128 var $panel = $holder.find('.rttm-sp-panel'); 1129 if (swap && $panel.length) { 1130 $panel.addClass('is-swapping'); 1131 void $panel[0].offsetWidth; 1132 requestAnimationFrame(function () { 1133 $panel.removeClass('is-swapping'); 1134 }); 1135 } 1136 1137 ttpSpSkills($wrap); 1138 }, 1139 error: function (e) { 1140 console.log(e); 1141 $wrap.removeClass('loading'); 1142 $holder.html('<p>Loading error!!!</p>'); 1143 } 1144 }); 1145 }; 1146 1147 if (swap && $old.length) { 1148 $old.addClass('is-swapping'); 1149 setTimeout(fire, 200); 1150 } else { 1151 fire(); 1152 } 1153 } 1154 1155 /* the skill bars animate from 0 to their data-progress-animation width */ 1156 function ttpSpSkills($wrap) { 1157 $('.tlp-tooltip', $wrap).rtTooltip(); 1158 $('.tlp-team-skill', $wrap).find('.fill').css('width', '0%'); 1159 $('.tlp-team-skill .fill', $wrap).each(function () { 1160 var k = 0, 1161 f = $(this), 1162 p = f.attr('data-progress-animation'), 1163 w = f.width(); 1164 if (w == 0 && p) { 1165 p = p.substring(0, p.length - 1); 1166 var go = function () { 1167 return k >= p || k >= 100 ? false : ((k += 1), f.css('width', k + '%'), setTimeout(go, 20)); 1168 }; 1169 go(); 1170 } 1171 }); 1172 } 1173 1174 /* Bound ONCE â the old code re-bound its close/nav handlers on every card click. */ 1175 $(document).on('keydown.rttmSp', function (event) { 1176 var $wrap = $('#rt-smart-modal-container.open'); 1177 1178 if (!$wrap.length) { 1179 return; 1180 } 1181 1182 if (event.keyCode === 27) { 1183 ttpSpClose(); 1184 } else if (event.keyCode === 37) { 1185 ttpSpStep($wrap, -1); 1186 } else if (event.keyCode === 39) { 1187 ttpSpStep($wrap, 1); 1188 } 1189 }); 1190 1191 /* ---------- multiple popup: the fullscreen viewer ---------- 1192 The shell is built once per open and survives every member step; only the panel 1193 inside `.tlp-popup-content` is swapped. Every legacy hook class is kept on it 1194 (.tlp-popup-navigation-wrap, .tlp-popup-navigation, .tlp-popup-prev/-close/-next, 1195 .tlp-popup-content and the counter) because user Style controls are wired to 1196 them â see ElementorFilters::colorControls() "PopUp Colors" and the popup
1197 background block in Fns::layoutStyleGenerator(). */ 1198 1199 function ttpMpopClose() { 1200 var $wrap = $('#tlp-popup-wrap'); 1201 if (!$wrap.length) { 1202 return; 1203 } 1204 $wrap.removeClass('is-open'); 1205 setTimeout(function () { 1206 $wrap.remove(); 1207 }, 350); 1208 } 1209 1210 function ttpMpopBuild() { 1211 $('#tlp-popup-wrap').remove(); 1212 1213 var html = 1214 '<div id="tlp-popup-wrap" class="tlp-popup-wrap rttm-mpop">' + 1215 '<div class="tlp-popup-navigation-wrap rttm-mpop-bar">' + 1216 '<div class="tlp-popup-singlePage-counter rttm-mpop-counter"><b class="ccurrent"></b> <span class="rttm-mpop-of">' + ttp.lan.of + '</span> <span class="ctotal"></span></div>' + 1217 '<div class="tlp-popup-navigation rttm-mpop-controls">' + 1218 '<button type="button" class="tlp-popup-prev rttm-mpop-ctrl" title="Previous (Left arrow key)" data-action="prev" aria-label="Previous member"><i class="fas fa-chevron-left"></i></button>' + 1219 '<button type="button" class="tlp-popup-close rttm-mpop-ctrl is-close" title="Close (Esc key)" data-action="close" aria-label="Close"><i class="fas fa-times"></i></button>' + 1220 '<button type="button" class="tlp-popup-next rttm-mpop-ctrl" title="Next (Right arrow key)" data-action="next" aria-label="Next member"><i class="fas fa-chevron-right"></i></button>' + 1221 '</div>' + 1222 '<div class="rttm-mpop-spacer"></div>' + 1223 '<div class="rttm-mpop-progress"></div>' + 1224 '</div>' + 1225 '<div class="tlp-popup-content rttm-mpop-stage"><div class="rttm-mpop-loading"></div></div>' + 1226 '<div class="rttm-mpop-strip"></div>' + 1227 '</div>'; 1228 1229 $('body').append(html); 1230 1231 var $wrap = $('#tlp-popup-wrap'); 1232 1233 // Adding the reveal class in the same frame as the insert collapses both states 1234 // and the viewer just appears; force a style flush first. 1235 void $wrap[0].offsetWidth; 1236 requestAnimationFrame(function () { 1237 $wrap.addClass('is-open'); 1238 }); 1239 1240 $wrap.on('click', '.tlp-popup-close', function () { 1241 ttpMpopClose(); 1242 return false; 1243 }); 1244 $wrap.on('click', '.tlp-popup-prev', function () { 1245 ttpMpopStep($wrap, -1); 1246 return false; 1247 }); 1248 $wrap.on('click', '.tlp-popup-next', function () { 1249 ttpMpopStep($wrap, 1); 1250 return false; 1251 }); 1252 $wrap.on('click', '.rttm-mpop-thumb', function () { 1253 var id = String($(this).attr('data-id')), 1254 list = $wrap.data('rttmList') || [], 1255 cur = String($wrap.data('rttmCurrent')); 1256 if (id === cur) { 1257 return false; 1258 } 1259 ttpMpopLoad($wrap, id, $.inArray(id, list) > $.inArray(cur, list) ? 1 : -1); 1260 return false; 1261 }); 1262 $wrap.on('click', '.rttm-mpop-garrow', function () { 1263 ttpMpopShot($wrap, $(this).hasClass('next') ? 1 : -1, false); 1264 return false; 1265 }); 1266 $wrap.on('click', '.rttm-mpop-dot', function () { 1267 ttpMpopShot($wrap, parseInt($(this).attr('data-i'), 10), true); 1268 return false; 1269 }); 1270 1271 return $wrap; 1272 } 1273 1274 /* counter, progress bar, and hiding the stepper when there is only one member */ 1275 function ttpMpopLevel($wrap, current, list) { 1276 var index = $.inArray(String(current), list) + 1, 1277 count = list.length; 1278 1279 $wrap.find('.ccurrent').text(index || 1); 1280 $wrap.find('.ctotal').text(count); 1281 $wrap.find('.rttm-mpop-progress').css('width', count ? ((index || 1) / count) * 100 + '%' : 0); 1282 $wrap.find('.tlp-popup-prev, .tlp-popup-next').css('display', count > 1 ? '' : 'none'); 1283 } 1284 1285 /* The strip mirrors exactly the members the viewer can step through â the visible 1286 cards getItemsArray() counts â so the thumbnails come from the opening 1287 container's own cards rather than a second query. */ 1288 function ttpMpopStrip($wrap, container, list, current) { 1289 var $strip = $wrap.find('.rttm-mpop-strip'); 1290 1291 if (!$strip.length) { 1292 return; 1293 } 1294 1295 if (!container || list.length < 2) { 1296 $strip.empty(); 1297 return; 1298 } 1299 1300 if ($strip.data('rttmFor') !== list.join(',')) { 1301 var html = ''; 1302 $.each(list, function (i, id) { 1303 var $img = container.find('.rt-grid-item[data-id="' + id + '"]').first().find('img').first(), 1304 src = $img.attr('src') || '', 1305 alt = ($img.attr('alt') || '').replace(/"/g, ''); 1306 html += 1307 '<button type="button" class="rttm-mpop-thumb" data-id="' + id + '" aria-label="' + alt + '">' + 1308 (src ? '<img src="' + src + '" alt="' + alt + '" />' : '') + 1309 '</button>'; 1310 }); 1311 $strip.html(html).data('rttmFor', list.join(',')); 1312 } 1313 1314 $strip.find('.rttm-mpop-thumb').each(function () {
1315 $(this).toggleClass('is-active', String($(this).attr('data-id')) === String(current)); 1316 }); 1317 } 1318 1319 /* photo slider inside the panel â a plain cross-fade, so nothing has to measure a 1320 container that is still fading in */ 1321 function ttpMpopShot($wrap, value, absolute) { 1322 var $slides = $wrap.find('.rttm-mpop-slide'), 1323 $dots = $wrap.find('.rttm-mpop-dot'); 1324 1325 if (!$slides.length) { 1326 return; 1327 } 1328 1329 var cur = $slides.index($slides.filter('.is-active')); 1330 if (cur < 0) { 1331 cur = 0; 1332 } 1333 1334 var i = absolute ? value : cur + value; 1335 i = ((i % $slides.length) + $slides.length) % $slides.length; 1336 1337 $slides.removeClass('is-active').eq(i).addClass('is-active'); 1338 $dots.removeClass('is-active').eq(i).addClass('is-active'); 1339 } 1340 1341 function ttpMpopStep($wrap, delta) { 1342 var list = $wrap.data('rttmList') || [], 1343 cur = String($wrap.data('rttmCurrent')); 1344 1345 if (list.length < 2) { 1346 return; 1347 } 1348 1349 var i = $.inArray(cur, list); 1350 if (i < 0) { 1351 i = 0; 1352 } 1353 i = (i + delta + list.length) % list.length; 1354 1355 ttpMpopLoad($wrap, list[i], delta); 1356 } 1357 1358 /* Loads one member. `dir` is 0 on first open and ±1 when stepping, which drives the 1359 slide-out / slide-back-in: the outgoing panel leaves in the direction of travel 1360 and the incoming one arrives from the opposite side. */ 1361 function ttpMpopLoad($wrap, id, dir) { 1362 var $stage = $wrap.find('.rttm-mpop-stage'), 1363 $old = $stage.find('.rttm-mpop-card'), 1364 list = $wrap.data('rttmList') || []; 1365 1366 $wrap.data('rttmCurrent', String(id)); 1367 ttpMpopLevel($wrap, id, list); 1368 ttpMpopStrip($wrap, $wrap.data('rttmContainer'), list, id); 1369 1370 var fire = function () { 1371 $.ajax({ 1372 type: 'post', 1373 url: ttp.ajaxurl, 1374 data: ttp.nonceID + '=' + ttp.nonce + '&action=tlp_multi_popup_single&id=' + id, 1375 success: function (data) { 1376 $stage.html(data.data); 1377 1378 var $card = $stage.find('.rttm-mpop-card'); 1379 if (dir && $card.length) { 1380 $card[0].style.setProperty('--rttm-mpop-swap', dir > 0 ? '24px' : '-24px'); 1381 $card.addClass('is-swapping'); 1382 void $card[0].offsetWidth; 1383 requestAnimationFrame(function () { 1384 $card.removeClass('is-swapping'); 1385 }); 1386 } 1387 1388 tlpSingleTeamScript(); 1389 }, 1390 error: function (e) { 1391 console.log(e); 1392 $stage.html('<p>Loading error!!!</p>'); 1393 } 1394 }); 1395 }; 1396 1397 if (dir && $old.length) { 1398 $old[0].style.setProperty('--rttm-mpop-swap', dir > 0 ? '-24px' : '24px'); 1399 $old.addClass('is-swapping'); 1400 setTimeout(fire, 220); 1401 } else { 1402 $stage.html('<div class="rttm-mpop-loading"></div>'); 1403 fire(); 1404 } 1405 } 1406 1407 /* Bound ONCE. The old code bound this inside the card click handler, so every card 1408 ever clicked added another listener and a single arrow press stepped several 1409 times. */ 1410 $(document).on('keydown.rttmMpop', function (event) { 1411 var $wrap = $('#tlp-popup-wrap.is-open'); 1412 1413 if (!$wrap.length) { 1414 return; 1415 } 1416 1417 if (event.keyCode === 27) { 1418 ttpMpopClose(); 1419 } else if (event.keyCode === 37) { 1420 ttpMpopStep($wrap, -1); 1421 } else if (event.keyCode === 39) { 1422 ttpMpopStep($wrap, 1); 1423 } 1424 }); 1425 1426 /* the viewer sizes itself from the viewport; the old slide-in panel needed a 1427 display:block nudge on resize, this one must never be forced visible. */ 1428 function navResize() {} 1429 1430 $(window).on('load resize', function () { 1431 navResize(); 1432 HeightResize(); 1433 if ($(".tlp-md-content").length) { 1434 $(".tlp-md-content").mCustomScrollbar({ 1435 scrollbarPosition: "outside" 1436 }); 1437 } 1438 }); 1439 $.fn.alterClass = function (removals, additions) { 1440 var self = this; 1441 if (removals.indexOf('*') === -1) { 1442 // Use native jQuery methods if there is no wildcard matching 1443 self.removeClass(removals); 1444 return !additions ? self : self.addClass(additions); 1445 } 1446 var patt = new RegExp('\\s' + 1447 removals.replace(/\*/g, '[A-Za-z0-9-_]+').split(' ').join('\\s|\\s') + 1448 '\\s', 'g'); 1449 self.each(function (i, it) { 1450 var cn = ' ' + it.className + ' '; 1451 while (patt.test(cn)) { 1452 cn = cn.replace(patt, ' '); 1453 } 1454 it.className = $.trim(cn); 1455 }); 1456 return !additions ? self : self.addClass(additions); 1457 }; 1458 1459 $('.md-close').on('click', function (e) { 1460 e.preventDefault(); 1461 mdModalWrap.removeClass('md-show'); 1462 mdModalWrap.alterClass('tlp-modal-*'); 1463 mdModalWrap.find('.tlp-md-content-holder').html(''); 1464 }); 1465 1466 skillAnimation(); 1467 1468 if( $('.tlp-tooltip').length > 0 ) { 1469 $('.tlp-tooltip').rtTooltip(); 1470 } 1471 1472 var RttmSlider = function ($slider) { 1473 this.$slider = $slider; 1474 this.slider = this.$slider.get(0); 1475 this.swiperSlider = this.slider.swiper || null; 1476 this.defaultOptions = { 1477 breakpointsInverse: true, 1478 observer: true, 1479 navigation: { 1480 nextEl: this.$slider.find('.swiper-button-next').get(0), 1481 prevEl: this.$slider.find('.swiper-button-prev').get(0), 1482 }, 1483 pagination: { 1484 el: this.$slider.find('.swiper-pagination').get(0), 1485 type: 'bullets', 1486 clickable: true 1487 } 1488 }; 1489 1490 this.slider_enabled = 'function' === typeof Swiper; 1491 this.options = Object.assign({}, this.defaultOptions, this.$slider.data('options') || {}); 1492 this.initSlider = function () { 1493 if (!this.slider_enabled) { 1494 return; 1495 } 1496 if (this.options.rtl) { 1497 this.$slider.attr('dir', 'rtl'); 1498 } 1499 if (this.swiperSlider) { 1500 this.swiperSlider.parents = this.options;
1501 this.swiperSlider.update(); 1502 } else { 1503 this.swiperSlider = new Swiper(this.$slider.get(0), this.options); 1504 } 1505 }; 1506 this.imagesLoaded = function () { 1507 if(this.$slider.data('options').lazy) { 1508 this.$slider.trigger('rttm_slider_loaded', this); 1509 return; 1510 } 1511 1512 var that = this; 1513 1514 if (!$.isFunction($.fn.imagesLoaded) || $.fn.imagesLoaded.done) { 1515 this.$slider.trigger('rttm_slider_loading', this); 1516 this.$slider.trigger('rttm_slider_loaded', this); 1517 return; 1518 } 1519 1520 this.$slider.imagesLoaded().progress(function (instance, image) { 1521 that.$slider.trigger('rttm_slider_loading', [that]); 1522 }).done(function (instance) { 1523 that.$slider.trigger('rttm_slider_loaded', [that]); 1524 }); 1525 }; 1526 this.start = function () { 1527 var that = this; 1528 this.$slider.on('rttm_slider_loaded', this.init.bind(this)); 1529 setTimeout(function () { 1530 that.imagesLoaded(); 1531 }, 1); 1532 }; 1533 this.init = function () { 1534 this.initSlider(); 1535 }; 1536 this.rtSwiper = function () { 1537 return new Swiper(this.$slider.get(0), this.options); 1538 }; 1539 1540 this.start(); 1541 }; 1542 1543 $.fn.rttm_slider = function () { 1544 new RttmSlider(this); 1545 return this; 1546 }; 1547 window.rttmpBuilderInit = { 1548 initSlider: function () { 1549 var $ = jQuery; 1550 rtSliderInit($); 1551 }, 1552 initLoader: function () { 1553 $(".rttmp-team-builder").each(function (index) { 1554 var container = $(this), 1555 loader = container.find(".rt-content-loader"); 1556 1557 loader.find('.rt-loading').fadeOut(300); 1558 loader.removeClass('ttp-pre-loader'); 1559 }); 1560 1561 } 1562 }; 1563 rttmpBuilderInit.initLoader(); 1564 rttmpBuilderInit.initSlider() 1565 1566 1567})(jQuery); 1568 1569function rtSliderInit($) { 1570 $('.rttm-carousel-slider').each(function () { 1571 $(this).rttm_slider(); 1572 }); 1573} 1574 1575function skillAnimation() { 1576 jQuery('.tlp-team-skill').find('.fill').css('width', '0%'); 1577 jQuery(window).bind('load', function () { 1578 jQuery('.tlp-team-skill').each(function () { 1579 jQuery(this).find('.fill').each(function () { 1580 var k = 0, f = jQuery(this), p = f.attr('data-progress-animation'), w = f.width(); 1581 if (w == 0) { 1582 p = p.substring(0, p.length - 1); 1583 var go = function () { 1584 return k >= p || k >= 100 ? (false) : (k += 1, f.css('width', k + '%'), setTimeout(go, 20)) 1585 }; 1586 go(); 1587 } 1588 }); 1589 }); 1590 }); 1591} 1592 1593function mdPopUpSkillAnimation() { 1594 rtSliderInit(jQuery); 1595 jQuery('#tlp-modal .tlp-md-content').mCustomScrollbar({ 1596 scrollbarPosition: 'outside' 1597 }); 1598 jQuery('#tlp-modal .tlp-tooltip').rtTooltip(); 1599 jQuery('#tlp-modal .tlp-team-skill').find('.fill').css('width', '0%'); 1600 1601 jQuery('#tlp-modal .tlp-team-skill').each(function () { 1602 jQuery(this).find('.fill').each(function () { 1603 var k = 0, f = jQuery(this), p = f.attr('data-progress-animation'), w = f.width(); 1604 if (w == 0) { 1605 p = p.substring(0, p.length - 1); 1606 var go = function () { 1607 return k >= p || k >= 100 ? (false) : (k += 1, f.css('width', k + '%'), setTimeout(go, 20)) 1608 }; 1609 go(); 1610 } 1611 }); 1612 }); 1613} 1614 1615function tlpSingleTeamScript() { 1616 jQuery('#tlp-popup-wrap .tlp-tooltip').rtTooltip(); 1617 jQuery('#tlp-popup-wrap .tlp-team-skill').find('.fill').css('width', '0%'); 1618 jQuery('#tlp-popup-wrap .tlp-team-skill .fill').each(function () { 1619 var k = 0, f = jQuery(this), p = f.attr('data-progress-animation'), w = f.width(); 1620 if (w == 0) { 1621 p = p.substring(0, p.length - 1); 1622 var go = function () { 1623 return k >= p || k >= 100 ? (false) : (k += 1, f.css('width', k + '%'), setTimeout(go, 20)) 1624 }; 1625 go(); 1626 } 1627 }); 1628 rtSliderInit(jQuery); 1629} 1630 1631function RTElementThumbCarousel(container, options, instance, index) { 1632 // Params 1633 var mainSlider = container.find('.rttm-carousel-main').addClass('instance-' + index), 1634 navSlider = container.find('.ttp-carousel-thumb').addClass('instance-' + index), 1635 navPrev = '.swiper-button-prev', 1636 navNext = '.swiper-button-next', 1637 dotsEl = '.swiper-pagination'; 1638 1639 container.find(navPrev).addClass('prev-' + index); 1640 container.find(navNext).addClass('next-' + index); 1641 1642 // Main Slider 1643 var mainSliderOptions = { 1644 loop: true, 1645 speed: options.speed ? options.speed : 1000, 1646 loopedSlides: 5, 1647 autoHeight: options.autoHeight ? options.autoHeight : false, 1648 navigation: { 1649 nextEl: navNext, 1650 prevEl: navPrev 1651 }, 1652 pagination: { 1653 el: dotsEl, 1654 type: 'bullets', 1655 clickable: true 1656 } 1657 }; 1658 1659 var main = new Swiper(mainSlider[0], mainSliderOptions); 1660 1661 // Navigation Slider 1662 var navSliderOptions = { 1663 loop: true, 1664 speed: options.speed ? options.speed : 1000, 1665 observer: true, 1666 observerParents: true, 1667 slidesPerView: options.slidesPerView ? options.slidesPerView : 5, 1668 centeredSlides: true, 1669 spaceBetween: 0, 1670 touchRatio: 0.2, 1671 slideToClickedSlide: true, 1672 loopedSlides: 5, 1673 watchSlidesProgress: true, 1674 breakpoints: options.breakpoints 1675 }; 1676 1677 if (options.autoplay) { 1678 navSliderOptions.autoplay = { 1679 delay: options.autoplay.delay, 1680 pauseOnMouseEnter: options.autoplay.pauseOnMouseEnter, 1681 disableOnInteraction: false 1682 }; 1683 } 1684 1685 if (options.lazy) { 1686 navSliderOptions.preloadImages = false;
1687 navSliderOptions.lazy = true; 1688 } 1689 1690 var thumb = new Swiper(navSlider[0], navSliderOptions); 1691 1692 // Syncing the sliders 1693 main.controller.control = thumb; 1694 thumb.controller.control = main; 1695 1696 instance[index] = [main, thumb]; 1697}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.