1jQuery(function ($) { 2 function getSelectedCategories($button) { 3 const filterGroup = $button.attr("data-filter-group"); 4 5 if (!filterGroup) { 6 return []; 7 } 8 9 return $(filterGroup) 10 .find(".js-post-filter:checked") 11 .map(function () { 12 return parseInt($(this).val(), 10); 13 }) 14 .get(); 15 } 16 17 function updateFilterClasses($filterGroup) { 18 const hasSelectedFilters = 19 $filterGroup.find(".js-post-filter:checked").length > 0; 20 21 $filterGroup 22 .find(".js-clear-post-filters") 23 .toggleClass("is-active", !hasSelectedFilters); 24 25 $filterGroup.find(".blog-filter-option").removeClass("is-active"); 26 27 $filterGroup 28 .find(".js-post-filter:checked") 29 .closest(".blog-filter-option") 30 .addClass("is-active"); 31 32 $filterGroup.find(".blog-filter-dropdown").each(function () { 33 const $dropdown = $(this); 34 35 const parentSelected = $dropdown 36 .find('.js-post-filter[data-is-parent="true"]') 37 .is(":checked"); 38 39 const totalSubcategories = $dropdown.find( 40 '.js-post-filter:not([data-is-parent="true"])', 41 ).length; 42 43 const selectedSubcategories = $dropdown.find( 44 '.js-post-filter:checked:not([data-is-parent="true"])', 45 ).length; 46 47 const selectedCount = parentSelected 48 ? totalSubcategories 49 : selectedSubcategories; 50 51 $dropdown.find(".blog-filter-count").text(selectedCount); 52 53 $dropdown 54 .find(".js-filter-dropdown-toggle") 55 .toggleClass("is-active", selectedCount > 0); 56 }); 57 } 58 59 function requestPosts($button, page, replaceResults) { 60 const targetSelector = $button.attr("data-target"); 61 const noResultsSelector = $button.attr("data-no-results"); 62 63 const $target = $(targetSelector); 64 const $noResults = noResultsSelector ? $(noResultsSelector) : $(); 65 66 67 if (!$target.length || $button.data("loading")) { 68 return; 69 } 70 71 const originalText = $button.text(); 72 const filterGroup = $button.attr("data-filter-group"); 73 const $filterGroup = filterGroup ? $(filterGroup) : $(); 74 75 $.ajax({ 76 url: themeLoadMore.ajaxUrl, 77 type: "POST", 78 dataType: "json", 79 80 data: { 81 action: "theme_load_more", 82 nonce: themeLoadMore.nonce, 83 page: page, 84 post_type: $button.attr("data-post-type"), 85 categories: getSelectedCategories($button), 86 }, 87 88 beforeSend: function () { 89 90 $button 91 .data("loading", true) 92 .prop("disabled", true) 93 .attr("aria-busy", "true"); 94 95 $filterGroup.find("button, input").prop("disabled", true); 96 97 if (replaceResults) { 98 $target.addClass("is-loading"); 99 } 100 }, 101 102 success: function (response) { 103 if (!response.success) { 104 console.error(response.data?.message || "Unable to load posts."); 105 106 return; 107 } 108 109 const data = response.data; 110 const hasResults = data.html.trim().length > 0; 111 112 if (replaceResults) { 113 $target.html(data.html); 114 } else if (hasResults) { 115 $target.append(data.html); 116 } 117 118 $button 119 .attr("data-page", data.page) 120 .attr("data-max-pages", data.maxPages); 121 122 $button.prop("hidden", !data.hasMore); 123 124 if ($noResults.length) { 125 $noResults.prop("hidden", data.foundPosts > 0); 126 } 127 128 $(document).trigger("themePostsLoaded", [$target, data]); 129 }, 130 131 error: function (xhr) { 132 133 let message = "Something went wrong while loading posts."; 134 135 if ( 136 xhr.responseJSON && 137 xhr.responseJSON.data && 138 xhr.responseJSON.data.message 139 ) { 140 message = xhr.responseJSON.data.message; 141 } 142 143 console.error(message); 144 }, 145 146 complete: function () { 147 page_scroll(); 148 $button 149 .data("loading", false) 150 .prop("disabled", false) 151 .attr("aria-busy", "false"); 152 153 $filterGroup.find("button, input").prop("disabled", false); 154 155 $target.removeClass("is-loading"); 156 }, 157 }); 158 } 159 160 /* 161 * Load the next page. 162 */ 163 $(document).on("click", ".js-load-more", function () { 164 const $button = $(this); 165 const currentPage = parseInt($button.attr("data-page"), 10) || 1; 166 167 requestPosts($button, currentPage + 1, false); 168 }); 169 170 /* 171 * Apply category filters. 172 */ 173 $(document).on("change", ".js-post-filter", function () { 174 const $filter = $(this); 175 const $filterGroup = $filter.closest(".blog-filters"); 176 const $button = $(".js-load-more").filter(function () { 177 return ( 178 $(this).attr("data-filter-group") === "#" + $filterGroup.attr("id") 179 ); 180 }); 181 182 const parentID = String($filter.attr("data-parent") || ""); 183 184 if ($filter.is(":checked") && parentID) { 185 /* 186 * Selecting "View all Parent" clears that parent's 187 * individual child selections. 188 */ 189 if ($filter.attr("data-is-parent") === "true") { 190 $filterGroup 191 .find('.js-post-filter[data-parent="' + parentID + '"]') 192 .not($filter) 193 .prop("checked", false); 194 } else { 195 /* 196 * Selecting a child clears "View all Parent". 197 */ 198 $filterGroup 199 .find( 200 '.js-post-filter[data-is-parent="true"]' +
201 '[data-parent="' + 202 parentID + 203 '"]', 204 ) 205 .prop("checked", false); 206 } 207 } 208 209 updateFilterClasses($filterGroup); 210 211 requestPosts($button, 1, true); 212 }); 213 214 /* 215 * Clear all selected categories. 216 */ 217 $(document).on("click", ".js-clear-post-filters", function () { 218 const $clearButton = $(this); 219 const $filterGroup = $clearButton.closest(".blog-filters"); 220 221 const $button = $(".js-load-more").filter(function () { 222 return ( 223 $(this).attr("data-filter-group") === "#" + $filterGroup.attr("id") 224 ); 225 }); 226 227 $filterGroup.find(".js-post-filter").prop("checked", false); 228 229 updateFilterClasses($filterGroup); 230 231 requestPosts($button, 1, true); 232 }); 233 234 /* 235 * Open and close category dropdowns. 236 */ 237 $(document).on("click", ".js-filter-dropdown-toggle", function () { 238 const $toggle = $(this); 239 const $dropdown = $toggle.closest(".blog-filter-dropdown"); 240 241 const $menu = $dropdown.find(".blog-filter-dropdown-menu"); 242 243 const isOpen = $toggle.attr("aria-expanded") === "true"; 244 245 $(".js-filter-dropdown-toggle").not($toggle).attr("aria-expanded", "false"); 246 247 $(".blog-filter-dropdown-menu").not($menu).prop("hidden", true); 248 249 $toggle.attr("aria-expanded", isOpen ? "false" : "true"); 250 251 $menu.prop("hidden", isOpen); 252 }); 253 254 /* 255 * Close dropdowns when clicking elsewhere. 256 */ 257 $(document).on("click", function (event) { 258 if ($(event.target).closest(".blog-filter-dropdown").length) { 259 return; 260 } 261 262 $(".js-filter-dropdown-toggle").attr("aria-expanded", "false"); 263 264 $(".blog-filter-dropdown-menu").prop("hidden", true); 265 }); 266});
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.