Wire product cat/tag archives to settings-driven sort and AJAX paging, seller product options/video/params editing, revenue withdraw form and order review submit — finishing remaining shop frontend gaps after buy-path.
153 lines
5.1 KiB
JavaScript
153 lines
5.1 KiB
JavaScript
/**
|
|
* 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);
|
|
}
|
|
})();
|