1 2/* ========================================================================= 3 * Isotope filter bar â count badges + sliding glider (redesign, appended). 4 * Self-contained: enhances the plugin's .ttp-isotope-buttons on EVERY isotope 5 * layout (global nav style), not just isotope-free. Counts are read from the 6 * loaded .isotope-item items in the .rt-content-loader row; the glider is a 7 * span that slides to the active pill. Adds .rttm-iso-has-glider to the group so 8 * the CSS can make the active button transparent (glider provides the gradient); 9 * without JS the CSS keeps a gradient background on .selected as a fallback. 10 * ========================================================================= */ 11(function ($) { 12 'use strict'; 13 14 function positionGlider($group) { 15 var $active = $group.children('button.selected').filter(':visible').first(); 16 var $glider = $group.children('.rttm-iso-glider'); 17 if (!$active.length || !$glider.length) { 18 $glider.css('opacity', 0); 19 return; 20 } 21 var btn = $active[0]; 22 $glider.css({ 23 left: btn.offsetLeft + 'px', 24 top: btn.offsetTop + 'px', 25 width: btn.offsetWidth + 'px', 26 height: btn.offsetHeight + 'px', 27 opacity: 1 28 }); 29 } 30 31 function initGroup($group) { 32 if ($group.data('rttmIsoInit')) { 33 positionGlider($group); 34 return; 35 } 36 $group.data('rttmIsoInit', true); 37 38 // `.rt-content-loader` is the row shared by EVERY isotope layout (it wraps both the 39 // filter bar and the items), and `.isotope-item` is the item class every isotope layout 40 // uses â so counting works on any isotope layout, not just isotope-free. 41 var $row = $group.closest('.rt-content-loader'); 42 43 // 1. count badge per button (from the loaded items); hide empty non-"all" filters 44 $group.children('button').each(function () { 45 var $btn = $(this); 46 var f = $btn.attr('data-filter'); 47 var count; 48 try { 49 count = (f === '*') ? $row.find('.isotope-item').length : $row.find('.isotope-item' + f).length; 50 } catch (e) { 51 count = 0; 52 } 53 if (count === 0 && f !== '*') { 54 $btn.hide(); 55 return; 56 } 57 if (!$btn.children('.count').length) { 58 $btn.append(' <span class="count">' + count + '</span>'); 59 } 60 }); 61 62 // 2. glider element (behind the pills) + flag the group so CSS clears the button bg 63 if (!$group.children('.rttm-iso-glider').length) { 64 $group.prepend('<span class="rttm-iso-glider" aria-hidden="true"></span>'); 65 } 66 $group.addClass('rttm-iso-has-glider'); 67 68 // 3. slide the glider when a pill is clicked (after the plugin toggles .selected) 69 $group.on('click.rttmIso', 'button', function () { 70 setTimeout(function () { positionGlider($group); }, 0); 71 }); 72 73 positionGlider($group); 74 // re-measure once more after fonts/layout settle 75 setTimeout(function () { positionGlider($group); }, 250); 76 } 77 78 function initAll() { 79 $('.rt-team-container .ttp-isotope-buttons').each(function () { 80 initGroup($(this)); 81 }); 82 } 83 84 $(window).on('load', initAll); 85 $(document).ready(initAll); 86 87 // Expose the initialiser for contexts that inject the filter-bar markup AFTER page load, 88 // where the load/ready handlers above never fire â e.g. the admin shortcode preview, which 89 // re-renders via AJAX on every form change. Safe to call repeatedly: initGroup is idempotent 90 // per group (guards on .data('rttmIsoInit')), and the preview replaces the DOM each render so 91 // a fresh group re-initialises cleanly. 92 window.rttmIsoFilter = { init: initAll, initGroup: initGroup, position: positionGlider }; 93 94 // Elementor renders widgets asynchronously and, in the EDITOR, re-renders them on every 95 // change WITHOUT a page reload â so the load/ready handlers above never fire for the fresh 96 // DOM. Hook the widget's ready event so the counts + glider initialise each time it renders 97 // (idempotent: initGroup guards with .data('rttmIsoInit'), and the editor recreates the DOM 98 // so the guard is naturally clear on the new node). Runs on the real frontend too, harmless. 99 $(window).on('elementor/frontend/init', function () { 100 if (!window.elementorFrontend || !elementorFrontend.hooks || !elementorFrontend.hooks.addAction) { 101 return; 102 } 103 elementorFrontend.hooks.addAction('frontend/element_ready/rttm-team-isotope.default', function ($scope) { 104 $scope.find('.ttp-isotope-buttons').each(function () { 105 initGroup($(this)); 106 }); 107 }); 108 }); 109 110 var resizeT; 111 $(window).on('resize', function () { 112 clearTimeout(resizeT); 113 resizeT = setTimeout(function () { 114 $('.rt-team-container .ttp-isotope-buttons').each(function () { 115 positionGlider($(this)); 116 }); 117 }, 150); 118 }); 119})(jQuery);
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.