/** * AKSRT AJAX Pagination & Lazy Load */ (function () { "use strict"; function hasAjaxConfig() { return !!(window.aksrtData && aksrtData.ajaxUrl && aksrtData.nonce); } function initAjaxPagination(root) { var containers = (root || document).querySelectorAll(".aksrt-pagination-ajax, .ajax-pagination"); if (!containers.length) return; var triggerText = (window.aksrtData && aksrtData.ajaxTrigger) || "加载更多"; var nomoreText = (window.aksrtData && aksrtData.ajaxNomore) || "没有更多了"; var loadingText = (window.aksrtData && aksrtData.ajaxLoading) || "正在加载..."; var errorText = (window.aksrtData && aksrtData.ajaxLoadError) || "加载失败,请重试"; containers.forEach(function (container) { if (container.dataset.aksrtPaginationBound === "1") return; container.dataset.aksrtPaginationBound = "1"; var mode = container.dataset.mode || "load_more"; var nextPage = parseInt(container.dataset.nextPage, 10) || 2; var maxPages = parseInt(container.dataset.maxPages, 10) || 1; var isComment = container.classList.contains("aksrt-comment-pagination"); var postId = container.dataset.postId || ""; var commentOrder = container.dataset.commentOrder || "newest"; var loading = false; var failed = false; var loadMoreBtn = container.querySelector(".aksrt-load-more-btn, .ajax-next"); var indicator = container.querySelector(".aksrt-loading-indicator"); var observer = null; var iasEnabled = false; var successfulAutoLoads = 0; var target = container.previousElementSibling; if (target && target.classList && target.classList.contains("content-stream__footer")) { target = target.previousElementSibling; } if (isComment) { var commentList = document.getElementById("comment-list") || (container.parentElement && container.parentElement.querySelector("#comment-list, .commentlist, ol.commentlist")); if (commentList) target = commentList; } if (!target && container.parentElement) { target = container.parentElement.querySelector(".post-grid, .comment-list, .commentlist, .content-stream__list"); } function showSkeleton() { if (!target) return; var loader = target.querySelector(".post-ajax-loader"); if (loader) { loader.classList.add("is-loading"); } } function hideSkeleton() { if (!target) return; var loader = target.querySelector(".post-ajax-loader"); if (loader) { loader.classList.remove("is-loading"); } } function stopInfinite(markNomore) { if (observer) { observer.disconnect(); observer = null; } iasEnabled = false; container.classList.remove("ias-pending"); if (markNomore && loadMoreBtn) { loadMoreBtn.textContent = nomoreText; loadMoreBtn.classList.remove("is-loading"); loadMoreBtn.classList.add("ajax-nomore"); loadMoreBtn.style.pointerEvents = "none"; } else if (loadMoreBtn && !loadMoreBtn.classList.contains("ajax-nomore")) { loadMoreBtn.classList.remove("is-loading"); loadMoreBtn.textContent = failed ? errorText : triggerText; loadMoreBtn.style.pointerEvents = ""; } } function markFailed(message) { failed = true; stopInfinite(false); if (loadMoreBtn) { loadMoreBtn.textContent = message || errorText; loadMoreBtn.classList.remove("is-loading"); loadMoreBtn.classList.remove("ajax-nomore"); loadMoreBtn.style.pointerEvents = ""; } } function loadNextPage(fromAuto) { if (loading || failed || nextPage > maxPages || !target) return Promise.resolve(false); if (!hasAjaxConfig()) { markFailed(errorText); return Promise.resolve(false); } loading = true; if (indicator) indicator.style.display = "flex"; if (loadMoreBtn) { loadMoreBtn.classList.add("is-loading"); loadMoreBtn.textContent = loadingText; } showSkeleton(); var action = isComment ? "aksrt_load_more_comments" : "aksrt_load_more_posts"; var queryContext = container.dataset.queryContext || ""; var queryVars = container.dataset.queryVars || ""; var renderConfig = container.dataset.renderConfig || ""; var body = new URLSearchParams(); body.set("action", action); body.set("nonce", aksrtData.nonce); body.set("page", String(nextPage)); if (queryContext) { body.set("query_context", queryContext); } if (!isComment && queryVars) { body.set("query_vars", queryVars); } if (!isComment && renderConfig) { body.set("render_config", renderConfig); } if (isComment && postId) { body.set("post_id", postId); body.set("comment_order", commentOrder); var authorOnly = container.dataset.authorOnly || "0"; if (authorOnly === "1") body.set("author_only", "1"); } return fetch(aksrtData.ajaxUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" }, credentials: "same-origin", body: body.toString(), }) .then(function (r) { if (!r.ok) { throw new Error("HTTP " + r.status); } return r.text().then(function (text) { try { return JSON.parse(text); } catch (err) { throw new Error("Invalid JSON"); } }); }) .then(function (res) { if (!(res && res.success && res.data && typeof res.data.html === "string")) { var msg = res && res.data && res.data.message ? res.data.message : errorText; markFailed(msg); return false; } var temp = document.createElement("div"); temp.innerHTML = res.data.html; var newItems = temp.children; while (newItems.length > 0) { target.appendChild(newItems[0]); } if (isComment && window.AksrtFrontend) { AksrtFrontend.rehydrate(target, "ajax"); } nextPage++; container.dataset.nextPage = String(nextPage); if (fromAuto) { successfulAutoLoads++; } if (typeof initLazyLoad === "function") initLazyLoad(target); if (nextPage > maxPages || !res.data.has_more) { stopInfinite(true); if (!loadMoreBtn) { container.innerHTML = '' + nomoreText + ''; } } return true; }) .catch(function () { markFailed(errorText); return false; }) .finally(function () { loading = false; hideSkeleton(); if (indicator) indicator.style.display = "none"; if (loadMoreBtn && !loadMoreBtn.classList.contains("ajax-nomore") && !failed) { loadMoreBtn.classList.remove("is-loading"); loadMoreBtn.textContent = triggerText; } }); } if (loadMoreBtn) { loadMoreBtn.addEventListener("click", function(e) { e.preventDefault(); if (loadMoreBtn.dataset.jumpComments === "1") { var jumpInput = container.querySelector(".jump-input"); if (!jumpInput) return; var targetPage = parseInt(jumpInput.value, 10) || 1; var max = parseInt(jumpInput.dataset.maxPages || String(maxPages), 10) || maxPages; targetPage = Math.max(1, Math.min(max, targetPage)); var url = new URL(window.location.href); url.searchParams.set("cpage", String(targetPage)); window.location.href = url.toString(); return; } if (loadMoreBtn.dataset.jumpArchive === "1") { var archiveJumpInput = container.querySelector(".jump-input"); if (!archiveJumpInput) return; var archiveTargetPage = parseInt(archiveJumpInput.value, 10) || 1; var archiveMax = parseInt(archiveJumpInput.dataset.maxPages || String(maxPages), 10) || maxPages; archiveTargetPage = Math.max(1, Math.min(archiveMax, archiveTargetPage)); var archiveUrl = new URL(window.location.href); archiveUrl.searchParams.set("paged", String(archiveTargetPage)); window.location.href = archiveUrl.toString(); return; } // Manual click can recover from a previous auto-load failure. failed = false; loadNextPage(false); }); } if (mode === "infinite" && "IntersectionObserver" in window) { if (isComment && window.aksrtData && aksrtData.commentIasAuto === false) { return; } if (!hasAjaxConfig()) { return; } var sentinel = document.createElement("div"); sentinel.className = "aksrt-scroll-sentinel"; container.appendChild(sentinel); var lazyloadAction = container.dataset.lazyloadAction || ""; var iasMax = isComment ? ((window.aksrtData && typeof aksrtData.commentIasMax !== "undefined") ? parseInt(aksrtData.commentIasMax, 10) : 0) : ((window.aksrtData && typeof aksrtData.iasMax !== "undefined") ? parseInt(aksrtData.iasMax, 10) : 0); observer = new IntersectionObserver( function (entries) { if (!iasEnabled || failed) return; if (!(entries[0] && entries[0].isIntersecting) || loading) return; if (iasMax > 0 && successfulAutoLoads >= iasMax) { stopInfinite(true); return; } loadNextPage(true); }, { rootMargin: "200px" } ); if (lazyloadAction === "ias") { container.classList.add("ias-pending"); } // Policy A: do not auto-fire on first paint; wait for real user scroll. var enableOnScroll = function () { if (iasEnabled || failed) return; iasEnabled = true; container.classList.remove("ias-pending"); observer.observe(sentinel); }; window.addEventListener("scroll", enableOnScroll, { passive: true, once: true }); window.addEventListener("touchmove", enableOnScroll, { passive: true, once: true }); window.addEventListener("wheel", enableOnScroll, { passive: true, once: true }); } }); } function initLazyLoad(root) { var scope = root || document; var lazyImages = scope.querySelectorAll("img.aksrt-lazy"); if (!lazyImages.length) return; if (!("IntersectionObserver" in window)) { lazyImages.forEach(function (img) { var src = img.dataset.src; if (src) { img.src = src; img.classList.remove("aksrt-lazy"); img.classList.add("aksrt-loaded"); } var skeleton = img.previousElementSibling; if (skeleton && skeleton.classList.contains("aksrt-skeleton")) { skeleton.remove(); } }); return; } var observer = new IntersectionObserver(function (entries) { entries.forEach(function (entry) { if (!entry.isIntersecting) return; var img = entry.target; var src = img.dataset.src; if (!src) { observer.unobserve(img); return; } var tempImg = new Image(); tempImg.onload = function () { img.src = src; img.classList.remove("aksrt-lazy"); img.classList.add("aksrt-loaded"); var skeleton = img.previousElementSibling; if (skeleton && skeleton.classList.contains("aksrt-skeleton")) { skeleton.remove(); } }; tempImg.onerror = function () { img.classList.remove("aksrt-lazy"); img.classList.add("aksrt-error"); var skeleton = img.previousElementSibling; if (skeleton && skeleton.classList.contains("aksrt-skeleton")) { skeleton.remove(); } }; tempImg.src = src; observer.unobserve(img); }); }, { rootMargin: "200px 0px", threshold: 0.01 }); lazyImages.forEach(function (img) { observer.observe(img); }); } window.AksrtFrontend.register("aksrt-ajax-pagination", function (root) { initAjaxPagination(root); }); window.AksrtFrontend.register("aksrt-lazy-load", function (root) { initLazyLoad(root); }); })();