/** * Product archive — sort + AJAX load more. * * @package AKSRT */ (function () { "use strict"; var root = document.querySelector("[data-aksrt-product-archive]"); if (!root) return; function restBase() { var site = (window.aksrtData && aksrtData.siteUrl) ? String(aksrtData.siteUrl).replace(/\/$/, "") : ""; return site + "/wp-json/aksrt/v1"; } function toast(msg) { if (typeof window.aksrtToast === "function") { window.aksrtToast(msg); return; } if (window.console) console.log(msg); } var grid = root.querySelector("[data-aksrt-product-grid], #aksrt-product-grid"); var countEl = root.querySelector("[data-aksrt-archive-count]"); var loadMoreBtn = root.querySelector("[data-aksrt-shop-load-more]"); var state = { taxonomy: root.getAttribute("data-taxonomy") || "", termId: Number(root.getAttribute("data-term-id") || 0), orderby: root.getAttribute("data-orderby") || "date", page: Number(root.getAttribute("data-page") || 1), maxPages: Number(root.getAttribute("data-max-pages") || 1), paging: root.getAttribute("data-paging") || "number", ias: root.getAttribute("data-ias") === "1", iasMax: Number(root.getAttribute("data-ias-max") || 5), loading: false, autoLoads: 0, }; function fetchArchive(page, orderby, replace) { if (state.loading) return Promise.resolve(); state.loading = true; if (loadMoreBtn) { loadMoreBtn.disabled = true; loadMoreBtn.textContent = "加载中..."; } var qs = new URLSearchParams(); qs.set("taxonomy", state.taxonomy); qs.set("term_id", String(state.termId)); qs.set("page", String(page)); qs.set("orderby", orderby || state.orderby); return fetch(restBase() + "/shop/frontend/products/archive?" + qs.toString(), { method: "GET", credentials: "same-origin", headers: { "X-WP-Nonce": (window.aksrtData && aksrtData.restNonce) || "", }, }) .then(function (r) { return r.json(); }) .then(function (result) { state.loading = false; if (!result || !result.success || !result.data) { toast((result && result.message) || "加载失败"); if (loadMoreBtn) { loadMoreBtn.disabled = false; loadMoreBtn.textContent = "加载更多"; } return; } var data = result.data; state.page = Number(data.page || page); state.maxPages = Number(data.max_pages || 1); state.orderby = data.orderby || state.orderby; root.setAttribute("data-page", String(state.page)); root.setAttribute("data-max-pages", String(state.maxPages)); root.setAttribute("data-orderby", state.orderby); if (countEl && typeof data.total !== "undefined") { countEl.textContent = "共 " + data.total + " 件商品"; } if (grid) { if (replace) { grid.innerHTML = data.html || ""; } else if (data.html) { grid.insertAdjacentHTML("beforeend", data.html); } } root.querySelectorAll("[data-aksrt-shop-orderby]").forEach(function (a) { a.classList.toggle("is-active", a.getAttribute("data-aksrt-shop-orderby") === state.orderby); }); if (loadMoreBtn) { var hasMore = state.page < state.maxPages; loadMoreBtn.style.display = hasMore ? "" : "none"; loadMoreBtn.disabled = false; loadMoreBtn.textContent = "加载更多"; } }) .catch(function () { state.loading = false; if (loadMoreBtn) { loadMoreBtn.disabled = false; loadMoreBtn.textContent = "加载更多"; } toast("网络错误"); }); } root.addEventListener("click", function (e) { var sort = e.target.closest("[data-aksrt-shop-orderby]"); if (sort && root.contains(sort)) { e.preventDefault(); var orderby = sort.getAttribute("data-aksrt-shop-orderby") || "date"; if (orderby === state.orderby && state.paging === "ajax") return; state.orderby = orderby; state.autoLoads = 0; try { var u = new URL(window.location.href); u.searchParams.set("shop_orderby", orderby); u.searchParams.delete("paged"); window.history.replaceState({}, "", u.toString()); } catch (err) {} fetchArchive(1, orderby, true); return; } var more = e.target.closest("[data-aksrt-shop-load-more]"); if (more && root.contains(more)) { e.preventDefault(); if (state.page >= state.maxPages) return; fetchArchive(state.page + 1, state.orderby, false); } }); if (state.paging === "ajax" && state.ias && "IntersectionObserver" in window && loadMoreBtn) { var io = new IntersectionObserver(function (entries) { entries.forEach(function (entry) { if (!entry.isIntersecting) return; if (state.loading || state.page >= state.maxPages) return; if (state.iasMax > 0 && state.autoLoads >= state.iasMax) return; state.autoLoads += 1; fetchArchive(state.page + 1, state.orderby, false); }); }, { rootMargin: "240px" }); io.observe(loadMoreBtn); } })();