// ==UserScript==
// @name lib:all functions
// @version 10
// @description none
// @license GPLv3
// @run-at document-start
// @author You
// @match *://*/*
// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAMAAABiM0N1AAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAHJQTFRFAAAAEIijAo2yAI60BYyuF4WaFIifAY6zBI2wB4usGIaZEYigIoiZCIyrE4igG4iYD4mjEomhFoedCoqpDIqnDomlBYyvE4efEYmiDYqlA42xBoytD4mkCYqqGYSUFYidC4qoC4upAo6yCoupDYqmCYur4zowOQAAACZ0Uk5TAO////9vr////1+/D/+/L+/Pf/////+f3///////H4////////+5G91rAAACgUlEQVR4nM2Y22KjIBCGidg1264liZqDadK03X3/V2wNKHMC7MpF/xthHD5mgERAqZhWhfYqH6K+Qf2qNNf625hCoFj9/gblMUi5q5jLkXLCKudgyiRm0FMK82cWJp1fLbV5VmvJbCIc0GCYaFqqlDJgADdBjncqAXYobm1xh72aFMflbysteFfdy2Yi1XGOm5HGBzQ1dq7TzEoxjeNTjQZb7VA3e1c7+ImgasAgQ9+xusNVNZIo5xmOMgihIS2PbCQIiHEUdTvhxCcS/kPomfFI2zHy2PkWmA6aNatIJpKFJyekyy02xh5Y3DI9T4aOT6VhIUrsNTFp1pf79Z4SIIVDegl6IJO6cHiL/GimIZDhgTu/BlYWCQzHMl0zBWT/T3KAhtxOuUB9FtBrpsz0RV4xsjHmW+UCaffcSy/5viMGer0/6HdFNMZBq/vjJL38H9Dqx4Fuy0Em12DbZy+9pGtiDijbglwAehyj11n0tRD3WUBm+lwulE/8h4BuA+iWAQQnteg2Xm63WQLTpnMnpjdge0Mgu/GRPsV4xdjQ94Lfi624fabhDkfUqIKNrM64Q837v8yL0prasepCgrtvw1sJpoqanGEX7b5mQboNW8eawXaWXTMfMGxub472hzWzHSn6Sg2G9+6TAyRruE71s+zAzjWaknoyJCQzwxrghH2k5FDT4eqWunuNxyN9QCGcxVod5oADbYnIUkDTGZEf1xDJnSFteQ3KdsT8zYDMQXcHxsevcLH1TrsABzkNPyA/L7b0jg704viMMlpQI96WsHknCt/3YH0kOEo9zcGkwrFK39ck72rmoehmKqo2RKlilzSy/nJKEV45CT38myJp456fezktHjN5aeMAAAAASUVORK5CYII=
// @grant none
// @exclude /livereload.net\/files\/ffopen\/index.html$/
// @namespace https://greasyfork.org/users/1184528
// ==/UserScript==
;(async function () {
const { savelib } = loadlib("libloader", "allfuncs.js")
const proxy_set = new WeakSet()
const oldproxy = Proxy
window.Proxy = new Proxy(oldproxy, {
construct(_target, args) {
const proxy = new oldproxy(...args)
proxy_set.add(proxy)
return proxy
},
})
const isproxy = function (proxy) {
return proxy_set.has(proxy)
}
Object.keys(console).forEach((e) => {
window[e] = function (...args) {
var z = []
let pi = 0
args.forEach((y) => {
let rand = `{${pi}}${a().randstr().val}`
while (true) {
if (isa(y)) {
z.push("function_chain >")
y = y.val
continue
} else if (a(y).gettype("promise").val) {
pi++
y.then((...args) => window[e]("RESOLVED - " + rand, ...args)).catch(
(...args) => window[e]("REJECTED - " + rand, ...args)
)
y = "PROMISE - " + rand
continue
}
z.push(y)
break
}
})
console[e](...z)
return z
}
})
const warn = console.warn.bind(window)
const log = console.log.bind(window)
const error = console.error.bind(window)
const time = console.time.bind(window)
const timeEnd = console.timeEnd.bind(window)
// Object.assign(window, console)
// if (window.a) error("allfuncs allready exists")
var getvm = function () {
const oldBind = Function.prototype.bind
Function.prototype.bind = function (...args) {
if (
args[0] &&
args[0]?.hasOwnProperty?.("editingTarget") &&
args[0].hasOwnProperty("runtime")
) {
Function.prototype.bind = oldBind
savelib("scratch", { vm: args[0] })
}
return oldBind.apply(this, args)
}
}
getvm()
function isa(inp1) {
return (
inp1?.[Math.random()]?.name === "function_chain" ||
inp1?.name === "function_chain"
)
}
function noa(inp1) {
return isa(inp1) ? inp1.val : inp1
}
const blank = {}
const isstrict = {}
const ischaining = {}
function a(inp1, ic, temparr) {
if (ic !== ischaining) {
temparr = []
}
inp1 = noa(inp1)
return new Proxy(
{},
{
set(_obj, _prop, _val) {},
get(_obj, prop) {
if (prop == Symbol.toStringTag) {
warn(Symbol.toStringTag)
return "testing"
}
if (prop == Symbol.iterator) {
switch (a(inp1).gettype().val) {
case "string":
return function* () {
for (var i in inp1.split("")) yield inp1[i]
}
case "number":
return function* () {
for (var i in String(inp1).split("")) yield inp1[i]
}
case "array":
return function* () {
for (var i in inp1) yield inp1[i]
}
case "object":
return function* () {
for (var i in Object.entries(inp1)) yield inp1[i]
}
default:
return function* () {
yield inp1
}
}
}
if (prop == Symbol.toPrimitive) {
return function (hint) {
switch (hint) {
case "number":
if (Number(inp1) != inp1)
error(`"${inp1}" is not a number or is nan`, inp1)
return Number(inp1)
case "string":
if (a(inp1).gettype(["array", "object"]).val)
return JSON.stringify(inp1)
return String(inp1)
case "default":
if (a(inp1).gettype("string").val)
if (String(Number(inp1)) == inp1) return Number(inp1)
else return String(inp1)
if (a(inp1).gettype(["array", "object"]).val)
return JSON.stringify(inp1)
if (a(inp1).gettype(["undefined", "null", "nan"]))
return String(inp1)
}
error(prop, hint)
return hint
}
}
if (typeof prop == "symbol") log(prop)
if (["end", "out", "ret", "done", "value", "val"].includes(prop)) {
if (temparr.length) {
var x = [...temparr]
temparr = []
return x
}
return inp1
}
if (prop == "allfuncs")
return new Proxy(allfuncs, {
set(_a, s) {
throw new Error(
`you can't overwrite property "${s}" on "allfuncs".
if you are trying to add a new function
use allfuncs.new(function_name, function, tags)`
)
},
deleteProperty(_a, s) {
throw new Error(
`you can't delete property "${s}" on "allfuncs".`
)
},
})
if (prop == "push")
return new Proxy(
{},
{
get(_a, s) {
temparr.push(inp1[s])
return a(inp1, ischaining, temparr)
},
}
)
if (prop == "get")
return new Proxy(
{},
{
get(_a, s) {
return a(inp1[s], ischaining, temparr)
},
}
)
if (prop == "set")
return new Proxy(
{},
{
get(_a, s) {
return function (val) {
inp1[s] = val
return a(inp1, ischaining, temparr)
}
},
}
)
if (prop == "run")
return new Proxy(
{},
{
get(_a, s) {
if (s == "same") {
return new Proxy(
{},
{
get(_a, s) {
return function (...args) {
var inp = inp1
inp1[s](...args)
return a(inp, ischaining, temparr)
}
},
}
)
} else
return function (...args) {
return a(inp1[s](...args), ischaining, temparr)
}
},
}
)
const { gettype } = allfuncs
const function_chain = function (...rest) {
if (gettype(allfuncs[prop]) !== "function")
if (!gettype(inp1, ["undefined", "null", "nan"]))
if (gettype(Object.getPrototypeOf(inp1)[prop], "function"))
return a(
Object.getPrototypeOf(inp1)[prop].call(inp1, ...rest)
)
else throw new Error(`"${prop}" is not a function`)
var inps = inp1 === blank ? rest : [inp1, ...rest]
var ret = allfuncs[prop](...inps)
if (
gettype(ret, "array") &&
inp1?.strictargs?.[0] === isstrict &&
ret?.strictargs?.[0] !== isstrict
)
switch (inp1.strictargs[1]) {
case "object":
ret = strictobj(
inp1.strictargs[2],
inp1.strictargs[3],
ret,
inp1.strictargs[5]
)
break
case "array":
ret = strictarr(
inp1.strictargs[2],
inp1.strictargs[3],
ret,
inp1.strictargs[5]
)
break
}
return a(ret)
}
var temp = {}
Object.assign(temp, allfuncs[prop]?.function ?? {})
Object.assign(temp, allfuncs[prop])
Object.keys(temp).forEach((e) => {
let func = temp[e]
function_chain[e] = function (...args) {
return a(func(...args))
}
})
if (gettype(allfuncs[prop], "function"))
function_chain.inputs = getprops(allfuncs[prop])
function_chain.same = function (...args) {
var inp = inp1
a(inp1, ischaining, temparr)[prop](...args)
return a(inp, ischaining, temparr)
}
function_chain.run = function (obj) {
var m = [...function_chain.inputs]
m = m.vars.map((e, i) =>
i == 0
? e.var in obj
? obj[e.var]
: inp1 == blank
? undefined
: inp1
: obj[e.var]
)
var ret = allfuncs[prop](...m)
if (inp1?.strictargs[0] === isstrict)
switch (inp1.strictargs[1]) {
case "object":
ret = strictobj(
inp1.strictargs[2],
inp1.strictargs[3],
ret,
inp1.strictargs[5]
)
break
case "array":
ret = strictarr(
inp1.strictargs[2],
inp1.strictargs[3],
ret,
inp1.strictargs[5]
)
break
}
var shouldret = getprops(allfuncs[prop]).return
if (
shouldret
.split("|")
.find((type) => type == "any" || type == gettype(ret))
)
return a(ret)
throw new Error(
`the function "${prop}" returned a type of "${gettype(
ret
)}",\nwhich doesn't match type of "${shouldret}"`
)
}
return function_chain
},
}
)
}
function expandederror( //error
obj //object
) {
error(obj)
return Error(obj.message)
}
const strictfunction = function (
//any
func, //function|class
name, //string|none
notrequired //boolean|none
) {
if (notrequired) {
if (getprops(func).broken) {
warn("the function is missing type data")
return func
}
} else {
if (getprops(func).broken) {
error(getprops(func))
throw new Error(`the function doesn't have the required type data`)
}
}
var temp = function (...args) {
var vars = getprops(func).vars
if (
vars.filter(
(e) =>
!(
e.type.includes("?") ||
e.type.split("|").includes("none") ||
e.type.split("|").includes("undefined")
)
).length > args.length
) {
error(
`function [${
Object.getPrototypeOf(func).name || name || "unknown"
}] - requires ${
vars.filter((e) => !e.type.includes("?")).length
} arguments but only found ${args.length}`
)
}
vars.length = args.length
vars.map(function (thing, index) {
if (thing.type) {
if (index > args.length - 1) {
if (thing.type.includes("?") || thing.type.includes("none"))
return true
throw expandederror({
message: `function [${
Object.getPrototypeOf(func).name || name || "unknown"
}] - input "${thing.var}" is not optional`,
function_name:
Object.getPrototypeOf(func).name || name || "unknown",
function: func,
values: args,
function_string: String(func),
})
}
if (
thing.type.split("|").includes("array") &&
a(args[index]).gettype("htmlcollection").val
) {
args[index] = [...args[index]]
}
if (
thing.type
.split("|")
.find(
(type) =>
(!!args[index] === true && type == "true") ||
(!!args[index] === false && type == "false") ||
(a(args[index]).gettype(["null", "undefined", "nan"]).val &&
type == "none") ||
type == "any" ||
a(args[index]).gettype(type).val
)
)
return true
else if (
thing.type.split("|").includes("elements") &&
a(args[index]).toelem().gettype("array").val
) {
args[index] = a(args[index]).toelem().val
if (
thing.type.split("|").includes("element") &&
args[index].length === 1
)
args[index] = args[index][0]
return true
} else if (
thing.type.split("|").includes("element") &&
a(args[index]).toelem(true).gettype("element").val
)
args[index] = a(args[index]).toelem(true).val
if (
thing.type.split("|").includes("element") &&
a(args[index]).toelem(true).gettype("element").val
) {
args[index] = a(args[index]).toelem(true).val
return true
} else {
throw expandederror({
message: `function [${
Object.getPrototypeOf(func).name || name || "unknown"
}] - in "${thing.var}", the input of "${
args[index]
}" is a type of "${
a(args[index]).gettype().val
}", which doesn't match required type of "${thing.type}"`,
function_name:
Object.getPrototypeOf(func).name || name || "unknown",
function: func,
function_string: String(func),
})
}
} else return true
})
var shouldret = getprops(func).return
if (a(func).gettype("function").val) {
var ret = func(
...args //...getprops(func).vars.map((_e, index) => args[index])
)
} else {
var ret = new func(...args)
}
// if (args[0]?.strictargs?.[0] === isstrict)
// switch (args[0].strictargs[1]) {
// case "object":
// ret = strictobj(
// args[0].strictargs[2],
// args[0].strictargs[3],
// ret,
// args[0].strictargs[5]
// )
// break
// case "array":
// ret = strictarr(
// args[0].strictargs[2],
// args[0].strictargs[3],
// ret,
// args[0].strictargs[5]
// )
// break
// }
if (
shouldret
.split("|")
.find(
(type) =>
(!!ret === true && type == "true") ||
(!!ret === false && type == "false") ||
(["null", "undefined", "nan"].includes(a(ret).gettype().val) &&
type == "none") ||
type == "any" ||
a(ret).gettype(type).val
)
)
return ret
throw expandederror({
message: `the function [${
Object.getPrototypeOf(func).name || name || "unknown"
}] returned a type of "${
a(ret).gettype().val
}", which doesn't match type of "${shouldret}"`,
function_name: Object.getPrototypeOf(func).name || name || "unknown",
function: func,
function_string: String(func),
})
}
temp.function = func
return temp
}
const getprops = (function () {
var cache = {}
return function (
//array
func //function
) {
var test = String(func).match(/\(([^]*)/)[1]
if (cache[test]) return cache[test]
var arr = []
var x
test = test
.replaceAll(/\\./g, "")
.replaceAll(/`[^]*?(?<!\\)`/g, "")
.replaceAll(/'.*?(?<!\\)'/g, "")
.replaceAll(/".*?(?<!\\)"/g, "")
.replaceAll(/(\/\/).*|\/\*[^]*?\*(?<!\\)\//g, function (e, a) {
arr.push(
a
? e.replace("//", "")
: e.replace(/^\/\*/, "").replace(/\*\/$/, "")
)
return `\u1111${arr.length - 1}\u1111`
})
.replaceAll(/\/.*?(?<!\\)\//g)
var prevtest = test
while (prevtest.match(/(?<![\]})])[{\[(]/)) {
test = prevtest
x = prevtest.match(/(?<![\]})].*?)[{\[(]/)
if (!x) break
var count = 0
var i = 0
var start = x.index
var end = x.index
while (i++ < 40) {
if (/[\[{(]/.test(x[0])) count++
else count--
if (count == 0) break
test = test.slice(x.index + 1)
x = test.match(/[{\[(\])}]/)
end += x.index + 1
}
prevtest = prevtest.slice(0, start) + "<><><>" + prevtest.slice(end + 1)
}
var fualtyreturn = false
var temp = {
return: arr[0],
vars: [
...[
...prevtest
.match(/[^]*?(?=\))/)[0]
.matchAll(
/(?<=(?:,|^)[^=]*)([a-zA-Z_$][\da-zA-Z_$]*)(?:(?:[^](?![a-zA-Z_$][\da-zA-Z_$].*,|,.*[a-zA-Z_$][\da-zA-Z_$]))*?(?:\s*=\s*)?[^\u1111]*\u1111(\d+)\u1111)?/g
),
].map((e, _i) => {
if (e[2] == 0) fualtyreturn = true
return {
var: e[1],
type: arr[e[2]],
}
}),
],
}
if (fualtyreturn) temp.return = undefined
temp.broken = false
if (temp.return == undefined) temp.broken = true
temp.vars.forEach((e) => {
if (e.type === undefined) temp.broken = true
})
// temp.return||='any'
// temp.broken
// temp.vars = temp.vars.map(e=>{return{...e, type:e.type||'any'}})
cache[String(func).match(/\(([^]*)/)[1]] = temp
return temp
}
})()
const allfuncs = {
new(name, func, folder) {
if (this[name]) {
name += Math.random()
error(name)
}
this[name] =
name == "gettype" || name == "toelem"
? func
: strictfunction(func, name, true)
var arr = getprops(func)
arr = [
...arr.vars,
{
return: arr.return,
},
]
if (
arr.map((e) => e.type || e?.return).filter((e) => typeof e !== "string")
.length
)
warn(name)
this[name].help = arr
this[name].function = func
this[name].table = function () {
var x = getprops(this?.function || allfuncs[name].function)
var arr = {}
x.vars.forEach((e) => {
arr = {
...arr,
...{
[e.var]: e.type,
},
}
})
table({
...arr,
broken: x.broken,
return: x.return,
})
}
if (!folder) folder = "unknown"
if (folder.includes("/")) folder = folder.split("/")
else if (typeof folder == "string") folder = [folder]
folder.forEach((folder) => {
if (!this.folders) this.folders = {}
if (!this.folders[folder]) this.folders[folder] = {}
this.folders[folder][name] = func
this.folders[folder][name].help = arr
})
this[name].folders = folder
Object.defineProperty(a, "length", {
//new
//folders
value: Object.keys(allfuncs).length - 2,
})
return this[name]
},
}
class tween {
#from
#to
#time
#delay
#loopondone
#reverseondone
#updatefunc = []
#donefunc = []
#active = 0
#firstfrom
#firstto
constructor(
//object
from, //number
to, //number
time, //number
delay, //number
loopondone, //boolean|none
reverseondone, //boolean|none
ignorefocusloss //boolean|none
) {
if (typeof from == "number") {
this.#from = from
this.#to = to
this.#time = time
this.#delay = delay
this.#loopondone = loopondone
this.#reverseondone = reverseondone
} else if (typeof from == "object") {
a(from).foreach(function (key, value) {
this["#" + key] = value
})
}
this.restart = this.restart
this.onchange = this.onchange
this.ondone = this.ondone
this.#firstfrom = this.#from
this.#firstto = this.#to
const top = this
if (!ignorefocusloss) {
a(window).listen("blur", function () {
if (!top.paused) top.paused = 1
})
a(window).listen("focus", function () {
if (top.paused === 1) top.paused = false
})
}
if (this.#loopondone) this.#reverseondone = false
this.#updatefunc = []
this.#donefunc = []
this.#go()
}
restart() {
this.#from = this.#firstfrom
this.#to = this.#firstto
this.#go()
}
async #go() {
this.#active++
var lastactive = this.#active
var from = this.#from
var to = this.#to
var time = this.#time
var delay = this.#delay || 30
this.out = this.#from
var i = 0
var last = Date.now()
var dt = 0
while (i < time) {
if (lastactive !== this.#active) return
await a(() => !this.paused).waituntil().val
a(() => this.#updatefunc.forEach((e) => e(this.out))).ignore()
last = Date.now()
var lastwait = delay - dt
var dt = await a(lastwait).wait().val
dt = Date.now() - last
i += dt
dt -= lastwait
if (lastactive !== this.#active) return
this.out = a(i).rerange(0, time, from, to).val
}
if (lastactive !== this.#active) return
this.out = to
a(() => this.#updatefunc.forEach((e) => e(this.out))).ignore()
a(() => this.#donefunc.forEach((e) => e())).ignore()
if (lastactive !== this.#active) return
if (this.#reverseondone) {
this.#flip()
this.#go()
}
if (this.#loopondone) this.#go()
}
#flip() {
var x = this.#from
this.#from = this.#to
this.#to = x
}
onchange(func) {
this.#updatefunc.push(func)
}
ondone(func) {
this.#donefunc.push(func)
}
destroy() {
this.#active = null
this.paused = false
this.#updatefunc = undefined
this.#donefunc = undefined
var top = this
a(this).foreach(function (a) {
delete top[a]
})
}
}
allfuncs.new("tween", tween, "time", false)
allfuncs.new(
"foreach",
function (
//none
arr, //array|object|any
func //function
) {
var type = a(arr).gettype().val
if (type == "array") arr.forEach(func)
else if (type == "object") {
Reflect.ownKeys(arr).forEach((e, i) => {
func(e, arr[e], i)
})
} else {
;[arr].forEach(func)
}
},
"array",
true
)
allfuncs.new(
"sendevent",
function (
//element
element, //element
eventName //string
) {
function extend(destination, source) {
for (var property in source) destination[property] = source[property]
return destination
}
var eventMatchers = {
HTMLEvents:
/^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/,
MouseEvents: /^(?:click|dblclick|mouse(?:down|up|over|move|out))$/,
}
var defaultOptions = {
pointerX: 0,
pointerY: 0,
button: 0,
ctrlKey: false,
altKey: false,
shiftKey: false,
metaKey: false,
bubbles: true,
cancelable: true,
}
var options = extend(defaultOptions, arguments[2] || {})
var oEvent,
eventType = null
for (var name in eventMatchers) {
if (eventMatchers[name].test(eventName)) {
eventType = name
break
}
}
if (!eventType)
throw new SyntaxError(
"Only HTMLEvents and MouseEvents interfaces are supported"
)
if (document.createEvent) {
oEvent = document.createEvent(eventType)
if (eventType == "HTMLEvents") {
oEvent.initEvent(eventName, options.bubbles, options.cancelable)
} else {
oEvent.initMouseEvent(
eventName,
options.bubbles,
options.cancelable,
document.defaultView,
options.button,
options.pointerX,
options.pointerY,
options.pointerX,
options.pointerY,
options.ctrlKey,
options.altKey,
options.shiftKey,
options.metaKey,
options.button,
element
)
}
element.dispatchEvent(oEvent)
} else {
options.clientX = options.pointerX
options.clientY = options.pointerY
var evt = document.createEventObject()
oEvent = extend(evt, options)
element.fireEvent("on" + eventName, oEvent)
}
return element
},
"element/event/automation"
)
allfuncs.new(
"ignore",
function (
//any
func, //function
senderr, //boolean|none
...args //any|none
) {
try {
return func(...args)
} catch (e) {
return senderr ? e.message : undefined
}
},
"error",
true
)
allfuncs.new(
"wait",
function (
//promise
ms //number
) {
return new Promise(function (a) {
var last = Date.now()
setTimeout(() => a(Date.now() - last - ms), ms)
})
},
"time",
true
)
allfuncs.new(
"waituntil",
function (
//promise
q, //function
cb //function|none
) {
return new Promise((resolve) => {
var last = Date.now()
// if (!!q()) {
// ignore(() => cb(Date.now() - last))
// return resolve(Date.now() - last)
// }
var int = setInterval(
function (q, cb) {
if (!!q()) {
clearInterval(int)
a(() => cb(Date.now() - last)).ignore()
resolve(Date.now() - last)
}
},
0,
q,
cb
)
})
},
"time",
true
)
allfuncs.new(
"keeponlyone",
function (
//array
arr //array
) {
return [...new Set(arr)]
},
"array",
true
)
allfuncs.new(
"inin",
function (
//any
x, //any
y, //array
z //array
) {
return z[y.indexOf(x)]
},
"array",
true
)
allfuncs.new(
"matchall",
function (
//array|string
x, //string
y //regex
) {
return [...x.matchAll(y)].map((e) => (e[1] !== undefined ? [...e] : e[0]))
},
"regex",
true
)
allfuncs.new(
"matchany",
function (
//boolean
x, //any
...y //any
) {
return y.includes(x)
},
"string",
true
)
allfuncs.new(
"randfrom",
function (
//any
min, //array|number
max //undefined|number
) {
if (max === undefined)
return min.length ? min[a(0).randfrom(min.length - 1).val] : ""
if (min == max) return min
if (max) return Math.round(Math.random() * (max - min)) + min
return min[Math.round(Math.random() * (min.length - 1))]
},
"number/array",
true
)
allfuncs.new(
"unlisten",
function (
//array
data //array
) {
data.forEach((data) => data[0].removeEventListener(data[1], data[2]))
return data
},
"event/elem",
true
)
allfuncs.new(
"listen",
function (
//array
elem, //element
type, //string|object|array
cb, //function|array|boolean|undefined
istrue = false //boolean|undefined
) {
var all = []
if (a(type).gettype("array").val) {
var temp = {}
a(type).foreach((e) => (temp[e] = cb))
type = temp
}
if (a(type).gettype("object").val) {
istrue = cb
a(type).foreach(function (type, cb) {
if (a(type).gettype("string").val)
type = a(type).matchall(/[a-z]+/g).val
type.forEach((type) => {
const newcb = function (...e) {
cb(...e)
}
elem.addEventListener(type, newcb, istrue)
all.push([elem, type, newcb])
})
})
} else if (a(type).gettype("string").val) {
type = a(type).matchall(/[a-z]+/g).val
type.forEach((type) => {
const newcb = function (e) {
cb(e, type)
}
elem.addEventListener(type, newcb, istrue)
all.push([elem, type, newcb])
})
}
return all
},
"event/elem",
true
)
allfuncs.new(
"toelem",
function (
//element|undefined|array
elem, //any
single //boolean|none
) {
if (a(elem).gettype("element").val) return elem
switch (a(elem).gettype().val) {
case "string":
return single ? a(elem).qs().val : a(elem).qsa().val
case "array":
return elem.map((elem) => {
return a(elem).toelem(single).val
})
case "object":
var newobj = {
...elem,
}
if (single)
return {
[Object.keys(newobj)[0]]: a(
newobj[Object.keys(newobj)[0]]
).toelem(single).val,
}
a(newobj).foreach(function (a, s) {
newobj[a] = a(s).toelem().val
})
return newobj
default:
error(elem, "inside [toelem] - not an element?")
return undefined
}
},
"elem",
true
)
allfuncs.new(
"geturlperams",
function (
//object
e = location.href //undefined|string
) {
var arr = {}
;[...e.matchAll(/[?&]([^&\s]+?)(?:=([^&\s]*?))?(?=&|$|\s)/g)].forEach(
(e) => {
if (e[1].includes("#")) arr["#"] = e[1].match(/#(.*$)/)[1]
if (e[2].includes("#")) arr["#"] = e[2].match(/#(.*$)/)[1]
e[1] = e[1].replace(/#.*$/, "")
e[2] = e[2].replace(/#.*$/, "")
arr[decodeURIComponent(e[1]).replaceAll("+", " ")] =
e[2] === undefined
? undefined
: decodeURIComponent(e[2]).replaceAll("+", " ")
}
)
return arr
},
"url",
false
)
allfuncs.new(
"updateurlperam",
function (
//string
key, //string
value, //string|undefined
cangoback //undefined|boolean
) {
var g = {
...a().geturlperams().val,
[key]: value,
}
var k = ""
var hash = ""
a(g).foreach(function (key, value) {
if (key == "#") return (hash = key + value)
key = encodeURIComponent(key)
value = encodeURIComponent(value)
k += "&" + (value === undefined ? key : key + "=" + value)
})
k = k.replace("&", "?")
k += hash
cangoback
? history.pushState(null, null, k)
: history.replaceState(null, null, k)
return key
},
"url",
true
)
allfuncs.new(
"newvarfunc",
function (
//undefined
name, //string
func, //function
obj = window //undefined|object
) {
Object.defineProperty(obj, name, {
configurable: false,
get() {
return func.call({})
},
set(a) {
return func.call(a, a, true)
},
})
},
"var",
true
)
allfuncs.new(
"rerange",
function (
//number
val, //number
low1, //number
high1, //number
low2, //number
high2 //number
) {
return ((val - low1) / (high1 - low1)) * (high2 - low2) + low2
},
"number",
false
)
allfuncs.new(
"destring",
function (
//any
inp //string
) {
var out = inp
if (/^[\-0-9]+$/.test(inp)) return Number(inp)
if (a((out = JSON.parse(inp))).gettype("array").val) return out
if (
a(
(out = JSON.parse(inp.replaceAll("'", '"').replaceAll("`", '"')))
).gettype("object").val
)
return out
if (inp == "true") return true
if (inp == "false") return false
if (inp == "undefined") return undefined
if (inp == "NaN") return NaN
return inp
},
"string/parse",
true
)
allfuncs.new(
"eachelem",
function (
//array
arr1, //array
cb //function
) {
var arr = []
var elem = []
if (a(arr1).gettype("array").val) {
arr1.foreach((e) => {
elem = [
...elem,
...(a(e).gettype("string").val ? a(e).qsa().val : [e]),
]
})
} else {
elem = a(arr1).gettype("string").val ? a(ar1).qsa().val : [arr1]
}
elem = elem.filter((e) => {
return e instanceof Element
})
elem.foreach(function (...a) {
arr.push(cb(...a))
})
if (arr.length == 1) arr = arr[0]
return arr
},
"elem",
true
)
allfuncs.new(
"remove",
function (
//array
arr, //array
idx, //number|any
isidx //boolean|undefined
) {
arr = [...arr]
idx = isidx ? idx : arr.indexOf(idx)
if (idx < 0 || typeof idx !== "number") return arr
arr.splice(idx, 1)
return arr
},
"array",
true
)
allfuncs.new(
"download",
function (
//string|file|blob
data, //string|file|blob
filename = "temp.txt", //string|undefined
type, //string|undefined
isurl //boolean|undefined
) {
var url
if (isurl) {
url = data
} else {
var file = a(data).gettype("string").val
? new Blob([data], {
type,
})
: (data.name ? (filename = data.name) : "", data)
url = URL.createObjectURL(file)
}
a()
.bodyload()
.then(() => {
var link = a(document.body).createelem("a", {
href: url,
download: filename,
}).val
link.click()
link.remove()
if (!isurl) window.URL.revokeObjectURL(url)
})
return data
},
"file",
true
)
allfuncs.new(
"idx",
function (
//array
arr, //array|string
idx //number
) {
return idx >= 0 ? arr[idx] : arr[arr.length + idx]
},
"array",
true
)
allfuncs.new(
"compare",
function (
//boolean
x, //string|any
y //string|any
) {
return x && y
? (typeof x == "string" ? x.toLowerCase() : x) ==
(typeof y == "string" ? y.toLowerCase() : y)
: true
},
"check",
true
)
allfuncs.new(
"createelem",
function (
//element
parent, //element|none
elem, //string
data //object
) {
//if (!parent) warn("no parent set", elem, data)
var type = elem
var issvg = elem == "svg" || parent?.tagName?.toLowerCase?.() == "svg"
// warn(issvg, 'issvg', elem, parent, parent?.tagName)
elem = issvg
? document.createElementNS("http://www.w3.org/2000/svg", elem)
: document.createElement(elem)
if (data.class)
data.class.split(" ").forEach((e) => {
elem.classList.add(e)
})
if (data.options && type == "select")
data.options = data.options.map((e) =>
a(e).gettype("array").val
? a(elem).createelem("option", {
innerHTML: e[0],
value: e[1],
}).val
: a(elem).createelem("option", {
innerHTML: e,
value: e,
}).val
)
if (type == "label" && "for" in data) {
data.htmlFor = data.for
}
Object.assign(elem.style, data)
if (type == "select") {
a(data).foreach(function (a, s) {
elem[a] = s
})
} else if (issvg) {
Object.keys(data).forEach((e) => (elem[e] = data[e]))
} else {
Object.assign(elem, data)
}
if (typeof parent == "string") parent = a(parent).qs().val
a(() => parent.appendChild(elem)).ignore()
return elem
},
"elem",
true
)
allfuncs.new(
"gettype",
function (
//string
thing, //any
match //undefined|string|array
) {
if (
!match ||
(Object.prototype.toString
.call(match)
.toLowerCase()
.match(/^\[[a-z]+ (.+)\]$/)[1] == "string" &&
!match.includes("|"))
) {
var type = Object.prototype.toString
.call(thing)
.toLowerCase()
.match(/^\[[a-z]+ (.+)\]$/)[1]
if (type !== "function") if (type == match) return true
if (match == "normalfunction") return type == "function"
if (type == "htmldocument" && match == "document") return true
if (match == "body" && type == "htmlbodyelement") return true
if (match && new RegExp(`^html${match}element$`).test(type)) return true
if (/^html\w+element$/.test(type)) type = "element"
if (type == "htmldocument") type = "element"
if (type == "asyncfunction") type = "function"
if (type == "generatorfunction") type = "function"
if (type == "regexp") type = "regex"
if (match == "regexp") match = "regex"
if (match == "element" && type == "window") return true
if (match == "element" && type == "shadowroot") return true
if (match == "event" && /\w+event$/.test(type)) return true
if (/^(html|svg).*element$/.test(type)) type = "element"
if (type == "function") {
type = /^\s*class\s/.test(Function.prototype.toString.call(thing))
? "class"
: "function"
}
if (match == "none")
return type == "nan" || type == "undefined" || type == "null"
try {
if (type === "number" && isNaN(thing) && match == "nan") return true
} catch (e) {
error(thing)
}
return match ? match === type : type
} else {
if (match.includes("|")) match = match.split("|")
match = [...new Set(match)]
return match.filter((e) => a(thing).gettype(e).val).length > 0
}
},
"check",
true
)
allfuncs.new(
"waitforelem",
async function (
//promise
selector //string|array
) {
if (a(selector).gettype("string").val) {
selector = [selector]
}
await a().bodyload()
var g = false
return new Promise((resolve) => {
var observer = new MutationObserver(check)
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
characterData: false,
})
check()
function check() {
if (g) return
if (selector.find((selector) => !a(selector).qs().val)) return
observer.disconnect()
resolve(
selector.length == 1
? a(selector[0]).qs().val
: selector.map((e) => a(e).qs().val)
)
}
})
},
"time/elem"
)
allfuncs.new(
"findvar",
function (
//any
obj, //object|element
findkey, //any
objectname = "obj", //string
exact, //boolean
all //boolean
) {
var vvv = []
var allarr = []
var chain = objectname
var arr = []
var arr2 = [
{
chain,
value: obj,
},
]
var visited = []
var i = 0
while (arr2.length && i++ < 800) {
if (
arr2
.map((e) => e.chain)
.join("/")
.includes("." + findkey + (exact ? "/" : ""))
) {
if (all)
vvv.push(
arr2.filter((e) =>
exact
? e.chain.endsWith("." + findkey)
: e.chain.includes("." + findkey)
)
)
else
return arr2.filter((e) =>
exact
? e.chain.endsWith("." + findkey)
: e.chain.includes("." + findkey)
)[0]
}
var oldarr2 = [...arr2]
allarr.push(arr2)
arr2 = []
oldarr2.forEach((e) => {
if (
a(e.value).gettype("object").val ||
a(e.value).gettype("element").val
)
a(e.value).foreach(function (key, value) {
if (a(key).gettype().val !== "string")
return warn(key, a(key).gettype().val)
var newchain = /^[a-z_][_a-z0-9]*$/i.test(key)
? "." + key
: `["${key.replaceAll('"', '\\"')}"]`
arr.push(e.chain + newchain)
if (visited.includes(e.value)) return
arr2.push({
chain: e.chain + newchain,
value,
})
})
visited.push(e.value)
})
}
return vvv.length > 0 ? vvv : allarr
},
"debug",
false
)
allfuncs.new(
"getallvars",
function () {
//object
var obj = {}
var variables = []
for (var name in this)
if (
!`window self document name location customElements history locationbar menubar personalbar scrollbars statusbar toolbar status closed frames length top opener parent frameElement navigator origin external screen innerWidth innerHeight scrollX pageXOffset scrollY pageYOffset visualViewport screenX screenY outerWidth outerHeight devicePixelRatio clientInformation screenLeft screenTop styleMedia onsearch isSecureContext trustedTypes performance onappinstalled onbeforeinstallprompt crypto indexedDB sessionStorage localStorage onbeforexrselect onabort onbeforeinput onblur oncancel oncanplay oncanplaythrough onchange onclick onclose oncontextlost oncontextmenu oncontextrestored oncuechange ondblclick ondrag ondragend ondragenter ondragleave ondragover ondragstart ondrop ondurationchange onemptied onended onerror onfocus onformdata oninput oninvalid onkeydown onkeypress onkeyup onload onloadeddata onloadedmetadata onloadstart onmousedown onmouseenter onmouseleave onmousemove onmouseout onmouseover onmouseup onmousewheel onpause onplay onplaying onprogress onratechange onreset onresize onscroll onsecuritypolicyviolation onseeked onseeking onselect onslotchange onstalled onsubmit onsuspend ontimeupdate ontoggle onvolumechange onwaiting onwebkitanimationend onwebkitanimationiteration onwebkitanimationstart onwebkittransitionend onwheel onauxclick ongotpointercapture onlostpointercapture onpointerdown onpointermove onpointerrawupdate onpointerup onpointercancel onpointerover onpointerout onpointerenter onpointerleave onselectstart onselectionchange onanimationend onanimationiteration onanimationstart ontransitionrun ontransitionstart ontransitionend ontransitioncancel onafterprint onbeforeprint onbeforeunload onhashchange onlanguagechange onmessage onmessageerror onoffline ononline onpagehide onpageshow onpopstate onrejectionhandled onstorage onunhandledrejection onunload crossOriginIsolated scheduler alert atob blur btoa cancelAnimationFrame cancelIdleCallback captureEvents clearInterval clearTimeout close confirm createImageBitmap fetch find focus getComputedStyle getSelection matchMedia moveBy moveTo open postMessage print prompt queueMicrotask releaseEvents reportError requestAnimationFrame requestIdleCallback resizeBy resizeTo scroll scrollBy scrollTo setInterval setTimeout stop structuredClone webkitCancelAnimationFrame webkitRequestAnimationFrame originAgentCluster navigation webkitStorageInfo speechSynthesis oncontentvisibilityautostatechange openDatabase webkitRequestFileSystem webkitResolveLocalFileSystemURL chrome caches cookieStore ondevicemotion ondeviceorientation ondeviceorientationabsolute launchQueue onbeforematch getDigitalGoodsService getScreenDetails queryLocalFonts showDirectoryPicker showOpenFilePicker showSaveFilePicker TEMPORARY PERSISTENT addEventListener dispatchEvent removeEventListener`
.split(" ")
.includes(name)
)
variables.push(name)
variables.forEach((e) => {
var c = String(a(this[e]).gettype().val)
if (c === "object") c = "variable"
if (!obj[c]) obj[c] = []
obj[c].push(e)
})
return obj
},
"debug",
false
)
allfuncs.new(
"newfunc",
function (
//undefined
func1, //string
func2 //function
) {
eval(`var a = ${func1}
var s = ${func2}
${func1} = function (...args) {
a.call(this, ...args)
s(arguments)
}`)
},
"function/jank",
true
)
allfuncs.new(
"findall",
function (
//array
obj, //object
objectname = "obj" //string
) {
var chain = objectname
var arr = []
var arr2 = [
{
chain,
value: obj,
},
]
var visited = []
var i = 0
while (arr2.length && i++ < 800) {
var oldarr2 = [...arr2]
arr2 = []
oldarr2.forEach((e) => {
if (a(e.value).gettype("object").val)
a(e.value).foreach(function (key, value) {
var newchain = /^[_a-z][_a-z0-9]*$/i.test(key)
? "." + key
: `["${key.replaceAll('"', '\\"')}"]`
arr.push(e.chain + newchain)
if (visited.includes(e.value)) return
log({
key,
value,
chain: e.chain + newchain,
})
arr2.push({
chain: e.chain + newchain,
value,
})
})
visited.push(e.value)
})
}
return visited
},
"debug",
true
)
allfuncs.new(
"sha",
function (
//string
s = "", //string
includesymbols //boolean|string
) {
var tab
if (typeof includesymbols == "string") {
tab = includesymbols
} else if (includesymbols) {
tab =
"`~\\|[];',./{}:<>?\"!@#$%^&*ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
} else {
tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
}
return binb2b64(core_sha1(str2binb(s), s.length * 8))
function core_sha1(x, len) {
x[len >> 5] |= 0x80 << (24 - len)
x[(((len + 64) >> 9) << 4) + 15] = len
var w = Array(80)
var a = 1732584193
var b = -271733879
var c = -1732584194
var d = 271733878
var e = -1009589776
for (var i = 0; i < x.length; i += 16) {
var olda = a
var oldb = b
var oldc = c
var oldd = d
var olde = e
for (var j = 0; j < 80; j++) {
if (j < 16) w[j] = x[i + j]
else w[j] = rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1)
var t = safe_add(
safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
safe_add(safe_add(e, w[j]), sha1_kt(j))
)
e = d
d = c
c = rol(b, 30)
b = a
a = t
}
a = safe_add(a, olda)
b = safe_add(b, oldb)
c = safe_add(c, oldc)
d = safe_add(d, oldd)
e = safe_add(e, olde)
}
return Array(a, b, c, d, e)
}
function sha1_ft(t, b, c, d) {
if (t < 20) return (b & c) | (~b & d)
if (t < 40) return b ^ c ^ d
if (t < 60) return (b & c) | (b & d) | (c & d)
return b ^ c ^ d
}
function sha1_kt(t) {
return t < 20
? 1518500249
: t < 40
? 1859775393
: t < 60
? -1894007588
: -899497514
}
function safe_add(x, y) {
var lsw = (x & 0xffff) + (y & 0xffff)
var msw = (x >> 16) + (y >> 16) + (lsw >> 16)
return (msw << 16) | (lsw & 0xffff)
}
function rol(num, cnt) {
return (num << cnt) | (num >>> (32 - cnt))
}
function str2binb(str) {
var bin = Array()
var mask = (1 << 8) - 1
for (var i = 0; i < str.length * 8; i += 8)
bin[i >> 5] |= (str.charCodeAt(i / 8) & mask) << (24 - i)
return bin
}
function binb2b64(binarray) {
var str = ""
for (var i = 0; i < binarray.length * 4; i += 3) {
var triplet =
(((binarray[i >> 2] >> (8 * (3 - (i % 4)))) & 0xff) << 16) |
(((binarray[(i + 1) >> 2] >> (8 * (3 - ((i + 1) % 4)))) & 0xff) <<
8) |
((binarray[(i + 2) >> 2] >> (8 * (3 - ((i + 2) % 4)))) & 0xff)
for (var j = 0; j < 4; j++) {
if (i * 8 + j * 6 > binarray.length * 32) str += ""
else str += tab.charAt((triplet >> (6 * (3 - j))) & 0x3f)
}
}
return str
}
},
"code",
true
)
allfuncs.new(
"qs",
function (
//element|none
text, //string
parent = document //element|none
) {
return parent.querySelector(text)
},
"elem",
true
)
allfuncs.new(
"qsa",
function (
//array
text, //string
parent = document //element|none
) {
return Array.from(parent.querySelectorAll(text))
},
"elem",
true
)
allfuncs.new(
"csspath",
function (
//string|array
el //elements|element
) {
if (a(el).gettype("array").val)
return a(el).map((e) => a(e).csspath().val)
if (!(el instanceof Element)) return
var path = []
while (el.nodeType === Node.ELEMENT_NODE) {
var selector = el.nodeName.toLowerCase()
if (el.id) {
selector += "#" + el.id
path.unshift(selector)
break
} else {
var sib = el,
nth = 1
while ((sib = sib.previousElementSibling)) {
if (sib.nodeName.toLowerCase() == selector) nth++
}
if (nth != 1) selector += ":nth-of-type(" + nth + ")"
}
path.unshift(selector)
el = el.parentNode
}
return path.join(" > ")
},
"elem",
true
)
allfuncs.new(
"fromms",
function (
//object
ms //number
) {
//returns a unix timestamp as an object where "ms" is the unixtimestamp
ms = Number(ms)
return {
years: Math.floor(ms / 1000 / 60 / 60 / 24 / 365),
days: Math.floor(ms / 1000 / 60 / 60 / 24) % 365,
hours: Math.floor(ms / 1000 / 60 / 60) % 24,
mins: Math.floor(ms / 1000 / 60) % 60,
secs: Math.floor(ms / 1000) % 60,
ms: Math.floor(ms) % 1000,
}
},
"time",
true
)
allfuncs.new(
"toms",
function (
//number
{ ms = 0, secs = 0, mins = 0, hours = 0, days = 0, years = 0 } //object
) {
return (
ms +
secs * 1000 +
mins * 60000 +
hours * 3600000 +
days * 86400000 +
years * 31560000000
)
},
"time",
true
)
allfuncs.new(
"rect",
function (
//object
e //element
) {
if (a(e).gettype("string").val) e = a(e).qs().val
var { x, y, width, height } = e.getBoundingClientRect().toJSON()
return {
x,
y,
w: width,
h: height,
}
},
"elem",
true
)
allfuncs.new(
"setelem",
function (
//element
elem, //element
data //object
) {
var issvg = elem == "svg" || parent?.tagName?.toLowerCase?.() == "svg"
// warn(issvg, 'issvg', elem, parent, parent?.tagName)
if (data.class)
data.class.split(" ").forEach((e) => {
elem.classList.add(e)
})
if (data.options && elem.tagName.toLowerCase() == "select")
data.options = data.options.map((e) =>
a(e).gettype("array").val
? a(elem).createelem("option", {
innerHTML: e[0],
value: e[1],
}).val
: a(elem).createelem("option", {
innerHTML: e,
value: e,
}).val
)
if (elem.tagName.toLowerCase() == "label" && "for" in data) {
data.htmlFor = data.for
}
Object.assign(elem.style, data)
if (elem.tagName.toLowerCase() == "select") {
a(data).foreach(function (a, s) {
elem[a] = s
})
} else if (issvg) {
Object.keys(data).forEach((e) => (elem[e] = data[e]))
} else {
Object.assign(elem, data)
}
return elem
},
"elem",
true
)
allfuncs.new(
"watchvar",
function (
//undefined
varname, //string
onset, //function
onget, //function|none
obj = window //object|window
) {
//creates a new var and runs "onset" on the change of "varname", and "onget" when "varname" is read
obj = obj || window
obj[`_${varname}`] = undefined
obj[`${varname}`] = undefined
Object.defineProperty(obj, varname, {
configurable: false,
get() {
if (onget) return onget(obj[`_${varname}`])
return obj[`_${varname}`]
},
set(value) {
if (value === obj[`_${value}`]) {
return
}
var s = onset(value, obj[`_${varname}`])
if (s) obj[`_${varname}`] = value
},
})
},
"var/debug",
true
)
allfuncs.new(
"randomizeorder",
function (
//array
arr //array
) {
arr = [...arr]
var arr2 = []
var count = arr.length
for (var i = 0; i < count; i++) {
var idx = randfrom(0, arr.length - 1)
arr2.push(arr[idx])
arr.splice(idx, 1)
}
return arr2
},
"array",
true
)
allfuncs.new(
"constrainvar",
function (
//undefined
varname, //string
min, //number
max //number
) {
//creates a new var that can't go beyond the bounds of "min" and "max"
window[`_${varname}`] = undefined
window[`${varname}`] = undefined
Object.defineProperty(window, varname, {
configurable: false,
get() {
return window[`_${varname}`]
},
set(value) {
if (value === window[`_${varname}`]) {
return
}
if (value > max) value = max
if (value < min) value = min
window[`_${varname}`] = value
},
})
},
"var",
true
)
allfuncs.new(
"isbetween",
function (
//boolean
z, //number
x, //number
c //number
) {
//returns true if "z" is between "x" and "c"
if (x == c) return false
var big, small
if (x > c) {
big = x
small = c
} else {
big = c
small = x
return z > big && z < small
}
},
"check",
true
)
allfuncs.new(
"indexsof",
function (
//array
y, //string
x //string
) {
var i = 0
var arr = []
y.split(x).forEach((e, k) => {
i += e.length
arr.push(i + k)
})
arr.pop()
return arr
},
"array",
true
)
allfuncs.new(
"export",
function () {
//string
//saves the data of text inputs and checkboxes
var s = []
a("input, textarea")
.qsa()
.foreach((e) => {
s.push({
path: a(e).csspath().val,
value: escape(e.value),
checked: e.checked,
})
})
return JSON.stringify(s)
},
"data",
false
)
allfuncs.new(
"import",
function (
//string
data //string
) {
//loads the data of text inputs and checkboxes
data.forEach((e) => {
var s = a(e.path).qs().val
s.checked = e.checked
s.value = unescape(e.value)
})
return data
},
"data",
true
)
allfuncs.new(
"popup",
function (
//window
data, //string
x, //number|none
y, //number|none
w, //number|none
h //number|none
) {
//creates a popup window
if (x || x === 0) {
x = (screen.width / 100) * x
y = (screen.height / 100) * y
w = (screen.width / 100) * w
h = (screen.height / 100) * h
var win = open("", "", `left=${x}, top=${y} width=${w},height=${h}`)
win.document.write(data)
return win
} else {
var win = open("")
win.document.write(data)
return win
}
},
"window",
true
)
allfuncs.new(
"same",
function (
//boolean
...a //any
) {
if (a.length == 1) a = a[0]
return [...new Set(a.map((e) => JSON.stringify(e)))].length === 1
},
"check",
true
)
allfuncs.new(
"containsany",
function (
//boolean
arr1, //array|string
arr2 //array
) {
return !!arr2.find((e) => arr1.includes(e))
},
"array"
)
allfuncs.new(
"run",
function (
//any
func, //function
obj //object
) {
return func(...getprops(func).vars.map((e) => obj[e.var]))
},
"function",
true
)
allfuncs.new(
"getprops",
function (
//array|object
func, //function
peramsonly /*?|boolean*/
) {
return peramsonly
? getprops(func)
.vars.map((e) => e.var)
.filter((e) => e)
: getprops(func)
},
"function/parse",
true
)
allfuncs.new(
"bodyload",
function () {
//promise
return new Promise((resolve) => {
if (document.body) resolve()
const int = setInterval(() => {
if (document.body) resolve(clearInterval(int))
})
})
},
"elem/time",
false
)
;(async function () {
const { bodyload } = allfuncs
await bodyload()
// var optionselem = loadlib("addnewoption", "optionselem")
// delete localStorage.buttonsheight
// delete localStorage.buttonswidth
// delete localStorage.buttonsx
// delete localStorage.buttonsy
if (!localStorage.buttonsheight) localStorage.buttonsheight = "100px"
if (!localStorage.buttonswidth) localStorage.buttonswidth = "120px"
var c = document.body
if (!window.optionselem) {
c = a(c)
.createelem("div", {
position: "fixed",
top: (Number(localStorage.buttonsy) || 10) + "px",
left:
(Number(localStorage.buttonsx) ||
Number(localStorage.buttonswidth.match(/[0-9]+/)[0]) / 2) + "px",
width: 0,
height: 0,
zIndex: 999999999999999,
pointerEvents: "all",
backgroundColor: "#0000",
})
.val.attachShadow({
mode: "closed",
})
window.optionselem = a(c).createelem("div", {
overflow: "hidden",
position: "fixed",
top:
constrain(
(Number(localStorage.buttonsy) || 10, 0 + 50 / 2),
innerHeight - this.clientHeight / 2
) + "px",
left:
constrain(
localStorage.buttonswidth,
0 + this.clientWidth / 2,
innerWidth - this.clientWidth / 2
) + "px",
zIndex: 999999999999999,
height: "20px",
pointerEvents: "all",
backgroundColor: "#0f09",
test(e) {
if (!this.moving && e) return
if (!e) {
this.style.translate = "0 0"
e = {
clientX: this.getBoundingClientRect().toJSON().x,
clientY: this.getBoundingClientRect().toJSON().y,
}
}
// this.style.translate = "-50% -50%"
this.style.top =
constrain(e.clientY - 10, 0, innerHeight - this.clientHeight) + "px"
this.style.left =
constrain(
e.clientX - this.clientWidth / 2,
0,
innerWidth - this.clientWidth
) + "px"
localStorage.buttonsx = e.clientX
localStorage.buttonsy = e.clientY
},
onmouseup() {
this.moving = false
},
}).val
optionselem.style.left =
constrain(
Number(localStorage.buttonswidth) || 0,
0 + optionselem.clientWidth / 2,
innerWidth - optionselem.clientWidth / 2
) + "px"
optionselem.style.top =
constrain(
Number(localStorage.buttonsy) || 10,
0 + 50 / 2,
innerHeight - optionselem.clientHeight / 2
) + "px"
var ismain
try {
ismain = window?.parent?.location?.href === location.href
} catch (e) {
ismain = false
}
a(window.optionselem).createelem("div", {
backgroundColor: ismain ? "#00f" : "#f00",
width: "100%",
height: "20px",
oncontextmenu(e) {
e.preventDefault()
log(window.optionselem)
if (window.optionselem.style.height === "20px")
window.optionselem.style.height = "auto"
else window.optionselem.style.height = "20px"
},
onmousedown(e) {
e.preventDefault()
if (e.which == 3 || e.button == 2) return
window.optionselem.moving = true
},
onmouseup() {
window.optionselem.moving = false
},
})
}
function constrain(inp, max, min) {
if (min > max) {
var c = min
min = max
max = c
}
return Math.min(max, Math.max(min, inp))
}
a(window).listen({
resize() {
window.optionselem.moving = false
optionselem.test.call(optionselem)
},
blur() {
window.optionselem.moving = false
},
focus() {
window.optionselem.moving = false
},
mousemove(e) {
optionselem.test.call(optionselem, e)
},
})
function addnewoption( //undefined
...z //object|undefined
) {
var zz = z[0]
// trymatch(zz.host, location.host)
// trymatch(zz.href, location.n)
// trymatch(zz.hostname, location.n)
// trymatch(zz.origin, location.n)
// trymatch(zz.pathname, location.n)
var s = a(optionselem).createelem("div", {
textAlign: "center",
width: localStorage.buttonswidth,
minHeight: localStorage.buttonsheight,
backgroundColor: zz.backgroundColor || "#0000",
}).val
a(s).createelem("p", {
innerHTML: zz.title || " ",
textAlign: "center",
color: zz.titlecolor,
})
;[...z].forEach((z, i) => {
if (i === 0) return
var elem
switch (z.type) {
case "button":
elem = a(s).createelem("button", {
id: z.id,
itemnumber: i,
index: i,
innerHTML: z.text,
onclick: z.onclick,
textAlign: "center",
}).val
break
case "toggle":
elem = a(s).createelem("input", {
id: z.id,
itemnumber: i,
index: i,
type: "checkbox",
onclick(e) {
if (this.checked) z.onon?.call?.(this, e)
else z.onoff?.call?.(this, e)
z.onclick?.call?.(this, e)
},
}).val
break
case "select":
var x = a(s).createelem("select", {
id: z.id,
options: z.options,
index: i,
itemnumber: i,
value: z.value,
onchange: z.onchange,
}).val
elem = x
break
case "input":
elem = a(s).createelem("input", {
id: z.id,
itemnumber: i,
index: i,
width: "90%",
value: z.value,
placeholder: z.placeholder,
onchange(e) {
z.onchange.call(this, e)
},
}).val
break
case "p":
elem = a(s).createelem("p", {
id: z.id,
innerHTML: z.text,
}).val
break
case "br":
elem = a(s).createelem("br", {}).val
break
default:
error(`type not found: "${z.type}"`)
}
if (z.id) window[z.id] = elem
})
}
// addnewoption({ title: "asddssa" }, { type: "button" })
allfuncs.new("addnewoption", addnewoption, "elem", true)
})()
allfuncs.new(
"replacealltext",
function (
//string|regex
pattern, //string|regex
string, //string
element = document.body //element|none
) {
;[
element,
...element.querySelectorAll("*:not(script):not(noscript):not(style)"),
].forEach(({ childNodes: [...nodes] }) =>
nodes
.filter(({ nodeType }) => nodeType === Node.TEXT_NODE)
.forEach(
(textNode) =>
(textNode.textContent = textNode.textContent.replaceAll(
pattern,
string
))
)
)
return pattern
},
"string",
true
)
allfuncs.new(
"repeat",
function (
//promise|undefined
func, //function
count, //number
delay, //number|none
instantstart, //boolean|none
waituntildone //boolean|none
) {
if (delay || waituntildone)
return new Promise(async (resolve) => {
if (delay) {
var extra = 0
for (var i = 0; i < count; i++) {
if (instantstart) waituntildone ? await func(i) : func(i)
extra = await a(delay - extra).wait().val
if (!instantstart) waituntildone ? await func(i) : func(i)
}
resolve()
} else
for (var i = 0; i < count; i++)
waituntildone ? await func(i) : func(i)
resolve()
})
for (var i = 0; i < count; i++) func(i)
return
},
"repeat",
true
)
allfuncs.new(
"repeatuntil",
function (
//promise
func, //function
donecheck, //function
delay, //number|none
instantstart, //boolean|none
waituntildone //boolean|none
) {
return new Promise(async (resolve) => {
if (delay) {
var extra = 0
var i = 0
while (!donecheck()) {
i++
if (instantstart) {
waituntildone ? await func(i) : func(i)
}
extra = await a(delay - extra).wait().val
if (!instantstart) {
waituntildone ? await func(i) : func(i)
}
}
resolve()
} else {
var i = 0
while (!donecheck()) {
i++
waituntildone ? await func(i) : func(i)
}
resolve()
}
})
},
"repeat",
true
)
// ;(async function () {
// const { bodyload } = allfuncs
// await bodyload()
// const listeners = []
// a(document).listen({
// dragover(e) {
// e.stopPropagation()
// e.preventDefault()
// },
// drop(e) {
// e.stopPropagation()
// e.preventDefault()
// var files = [...e.dataTransfer.files]
// listeners.forEach((y) => y[0](y[1] ? files[0] : files))
// },
// })
// allfuncs.new(
// "newdrop",
// function (
// //undefined
// func, //function
// onlyone //boolean
// ) {
// listeners.push([func, onlyone])
// },
// "file"
// )
// })()
;(async () => {
const drops = []
await a().bodyload()
a(document.body).listen({
dragover(e) {
e.preventDefault()
},
async drop(e) {
e.preventDefault()
drops.forEach(async ({ types, multi, func, elem }) => {
if (elem) if (e.target !== elem) return
if (multi) var ret = []
for (const item of e.dataTransfer.items) {
if (item.kind == "file") {
if (types.includes("file") || types.includes("directory")) {
const entry = await item.getAsFileSystemHandle()
if (entry.kind === "file" && types.includes("file")) {
if (!multi) return func(entry, e)
ret.push(entry)
} else if (
entry.kind === "directory" &&
types.includes("directory")
) {
if (!multi) return func(entry, e)
ret.push(entry)
}
}
}
}
if (multi && ret.length) return func(ret, e)
})
},
})
allfuncs.new(
"ondrop",
function (
//object
obj //object
) {
if (!obj.types) obj.types = "all"
obj.types = a(obj.types).toarray().val
if (!obj.func) throw new Error('object is missing "func"')
var oldelem = obj.elem
if (obj.elem) obj.elem = a(obj.elem).toelem(true).val
if (obj.elem && !a(obj.elem).gettype("element").val)
throw new Error(`elem is not an elem, ${oldelem} -> ${obj.elem}`)
drops.push(obj)
return obj
},
"file"
)
})()
allfuncs.new(
"getfolderpath",
async function (
//promise
folder //filesystemdirectoryhandle
) {
async function parsedir(dir, x) {
if (!x) {
return [
{
name: dir.name,
inside: await parsedir(dir, true),
type: "folder",
handle: dir,
},
]
} else var arr = []
for await (const [name, handle] of dir.entries()) {
arr.push(
a(handle).gettype("filesystemdirectoryhandle").val
? {
type: "folder",
inside: await parsedir(handle, true),
name,
handle,
}
: { type: "file", handle, name }
)
}
return arr
}
return parsedir(folder)
},
"file",
false
)
allfuncs.new(
"getfiles",
async function (
//promise
oldway, //boolean|none
multiple, //boolean|none
accept = [], //array|string|none
options = {} //object|undefined
) {
const supportsFileSystemAccess =
"showOpenFilePicker" in window &&
(() => {
try {
return window.self === window.top
} catch {
return false
}
})()
if (!oldway) {
if (!supportsFileSystemAccess) throw new Error("no access")
let fileOrFiles = undefined
try {
const handles = await showOpenFilePicker({
types: [
{
accept: {
"*/*": accept,
},
},
],
multiple,
...options,
})
if (!multiple) {
fileOrFiles = handles[0]
} else {
fileOrFiles = await Promise.all(handles)
}
} catch (err) {
if (err.name !== "AbortError") {
error(err.name, err.message)
}
}
return fileOrFiles
}
return new Promise(async (resolve) => {
await a().bodyload().val
const input = document.createElement("input")
input.style.display = "none"
input.type = "file"
if (accept) input.accept = accept
document.body.append(input)
if (multiple) {
input.multiple = true
}
input.addEventListener("change", () => {
input.remove()
// if (!input.files) {
// return
// }
resolve(multiple ? Array.from(input.files) : input.files[0])
})
if ("showPicker" in HTMLInputElement.prototype) {
input.showPicker()
} else {
input.click()
}
})
},
"file",
true
)
allfuncs.new(
"map",
function (
//array|object
arr, //array|object|any
func //function
) {
var type = a(arr).gettype().val
if (type == "array") return arr.map(func)
else if (type == "object") {
var temparr = {}
Reflect.ownKeys(arr).forEach((e, i) => {
temparr = {
...temparr,
...func(e, arr[e], i),
}
})
return temparr
} else {
return [arr].map(func)
}
},
"array",
true
)
allfuncs.new(
"find",
function (
//any
arr, //array|object|any
func //function
) {
var type = a(arr).gettype().val
if (type == "array") return arr.find(func)
else if (type == "object") {
return Reflect.ownKeys(arr).find((e, i) => {
return func(e, arr[e], i)
})
} else {
return [arr].find(func)
}
},
"array",
true
)
allfuncs.new(
"filteridx",
function (
//array
arr, //array|any
func //function
) {
if (a(arr).gettype("object").val) arr = [arr]
return a(arr)
.map((e, i) => (func(e, i) ? i : undefined))
.filter((e) => e !== undefined)
},
"array"
)
allfuncs.new(
"filter",
function (
//array|object
arr, //array|object|any
func //function
) {
var type = a(arr).gettype().val
if (type == "array") return arr.filter(func)
else if (type == "object") {
var temparr = {}
Reflect.ownKeys(arr).forEach((e, i) => {
if (func(e, arr[e], i))
temparr = {
...temparr,
[e]: arr[e],
}
})
return temparr
} else {
return [arr].filter(func)
}
},
"array",
true
)
;(function () {
var last
var different = allfuncs.new(
"unique",
function () /*object*/ {
return last || (last = different.new())
},
"check",
false
)
different.new = function (name) {
var $ = new Proxy(
{},
{
get(_a, s) {
return s == "name" ? name || "different" : $
},
set() {
return $
},
}
)
return (last = $)
}
})()
allfuncs.new(
"elif",
function (
//any
cond, //any
iftrue, //any
iffalse //any
) {
return cond ? iftrue : iffalse
},
"check",
true
)
allfuncs.new(
"tonumber",
function (
//number
e //any
) {
return Number(e)
},
"number/format",
true
)
allfuncs.new(
"toarray",
function (
//array
e, //any
split //string|none|undefined
) {
if (a(e).gettype("string").val) {
if (split) e = e.split(split)
else return [e]
}
return [...e]
},
"number/format",
true
)
allfuncs.new(
"tostring",
function (
//string
e //any
) {
if (["object", "array"].includes(a(e).gettype().val))
return JSON.stringify(e)
if (a(e).gettype("element").val) return a(e).csspath().val
return String(e)
},
"string/format",
true
)
allfuncs.new(
"eval",
function (
//any
a //any
) {
return eval(a)
},
"js/eval",
true
)
allfuncs.new(
"toregex",
function (
//regex
d, //string|array|regex
s //undefined|string
) {
if (a(d).gettype("array").val) var temp = d
if (s) var temp = [d, s]
else if (String(d).match(/^\/(.*)\/(\w*)$/)) {
var m = String(d).match(/^\/(.*)\/(\w*)$/)
var temp = [m[1], m[2]]
} else var temp = [String(d), ""]
temp[1] = temp[1].toLowerCase()
if (temp[1].includes("w")) {
temp[1] = temp[1].replace("w", "")
temp[0] = `(?<=[^a-z0-9]|^)${temp[0]}(?=[^a-z0-9]|$)`
}
return new RegExp(temp[0], temp[1].replaceAll(/(.)(?=.*\1)/g, ""))
},
"regex",
true
)
allfuncs.new(
"isregex",
function (
//boolean
s //string|regex
) {
if (a(s).gettype("regex").val) return true
return /^\/.*(?<!\\)\/[gimusy]*$/.test(s) && !/^\/\*.*\*\/$/.test(s)
},
"check",
true
)
allfuncs.new(
"ispressed",
function (
//boolean
e /*event*/,
code //string
) {
code = code.toLowerCase()
var temp =
e.shiftKey == code.includes("shift") &&
e.altKey == code.includes("alt") &&
e.ctrlKey == code.includes("ctrl") &&
e.metaKey == code.includes("meta") &&
e.key.toLowerCase() ==
code.replaceAll(/alt|ctrl|shift|meta/g, "").trim()
if (temp && !a) e.preventDefault()
return temp
},
"check/input/event",
true
)
allfuncs.new(
"controller_vibrate",
function (
//number
pad, //number
duration = 1000, //number|none
strongMagnitude = 0, //number|none
weakMagnitude = 0 //number|none
) {
getpad(pad).vibrationActuator.playEffect("dual-rumble", {
duration,
strongMagnitude,
weakMagnitude,
})
return pad
},
"controller/haptic",
true
)
allfuncs.new(
"controller_getbutton",
function (
//number
pad, //number
button //number|none
) {
return button
? getpad(pad).buttons[button].value
: getpad(pad).buttons.map((e) => e.value)
},
"controller/input",
true
)
allfuncs.new(
"controller_getaxes",
function (
//array|number
pad, //number
axes //number|none
) {
return axes ? getpad(pad).axes[axes] : getpad(pad).axes
},
"controller/input",
true
)
allfuncs.new(
"controller_exists",
function (
//boolean|number
pad //number|none
) {
return pad === undefined
? getpad().filter((e) => e).length
: !!getpad(pad)
},
"controller/check",
true
)
allfuncs.new(
"runall",
function (
//array|function
funcs, //array|function
args //array|any
) {
if (!a(args).gettype("array").val) args = [args]
if (!a(funcs).gettype("array").val) funcs = [funcs]
funcs.map((func) => func(...args))
return funcs
},
"function"
)
allfuncs.new(
"readfile",
async function (
//promise
file, //file
type = "Text" //string|none
) {
return new Promise(function (done, error) {
var f = new FileReader()
f.onerror = error
f.onload = () => done(type == "json" ? JSON.parse(f.result) : f.result)
f["readAs" + (type == "json" ? "Text" : type)](file)
})
},
"file"
)
allfuncs.new(
"writefile",
async function writefile(
//promise
file, //filesystemfilehandle
text //string
) {
var f = await await file.createWritable()
await f.write(text)
await f.close()
return file
},
"file"
)
allfuncs.new(
"getfileperms",
async function (
//promise
fileHandle, //filesystemfilehandle
readWrite //boolean|none
) {
const options = {}
if (readWrite) {
options.mode = "readwrite"
}
return (
(await fileHandle.queryPermission(options)) === "granted" ||
(await fileHandle.requestPermission(options)) === "granted"
)
},
"file/permission",
true
)
allfuncs.new(
"indexeddb_set",
async function (
//promise
place, //object
obj //object
) {
return new Promise((done, error) =>
place.put(
obj,
(e) => done(e),
(e) => error(e)
)
)
},
"indexeddb",
true
)
allfuncs.new(
"indexeddb_get",
async function (
//promise
place, //object
obj //string
) {
return new Promise((done, error) =>
place.get(
obj,
(e) => done(e),
(e) => error(e)
)
)
},
"indexeddb",
true
)
allfuncs.new(
"indexeddb_getall",
async function (
//promise
place //object
) {
return new Promise((done, error) =>
place.getAll(
(e) => done(e),
(e) => error(e)
)
)
},
"indexeddb",
true
)
allfuncs.new(
"indexeddb_clearall",
async function (
//promise
place //object
) {
return new Promise((done, error) =>
place.clear(
(e) => done(e),
(e) => error(e)
)
)
},
"indexeddb",
true
)
allfuncs.new(
"indexeddb_remove",
async function (
//promise
place, //object
obj //string|number
) {
return new Promise((done, error) =>
place.remove(
obj,
(e) => done(e),
(e) => error(e)
)
)
},
"indexeddb",
true
)
allfuncs.new(
"indexeddb_setup",
async function (
//promise
obj //object|none
) {
return new Promise((e) => {
var x
obj = {
...{
dbVersion: 1,
storeName: "tempstorename",
keyPath: "id",
autoIncrement: true,
},
...obj,
onStoreReady() {
e(x)
},
}
if (!window.IDBStore) {
//IDBStore start
;(function (p, h, k) {
"function" === typeof define
? define(h)
: "undefined" !== typeof module && module.exports
? (module.exports = h())
: (k[p] = h())
})(
"IDBStore",
function () {
function p(a, b) {
var c, d
for (c in b) (d = b[c]), d !== u[c] && d !== a[c] && (a[c] = d)
return a
}
var h = function (a) {
throw a
},
k = function () {},
r = {
storeName: "Store",
storePrefix: "IDBWrapper-",
dbVersion: 1,
keyPath: "id",
autoIncrement: !0,
onStoreReady: function () {},
onError: h,
indexes: [],
implementationPreference: [
"indexedDB",
"webkitIndexedDB",
"mozIndexedDB",
"shimIndexedDB",
],
},
q = function (a, b) {
"undefined" == typeof b && "function" == typeof a && (b = a)
"[object Object]" != Object.prototype.toString.call(a) &&
(a = {})
for (var c in r)
this[c] = "undefined" != typeof a[c] ? a[c] : r[c]
this.dbName = this.storePrefix + this.storeName
this.dbVersion = parseInt(this.dbVersion, 10) || 1
b && (this.onStoreReady = b)
var d = "object" == typeof window ? window : self
this.implementation = this.implementationPreference.filter(
function (a) {
return a in d
}
)[0]
this.idb = d[this.implementation]
this.keyRange =
d.IDBKeyRange || d.webkitIDBKeyRange || d.mozIDBKeyRange
this.consts = {
READ_ONLY: "readonly",
READ_WRITE: "readwrite",
VERSION_CHANGE: "versionchange",
NEXT: "next",
NEXT_NO_DUPLICATE: "nextunique",
PREV: "prev",
PREV_NO_DUPLICATE: "prevunique",
}
this.openDB()
},
t = {
constructor: q,
version: "1.7.2",
db: null,
dbName: null,
dbVersion: null,
store: null,
storeName: null,
storePrefix: null,
keyPath: null,
autoIncrement: null,
indexes: null,
implementationPreference: null,
implementation: "",
onStoreReady: null,
onError: null,
_insertIdCount: 0,
openDB: function () {
var a = this.idb.open(this.dbName, this.dbVersion),
b = !1
a.onerror = function (a) {
var b
b =
"error" in a.target
? "VersionError" == a.target.error.name
: "errorCode" in a.target
? 12 == a.target.errorCode
: !1
if (b)
this.onError(
Error(
"The version number provided is lower than the existing one."
)
)
else
a.target.error
? (a = a.target.error)
: ((b =
"IndexedDB unknown error occurred when opening DB " +
this.dbName +
" version " +
this.dbVersion),
"errorCode" in a.target &&
(b += " with error code " + a.target.errorCode),
(a = Error(b))),
this.onError(a)
}.bind(this)
a.onsuccess = function (a) {
if (!b)
if (this.db) this.onStoreReady()
else if (
((this.db = a.target.result),
"string" == typeof this.db.version)
)
this.onError(
Error(
"The IndexedDB implementation in this browser is outdated. Please upgrade your browser."
)
)
else if (
this.db.objectStoreNames.contains(this.storeName)
) {
this.store = this.db
.transaction(
[this.storeName],
this.consts.READ_ONLY
)
.objectStore(this.storeName)
var d = Array.prototype.slice.call(
this.getIndexList()
)
this.indexes.forEach(function (a) {
var c = a.name
if (c)
if (
(this.normalizeIndexData(a), this.hasIndex(c))
) {
var g = this.store.index(c)
this.indexComplies(g, a) ||
((b = !0),
this.onError(
Error(
'Cannot modify index "' +
c +
'" for current version. Please bump version number to ' +
(this.dbVersion + 1) +
"."
)
))
d.splice(d.indexOf(c), 1)
} else
(b = !0),
this.onError(
Error(
'Cannot create new index "' +
c +
'" for current version. Please bump version number to ' +
(this.dbVersion + 1) +
"."
)
)
else
(b = !0),
this.onError(
Error(
"Cannot create index: No index name given."
)
)
}, this)
d.length &&
((b = !0),
this.onError(
Error(
'Cannot delete index(es) "' +
d.toString() +
'" for current version. Please bump version number to ' +
(this.dbVersion + 1) +
"."
)
))
b || this.onStoreReady()
} else
this.onError(
Error("Object store couldn't be created.")
)
}.bind(this)
a.onupgradeneeded = function (a) {
this.db = a.target.result
this.db.objectStoreNames.contains(this.storeName)
? (this.store = a.target.transaction.objectStore(
this.storeName
))
: ((a = { autoIncrement: this.autoIncrement }),
null !== this.keyPath && (a.keyPath = this.keyPath),
(this.store = this.db.createObjectStore(
this.storeName,
a
)))
var d = Array.prototype.slice.call(this.getIndexList())
this.indexes.forEach(function (a) {
var c = a.name
c ||
((b = !0),
this.onError(
Error("Cannot create index: No index name given.")
))
this.normalizeIndexData(a)
if (this.hasIndex(c)) {
var g = this.store.index(c)
this.indexComplies(g, a) ||
(this.store.deleteIndex(c),
this.store.createIndex(c, a.keyPath, {
unique: a.unique,
multiEntry: a.multiEntry,
}))
d.splice(d.indexOf(c), 1)
} else
this.store.createIndex(c, a.keyPath, {
unique: a.unique,
multiEntry: a.multiEntry,
})
}, this)
d.length &&
d.forEach(function (a) {
this.store.deleteIndex(a)
}, this)
}.bind(this)
},
deleteDatabase: function (a, b) {
if (this.idb.deleteDatabase) {
this.db.close()
var c = this.idb.deleteDatabase(this.dbName)
c.onsuccess = a
c.onerror = b
} else
b(
Error(
"Browser does not support IndexedDB deleteDatabase!"
)
)
},
put: function (a, b, c, d) {
null !== this.keyPath && ((d = c), (c = b), (b = a))
d || (d = h)
c || (c = k)
var f = !1,
e = null,
g = this.db.transaction(
[this.storeName],
this.consts.READ_WRITE
)
g.oncomplete = function () {
;(f ? c : d)(e)
}
g.onabort = d
g.onerror = d
null !== this.keyPath
? (this._addIdPropertyIfNeeded(b),
(a = g.objectStore(this.storeName).put(
(() => {
function isFilesystemHandle(obj) {
// Check if the object is a FilesystemFileHandle or FilesystemDirectoryHandle
return (
obj &&
(obj instanceof FileSystemFileHandle ||
obj instanceof FileSystemDirectoryHandle)
)
}
function replaceProxies(obj) {
if (isFilesystemHandle(obj)) {
return obj // Skip replacing FilesystemFileHandle and FilesystemDirectoryHandle
}
if (typeof obj !== "object" || obj === null) {
return obj
}
if (Array.isArray(obj)) {
return obj.map((item) => replaceProxies(item))
}
const result = {}
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = replaceProxies(obj[key])
}
}
return result
}
// warn("ghadsgjasdjh", b, replaceProxies(b))
// throw ""
return replaceProxies(b)
})()
)))
: (a = g.objectStore(this.storeName).put(b, a))
a.onsuccess = function (a) {
f = !0
e = a.target.result
}
a.onerror = d
return g
},
get: function (a, b, c) {
c || (c = h)
b || (b = k)
var d = !1,
f = null,
e = this.db.transaction(
[this.storeName],
this.consts.READ_ONLY
)
e.oncomplete = function () {
;(d ? b : c)(f)
}
e.onabort = c
e.onerror = c
a = e.objectStore(this.storeName).get(a)
a.onsuccess = function (a) {
d = !0
f = a.target.result
}
a.onerror = c
return e
},
remove: function (a, b, c) {
c || (c = h)
b || (b = k)
var d = !1,
f = null,
e = this.db.transaction(
[this.storeName],
this.consts.READ_WRITE
)
e.oncomplete = function () {
;(d ? b : c)(f)
}
e.onabort = c
e.onerror = c
a = e.objectStore(this.storeName)["delete"](a)
a.onsuccess = function (a) {
d = !0
f = a.target.result
}
a.onerror = c
return e
},
batch: function (a, b, c) {
c || (c = h)
b || (b = k)
if ("[object Array]" != Object.prototype.toString.call(a))
c(Error("dataArray argument must be of type Array."))
else if (0 === a.length) return b(!0)
var d = a.length,
f = !1,
e = !1,
g = this.db.transaction(
[this.storeName],
this.consts.READ_WRITE
)
g.oncomplete = function () {
;(e ? b : c)(e)
}
g.onabort = c
g.onerror = c
var l = function () {
d--
0 !== d || f || (e = f = !0)
}
a.forEach(function (a) {
var b = a.type,
d = a.key,
e = a.value
a = function (a) {
g.abort()
f || ((f = !0), c(a, b, d))
}
"remove" == b
? ((e = g.objectStore(this.storeName)["delete"](d)),
(e.onsuccess = l),
(e.onerror = a))
: "put" == b &&
(null !== this.keyPath
? (this._addIdPropertyIfNeeded(e),
(e = g.objectStore(this.storeName).put(e)))
: (e = g.objectStore(this.storeName).put(e, d)),
(e.onsuccess = l),
(e.onerror = a))
}, this)
return g
},
putBatch: function (a, b, c) {
a = a.map(function (a) {
return { type: "put", value: a }
})
return this.batch(a, b, c)
},
upsertBatch: function (a, b, c, d) {
"function" == typeof b && ((d = c = b), (b = {}))
d || (d = h)
c || (c = k)
b || (b = {})
"[object Array]" != Object.prototype.toString.call(a) &&
d(Error("dataArray argument must be of type Array."))
var f = b.keyField || this.keyPath,
e = a.length,
g = !1,
l = !1,
n = 0,
m = this.db.transaction(
[this.storeName],
this.consts.READ_WRITE
)
m.oncomplete = function () {
l ? c(a) : d(!1)
}
m.onabort = d
m.onerror = d
var v = function (b) {
a[n++][f] = b.target.result
e--
0 !== e || g || (l = g = !0)
}
a.forEach(function (a) {
var b = a.key
null !== this.keyPath
? (this._addIdPropertyIfNeeded(a),
(a = m.objectStore(this.storeName).put(a)))
: (a = m.objectStore(this.storeName).put(a, b))
a.onsuccess = v
a.onerror = function (a) {
m.abort()
g || ((g = !0), d(a))
}
}, this)
return m
},
removeBatch: function (a, b, c) {
a = a.map(function (a) {
return { type: "remove", key: a }
})
return this.batch(a, b, c)
},
getBatch: function (a, b, c, d) {
c || (c = h)
b || (b = k)
d || (d = "sparse")
if ("[object Array]" != Object.prototype.toString.call(a))
c(Error("keyArray argument must be of type Array."))
else if (0 === a.length) return b([])
var f = [],
e = a.length,
g = !1,
l = null,
n = this.db.transaction(
[this.storeName],
this.consts.READ_ONLY
)
n.oncomplete = function () {
;(g ? b : c)(l)
}
n.onabort = c
n.onerror = c
var m = function (a) {
a.target.result || "dense" == d
? f.push(a.target.result)
: "sparse" == d && f.length++
e--
0 === e && ((g = !0), (l = f))
}
a.forEach(function (a) {
a = n.objectStore(this.storeName).get(a)
a.onsuccess = m
a.onerror = function (a) {
l = a
c(a)
n.abort()
}
}, this)
return n
},
getAll: function (a, b) {
b || (b = h)
a || (a = k)
var c = this.db.transaction(
[this.storeName],
this.consts.READ_ONLY
),
d = c.objectStore(this.storeName)
d.getAll
? this._getAllNative(c, d, a, b)
: this._getAllCursor(c, d, a, b)
return c
},
_getAllNative: function (a, b, c, d) {
var f = !1,
e = null
a.oncomplete = function () {
;(f ? c : d)(e)
}
a.onabort = d
a.onerror = d
a = b.getAll()
a.onsuccess = function (a) {
f = !0
e = a.target.result
}
a.onerror = d
},
_getAllCursor: function (a, b, c, d) {
var f = [],
e = !1,
g = null
a.oncomplete = function () {
;(e ? c : d)(g)
}
a.onabort = d
a.onerror = d
a = b.openCursor()
a.onsuccess = function (a) {
;(a = a.target.result)
? (f.push(a.value), a["continue"]())
: ((e = !0), (g = f))
}
a.onError = d
},
clear: function (a, b) {
b || (b = h)
a || (a = k)
var c = !1,
d = null,
f = this.db.transaction(
[this.storeName],
this.consts.READ_WRITE
)
f.oncomplete = function () {
;(c ? a : b)(d)
}
f.onabort = b
f.onerror = b
var e = f.objectStore(this.storeName).clear()
e.onsuccess = function (a) {
c = !0
d = a.target.result
}
e.onerror = b
return f
},
_addIdPropertyIfNeeded: function (a) {
"undefined" == typeof a[this.keyPath] &&
(a[this.keyPath] = this._insertIdCount++ + Date.now())
},
getIndexList: function () {
return this.store.indexNames
},
hasIndex: function (a) {
return this.store.indexNames.contains(a)
},
normalizeIndexData: function (a) {
a.keyPath = a.keyPath || a.name
a.unique = !!a.unique
a.multiEntry = !!a.multiEntry
},
indexComplies: function (a, b) {
return ["keyPath", "unique", "multiEntry"].every(function (
c
) {
if ("multiEntry" == c && void 0 === a[c] && !1 === b[c])
return !0
if (
"keyPath" == c &&
"[object Array]" == Object.prototype.toString.call(b[c])
) {
c = b.keyPath
var d = a.keyPath
if ("string" == typeof d) return c.toString() == d
if (
("function" != typeof d.contains &&
"function" != typeof d.indexOf) ||
d.length !== c.length
)
return !1
for (var f = 0, e = c.length; f < e; f++)
if (
!(
(d.contains && d.contains(c[f])) ||
d.indexOf(-1 !== c[f])
)
)
return !1
return !0
}
return b[c] == a[c]
})
},
iterate: function (a, b) {
b = p(
{
index: null,
order: "ASC",
autoContinue: !0,
filterDuplicates: !1,
keyRange: null,
writeAccess: !1,
onEnd: null,
onError: h,
limit: Infinity,
offset: 0,
allowItemRejection: !1,
},
b || {}
)
var c = "desc" == b.order.toLowerCase() ? "PREV" : "NEXT"
b.filterDuplicates && (c += "_NO_DUPLICATE")
var d = !1,
f = this.db.transaction(
[this.storeName],
this.consts[b.writeAccess ? "READ_WRITE" : "READ_ONLY"]
),
e = f.objectStore(this.storeName)
b.index && (e = e.index(b.index))
var g = 0
f.oncomplete = function () {
if (d)
if (b.onEnd) b.onEnd()
else a(null)
else b.onError(null)
}
f.onabort = b.onError
f.onerror = b.onError
c = e.openCursor(b.keyRange, this.consts[c])
c.onerror = b.onError
c.onsuccess = function (c) {
if ((c = c.target.result))
if (b.offset) c.advance(b.offset), (b.offset = 0)
else {
var e = a(c.value, c, f)
;(b.allowItemRejection && !1 === e) || g++
if (b.autoContinue)
if (g + b.offset < b.limit) c["continue"]()
else d = !0
}
else d = !0
}
return f
},
query: function (a, b) {
var c = [],
d = 0
b = b || {}
b.autoContinue = !0
b.writeAccess = !1
b.allowItemRejection = !!b.filter
b.onEnd = function () {
a(c, d)
}
return this.iterate(function (a) {
d++
var e = b.filter ? b.filter(a) : !0
!1 !== e && c.push(a)
return e
}, b)
},
count: function (a, b) {
b = p({ index: null, keyRange: null }, b || {})
var c = b.onError || h,
d = !1,
f = null,
e = this.db.transaction(
[this.storeName],
this.consts.READ_ONLY
)
e.oncomplete = function () {
;(d ? a : c)(f)
}
e.onabort = c
e.onerror = c
var g = e.objectStore(this.storeName)
b.index && (g = g.index(b.index))
g = g.count(b.keyRange)
g.onsuccess = function (a) {
d = !0
f = a.target.result
}
g.onError = c
return e
},
makeKeyRange: function (a) {
var b = "undefined" != typeof a.lower,
c = "undefined" != typeof a.upper,
d = "undefined" != typeof a.only
switch (!0) {
case d:
a = this.keyRange.only(a.only)
break
case b && c:
a = this.keyRange.bound(
a.lower,
a.upper,
a.excludeLower,
a.excludeUpper
)
break
case b:
a = this.keyRange.lowerBound(a.lower, a.excludeLower)
break
case c:
a = this.keyRange.upperBound(a.upper, a.excludeUpper)
break
default:
throw Error(
'Cannot create KeyRange. Provide one or both of "lower" or "upper" value, or an "only" value.'
)
}
return a
},
},
u = {}
q.prototype = t
q.version = t.version
return q
},
this
)
//IDBStore end
}
x = new IDBStore(obj)
})
},
"indexeddb",
true
)
allfuncs.new(
"keepsame",
function (
//object|any
thing //object|element
) {
var all = []
var x = new Proxy(thing, {
get(_obj, prop) {
if (prop == "val") return _obj
if (prop == "all") return all
if (prop == "func")
return function (e) {
all.push(e(thing))
return x
}
return function (...args) {
try {
all.push(thing[prop](thing, ...args))
} catch (e) {
all.push(thing[prop])
}
return x
}
},
})
return x
},
"function",
true
)
allfuncs.new("strictfunction", strictfunction, "function/typescript", true)
allfuncs.new(
"readfileslow",
function (
//undefined
file, //file
type = "Text", //string|undefined
cb1 = (e) => e, //function|undefined
cb2 = (e) => e //function|undefined
) {
var fileSize = file.size
var chunkSize = 64 * 1024 * 50 // bytes
var offset = 0
var chunkReaderBlock = null
var arr = []
var lastidx
var readEventHandler = function (evt, idx) {
if (evt.target.error == null) {
arr.push([idx, evt.target.result])
cb1(a(arr.length).rerange(0, lastidx, 0, 100).val)
if (arr.length === lastidx)
cb2(arr.sort((e) => e[0]).map((e) => e[1]))
} else {
return error("Read error: " + evt.target.error)
}
}
chunkReaderBlock = function (_offset, length, _file, idx) {
var r = new FileReader()
var blob = _file.slice(_offset, length + _offset)
const zzz = idx + 1
r.onload = function (e) {
readEventHandler(e, zzz - 1)
}
r["readAs" + type](blob)
}
let idx = 0
while (offset < fileSize) {
idx++
chunkReaderBlock(offset, chunkSize, file, idx)
offset += chunkSize
}
lastidx = idx
},
"file"
)
allfuncs.new(
"cbtoasync",
function (
//promise
func, //function
...args //any
) {
return new Promise(function (resolve) {
func(...args, resolve)
})
},
"function"
)
allfuncs.new(
"asynctocb",
function (
//undefined
func, //function
...args //any
) {
var cb = args.pop()
return func(...args).then(cb)
},
"function"
)
// ;(function () {
// const samerand = function () //string
// {
// return (
// lastrand ||
// (lastrand = samerand.new(20, {
// lower: true,
// upper: true,
// }))
// )
// }
// allfuncs.new("samerand", samerand, "function/random", false)
// var lastrand = ""
// samerand.new = (
// e = 20,
// { lower = true, upper = false, number = false, symbol = false } = {
// lower: true,
// upper: false,
// number: false,
// symbol: false,
// }
// ) => (
// (lastrand = ""),
// a(
// () =>
// (lastrand += a(
// `${lower ? "asdfghjklzxcvbnmqwertyuiop" : ""}${
// upper ? "ASDFGHJKLQWERTYUIOPZXCVBNM" : ""
// }${number ? "0123456789" : ""}${
// symbol ? ",./;'[]-=\\`~!@#$%^&*()_+|{}:\"<>?" : ""
// }`.split("")
// ).randfrom().val)
// ).repeat(e),
// lastrand
// )
// })()
allfuncs.new(
"randstr",
function (
/*string|input of object:
{
lower = true, //boolean|undefined
upper = false, //boolean|undefined
number = false, //boolean|undefined
symbol = false, //boolean|undefined
length = 20, //number|undefined
}
*/
{
lower = true,
upper = false,
number = false,
symbol = false,
length = 20,
} = {
lower: true,
upper: false,
number: false,
symbol: false,
length: 20,
}
) {
var rand = ""
a(() => {
rand += a(
`${lower ? "asdfghjklzxcvbnmqwertyuiop" : ""}${
upper ? "ASDFGHJKLQWERTYUIOPZXCVBNM" : ""
}${number ? "0123456789" : ""}${
symbol ? ",./;'[]-=\\`~!@#$%^&*()_+|{}:\"<>?" : ""
}`.split("")
).randfrom().val
}).repeat(length)
return rand
},
"random/string"
)
allfuncs.new(
"toplaces",
function (
//string
num, //number|string
pre, //number|none
post = 0, //number|undefined
func = Math.round //function
) {
num = String(num).split(".")
if (num.length == 1) num.push("")
if (pre !== undefined) {
num[0] = num[0].substring(num[0].length - pre, num[0].length)
while (num[0].length < pre) num[0] = "0" + num[0]
}
var temp = num[1].substring(post, post + 1) ?? 0
num[1] = num[1].substring(0, post)
while (num[1].length < post) num[1] += "0"
if (post > 0) {
temp = func(num[1].at(-1) + "." + temp)
num[1] = num[1].split("")
num[1].pop()
num[1].push(temp)
num[1] = num[1].join("")
num = num.join(".")
} else num = num[0]
return num
},
"number/format",
true
)
allfuncs.new(
"forcenumlength",
function (
//string
string, //string
lengths //array|number|object
) {
var i = -1
if (a(lengths).gettype("object").val) {
lengths = lengths[[...string.matchAll(/\d+(?:\.\d+)?/g)].length]
}
if (!lengths) {
log(string)
debugger
}
return string.replaceAll(/\d+(?:\.\d+)?/g, function (v) {
i++
try {
return a(lengths[i]).gettype("array").val
? a(Number(v)).toplaces(lengths[i][0], lengths[i][1]).val
: a(Number(v)).toplaces(lengths[i], 0).val
} catch (e) {
log(string, lengths, i)
debugger
}
})
},
"number/format",
true
)
;(function () {
var lasttime = Date.now()
allfuncs.new(
"tick",
function () {
//number
var time = Date.now() - lasttime
lasttime = Date.now()
return time
},
"time"
)
})()
allfuncs.new("expandederror", expandederror, "error", true)
allfuncs.new(
"fetch",
async function (
//promise
url, //string
type = "text", //string|none
...args //any|undefined
) {
return await (await fetch(url, ...args))[type]()
},
"url/web"
)
allfuncs.new(
"copy",
function (
//string
text //string
) {
navigator.clipboard.writeText(text)
return ""
try {
var temp = a(document.body)
.createelem("textarea", {
value: text,
width: 0,
height: 0,
position: "fixed",
top: 0,
left: 0,
})
.run.same.focus()
.run.same.select()
document.execCommand("copy")
temp.run.remove()
} catch (e) {
navigator.clipboard.writeText(text)
}
return text
},
"clipboard"
)
// allfuncs.new(
// "cache",
// (function () {
// var cac = {}
// function cache( //any
// args, //arguments|any
// data, //function
// notfoundincache //function|undefined
// ) {
// // if (a(args).gettype(["array", "arguments"]).val)
// // args = [...args].join("\u1111")
// args = JSON.stringify(args)
// var c = String(arguments.callee.caller).replaceAll(/\s\s+/g, " ").trim()
// // log(structuredClone(cac))
// if (!cac[c]) cac[c] = {}
// if (args in cac[c]) return cac[c][args]
// cac[c][args] = data()
// if (notfoundincache) notfoundincache(cac[c][args])
// return cac[c][args]
// }
// cache.getall = function () {
// return cac
// }
// cache.setall = function (e) {
// return (cac = e)
// }
// cache.add = function (e) {
// return (cac = { ...cac, ...e })
// }
// cache.clear = function () {
// cac = {}
// }
// return cache
// })(),
// "data/storage"
// )
Object.keys(console).forEach((e) =>
allfuncs.new(
e,
(/*undefined*/ ...z /*any*/) => console[e](...z),
"console/debug"
)
)
allfuncs.new(
"replaceall",
function (
//string
text, //string
regex, //regex|string|array
replacewith //string|function
) {
return text.replaceAll(
a(String(a(regex).toregex().val) + "g").toregex().val,
replacewith
)
},
""
)
allfuncs.new(
"setrange",
function (
//number
num, //number
min, //number
max //number
) {
return num < min ? min : num > max ? max : num
},
"number"
)
allfuncs.new(
"isstrict",
function (
//boolean
thing //array|object
) {
return thing?.strictargs?.[0] === isstrict
},
"typescript"
)
allfuncs.new(
"runonalltext",
function (
//undefined
func, //function
ignoretags = ["STYLE", "SCRIPT", "NOSCRIPT"] //array|undefined
) {
// log(String(func))
a("*").qsa().foreach(repl)
watch(document.documentElement)
function watch(elem) {
new MutationObserver((e) => {
if (location.href.includes("scratch.mit.edu/projects")) return
;[...e].forEach((e) => repl(e.target))
// ;[...e].forEach((e) => [...e.addedNodes].forEach(repl))
}).observe(elem, {
childList: true,
subtree: true,
attributes: true,
characterData: false,
})
}
function repl(node) {
if (node.shadowRoot) {
a("*").qsa(node.shadowRoot).foreach(repl)
watch(node.shadowRoot)
return repl(node.shadowRoot)
}
if (ignoretags.includes(node.tagName)) return
var nodes = node?.childNodes
if (!nodes) return
for (var i = 0, m = nodes.length; i < m; i++) {
var n = nodes[i]
// if (n.textContent.includes("Jul 17, 2021")) log(n, n.textContent)
if (n.nodeType == n.TEXT_NODE) {
func(n)
} else {
repl(n)
}
}
}
},
"text/elem"
)
allfuncs.new(
"runonallelems",
function runonallelems(
//undefined
func, //function
selector = "*", //string|undefined
ignoretags = [] //array|undefined
) {
let timeout
const observer = new MutationObserver((mutations) => {
clearTimeout(timeout)
timeout = setTimeout(() => {
for (const mutation of mutations) {
repl(mutation.target)
}
}, 100) // debounce mutations for 100ms
})
observer.observe(document.documentElement, {
childList: true,
subtree: true,
attributes: true,
characterData: true,
})
function repl(elem) {
if (elem.nodeType === 1) {
// Check if elem is an element node
if (elem.shadowRoot) {
repl(elem.shadowRoot)
const shadowRootElems = elem.shadowRoot.querySelectorAll(selector)
for (const elem of shadowRootElems) {
if (!ignoretags.includes(elem.tagName.toLowerCase())) {
func(elem)
}
}
}
const elems = elem.querySelectorAll(selector)
for (const elem of elems) {
if (!ignoretags.includes(elem.tagName.toLowerCase())) {
func(elem)
}
}
}
}
},
"elem"
)
allfuncs.new(
"say",
async function (
//promise
text, //string
vol = 100,
speed = 3
) {
debugger
speechSynthesis.cancel()
speechSynthesis.speak(
a(new SpeechSynthesisUtterance())
.set.text(text + " ")
.set.volume(a(vol).rerange(0, 100, 0, 1).val)
.set.rate(3)
// .set.voice(speechSynthesis.getVoices().find(e=>e.name==
// "Chrome OS UK English 7"))
.set.lang("en").val
)
await a((e) => speechSynthesis.speaking).waituntil()
await a((e) => !speechSynthesis.speaking).waituntil()
return undefined
}
)
savelib("allfuncs", a)
function extras() {
;(() => {
if (!window.showDirectoryPicker) return
if (!window.showOpenFilePicker) return
if (!window.showSaveFilePicker) return
const old = {
showDirectoryPicker: showDirectoryPicker.bind(window),
showOpenFilePicker: showOpenFilePicker.bind(window),
showSaveFilePicker: showSaveFilePicker.bind(window),
}
showDirectoryPicker = a(function (
//promise
obj = false //object|boolean|undefined
) {
if (obj === true) {
obj = { mode: "readwrite" }
} else if (obj === false) {
obj = { mode: "read" }
}
return old.showDirectoryPicker(obj)
}).strictfunction("showDirectoryPicker").val
showOpenFilePicker = a(async function (
//promise
obj = {}, //object|undefined
write, //boolean|undefined
multiple, //boolean|undefined
types, //array|undefined
exts, //array|string|undefined
excludeAcceptAllOption = false //boolean|undefined
) {
if (obj.types && !types) {
types = obj.types
delete obj.types
}
if (obj.exts && !exts) {
exts = obj.exts
delete obj.exts
}
if (excludeAcceptAllOption) obj.excludeAcceptAllOption = true
if (obj.name) obj.suggestedName = obj.name
if (multiple !== undefined) {
obj.multiple = multiple
delete obj.name
}
if (exts) {
obj.types = {
accept: {
"*/*": exts,
},
}
}
if (types) {
if (!obj.type) obj.type = { accept: {} }
types.forEach((type) => (obj.type.accept[type] = ["*"]))
}
if (obj.multiple) return await old.showOpenFilePicker(obj)
var x = await old.showOpenFilePicker(obj)
x = x[0] ?? x
if (obj.mode == "readwrite" || write)
if ((await x.requestPermission({ mode: "readwrite" })) !== "granted")
throw new Error("user didn't grant write permission")
return x
}).strictfunction("showOpenFilePicker").val
showSaveFilePicker = a(function (
//promise
obj = {}, //object|none|string
multiple = false, //boolean|none
types, //array|none
exts, //array|string|none
excludeAcceptAllOption = false //boolean|undefined
) {
if (typeof obj == "string") obj = { suggestedName: obj }
if (obj.types && !types) {
types = obj.types
delete obj.types
}
if (obj.exts && !exts) {
exts = obj.exts
delete obj.exts
}
if (excludeAcceptAllOption) obj.excludeAcceptAllOption = true
if (obj.name) obj.suggestedName = obj.name
if (multiple !== undefined) {
obj.multiple = multiple
delete obj.name
}
if (exts) {
obj.types = {
accept: {
"*/*": exts,
},
}
}
if (types) {
if (!obj.type) obj.type = { accept: {} }
types.forEach((type) => (obj.type.accept[type] = ["*"]))
}
return old.showSaveFilePicker(obj)
}).strictfunction("showSaveFilePicker").val
})()
}
extras()
await loadlib("libloader").waitforlib("scratch")
;(() => {
const vm = loadlib("scratch").vm
allfuncs.new(
"scratch_gettarget",
function (
//object
sprite //string|none
) {
if (sprite) var x = vm.runtime.getSpriteTargetByName(sprite)
else var x = vm.runtime.getTargetForStage()
x.getvar = x.lookupVariableByNameAndType
return x
},
"scratch",
true
)
allfuncs.new(
"scratch_sendbroadcast",
function (
//string
data //string
) {
vm.runtime.startHats("event_whenbroadcastreceived", {
BROADCAST_OPTION: data,
})
return data
},
"scratch",
true
)
allfuncs.new(
"scratch_canvas",
function () {
//element
return (
window?.vm?.runtime?.renderer?.canvas ||
a(
"#app > div > div.gui_body-wrapper_-N0sA.box_box_2jjDp > div > div.gui_stage-and-target-wrapper_69KBf.box_box_2jjDp > div.stage-wrapper_stage-wrapper_2bejr.box_box_2jjDp > div.stage-wrapper_stage-canvas-wrapper_3ewmd.box_box_2jjDp > div > div.stage_stage_1fD7k.box_box_2jjDp > div:nth-child(1) > canvas"
).qs().val ||
a(
"#view > div > div.inner > div:nth-child(2) > div.guiPlayer > div.stage-wrapper_stage-wrapper_2bejr.box_box_2jjDp > div.stage-wrapper_stage-canvas-wrapper_3ewmd.box_box_2jjDp > div > div.stage_stage_1fD7k.box_box_2jjDp > div:nth-child(1) > canvas"
).qs().val ||
a(
"#app > div > div > div > div.gui_body-wrapper_-N0sA.box_box_2jjDp > div > div.gui_stage-and-target-wrapper_69KBf.box_box_2jjDp > div.stage-wrapper_stage-wrapper_2bejr.box_box_2jjDp > div.stage-wrapper_stage-canvas-wrapper_3ewmd.box_box_2jjDp > div > div.stage_stage_1fD7k.box_box_2jjDp > div:nth-child(1) > canvas"
).qs().val
)
},
"scratch",
false
)
allfuncs.new(
"scratch_press",
function (
//string
key //string
) {
if (key == " ") key = "space"
if (/^[a-z]$/.test(key)) key = key.toUpperCase()
var index = vm.runtime.ioDevices.keyboard._keysPressed.indexOf(key)
if (index !== -1) {
vm.runtime.ioDevices.keyboard._keysPressed.splice(index, 1)
}
vm.runtime.ioDevices.keyboard._keysPressed.push(key)
vm.runtime.startHats("event_whenkeypressed", {
KEY_OPTION: key,
})
vm.runtime.startHats("event_whenkeypressed", {
KEY_OPTION: "any",
})
return key
},
"scratch"
)
allfuncs.new(
"scratch_unpress",
function (
//undefined
key //string
) {
if (key == " ") key = "space"
if (/^[a-z]$/.test(key)) key = key.toUpperCase()
var index = vm.runtime.ioDevices.keyboard._keysPressed.indexOf(key)
if (index !== -1) {
vm.runtime.ioDevices.keyboard._keysPressed.splice(index, 1)
}
},
"scratch"
)
allfuncs.new(
"scratch_getallkeys",
function () {
var m = vm.runtime
var f = {
bools: m.targets
.map((e) => {
return {
name: e.sprite.name,
blocks: Object.values(e.blocks._blocks)
.filter((e) => e.opcode === "sensing_keypressed")
.map((e) => e.inputs.KEY_OPTION.block),
otherblocks: e.blocks._blocks,
}
})
.filter((e) => e.blocks.length)
.map((e) => {
return {
name: e.name,
value: [
...new Set(
e.blocks
.map((y) => e.otherblocks[y])
.map(
(e) =>
e.fields?.KEY_OPTION?.value ||
e.fields?.VALUE?.value ||
error(e)
)
),
],
}
}),
hats: m.targets
.map((e) => {
return {
name: e.name,
blocks: Object.values(e.blocks)
.filter((e) => e.opcode === "event_whenkeypressed")
.map((e) => e.fields.KEY_OPTION.value),
}
})
.filter((e) => e.blocks.length),
}
f.all = [
...f.hats.map((e) => e.blocks).flat(),
...f.bools.map((e) => e.value).flat(),
]
f.all = [...new Set(f.all)]
return f
},
"scratch",
false
)
})()
//log(...Object.keys( allfuncs).map(e=>[e, allfuncs[e].help, allfuncs[e]]||warn(e)))
})()