mylib

我的工具

このスクリプトは単体で利用できません。右のようなメタデータを含むスクリプトから、ライブラリとして読み込まれます: // @require https://update.greasyfork.org/scripts/435697/1742073/mylib.js

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
//==UserScript==
// @name mylib260125
// @match *://*/*
// @description 需要兼容油猴环境和非油猴环境(如博客园)
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// @grant GM_listValues
// @grant GM.xmlHttpRequest
//==/UserScript==
;(function(){
    "use strict";
    const win = unsafeWindow ?? window,myxhr = GM.xmlHttpRequest ?? null,
          info = win.info = GM_info ?? (GM?.info ?? {script:{name:'Userscript',namespace:'Nonamespace'}});
    win.my=new My(win);//初始化
    function My(win){//构造函数,需配合实例方法,与this,prototype有关
        win.al=win.alert;
        win.cl=win.console.log;
        win.cc=win.console.clear;
        win.ce=win.console.error;
        win.dq=selector=>document.qs(selector);
        win.dqa=selector=>document.qsa(selector);
        win.si=win.setInterval;
        win.st=win.setTimeout;
        win.mysv=function(name, value) {//增/改
            typeof GM_setValue==='function'?GM_setValue(name, value):localStorage.setItem(`${getScriptIdentifier()}_${name}`, value);
        }
        win.mygv=function(name, defvalue) { //查
            if(typeof GM_getValue==='function')return GM_getValue(name, defvalue)
            else{
                if ((`${getScriptIdentifier()}_${name}`) in localStorage) return localStorage.getItem(`${getScriptIdentifier()}_${name}`);
                else return defvalue;
            }
        }
        win.myas=css=>win.myz.myappend('style',css);//function和lambda this指向不同,后者没有prototype、arguments,后者不能new/作为构造函数;
        win.myaddbtns=(...args)=>{//myaddbtns(()=>{},e=>{confirm(e.target.id)},function outerHTML(e){prompt(e.target.outerHTML)},function test(e){return 1},function event(ev){cl(ev)})
            args.forEach(arg=>{//{func:async function f(ev){...},title:'...'}
                if(arg instanceof Function) win.mybtns.myappend('button',arg.name,`className`,'my-btn').ael('mouseup',arg);
                else{//如非function,均为json
                    const btn=win.mybtns.myappend('input','','value',arg.func.name,'type','button',`className`,'my-btn','title',arg.title).ael('mouseup',arg.func);
                    if(arg.img) btn.style.backgroundImage=`url(${arg.img})`
                }
            })
            return win.mybtns;
        }
        //My.静态方法 My.prototype实例方法(如本案例中my.prototype.constructor.toString())
        // My.prototype.test1=function(){};My.test2=function(){}
        EventTarget.prototype.mybefore=function(tagName,innerHTML,...attributes){//myz.mybefore('test','content','key','value').ael('click',()=>{al(1)})
            const el=document.createElement(tagName);
            el.innerHTML=innerHTML;
            for(let i=0;i<attributes.length;i+=2) el[attributes[i]]=attributes[i+1];
            this.before(el);
            return el;
        }
        EventTarget.prototype.qs=Document.prototype.qs=function(selector){return this.querySelector(selector)||null}
        EventTarget.prototype.qsa=Document.prototype.qsa=function(selector){return this.querySelectorAll(selector)||null}
        EventTarget.prototype.myappend=function(tagName,innerHTML,...attributes){//myz.myappend('test','content','key','value').ael("click",()=>{al(1)}).myappend('y','test','idk','true','data-s')
            const el=document.createElement(tagName);
            el.innerHTML=innerHTML;
            for(let i=0;i<attributes.length;i+=2) el[attributes[i]]=attributes[i+1];
            this.appendChild(el);
            return el;
        }
        EventTarget.prototype.myinsert=function(tagName, innerHTML,...attributes) {//myz.myinsert('test','content','key','value').ael('',()=>{al(1)})
            const el=document.createElement(tagName);
            el.innerHTML=innerHTML;
            for (let i=0; i < attributes.length; i += 2) el[attributes[i]]=attributes[i + 1];
            const firstChild=this.firstChild;
            this.insertBefore(el,firstChild);
            return el;
        }
        EventTarget.prototype.myafter=function(tagName,innerHTML,...attributes){//myz.myafter('test','content','key','value').ael("click",()=>{al(1)})
            const el=document.createElement(tagName);
            el.innerHTML=innerHTML;
            for(let i=0;i<attributes.length;i+=2) el[attributes[i]]=attributes[i+1];
            this.after(el);
            return el;
        }
        EventTarget.prototype.ael=function(event,callback){//Element 和 Document 都实现了 EventTarget 接口,为更通用改Element为EventTarget
            this.addEventListener(event,callback);
            return this;
        }
        EventTarget.prototype.rel=function(event,handler){
            this.removeEventListener(event,handler);
            return this;
        }
        NodeList.prototype.removeEach=function(){//.forEach(e=>e.remove())
            this.forEach(e=>e.remove());
        };
        NodeList.prototype.clickEach=function(){
            this.forEach(e=>e.click());
        };
        win.myms2date=timestamp=>{//myms2date(Date.now())
            const d=new Date(typeof timestamp==="number"?timestamp:Date.now()),f=n=>String(n).padStart(2,'0');
            return`${d.getFullYear()}${f(d.getMonth()+1)}${f(d.getDate())}${f(d.getHours())}${f(d.getMinutes())}`;//${f(d.getSeconds())}${String(d.getMilliseconds()).padStart(3,'0')}
        }
        win.myBindDrag=el=>{//鼠标拖动
            el.ael('mousedown',ev=>{
                ev.stopPropagation()//ev.preventDefault();
                const rect=el.getBoundingClientRect(); // 获取元素实际位置
                let startX=ev.clientX-rect.left; // 使用视口绝对坐标
                let startY=ev.clientY-rect.top;
                const move=e=>{
                    const dx=e.clientX-startX,dy=e.clientY-startY; // 保持相对位移计算
                    el.style.transform=`translate(${dx}px,${dy}px)`;
                },up=()=>{
                    document.rel('mousemove',move);
                    document.rel('mouseup',up);
                };
                document.ael('mousemove',move);
                document.ael('mouseup',up);
            });
        }
        win.mylockprop=function(obj,prop,value){//lock property;mylockprop(document,"title")
            Object.defineProperty(obj,prop,{
                set:v=>value,get:()=>value
            });
        }
        win.myaddas=(...urls)=>urls.forEach(async(url,index)=>{//必须配合@connect
            await myxhr({url:url}).then(resp=>resp.responseText).then(html=>{//myaddas("https://www.bilibili.com/","https://www.example.com/")
                const doc=new DOMParser().parseFromString(html,'text/html'),title=doc.title;
                win.mybtns.myappend('a',index+title,'href',url,`className`,'my-a my-btn');
            }).catch(err=>{//跨域了
                win.cl('跨域了'+err)
                win.mybtns.myappend('a',`框${index}`,'href',url,`className`,'my-a my-btn');
            });
        });
        win.mywait=time=>new Promise(resolve=> setTimeout(resolve,time));
        win.mywaitele=(selector,timeout=3e4)=>{//查找ele,超时30000
            return new Promise((resolve,reject)=>{
                const 间隔=500,startTime=Date.now(),i=setInterval(()=>{
                    const el=win.dq(selector);
                    if (el){
                        clearInterval(i);
                        resolve(el);//找到
                    } else if (Date.now() - startTime > timeout){
                        clearInterval(i);
                        reject(`Timeout waiting ${selector}.`);//超时
                    }//继续找
                },间隔);
            });
        }
        win.mywaiteles=(selector,timeout=3e4)=>new Promise((resolve,reject)=>{//查找eles
            const intervalTime=500,startTime=Date.now(),i=win.si(()=>{
                const els=win.dqa(selector);
                if (els.length>0){
                    clearInterval(i);
                    resolve(els);
                } else if(Date.now() - startTime > timeout){
                    clearInterval(i);
                    reject(`Timeout waiting ${selector}.`);
                }
            },intervalTime);
        });
        win.myshowlv=()=>{//当前页面第几层
            let level=0,currentWindow=win;
            do{level++;
               // al(level+currentWindow.location.href);
               if(currentWindow === currentWindow.top) break;
               currentWindow=currentWindow.parent;
              }while(currentWindow.parent);
            win.mybtns.myappend('a',`第${level}层`,'href',win.location.href,'className','my-a');
        }
        win.mydv=function(name) {//删
            typeof GM_deleteValue==='function'?GM_deleteValue(name):localStorage.removeItem(`${getScriptIdentifier()}_${name}`);
        }
        win.mylv=function() {//查2
            if(typeof GM_listValues==='function')return GM_listValues();
            else{
                let values =[],prefix =getScriptIdentifier(),prelen =getScriptIdentifier().length;
                for (let i =0; i < localStorage.length; i++) if (localStorage.key(i).substr(0, prelen)===prefix) values.push(localStorage.key(i).substr(prelen+1));
                return values;
            }
        }
        My.divideStr=(str,char)=>Array.from(str).join(char);//以特定字符分隔字符串
        My.reverseStr=str=>str.split('').reverse().join('');//反转str
        function getScriptIdentifier(){
            const scriptNamespace=typeof info.script.namespace==='string'?info.script.namespace.trim():'Nonamespace',scriptName=(typeof info.script.name==='string'&&info.script.name.trim().length > 0)?info.script.name.trim():'Userscript';
            return `${scriptNamespace}-${scriptName}`;
        }
        return My;
    }
})()