Infini-Gallery

Makes so that the gallery continues loading the next page when you reach its bottom

当前为 2023-04-06 提交的版本,查看 最新版本

// ==UserScript==
// @name        Infini-Gallery
// @namespace   Violentmonkey Scripts
// @match       *://*.furaffinity.net/*
// @grant       none
// @version     1.3
// @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
// @homepageURL https://gf.qytechs.cn/de/scripts/462632-infini-gallery
// @supportURL  https://gf.qytechs.cn/de/scripts/462632-infini-gallery/feedback
// @license     MIT
// ==/UserScript==

// jshint esversion: 8

//User Options:
let showPageSeperator = JSON.parse(localStorage.getItem("igsetting_01"));
if (showPageSeperator == null)
  showPageSeperator = true;
let showDisableButton = JSON.parse(localStorage.getItem("igsetting_02"));
if (showDisableButton == null)
  showDisableButton = true;
const matchList = ['net/browse', 'net/gallery', 'net/search', 'net/favorites' ];

const isSettings = window.location.toString().includes('controls/settings');
let exSettings = JSON.parse(localStorage.getItem("igsettings"));
if (exSettings == null)
  exSettings = false;
addExSettings();
if (isSettings) {
  addExSettingsSidebar();
  if (exSettings)
    createSettings();
}

if (window.parent !== window)
  return;
if (!matchList.some(x => window.location.toString().includes(x)))
  return;

console.info('%cRunning: Infini-Gallery', 'color: blue');


const isGallery = window.location.toString().includes('net/gallery');
const isFavorites = window.location.toString().includes('net/favorites');
const isBrowse = window.location.toString().includes('net/browse');

let allowScan = true;
let nextButtons;
let lastNextButton;
let gallery;
let lastLink;
let lastNextPageButton;
let pageCount;

if (!isSettings) {
  if (isGallery)
    nextButtons = document.querySelectorAll('button[class*="button standard"][type="submit"]');
  else if (isFavorites)
    nextButtons = document.querySelectorAll('a[class*="button mobile-button right"][href]');
  else if (isBrowse)
    nextButtons = document.querySelectorAll('a[class*="button standard"][href]');
  if (!nextButtons || nextButtons.length == 0)
    return;

  if (showDisableButton) {
    let navPage = document.querySelector('userpage-nav-links').querySelector('ul');
    let disableIGButton = document.createElement('button');
    disableIGButton.id = "disableIGButton";
    disableIGButton.type = "button";
    disableIGButton.className = "button standard mobile-fix";
    disableIGButton.textContent = "Disable Infini Gallery";
    disableIGButton.style.marginTop = "8px";
    disableIGButton.style.marginRight = "18px";
    disableIGButton.onclick = function() {
      allowScan = !allowScan;
      if (allowScan) {
        disableIGButton.textContent = "Disable Infini Gallery";
        scan();
      } else
        disableIGButton.textContent = "Enable Infini Gallery";
    };
    navPage.appendChild(disableIGButton);
  }

  lastNextButton = nextButtons[nextButtons.length - 1];
  gallery = document.querySelector('section[id*="gallery"]');
  lastLink = window.location.toString();
  lastNextPageButton = lastNextButton;
  pageCount = 1;
  scan();
}

async function scan() {
  const interval = setInterval(() => {
    if (!allowScan)
      clearInterval(interval);
    if (isElementOnScreen(lastNextButton)) {
      clearInterval(interval);
      loadNextPage();
    }
  }, 100);
}

async function loadNextPage() {
  let figures;
  if (isGallery)
    figures = await getNextPageFiguresGallery();
  else if (isFavorites)
    figures = await getNextPageFiguresFavorites();
  else if (isBrowse)
    figures = await getNextPageFiguresGallery();
  if (!figures || figures.length == 0) {
    lastNextButton.parentNode.removeChild(lastNextButton);
    return;
  }
  pageCount++;
  let nextPageDescContainer = document.createElement('div');
  nextPageDescContainer.className = 'folder-description';
  nextPageDescContainer.style.marginTop = '6px';
  nextPageDescContainer.style.marginBottom = '6px';
  let nextPageDesc = document.createElement('div');
  nextPageDesc.className = 'container-item-top';
  let nextPageDescText = document.createElement('h3');
  nextPageDescText.textContent = 'Page: ' + pageCount;
  nextPageDesc.appendChild(nextPageDescText);
  nextPageDescContainer.appendChild(nextPageDesc);
  gallery.appendChild(nextPageDescContainer);
  for (const figure of figures)
    gallery.appendChild(figure);
  try { window.updateEmbedded(); } catch {} //Embedded Image Viewer Integration
  try { window.updateFastFavoriter(); } catch {} //Fast Favoriter 2 Integration

  await scan();
}

async function getNextPageFiguresGallery() {
  const nextLink = await incrementUrlLastNumber(lastLink);
  console.log(nextLink);
  lastLink = nextLink;
  const nextPage = await getHTML(nextLink);
  const figures = nextPage.querySelectorAll('figure[class*="t"]');
  return figures;
}
async function getNextPageFiguresFavorites() {
  const nextLink = lastNextPageButton.href;
  console.log(nextLink);
  lastLink = nextLink;
  const nextPage = await getHTML(nextLink);
  let currNextPageButton = nextPage.querySelectorAll('a[class="button mobile-button right"][href]');
  lastNextPageButton = currNextPageButton[currNextPageButton.length - 1];
  const figures = nextPage.querySelectorAll('figure[class*="t"]');
  return figures;
}

async function incrementUrlLastNumber(url) {
  if (url.endsWith('/?'))
    url = url.slice(0, -1);
  if (url.endsWith('/'))
    url = url.slice(0, -1);

  var segments = url.split('/');
  var lastSegment = segments[segments.length - 1];

  var match = lastSegment.match(/^\d+/);

  if (match) {
    var nextNumber = parseInt(match[0]) + 1;
    return url.replace(/\d+$/, nextNumber);
  } else
    return url + '/2';
}


function isElementOnScreen(element) {
  var rect = element.getBoundingClientRect();
  var windowHeight = (window.innerHeight || document.documentElement.clientHeight) * 2;
  return (rect.top <= windowHeight) && ((rect.top + rect.height) >= 0);
}

async function getHTML(url) {
  try {
    const response = await fetch(url);
    const html = await response.text();
    const parser = new DOMParser();
    const doc = parser.parseFromString(html, 'text/html');
    return doc;
  } catch (error) {
    console.error(error);
  }
}

async function addExSettings() {
  const settings = document.querySelector('ul[class="navhideonmobile"]').querySelector('a[href="/controls/settings/"]').parentNode;

  if (document.getElementById("extension_settings")) {
    document.getElementById('midori_settings').addEventListener('click', function() { localStorage.setItem("igsettings", true.toString()); });
    return;
  }
  let exSettingsHeader = document.createElement("h3");
  exSettingsHeader.id = "extension_settings";
  exSettingsHeader.textContent = "Extension Settings";
  settings.appendChild(exSettingsHeader);

  let wfsettings = document.createElement("a");
  wfsettings.id = "midori_settings";
  wfsettings.textContent = "Midori's Script Settings";
  wfsettings.style.cursor = "pointer";
  wfsettings.onclick = function() {
    localStorage.setItem("igsettings", true.toString());
    window.location = "https://www.furaffinity.net/controls/settings";
  }
  settings.appendChild(wfsettings);
}

async function addExSettingsSidebar() {
  const settings = document.getElementById('controlpanelnav');

  if (document.getElementById("extension_settings_side")) {
    document.getElementById('midori_settings_side').addEventListener('click', function() { localStorage.setItem("igsettings", true.toString()); });
    return;
  }
  let exSettingsHeader = document.createElement("h3");
  exSettingsHeader.id = "extension_settings_side";
  exSettingsHeader.textContent = "Extension Settings";
  settings.appendChild(exSettingsHeader);

  let wfsettings = document.createElement("a");
  wfsettings.id = "midori_settings_side";
  wfsettings.textContent = "Midori's Script Settings";
  wfsettings.style.cursor = "pointer";
  wfsettings.onclick = function() {
    localStorage.setItem("igsettings", true.toString());
    window.location = "https://www.furaffinity.net/controls/settings";
  }
  settings.appendChild(wfsettings);
}

async function createSettings() {
  localStorage.setItem("igsettings", false.toString());
  const columnPage = document.getElementById("columnpage");
  let content = columnPage.querySelector('div[class="content"]');
  for (const section of content.querySelectorAll('section:not([class="exsettings"])'))
    section.parentNode.removeChild(section);

  let section = document.createElement("section");
  section.className = 'exsettings';
    let headerContainer = document.createElement("div");
    headerContainer.className = "section-header";
      let header = document.createElement("h2");
      header.textContent = "Infini Gallery Settings";
      headerContainer.appendChild(header);
    section.appendChild(headerContainer);
    let bodyContainer = document.createElement("div");
    bodyContainer.className = "section-body";
      let Item1 = document.createElement("div");
      Item1.className = "control-panel-item-container";
        let Item1Name = document.createElement("div");
        Item1Name.className = "control-panel-item-name";
          let Item1NameText = document.createElement("h4");
          Item1NameText.textContent = "Page Seperator";
          Item1Name.appendChild(Item1NameText);
        Item1.appendChild(Item1Name);
        let Item1Desc = document.createElement("div");
        Item1Desc.className = "control-panel-item-description";
          let Item1DescText = document.createTextNode('Sets wether a Page Seperator is shown foreach new Page loaded.');
          Item1Desc.appendChild(Item1DescText);
        Item1.appendChild(Item1Desc);
        let Item1Option = document.createElement("div");
        Item1Option.className = "control-panel-item-options";
          let Item1OptionContainer = document.createElement("div");
            let Item1OptionElem1 = document.createElement("input");
            Item1OptionElem1.id = 'igsettings_01';
            Item1OptionElem1.type = "checkbox";
            Item1OptionElem1.style.cursor = 'pointer';
            Item1OptionElem1.style.marginRight = '4px';
            Item1OptionElem1.addEventListener('change', function() {
              showPageSeperator = Item1OptionElem1.checked;
              localStorage.setItem("igsetting_01", showPageSeperator.toString());
            });
            Item1OptionContainer.appendChild(Item1OptionElem1);
            let Item1OptionElem2 = document.createTextNode('Show Page Seperators');
            Item1OptionContainer.appendChild(Item1OptionElem2);
          Item1Option.appendChild(Item1OptionContainer);
        Item1.appendChild(Item1Option);
      bodyContainer.appendChild(Item1);
        let Item2 = document.createElement("div");
        Item2.className = "control-panel-item-container";
        let Item2Name = document.createElement("div");
        Item2Name.className = "control-panel-item-name";
          let Item2NameText = document.createElement("h4");
          Item2NameText.textContent = "Disable Button";
          Item2Name.appendChild(Item2NameText);
        Item2.appendChild(Item2Name);
        let Item2Desc = document.createElement("div");
        Item2Desc.className = "control-panel-item-description";
          let Item2DescText = document.createTextNode("Sets wether the disable Infini Gallery button is shown in each Gallery");
          Item2Desc.appendChild(Item2DescText);
        Item2.appendChild(Item2Desc);
        let Item2Option = document.createElement("div");
        Item2Option.className = "control-panel-item-options";
          let Item2OptionContainer = document.createElement("div");
            let Item2OptionElem1 = document.createElement("input");
            Item2OptionElem1.id = 'igsettings_02';
            Item2OptionElem1.type = "checkbox";
            Item2OptionElem1.style.cursor = 'pointer';
            Item2OptionElem1.style.marginRight = '4px';
            Item2OptionElem1.addEventListener('change', function() {
              showDisableButton = Item2OptionElem1.checked;
              localStorage.setItem("igsetting_02", showDisableButton.toString());
            });
            Item2OptionContainer.appendChild(Item2OptionElem1);
            let Item2OptionElem2 = document.createTextNode('Show disable Infini Gallery button');
            Item2OptionContainer.appendChild(Item2OptionElem2);
          Item2Option.appendChild(Item2OptionContainer);
        Item2.appendChild(Item2Option);
      bodyContainer.appendChild(Item2);
    section.appendChild(bodyContainer);
  content.appendChild(section);

  fillSettings();
}

async function fillSettings() {
  let setting1 = document.getElementById('igsettings_01');
  setting1.checked = showPageSeperator;

  let setting2 = document.getElementById('igsettings_02');
  setting2.checked = showDisableButton;
}

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址