您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Vanilla JS library
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/369430/756036/vanilla-lib.js
// ==UserScript== // @name vanilla-lib // @namespace http://dev.rsalazar.name/js/ // @version 1.2.191207.1426 // @description Vanilla JS library // @author rsalazar // @grant none // ==/UserScript== function VanillaLib( ) { 'use strict'; let self = { version:'1.2.191207.1426' }, undefined; // ensure an 'undefined' reference // Logging related self.logging = true; self.log = function( ) { return ! self.logging ? false : console.debug.apply(console, arguments); }; self.logGroup = function( ) { return ! self.logging ? false : console.groupCollapsed.apply(console, arguments); }; self.logEnd = function( ) { return ! self.logging ? false : console.groupEnd.apply(console, arguments); }; self.time = function( ) { return ! self.logging ? false : console.time.apply(console, arguments); }; self.timeEnd = function( ) { return ! self.logging ? false : console.timeEnd.apply(console, arguments); }; self.warn = function( ) { return ! self.logging ? false : console.warn.apply(console, arguments); }; // Informative functionality self.isobj = ( expr,type ) => ( 'object' === typeof expr && ( ! type || null !== expr && ( true === type || !! expr.constructor && type === ( self.isstr(type) ? expr.constructor.name : expr.constructor ) ) ) ); self.ownsIt = ( obj,prop ) => ( !! prop && self.isobj(obj, true) && obj.hasOwnProperty(prop) ); self.hasval = expr => ( null !== expr && ! self.ndef(expr) ); self.isbool = expr => ( 'boolean' === typeof expr ); self.ifnan = ( expr,value ) => ( isNaN(expr) ? value : expr ); self.ifndef = ( expr,value ) => ( self.ndef(expr) ? value : expr ); self.ispojo = expr => self.isobj(expr, Object); self.isarr = expr => self.isobj(expr, Array); self.isnum = expr => ( 'number' === typeof expr ); self.isstr = expr => ( 'string' === typeof expr ); self.isfn = expr => ( 'function' === typeof expr ); self.defn = expr => ( 'undefined' !== typeof expr ); self.ndef = expr => ( 'undefined' === typeof expr ); // Miscelaneous self.mapFlat = ( array,func ) => array.map( x => func(x) ).reduce( (a,b) => a.concat(b) ); self.test = ( expr,func,other ) => ( !! expr ? func(expr) : self.isfn(other) ? other(expr) : other ); // DOM related self.parenth = ( elem,nth ) => self.traverse(elem, self.ifndef(nth, 1), 0); self.html = ( elem,val ) => self.test(elem, el => self.ndef(val) ? el.innerHTML : (el.innerHTML = val) ); self.text = ( elem,val ) => self.test(elem, el => self.ndef(val) ? el.innerText : (el.innerText = val) ); self.$$ = ( sel,elem ) => self.toArray((elem || document).querySelectorAll(sel)); self.$ = ( sel,elem ) => (elem || document).querySelector(sel); // Number related self.aggRate = ( amnt,rate,times ) => ( times < 1 ? amnt : self.aggRate(amnt * rate, rate, times - 1) ); self.between = ( value,from,to,open ) => ( from > to ? self.between(value, to, from, open) : open ? from < value && value < to : from <= value && value <= to ); self.toDec = expr => ( Math.round(parseFloat((expr +'').replace(/\$|,/g, '')) * 100) / 100 ); // Date/Time related self.secondsIn = ( from,to,other ) => self.ifnan((to - from) / 1000, self.ifndef(other, NaN)); self.minutesIn = ( from,to,other ) => self.ifnan((to - from) / 60000, self.ifndef(other, NaN)); self.hoursIn = ( from,to,other ) => self.ifnan((to - from) / 3600000, self.ifndef(other, NaN)); self.daysIn = ( from,to,other ) => self.ifnan((to - from) / 86400000, self.ifndef(other, NaN)); self.secondsSince = ( from,other ) => self.secondsIn(from, Date.now(), other); self.minutesSince = ( from,other ) => self.minutesIn(from, Date.now(), other); self.hoursSince = ( from,other ) => self.hoursIn(from, Date.now(), other); self.daysSince = ( from,other ) => self.daysIn(from, Date.now(), other); self.addClass = function( element, name ) { if ( !! element && !! name ) { if ( self.isarr(element) ) { return element.map( elem => self.addClass(elem, name) ); } // ToDo: Use .classList if available name = ( self.isarr(name) ? name : name.split(',') ); name = name.map( nm => nm.trim() ) .filter( nm => ! element.classList.contains(nm) ); element.className = (element.className +' '+ name.join(' ')).trim(); return true; } return false; }; self.appendTo = function( element, parent, reference ) { if ( self.isarr(element) ) { return element.map( elem => self.appendTo(elem, parent, reference) ); } if ( !! reference ) { parent = reference.parentNode; reference = reference.nextSibling; } if ( !! reference ) { return self.prependTo(element, parent, reference); } else if ( !! parent ) { parent.append(element); } else { self.warn('*** appendTo() could not add element: No parent or reference element provided'); } return element; }; self.attr = function( element, name, value ) { if ( !! element ) { if ( self.isarr(element) ) { return element.map( elem => self.attr(elem, name, value) ); } return self.keysAndValues(name, value, ( n,v ) => { return ( self.hasval(v) ? element.setAttribute(n, v) : null === v ? element.removeAttribute(n) : element.getAttribute(n) ); } ); } return element; }; self.choose = function( index, values ) { return self.toArray(arguments)[ index ]; } self.create = function( html, containerType ) { let container = null, result = null, attrs, style; if ( self.isobj(containerType) ) { attrs = containerType.attrs; style = containerType.style; containerType = containerType.container; } containerType = containerType || 'div'; create[ containerType ] = container = self.create[ containerType ] || document.createElement(containerType); container.innerHTML = html; result = self.toArray(container.childNodes) .map( elem => (elem.remove(), elem) ); if ( !! attrs ) { self.attr(result, attrs); } if ( !! style ) { self.css(result, style); } if ( 1 == result.length ) { result = result[ 0 ]; } return result; }; // Create sandbox, optionally adding it to `cache` as (read-only) `property` (or `_sandbox`, if missing) self.createSandbox = function( cache, property ) { const frame = document.createElement('iframe'); frame.src = 'about:blank', frame.style.display = 'none'; document.body.appendChild(frame); const context = frame.contentWindow; !! cache && Object.defineProperty(cache, (property || '_sandbox'), { value:context, enumerable:false, writable:false, configurable:false }); document.body.removeChild(frame); return context; }; self.createXHR = function( ) { let xhr = new XMLHttpRequest( ); xhr.onabort = function( ev, xhr ) { self.log('XHR Abort:', ev, xhr, this); }; xhr.onerror = function( ev, xhr ) { self.log('XHR Error:', ev, xhr, this); }; xhr.onload = function( ev, xhr ) { self.log('XHR Load:', ev, xhr, this); }; self.on(xhr, { 'abort': function( ev ) { self.isfn(this.onabort) && this.onabort(ev, this); }, 'error': function( ev ) { self.isfn(this.onerror) && this.onerror(ev, this); }, 'load': function( ev ) { self.isfn(this.onload) && this.onload(ev, this); }, }); return xhr; }; self.css = function( element, key, value ) { if ( isarr(element) ) { return element.map( elem => self.css(elem, key, value) ); } keysAndValues(key, value, ( k,v ) => element.style[ k ] = v ); return element; }; self.extend = function( target, sources ) { for ( let i = 1, n = arguments.length; i < n; i ++ ) { self.isobj(arguments[ i ], true) && self.copyMembers(arguments[ i ], target); } return target; }; self.extendProperties = function( target, source, overwrite, writable, enumerable, configurable ) { if ( !! target && !! source ) { overwrite = !! overwrite; writable = !! writable; enumerable = !! enumerable; configurable = !! configurable; if ( self.isarr(source) ) { for ( let i = 0, n = source.length; i < n; i ++ ) { self.extendProperties(target, source[ i ], overwrite, writable, enumerable, configurable); } } else if ( self.isobj(source, true) ) { for ( let prop in source ) { if ( overwrite || self.ndef(target[ prop ]) ) { Object.defineProperty(target, prop, self.propDef(source[ prop ], writable, enumerable, configurable)); } } } } return target; }; self.fire = function( element, event, args ) { if ( isarr(element) ) { return element.map( elem => self.fire(elem, event, args) ); } if ( self.isstr(event) ) { args = self.ifndef(args, { 'bubbles':true, 'cancelable':true }); event = new Event( event, args ); } return element.dispatchEvent(event); }; self.keysAndValues = function( key, value, action ) { if ( self.ndef(action) && self.isfn(value) ) { action = value; value = undefined; } // Case 1: key is an object (and there is no value) if ( self.isobj(key) && ! value ) { return Object.keys(key) .map( k => action(k, key[ k ]) ); // Case 2: key is an array } else if ( self.isarr(key) ) { // Case 1.a: value is an array of the same length if ( self.isarr(value) && key.length === value.length ) { return key.map( ( k,i ) => action(k, value[ i ]) ); // Case 1.b: value is considered a simple, plain value } else { return key.map( k => action(k, value) ); } // Default Case: key and value considered as simple, plain values } else { return action(key, value); } }; self.lazy = function( func, storage ) { // If the argument is a function (expected), set it as lazy getter if ( self.isfn(func) ) { let name = 'initializer::'+ Math.random(), me = self.lazy; storage = storage || me.storage || (me.storage = { }); return ( ) => ( self.defn(storage[ name ]) ? storage[ name ] : (storage[ name ] = func()) ); // If the argument was "something" else (not undefined), set it as the result } else if ( self.defn(func) ) { return ( ) => func; } // Otherwise: No idea throw 'lazy(): The first argument (lazy getter / value) must be provided'; //return null; }; self.localJson = function( key, value ) { if ( !! key && self.isstr(key) ) { try { if ( self.ndef(value) ) { return JSON.parse(localStorage.getItem(key)); } else if ( null === value ) { return localStorage.removeItem(key); } else { return localStorage.setItem(key, JSON.stringify(value)); } } catch ( error ) { self.warn('* localJson() error:', error, '\n\tfor:', key, value); } } return null; }; self.off = function( element, event, callback ) { if ( self.ndef(callback) && self.isobj(event) ) { return self.keysAndValues(event, ( k,v ) => self.off(element, k, v) ); } else if ( self.isarr(element) ) { return element.map( elem => self.off(elem, event, callback) ); } return element.removeEventListener(event, callback); }; self.on = function( element, event, callback ) { if ( self.ndef(callback) && self.isobj(event) ) { return self.keysAndValues(event, ( k,v ) => self.on(element, k, v) ); } else if ( self.isarr(element) ) { return element.map( elem => self.on(elem, event, callback) ); } return element.addEventListener(event, callback); }; self.onmutate = function( element, callback, config ) { if ( !! element && self.isfn(callback) ) { config = config || { 'attributes':false, 'childList':true, 'subtree':false }; if ( self.isarr(element) ) { return element.map( elem => self.onmutate(elem, callback, config) ); } let observer = new MutationObserver( callback ); observer.initialConfig = ( ) => config; observer.reconnect = function( newConfig ) { this.observe(element, newConfig || this.initialConfig()); return this; }; return observer.reconnect(); } return null; }; self.pojo2query = function( pojo ) { if ( self.isobj(pojo) && !! pojo ) { let query = Object.keys(pojo) .map( key => escape(key) +'='+ escape(pojo[ key ]) ) .join('&'); return '?'+ query; } return null; }; self.prependTo = function( element, parent, reference ) { if ( ! reference && !! parent ) { reference = parent.childNodes[ 0 ]; } if ( isarr(element) ) { return element.map( elem => self.prependTo(elem, parent, reference) ); } if ( !! reference ) { reference.parentNode.insertBefore(element, reference); } else if ( !! parent ) { parent.append(element); } else { self.warn('*** prependTo() could not add element: No parent or reference element provided'); } return element; }; self.propDef = function( value, writable, enumerable, configurable ) { enumerable = !! enumerable; var def = { 'enumerable': enumerable, 'configurable': !! configurable, }; if ( self.isfn(value) && ( enumerable || self.isfn(writable) ) ) { def.get = value; if ( self.isfn(writable) ) { def.set = writable; } } else { def.value = value; def.writable = !! writable; } return def; } self.query2pojo = function( query ) { query = (self.ifndef(query, location.search) +'') .replace(/^[?&]+|$&+/g, ''); if ( !! query ) { let segs, key, val, pojo = { }; query.split('&') .forEach( item => { [ key, val ] = segs = item.split('='); val = ( self.ndef(val) ? null : segs.slice(1).join('=') ); pojo[ unescape(key) ] = unescape(val); } ); return pojo; } return null; }; self.range = function( from, to, inc ) { inc = ( ! inc || isNaN(inc) ? 1 : inc ); if ( from == to - inc ) { return [ from, to ]; } else if ( from == to ) { return [ to ]; } else if ( (to - from) % inc || ! self.between(from + inc, from, to) ) { throw 'Cannot create range '+ from +'..'+ to +' with increments of '+ inc; //return null ;//[ ]; } return self.range(from, to - inc, inc).concat(to); }; self.request = function( url, verb, data, callback ) { self.log('* request of:', verb, url, data, callback); // "Validate" HTTP Verb, to an extent verb = (verb || 'GET').toUpperCase(); switch ( verb ) { case 'P': verb = 'POST'; break; case 'G': verb = 'GET'; break; case 'H': verb = 'HEAD'; break; } // Switch callback and data when ther is no data if ( self.ndef(callback) && self.isfn(data) ) { callback = data; data = null; } // Set the data to a string or null data = self.ifndef(data, null); data = ( !! data && self.isobj(data) ? self.pojo2query(data).replace('?', '') : data.toString() ); self.log('- request data:', data); // Add data to the URL for GET requests if ( 'GET' === verb && !! data ) { url += ( url.includes('?') ? '&' : '?' ) + data; data = null; } // Create & open XHR object... let xhr = self.createXHR(); self.log('-> opening request:', verb, url); xhr.open(verb, url); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); // Set the internal event handler, which removes itself on execution xhr.onabort = xhr.onerror = xhr.onload = callback; // Send the actual request self.log('-> sending request:', data, xhr.readyState, xhr); return xhr.send(data); }; // Sandboxed `Function([exportedValues,] arg1, ..., argN, funcBody)` self.sandbox = function( exports, funcArgsAndCode ) { const C = self.sandbox._sandbox || self.createSandbox(self.sandbox), F = C.Function.bind(C); const args = self.toArray(arguments); if ( 'string' !== typeof exports ) { args.shift(); } // Do we need to pass-in any "exports" values (as arguments?) if ( !! exports && self.ispojo(exports) ) { let inrArgs = Object.keys(exports); if ( inrArgs.length > 0 ) { inrArgs = inrArgs.concat(args); const vals = Object.values(exports), fn = F.apply(null, inrArgs); (arguments[ arguments.length - 1 ] || '').includes('arguments') && console.warn('sandbox() - sandboxed code with `exports` should not rely on `arguments`'); return function _sandboxed_withExports( ){ return fn.apply(null, vals.concat(toArray(arguments))); }; } } return F.apply(null, args); }; self.table2json = function( table, headers, filter ) { if ( !! table && !! table.rows ) { let obj = { head:[ ], data:[ ] }; obj.head = ( self.isfn(headers) ? headers(table) : table.rows[ 0 ] ); if ( self.isobj(obj.head) && !! obj.head.cells ) { obj.head = Array.map(obj.head.cells, th => th.innerText.trim() ); } if ( obj.head.length ) { filter = filter || (( row,i ) => ( i && 'TBODY' === row.parentNode.nodeName )); for ( let r = 0, nr = table.rows.length; r < nr; r ++ ) { let row = table.rows[ r ]; if ( filter(row, r) ) { let item = { }; obj.head.forEach( ( col,i ) => { col[ 0 ] && (item[ col ] = row.cells[ i ].innerText.trim()); } ); obj.data.push(item); } } } return obj.data; } return null; }; self.toArray = function( expr ) { if ( self.hasval(expr) && ! self.isarr(expr) ) { return ( self.ndef(expr.length) ? [ expr ] : Array.prototype.slice.call(expr) ); } return expr || [ ]; }; self.toDec2 = function( amount ) { amount = self.toDec(amount); if ( isNaN(amount) ) { return null; } let segs = (amount +'').split('.'); return segs[ 0 ] +'.'+ ((segs[ 1 ] || 0) +'0').slice(0, 2); }; self.toMoney = function( amount ) { let dec2 = self.toDec2(amount); return ( isNaN(dec2) ? null : dec2 < 0 ? '-$ '+ (-dec2) : '$ '+ dec2 ); }; self.traverse = function( elem, up, sideways, elementsOnly, lastIfNull ) { let last = elem; while ( !! elem && up -- > 0 ) elem = (last = elem, elem.parentNode); let prop = ( elementsOnly ? 'Element' : '' ) +'Sibling'; if ( sideways < 0 ) { while ( !! elem && sideways ++ < 0 ) elem = (last = elem, elem[ 'previous'+ prop ]); } else if ( sideways > 0 ) { while ( !! elem && sideways -- > 0 ) elem = (last = elem, elem[ 'next'+ prop ]); } return ( ! lastIfNull ? elem : elem || last ); }; self.wrapWith = function( content, wrapper ) { let wrap = content; if ( !! content && !! wrapper ) { wrap = self.toArray( self.isstr(wrapper) ? self.create(wrapper) : wrapper )[ 0 ]; if ( !! wrap ) { let cont = self.toArray(content); self.prependTo(wrap, null, cont[ 0 ]); cont.forEach( c => self.appendTo(c, wrap) ); } } return wrap; }; // Object for feature-detection (modern browsers only --e.g., uses lambdas) self.detected = Object.create(null, { // Detect support for passive event listeners // Reference: https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection 'passiveEvents': self.propDef(self.lazy( ( ) => { var supported = false; try { var opts = Object.defineProperty({ }, 'passive', self.propDef( ( ) => supported = true )); window.addEventListener('testPassive', null, opts); window.removeEventListener('testPassive', null, opts); } catch ( e ) { } return supported; } )), }); // ---------------------------------------------------- // Intended for Internal Use self.copyMembers = function( source, target, members, preserve ) { //self.log('* Copying from', source, '\n\tto', target, '\n\t'+ members, preserve); if ( ! self.isobj(source) || ! self.isobj(target) ) { self.warn('=> Cannot copy from/to non-objects'); return false; } let names = Object.keys(source); preserve = ( self.isobj(preserve) ? preserve : false ); //self.log('- Full list of members:', names, '\n\t', source); if ( self.isstr(members) ) { members = members.split(',').map( nm => nm.trim() ); } if ( self.isarr(members) ) { //self.log('* Member filter:', members); names = names.filter( nm => members.includes(nm) ); } else if ( self.isfn(members) ) { names = names.filter(members); } //self.log('- Filtered list of members:', names); names.forEach( nm => { if ( !! target[ nm ] && !! preserve ) { preserve[ nm ] = target[ nm ]; } target[ nm ] = source[ nm ]; //self.log('- Target members', nm, target[ nm ]); } ); //self.log('=>', target); return (preserve || target); }; self.export = function( scope, members, overwriten ) { if ( ! scope ) { return false; } if ( '*' === (members +'').trim() ) { members = null; } return self.copyMembers(self, scope, members, overwriten); }; // Avoid needing a 'new' operator; this is just a wrapper return self; }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址