您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Makes so that the gallery continues loading the next page when you reach its bottom
当前为
// ==UserScript== // @name FA Infini-Gallery // @namespace Violentmonkey Scripts // @match *://*.furaffinity.net/* // @require https://update.gf.qytechs.cn/scripts/475041/1267274/Furaffinity-Custom-Settings.js // @require https://update.gf.qytechs.cn/scripts/485827/1326313/Furaffinity-Match-List.js // @require https://update.gf.qytechs.cn/scripts/483952/1519487/Furaffinity-Request-Helper.js // @grant GM_info // @version 2.0.1 // @author Midori Dragon // @description Makes so that the gallery continues loading the next page when you reach its bottom // @icon https://www.furaffinity.net/themes/beta/img/banners/fa_logo.png?v2 // @license MIT // ==/UserScript== // jshint esversion: 8 (() => { "use strict"; var __webpack_require__ = { d: (exports, definition) => { for (var key in definition) __webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key) && Object.defineProperty(exports, key, { enumerable: !0, get: definition[key] }); }, o: (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop) }; function createSeparatorElem(pageNo) { const nextPageDescContainer = document.createElement("div"); nextPageDescContainer.className = "folder-description", nextPageDescContainer.style.marginTop = "6px", nextPageDescContainer.style.marginBottom = "6px"; const nextPageDesc = document.createElement("div"); nextPageDesc.className = "container-item-top"; const nextPageDescText = document.createElement("h3"), pageString = pageSeparatorTextSetting.value.replace(/%page%/g, pageNo); return nextPageDescText.textContent = pageString, nextPageDesc.appendChild(nextPageDescText), nextPageDescContainer.appendChild(nextPageDesc), nextPageDescContainer; } function getFiguresFromPage(page) { return page.querySelectorAll('figure[class*="t"]'); } function getUserNameFromUrl(url) { return url.includes("?") && (url = url.substring(0, url.indexOf("?"))), (url = trimEnd(url, "/")).substring(url.lastIndexOf("/") + 1); } function trimEnd(string, toRemove) { return string.endsWith(toRemove) && (string = string.slice(0, -1)), string; } __webpack_require__.d({}, { I4: () => pageSeparatorTextSetting, uL: () => requestHelper, kG: () => showPageSeparatorSetting }); class BrowsePage { constructor(pageNo) { this.pageNo = pageNo, this.gallery = document.querySelector('section[id*="gallery"]'); } async getPage() { return await requestHelper.UserRequests.SearchRequests.Browse.getPage(this.pageNo, this.getBrowseOptions()); } getBrowseOptions() { const browseOptions = requestHelper.UserRequests.SearchRequests.Browse.newBrowseOptions, sideBar = document.getElementById("sidebar-options"), optionContainers = sideBar.querySelectorAll('div[class*="browse-search-flex-item"]'); for (const optionContainer of Array.from(optionContainers)) try { const optionName = trimEnd(optionContainer.querySelector("strong").textContent.toLowerCase(), ":"), optionValue = optionContainer.querySelector("option[selected]").getAttribute("value"); browseOptions[optionName] = optionValue; } catch {} const checkBoxes = sideBar.querySelectorAll('input[type="checkbox"]'); for (const checkbox of Array.from(checkBoxes)) switch (checkbox.getAttribute("name")) { case "rating_general": browseOptions.ratingGeneral = checkbox.hasAttribute("checked"); break; case "rating_mature": browseOptions.ratingMature = checkbox.hasAttribute("checked"); break; case "rating_adult": browseOptions.ratingAdult = checkbox.hasAttribute("checked"); } return browseOptions; } async loadPage() { const figures = getFiguresFromPage(await this.getPage()); if (!figures || 0 === figures.length) throw new Error("No figures found"); if (!0 === showPageSeparatorSetting.value) { const separator = createSeparatorElem(this.pageNo); this.gallery.appendChild(separator); } for (const figure of Array.from(figures)) this.gallery.appendChild(figure); window.dispatchEvent(new CustomEvent("updateEmbeddedEvent")); } } class FavoritesPage { constructor(pageNo) { this.pageNo = pageNo, this.gallery = document.querySelector('section[id*="gallery"]'); } async getPage() { const username = getUserNameFromUrl(window.location.toString()); return await requestHelper.UserRequests.GalleryRequests.Favorites.getPage(username, this.pageNo); } async loadPage() { const figures = getFiguresFromPage(await this.getPage()); if (!figures || 0 === figures.length) throw new Error("No figures found"); if (!0 === showPageSeparatorSetting.value) { const separator = createSeparatorElem(this.pageNo); this.gallery.appendChild(separator); } for (const figure of Array.from(figures)) this.gallery.appendChild(figure); window.dispatchEvent(new CustomEvent("updateEmbeddedEvent")); } } class GalleryPage { constructor(pageNo) { this.pageNo = pageNo, this.gallery = document.querySelector('section[id*="gallery"]'), this.isInFolder = window.location.toString().includes("/folder/"); } async getPage() { const username = getUserNameFromUrl(window.location.toString()); let page; if (!0 === this.isInFolder) { let folderId; page = await requestHelper.UserRequests.GalleryRequests.Gallery.getPageInFolder(username, folderId, this.pageNo); } else page = await requestHelper.UserRequests.GalleryRequests.Gallery.getPage(username, this.pageNo); return page; } async loadPage() { const figures = getFiguresFromPage(await this.getPage()); if (!figures || 0 === figures.length) throw new Error("No figures found"); if (!0 === showPageSeparatorSetting.value) { const separator = createSeparatorElem(this.pageNo); this.gallery.appendChild(separator); } for (const figure of Array.from(figures)) this.gallery.appendChild(figure); window.dispatchEvent(new CustomEvent("updateEmbeddedEvent")); } } class ScrapsPage { constructor(pageNo) { this.pageNo = pageNo, this.gallery = document.querySelector('section[id*="gallery"]'); } async getPage() { const username = getUserNameFromUrl(window.location.toString()); return await requestHelper.UserRequests.GalleryRequests.Scraps.getPage(username, this.pageNo); } async loadPage() { const figures = getFiguresFromPage(await this.getPage()); if (!figures || 0 === figures.length) throw new Error("No figures found"); if (!0 === showPageSeparatorSetting.value) { const separator = createSeparatorElem(this.pageNo); this.gallery.appendChild(separator); } for (const figure of Array.from(figures)) this.gallery.appendChild(figure); window.dispatchEvent(new CustomEvent("updateEmbeddedEvent")); } } class SearchPage { constructor(pageNo) { this.pageNo = pageNo, this.gallery = document.querySelector('section[id*="gallery"]'); } async getPage() { return await requestHelper.UserRequests.SearchRequests.Search.getPage(this.pageNo, this.getSearchOptions()); } getSearchOptions() { const searchOptions = requestHelper.UserRequests.SearchRequests.Search.newSearchOptions, input = document.getElementById("q"); searchOptions.input = input.getAttribute("value"); const searchContainer = document.getElementById("search-advanced"), options = searchContainer.querySelectorAll("option[selected]"); for (const option of Array.from(options)) { const name = option.parentNode instanceof HTMLSelectElement ? option.parentNode.getAttribute("name") : null, value = option.getAttribute("value"); switch (name) { case "order-by": searchOptions.orderBy = value; break; case "order-direction": searchOptions.orderDirection = value; } } const radioButtons = searchContainer.querySelectorAll('input[type="radio"][checked]'); for (const radioButton of Array.from(radioButtons)) { const name = radioButton.getAttribute("name"), value = radioButton.getAttribute("value"); switch (name) { case "range": searchOptions.range = value; break; case "mode": searchOptions.matching = value; } if ("manual" == value) { const rangeFrom = searchContainer.querySelector('input[type="date"][name="range_from"]'); searchOptions.rangeFrom = rangeFrom.getAttribute("value"); const rangeTo = searchContainer.querySelector('input[type="date"][name="range_to"]'); searchOptions.rangeTo = rangeTo.getAttribute("value"); } } const checkBoxes = searchContainer.querySelectorAll('input[type="checkbox"]'); for (const checkBox of Array.from(checkBoxes)) switch (checkBox.getAttribute("name")) { case "rating-general": searchOptions.ratingGeneral = checkBox.hasAttribute("checked"); break; case "rating-mature": searchOptions.ratingMature = checkBox.hasAttribute("checked"); break; case "rating-adult": searchOptions.ratingAdult = checkBox.hasAttribute("checked"); break; case "type-art": searchOptions.typeArt = checkBox.hasAttribute("checked"); break; case "type-music": searchOptions.typeMusic = checkBox.hasAttribute("checked"); break; case "type-flash": searchOptions.typeFlash = checkBox.hasAttribute("checked"); break; case "type-story": searchOptions.typeStory = checkBox.hasAttribute("checked"); break; case "type-photo": searchOptions.typePhotos = checkBox.hasAttribute("checked"); break; case "type-poetry": searchOptions.typePoetry = checkBox.hasAttribute("checked"); } return searchOptions; } async loadPage() { const figures = getFiguresFromPage(await this.getPage()); if (!figures || 0 === figures.length) throw new Error("No figures found"); if (!0 === showPageSeparatorSetting.value) { const separator = createSeparatorElem(this.pageNo); this.gallery.appendChild(separator); } for (const figure of Array.from(figures)) this.gallery.appendChild(figure); window.dispatchEvent(new CustomEvent("updateEmbeddedEvent")); } } class GalleryManager { constructor() { if (this.pageNo = 1, this.isGallery = window.location.toString().includes("net/gallery"), this.isFavorites = window.location.toString().includes("net/favorites"), this.isScraps = window.location.toString().includes("net/scraps"), this.isBrowse = window.location.toString().includes("net/browse"), !0 === this.isBrowse) { const pageOption = document.getElementById("manual-page"); pageOption instanceof HTMLInputElement && (this.pageNo = parseInt(pageOption.value)); } this.isSearch = window.location.toString().includes("net/search"); } async loadNextPage() { let nextPage; this.pageNo++, !0 === this.isGallery ? nextPage = new GalleryPage(this.pageNo) : !0 === this.isFavorites ? nextPage = new FavoritesPage(this.pageNo) : !0 === this.isScraps ? nextPage = new ScrapsPage(this.pageNo) : !0 === this.isBrowse ? nextPage = new BrowsePage(this.pageNo) : !0 === this.isSearch && (nextPage = new SearchPage(this.pageNo)), await nextPage.loadPage(); } } class InfiniGallery { constructor() { this.scanElem = document.getElementById("footer"), this.galleryManager = new GalleryManager; } startScrollDetection() { this.scanInterval = setInterval((() => { (function(element) { const rect = element.getBoundingClientRect(), windowHeight = 2 * (window.innerHeight || document.documentElement.clientHeight); return rect.top <= windowHeight && rect.top + rect.height >= 0; })(this.scanElem) && (this.stopScrollDetection(), this.loadNextPage()); }), 100); } stopScrollDetection() { clearInterval(this.scanInterval); } async loadNextPage() { try { await this.galleryManager.loadNextPage(), this.startScrollDetection(); } catch { this.stopScrollDetection(); } } } CustomSettings.name = "Extension Settings", CustomSettings.provider = "Midori's Script Settings", CustomSettings.headerName = `${GM_info.script.name} Settings`; const showPageSeparatorSetting = CustomSettings.newSetting("Page Separator", "Wether a Page Separator is shown foreach new Page loaded.", SettingTypes.Boolean, "Show Page Separators", !0), pageSeparatorTextSetting = CustomSettings.newSetting("Page Separator Text", "The Text that is displayed when a new Infini-Gallery Page is loaded (if shown). Number of Page gets inserted instead of: %page% .", SettingTypes.Text, "", "Infini-Gallery Page: %page%"); CustomSettings.loadSettings(); const matchList = new MatchList(CustomSettings); matchList.matches = [ "net/gallery", "net/favorites", "net/scraps", "net/browse", "net/search" ], matchList.runInIFrame = !1; const requestHelper = new FARequestHelper(2); if (matchList.hasMatch()) { (new InfiniGallery).startScrollDetection(); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址