/* =========================================================================
* Isotope filter bar — count badges + sliding glider (redesign, appended).
* Self-contained: enhances the plugin's .ttp-isotope-buttons on EVERY isotope
* layout (global nav style), not just isotope-free. Counts are read from the
* loaded .isotope-item items in the .rt-content-loader row; the glider is a
* span that slides to the active pill. Adds .rttm-iso-has-glider to the group so
* the CSS can make the active button transparent (glider provides the gradient);
* without JS the CSS keeps a gradient background on .selected as a fallback.
* ========================================================================= */
(function ($) {
'use strict';
function positionGlider($group) {
var $active = $group.children('button.selected').filter(':visible').first();
var $glider = $group.children('.rttm-iso-glider');
if (!$active.length || !$glider.length) {
$glider.css('opacity', 0);
return;
}
var btn = $active[0];
$glider.css({
left: btn.offsetLeft + 'px',
top: btn.offsetTop + 'px',
width: btn.offsetWidth + 'px',
height: btn.offsetHeight + 'px',
opacity: 1
});
}
function initGroup($group) {
if ($group.data('rttmIsoInit')) {
positionGlider($group);
return;
}
$group.data('rttmIsoInit', true);
// `.rt-content-loader` is the row shared by EVERY isotope layout (it wraps both the
// filter bar and the items), and `.isotope-item` is the item class every isotope layout
// uses — so counting works on any isotope layout, not just isotope-free.
var $row = $group.closest('.rt-content-loader');
// 1. count badge per button (from the loaded items); hide empty non-"all" filters
$group.children('button').each(function () {
var $btn = $(this);
var f = $btn.attr('data-filter');
var count;
try {
count = (f === '*') ? $row.find('.isotope-item').length : $row.find('.isotope-item' + f).length;
} catch (e) {
count = 0;
}
if (count === 0 && f !== '*') {
$btn.hide();
return;
}
if (!$btn.children('.count').length) {
$btn.append(' ' + count + '');
}
});
// 2. glider element (behind the pills) + flag the group so CSS clears the button bg
if (!$group.children('.rttm-iso-glider').length) {
$group.prepend('');
}
$group.addClass('rttm-iso-has-glider');
// 3. slide the glider when a pill is clicked (after the plugin toggles .selected)
$group.on('click.rttmIso', 'button', function () {
setTimeout(function () { positionGlider($group); }, 0);
});
positionGlider($group);
// re-measure once more after fonts/layout settle
setTimeout(function () { positionGlider($group); }, 250);
}
function initAll() {
$('.rt-team-container .ttp-isotope-buttons').each(function () {
initGroup($(this));
});
}
$(window).on('load', initAll);
$(document).ready(initAll);
// Expose the initialiser for contexts that inject the filter-bar markup AFTER page load,
// where the load/ready handlers above never fire — e.g. the admin shortcode preview, which
// re-renders via AJAX on every form change. Safe to call repeatedly: initGroup is idempotent
// per group (guards on .data('rttmIsoInit')), and the preview replaces the DOM each render so
// a fresh group re-initialises cleanly.
window.rttmIsoFilter = { init: initAll, initGroup: initGroup, position: positionGlider };
// Elementor renders widgets asynchronously and, in the EDITOR, re-renders them on every
// change WITHOUT a page reload — so the load/ready handlers above never fire for the fresh
// DOM. Hook the widget's ready event so the counts + glider initialise each time it renders
// (idempotent: initGroup guards with .data('rttmIsoInit'), and the editor recreates the DOM
// so the guard is naturally clear on the new node). Runs on the real frontend too, harmless.
$(window).on('elementor/frontend/init', function () {
if (!window.elementorFrontend || !elementorFrontend.hooks || !elementorFrontend.hooks.addAction) {
return;
}
elementorFrontend.hooks.addAction('frontend/element_ready/rttm-team-isotope.default', function ($scope) {
$scope.find('.ttp-isotope-buttons').each(function () {
initGroup($(this));
});
});
});
var resizeT;
$(window).on('resize', function () {
clearTimeout(resizeT);
resizeT = setTimeout(function () {
$('.rt-team-container .ttp-isotope-buttons').each(function () {
positionGlider($(this));
});
}, 150);
});
})(jQuery);