您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
library to load the webix JS from CDN only if it hasn't already, and create the menu
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/541008/1615676/AO3%3A%20Initialize%20webix%20GUI.js
// ==UserScript== // @name AO3: Initialize webix GUI // @namespace https://greasyfork.org/en/users/906106-escctrl // @description library to load the webix 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/541008-ao3-initialize-webix-gui for a full description how to use this library /* global webix, $$ */ '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 loadWebix() { return new Promise((resolve, reject) => { if (typeof webix !== "undefined") resolve("success"); else { // 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 = 'https://cdn.jsdelivr.net/npm/[email protected]/webix.min.js'; }) .then(() => resolve("success")) .catch((err) => reject(err)); } }); } async function initGUI(e, id, heading, maxWidth, views=null) { let loadSuccess = await loadWebix(); if (loadSuccess === "success") { // setting up the GUI CSS (only if no other script has created it yet) if (!q("head link[href*='webix.min.css']")) { q("head").insertAdjacentHTML('beforeend',`<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/webix.min.css" type="text/css">`); q("head").insertAdjacentHTML('beforeend',`<style type="text/css">/* webix stuff that's messed up by AO3 default skins */ .webix_view { label { margin-right: unset; } button { box-shadow: unset; } }</style>`); } // automatic darkmode if the background is dark (e.g. Reversi) let theme = lightOrDark(getComputedStyle(q("body")).getPropertyValue("background-color")); if (theme === "dark") { if (views === null) views = [id]; views = views.map((x) => `.webix_view[view_id="${x}"]`).join(', '); q("head").insertAdjacentHTML('beforeend',`<style type="text/css">/* switching webix colors to a dark mode if AO3 is dark */ ${views} { --text-on-dark: #ddd; --handles-on-dark: #bbb; --highlight-on-dark: #0c6a82; --background-dark: #222; --border-on-dark: #555; --no-border: transparent; --button-dark: #333; background-color: var(--background-dark); color: var(--text-on-dark); border-color: var(--border-on-dark); &.webix_popup { border: 1px solid var(--border-on-dark); } .webix_win_head { border-bottom-color: var(--border-on-dark); } .webix_icon_button:hover::before { background-color: var(--highlight-on-dark); } .webix_view.webix_form, .webix_view.webix_header, .webix_win_body>.webix_view { background-color: var(--background-dark); } .webix_secondary .webix_button, .webix_slider_box .webix_slider_right, .webix_el_colorpicker .webix_inp_static, .webix_color_out_text, .webix_switch_box { background-color: var(--button-dark); } .webix_primary .webix_button, .webix_slider_box .webix_slider_left, .webix_switch_box.webix_switch_on { background-color: var(--highlight-on-dark); } .webix_switch_handle, .webix_slider_box .webix_slider_handle { background-color: var(--handles-on-dark); } .webix_el_colorpicker .webix_inp_static, .webix_color_out_block, .webix_color_out_text, .webix_switch_handle, .webix_slider_box .webix_slider_handle { border-color: var(--border-on-dark); } .webix_switch_box, .webix_slider_box .webix_slider_left, .webix_slider_box .webix_slider_right { border-color: var(--no-border); } * { color: var(--text-on-dark); } }</style>`); } let dialogwidth = parseInt(getComputedStyle(q("body")).getPropertyValue("width")); webix.ui({ view: "window", id: id, width: dialogwidth > maxWidth ? maxWidth : dialogwidth * 0.9, position: "top", head: heading, close: true, move: true, body: { type:"wide", id:"container", rows:[ ] } }); // event listener for reopening the dialog on subsequent menu clicks (without recreating the whole GUI) e.target.addEventListener("click", function(e) { $$(id).show(); }); // if the window resizes the dialog would move off of the screen window.addEventListener('resize', function(e) { let dialogwidth = parseInt(getComputedStyle(q("body")).getPropertyValue("width")); // get the new browser width $$(id).config.width = dialogwidth > maxWidth ? maxWidth : dialogwidth * 0.9; // reoptimize dialog width $$(id).resize(); // repaint the GUI and its components }); return $$(id).queryView((view) => view.config.id === "container"); } else { console.debug("library has failed to load webix", loadSuccess); return false; } } // 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'; } }