您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
library to load the jQuery, jQueryUI and TouchPunch JS from CDN only if it hasn't already, and create the menu
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.org/scripts/542049/1623295/AO3%3A%20Initialize%20jQueryUI.js
// ==UserScript== // @name AO3: Initialize jQueryUI // @namespace https://greasyfork.org/en/users/906106-escctrl // @description library to load the jQuery, jQueryUI and TouchPunch JS from CDN only if it hasn't already, and create the menu // @author escctrl // @version 1.0 // @grant none // @license MIT // ==/UserScript== // HOW TO USE: // please refer to https://greasyfork.org/en/scripts/542049 for a full description how to use this library /* global jQuery, $ */ 'use strict'; // utility to reduce verboseness const q = (selector, node=document) => node.querySelector(selector); const qa = (selector, node=document) => node.querySelectorAll(selector); function createMenu(id, heading) { // if no other script has created it yet, write out a "Userscripts" option to the main navigation if (qa('#scriptconfig').length === 0) { qa('#header nav[aria-label="Site"] li.search')[0] // insert as last li before search .insertAdjacentHTML('beforebegin', `<li class="dropdown" id="scriptconfig"> <a class="dropdown-toggle" href="/" data-toggle="dropdown" data-target="#">Userscripts</a> <ul class="menu dropdown-menu"></ul></li>`); } // then add this script's config option to navigation dropdown q('#scriptconfig .dropdown-menu').insertAdjacentHTML('beforeend', `<li><a href="javascript:void(0);" id="opencfg_${id}">${heading}</a></li>`); } function loadjQuery(URI) { return new Promise((resolve, reject) => { // based on https://stackoverflow.com/a/44807594 new Promise((resolve, reject) => { const script = document.createElement('script'); document.head.appendChild(script); script.onload = resolve; script.onerror = reject; script.async = true; script.src = URI; }) .then(() => resolve("success")) .catch((err) => reject(err)); }); } async function initGUI(e, id, heading, maxWidth) { if (!q("head script[src*='/3.7.0/jquery.min.js']")) { let loadSuccess = await loadjQuery('https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js'); if (loadSuccess !== "success") { console.debug("library has failed to load jQuery", loadSuccess); return false; } } if (!q("head script[src*='/1.13.2/jquery-ui.min.js']")) { loadSuccess = await loadjQuery('https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js'); if (loadSuccess !== "success") { console.debug("library has failed to load jQueryUI", loadSuccess); return false; } loadSuccess = await loadjQuery('https://cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.3/jquery.ui.touch-punch.min.js'); if (loadSuccess !== "success") { console.debug("library has failed to load TouchPunch", loadSuccess); return false; } } // automatic darkmode if the background is dark (e.g. Reversi) let theme = lightOrDark(getComputedStyle(q("body")).getPropertyValue("background-color")); theme = theme == "dark" ? "dark-hive" : "base"; id = "#"+id; // setting up the GUI CSS (only if no other script has created it yet) if (!q("head link[href*='jquery-ui.css']")) { q("head").insertAdjacentHTML('beforeend',`<link rel="stylesheet" href="https://code.jquery.com/ui/1.13.2/themes/${theme}/jquery-ui.css" type="text/css">`); } q("head").insertAdjacentHTML('beforeend',`<style type="text/css">/* jQueryUI stuff that's messed up by AO3 default skins */ .ui-widget, ${id}, .ui-dialog .ui-dialog-buttonpane button {font-size: revert !important; line-height: 1.286;} ${id} { form, fieldset {border: revert; box-shadow: revert; background: revert; cursor:auto;} ol { margin-left: 2em; li { list-style: decimal; } } fieldset p { padding-left: 0; padding-right: 0; } legend {font-size: inherit; height: auto; width: auto; opacity: inherit;} label { margin: 0; } select { vertical-align: baseline; } .ui-sortable li { background-color: revert; border: revert; margin: 0; float: none; clear: none; box-shadow: revert; width: auto; display: inline-block; } /* Toggle Switches (CSS) */ --switch-height: 1.5em; --slider-size: calc(var(--switch-height) - 0.2em); --slider-color: currentColor; /* The switch - the box around the slider */ .switch { position: relative; bottom: 0.1em; display: inline-block; width: 3em; height: var(--switch-height); padding: 0; border-radius: 1em; } /* Hide default HTML checkbox */ .switch input { opacity: 0; width: 0; height: 0; } /* The slider */ .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; -webkit-transition: .4s; transition: .4s; } .slider:before { position: absolute; content: ""; height: var(--slider-size); width: var(--slider-size); left: 0.2em; bottom: 0.1em; background-color: var(--slider-color); -webkit-transition: .4s; transition: .4s; } input:checked + .slider { } input:focus + .slider { } input:checked + .slider:before { -webkit-transform: translateX(var(--slider-size)); -ms-transform: translateX(var(--slider-size)); transform: translateX(var(--slider-size)); } /* Rounded sliders */ .slider.round { border-radius: 1em; } .slider.round:before { border-radius: 50%; } }</style>`); // wrapper div for the dialog $("body").append(`<div id="${id.slice(1)}"></div>`); let dialogwidth = parseInt($("body").css("width")); dialogwidth = dialogwidth > maxWidth ? maxWidth : dialogwidth * 0.9; $(id).dialog({ appendTo: "#main", modal: true, title: heading, draggable: false, resizable: false, autoOpen: false, width: dialogwidth, position: {my:"center", at: "center top", of: window}, }); // event listener for reopening the dialog on subsequent menu clicks (without recreating the whole GUI) e.target.addEventListener("click", function(e) { $( id ).dialog('open'); }); // if the window resizes the dialog would move off of the screen window.addEventListener('resize', function(e) { let dialogwidth = parseInt($("body").css("width")); // get the new browser width dialogwidth = dialogwidth > maxWidth ? maxWidth : dialogwidth * 0.9; $(id).dialog("option", "width", dialogwidth) // resize the dialog .dialog("option", "position", {my:"center top", at: "center top", of: window} ); // reposition the dialog }); return $(id); } // helper function to determine whether a color (the background in use) is light or dark // https://awik.io/determine-color-bright-dark-using-javascript/ function lightOrDark(color) { var r, g, b, hsp; if (color.match(/^rgb/)) { color = color.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/); r = color[1]; g = color[2]; b = color[3]; } else { color = +("0x" + color.slice(1).replace(color.length < 5 && /./g, '$&$&')); r = color >> 16; g = color >> 8 & 255; b = color & 255; } hsp = Math.sqrt( 0.299 * (r * r) + 0.587 * (g * g) + 0.114 * (b * b) ); if (hsp>127.5) { return 'light'; } else { return 'dark'; } }