1 2document.addEventListener("DOMContentLoaded",()=>{const filterWrapper=document.getElementById("productCategories");const container=document.getElementById("productGrid");const catSelect=document.querySelector(".bl-cat-select");if(!container)return;if(!filterWrapper&&!catSelect)return;let currentCat="";let currentPage=1;let totalPages=0;let loader=container.querySelector(".bl-loader-overlay");if(!loader){loader=document.createElement("div");loader.className="bl-loader-overlay";loader.innerHTML='<div class="bl-spinner"></div>';container.appendChild(loader)} 3const templateId=container.dataset.templateId||0;const perPage=container.dataset.perPage||12;const defaultCat=container.dataset.defaultCat||"";const defaultSort=container.dataset.defaultSort||"default";function getCatFromUrl(){const params=new URLSearchParams(window.location.search);const urlCat=params.get("course_cat");return urlCat!==null&&urlCat!==""?urlCat:defaultCat} 4function updateUrl(cat){const newUrl=new URL(window.location);if(cat){newUrl.searchParams.set("course_cat",cat)}else{newUrl.searchParams.delete("course_cat")} 5window.history.pushState({cat},"",newUrl)} 6function setCategory(cat){currentCat=cat;filterWrapper?.querySelectorAll(".bl-cat-item").forEach((el)=>{el.classList.toggle("active",(el.dataset.cat||"")===(cat||""))});if(catSelect){catSelect.value=cat||""}} 7let pageJumpOutsideHandler=null;function closePageJumpPopover(){container.querySelectorAll(".bl-page-jump").forEach((el)=>el.remove());if(pageJumpOutsideHandler){document.removeEventListener("mousedown",pageJumpOutsideHandler);pageJumpOutsideHandler=null}} 8function setActivePage(page){container.querySelectorAll(".bl-pagination .bl-page[data-page]").forEach((btn)=>{btn.classList.toggle("active",parseInt(btn.dataset.page,10)===page)})} 9function showPageJumpPopover(ellipsisBtn){const existing=ellipsisBtn.nextElementSibling;if(existing&&existing.classList.contains("bl-page-jump")){closePageJumpPopover();return} 10closePageJumpPopover();const start=parseInt(ellipsisBtn.dataset.start,10);const end=parseInt(ellipsisBtn.dataset.end,10);const popover=document.createElement("div");popover.className="bl-page-jump";popover.innerHTML='<span class="bl-page-jump-field">'+'<span class="bl-page-jump-label">Page</span>'+'<input type="number" class="bl-page-jump-input" min="'+start+'" max="'+end+'" placeholder="'+start+"\u2013"+end+'" aria-label="Page number" />'+"</span>"+'<button type="button" class="bl-page-jump-go">Go</button>';ellipsisBtn.insertAdjacentElement("afterend",popover);const input=popover.querySelector(".bl-page-jump-input");popover.addEventListener("mousedown",(e)=>e.stopPropagation());popover.addEventListener("click",(e)=>e.stopPropagation());input.focus();const go=()=>{const num=parseInt(input.value,10);const max=totalPages||parseInt(end,10);if(num>=1&&num<=max){currentPage=num;setActivePage(currentPage);closePageJumpPopover();fetchProducts(currentCat,currentPage)}};popover.querySelector(".bl-page-jump-go").addEventListener("click",(e)=>{e.preventDefault();e.stopPropagation();go()});input.addEventListener("keydown",(ev)=>{if(ev.key==="Enter"){ev.preventDefault();go()} 11if(ev.key==="Escape")closePageJumpPopover();});pageJumpOutsideHandler=(ev)=>{if(popover.contains(ev.target)||ellipsisBtn.contains(ev.target)){return} 12closePageJumpPopover()};setTimeout(()=>{document.addEventListener("mousedown",pageJumpOutsideHandler)},0)} 13async function fetchProducts(catSlug=defaultCat,page=1,sort=defaultSort){closePageJumpPopover();loader.style.display="flex";const formData=new FormData();formData.append("action","bl_filter_products");formData.append("nonce",blCatFilter.nonce);formData.append("course_cat",catSlug);formData.append("paged",page);formData.append("template_id",templateId);formData.append("per_page",perPage);formData.append("sort",sort);if(blCatFilter.lang)formData.append("lang",blCatFilter.lang);const searchInput=document.querySelector(".bl-search-input");if(searchInput)formData.append("search",searchInput.value);try{const response=await fetch(blCatFilter.ajax_url,{method:"POST",body:formData});const result=await response.json();if(result.success){const existingInner=container.querySelector(".bl-products-inner");if(existingInner){existingInner.outerHTML=result.data.html}else{container.insertAdjacentHTML("afterbegin",result.data.html)} 14const oldPagination=container.querySelector(".bl-pagination");if(oldPagination)oldPagination.remove();if(result.data.pagination){const paginationWrapper=document.createElement("div");paginationWrapper.innerHTML=result.data.pagination;container.appendChild(paginationWrapper)} 15if(result.data.total_pages){totalPages=parseInt(result.data.total_pages,10)}}else{container.innerHTML="<p>No products found.</p>";container.appendChild(loader)}}catch(error){console.error(error);container.innerHTML="<p>Error loading products.</p>";container.appendChild(loader)} 16loader.style.display="none"} 17filterWrapper?.addEventListener("click",(e)=>{const link=e.target.closest(".bl-cat-item");if(!link)return;e.preventDefault();currentPage=1;setCategory(link.dataset.cat||"");updateUrl(currentCat);fetchProducts(currentCat,currentPage)});catSelect?.addEventListener("change",()=>{currentPage=1;setCategory(catSelect.value);updateUrl(currentCat);fetchProducts(currentCat,currentPage)});container.addEventListener("click",(e)=>{const ellipsis=e.target.closest(".bl-page-ellipsis");if(ellipsis){e.preventDefault();e.stopPropagation();showPageJumpPopover(ellipsis);return} 18const pageBtn=e.target.closest(".bl-page[data-page]");if(!pageBtn)return;e.preventDefault();closePageJumpPopover();currentPage=parseInt(pageBtn.dataset.page,10);setActivePage(currentPage);fetchProducts(currentCat,currentPage)});const searchInput=document.querySelector(".bl-search-input");if(searchInput){searchInput.addEventListener("keyup",(e)=>{if(e.key==="Enter"){currentPage=1;fetchProducts(currentCat,currentPage)}});const searchBtn=document.querySelector(".bl-search-btn");if(searchBtn){searchBtn.addEventListener("click",()=>{currentPage=1;fetchProducts(currentCat,currentPage)})}} 19const sortSelect=document.querySelector(".bl-sort-select");if(sortSelect){sortSelect.addEventListener("change",()=>{currentPage=1;fetchProducts(currentCat,currentPage)})} 20window.addEventListener("popstate",()=>{currentPage=1;setCategory(getCatFromUrl());fetchProducts(currentCat,currentPage)});setCategory(getCatFromUrl());fetchProducts(currentCat,currentPage)}); 21 22
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.