您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds an "Index" button on post pages, allowing you to return to a search starting from the ID of the current post you're on, and provides swiping next/previous on mobile
// ==UserScript== // @name Gelbooru "Index" Button & Page Swiping // @namespace https://gelbooru.com/ // @version 2.0 // @description Adds an "Index" button on post pages, allowing you to return to a search starting from the ID of the current post you're on, and provides swiping next/previous on mobile // @match https://gelbooru.com/index.php?page=post&s=view* // @icon https://gelbooru.com/favicon.ico // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; // Ensure we're on gelbooru if (location.hostname !== 'gelbooru.com') return; (function addIndexButton() { const url = new URL(window.location.href); const urlParams = url.searchParams; const currentId = urlParams.get('id'); if (!currentId) return; urlParams.delete('id'); urlParams.set('s', 'list'); const rawTags = urlParams.get('tags') || ''; let decodedTags = decodeURIComponent(rawTags); const newIdSearch = 'id:=<' + currentId; const idSearchRegex = /id:=<\d+/i; if (idSearchRegex.test(decodedTags)) { decodedTags = decodedTags.replace(idSearchRegex, newIdSearch); } else { decodedTags = decodedTags.trim(); if (decodedTags) decodedTags += ' '; decodedTags += newIdSearch; } urlParams.set('tags', decodedTags.trim()); const finalUrl = `${url.origin}${url.pathname}?${urlParams.toString()}`; const box = document.createElement('div'); box.className = 'alert alert-info'; box.style.textAlign = 'center'; box.style.margin = '10px 0px'; box.style.padding = '10px'; const indexLink = document.createElement('a'); indexLink.textContent = 'Index'; indexLink.href = finalUrl; box.appendChild(indexLink); const navContainers = document.querySelectorAll('.alert.alert-info'); if (navContainers.length > 0) { navContainers[navContainers.length - 1].insertAdjacentElement('afterend', box); } else { const mainBody = document.querySelector('.mainBodyPadding'); if (mainBody) mainBody.appendChild(box); } })(); (function addSwipeNavigation() { if (typeof navigatePrev !== 'function' || typeof navigateNext !== 'function') { return; } let startX = 0; const threshold = 50; //works on my machine, can't be bothered to see how this feels on different resolutions document.addEventListener('touchstart', (e) => { if (e.changedTouches.length > 0) { startX = e.changedTouches[0].screenX; } }); document.addEventListener('touchend', (e) => { if (e.changedTouches.length > 0) { const endX = e.changedTouches[0].screenX; const diffX = endX - startX; if (diffX > threshold) { showArrowOverlay('left', navigatePrev); } else if (diffX < -threshold) { showArrowOverlay('right', navigateNext); } } }); function showArrowOverlay(direction, callback) { const overlay = document.createElement('div'); overlay.style.position = 'fixed'; overlay.style.top = '0'; overlay.style.left = '0'; overlay.style.width = '100%'; overlay.style.height = '100%'; overlay.style.display = 'flex'; overlay.style.alignItems = 'center'; overlay.style.justifyContent = 'center'; overlay.style.zIndex = '999999'; overlay.style.backgroundColor = 'rgba(0, 0, 0, 0)'; const arrowWrapper = document.createElement('div'); arrowWrapper.style.animation = 'arrowAnimation 0.3s forwards ease-out'; arrowWrapper.style.display = 'flex'; arrowWrapper.style.alignItems = 'center'; arrowWrapper.style.justifyContent = 'center'; const arrowSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); arrowSvg.setAttribute('viewBox', '0 0 100 100'); arrowSvg.setAttribute('width', '120'); arrowSvg.setAttribute('height', '120'); const bgCircle = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); bgCircle.setAttribute('cx', '50'); bgCircle.setAttribute('cy', '50'); bgCircle.setAttribute('r', '45'); bgCircle.setAttribute('fill', 'rgba(0,0,0,0.3)'); arrowSvg.appendChild(bgCircle); const arrowPath = document.createElementNS('http://www.w3.org/2000/svg', 'path'); arrowPath.setAttribute('fill', 'none'); arrowPath.setAttribute('stroke', 'white'); arrowPath.setAttribute('stroke-width', '10'); if (direction === 'left') { arrowPath.setAttribute('d', 'M70 20 L30 50 L70 80'); } else { // right arrowPath.setAttribute('d', 'M30 20 L70 50 L30 80'); } arrowSvg.appendChild(arrowPath); arrowWrapper.appendChild(arrowSvg); overlay.appendChild(arrowWrapper); document.body.appendChild(overlay); setTimeout(() => { document.body.removeChild(overlay); callback(); }, 100); } const styleEl = document.createElement('style'); styleEl.textContent = ` @keyframes arrowAnimation { 0% { transform: scale(0.8); opacity: 0; } 50% { transform: scale(1); opacity: 1; } 100% { transform: scale(1.2); opacity: 0; } }`; document.head.appendChild(styleEl); })(); })();