my JS library
This script should not be not be installed directly. It is a library for other scripts to include with the meta directive // @require https://update.greasyfork.org/scripts/524553/1525219/MDA%20library.js
// ==UserScript== // @name MDA library // @namespace http://tampermonkey.net/ // @version 1.2.1 // @description my JS library // @author mr-d-r // ==/UserScript== // @require file://D:\...\_MDAlib_tampermonkey.js ВСЕГДА добавляет в самое начало скрипта, где он использован // т.о. переменные объявленные здесь всегда глобальные !!! // try to make global functions as in https://stackoverflow.com/questions/27680230/how-do-i-make-functions-added-by-tampermonkey-be-available-in-console-after-the // пробовать делать библиотеку, которая запускается на каждой странице var MDAlib="included", dbg; // real global vars !!! // dbg - отладка // verb - немного расширенные сообщения // localStorage.setItem("MDAlib", "loaded @" +Date.now()); // !!! в скриптах можно проверять так: // MDAlib=${(typeof MDAlib == "undefined") ? "absent" : MDAlib} // if(typeof MDAlib == 'undefined') console.log("MDAlib 1212 is NOT defined in _MDAlib_tampermonkey"); else console.log("MDAlib 1212 DEFINED in _MDAlib_tampermonkey = " +MDAlib); // if(typeof dbg == 'undefined') console.log("dbg 1212 is NOT defined in _MDAlib_tampermonkey"); else console.log("dbg 1212 DEFINED in _MDAlib_tampermonkey = " +dbg); // !!! пользовать tampermonkey storage для persistent vars и обмена между скриптами !!! // TRY !!! from https://greasyfork.org/en/scripts/14782-facebook-event-exporter/code /* var err = console.error.bind(console), log = console.log.bind(console), */ function anyActiveInput () { if( Array.from(document.querySelectorAll("input,textarea")).includes(document.activeElement) ) return true; if( document.activeElement.contentEditable == 'true' ) return true; // for stupid youtube reply mini-window // !!! warning: MUST BE: document.activeElement.contentEditable == true if( document.activeElement.querySelector('span[data-lexical-text="true"]') ) return true; // for stupid facebook input fields //if ((aaBB = document.activeElement) && (editable(a) || (a.tagName === "INPUT") || (a.tagName === "TEXTAREA"))) return; } // anyActiveInput() function ttout (delay, func) { // wrap for setTimeout() // WORKS setTimeout(() => { func(); }, delay); } // ttout() var tTO=ttout; function ttoutSMART (delay=1000, label, cmd='new', func) { // wrap for setTimeout() // static массив всех вызванных таймеров с метками let a, b, hnd, min=10000, max=99999, fn=fnName(); if ( typeof ttout.arr == 'undefined' ) { ttout.arr = []; if(dbg && dbg>5) log(`${fn}: static arr init`); } if( ! isNumber(delay) ) { console.error(`${fn}: delay is not a number: ${delay}`); return; } // isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a) switch (cmd) { case 'chk': case 'exists': case 'exist': if( a=ttout.arr.find( (el) => el.label == label ) ) return a; // a.hnd else return false; break; case 'list': showArrQvTyIk(); break; case 'del': // delete by label from array case 'delete': delQvTyIk(label); break; default: // create new or update existing case 'new': case 'set': if( !label ) label=`lbl_${Math.floor(Math.random() * (max - min + 1)) + min}`; // если label пуста, то сгенерировать случайную !!! delQvTyIk(label); // ищет в массиве существующий таймер, делает ему clear и удаляет его из массива //log(`creating new: ${label}`); hnd=setTimeout(() => { func(); }, delay); b=setTimeout(()=>{ //log(`deleting on TIMEOUT ${label}`); delQvTyIk(label); }, delay+3); // по истечении таймера удалить его из массива !!! ttout.arr.push( { label: label, hnd: hnd, hnd2: b, delay: delay } ); break; } // switch function showArrQvTyIk() { for( let i in ttout.arr ) log(ttout.arr[i]); console.log('---'); } function delQvTyIk(ll) { let a=ttout.arr.findIndex( (el) => el.label == ll ); // log(`${fn}: deleting ${ll} at ${a}`); if(a>=0) { clearTimeout(ttout.arr[a].hnd); clearTimeout(ttout.arr[a].hnd2); ttout.arr.splice(a, 1); } // splice here deletes the element!!! } } // ttoutSMART() var tTS=ttoutSMART; function showMSGsimple (msg, duration, hook, styl) { // one line showmsg () // - hook in querySelector form, i.e. "#smth" or "div[id='smth']" // looks GOOD and debugged let aa, mydiv, pareFou, fn=fnName(); // - if msg="" - then mydiv will be removed let mydivBase="showMSGsimple", mydivTitle="sshowMSGsimple_title"; // - is styl starts with + then add style, if no + then replace mydiv.style if( !duration ) duration=2000_000; // НЕ переносить в декларацию (... , duration, ...) if( !hook ) hook=document.body; // НЕ переносить в декларацию (... , hook, ...) if( hook!=document.body ) pareFou=document.querySelector(hook); else pareFou=document.body; // log(fn +": hook= ", hook, "\n", "pareFou= ", pareFou); if( !pareFou ) { log(fn +": hook is not found"); return; } aa=pareFou.querySelector('#' +mydivBase); if(aa) { mydiv = aa; if(!msg) { aa?.remove(); return; } } else { if(!msg) return; // if (msg="" или undefined) mydiv = document.createElement("div"); if(dbg && dbg>5) log(fn +": append child hook= ", hook, "\n", "pareFou= ", pareFou); pareFou.insertBefore(mydiv, pareFou.firstChild); //pareFou.appendChild(mydiv); // pareFou.insertBefore(mydiv, pareFou.firstChild); } mydiv.innerHTML = msg; // mydiv.style.zIndex=100; // border: solid 5px Red; mydiv.id=mydivBase; mydiv.title=mydivTitle; // mydiv.style.position="absolute"; if(styl) if( styl.startsWith("+") ) mydiv.style.cssText = `${mydiv.style.cssText} ${styl.replace(/^\+/,'')}`; // trim '+' & add ещ styles else mydiv.style.cssText = styl; // replace style setTimeout(() => { if(dbg && dbg>5) log(fn +" removing", mydiv); mydiv?.parentNode?.removeChild(mydiv); }, duration); } // end of showMSGsimple() async function mySaveAs (fname, url, opt1 ) { // WORKS FINE // usage: (async() => { ww=await mySaveAs("filename", "http://abc", ''); })(); if(!opt1) opt1={ suggestedName: fname, types: [ { description: 'Images', accept: { 'image/*': ['.png', '.gif', '.jpeg', '.jpg'] } }, ], }; if(dbg) log("mySaveAs(): " +fname, url, opt1, "---"); // если с opt1 что-то не то, window.showSaveFilePicker молча обламывается var fhnd = await window.showSaveFilePicker(opt1); if (!fhnd) { log("mySaveAs(): showSaveFilePicker() failed"); return null; } var wr = await fhnd.createWritable(); if (!wr) { log("mySaveAs(): createWritable() failed"); return null; } // Create a FileSystemWritableFileStream to write to. var re = await fetch(url); if (!re) { log("mySaveAs(): fetch()"); return null; } // Make an HTTP request for the contents. await re.body.pipeTo(wr); // Stream the response into the file. // pipeTo() closes the destination pipe by default, no need to close it. } //console.log(DOMRegex(/^service\//)); // your regex here function DOMRegex(regex) { // try as function and as prototype let output = []; for (let i of document.querySelectorAll('*')) { if (regex.test(i.type)) { // or whatever attribute you want to search output.push(i); } } return output; } //getAllTagMatches(/^di/i); // Returns an array of all elements that begin with "di", eg "div" function getAllTagMatches(regEx) { return Array.prototype.slice.call(document.querySelectorAll('*')).filter(function (el) { return el.tagName.match(regEx); }); } function showmsg578 (msg, duration) { var dbg=9, fn="showmsg578"; let mydivBase="showmsg", mydivTitle="showmsgCOMMONtitle"; //, myDivN=mydivBase; let parents=[ mydivBase, "styles_photo__", "body" ]; // 'body' must be ALWAYS present !!! let pareFou=0, mydiv, aa="n/a", bb="n/a", ddd1, ddd2; for (let x=0;x<2;x++) { for (let i of parents) { pareFou=document.querySelector(i); if(pareFou != null) { aa=i; break; } // потом допилить еще блее красивый поиск pareFou=document.querySelector(`[class*="${i}"]`); if(pareFou != null) { aa=i; break; } pareFou=document.getElementById(i); if(pareFou != null) { aa=i; break; } }; if(dbg>5) log(`${fn}(): ${msg}`, ` found parent ${aa} pareFou=`, pareFou); if (!pareFou) { console.log("showmsg(): can NOT add child to HTML"); return 11; } if (pareFou.id != mydivBase) { if(dbg>5) log(`${fn}(): creating the anchor DIV !!!: `, aa); mydiv = document.createElement("div"); mydiv.id=mydivBase; mydiv.style.position="absolute"; mydiv.title=mydivTitle + "_anchor"; bb=pareFou.insertAdjacentElement("afterbegin", mydiv); // new way to appendChild !!! https://www.w3schools.com/jsref/met_node_insertadjacentelement.asp https://stackoverflow.com/questions/2007357/how-to-set-dom-element-as-first-child } } // for x mydiv = document.createElement("div"); mydiv.id=mydivBase + Math.floor(Math.random() * 10000); mydiv.style.position="relative"; mydiv.setAttribute("style",`width:auto; height:auto; top:10%; left:5%; padding: 10px; color:Silver; font-size:15px; background-color:#00008B; z-index:99;`); // opacity:0.9; text-shadow: 5px 5px 20px #00FF00;`); mydiv.innerHTML = `<h2> ${msg} </h2>`; // border: solid 5px Red; bb=pareFou.appendChild(mydiv); if(dbg>5) log(`${fn}(): ---- new DIV=|${mydiv.id}|`, mydiv.id); setTimeout(function() { if(pareFou!=null) mydiv.parentNode.removeChild(mydiv); }, duration); if(dbg>5) { log(`${fn}(): ${mydiv.id} appended to ${aa} rc=${bb} <===`); ddd1 = document.querySelector(mydiv.id); ddd2 = document.getElementById(mydiv.id); log(`${fn}(): check ${mydiv.id} getElementById=${ddd1} querySelector=${ddd2}`); } // !!!!!! и querySelector и getElementById глючат и часто показывают null return } // end of showmsg() function WLH () { let aa=window.location.href; if (aa.match(/accounts.youtube/)) return "accounts.yotube"; return aa.replace(/http.*\/\/(www.)*(.*)\?.*/g,'$2'); } var fnName = getFunctionsNameThatCalledThisFunction; // get name of currently executing function //function gFNTCTF() { return gFNTCTF.caller.name; } function getFunctionsNameThatCalledThisFunction() { return getFunctionsNameThatCalledThisFunction.caller.name; } var log = console.log; //var originalLogger = console.log; // var log = function() { for (var i of arguments) originalLogger(i); } // писать одним аргументом, чтобы вывод был в пределах одного сообщения в логе !!! \n отрабатыват отлично! log("1\n2", "3"); function sleepSYNC (millis) { // BLOCK execution of others threads!!! ex.pausecomp // выполнять блоками по 100-200 мс, чтобы не ставила все раком let date = new Date(), curDate = null; do { curDate = new Date(); } while(curDate-date < millis); } function sleepASYNC (ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } const repeatedGreetings = async () => { // one more sleep ASYNC - WORKS !!! console.log("First"); await sleepASYNC(1000) console.log("Second"); await sleepASYNC(1000) console.log("Third"); await sleepASYNC(1000) } // repeatedGreetings() // function sleepQW (durat) { setTimeout(function(){ log("sleepQW()"); },durat); } let mySleepInterim = (g) => (...args) => { let f, res = () => f.next(), sleep = (ms) => setTimeout(res, ms); f = g.apply({sleep}, args); f.next(); }; let mySleepExample = mySleepInterim(function*() { // https://developer.mozilla.org/ru/docs/Learn/JavaScript/Asynchronous/Promises let sl=1200, cnt; let {sleep} = this; // !!! РІ песочнице работало хорошо console.log("Sleeping"); yield sleep(sl); console.log("stage2"); yield sleep(sl); console.log("stage3"); yield sleep(sl); console.log("Done"); }); //mySleepExample(); // run step by step with delays // ВРОДЕ РАБОТАЕТ и НЕ жрет проц function vsc_font(fntsz="") { // change of Video Speed Controller (VSC) font size //document.querySelector(".vsc-controller").shadowRoot.styleSheets[0].rules[0].styleSheet.cssRules[0].style.fontSize = '25px'; let font1=document.querySelector(".vsc-controller"); if (fntsz == "") return font1?.shadowRoot?.styleSheets[0]?.rules[0]?.styleSheet?.cssRules[0]?.style?.fontSize; if (font1?.shadowRoot?.styleSheets[0]?.rules[0]?.styleSheet?.cssRules[0]?.style?.fontSize) { document.querySelector(".vsc-controller").shadowRoot.styleSheets[0].rules[0].styleSheet.cssRules[0].style.fontSize = fntsz; if (dbg) console.log("vsc_font(): change " + font1?.shadowRoot?.styleSheets[0]?.rules[0]?.styleSheet?.cssRules[0]?.style?.fontSize + " -> " +fntsz); return fntsz; } else console.error("vsc_font(): .vsc-controller....cssRules[0].style.fontSize is not found") return 0; } // fu nc tion waitElement(ele) { // rc=1 - FOUND function qS (query, elem=document) { return elem.querySelector(query); } // WORKS //function qSA (que, elem=document) { return elem.querySelectorALL(que); } // FAILs если в que перечислены несколько критериев function queryElement(ele, doc=document) { // еще доделать, чтобы сначала искать указанный doc, а потом в нем искать ele let aaa=doс?.querySelector(ele); if(dbg>5) log("getEl(): " + aaa); return aaa; } //const qS = queryElement; //const qSA = document.querySelectorAll; // FAILs //var qs = document.querySelector.bind(document), var qSA = document.querySelectorAll.bind(document); // WORKS const getEl = queryElement; const queryEl = queryElement; // !!! see also https://stackoverflow.com/questions/13383886/making-a-short-alias-for-document-queryselectorall function deleteElement (ele) { let aaa=document.querySelector(ele); if(aaa) aaa.remove(); if(dbg && dbg>=5) console.log("deleteElement(" +ele+ "): ", aaa); } function showmsg (msg, duration=2000, styl="", paren='n/a') { // ``` ёёё let mydivBase="showmsg", mydivTitle="showmsgCOMMONtitle"; //, myDivN=mydivBase; let sL1="n/a"; // static label // let parents=[ mydivBase, "#player", "body > div.container-fluid.inner-pages-banner > div", "body > div.ribbon-container > div", "body > header > div.container.less-margin", "body > div.container-fluid.inner-pages-banner > div"]; // let parents=[ mydivBase, "body > div.mfp-wrap.mfp-gallery.mfp-close-btn-in.mfp-auto-cursor.mfp-fade.mfp-ready > div", "#player", "body > div.container-fluid.inner-pages-banner > div", "body > div.ribbon-container > div", "body > header > div.container.less-margin", "body > div.container-fluid.inner-pages-banner > div"]; // терпимо, но когда картинка на весь экран, то showmsg не видно "body > div.mfp-wrap.mfp-gallery.mfp-close-btn-in.mfp-auto-cursor.mfp-fade.mfp-ready > div" let parents=[ mydivBase, "body > div.mfp-wrap.mfp-gallery.mfp-close-btn-in.mfp-auto-cursor.mfp-fade.mfp-ready > div > div.mfp-content > div > button", "#player", "body > div.container-fluid.inner-pages-banner > div", "body > div.ribbon-container > div", "body > header > div.container.less-margin", "body > div.container-fluid.inner-pages-banner > div"]; let pareFou=0, mydiv, aa="n/a", bb="n/a", ddd1, ddd2; for (let i of parents) { pareFou=document.querySelector(i); if(pareFou != null) { aa=i; break; } // try add id[i] pareFou=document.getElementById(i); if(pareFou != null) { aa=i; break; } }; if(dbg>5) log(` showmsg(): ${msg}`, ` found parent ${aa} pareFou=`, pareFou); mydiv = document.createElement("div"); //mydiv.setAttribute("style",`width:auto; top:5%; left:9%; height:auto; color:Silver; font-size: 20px; background-color:black; `); // position & z-index можно и тут прописать //mydiv.setAttribute("style",`width:800px; top:5%; left:9%; height:auto; color:Silver; font-size: 20px; background-color:black; `); // position & z-index можно и тут прописать if(styl) mydiv.setAttribute("style",styl); mydiv.style.zIndex=100; //mydiv.innerHTML = `<h1> ${msg} </h1>`; // border: solid 5px Red; // padding later // padding: 15px; mydiv.innerHTML = msg; var qaz=pareFou.id; // qaz=pareFou.title; //log(` qaz=|${qaz}| new DIV=|${mydiv.id}|`); if(qaz==mydivBase) { mydiv.id=mydivBase + Math.floor(Math.random() * 10000); mydiv.style.position="relative"; //aa=document.querySelector(`[title='showmsgCOMMONtitle']`); if(dbg) log("found by title: ", aa); } else { mydiv.id=mydivBase; mydiv.style.position="absolute"; mydiv.title=mydivTitle; } if(dbg>5) log(` ---- new DIV=|${mydiv.id}|`); //log(` ------- cmp qaz==mydivBase ${qaz==mydivBase} ${qaz===mydivBase}`); // ${qaz.localeCompare(mydivBase)}`); //var zx=new String(qaz); log(zx.length); var zy=new String(mydivBase); log(zy.length); log(zx==zy); log(zx===zy); //if ( aa=staticL('chk') ) // cmp ? // log(`mydivBase= ${aa} already exists=${staticL('get')}`); if(pareFou==null) { aa="document.body"; bb=document.body.appendChild(mydiv); } else bb=pareFou.appendChild(mydiv); setTimeout(function() { //if (mydiv.id=mydivBase) return; // never delete base if(pareFou!=null) mydiv.parentNode.removeChild(mydiv); // также восстановить staticLabel }, duration); if(dbg>5) log(` showmsg(): ${mydiv.id} appended to ${aa} rc=${bb} <===`); ddd1 = document.querySelector(mydiv.id); ddd2 = document.getElementById(mydiv.id); if(dbg) log(` showmsg(): check ${mydiv.id} getElementById=${ddd1} querySelector=${ddd2}`); // !!!!!! и querySelector и getElementById глючат и часто показывают null return } // end of showmsg() function deletemsg() { let what="showmsg"; let ddd1 = document.querySelector(what); let ddd2 = document.getElementById(what); if(dbg) log(`hidemsg(): ${what} getElementById=${ddd1} querySelector=${ddd2}`); // querySelector ВСЕГДА показывает null // getElementById - WORKS FINE !!! if(ddd1!=null) ddd1.parentNode.removeChild(ddd1); if(ddd2!=null) ddd2.parentNode.removeChild(ddd2); } function staticL_example () { // !!! for use as static variables // persistent let aa; aa=staticL('create', "myLabel13", "cr567"); log(`create: rc=${aa} exists: ${staticL('chk', "myLabel13")} value=${staticL('get', "myLabel13")}`); aa=staticL('zero', "myLabel13"); log(`zero: rc=${aa} exists: ${staticL('chk', "myLabel13")} value=${staticL('get', "myLabel13")}`); aa=staticL('update', "myLabel13", "upd755"); log(`update: rc=${aa} exists: ${staticL('chk', "myLabel13")} value=${staticL('get', "myLabel13")}`); aa=staticL('compare', "myLabel13", "upd444"); log(`compare bad rc=${aa} exists: ${staticL('chk', "myLabel13")} value=${staticL('get', "myLabel13")}`); aa=staticL('compare', "myLabel13", "upd755"); log(`compare ok rc=${aa} exists: ${staticL('chk', "myLabel13")} value=${staticL('get', "myLabel13")}`); aa=staticL('wrong', "smr332"); log(`wrong_cmd rc=${aa} exists: ${staticL('chk', "myLabel13")} value=${staticL('get', "myLabel13")}`); } // end of staticL_example() //function staticL (cmd, staticLabel="sampleStatLabel111", txt="n/a") { // !!! for use as static variables // persistent // let sLL="n/a", aa, staticLabel="showmsg_static1" function staticL (cmd, staticLabel="sampleStatLabel111", txt="n/a") { // !!! for use as static variables // persistent let sLL="n/a", aa; // staticLabel="showmsg_static1" switch (cmd) { case 'cr': case 'create': sLL=queryL(); // usage: aa=staticL('cr|create', "myLabel13", "init123"); log(`create: rc=${aa} exists: ${staticL('chk')} value=${staticL('get')}`); if(sLL == null) { sLL=document.createElement("LABEL"); sLL.htmlFor=staticLabel; document.body.appendChild(sLL); sLL.setAttribute("display","none"); } sLL.innerText=txt; return true; break; case 'get': // usage: aa=staticL('get', "myLabel13"); log(`get: rc=${aa} exists: ${staticL('chk')} value=${staticL('get')}`); sLL=queryL(); if(sLL == null) return null; return sLL.innerText; break; case 'zero': case 'reset': case 'upd': case 'update': // usage: aa=staticL('zero|reset', "myLabel13"); log(`zero: rc=${aa} exists: ${staticL('chk')} value=${staticL('get')}`); // usage: aa=staticL('upd|update', "myLabel13", "upd555") ; log(`update: rc=${aa} exists: ${staticL('chk')} value=${staticL('get')}`); sLL=queryL(); if(sLL == null) return null; (cmd=="zero" || cmd=="reset") ? sLL.innerText="" : sLL.innerText=txt; return true; break; case 'cmp': case 'compare': // usage: aa=staticL('cmp|compare', "myLabel13", "upd555"); log(`compare rc=${aa} exists: ${staticL('chk')} value=${staticL('get')}`); sLL=queryL(); if(sLL.innerText != txt) return null; return true; break; case 'chk': case 'exist': case 'check': // usage: aa=staticL('chk|exist|check', "myLabel13"); log(`check rc=${aa} exists: ${staticL('chk')} value=${staticL('get')}`); if (queryL()) return true; else return null; break; default: log("staticL(): bad cmd=" + cmd); // usage: aa=staticL('wrong', "smr332"); log(`wrong_cmd rc=${aa} exists: ${staticL('chk')} value=${staticL('get')}`); return null; break; } function queryL() { return document.querySelector( `label[for=${staticLabel}]` ); } } // end of staticL() function isNumber(n){ return Number(n)=== n; // see also function isNumber(val) { return !isNaN(val); } // // https://stackoverflow.com/questions/18082/validate-decimal-numbers-in-javascript-isnumeric // // https://stackoverflow.com/questions/20169217/how-to-write-isnumber-in-javascript //test // [0, 1, 2, -1, 1.345e+17, Infinity, false, true, NaN, '1', '0'].map(function(itm){ return itm+'= '+isNumber(itm); }); } // isNumber() function TrustedHTMLworkaround () { if (window.trustedTypes && window.trustedTypes.createPolicy) { window.trustedTypes.createPolicy('default', { createHTML: (string, sink) => string }); } } // TrustedHTMLworkaround() function TrustedHTMLworkaround2 () { // WORKAROUND: TypeError: Failed to set the 'innerHTML' property on 'Element': This document requires 'TrustedHTML' assignment. if (window.trustedTypes) { if (!window.trustedTypes.defaultPolicy) { const passThroughFn = (x) => x; window.trustedTypes.createPolicy('default', { createHTML: passThroughFn, createScriptURL: passThroughFn, createScript: passThroughFn, }); } } } // TrustedHTMLworkaround2()