1/** 2 * Widget Directory - Search and Filter Functionality 3 */ 4(function($) { 5 'use strict'; 6 7 var WidgetDirectory = { 8 init: function() { 9 this.bindEvents(); 10 }, 11 12 bindEvents: function() { 13 $(document).on('click', '.jltma-widget-dir-tab', this.handleTabClick); 14 $(document).on('input', '.jltma-widget-search', this.handleSearch); 15 16 // Initialize on Elementor frontend init 17 $(window).on('elementor/frontend/init', function() { 18 WidgetDirectory.initWidgets(); 19 }); 20 21 // Initialize on document ready 22 $(document).ready(function() { 23 WidgetDirectory.initWidgets(); 24 }); 25 }, 26 27 initWidgets: function() { 28 $('.jltma-widget-directory').each(function() { 29 var $widget = $(this); 30 31 // Set initial active tab 32 var $activeTab = $widget.find('.jltma-widget-dir-tab.active'); 33 if ($activeTab.length) { 34 WidgetDirectory.filterItems($widget, $activeTab.data('filter')); 35 } 36 }); 37 }, 38 39 handleTabClick: function(e) { 40 e.preventDefault(); 41 42 var $tab = $(this); 43 var $widget = $tab.closest('.jltma-widget-directory'); 44 var filter = $tab.data('filter'); 45 var $wrapper = $widget.find('.jltma-widget-dir-content-wrapper'); 46 var $preloader = $widget.find('.jltma-widget-dir-preloader'); 47 48 // Update active state 49 $widget.find('.jltma-widget-dir-tab').removeClass('active'); 50 $tab.addClass('active'); 51 52 // Clear search 53 $widget.find('.jltma-widget-search').val(''); 54 55 // Show preloader 56 $wrapper.addClass('loading'); 57 $preloader.addClass('active'); 58 59 // Filter items with delay for preloader visibility 60 setTimeout(function() { 61 WidgetDirectory.filterItems($widget, filter); 62 63 // Hide preloader 64 $wrapper.removeClass('loading'); 65 $preloader.removeClass('active'); 66 }, 300); 67 }, 68 69 handleSearch: function(e) { 70 var $search = $(this); 71 var $widget = $search.closest('.jltma-widget-directory'); 72 var searchTerm = $search.val().toLowerCase().trim(); 73 var $activeTab = $widget.find('.jltma-widget-dir-tab.active'); 74 var activeFilter = $activeTab.length ? $activeTab.data('filter') : 'all'; 75 var $wrapper = $widget.find('.jltma-widget-dir-content-wrapper'); 76 var $preloader = $widget.find('.jltma-widget-dir-preloader'); 77 78 // Show preloader 79 $wrapper.addClass('loading'); 80 $preloader.addClass('active'); 81 82 // Debounce search with delay for preloader visibility 83 clearTimeout($search.data('searchTimeout')); 84 var searchTimeout = setTimeout(function() { 85 // If search is empty, show filtered items by tab 86 if (searchTerm === '') { 87 WidgetDirectory.filterItems($widget, activeFilter); 88 } else { 89 // Search through items 90 $widget.find('.jltma-widget-dir-item').each(function() { 91 var $item = $(this); 92 var itemName = $item.data('name'); 93 var itemFilters = $item.data('filters').toString().split(','); 94 95 // Check if item matches search term and active filter 96 var matchesSearch = itemName.indexOf(searchTerm) !== -1; 97 var matchesFilter = activeFilter === 'all' || itemFilters.indexOf(activeFilter) !== -1; 98 99 if (matchesSearch && matchesFilter) { 100 $item.removeClass('hidden'); 101 } else { 102 $item.addClass('hidden'); 103 } 104 }); 105 106 // Update counts 107 WidgetDirectory.updateCounts($widget); 108 } 109 110 // Hide preloader 111 $wrapper.removeClass('loading'); 112 $preloader.removeClass('active'); 113 }, 300); 114 115 $search.data('searchTimeout', searchTimeout); 116 }, 117 118 filterItems: function($widget, filter) { 119 $widget.find('.jltma-widget-dir-item').each(function() { 120 var $item = $(this); 121 var itemFilters = $item.data('filters').toString().split(','); 122 123 if (filter === 'all' || itemFilters.indexOf(filter) !== -1) { 124 $item.removeClass('hidden'); 125 } else { 126 $item.addClass('hidden'); 127 } 128 }); 129 130 // Update counts 131 this.updateCounts($widget); 132 }, 133 134 updateCounts: function($widget) { 135 // Update visible count for current tab 136 var visibleCount = $widget.find('.jltma-widget-dir-item:not(.hidden)').length; 137 var $activeTab = $widget.find('.jltma-widget-dir-tab.active'); 138 139 if ($activeTab.length) { 140 $activeTab.find('.tab-count').text(visibleCount); 141 } 142 } 143 }; 144 145 // Initialize 146 WidgetDirectory.init(); 147 148}
148)(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.