mirror of
https://github.com/SwingTheVine/Wplace-BlueMarble.git
synced 2026-03-11 17:15:38 +00:00
Added Wiki for documentation
This commit is contained in:
parent
dbacfb9985
commit
3e51e35b25
49 changed files with 23846 additions and 59 deletions
|
|
@ -78,7 +78,7 @@ body:
|
|||
id: system-information
|
||||
attributes:
|
||||
label: System Information
|
||||
description: "Please fill out these details about your OS, Blue Marble version, and what website browser you use."
|
||||
description: "Please fill out these details about your OS, Blue Marble version, and what website browser you use. Please fill this out!"
|
||||
placeholder: |
|
||||
OS: (E.g. Windows)
|
||||
Blue Marble Version: 3.346.0
|
||||
|
|
|
|||
|
|
@ -24,6 +24,18 @@ const isGitHub = !!process.env?.GITHUB_ACTIONS; // Is this running in a GitHub A
|
|||
|
||||
console.log(`${consoleStyle.BLUE}Starting build...${consoleStyle.RESET}`);
|
||||
|
||||
// Tries to build the wiki if build.js is run in a GitHub Workflow
|
||||
if (isGitHub) {
|
||||
try {
|
||||
console.log(`Generating JSDoc...`);
|
||||
execSync(`npx jsdoc src/ -r -d wiki`, { stdio: "inherit" });
|
||||
console.log(`JSDoc built ${consoleStyle.GREEN}successfully${consoleStyle.RESET}`);
|
||||
} catch (error) {
|
||||
console.error(`${consoleStyle.RED + consoleStyle.BOLD}Failed to generate JSDoc${consoleStyle.RESET}:`, error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Tries to bump the version
|
||||
try {
|
||||
const update = execSync('node build/update-version.js', { stdio: 'inherit' });
|
||||
|
|
|
|||
4
dist/BlueMarble.user.js
vendored
4
dist/BlueMarble.user.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -51,6 +51,8 @@
|
|||
<a href="https://github.com/SwingTheVine/Wplace-BlueMarble/blob/main/LICENSE.txt" target="_blank" rel="noopener noreferrer"><img alt="Software License: MPL-2.0" src="https://img.shields.io/badge/Software_License-MPL--2.0-slateblue?style=flat"></a>
|
||||
<p>
|
||||
Thank you for wanting to contribute to the userscript "Blue Marble"! It means a lot to me that someone likes my project enough to want to help it grow. If you haven't already done so, consider joining our Discord. You can ask questions about the userscript there and receive feedback.
|
||||
<br>
|
||||
<b>Note</b>: If you are using AI, and you want to tell the AI how the codebase files are related to each-other, go to the <code>Class diagram of relationships for Blue Marble</code> diagram in the chart section of this file. Copy the chart, and give it to the AI.
|
||||
</p>
|
||||
|
||||
<h2>Summary</h2>
|
||||
|
|
|
|||
|
|
@ -24,6 +24,6 @@ The favicon "Blue Marble" is owned by NASA
|
|||
Special Thanks:
|
||||
* nof, [darkness](https://github.com/TouchedByDarkness) for creating similar userscripts!
|
||||
* [BullStein](https://github.com/BullStein), [allanf181](https://github.com/allanf181) for being early beta testers!
|
||||
* guidu_ for the "Minimize" Button code!
|
||||
* guidu_ and [Nick-machado](https://github.com/Nick-machado) for the "Minimize" Button code!
|
||||
* Nomad and [Gustav](https://www.youtube.com/@gustav_vv) for the tutorials!
|
||||
* TheBlueCorner for getting me interested in online pixel canvases!
|
||||
|
|
@ -44,11 +44,11 @@
|
|||
<a href="https://github.com/SwingTheVine/Wplace-BlueMarble/blob/main/LICENSE.txt" target="_blank" rel="noopener noreferrer"><img alt="Software License: MPL-2.0" src="https://img.shields.io/badge/Software_License-MPL--2.0-slateblue?style=flat"></a>
|
||||
<a href="https://discord.gg/tpeBPy46hf" target="_blank" rel="noopener noreferrer"><img alt="Contact Me" src="https://img.shields.io/badge/Contact_Me-gray?style=flat&logo=Discord&logoColor=white&logoSize=auto&labelColor=cornflowerblue"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="WakaTime" src="https://img.shields.io/badge/Coding_Time-91hrs_0mins-blue?style=flat&logo=wakatime&logoColor=black&logoSize=auto&labelColor=white"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Patches" src="https://img.shields.io/badge/Total_Patches-489-black?style=flat"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Patches" src="https://img.shields.io/badge/Total_Patches-493-black?style=flat"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Lines of Code" src="https://tokei.rs/b1/github/SwingTheVine/Wplace-BlueMarble?category=code"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Total Comments" src="https://tokei.rs/b1/github/SwingTheVine/Wplace-BlueMarble?category=comments"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Compression" src="https://img.shields.io/badge/Compression-73.69%25-blue"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Visitors" src="https://img.shields.io/badge/Visitors-29_589-gainsboro?style=flat"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Visitors" src="https://img.shields.io/badge/Visitors-37_847-gainsboro?style=flat"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="Build" src="https://github.com/SwingTheVine/Wplace-BlueMarble/actions/workflows/build.yml/badge.svg"></a>
|
||||
<a href="" target="_blank" rel="noopener noreferrer"><img alt="CodeQL" src="https://github.com/SwingTheVine/Wplace-BlueMarble/actions/workflows/github-code-scanning/codeql/badge.svg"></a>
|
||||
|
||||
|
|
|
|||
303
package-lock.json
generated
303
package-lock.json
generated
|
|
@ -1,17 +1,64 @@
|
|||
{
|
||||
"name": "wplace-bluemarble",
|
||||
"version": "0.73.13",
|
||||
"version": "0.74.4",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "wplace-bluemarble",
|
||||
"version": "0.73.13",
|
||||
"version": "0.74.4",
|
||||
"devDependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"jsdoc": "^4.0.4",
|
||||
"terser": "^5.43.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-string-parser": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
|
||||
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-identifier": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
|
||||
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz",
|
||||
"integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.28.0"
|
||||
},
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.28.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz",
|
||||
"integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/helper-string-parser": "^7.27.1",
|
||||
"@babel/helper-validator-identifier": "^7.27.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.25.8",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz",
|
||||
|
|
@ -473,6 +520,40 @@
|
|||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@jsdoc/salty": {
|
||||
"version": "0.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.9.tgz",
|
||||
"integrity": "sha512-yYxMVH7Dqw6nO0d5NIV8OQWnitU8k6vXH8NtgqAfIa/IUqRMxRv/NUJJ08VEKbAakwxlgBl5PJdrU0dMPStsnw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.21"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=v12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/linkify-it": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz",
|
||||
"integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/markdown-it": {
|
||||
"version": "14.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz",
|
||||
"integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/linkify-it": "^5",
|
||||
"@types/mdurl": "^2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/mdurl": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz",
|
||||
"integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.15.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||
|
|
@ -485,18 +566,54 @@
|
|||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/bluebird": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/buffer-from": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/catharsis": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz",
|
||||
"integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.15"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.25.8",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz",
|
||||
|
|
@ -538,6 +655,158 @@
|
|||
"@esbuild/win32-x64": "0.25.8"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-string-regexp": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
|
||||
"integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/js2xmlparser": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz",
|
||||
"integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"xmlcreate": "^2.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/jsdoc": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.4.tgz",
|
||||
"integrity": "sha512-zeFezwyXeG4syyYHbvh1A967IAqq/67yXtXvuL5wnqCkFZe8I0vKfm+EO+YEvLguo6w9CDUbrAXVtJSHh2E8rw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.20.15",
|
||||
"@jsdoc/salty": "^0.2.1",
|
||||
"@types/markdown-it": "^14.1.1",
|
||||
"bluebird": "^3.7.2",
|
||||
"catharsis": "^0.9.0",
|
||||
"escape-string-regexp": "^2.0.0",
|
||||
"js2xmlparser": "^4.0.2",
|
||||
"klaw": "^3.0.0",
|
||||
"markdown-it": "^14.1.0",
|
||||
"markdown-it-anchor": "^8.6.7",
|
||||
"marked": "^4.0.10",
|
||||
"mkdirp": "^1.0.4",
|
||||
"requizzle": "^0.2.3",
|
||||
"strip-json-comments": "^3.1.0",
|
||||
"underscore": "~1.13.2"
|
||||
},
|
||||
"bin": {
|
||||
"jsdoc": "jsdoc.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/klaw": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz",
|
||||
"integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.1.9"
|
||||
}
|
||||
},
|
||||
"node_modules/linkify-it": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
|
||||
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"uc.micro": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/markdown-it": {
|
||||
"version": "14.1.0",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
|
||||
"integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1",
|
||||
"entities": "^4.4.0",
|
||||
"linkify-it": "^5.0.0",
|
||||
"mdurl": "^2.0.0",
|
||||
"punycode.js": "^2.3.1",
|
||||
"uc.micro": "^2.1.0"
|
||||
},
|
||||
"bin": {
|
||||
"markdown-it": "bin/markdown-it.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/markdown-it-anchor": {
|
||||
"version": "8.6.7",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz",
|
||||
"integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"@types/markdown-it": "*",
|
||||
"markdown-it": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/marked": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz",
|
||||
"integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"marked": "bin/marked.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/mdurl": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
|
||||
"integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/punycode.js": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
|
||||
"integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/requizzle": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz",
|
||||
"integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.21"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
|
|
@ -557,6 +826,18 @@
|
|||
"source-map": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-json-comments": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
||||
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.43.1",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz",
|
||||
|
|
@ -574,6 +855,24 @@
|
|||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/uc.micro": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
|
||||
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/underscore": {
|
||||
"version": "1.13.7",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz",
|
||||
"integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/xmlcreate": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz",
|
||||
"integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "wplace-bluemarble",
|
||||
"version": "0.74.0",
|
||||
"version": "0.74.4",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "node build/build.js",
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"jsdoc": "^4.0.4",
|
||||
"terser": "^5.43.1"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// ==UserScript==
|
||||
// @name Blue Marble
|
||||
// @namespace https://github.com/SwingTheVine/
|
||||
// @version 0.74.0
|
||||
// @version 0.74.4
|
||||
// @description A userscript to automate and/or enhance the user experience on Wplace.live. Make sure to comply with the site's Terms of Service, and rules! This script is not affiliated with Wplace.live in any way, use at your own risk. This script is not affiliated with TamperMonkey. The author of this userscript is not responsible for any damages, issues, loss of data, or punishment that may occur as a result of using this script. This script is provided "as is" under the MPL-2.0 license. The "Blue Marble" icon is licensed under CC0 1.0 Universal (CC0 1.0) Public Domain Dedication. The image is owned by NASA.
|
||||
// @author SwingTheVine
|
||||
// @license MPL-2.0
|
||||
|
|
|
|||
|
|
@ -125,11 +125,11 @@ export default class Overlay {
|
|||
this.parentStack = [];
|
||||
}
|
||||
|
||||
/** Adds a `<div>` to the overlay.
|
||||
* This `<div>` element will have properties shared between all `<div>` elements in the overlay.
|
||||
/** Adds a `div` to the overlay.
|
||||
* This `div` element will have properties shared between all `div` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `<div>` that are NOT shared between all overlay `<div>` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLDivElement):void} [callback=()=>{}] - Additional JS modification to the `<div>`.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `div` that are NOT shared between all overlay `div` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLDivElement):void} [callback=()=>{}] - Additional JS modification to the `div`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.2
|
||||
* @example
|
||||
|
|
@ -150,11 +150,11 @@ export default class Overlay {
|
|||
return this;
|
||||
}
|
||||
|
||||
/** Adds a `<p>` to the overlay.
|
||||
* This `<p>` element will have properties shared between all `<p>` elements in the overlay.
|
||||
/** Adds a `p` to the overlay.
|
||||
* This `p` element will have properties shared between all `p` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `<p>` that are NOT shared between all overlay `<p>` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLParagraphElement):void} [callback=()=>{}] - Additional JS modification to the `<p>`.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `p` that are NOT shared between all overlay `p` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLParagraphElement):void} [callback=()=>{}] - Additional JS modification to the `p`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.2
|
||||
* @example
|
||||
|
|
@ -175,11 +175,11 @@ export default class Overlay {
|
|||
return this;
|
||||
}
|
||||
|
||||
/** Adds a `<small>` to the overlay.
|
||||
* This `<small>` element will have properties shared between all `<small>` elements in the overlay.
|
||||
/** Adds a `small` to the overlay.
|
||||
* This `small` element will have properties shared between all `small` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `<small>` that are NOT shared between all overlay `<small>` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLParagraphElement):void} [callback=()=>{}] - Additional JS modification to the `<small>`.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `small` that are NOT shared between all overlay `small` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLParagraphElement):void} [callback=()=>{}] - Additional JS modification to the `small`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.55.8
|
||||
* @example
|
||||
|
|
@ -200,11 +200,11 @@ export default class Overlay {
|
|||
return this;
|
||||
}
|
||||
|
||||
/** Adds a `<img>` to the overlay.
|
||||
* This `<img>` element will have properties shared between all `<img>` elements in the overlay.
|
||||
/** Adds a `img` to the overlay.
|
||||
* This `img` element will have properties shared between all `img` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `<img>` that are NOT shared between all overlay `<img>` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLImageElement):void} [callback=()=>{}] - Additional JS modification to the `<img>`.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `img` that are NOT shared between all overlay `img` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLImageElement):void} [callback=()=>{}] - Additional JS modification to the `img`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.2
|
||||
* @example
|
||||
|
|
@ -251,11 +251,11 @@ export default class Overlay {
|
|||
return this;
|
||||
}
|
||||
|
||||
/** Adds a `<hr>` to the overlay.
|
||||
* This `<hr>` element will have properties shared between all `<hr>` elements in the overlay.
|
||||
/** Adds a `hr` to the overlay.
|
||||
* This `hr` element will have properties shared between all `hr` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `<hr>` that are NOT shared between all overlay `<hr>` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLHRElement):void} [callback=()=>{}] - Additional JS modification to the `<hr>`.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `hr` that are NOT shared between all overlay `hr` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLHRElement):void} [callback=()=>{}] - Additional JS modification to the `hr`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.7
|
||||
* @example
|
||||
|
|
@ -276,11 +276,11 @@ export default class Overlay {
|
|||
return this;
|
||||
}
|
||||
|
||||
/** Adds a `<br>` to the overlay.
|
||||
* This `<br>` element will have properties shared between all `<br>` elements in the overlay.
|
||||
/** Adds a `br` to the overlay.
|
||||
* This `br` element will have properties shared between all `br` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `<br>` that are NOT shared between all overlay `<br>` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLBRElement):void} [callback=()=>{}] - Additional JS modification to the `<br>`.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `br` that are NOT shared between all overlay `br` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLBRElement):void} [callback=()=>{}] - Additional JS modification to the `br`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.11
|
||||
* @example
|
||||
|
|
@ -333,11 +333,11 @@ export default class Overlay {
|
|||
return this;
|
||||
}
|
||||
|
||||
/** Adds a `<button>` to the overlay.
|
||||
* This `<button>` element will have properties shared between all `<button>` elements in the overlay.
|
||||
/** Adds a `button` to the overlay.
|
||||
* This `button` element will have properties shared between all `button` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `<button>` that are NOT shared between all overlay `<button>` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLButtonElement):void} [callback=()=>{}] - Additional JS modification to the `<button>`.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `button` that are NOT shared between all overlay `button` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLButtonElement):void} [callback=()=>{}] - Additional JS modification to the `button`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.12
|
||||
* @example
|
||||
|
|
@ -360,10 +360,10 @@ export default class Overlay {
|
|||
|
||||
/** Adds a help button to the overlay. It will have a "?" icon unless overridden in callback.
|
||||
* On click, the button will attempt to output the title to the output element (ID defined in Overlay constructor).
|
||||
* This `<button>` element will have properties shared between all `<button>` elements in the overlay.
|
||||
* This `button` element will have properties shared between all `button` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `<button>` that are NOT shared between all overlay `<button>` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLButtonElement):void} [callback=()=>{}] - Additional JS modification to the `<button>`.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `button` that are NOT shared between all overlay `button` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLButtonElement):void} [callback=()=>{}] - Additional JS modification to the `button`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.12
|
||||
* @example
|
||||
|
|
@ -405,11 +405,11 @@ export default class Overlay {
|
|||
return this;
|
||||
}
|
||||
|
||||
/** Adds a `<input>` to the overlay.
|
||||
* This `<input>` element will have properties shared between all `<input>` elements in the overlay.
|
||||
/** Adds a `input` to the overlay.
|
||||
* This `input` element will have properties shared between all `input` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `<input>` that are NOT shared between all overlay `<input>` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLInputElement):void} [callback=()=>{}] - Additional JS modification to the `<input>`.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `input` that are NOT shared between all overlay `input` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLInputElement):void} [callback=()=>{}] - Additional JS modification to the `input`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.13
|
||||
* @example
|
||||
|
|
@ -489,11 +489,11 @@ export default class Overlay {
|
|||
return this;
|
||||
}
|
||||
|
||||
/** Adds a `<textarea>` to the overlay.
|
||||
* This `<textarea>` element will have properties shared between all `<textarea>` elements in the overlay.
|
||||
/** Adds a `textarea` to the overlay.
|
||||
* This `textarea` element will have properties shared between all `textarea` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `<textarea>` that are NOT shared between all overlay `<textarea>` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLTextAreaElement):void} [callback=()=>{}] - Additional JS modification to the `<textarea>`.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `textarea` that are NOT shared between all overlay `textarea` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLTextAreaElement):void} [callback=()=>{}] - Additional JS modification to the `textarea`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.13
|
||||
* @example
|
||||
|
|
@ -516,7 +516,7 @@ export default class Overlay {
|
|||
|
||||
/** Updates the inner HTML of the element.
|
||||
* The element is discovered by it's id.
|
||||
* If the element is an <input>, it will modify the value attribute instead.
|
||||
* If the element is an `input`, it will modify the value attribute instead.
|
||||
* @param {string} id - The ID of the element to change
|
||||
* @param {string} html - The HTML/text to update with
|
||||
* @param {boolean} [doSafe] - (Optional) Should `textContent` be used instead of `innerHTML` to avoid XSS? False by default
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export default class Template {
|
|||
* @param {string} [params.authorID=''] - The user ID of the person who exported the template (prevents sort ID collisions)
|
||||
* @param {string} [params.url=''] - The URL to the source image
|
||||
* @param {File} [params.file=null] - The template file (pre-processed File or processed bitmap)
|
||||
* @param {[number, number, number, number]} [params.coords=null] - The coordinates of the top left corner as (tileX, tileY, pixelX, pixelY)
|
||||
* @param {Array<number>} [params.coords=null] - The coordinates of the top left corner as (tileX, tileY, pixelX, pixelY)
|
||||
* @param {Object} [params.chunked=null] - The affected chunks of the template, and their template for each chunk
|
||||
* @param {number} [params.tileSize=1000] - The size of a tile in pixels (assumes square tiles)
|
||||
* @param {number} [params.pixelCount=0] - Total number of pixels in the template (calculated automatically during processing)
|
||||
|
|
|
|||
39
src/main.js
39
src/main.js
|
|
@ -174,11 +174,12 @@ document.head?.appendChild(stylesheetLink);
|
|||
|
||||
// CONSTRUCTORS
|
||||
const observers = new Observers(); // Constructs a new Observers object
|
||||
const overlay = new Overlay(name, version); // Constructs a new Overlay object
|
||||
const templateManager = new TemplateManager(name, version, overlay); // Constructs a new TemplateManager object
|
||||
const overlayMain = new Overlay(name, version); // Constructs a new Overlay object for the main overlay
|
||||
const overlayTabTemplate = new Overlay(name, version); // Constructs a Overlay object for the template tab
|
||||
const templateManager = new TemplateManager(name, version, overlayMain); // Constructs a new TemplateManager object
|
||||
const apiManager = new ApiManager(templateManager); // Constructs a new ApiManager object
|
||||
|
||||
overlay.setApiManager(apiManager); // Sets the API manager
|
||||
overlayMain.setApiManager(apiManager); // Sets the API manager
|
||||
|
||||
const storageTemplates = JSON.parse(GM_getValue('bmTemplates', '{}'));
|
||||
console.log(storageTemplates);
|
||||
|
|
@ -186,9 +187,9 @@ templateManager.importJSON(storageTemplates); // Loads the templates
|
|||
|
||||
buildOverlayMain(); // Builds the main overlay
|
||||
|
||||
overlay.handleDrag('#bm-overlay', '#bm-bar-drag'); // Creates dragging capability on the drag bar for dragging the overlay
|
||||
overlayMain.handleDrag('#bm-overlay', '#bm-bar-drag'); // Creates dragging capability on the drag bar for dragging the overlay
|
||||
|
||||
apiManager.spontaneousResponseListener(overlay); // Reads spontaneous fetch responces
|
||||
apiManager.spontaneousResponseListener(overlayMain); // Reads spontaneous fetch responces
|
||||
|
||||
observeBlack(); // Observes the black palette color
|
||||
|
||||
|
|
@ -242,7 +243,7 @@ function observeBlack() {
|
|||
function buildOverlayMain() {
|
||||
let isMinimized = false; // Overlay state tracker (false = maximized, true = minimized)
|
||||
|
||||
overlay.addDiv({'id': 'bm-overlay', 'style': 'top: 10px; right: 75px;'})
|
||||
overlayMain.addDiv({'id': 'bm-overlay', 'style': 'top: 10px; right: 75px;'})
|
||||
.addDiv({'id': 'bm-contain-header'})
|
||||
.addDiv({'id': 'bm-bar-drag'}).buildElement()
|
||||
.addImg({'alt': 'Blue Marble Icon - Click to minimize/maximize', 'src': 'https://raw.githubusercontent.com/SwingTheVine/Wplace-BlueMarble/main/dist/assets/Favicon.png', 'style': 'cursor: pointer;'},
|
||||
|
|
@ -523,7 +524,7 @@ function buildOverlayMain() {
|
|||
}
|
||||
}).buildElement()
|
||||
.buildElement()
|
||||
.addTextarea({'id': overlay.outputStatusId, 'placeholder': `Status: Sleeping...\nVersion: ${version}`, 'readOnly': true}).buildElement()
|
||||
.addTextarea({'id': overlayMain.outputStatusId, 'placeholder': `Status: Sleeping...\nVersion: ${version}`, 'readOnly': true}).buildElement()
|
||||
.addDiv({'id': 'bm-contain-buttons-action'})
|
||||
.addDiv()
|
||||
// .addButton({'id': 'bm-button-teleport', 'className': 'bm-help', 'textContent': '✈'}).buildElement()
|
||||
|
|
@ -541,3 +542,27 @@ function buildOverlayMain() {
|
|||
.buildElement()
|
||||
.buildOverlay(document.body);
|
||||
}
|
||||
|
||||
function buildOverlayTabTemplate() {
|
||||
overlayTabTemplate.addDiv({'id': 'bm-tab-template', 'style': 'top: 20%; left: 10%;'})
|
||||
.addDiv()
|
||||
.addDiv({'className': 'bm-dragbar'}).buildElement()
|
||||
.addButton({'className': 'bm-button-minimize', 'textContent': '↑'},
|
||||
(instance, button) => {
|
||||
button.onclick = () => {
|
||||
let isMinimized = false;
|
||||
if (button.textContent == '↑') {
|
||||
button.textContent = '↓';
|
||||
} else {
|
||||
button.textContent = '↑';
|
||||
isMinimized = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
).buildElement()
|
||||
.buildElement()
|
||||
.buildElement()
|
||||
.buildOverlay();
|
||||
}
|
||||
|
|
@ -199,7 +199,7 @@ export default class TemplateManager {
|
|||
/** Draws all templates on the specified tile.
|
||||
* This method handles the rendering of template overlays on individual tiles.
|
||||
* @param {File} tileBlob - The pixels that are placed on a tile
|
||||
* @param {[number, number]} tileCoords - The tile coordinates [x, y]
|
||||
* @param {Array<number>} tileCoords - The tile coordinates [x, y]
|
||||
* @since 0.65.77
|
||||
*/
|
||||
async drawTemplateOnTile(tileBlob, tileCoords) {
|
||||
|
|
|
|||
748
wiki/Overlay.js.html
Normal file
748
wiki/Overlay.js.html
Normal file
|
|
@ -0,0 +1,748 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: Overlay.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: Overlay.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/** The overlay builder for the Blue Marble script.
|
||||
* @description This class handles the overlay UI for the Blue Marble script.
|
||||
* @since 0.0.2
|
||||
* @example
|
||||
* const overlay = new Overlay();
|
||||
* overlay.addDiv({ 'id': 'overlay' })
|
||||
* .addDiv({ 'id': 'header' })
|
||||
* .addHeader(1, {'textContent': 'Your Overlay'}).buildElement()
|
||||
* .addP({'textContent': 'This is your overlay. It is versatile.'}).buildElement()
|
||||
* .buildElement() // Marks the end of the header <div>
|
||||
* .addHr().buildElement()
|
||||
* .buildOverlay(document.body);
|
||||
* // Output:
|
||||
* // (Assume <body> already exists in the webpage)
|
||||
* <body>
|
||||
* <div id="overlay">
|
||||
* <div id="header">
|
||||
* <h1>Your Overlay</h1>
|
||||
* <p>This is your overlay. It is versatile.</p>
|
||||
* </div>
|
||||
* <hr>
|
||||
* </div>
|
||||
* </body>
|
||||
*/
|
||||
export default class Overlay {
|
||||
|
||||
/** Constructor for the Overlay class.
|
||||
* @param {string} name - The name of the userscript
|
||||
* @param {string} version - The version of the userscript
|
||||
* @since 0.0.2
|
||||
* @see {@link Overlay}
|
||||
*/
|
||||
constructor(name, version) {
|
||||
this.name = name; // Name of userscript
|
||||
this.version = version; // Version of userscript
|
||||
|
||||
this.apiManager = null; // The API manager instance. Later populated when setApiManager is called
|
||||
|
||||
this.outputStatusId = 'bm-output-status'; // ID for status element
|
||||
|
||||
this.overlay = null; // The overlay root DOM HTMLElement
|
||||
this.currentParent = null; // The current parent HTMLElement in the overlay
|
||||
this.parentStack = []; // Tracks the parent elements BEFORE the currentParent so we can nest elements
|
||||
}
|
||||
|
||||
/** Populates the apiManager variable with the apiManager class.
|
||||
* @param {apiManager} apiManager - The apiManager class instance
|
||||
* @since 0.41.4
|
||||
*/
|
||||
setApiManager(apiManager) {this.apiManager = apiManager;}
|
||||
|
||||
/** Creates an element.
|
||||
* For **internal use** of the {@link Overlay} class.
|
||||
* @param {string} tag - The tag name as a string.
|
||||
* @param {Object.<string, any>} [properties={}] - The DOM properties of the element.
|
||||
* @returns {HTMLElement} HTML Element
|
||||
* @since 0.43.2
|
||||
*/
|
||||
#createElement(tag, properties = {}, additionalProperties={}) {
|
||||
|
||||
const element = document.createElement(tag); // Creates the element
|
||||
|
||||
// If this is the first element made...
|
||||
if (!this.overlay) {
|
||||
this.overlay = element; // Declare it the highest overlay element
|
||||
this.currentParent = element;
|
||||
} else {
|
||||
this.currentParent?.appendChild(element); // ...else delcare it the child of the last element
|
||||
this.parentStack.push(this.currentParent);
|
||||
this.currentParent = element;
|
||||
}
|
||||
|
||||
// For every passed in property (shared by all like-elements), apply the it to the element
|
||||
for (const [property, value] of Object.entries(properties)) {
|
||||
element[property] = value;
|
||||
}
|
||||
|
||||
// For every passed in additional property, apply the it to the element
|
||||
for (const [property, value] of Object.entries(additionalProperties)) {
|
||||
element[property] = value;
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/** Finishes building an element.
|
||||
* Call this after you are finished adding children.
|
||||
* If the element will have no children, call it anyways.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.2
|
||||
* @example
|
||||
* overlay
|
||||
* .addDiv()
|
||||
* .addHeader(1).buildElement() // Breaks out of the <h1>
|
||||
* .addP().buildElement() // Breaks out of the <p>
|
||||
* .buildElement() // Breaks out of the <div>
|
||||
* .addHr() // Since there are no more elements, calling buildElement() is optional
|
||||
* .buildOverlay(document.body);
|
||||
*/
|
||||
buildElement() {
|
||||
if (this.parentStack.length > 0) {
|
||||
this.currentParent = this.parentStack.pop();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Finishes building the overlay and displays it.
|
||||
* Call this when you are done chaining methods.
|
||||
* @param {HTMLElement} parent - The parent HTMLElement this overlay should be appended to as a child.
|
||||
* @since 0.43.2
|
||||
* @example
|
||||
* overlay
|
||||
* .addDiv()
|
||||
* .addP().buildElement()
|
||||
* .buildElement()
|
||||
* .buildOverlay(document.body); // Adds DOM structure to document body
|
||||
* // <div><p></p></div>
|
||||
*/
|
||||
buildOverlay(parent) {
|
||||
parent?.appendChild(this.overlay);
|
||||
|
||||
// Resets the class-bound variables of this class instance back to default so overlay can be build again later
|
||||
this.overlay = null;
|
||||
this.currentParent = null;
|
||||
this.parentStack = [];
|
||||
}
|
||||
|
||||
/** Adds a `div` to the overlay.
|
||||
* This `div` element will have properties shared between all `div` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `div` that are NOT shared between all overlay `div` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLDivElement):void} [callback=()=>{}] - Additional JS modification to the `div`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.2
|
||||
* @example
|
||||
* // Assume all <div> elements have a shared class (e.g. {'className': 'bar'})
|
||||
* overlay.addDiv({'id': 'foo'}).buildOverlay(document.body);
|
||||
* // Output:
|
||||
* // (Assume <body> already exists in the webpage)
|
||||
* <body>
|
||||
* <div id="foo" class="bar"></div>
|
||||
* </body>
|
||||
*/
|
||||
addDiv(additionalProperties = {}, callback = () => {}) {
|
||||
|
||||
const properties = {}; // Shared <div> DOM properties
|
||||
|
||||
const div = this.#createElement('div', properties, additionalProperties); // Creates the <div> element
|
||||
callback(this, div); // Runs any script passed in through the callback
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Adds a `p` to the overlay.
|
||||
* This `p` element will have properties shared between all `p` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `p` that are NOT shared between all overlay `p` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLParagraphElement):void} [callback=()=>{}] - Additional JS modification to the `p`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.2
|
||||
* @example
|
||||
* // Assume all <p> elements have a shared class (e.g. {'className': 'bar'})
|
||||
* overlay.addP({'id': 'foo', 'textContent': 'Foobar.'}).buildOverlay(document.body);
|
||||
* // Output:
|
||||
* // (Assume <body> already exists in the webpage)
|
||||
* <body>
|
||||
* <p id="foo" class="bar">Foobar.</p>
|
||||
* </body>
|
||||
*/
|
||||
addP(additionalProperties = {}, callback = () => {}) {
|
||||
|
||||
const properties = {}; // Shared <p> DOM properties
|
||||
|
||||
const p = this.#createElement('p', properties, additionalProperties); // Creates the <p> element
|
||||
callback(this, p); // Runs any script passed in through the callback
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Adds a `small` to the overlay.
|
||||
* This `small` element will have properties shared between all `small` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `small` that are NOT shared between all overlay `small` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLParagraphElement):void} [callback=()=>{}] - Additional JS modification to the `small`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.55.8
|
||||
* @example
|
||||
* // Assume all <small> elements have a shared class (e.g. {'className': 'bar'})
|
||||
* overlay.addSmall({'id': 'foo', 'textContent': 'Foobar.'}).buildOverlay(document.body);
|
||||
* // Output:
|
||||
* // (Assume <body> already exists in the webpage)
|
||||
* <body>
|
||||
* <small id="foo" class="bar">Foobar.</small>
|
||||
* </body>
|
||||
*/
|
||||
addSmall(additionalProperties = {}, callback = () => {}) {
|
||||
|
||||
const properties = {}; // Shared <small> DOM properties
|
||||
|
||||
const small = this.#createElement('small', properties, additionalProperties); // Creates the <small> element
|
||||
callback(this, small); // Runs any script passed in through the callback
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Adds a `img` to the overlay.
|
||||
* This `img` element will have properties shared between all `img` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `img` that are NOT shared between all overlay `img` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLImageElement):void} [callback=()=>{}] - Additional JS modification to the `img`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.2
|
||||
* @example
|
||||
* // Assume all <img> elements have a shared class (e.g. {'className': 'bar'})
|
||||
* overlay.addimg({'id': 'foo', 'src': './img.png'}).buildOverlay(document.body);
|
||||
* // Output:
|
||||
* // (Assume <body> already exists in the webpage)
|
||||
* <body>
|
||||
* <img id="foo" src="./img.png" class="bar">
|
||||
* </body>
|
||||
*/
|
||||
addImg(additionalProperties = {}, callback = () => {}) {
|
||||
|
||||
const properties = {}; // Shared <img> DOM properties
|
||||
|
||||
const img = this.#createElement('img', properties, additionalProperties); // Creates the <img> element
|
||||
callback(this, img); // Runs any script passed in through the callback
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Adds a header to the overlay.
|
||||
* This header element will have properties shared between all header elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {number} level - The header level. Must be between 1 and 6 (inclusive)
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the header that are NOT shared between all overlay header elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLHeadingElement):void} [callback=()=>{}] - Additional JS modification to the header.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.7
|
||||
* @example
|
||||
* // Assume all header elements have a shared class (e.g. {'className': 'bar'})
|
||||
* overlay.addHeader(6, {'id': 'foo', 'textContent': 'Foobar.'}).buildOverlay(document.body);
|
||||
* // Output:
|
||||
* // (Assume <body> already exists in the webpage)
|
||||
* <body>
|
||||
* <h6 id="foo" class="bar">Foobar.</h6>
|
||||
* </body>
|
||||
*/
|
||||
addHeader(level, additionalProperties = {}, callback = () => {}) {
|
||||
|
||||
const properties = {}; // Shared header DOM properties
|
||||
|
||||
const header = this.#createElement('h' + level, properties, additionalProperties); // Creates the header element
|
||||
callback(this, header); // Runs any script passed in through the callback
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Adds a `hr` to the overlay.
|
||||
* This `hr` element will have properties shared between all `hr` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `hr` that are NOT shared between all overlay `hr` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLHRElement):void} [callback=()=>{}] - Additional JS modification to the `hr`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.7
|
||||
* @example
|
||||
* // Assume all <hr> elements have a shared class (e.g. {'className': 'bar'})
|
||||
* overlay.addhr({'id': 'foo'}).buildOverlay(document.body);
|
||||
* // Output:
|
||||
* // (Assume <body> already exists in the webpage)
|
||||
* <body>
|
||||
* <hr id="foo" class="bar">
|
||||
* </body>
|
||||
*/
|
||||
addHr(additionalProperties = {}, callback = () => {}) {
|
||||
|
||||
const properties = {}; // Shared <hr> DOM properties
|
||||
|
||||
const hr = this.#createElement('hr', properties, additionalProperties); // Creates the <hr> element
|
||||
callback(this, hr); // Runs any script passed in through the callback
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Adds a `br` to the overlay.
|
||||
* This `br` element will have properties shared between all `br` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `br` that are NOT shared between all overlay `br` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLBRElement):void} [callback=()=>{}] - Additional JS modification to the `br`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.11
|
||||
* @example
|
||||
* // Assume all <br> elements have a shared class (e.g. {'className': 'bar'})
|
||||
* overlay.addbr({'id': 'foo'}).buildOverlay(document.body);
|
||||
* // Output:
|
||||
* // (Assume <body> already exists in the webpage)
|
||||
* <body>
|
||||
* <br id="foo" class="bar">
|
||||
* </body>
|
||||
*/
|
||||
addBr(additionalProperties = {}, callback = () => {}) {
|
||||
|
||||
const properties = {}; // Shared <br> DOM properties
|
||||
|
||||
const br = this.#createElement('br', properties, additionalProperties); // Creates the <br> element
|
||||
callback(this, br); // Runs any script passed in through the callback
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Adds a checkbox to the overlay.
|
||||
* This checkbox element will have properties shared between all checkbox elements in the overlay.
|
||||
* You can override the shared properties by using a callback. Note: the checkbox element is inside a label element.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the checkbox that are NOT shared between all overlay checkbox elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLLabelElement, HTMLInputElement):void} [callback=()=>{}] - Additional JS modification to the checkbox.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.10
|
||||
* @example
|
||||
* // Assume all checkbox elements have a shared class (e.g. {'className': 'bar'})
|
||||
* overlay.addCheckbox({'id': 'foo', 'textContent': 'Foobar.'}).buildOverlay(document.body);
|
||||
* // Output:
|
||||
* // (Assume <body> already exists in the webpage)
|
||||
* <body>
|
||||
* <label>
|
||||
* <input type="checkbox" id="foo" class="bar">
|
||||
* "Foobar."
|
||||
* </label>
|
||||
* </body>
|
||||
*/
|
||||
addCheckbox(additionalProperties = {}, callback = () => {}) {
|
||||
|
||||
const properties = {'type': 'checkbox'}; // Shared checkbox DOM properties
|
||||
|
||||
const label = this.#createElement('label', {'textContent': additionalProperties['textContent'] ?? ''}); // Creates the label element
|
||||
delete additionalProperties['textContent']; // Deletes 'textContent' DOM property before adding the properties to the checkbox
|
||||
const checkbox = this.#createElement('input', properties, additionalProperties); // Creates the checkbox element
|
||||
label.insertBefore(checkbox, label.firstChild); // Makes the checkbox the first child of the label (before the text content)
|
||||
this.buildElement(); // Signifies that we are done adding children to the checkbox
|
||||
callback(this, label, checkbox); // Runs any script passed in through the callback
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Adds a `button` to the overlay.
|
||||
* This `button` element will have properties shared between all `button` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `button` that are NOT shared between all overlay `button` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLButtonElement):void} [callback=()=>{}] - Additional JS modification to the `button`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.12
|
||||
* @example
|
||||
* // Assume all <button> elements have a shared class (e.g. {'className': 'bar'})
|
||||
* overlay.addButton({'id': 'foo', 'textContent': 'Foobar.'}).buildOverlay(document.body);
|
||||
* // Output:
|
||||
* // (Assume <body> already exists in the webpage)
|
||||
* <body>
|
||||
* <button id="foo" class="bar">Foobar.</button>
|
||||
* </body>
|
||||
*/
|
||||
addButton(additionalProperties = {}, callback = () => {}) {
|
||||
|
||||
const properties = {}; // Shared <button> DOM properties
|
||||
|
||||
const button = this.#createElement('button', properties, additionalProperties); // Creates the <button> element
|
||||
callback(this, button); // Runs any script passed in through the callback
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Adds a help button to the overlay. It will have a "?" icon unless overridden in callback.
|
||||
* On click, the button will attempt to output the title to the output element (ID defined in Overlay constructor).
|
||||
* This `button` element will have properties shared between all `button` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `button` that are NOT shared between all overlay `button` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLButtonElement):void} [callback=()=>{}] - Additional JS modification to the `button`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.12
|
||||
* @example
|
||||
* // Assume all help button elements have a shared class (e.g. {'className': 'bar'})
|
||||
* overlay.addButtonHelp({'id': 'foo', 'title': 'Foobar.'}).buildOverlay(document.body);
|
||||
* // Output:
|
||||
* // (Assume <body> already exists in the webpage)
|
||||
* <body>
|
||||
* <button id="foo" class="bar" title="Help: Foobar.">?</button>
|
||||
* </body>
|
||||
* @example
|
||||
* // Assume all help button elements have a shared class (e.g. {'className': 'bar'})
|
||||
* overlay.addButtonHelp({'id': 'foo', 'textContent': 'Foobar.'}).buildOverlay(document.body);
|
||||
* // Output:
|
||||
* // (Assume <body> already exists in the webpage)
|
||||
* <body>
|
||||
* <button id="foo" class="bar" title="Help: Foobar.">?</button>
|
||||
* </body>
|
||||
*/
|
||||
addButtonHelp(additionalProperties = {}, callback = () => {}) {
|
||||
|
||||
const tooltip = additionalProperties['title'] ?? additionalProperties['textContent'] ?? 'Help: No info'; // Retrieves the tooltip
|
||||
|
||||
// Makes sure the tooltip is stored in the title property
|
||||
delete additionalProperties['textContent'];
|
||||
additionalProperties['title'] = `Help: ${tooltip}`;
|
||||
|
||||
// Shared help button DOM properties
|
||||
const properties = {
|
||||
'textContent': '?',
|
||||
'className': 'bm-help',
|
||||
'onclick': () => {
|
||||
this.updateInnerHTML(this.outputStatusId, tooltip);
|
||||
}
|
||||
};
|
||||
|
||||
const help = this.#createElement('button', properties, additionalProperties); // Creates the <button> element
|
||||
callback(this, help); // Runs any script passed in through the callback
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Adds a `input` to the overlay.
|
||||
* This `input` element will have properties shared between all `input` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `input` that are NOT shared between all overlay `input` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLInputElement):void} [callback=()=>{}] - Additional JS modification to the `input`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.13
|
||||
* @example
|
||||
* // Assume all <input> elements have a shared class (e.g. {'className': 'bar'})
|
||||
* overlay.addInput({'id': 'foo', 'textContent': 'Foobar.'}).buildOverlay(document.body);
|
||||
* // Output:
|
||||
* // (Assume <body> already exists in the webpage)
|
||||
* <body>
|
||||
* <input id="foo" class="bar">Foobar.</input>
|
||||
* </body>
|
||||
*/
|
||||
addInput(additionalProperties = {}, callback = () => {}) {
|
||||
|
||||
const properties = {}; // Shared <input> DOM properties
|
||||
|
||||
const input = this.#createElement('input', properties, additionalProperties); // Creates the <input> element
|
||||
callback(this, input); // Runs any script passed in through the callback
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Adds a file input to the overlay with enhanced visibility controls.
|
||||
* This input element will have properties shared between all file input elements in the overlay.
|
||||
* Uses multiple hiding methods to prevent browser native text from appearing during minimize/maximize.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the file input that are NOT shared between all overlay file input elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLDivElement, HTMLInputElement, HTMLButtonElement):void} [callback=()=>{}] - Additional JS modification to the file input.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.17
|
||||
* @example
|
||||
* // Assume all file input elements have a shared class (e.g. {'className': 'bar'})
|
||||
* overlay.addInputFile({'id': 'foo', 'textContent': 'Foobar.'}).buildOverlay(document.body);
|
||||
* // Output:
|
||||
* // (Assume <body> already exists in the webpage)
|
||||
* <body>
|
||||
* <div>
|
||||
* <input type="file" id="foo" class="bar" style="display: none"></input>
|
||||
* <button>Foobar.</button>
|
||||
* </div>
|
||||
* </body>
|
||||
*/
|
||||
addInputFile(additionalProperties = {}, callback = () => {}) {
|
||||
|
||||
const properties = {
|
||||
'type': 'file',
|
||||
'style': 'display: none !important; visibility: hidden !important; position: absolute !important; left: -9999px !important; width: 0 !important; height: 0 !important; opacity: 0 !important;'
|
||||
}; // Complete file input hiding to prevent native browser text interference
|
||||
const text = additionalProperties['textContent'] ?? ''; // Retrieves the text content
|
||||
|
||||
delete additionalProperties['textContent']; // Deletes the text content before applying the additional properties to the file input
|
||||
|
||||
const container = this.#createElement('div'); // Container for file input
|
||||
const input = this.#createElement('input', properties, additionalProperties); // Creates the file input
|
||||
this.buildElement(); // Signifies that we are done adding children to the file input
|
||||
const button = this.#createElement('button', {'textContent': text});
|
||||
this.buildElement(); // Signifies that we are done adding children to the button
|
||||
this.buildElement(); // Signifies that we are done adding children to the container
|
||||
|
||||
// Prevent file input from being accessible or visible by screen-readers and tabbing
|
||||
input.setAttribute('tabindex', '-1');
|
||||
input.setAttribute('aria-hidden', 'true');
|
||||
|
||||
button.addEventListener('click', () => {
|
||||
input.click(); // Clicks the file input
|
||||
});
|
||||
|
||||
// Update button text when file is selected
|
||||
input.addEventListener('change', () => {
|
||||
button.style.maxWidth = `${button.offsetWidth}px`;
|
||||
if (input.files.length > 0) {
|
||||
button.textContent = input.files[0].name;
|
||||
} else {
|
||||
button.textContent = text;
|
||||
}
|
||||
});
|
||||
|
||||
callback(this, container, input, button); // Runs any script passed in through the callback
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Adds a `textarea` to the overlay.
|
||||
* This `textarea` element will have properties shared between all `textarea` elements in the overlay.
|
||||
* You can override the shared properties by using a callback.
|
||||
* @param {Object.<string, any>} [additionalProperties={}] - The DOM properties of the `textarea` that are NOT shared between all overlay `textarea` elements. These should be camelCase.
|
||||
* @param {function(Overlay, HTMLTextAreaElement):void} [callback=()=>{}] - Additional JS modification to the `textarea`.
|
||||
* @returns {Overlay} Overlay class instance (this)
|
||||
* @since 0.43.13
|
||||
* @example
|
||||
* // Assume all <textarea> elements have a shared class (e.g. {'className': 'bar'})
|
||||
* overlay.addTextarea({'id': 'foo', 'textContent': 'Foobar.'}).buildOverlay(document.body);
|
||||
* // Output:
|
||||
* // (Assume <body> already exists in the webpage)
|
||||
* <body>
|
||||
* <textarea id="foo" class="bar">Foobar.</textarea>
|
||||
* </body>
|
||||
*/
|
||||
addTextarea(additionalProperties = {}, callback = () => {}) {
|
||||
|
||||
const properties = {}; // Shared <textarea> DOM properties
|
||||
|
||||
const textarea = this.#createElement('textarea', properties, additionalProperties); // Creates the <textarea> element
|
||||
callback(this, textarea); // Runs any script passed in through the callback
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Updates the inner HTML of the element.
|
||||
* The element is discovered by it's id.
|
||||
* If the element is an <input>, it will modify the value attribute instead.
|
||||
* @param {string} id - The ID of the element to change
|
||||
* @param {string} html - The HTML/text to update with
|
||||
* @param {boolean} [doSafe] - (Optional) Should `textContent` be used instead of `innerHTML` to avoid XSS? False by default
|
||||
* @since 0.24.2
|
||||
*/
|
||||
updateInnerHTML(id, html, doSafe=false) {
|
||||
|
||||
const element = document.getElementById(id.replace(/^#/, '')); // Retrieve the element from the 'id' (removed the '#')
|
||||
|
||||
if (!element) {return;} // Kills itself if the element does not exist
|
||||
|
||||
// Input elements don't have innerHTML, so we modify the value attribute instead
|
||||
if (element instanceof HTMLInputElement) {
|
||||
element.value = html;
|
||||
return;
|
||||
}
|
||||
|
||||
if (doSafe) {
|
||||
element.textContent = html; // Populate element with plain-text HTML/text
|
||||
} else {
|
||||
element.innerHTML = html; // Populate element with HTML/text
|
||||
}
|
||||
}
|
||||
|
||||
/** Handles dragging of the overlay.
|
||||
* Uses requestAnimationFrame for smooth animations and GPU-accelerated transforms.
|
||||
* @param {string} moveMe - The ID of the element to be moved
|
||||
* @param {string} iMoveThings - The ID of the drag handle element
|
||||
* @since 0.8.2
|
||||
*/
|
||||
handleDrag(moveMe, iMoveThings) {
|
||||
let isDragging = false;
|
||||
let offsetX, offsetY = 0;
|
||||
let animationFrame = null;
|
||||
let currentX = 0;
|
||||
let currentY = 0;
|
||||
let targetX = 0;
|
||||
let targetY = 0;
|
||||
|
||||
// Retrieves the elements (allows either '#id' or 'id' to be passed in)
|
||||
moveMe = document.querySelector(moveMe?.[0] == '#' ? moveMe : '#' + moveMe);
|
||||
iMoveThings = document.querySelector(iMoveThings?.[0] == '#' ? iMoveThings : '#' + iMoveThings);
|
||||
|
||||
// What to do when one of the two elements are not found
|
||||
if (!moveMe || !iMoveThings) {
|
||||
this.handleDisplayError(`Can not drag! ${!moveMe ? 'moveMe' : ''} ${!moveMe && !iMoveThings ? 'and ' : ''}${!iMoveThings ? 'iMoveThings ' : ''}was not found!`);
|
||||
return; // Kills itself
|
||||
}
|
||||
|
||||
// Smooth animation loop using requestAnimationFrame for optimal performance
|
||||
const updatePosition = () => {
|
||||
if (isDragging) {
|
||||
// Only update DOM if position changed significantly (reduce repaints)
|
||||
const deltaX = Math.abs(currentX - targetX);
|
||||
const deltaY = Math.abs(currentY - targetY);
|
||||
|
||||
if (deltaX > 0.5 || deltaY > 0.5) {
|
||||
currentX = targetX;
|
||||
currentY = targetY;
|
||||
|
||||
// Use CSS transform for GPU acceleration instead of left/top
|
||||
moveMe.style.transform = `translate(${currentX}px, ${currentY}px)`;
|
||||
moveMe.style.left = '0px';
|
||||
moveMe.style.top = '0px';
|
||||
moveMe.style.right = '';
|
||||
}
|
||||
|
||||
animationFrame = requestAnimationFrame(updatePosition);
|
||||
}
|
||||
};
|
||||
|
||||
// Cache initial position to avoid expensive getBoundingClientRect calls during drag
|
||||
let initialRect = null;
|
||||
|
||||
const startDrag = (clientX, clientY) => {
|
||||
isDragging = true;
|
||||
initialRect = moveMe.getBoundingClientRect();
|
||||
offsetX = clientX - initialRect.left;
|
||||
offsetY = clientY - initialRect.top;
|
||||
|
||||
// Get current position from transform or use element position
|
||||
const computedStyle = window.getComputedStyle(moveMe);
|
||||
const transform = computedStyle.transform;
|
||||
|
||||
if (transform && transform !== 'none') {
|
||||
const matrix = new DOMMatrix(transform);
|
||||
currentX = matrix.m41;
|
||||
currentY = matrix.m42;
|
||||
} else {
|
||||
currentX = initialRect.left;
|
||||
currentY = initialRect.top;
|
||||
}
|
||||
|
||||
targetX = currentX;
|
||||
targetY = currentY;
|
||||
|
||||
document.body.style.userSelect = 'none';
|
||||
iMoveThings.classList.add('dragging');
|
||||
|
||||
// Start animation loop
|
||||
if (animationFrame) {
|
||||
cancelAnimationFrame(animationFrame);
|
||||
}
|
||||
updatePosition();
|
||||
};
|
||||
|
||||
const endDrag = () => {
|
||||
isDragging = false;
|
||||
if (animationFrame) {
|
||||
cancelAnimationFrame(animationFrame);
|
||||
animationFrame = null;
|
||||
}
|
||||
document.body.style.userSelect = '';
|
||||
iMoveThings.classList.remove('dragging');
|
||||
};
|
||||
|
||||
// Mouse down - start dragging
|
||||
iMoveThings.addEventListener('mousedown', function(event) {
|
||||
event.preventDefault();
|
||||
startDrag(event.clientX, event.clientY);
|
||||
});
|
||||
|
||||
// Touch start - start dragging
|
||||
iMoveThings.addEventListener('touchstart', function(event) {
|
||||
const touch = event?.touches?.[0];
|
||||
if (!touch) {return;}
|
||||
startDrag(touch.clientX, touch.clientY);
|
||||
event.preventDefault();
|
||||
}, { passive: false });
|
||||
|
||||
// Mouse move - update target position
|
||||
document.addEventListener('mousemove', function(event) {
|
||||
if (isDragging && initialRect) {
|
||||
targetX = event.clientX - offsetX;
|
||||
targetY = event.clientY - offsetY;
|
||||
}
|
||||
}, { passive: true });
|
||||
|
||||
// Touch move - update target position
|
||||
document.addEventListener('touchmove', function(event) {
|
||||
if (isDragging && initialRect) {
|
||||
const touch = event?.touches?.[0];
|
||||
if (!touch) {return;}
|
||||
targetX = touch.clientX - offsetX;
|
||||
targetY = touch.clientY - offsetY;
|
||||
event.preventDefault();
|
||||
}
|
||||
}, { passive: false });
|
||||
|
||||
// End drag events
|
||||
document.addEventListener('mouseup', endDrag);
|
||||
document.addEventListener('touchend', endDrag);
|
||||
document.addEventListener('touchcancel', endDrag);
|
||||
}
|
||||
|
||||
/** Handles status display.
|
||||
* This will output plain text into the output Status box.
|
||||
* Additionally, this will output an info message to the console.
|
||||
* @param {string} text - The status text to display.
|
||||
* @since 0.58.4
|
||||
*/
|
||||
handleDisplayStatus(text) {
|
||||
const consoleInfo = console.info; // Creates a copy of the console.info function
|
||||
consoleInfo(`${this.name}: ${text}`); // Outputs something like "ScriptName: text" as an info message to the console
|
||||
this.updateInnerHTML(this.outputStatusId, 'Status: ' + text, true); // Update output Status box
|
||||
}
|
||||
|
||||
/** Handles error display.
|
||||
* This will output plain text into the output Status box.
|
||||
* Additionally, this will output an error to the console.
|
||||
* @param {string} text - The error text to display.
|
||||
* @since 0.41.6
|
||||
*/
|
||||
handleDisplayError(text) {
|
||||
const consoleError = console.error; // Creates a copy of the console.error function
|
||||
consoleError(`${this.name}: ${text}`); // Outputs something like "ScriptName: text" as an error message to the console
|
||||
this.updateInnerHTML(this.outputStatusId, 'Error: ' + text, true); // Update output Status box
|
||||
}
|
||||
}</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="module.exports.html">exports</a></li><li><a href="module.exports_module.exports.html">exports</a></li></ul><h3>Global</h3><ul><li><a href="global.html#addBr">addBr</a></li><li><a href="global.html#addButton">addButton</a></li><li><a href="global.html#addButtonHelp">addButtonHelp</a></li><li><a href="global.html#addCheckbox">addCheckbox</a></li><li><a href="global.html#addDiv">addDiv</a></li><li><a href="global.html#addHeader">addHeader</a></li><li><a href="global.html#addHr">addHr</a></li><li><a href="global.html#addImg">addImg</a></li><li><a href="global.html#addInput">addInput</a></li><li><a href="global.html#addInputFile">addInputFile</a></li><li><a href="global.html#addP">addP</a></li><li><a href="global.html#addSmall">addSmall</a></li><li><a href="global.html#addTextarea">addTextarea</a></li><li><a href="global.html#base64ToUint8">base64ToUint8</a></li><li><a href="global.html#buildElement">buildElement</a></li><li><a href="global.html#buildOverlay">buildOverlay</a></li><li><a href="global.html#buildOverlayMain">buildOverlayMain</a></li><li><a href="global.html#consoleError">consoleError</a></li><li><a href="global.html#consoleLog">consoleLog</a></li><li><a href="global.html#consoleWarn">consoleWarn</a></li><li><a href="global.html#createJSON">createJSON</a></li><li><a href="global.html#createObserverBody">createObserverBody</a></li><li><a href="global.html#createTemplate">createTemplate</a></li><li><a href="global.html#createTemplateTiles">createTemplateTiles</a></li><li><a href="global.html#deleteTemplate">deleteTemplate</a></li><li><a href="global.html#disableTemplate">disableTemplate</a></li><li><a href="global.html#drawTemplateOnTile">drawTemplateOnTile</a></li><li><a href="global.html#escapeHTML">escapeHTML</a></li><li><a href="global.html#getObserverBody">getObserverBody</a></li><li><a href="global.html#handleDisplayError">handleDisplayError</a></li><li><a href="global.html#handleDisplayStatus">handleDisplayStatus</a></li><li><a href="global.html#handleDrag">handleDrag</a></li><li><a href="global.html#importJSON">importJSON</a></li><li><a href="global.html#inject">inject</a></li><li><a href="global.html#negativeSafeModulo">negativeSafeModulo</a></li><li><a href="global.html#numberToEncoded">numberToEncoded</a></li><li><a href="global.html#observe">observe</a></li><li><a href="global.html#observeBlack">observeBlack</a></li><li><a href="global.html#serverTPtoDisplayTP">serverTPtoDisplayTP</a></li><li><a href="global.html#setApiManager">setApiManager</a></li><li><a href="global.html#setTemplatesShouldBeDrawn">setTemplatesShouldBeDrawn</a></li><li><a href="global.html#spontaneousResponseListener">spontaneousResponseListener</a></li><li><a href="global.html#uint8ToBase64">uint8ToBase64</a></li><li><a href="global.html#updateInnerHTML">updateInnerHTML</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Fri Aug 08 2025 15:52:04 GMT-0400 (Eastern Daylight Time)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
||||
230
wiki/Template.js.html
Normal file
230
wiki/Template.js.html
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: Template.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: Template.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>import { uint8ToBase64 } from "./utils";
|
||||
|
||||
/** An instance of a template.
|
||||
* Handles all mathematics, manipulation, and analysis regarding a single template.
|
||||
* @since 0.65.2
|
||||
*/
|
||||
export default class Template {
|
||||
|
||||
/** The constructor for the {@link Template} class with enhanced pixel tracking.
|
||||
* @param {Object} [params={}] - Object containing all optional parameters
|
||||
* @param {string} [params.displayName='My template'] - The display name of the template
|
||||
* @param {number} [params.sortID=0] - The sort number of the template for rendering priority
|
||||
* @param {string} [params.authorID=''] - The user ID of the person who exported the template (prevents sort ID collisions)
|
||||
* @param {string} [params.url=''] - The URL to the source image
|
||||
* @param {File} [params.file=null] - The template file (pre-processed File or processed bitmap)
|
||||
* @param {Array<number>} [params.coords=null] - The coordinates of the top left corner as (tileX, tileY, pixelX, pixelY)
|
||||
* @param {Object} [params.chunked=null] - The affected chunks of the template, and their template for each chunk
|
||||
* @param {number} [params.tileSize=1000] - The size of a tile in pixels (assumes square tiles)
|
||||
* @param {number} [params.pixelCount=0] - Total number of pixels in the template (calculated automatically during processing)
|
||||
* @since 0.65.2
|
||||
*/
|
||||
constructor({
|
||||
displayName = 'My template',
|
||||
sortID = 0,
|
||||
authorID = '',
|
||||
url = '',
|
||||
file = null,
|
||||
coords = null,
|
||||
chunked = null,
|
||||
tileSize = 1000,
|
||||
} = {}) {
|
||||
this.displayName = displayName;
|
||||
this.sortID = sortID;
|
||||
this.authorID = authorID;
|
||||
this.url = url;
|
||||
this.file = file;
|
||||
this.coords = coords;
|
||||
this.chunked = chunked;
|
||||
this.tileSize = tileSize;
|
||||
this.pixelCount = 0; // Total pixel count in template
|
||||
}
|
||||
|
||||
/** Creates chunks of the template for each tile.
|
||||
*
|
||||
* @returns {Object} Collection of template bitmaps & buffers organized by tile coordinates
|
||||
* @since 0.65.4
|
||||
*/
|
||||
async createTemplateTiles() {
|
||||
console.log('Template coordinates:', this.coords);
|
||||
|
||||
const shreadSize = 3; // Scale image factor for pixel art enhancement (must be odd)
|
||||
const bitmap = await createImageBitmap(this.file); // Create efficient bitmap from uploaded file
|
||||
const imageWidth = bitmap.width;
|
||||
const imageHeight = bitmap.height;
|
||||
|
||||
// Calculate total pixel count using standard width × height formula
|
||||
// TODO: Use non-transparent pixels instead of basic width times height
|
||||
const totalPixels = imageWidth * imageHeight;
|
||||
console.log(`Template pixel analysis - Dimensions: ${imageWidth}×${imageHeight} = ${totalPixels.toLocaleString()} pixels`);
|
||||
|
||||
// Store pixel count in instance property for access by template manager and UI components
|
||||
this.pixelCount = totalPixels;
|
||||
|
||||
const templateTiles = {}; // Holds the template tiles
|
||||
const templateTilesBuffers = {}; // Holds the buffers of the template tiles
|
||||
|
||||
const canvas = new OffscreenCanvas(this.tileSize, this.tileSize);
|
||||
const context = canvas.getContext('2d', { willReadFrequently: true });
|
||||
|
||||
// For every tile...
|
||||
for (let pixelY = this.coords[3]; pixelY < imageHeight + this.coords[3]; ) {
|
||||
|
||||
// Draws the partial tile first, if any
|
||||
// This calculates the size based on which is smaller:
|
||||
// A. The top left corner of the current tile to the bottom right corner of the current tile
|
||||
// B. The top left corner of the current tile to the bottom right corner of the image
|
||||
const drawSizeY = Math.min(this.tileSize - (pixelY % this.tileSize), imageHeight - (pixelY - this.coords[3]));
|
||||
|
||||
console.log(`Math.min(${this.tileSize} - (${pixelY} % ${this.tileSize}), ${imageHeight} - (${pixelY - this.coords[3]}))`);
|
||||
|
||||
for (let pixelX = this.coords[2]; pixelX < imageWidth + this.coords[2];) {
|
||||
|
||||
console.log(`Pixel X: ${pixelX}\nPixel Y: ${pixelY}`);
|
||||
|
||||
// Draws the partial tile first, if any
|
||||
// This calculates the size based on which is smaller:
|
||||
// A. The top left corner of the current tile to the bottom right corner of the current tile
|
||||
// B. The top left corner of the current tile to the bottom right corner of the image
|
||||
const drawSizeX = Math.min(this.tileSize - (pixelX % this.tileSize), imageWidth - (pixelX - this.coords[2]));
|
||||
|
||||
console.log(`Math.min(${this.tileSize} - (${pixelX} % ${this.tileSize}), ${imageWidth} - (${pixelX - this.coords[2]}))`);
|
||||
|
||||
console.log(`Draw Size X: ${drawSizeX}\nDraw Size Y: ${drawSizeY}`);
|
||||
|
||||
// Change the canvas size and wipe the canvas
|
||||
const canvasWidth = drawSizeX * shreadSize;// + (pixelX % this.tileSize) * shreadSize;
|
||||
const canvasHeight = drawSizeY * shreadSize;// + (pixelY % this.tileSize) * shreadSize;
|
||||
canvas.width = canvasWidth;
|
||||
canvas.height = canvasHeight;
|
||||
|
||||
console.log(`Draw X: ${drawSizeX}\nDraw Y: ${drawSizeY}\nCanvas Width: ${canvasWidth}\nCanvas Height: ${canvasHeight}`);
|
||||
|
||||
context.imageSmoothingEnabled = false; // Nearest neighbor
|
||||
|
||||
console.log(`Getting X ${pixelX}-${pixelX + drawSizeX}\nGetting Y ${pixelY}-${pixelY + drawSizeY}`);
|
||||
|
||||
// Draws the template segment on this tile segment
|
||||
context.clearRect(0, 0, canvasWidth, canvasHeight); // Clear any previous drawing (only runs when canvas size does not change)
|
||||
context.drawImage(
|
||||
bitmap, // Bitmap image to draw
|
||||
pixelX - this.coords[2], // Coordinate X to draw from
|
||||
pixelY - this.coords[3], // Coordinate Y to draw from
|
||||
drawSizeX, // X width to draw from
|
||||
drawSizeY, // Y height to draw from
|
||||
0, // Coordinate X to draw at
|
||||
0, // Coordinate Y to draw at
|
||||
drawSizeX * shreadSize, // X width to draw at
|
||||
drawSizeY * shreadSize // Y height to draw at
|
||||
); // Coordinates and size of draw area of source image, then canvas
|
||||
|
||||
// const final = await canvas.convertToBlob({ type: 'image/png' });
|
||||
// const url = URL.createObjectURL(final); // Creates a blob URL
|
||||
// window.open(url, '_blank'); // Opens a new tab with blob
|
||||
// setTimeout(() => URL.revokeObjectURL(url), 60000); // Destroys the blob 1 minute later
|
||||
|
||||
const imageData = context.getImageData(0, 0, canvasWidth, canvasHeight); // Data of the image on the canvas
|
||||
|
||||
for (let y = 0; y < canvasHeight; y++) {
|
||||
for (let x = 0; x < canvasWidth; x++) {
|
||||
// For every pixel...
|
||||
|
||||
// ... Make it transparent unless it is the "center"
|
||||
if (x % shreadSize !== 1 || y % shreadSize !== 1) {
|
||||
const pixelIndex = (y * canvasWidth + x) * 4; // Find the pixel index in an array where every 4 indexes are 1 pixel
|
||||
imageData.data[pixelIndex + 3] = 0; // Make the pixel transparent on the alpha channel
|
||||
|
||||
// if (!!imageData.data[pixelIndex + 3]) {
|
||||
// imageData.data[pixelIndex + 3] = 50; // Alpha
|
||||
// imageData.data[pixelIndex] = 30; // Red
|
||||
// imageData.data[pixelIndex + 1] = 30; // Green
|
||||
// imageData.data[pixelIndex + 2] = 30; // Blue
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Shreaded pixels for ${pixelX}, ${pixelY}`, imageData);
|
||||
|
||||
context.putImageData(imageData, 0, 0);
|
||||
|
||||
// Creates the "0000,0000,000,000" key name
|
||||
const templateTileName = `${(this.coords[0] + Math.floor(pixelX / 1000))
|
||||
.toString()
|
||||
.padStart(4, '0')},${(this.coords[1] + Math.floor(pixelY / 1000))
|
||||
.toString()
|
||||
.padStart(4, '0')},${(pixelX % 1000)
|
||||
.toString()
|
||||
.padStart(3, '0')},${(pixelY % 1000).toString().padStart(3, '0')}`;
|
||||
|
||||
templateTiles[templateTileName] = await createImageBitmap(canvas); // Creates the bitmap
|
||||
|
||||
const canvasBlob = await canvas.convertToBlob();
|
||||
const canvasBuffer = await canvasBlob.arrayBuffer();
|
||||
const canvasBufferBytes = Array.from(new Uint8Array(canvasBuffer));
|
||||
templateTilesBuffers[templateTileName] = uint8ToBase64(canvasBufferBytes); // Stores the buffer
|
||||
|
||||
console.log(templateTiles);
|
||||
|
||||
pixelX += drawSizeX;
|
||||
}
|
||||
|
||||
pixelY += drawSizeY;
|
||||
}
|
||||
|
||||
console.log('Template Tiles: ', templateTiles);
|
||||
console.log('Template Tiles Buffers: ', templateTilesBuffers);
|
||||
return { templateTiles, templateTilesBuffers };
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="module.exports.html">exports</a></li><li><a href="module.exports_module.exports.html">exports</a></li></ul><h3>Global</h3><ul><li><a href="global.html#addBr">addBr</a></li><li><a href="global.html#addButton">addButton</a></li><li><a href="global.html#addButtonHelp">addButtonHelp</a></li><li><a href="global.html#addCheckbox">addCheckbox</a></li><li><a href="global.html#addDiv">addDiv</a></li><li><a href="global.html#addHeader">addHeader</a></li><li><a href="global.html#addHr">addHr</a></li><li><a href="global.html#addImg">addImg</a></li><li><a href="global.html#addInput">addInput</a></li><li><a href="global.html#addInputFile">addInputFile</a></li><li><a href="global.html#addP">addP</a></li><li><a href="global.html#addSmall">addSmall</a></li><li><a href="global.html#addTextarea">addTextarea</a></li><li><a href="global.html#base64ToUint8">base64ToUint8</a></li><li><a href="global.html#buildElement">buildElement</a></li><li><a href="global.html#buildOverlay">buildOverlay</a></li><li><a href="global.html#buildOverlayMain">buildOverlayMain</a></li><li><a href="global.html#consoleError">consoleError</a></li><li><a href="global.html#consoleLog">consoleLog</a></li><li><a href="global.html#consoleWarn">consoleWarn</a></li><li><a href="global.html#createJSON">createJSON</a></li><li><a href="global.html#createObserverBody">createObserverBody</a></li><li><a href="global.html#createTemplate">createTemplate</a></li><li><a href="global.html#createTemplateTiles">createTemplateTiles</a></li><li><a href="global.html#deleteTemplate">deleteTemplate</a></li><li><a href="global.html#disableTemplate">disableTemplate</a></li><li><a href="global.html#drawTemplateOnTile">drawTemplateOnTile</a></li><li><a href="global.html#escapeHTML">escapeHTML</a></li><li><a href="global.html#getObserverBody">getObserverBody</a></li><li><a href="global.html#handleDisplayError">handleDisplayError</a></li><li><a href="global.html#handleDisplayStatus">handleDisplayStatus</a></li><li><a href="global.html#handleDrag">handleDrag</a></li><li><a href="global.html#importJSON">importJSON</a></li><li><a href="global.html#inject">inject</a></li><li><a href="global.html#negativeSafeModulo">negativeSafeModulo</a></li><li><a href="global.html#numberToEncoded">numberToEncoded</a></li><li><a href="global.html#observe">observe</a></li><li><a href="global.html#observeBlack">observeBlack</a></li><li><a href="global.html#serverTPtoDisplayTP">serverTPtoDisplayTP</a></li><li><a href="global.html#setApiManager">setApiManager</a></li><li><a href="global.html#setTemplatesShouldBeDrawn">setTemplatesShouldBeDrawn</a></li><li><a href="global.html#spontaneousResponseListener">spontaneousResponseListener</a></li><li><a href="global.html#uint8ToBase64">uint8ToBase64</a></li><li><a href="global.html#updateInnerHTML">updateInnerHTML</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Fri Aug 08 2025 15:52:04 GMT-0400 (Eastern Daylight Time)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
||||
193
wiki/apiManager.js.html
Normal file
193
wiki/apiManager.js.html
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: apiManager.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: apiManager.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/** ApiManager class for handling API requests, responses, and interactions.
|
||||
* Note: Fetch spying is done in main.js, not here.
|
||||
* @since 0.11.1
|
||||
*/
|
||||
|
||||
import TemplateManager from "./templateManager.js";
|
||||
import { escapeHTML, numberToEncoded, serverTPtoDisplayTP } from "./utils.js";
|
||||
|
||||
export default class ApiManager {
|
||||
|
||||
/** Constructor for ApiManager class
|
||||
* @param {TemplateManager} templateManager
|
||||
* @since 0.11.34
|
||||
*/
|
||||
constructor(templateManager) {
|
||||
this.templateManager = templateManager;
|
||||
this.disableAll = false; // Should the entire userscript be disabled?
|
||||
this.coordsTilePixel = []; // Contains the last detected tile/pixel coordinate pair requested
|
||||
this.templateCoordsTilePixel = []; // Contains the last "enabled" template coords
|
||||
}
|
||||
|
||||
/** Determines if the spontaneously recieved response is something we want.
|
||||
* Otherwise, we can ignore it.
|
||||
* Note: Due to aggressive compression, make your calls like `data['jsonData']['name']` instead of `data.jsonData.name`
|
||||
*
|
||||
* @param {Overlay} overlay - The Overlay class instance
|
||||
* @since 0.11.1
|
||||
*/
|
||||
spontaneousResponseListener(overlay) {
|
||||
|
||||
// Triggers whenever a message is sent
|
||||
window.addEventListener('message', async (event) => {
|
||||
|
||||
const data = event.data; // The data of the message
|
||||
const dataJSON = data['jsonData']; // The JSON response, if any
|
||||
|
||||
// Kills itself if the message was not intended for Blue Marble
|
||||
if (!(data && data['source'] === 'blue-marble')) {return;}
|
||||
|
||||
// Kills itself if the message has no endpoint (intended for Blue Marble, but not this function)
|
||||
if (!data['endpoint']) {return;}
|
||||
|
||||
// Trims endpoint to the second to last non-number, non-null directoy.
|
||||
// E.g. "wplace.live/api/pixel/0/0?payload" -> "pixel"
|
||||
// E.g. "wplace.live/api/files/s0/tiles/0/0/0.png" -> "tiles"
|
||||
const endpointText = data['endpoint']?.split('?')[0].split('/').filter(s => s && isNaN(Number(s))).filter(s => s && !s.includes('.')).pop();
|
||||
|
||||
console.log(`%cBlue Marble%c: Recieved message about "%s"`, 'color: cornflowerblue;', '', endpointText);
|
||||
|
||||
// Each case is something that Blue Marble can use from the fetch.
|
||||
// For instance, if the fetch was for "me", we can update the overlay stats
|
||||
switch (endpointText) {
|
||||
|
||||
case 'me': // Request to retrieve user data
|
||||
|
||||
// If the game can not retrieve the userdata...
|
||||
if (dataJSON['status'] && dataJSON['status']?.toString()[0] != '2') {
|
||||
// The server is probably down (NOT a 2xx status)
|
||||
|
||||
overlay.handleDisplayError(`You are not logged in!\nCould not fetch userdata.`);
|
||||
return; // Kills itself before attempting to display null userdata
|
||||
}
|
||||
|
||||
const nextLevelPixels = Math.ceil(Math.pow(Math.floor(dataJSON['level']) * Math.pow(30, 0.65), (1/0.65)) - dataJSON['pixelsPainted']); // Calculates pixels to the next level
|
||||
|
||||
console.log(dataJSON['id']);
|
||||
if (!!dataJSON['id'] || dataJSON['id'] === 0) {
|
||||
console.log(numberToEncoded(
|
||||
dataJSON['id'],
|
||||
'!#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~'
|
||||
));
|
||||
}
|
||||
this.templateManager.userID = dataJSON['id'];
|
||||
|
||||
overlay.updateInnerHTML('bm-user-name', `Username: <b>${escapeHTML(dataJSON['name'])}</b>`); // Updates the text content of the username field
|
||||
overlay.updateInnerHTML('bm-user-droplets', `Droplets: <b>${new Intl.NumberFormat().format(dataJSON['droplets'])}</b>`); // Updates the text content of the droplets field
|
||||
overlay.updateInnerHTML('bm-user-nextlevel', `Next level in <b>${new Intl.NumberFormat().format(nextLevelPixels)}</b> pixel${nextLevelPixels == 1 ? '' : 's'}`); // Updates the text content of the next level field
|
||||
break;
|
||||
|
||||
case 'pixel': // Request to retrieve pixel data
|
||||
const coordsTile = data['endpoint'].split('?')[0].split('/').filter(s => s && !isNaN(Number(s))); // Retrieves the tile coords as [x, y]
|
||||
const payloadExtractor = new URLSearchParams(data['endpoint'].split('?')[1]); // Declares a new payload deconstructor and passes in the fetch request payload
|
||||
const coordsPixel = [payloadExtractor.get('x'), payloadExtractor.get('y')]; // Retrieves the deconstructed pixel coords from the payload
|
||||
|
||||
// Don't save the coords if there are previous coords that could be used
|
||||
if (this.coordsTilePixel.length && (!coordsTile.length || !coordsPixel.length)) {
|
||||
overlay.handleDisplayError(`Coordinates are malformed!\nDid you try clicking the canvas first?`);
|
||||
return; // Kills itself
|
||||
}
|
||||
|
||||
this.coordsTilePixel = [...coordsTile, ...coordsPixel]; // Combines the two arrays such that [x, y, x, y]
|
||||
const displayTP = serverTPtoDisplayTP(coordsTile, coordsPixel);
|
||||
|
||||
const spanElements = document.querySelectorAll('span'); // Retrieves all span elements
|
||||
|
||||
// For every span element, find the one we want (pixel numbers when canvas clicked)
|
||||
for (const element of spanElements) {
|
||||
if (element.textContent.trim().includes(`${displayTP[0]}, ${displayTP[1]}`)) {
|
||||
|
||||
let displayCoords = document.querySelector('#bm-display-coords'); // Find the additional pixel coords span
|
||||
|
||||
const text = `(Tl X: ${coordsTile[0]}, Tl Y: ${coordsTile[1]}, Px X: ${coordsPixel[0]}, Px Y: ${coordsPixel[1]})`;
|
||||
|
||||
// If we could not find the addition coord span, we make it then update the textContent with the new coords
|
||||
if (!displayCoords) {
|
||||
displayCoords = document.createElement('span');
|
||||
displayCoords.id = 'bm-display-coords';
|
||||
displayCoords.textContent = text;
|
||||
displayCoords.style = 'margin-left: calc(var(--spacing)*3); font-size: small;';
|
||||
element.parentNode.parentNode.parentNode.insertAdjacentElement('afterend', displayCoords);
|
||||
} else {
|
||||
displayCoords.textContent = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'tiles':
|
||||
|
||||
// Runs only if the tile has the template
|
||||
let tileCoordsTile = data['endpoint'].split('/');
|
||||
tileCoordsTile = [parseInt(tileCoordsTile[tileCoordsTile.length - 2]), parseInt(tileCoordsTile[tileCoordsTile.length - 1].replace('.png', ''))];
|
||||
|
||||
const blobUUID = data['blobID'];
|
||||
const blobData = data['blobData'];
|
||||
|
||||
const templateBlob = await this.templateManager.drawTemplateOnTile(blobData, tileCoordsTile);
|
||||
|
||||
window.postMessage({
|
||||
source: 'blue-marble',
|
||||
blobID: blobUUID,
|
||||
blobData: templateBlob,
|
||||
blink: data['blink']
|
||||
});
|
||||
break;
|
||||
|
||||
case 'robots': // Request to retrieve what script types are allowed
|
||||
this.disableAll = dataJSON['userscript']?.toString().toLowerCase() == 'false'; // Disables Blue Marble if site owner wants userscripts disabled
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="module.exports.html">exports</a></li><li><a href="module.exports_module.exports.html">exports</a></li></ul><h3>Global</h3><ul><li><a href="global.html#addBr">addBr</a></li><li><a href="global.html#addButton">addButton</a></li><li><a href="global.html#addButtonHelp">addButtonHelp</a></li><li><a href="global.html#addCheckbox">addCheckbox</a></li><li><a href="global.html#addDiv">addDiv</a></li><li><a href="global.html#addHeader">addHeader</a></li><li><a href="global.html#addHr">addHr</a></li><li><a href="global.html#addImg">addImg</a></li><li><a href="global.html#addInput">addInput</a></li><li><a href="global.html#addInputFile">addInputFile</a></li><li><a href="global.html#addP">addP</a></li><li><a href="global.html#addSmall">addSmall</a></li><li><a href="global.html#addTextarea">addTextarea</a></li><li><a href="global.html#base64ToUint8">base64ToUint8</a></li><li><a href="global.html#buildElement">buildElement</a></li><li><a href="global.html#buildOverlay">buildOverlay</a></li><li><a href="global.html#buildOverlayMain">buildOverlayMain</a></li><li><a href="global.html#consoleError">consoleError</a></li><li><a href="global.html#consoleLog">consoleLog</a></li><li><a href="global.html#consoleWarn">consoleWarn</a></li><li><a href="global.html#createJSON">createJSON</a></li><li><a href="global.html#createObserverBody">createObserverBody</a></li><li><a href="global.html#createTemplate">createTemplate</a></li><li><a href="global.html#createTemplateTiles">createTemplateTiles</a></li><li><a href="global.html#deleteTemplate">deleteTemplate</a></li><li><a href="global.html#disableTemplate">disableTemplate</a></li><li><a href="global.html#drawTemplateOnTile">drawTemplateOnTile</a></li><li><a href="global.html#escapeHTML">escapeHTML</a></li><li><a href="global.html#getObserverBody">getObserverBody</a></li><li><a href="global.html#handleDisplayError">handleDisplayError</a></li><li><a href="global.html#handleDisplayStatus">handleDisplayStatus</a></li><li><a href="global.html#handleDrag">handleDrag</a></li><li><a href="global.html#importJSON">importJSON</a></li><li><a href="global.html#inject">inject</a></li><li><a href="global.html#negativeSafeModulo">negativeSafeModulo</a></li><li><a href="global.html#numberToEncoded">numberToEncoded</a></li><li><a href="global.html#observe">observe</a></li><li><a href="global.html#observeBlack">observeBlack</a></li><li><a href="global.html#serverTPtoDisplayTP">serverTPtoDisplayTP</a></li><li><a href="global.html#setApiManager">setApiManager</a></li><li><a href="global.html#setTemplatesShouldBeDrawn">setTemplatesShouldBeDrawn</a></li><li><a href="global.html#spontaneousResponseListener">spontaneousResponseListener</a></li><li><a href="global.html#uint8ToBase64">uint8ToBase64</a></li><li><a href="global.html#updateInnerHTML">updateInnerHTML</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Fri Aug 08 2025 15:52:04 GMT-0400 (Eastern Daylight Time)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
||||
BIN
wiki/fonts/OpenSans-Bold-webfont.eot
Normal file
BIN
wiki/fonts/OpenSans-Bold-webfont.eot
Normal file
Binary file not shown.
1830
wiki/fonts/OpenSans-Bold-webfont.svg
Normal file
1830
wiki/fonts/OpenSans-Bold-webfont.svg
Normal file
File diff suppressed because it is too large
Load diff
|
After Width: | Height: | Size: 116 KiB |
BIN
wiki/fonts/OpenSans-Bold-webfont.woff
Normal file
BIN
wiki/fonts/OpenSans-Bold-webfont.woff
Normal file
Binary file not shown.
BIN
wiki/fonts/OpenSans-BoldItalic-webfont.eot
Normal file
BIN
wiki/fonts/OpenSans-BoldItalic-webfont.eot
Normal file
Binary file not shown.
1830
wiki/fonts/OpenSans-BoldItalic-webfont.svg
Normal file
1830
wiki/fonts/OpenSans-BoldItalic-webfont.svg
Normal file
File diff suppressed because it is too large
Load diff
|
After Width: | Height: | Size: 118 KiB |
BIN
wiki/fonts/OpenSans-BoldItalic-webfont.woff
Normal file
BIN
wiki/fonts/OpenSans-BoldItalic-webfont.woff
Normal file
Binary file not shown.
BIN
wiki/fonts/OpenSans-Italic-webfont.eot
Normal file
BIN
wiki/fonts/OpenSans-Italic-webfont.eot
Normal file
Binary file not shown.
1830
wiki/fonts/OpenSans-Italic-webfont.svg
Normal file
1830
wiki/fonts/OpenSans-Italic-webfont.svg
Normal file
File diff suppressed because it is too large
Load diff
|
After Width: | Height: | Size: 120 KiB |
BIN
wiki/fonts/OpenSans-Italic-webfont.woff
Normal file
BIN
wiki/fonts/OpenSans-Italic-webfont.woff
Normal file
Binary file not shown.
BIN
wiki/fonts/OpenSans-Light-webfont.eot
Normal file
BIN
wiki/fonts/OpenSans-Light-webfont.eot
Normal file
Binary file not shown.
1831
wiki/fonts/OpenSans-Light-webfont.svg
Normal file
1831
wiki/fonts/OpenSans-Light-webfont.svg
Normal file
File diff suppressed because it is too large
Load diff
|
After Width: | Height: | Size: 114 KiB |
BIN
wiki/fonts/OpenSans-Light-webfont.woff
Normal file
BIN
wiki/fonts/OpenSans-Light-webfont.woff
Normal file
Binary file not shown.
BIN
wiki/fonts/OpenSans-LightItalic-webfont.eot
Normal file
BIN
wiki/fonts/OpenSans-LightItalic-webfont.eot
Normal file
Binary file not shown.
1835
wiki/fonts/OpenSans-LightItalic-webfont.svg
Normal file
1835
wiki/fonts/OpenSans-LightItalic-webfont.svg
Normal file
File diff suppressed because it is too large
Load diff
|
After Width: | Height: | Size: 120 KiB |
BIN
wiki/fonts/OpenSans-LightItalic-webfont.woff
Normal file
BIN
wiki/fonts/OpenSans-LightItalic-webfont.woff
Normal file
Binary file not shown.
BIN
wiki/fonts/OpenSans-Regular-webfont.eot
Normal file
BIN
wiki/fonts/OpenSans-Regular-webfont.eot
Normal file
Binary file not shown.
1831
wiki/fonts/OpenSans-Regular-webfont.svg
Normal file
1831
wiki/fonts/OpenSans-Regular-webfont.svg
Normal file
File diff suppressed because it is too large
Load diff
|
After Width: | Height: | Size: 117 KiB |
BIN
wiki/fonts/OpenSans-Regular-webfont.woff
Normal file
BIN
wiki/fonts/OpenSans-Regular-webfont.woff
Normal file
Binary file not shown.
7664
wiki/global.html
Normal file
7664
wiki/global.html
Normal file
File diff suppressed because it is too large
Load diff
65
wiki/index.html
Normal file
65
wiki/index.html
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Home</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Home</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3> </h3>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="module.exports.html">exports</a></li><li><a href="module.exports_module.exports.html">exports</a></li></ul><h3>Global</h3><ul><li><a href="global.html#addBr">addBr</a></li><li><a href="global.html#addButton">addButton</a></li><li><a href="global.html#addButtonHelp">addButtonHelp</a></li><li><a href="global.html#addCheckbox">addCheckbox</a></li><li><a href="global.html#addDiv">addDiv</a></li><li><a href="global.html#addHeader">addHeader</a></li><li><a href="global.html#addHr">addHr</a></li><li><a href="global.html#addImg">addImg</a></li><li><a href="global.html#addInput">addInput</a></li><li><a href="global.html#addInputFile">addInputFile</a></li><li><a href="global.html#addP">addP</a></li><li><a href="global.html#addSmall">addSmall</a></li><li><a href="global.html#addTextarea">addTextarea</a></li><li><a href="global.html#base64ToUint8">base64ToUint8</a></li><li><a href="global.html#buildElement">buildElement</a></li><li><a href="global.html#buildOverlay">buildOverlay</a></li><li><a href="global.html#buildOverlayMain">buildOverlayMain</a></li><li><a href="global.html#consoleError">consoleError</a></li><li><a href="global.html#consoleLog">consoleLog</a></li><li><a href="global.html#consoleWarn">consoleWarn</a></li><li><a href="global.html#createJSON">createJSON</a></li><li><a href="global.html#createObserverBody">createObserverBody</a></li><li><a href="global.html#createTemplate">createTemplate</a></li><li><a href="global.html#createTemplateTiles">createTemplateTiles</a></li><li><a href="global.html#deleteTemplate">deleteTemplate</a></li><li><a href="global.html#disableTemplate">disableTemplate</a></li><li><a href="global.html#drawTemplateOnTile">drawTemplateOnTile</a></li><li><a href="global.html#escapeHTML">escapeHTML</a></li><li><a href="global.html#getObserverBody">getObserverBody</a></li><li><a href="global.html#handleDisplayError">handleDisplayError</a></li><li><a href="global.html#handleDisplayStatus">handleDisplayStatus</a></li><li><a href="global.html#handleDrag">handleDrag</a></li><li><a href="global.html#importJSON">importJSON</a></li><li><a href="global.html#inject">inject</a></li><li><a href="global.html#negativeSafeModulo">negativeSafeModulo</a></li><li><a href="global.html#numberToEncoded">numberToEncoded</a></li><li><a href="global.html#observe">observe</a></li><li><a href="global.html#observeBlack">observeBlack</a></li><li><a href="global.html#serverTPtoDisplayTP">serverTPtoDisplayTP</a></li><li><a href="global.html#setApiManager">setApiManager</a></li><li><a href="global.html#setTemplatesShouldBeDrawn">setTemplatesShouldBeDrawn</a></li><li><a href="global.html#spontaneousResponseListener">spontaneousResponseListener</a></li><li><a href="global.html#uint8ToBase64">uint8ToBase64</a></li><li><a href="global.html#updateInnerHTML">updateInnerHTML</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Fri Aug 08 2025 15:52:04 GMT-0400 (Eastern Daylight Time)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
||||
618
wiki/main.js.html
Normal file
618
wiki/main.js.html
Normal file
|
|
@ -0,0 +1,618 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: main.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: main.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/** The main file. Everything in the userscript is executed from here.
|
||||
* @since 0.0.0
|
||||
*/
|
||||
|
||||
import Overlay from './Overlay.js';
|
||||
import Observers from './observers.js';
|
||||
import ApiManager from './apiManager.js';
|
||||
import TemplateManager from './templateManager.js';
|
||||
import { consoleLog, consoleWarn } from './utils.js';
|
||||
|
||||
const name = GM_info.script.name.toString(); // Name of userscript
|
||||
const version = GM_info.script.version.toString(); // Version of userscript
|
||||
const consoleStyle = 'color: cornflowerblue;'; // The styling for the console logs
|
||||
|
||||
/** Injects code into the client
|
||||
* This code will execute outside of TamperMonkey's sandbox
|
||||
* @param {*} callback - The code to execute
|
||||
* @since 0.11.15
|
||||
*/
|
||||
function inject(callback) {
|
||||
const script = document.createElement('script');
|
||||
script.setAttribute('bm-name', name); // Passes in the name value
|
||||
script.setAttribute('bm-cStyle', consoleStyle); // Passes in the console style value
|
||||
script.textContent = `(${callback})();`;
|
||||
document.documentElement?.appendChild(script);
|
||||
script.remove();
|
||||
}
|
||||
|
||||
/** What code to execute instantly in the client (webpage) to spy on fetch calls.
|
||||
* This code will execute outside of TamperMonkey's sandbox.
|
||||
* @since 0.11.15
|
||||
*/
|
||||
inject(() => {
|
||||
|
||||
const script = document.currentScript; // Gets the current script HTML Script Element
|
||||
const name = script?.getAttribute('bm-name') || 'Blue Marble'; // Gets the name value that was passed in. Defaults to "Blue Marble" if nothing was found
|
||||
const consoleStyle = script?.getAttribute('bm-cStyle') || ''; // Gets the console style value that was passed in. Defaults to no styling if nothing was found
|
||||
const fetchedBlobQueue = new Map(); // Blobs being processed
|
||||
|
||||
window.addEventListener('message', (event) => {
|
||||
const { source, endpoint, blobID, blobData, blink } = event.data;
|
||||
|
||||
const elapsed = Date.now() - blink;
|
||||
|
||||
// Since this code does not run in the userscript, we can't use consoleLog().
|
||||
console.groupCollapsed(`%c${name}%c: ${fetchedBlobQueue.size} Recieved IMAGE message about blob "${blobID}"`, consoleStyle, '');
|
||||
console.log(`Blob fetch took %c${String(Math.floor(elapsed/60000)).padStart(2,'0')}:${String(Math.floor(elapsed/1000) % 60).padStart(2,'0')}.${String(elapsed % 1000).padStart(3,'0')}%c MM:SS.mmm`, consoleStyle, '');
|
||||
console.log(fetchedBlobQueue);
|
||||
console.groupEnd();
|
||||
|
||||
// The modified blob won't have an endpoint, so we ignore any message without one.
|
||||
if ((source == 'blue-marble') && !!blobID && !!blobData && !endpoint) {
|
||||
|
||||
const callback = fetchedBlobQueue.get(blobID); // Retrieves the blob based on the UUID
|
||||
|
||||
// If the blobID is a valid function...
|
||||
if (typeof callback === 'function') {
|
||||
|
||||
callback(blobData); // ...Retrieve the blob data from the blobID function
|
||||
} else {
|
||||
// ...else the blobID is unexpected. We don't know what it is, but we know for sure it is not a blob. This means we ignore it.
|
||||
|
||||
consoleWarn(`%c${name}%c: Attempted to retrieve a blob (%s) from queue, but the blobID was not a function! Skipping...`, consoleStyle, '', blobID);
|
||||
}
|
||||
|
||||
fetchedBlobQueue.delete(blobID); // Delete the blob from the queue, because we don't need to process it again
|
||||
}
|
||||
});
|
||||
|
||||
// Spys on "spontaneous" fetch requests made by the client
|
||||
const originalFetch = window.fetch; // Saves a copy of the original fetch
|
||||
|
||||
// Overrides fetch
|
||||
window.fetch = async function(...args) {
|
||||
|
||||
const response = await originalFetch.apply(this, args); // Sends a fetch
|
||||
const cloned = response.clone(); // Makes a copy of the response
|
||||
|
||||
// Retrieves the endpoint name. Unknown endpoint = "ignore"
|
||||
const endpointName = ((args[0] instanceof Request) ? args[0]?.url : args[0]) || 'ignore';
|
||||
|
||||
// Check Content-Type to only process JSON
|
||||
const contentType = cloned.headers.get('content-type') || '';
|
||||
if (contentType.includes('application/json')) {
|
||||
|
||||
|
||||
// Since this code does not run in the userscript, we can't use consoleLog().
|
||||
console.log(`%c${name}%c: Sending JSON message about endpoint "${endpointName}"`, consoleStyle, '');
|
||||
|
||||
// Sends a message about the endpoint it spied on
|
||||
cloned.json()
|
||||
.then(jsonData => {
|
||||
window.postMessage({
|
||||
source: 'blue-marble',
|
||||
endpoint: endpointName,
|
||||
jsonData: jsonData
|
||||
}, '*');
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(`%c${name}%c: Failed to parse JSON: `, consoleStyle, '', err);
|
||||
});
|
||||
} else if (contentType.includes('image/') && (!endpointName.includes('openfreemap'))) {
|
||||
// Fetch custom for all images but opensourcemap
|
||||
|
||||
const blink = Date.now(); // Current time
|
||||
|
||||
const blob = await cloned.blob(); // The original blob
|
||||
|
||||
// Since this code does not run in the userscript, we can't use consoleLog().
|
||||
console.log(`%c${name}%c: ${fetchedBlobQueue.size} Sending IMAGE message about endpoint "${endpointName}"`, consoleStyle, '');
|
||||
|
||||
// Returns the manipulated blob
|
||||
return new Promise((resolve) => {
|
||||
const blobUUID = crypto.randomUUID(); // Generates a random UUID
|
||||
|
||||
// Store the blob while we wait for processing
|
||||
fetchedBlobQueue.set(blobUUID, (blobProcessed) => {
|
||||
// The response that triggers when the blob is finished processing
|
||||
|
||||
// Creates a new response
|
||||
resolve(new Response(blobProcessed, {
|
||||
headers: cloned.headers,
|
||||
status: cloned.status,
|
||||
statusText: cloned.statusText
|
||||
}));
|
||||
|
||||
// Since this code does not run in the userscript, we can't use consoleLog().
|
||||
console.log(`%c${name}%c: ${fetchedBlobQueue.size} Processed blob "${blobUUID}"`, consoleStyle, '');
|
||||
});
|
||||
|
||||
window.postMessage({
|
||||
source: 'blue-marble',
|
||||
endpoint: endpointName,
|
||||
blobID: blobUUID,
|
||||
blobData: blob,
|
||||
blink: blink
|
||||
});
|
||||
}).catch(exception => {
|
||||
const elapsed = Date.now();
|
||||
console.error(`%c${name}%c: Failed to Promise blob!`, consoleStyle, '');
|
||||
console.groupCollapsed(`%c${name}%c: Details of failed blob Promise:`, consoleStyle, '');
|
||||
console.log(`Endpoint: ${endpointName}\nThere are ${fetchedBlobQueue.size} blobs processing...\nBlink: ${blink.toLocaleString()}\nTime Since Blink: ${String(Math.floor(elapsed/60000)).padStart(2,'0')}:${String(Math.floor(elapsed/1000) % 60).padStart(2,'0')}.${String(elapsed % 1000).padStart(3,'0')} MM:SS.mmm`);
|
||||
console.error(`Exception stack:`, exception);
|
||||
console.groupEnd();
|
||||
});
|
||||
|
||||
// cloned.blob().then(blob => {
|
||||
// window.postMessage({
|
||||
// source: 'blue-marble',
|
||||
// endpoint: endpointName,
|
||||
// blobData: blob
|
||||
// }, '*');
|
||||
// });
|
||||
}
|
||||
|
||||
return response; // Returns the original response
|
||||
};
|
||||
});
|
||||
|
||||
// Imports the CSS file from dist folder on github
|
||||
const cssOverlay = GM_getResourceText("CSS-BM-File");
|
||||
GM_addStyle(cssOverlay);
|
||||
|
||||
// Imports the Roboto Mono font family
|
||||
var stylesheetLink = document.createElement('link');
|
||||
stylesheetLink.href = 'https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&display=swap';
|
||||
stylesheetLink.rel = 'preload';
|
||||
stylesheetLink.as = 'style';
|
||||
stylesheetLink.onload = function () {
|
||||
this.onload = null;
|
||||
this.rel = 'stylesheet';
|
||||
};
|
||||
document.head?.appendChild(stylesheetLink);
|
||||
|
||||
// CONSTRUCTORS
|
||||
const observers = new Observers(); // Constructs a new Observers object
|
||||
const overlayMain = new Overlay(name, version); // Constructs a new Overlay object for the main overlay
|
||||
const overlayTabTemplate = new Overlay(name, version); // Constructs a Overlay object for the template tab
|
||||
const templateManager = new TemplateManager(name, version, overlayMain); // Constructs a new TemplateManager object
|
||||
const apiManager = new ApiManager(templateManager); // Constructs a new ApiManager object
|
||||
|
||||
overlayMain.setApiManager(apiManager); // Sets the API manager
|
||||
|
||||
const storageTemplates = JSON.parse(GM_getValue('bmTemplates', '{}'));
|
||||
console.log(storageTemplates);
|
||||
templateManager.importJSON(storageTemplates); // Loads the templates
|
||||
|
||||
buildOverlayMain(); // Builds the main overlay
|
||||
|
||||
overlayMain.handleDrag('#bm-overlay', '#bm-bar-drag'); // Creates dragging capability on the drag bar for dragging the overlay
|
||||
|
||||
apiManager.spontaneousResponseListener(overlayMain); // Reads spontaneous fetch responces
|
||||
|
||||
observeBlack(); // Observes the black palette color
|
||||
|
||||
consoleLog(`%c${name}%c (${version}) userscript has loaded!`, 'color: cornflowerblue;', '');
|
||||
|
||||
/** Observe the black color, and add the "Move" button.
|
||||
* @since 0.66.3
|
||||
*/
|
||||
function observeBlack() {
|
||||
const observer = new MutationObserver((mutations, observer) => {
|
||||
|
||||
const black = document.querySelector('#color-1'); // Attempt to retrieve the black color element for anchoring
|
||||
|
||||
if (!black) {return;} // Black color does not exist yet. Kills iteself
|
||||
|
||||
let move = document.querySelector('#bm-button-move'); // Tries to find the move button
|
||||
|
||||
// If the move button does not exist, we make a new one
|
||||
if (!move) {
|
||||
move = document.createElement('button');
|
||||
move.id = 'bm-button-move';
|
||||
move.textContent = 'Move ↑';
|
||||
move.className = 'btn btn-soft';
|
||||
move.onclick = function() {
|
||||
const roundedBox = this.parentNode.parentNode.parentNode.parentNode; // Obtains the rounded box
|
||||
const shouldMoveUp = (this.textContent == 'Move ↑');
|
||||
roundedBox.parentNode.className = roundedBox.parentNode.className.replace(shouldMoveUp ? 'bottom' : 'top', shouldMoveUp ? 'top' : 'bottom'); // Moves the rounded box to the top
|
||||
roundedBox.style.borderTopLeftRadius = shouldMoveUp ? '0px' : 'var(--radius-box)';
|
||||
roundedBox.style.borderTopRightRadius = shouldMoveUp ? '0px' : 'var(--radius-box)';
|
||||
roundedBox.style.borderBottomLeftRadius = shouldMoveUp ? 'var(--radius-box)' : '0px';
|
||||
roundedBox.style.borderBottomRightRadius = shouldMoveUp ? 'var(--radius-box)' : '0px';
|
||||
this.textContent = shouldMoveUp ? 'Move ↓' : 'Move ↑';
|
||||
}
|
||||
|
||||
// Attempts to find the "Paint Pixel" element for anchoring
|
||||
const paintPixel = black.parentNode.parentNode.parentNode.parentNode.querySelector('h2');
|
||||
|
||||
paintPixel.parentNode?.appendChild(move); // Adds the move button
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(document.body, { childList: true, subtree: true });
|
||||
}
|
||||
|
||||
/** Deploys the overlay to the page with minimize/maximize functionality.
|
||||
* Creates a responsive overlay UI that can toggle between full-featured and minimized states.
|
||||
*
|
||||
* Parent/child relationships in the DOM structure below are indicated by indentation.
|
||||
* @since 0.58.3
|
||||
*/
|
||||
function buildOverlayMain() {
|
||||
let isMinimized = false; // Overlay state tracker (false = maximized, true = minimized)
|
||||
|
||||
overlayMain.addDiv({'id': 'bm-overlay', 'style': 'top: 10px; right: 75px;'})
|
||||
.addDiv({'id': 'bm-contain-header'})
|
||||
.addDiv({'id': 'bm-bar-drag'}).buildElement()
|
||||
.addImg({'alt': 'Blue Marble Icon - Click to minimize/maximize', 'src': 'https://raw.githubusercontent.com/SwingTheVine/Wplace-BlueMarble/main/dist/assets/Favicon.png', 'style': 'cursor: pointer;'},
|
||||
(instance, img) => {
|
||||
/** Click event handler for overlay minimize/maximize functionality.
|
||||
*
|
||||
* Toggles between two distinct UI states:
|
||||
* 1. MINIMIZED STATE (60×76px):
|
||||
* - Shows only the Blue Marble icon and drag bar
|
||||
* - Hides all input fields, buttons, and status information
|
||||
* - Applies fixed dimensions for consistent appearance
|
||||
* - Repositions icon with 3px right offset for visual centering
|
||||
*
|
||||
* 2. MAXIMIZED STATE (responsive):
|
||||
* - Restores full functionality with all UI elements
|
||||
* - Removes fixed dimensions to allow responsive behavior
|
||||
* - Resets icon positioning to default alignment
|
||||
* - Shows success message when returning to maximized state
|
||||
*
|
||||
* @param {Event} event - The click event object (implicit)
|
||||
*/
|
||||
img.addEventListener('click', () => {
|
||||
isMinimized = !isMinimized; // Toggle the current state
|
||||
|
||||
const overlay = document.querySelector('#bm-overlay');
|
||||
const header = document.querySelector('#bm-contain-header');
|
||||
const dragBar = document.querySelector('#bm-bar-drag');
|
||||
const coordsContainer = document.querySelector('#bm-contain-coords');
|
||||
const coordsButton = document.querySelector('#bm-button-coords');
|
||||
const createButton = document.querySelector('#bm-button-create');
|
||||
const enableButton = document.querySelector('#bm-button-enable');
|
||||
const disableButton = document.querySelector('#bm-button-disable');
|
||||
const coordInputs = document.querySelectorAll('#bm-contain-coords input');
|
||||
|
||||
// Pre-restore original dimensions when switching to maximized state
|
||||
// This ensures smooth transition and prevents layout issues
|
||||
if (!isMinimized) {
|
||||
overlay.style.width = "auto";
|
||||
overlay.style.maxWidth = "300px";
|
||||
overlay.style.minWidth = "200px";
|
||||
overlay.style.padding = "10px";
|
||||
}
|
||||
|
||||
// Define elements that should be hidden/shown during state transitions
|
||||
// Each element is documented with its purpose for maintainability
|
||||
const elementsToToggle = [
|
||||
'#bm-overlay h1', // Main title "Blue Marble"
|
||||
'#bm-contain-userinfo', // User information section (username, droplets, level)
|
||||
'#bm-overlay hr', // Visual separator lines
|
||||
'#bm-contain-automation > *:not(#bm-contain-coords)', // Automation section excluding coordinates
|
||||
'#bm-input-file-template', // Template file upload interface
|
||||
'#bm-contain-buttons-action', // Action buttons container
|
||||
`#${instance.outputStatusId}` // Status log textarea for user feedback
|
||||
];
|
||||
|
||||
// Apply visibility changes to all toggleable elements
|
||||
elementsToToggle.forEach(selector => {
|
||||
const elements = document.querySelectorAll(selector);
|
||||
elements.forEach(element => {
|
||||
element.style.display = isMinimized ? 'none' : '';
|
||||
});
|
||||
});
|
||||
// Handle coordinate container and button visibility based on state
|
||||
if (isMinimized) {
|
||||
// ==================== MINIMIZED STATE CONFIGURATION ====================
|
||||
// In minimized state, we hide ALL interactive elements except the icon and drag bar
|
||||
// This creates a clean, unobtrusive interface that maintains only essential functionality
|
||||
|
||||
// Hide coordinate input container completely
|
||||
if (coordsContainer) {
|
||||
coordsContainer.style.display = 'none';
|
||||
}
|
||||
|
||||
// Hide coordinate button (pin icon)
|
||||
if (coordsButton) {
|
||||
coordsButton.style.display = 'none';
|
||||
}
|
||||
|
||||
// Hide create template button
|
||||
if (createButton) {
|
||||
createButton.style.display = 'none';
|
||||
}
|
||||
|
||||
// Hide enable templates button
|
||||
if (enableButton) {
|
||||
enableButton.style.display = 'none';
|
||||
}
|
||||
|
||||
// Hide disable templates button
|
||||
if (disableButton) {
|
||||
disableButton.style.display = 'none';
|
||||
}
|
||||
|
||||
// Hide all coordinate input fields individually (failsafe)
|
||||
coordInputs.forEach(input => {
|
||||
input.style.display = 'none';
|
||||
});
|
||||
|
||||
// Apply fixed dimensions for consistent minimized appearance
|
||||
// These dimensions were chosen to accommodate the icon while remaining compact
|
||||
overlay.style.width = '60px'; // Fixed width for consistency
|
||||
overlay.style.height = '76px'; // Fixed height (60px + 16px for better proportions)
|
||||
overlay.style.maxWidth = '60px'; // Prevent expansion
|
||||
overlay.style.minWidth = '60px'; // Prevent shrinking
|
||||
overlay.style.padding = '8px'; // Comfortable padding around icon
|
||||
|
||||
// Apply icon positioning for better visual centering in minimized state
|
||||
// The 3px offset compensates for visual weight distribution
|
||||
img.style.marginLeft = '3px';
|
||||
|
||||
// Configure header layout for minimized state
|
||||
header.style.textAlign = 'center';
|
||||
header.style.margin = '0';
|
||||
header.style.marginBottom = '0';
|
||||
|
||||
// Ensure drag bar remains visible and properly spaced
|
||||
if (dragBar) {
|
||||
dragBar.style.display = '';
|
||||
dragBar.style.marginBottom = '0.25em';
|
||||
}
|
||||
} else {
|
||||
// ==================== MAXIMIZED STATE RESTORATION ====================
|
||||
// In maximized state, we restore all elements to their default functionality
|
||||
// This involves clearing all style overrides applied during minimization
|
||||
|
||||
// Restore coordinate container to default state
|
||||
if (coordsContainer) {
|
||||
coordsContainer.style.display = ''; // Show container
|
||||
coordsContainer.style.flexDirection = ''; // Reset flex layout
|
||||
coordsContainer.style.justifyContent = ''; // Reset alignment
|
||||
coordsContainer.style.alignItems = ''; // Reset alignment
|
||||
coordsContainer.style.gap = ''; // Reset spacing
|
||||
coordsContainer.style.textAlign = ''; // Reset text alignment
|
||||
coordsContainer.style.margin = ''; // Reset margins
|
||||
}
|
||||
|
||||
// Restore coordinate button visibility
|
||||
if (coordsButton) {
|
||||
coordsButton.style.display = '';
|
||||
}
|
||||
|
||||
// Restore create button visibility and reset positioning
|
||||
if (createButton) {
|
||||
createButton.style.display = '';
|
||||
createButton.style.marginTop = '';
|
||||
}
|
||||
|
||||
// Restore enable button visibility and reset positioning
|
||||
if (enableButton) {
|
||||
enableButton.style.display = '';
|
||||
enableButton.style.marginTop = '';
|
||||
}
|
||||
|
||||
// Restore disable button visibility and reset positioning
|
||||
if (disableButton) {
|
||||
disableButton.style.display = '';
|
||||
disableButton.style.marginTop = '';
|
||||
}
|
||||
|
||||
// Restore all coordinate input fields
|
||||
coordInputs.forEach(input => {
|
||||
input.style.display = '';
|
||||
});
|
||||
|
||||
// Reset icon positioning to default (remove minimized state offset)
|
||||
img.style.marginLeft = '';
|
||||
|
||||
// Restore overlay to responsive dimensions
|
||||
overlay.style.padding = '10px';
|
||||
|
||||
// Reset header styling to defaults
|
||||
header.style.textAlign = '';
|
||||
header.style.margin = '';
|
||||
header.style.marginBottom = '';
|
||||
|
||||
// Reset drag bar spacing
|
||||
if (dragBar) {
|
||||
dragBar.style.marginBottom = '0.5em';
|
||||
}
|
||||
|
||||
// Remove all fixed dimensions to allow responsive behavior
|
||||
// This ensures the overlay can adapt to content changes
|
||||
overlay.style.width = '';
|
||||
overlay.style.height = '';
|
||||
}
|
||||
|
||||
// ==================== ACCESSIBILITY AND USER FEEDBACK ====================
|
||||
// Update accessibility information for screen readers and tooltips
|
||||
|
||||
// Update alt text to reflect current state for screen readers and tooltips
|
||||
img.alt = isMinimized ?
|
||||
'Blue Marble Icon - Minimized (Click to maximize)' :
|
||||
'Blue Marble Icon - Maximized (Click to minimize)';
|
||||
|
||||
// No status message needed - state change is visually obvious to users
|
||||
});
|
||||
}
|
||||
).buildElement()
|
||||
.addHeader(1, {'textContent': name}).buildElement()
|
||||
.buildElement()
|
||||
|
||||
.addHr().buildElement()
|
||||
|
||||
.addDiv({'id': 'bm-contain-userinfo'})
|
||||
.addP({'id': 'bm-user-name', 'textContent': 'Username:'}).buildElement()
|
||||
.addP({'id': 'bm-user-droplets', 'textContent': 'Droplets:'}).buildElement()
|
||||
.addP({'id': 'bm-user-nextlevel', 'textContent': 'Next level in...'}).buildElement()
|
||||
.buildElement()
|
||||
|
||||
.addHr().buildElement()
|
||||
|
||||
.addDiv({'id': 'bm-contain-automation'})
|
||||
// .addCheckbox({'id': 'bm-input-stealth', 'textContent': 'Stealth', 'checked': true}).buildElement()
|
||||
// .addButtonHelp({'title': 'Waits for the website to make requests, instead of sending requests.'}).buildElement()
|
||||
// .addBr().buildElement()
|
||||
// .addCheckbox({'id': 'bm-input-possessed', 'textContent': 'Possessed', 'checked': true}).buildElement()
|
||||
// .addButtonHelp({'title': 'Controls the website as if it were possessed.'}).buildElement()
|
||||
// .addBr().buildElement()
|
||||
.addDiv({'id': 'bm-contain-coords'})
|
||||
.addButton({'id': 'bm-button-coords', 'className': 'bm-help', 'style': 'margin-top: 0;', 'innerHTML': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 4 6"><circle cx="2" cy="2" r="2"></circle><path d="M2 6 L3.7 3 L0.3 3 Z"></path><circle cx="2" cy="2" r="0.7" fill="white"></circle></svg></svg>'},
|
||||
(instance, button) => {
|
||||
button.onclick = () => {
|
||||
const coords = instance.apiManager?.coordsTilePixel; // Retrieves the coords from the API manager
|
||||
if (!coords?.[0]) {
|
||||
instance.handleDisplayError('Coordinates are malformed! Did you try clicking on the canvas first?');
|
||||
return;
|
||||
}
|
||||
instance.updateInnerHTML('bm-input-tx', coords?.[0] || '');
|
||||
instance.updateInnerHTML('bm-input-ty', coords?.[1] || '');
|
||||
instance.updateInnerHTML('bm-input-px', coords?.[2] || '');
|
||||
instance.updateInnerHTML('bm-input-py', coords?.[3] || '');
|
||||
}
|
||||
}
|
||||
).buildElement()
|
||||
.addInput({'type': 'number', 'id': 'bm-input-tx', 'placeholder': 'Tl X', 'min': 0, 'max': 2047, 'step': 1, 'required': true}).buildElement()
|
||||
.addInput({'type': 'number', 'id': 'bm-input-ty', 'placeholder': 'Tl Y', 'min': 0, 'max': 2047, 'step': 1, 'required': true}).buildElement()
|
||||
.addInput({'type': 'number', 'id': 'bm-input-px', 'placeholder': 'Px X', 'min': 0, 'max': 2047, 'step': 1, 'required': true}).buildElement()
|
||||
.addInput({'type': 'number', 'id': 'bm-input-py', 'placeholder': 'Px Y', 'min': 0, 'max': 2047, 'step': 1, 'required': true}).buildElement()
|
||||
.buildElement()
|
||||
.addInputFile({'id': 'bm-input-file-template', 'textContent': 'Upload Template', 'accept': 'image/png, image/jpeg, image/webp, image/bmp, image/gif'}).buildElement()
|
||||
.addDiv({'id': 'bm-contain-buttons-template'})
|
||||
.addButton({'id': 'bm-button-enable', 'textContent': 'Enable'}, (instance, button) => {
|
||||
button.onclick = () => {
|
||||
instance.apiManager?.templateManager?.setTemplatesShouldBeDrawn(true);
|
||||
instance.handleDisplayStatus(`Enabled templates!`);
|
||||
}
|
||||
}).buildElement()
|
||||
.addButton({'id': 'bm-button-create', 'textContent': 'Create'}, (instance, button) => {
|
||||
button.onclick = () => {
|
||||
const input = document.querySelector('#bm-input-file-template');
|
||||
|
||||
const coordTlX = document.querySelector('#bm-input-tx');
|
||||
if (!coordTlX.checkValidity()) {coordTlX.reportValidity(); instance.handleDisplayError('Coordinates are malformed! Did you try clicking on the canvas first?'); return;}
|
||||
const coordTlY = document.querySelector('#bm-input-ty');
|
||||
if (!coordTlY.checkValidity()) {coordTlY.reportValidity(); instance.handleDisplayError('Coordinates are malformed! Did you try clicking on the canvas first?'); return;}
|
||||
const coordPxX = document.querySelector('#bm-input-px');
|
||||
if (!coordPxX.checkValidity()) {coordPxX.reportValidity(); instance.handleDisplayError('Coordinates are malformed! Did you try clicking on the canvas first?'); return;}
|
||||
const coordPxY = document.querySelector('#bm-input-py');
|
||||
if (!coordPxY.checkValidity()) {coordPxY.reportValidity(); instance.handleDisplayError('Coordinates are malformed! Did you try clicking on the canvas first?'); return;}
|
||||
|
||||
// Kills itself if there is no file
|
||||
if (!input?.files[0]) {instance.handleDisplayError(`No file selected!`); return;}
|
||||
|
||||
templateManager.createTemplate(input.files[0], input.files[0]?.name.replace(/\.[^/.]+$/, ''), [Number(coordTlX.value), Number(coordTlY.value), Number(coordPxX.value), Number(coordPxY.value)]);
|
||||
|
||||
// console.log(`TCoords: ${apiManager.templateCoordsTilePixel}\nCoords: ${apiManager.coordsTilePixel}`);
|
||||
// apiManager.templateCoordsTilePixel = apiManager.coordsTilePixel; // Update template coords
|
||||
// console.log(`TCoords: ${apiManager.templateCoordsTilePixel}\nCoords: ${apiManager.coordsTilePixel}`);
|
||||
// templateManager.setTemplateImage(input.files[0]);
|
||||
|
||||
instance.handleDisplayStatus(`Drew to canvas!`);
|
||||
}
|
||||
}).buildElement()
|
||||
.addButton({'id': 'bm-button-disable', 'textContent': 'Disable'}, (instance, button) => {
|
||||
button.onclick = () => {
|
||||
instance.apiManager?.templateManager?.setTemplatesShouldBeDrawn(false);
|
||||
instance.handleDisplayStatus(`Disabled templates!`);
|
||||
}
|
||||
}).buildElement()
|
||||
.buildElement()
|
||||
.addTextarea({'id': overlayMain.outputStatusId, 'placeholder': `Status: Sleeping...\nVersion: ${version}`, 'readOnly': true}).buildElement()
|
||||
.addDiv({'id': 'bm-contain-buttons-action'})
|
||||
.addDiv()
|
||||
// .addButton({'id': 'bm-button-teleport', 'className': 'bm-help', 'textContent': '✈'}).buildElement()
|
||||
// .addButton({'id': 'bm-button-favorite', 'className': 'bm-help', 'innerHTML': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><polygon points="10,2 12,7.5 18,7.5 13.5,11.5 15.5,18 10,14 4.5,18 6.5,11.5 2,7.5 8,7.5" fill="white"></polygon></svg>'}).buildElement()
|
||||
// .addButton({'id': 'bm-button-templates', 'className': 'bm-help', 'innerHTML': '🖌'}).buildElement()
|
||||
.addButton({'id': 'bm-button-convert', 'className': 'bm-help', 'innerHTML': '🎨', 'title': 'Template Color Converter'},
|
||||
(instance, button) => {
|
||||
button.addEventListener('click', () => {
|
||||
window.open('https://pepoafonso.github.io/color_converter_wplace/', '_blank', 'noopener noreferrer');
|
||||
});
|
||||
}).buildElement()
|
||||
.buildElement()
|
||||
.addSmall({'textContent': 'Made by SwingTheVine', 'style': 'margin-top: auto;'}).buildElement()
|
||||
.buildElement()
|
||||
.buildElement()
|
||||
.buildOverlay(document.body);
|
||||
}
|
||||
|
||||
function buildOverlayTabTemplate() {
|
||||
overlayTabTemplate.addDiv({'id': 'bm-tab-template', 'style': 'top: 20%; left: 10%;'})
|
||||
.addDiv()
|
||||
.addDiv({'className': 'bm-dragbar'}).buildElement()
|
||||
.addButton({'className': 'bm-button-minimize', 'textContent': '↑'},
|
||||
(instance, button) => {
|
||||
button.onclick = () => {
|
||||
let isMinimized = false;
|
||||
if (button.textContent == '↑') {
|
||||
button.textContent = '↓';
|
||||
} else {
|
||||
button.textContent = '↑';
|
||||
isMinimized = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
).buildElement()
|
||||
.buildElement()
|
||||
.buildElement()
|
||||
.buildOverlay();
|
||||
}</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="module.exports.html">exports</a></li><li><a href="module.exports_module.exports.html">exports</a></li></ul><h3>Global</h3><ul><li><a href="global.html#addBr">addBr</a></li><li><a href="global.html#addButton">addButton</a></li><li><a href="global.html#addButtonHelp">addButtonHelp</a></li><li><a href="global.html#addCheckbox">addCheckbox</a></li><li><a href="global.html#addDiv">addDiv</a></li><li><a href="global.html#addHeader">addHeader</a></li><li><a href="global.html#addHr">addHr</a></li><li><a href="global.html#addImg">addImg</a></li><li><a href="global.html#addInput">addInput</a></li><li><a href="global.html#addInputFile">addInputFile</a></li><li><a href="global.html#addP">addP</a></li><li><a href="global.html#addSmall">addSmall</a></li><li><a href="global.html#addTextarea">addTextarea</a></li><li><a href="global.html#base64ToUint8">base64ToUint8</a></li><li><a href="global.html#buildElement">buildElement</a></li><li><a href="global.html#buildOverlay">buildOverlay</a></li><li><a href="global.html#buildOverlayMain">buildOverlayMain</a></li><li><a href="global.html#consoleError">consoleError</a></li><li><a href="global.html#consoleLog">consoleLog</a></li><li><a href="global.html#consoleWarn">consoleWarn</a></li><li><a href="global.html#createJSON">createJSON</a></li><li><a href="global.html#createObserverBody">createObserverBody</a></li><li><a href="global.html#createTemplate">createTemplate</a></li><li><a href="global.html#createTemplateTiles">createTemplateTiles</a></li><li><a href="global.html#deleteTemplate">deleteTemplate</a></li><li><a href="global.html#disableTemplate">disableTemplate</a></li><li><a href="global.html#drawTemplateOnTile">drawTemplateOnTile</a></li><li><a href="global.html#escapeHTML">escapeHTML</a></li><li><a href="global.html#getObserverBody">getObserverBody</a></li><li><a href="global.html#handleDisplayError">handleDisplayError</a></li><li><a href="global.html#handleDisplayStatus">handleDisplayStatus</a></li><li><a href="global.html#handleDrag">handleDrag</a></li><li><a href="global.html#importJSON">importJSON</a></li><li><a href="global.html#inject">inject</a></li><li><a href="global.html#negativeSafeModulo">negativeSafeModulo</a></li><li><a href="global.html#numberToEncoded">numberToEncoded</a></li><li><a href="global.html#observe">observe</a></li><li><a href="global.html#observeBlack">observeBlack</a></li><li><a href="global.html#serverTPtoDisplayTP">serverTPtoDisplayTP</a></li><li><a href="global.html#setApiManager">setApiManager</a></li><li><a href="global.html#setTemplatesShouldBeDrawn">setTemplatesShouldBeDrawn</a></li><li><a href="global.html#spontaneousResponseListener">spontaneousResponseListener</a></li><li><a href="global.html#uint8ToBase64">uint8ToBase64</a></li><li><a href="global.html#updateInnerHTML">updateInnerHTML</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Fri Aug 08 2025 15:52:04 GMT-0400 (Eastern Daylight Time)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
||||
1130
wiki/module.exports.html
Normal file
1130
wiki/module.exports.html
Normal file
File diff suppressed because it is too large
Load diff
222
wiki/module.exports_module.exports.html
Normal file
222
wiki/module.exports_module.exports.html
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Class: exports</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Class: exports</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
|
||||
<header>
|
||||
|
||||
<h2><span class="attribs"><span class="type-signature"></span></span>exports<span class="signature">(templateManager)</span><span class="type-signature"></span></h2>
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="container-overview">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="exports"><span class="type-signature"></span>new exports<span class="signature">(templateManager)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Constructor for ApiManager class
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Parameters:</h5>
|
||||
|
||||
|
||||
<table class="params">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th>Name</th>
|
||||
|
||||
|
||||
<th>Type</th>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<th class="last">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>templateManager</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">TemplateManager</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last"></td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-since">Since:</dt>
|
||||
<dd class="tag-since"><ul class="dummy"><li>0.11.34</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="apiManager.js.html">apiManager.js</a>, <a href="apiManager.js.html#line15">line 15</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="module.exports.html">exports</a></li><li><a href="module.exports_module.exports.html">exports</a></li></ul><h3>Global</h3><ul><li><a href="global.html#addBr">addBr</a></li><li><a href="global.html#addButton">addButton</a></li><li><a href="global.html#addButtonHelp">addButtonHelp</a></li><li><a href="global.html#addCheckbox">addCheckbox</a></li><li><a href="global.html#addDiv">addDiv</a></li><li><a href="global.html#addHeader">addHeader</a></li><li><a href="global.html#addHr">addHr</a></li><li><a href="global.html#addImg">addImg</a></li><li><a href="global.html#addInput">addInput</a></li><li><a href="global.html#addInputFile">addInputFile</a></li><li><a href="global.html#addP">addP</a></li><li><a href="global.html#addSmall">addSmall</a></li><li><a href="global.html#addTextarea">addTextarea</a></li><li><a href="global.html#base64ToUint8">base64ToUint8</a></li><li><a href="global.html#buildElement">buildElement</a></li><li><a href="global.html#buildOverlay">buildOverlay</a></li><li><a href="global.html#buildOverlayMain">buildOverlayMain</a></li><li><a href="global.html#consoleError">consoleError</a></li><li><a href="global.html#consoleLog">consoleLog</a></li><li><a href="global.html#consoleWarn">consoleWarn</a></li><li><a href="global.html#createJSON">createJSON</a></li><li><a href="global.html#createObserverBody">createObserverBody</a></li><li><a href="global.html#createTemplate">createTemplate</a></li><li><a href="global.html#createTemplateTiles">createTemplateTiles</a></li><li><a href="global.html#deleteTemplate">deleteTemplate</a></li><li><a href="global.html#disableTemplate">disableTemplate</a></li><li><a href="global.html#drawTemplateOnTile">drawTemplateOnTile</a></li><li><a href="global.html#escapeHTML">escapeHTML</a></li><li><a href="global.html#getObserverBody">getObserverBody</a></li><li><a href="global.html#handleDisplayError">handleDisplayError</a></li><li><a href="global.html#handleDisplayStatus">handleDisplayStatus</a></li><li><a href="global.html#handleDrag">handleDrag</a></li><li><a href="global.html#importJSON">importJSON</a></li><li><a href="global.html#inject">inject</a></li><li><a href="global.html#negativeSafeModulo">negativeSafeModulo</a></li><li><a href="global.html#numberToEncoded">numberToEncoded</a></li><li><a href="global.html#observe">observe</a></li><li><a href="global.html#observeBlack">observeBlack</a></li><li><a href="global.html#serverTPtoDisplayTP">serverTPtoDisplayTP</a></li><li><a href="global.html#setApiManager">setApiManager</a></li><li><a href="global.html#setTemplatesShouldBeDrawn">setTemplatesShouldBeDrawn</a></li><li><a href="global.html#spontaneousResponseListener">spontaneousResponseListener</a></li><li><a href="global.html#uint8ToBase64">uint8ToBase64</a></li><li><a href="global.html#updateInnerHTML">updateInnerHTML</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Fri Aug 08 2025 15:52:04 GMT-0400 (Eastern Daylight Time)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
||||
111
wiki/observers.js.html
Normal file
111
wiki/observers.js.html
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: observers.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: observers.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/** This class contains all MutationObservers used (which is 1 probably).
|
||||
* This is not an object, but rather a "collection" of functions (in a class).
|
||||
* @since 0.43.2
|
||||
*/
|
||||
export default class Observers {
|
||||
|
||||
/** The constructor for the observer class
|
||||
* @since 0.43.2
|
||||
*/
|
||||
constructor() {
|
||||
this.observerBody = null;
|
||||
this.observerBodyTarget = null;
|
||||
this.targetDisplayCoords = '#bm-display-coords';
|
||||
}
|
||||
|
||||
/** Creates the MutationObserver for document.body
|
||||
* @param {HTMLElement} target - Targeted element to watch
|
||||
* @returns {Observers} this (Observers class)
|
||||
* @since 0.43.2
|
||||
*/
|
||||
createObserverBody(target) {
|
||||
|
||||
this.observerBodyTarget = target;
|
||||
|
||||
this.observerBody = new MutationObserver((mutations) => {
|
||||
for (const mutation of mutations) {
|
||||
for (const node of mutation.addedNodes) {
|
||||
|
||||
if (!(node instanceof HTMLElement)) {continue;} // Does not track non-HTMLElements
|
||||
|
||||
if (node.matches?.(this.targetDisplayCoords)) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Retrieves the MutationObserver that watches document.body
|
||||
* @returns {MutationObserver}
|
||||
* @since 0.43.2
|
||||
*/
|
||||
getObserverBody() {
|
||||
return this.observerBody;
|
||||
}
|
||||
|
||||
/** Observe a MutationObserver
|
||||
* @param {MutationObserver} observer - The MutationObserver
|
||||
* @param {boolean} watchChildList - (Optional) Should childList be watched? False by default
|
||||
* @param {boolean} watchSubtree - (Optional) Should childList be watched? False by default
|
||||
* @since 0.43.2
|
||||
*/
|
||||
observe(observer, watchChildList=false, watchSubtree=false) {
|
||||
observer.observe(this.observerBodyTarget, {
|
||||
childList: watchChildList,
|
||||
subtree: watchSubtree
|
||||
});
|
||||
}
|
||||
}</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="module.exports.html">exports</a></li><li><a href="module.exports_module.exports.html">exports</a></li></ul><h3>Global</h3><ul><li><a href="global.html#addBr">addBr</a></li><li><a href="global.html#addButton">addButton</a></li><li><a href="global.html#addButtonHelp">addButtonHelp</a></li><li><a href="global.html#addCheckbox">addCheckbox</a></li><li><a href="global.html#addDiv">addDiv</a></li><li><a href="global.html#addHeader">addHeader</a></li><li><a href="global.html#addHr">addHr</a></li><li><a href="global.html#addImg">addImg</a></li><li><a href="global.html#addInput">addInput</a></li><li><a href="global.html#addInputFile">addInputFile</a></li><li><a href="global.html#addP">addP</a></li><li><a href="global.html#addSmall">addSmall</a></li><li><a href="global.html#addTextarea">addTextarea</a></li><li><a href="global.html#base64ToUint8">base64ToUint8</a></li><li><a href="global.html#buildElement">buildElement</a></li><li><a href="global.html#buildOverlay">buildOverlay</a></li><li><a href="global.html#buildOverlayMain">buildOverlayMain</a></li><li><a href="global.html#consoleError">consoleError</a></li><li><a href="global.html#consoleLog">consoleLog</a></li><li><a href="global.html#consoleWarn">consoleWarn</a></li><li><a href="global.html#createJSON">createJSON</a></li><li><a href="global.html#createObserverBody">createObserverBody</a></li><li><a href="global.html#createTemplate">createTemplate</a></li><li><a href="global.html#createTemplateTiles">createTemplateTiles</a></li><li><a href="global.html#deleteTemplate">deleteTemplate</a></li><li><a href="global.html#disableTemplate">disableTemplate</a></li><li><a href="global.html#drawTemplateOnTile">drawTemplateOnTile</a></li><li><a href="global.html#escapeHTML">escapeHTML</a></li><li><a href="global.html#getObserverBody">getObserverBody</a></li><li><a href="global.html#handleDisplayError">handleDisplayError</a></li><li><a href="global.html#handleDisplayStatus">handleDisplayStatus</a></li><li><a href="global.html#handleDrag">handleDrag</a></li><li><a href="global.html#importJSON">importJSON</a></li><li><a href="global.html#inject">inject</a></li><li><a href="global.html#negativeSafeModulo">negativeSafeModulo</a></li><li><a href="global.html#numberToEncoded">numberToEncoded</a></li><li><a href="global.html#observe">observe</a></li><li><a href="global.html#observeBlack">observeBlack</a></li><li><a href="global.html#serverTPtoDisplayTP">serverTPtoDisplayTP</a></li><li><a href="global.html#setApiManager">setApiManager</a></li><li><a href="global.html#setTemplatesShouldBeDrawn">setTemplatesShouldBeDrawn</a></li><li><a href="global.html#spontaneousResponseListener">spontaneousResponseListener</a></li><li><a href="global.html#uint8ToBase64">uint8ToBase64</a></li><li><a href="global.html#updateInnerHTML">updateInnerHTML</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Fri Aug 08 2025 15:52:04 GMT-0400 (Eastern Daylight Time)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
||||
25
wiki/scripts/linenumber.js
Normal file
25
wiki/scripts/linenumber.js
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*global document */
|
||||
(() => {
|
||||
const source = document.getElementsByClassName('prettyprint source linenums');
|
||||
let i = 0;
|
||||
let lineNumber = 0;
|
||||
let lineId;
|
||||
let lines;
|
||||
let totalLines;
|
||||
let anchorHash;
|
||||
|
||||
if (source && source[0]) {
|
||||
anchorHash = document.location.hash.substring(1);
|
||||
lines = source[0].getElementsByTagName('li');
|
||||
totalLines = lines.length;
|
||||
|
||||
for (; i < totalLines; i++) {
|
||||
lineNumber++;
|
||||
lineId = `line${lineNumber}`;
|
||||
lines[i].id = lineId;
|
||||
if (lineId === anchorHash) {
|
||||
lines[i].className += ' selected';
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
202
wiki/scripts/prettify/Apache-License-2.0.txt
Normal file
202
wiki/scripts/prettify/Apache-License-2.0.txt
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
2
wiki/scripts/prettify/lang-css.js
Normal file
2
wiki/scripts/prettify/lang-css.js
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n"]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com",
|
||||
/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]);
|
||||
28
wiki/scripts/prettify/prettify.js
Normal file
28
wiki/scripts/prettify/prettify.js
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
|
||||
(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a=
|
||||
[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c<
|
||||
f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&&
|
||||
(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r=
|
||||
{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length,
|
||||
t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===
|
||||
"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),
|
||||
l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
|
||||
q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/,
|
||||
q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g,
|
||||
"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a),
|
||||
a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}
|
||||
for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value",
|
||||
m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m=
|
||||
a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue=
|
||||
j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
|
||||
"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"],
|
||||
H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
|
||||
J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+
|
||||
I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),
|
||||
["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",
|
||||
/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),
|
||||
["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes",
|
||||
hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b=
|
||||
!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,
|
||||
250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",
|
||||
PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})();
|
||||
358
wiki/styles/jsdoc-default.css
Normal file
358
wiki/styles/jsdoc-default.css
Normal file
|
|
@ -0,0 +1,358 @@
|
|||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
src: url('../fonts/OpenSans-Regular-webfont.eot');
|
||||
src:
|
||||
local('Open Sans'),
|
||||
local('OpenSans'),
|
||||
url('../fonts/OpenSans-Regular-webfont.eot?#iefix') format('embedded-opentype'),
|
||||
url('../fonts/OpenSans-Regular-webfont.woff') format('woff'),
|
||||
url('../fonts/OpenSans-Regular-webfont.svg#open_sansregular') format('svg');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans Light';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
src: url('../fonts/OpenSans-Light-webfont.eot');
|
||||
src:
|
||||
local('Open Sans Light'),
|
||||
local('OpenSans Light'),
|
||||
url('../fonts/OpenSans-Light-webfont.eot?#iefix') format('embedded-opentype'),
|
||||
url('../fonts/OpenSans-Light-webfont.woff') format('woff'),
|
||||
url('../fonts/OpenSans-Light-webfont.svg#open_sanslight') format('svg');
|
||||
}
|
||||
|
||||
html
|
||||
{
|
||||
overflow: auto;
|
||||
background-color: #fff;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
body
|
||||
{
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
line-height: 1.5;
|
||||
color: #4d4e53;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
a, a:visited, a:active {
|
||||
color: #0095dd;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
header
|
||||
{
|
||||
display: block;
|
||||
padding: 0px 4px;
|
||||
}
|
||||
|
||||
tt, code, kbd, samp {
|
||||
font-family: Consolas, Monaco, 'Andale Mono', monospace;
|
||||
}
|
||||
|
||||
.class-description {
|
||||
font-size: 130%;
|
||||
line-height: 140%;
|
||||
margin-bottom: 1em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.class-description:empty {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#main {
|
||||
float: left;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
article dl {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
article img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
section
|
||||
{
|
||||
display: block;
|
||||
background-color: #fff;
|
||||
padding: 12px 24px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
.variation {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.signature-attributes {
|
||||
font-size: 60%;
|
||||
color: #aaa;
|
||||
font-style: italic;
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
nav
|
||||
{
|
||||
display: block;
|
||||
float: right;
|
||||
margin-top: 28px;
|
||||
width: 30%;
|
||||
box-sizing: border-box;
|
||||
border-left: 1px solid #ccc;
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
font-family: 'Lucida Grande', 'Lucida Sans Unicode', arial, sans-serif;
|
||||
font-size: 100%;
|
||||
line-height: 17px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
nav ul a, nav ul a:visited, nav ul a:active {
|
||||
font-family: Consolas, Monaco, 'Andale Mono', monospace;
|
||||
line-height: 18px;
|
||||
color: #4D4E53;
|
||||
}
|
||||
|
||||
nav h3 {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
nav li {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
footer {
|
||||
display: block;
|
||||
padding: 6px;
|
||||
margin-top: 12px;
|
||||
font-style: italic;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-weight: 200;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h1
|
||||
{
|
||||
font-family: 'Open Sans Light', sans-serif;
|
||||
font-size: 48px;
|
||||
letter-spacing: -2px;
|
||||
margin: 12px 24px 20px;
|
||||
}
|
||||
|
||||
h2, h3.subsection-title
|
||||
{
|
||||
font-size: 30px;
|
||||
font-weight: 700;
|
||||
letter-spacing: -1px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
h3
|
||||
{
|
||||
font-size: 24px;
|
||||
letter-spacing: -0.5px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
h4
|
||||
{
|
||||
font-size: 18px;
|
||||
letter-spacing: -0.33px;
|
||||
margin-bottom: 12px;
|
||||
color: #4d4e53;
|
||||
}
|
||||
|
||||
h5, .container-overview .subsection-title
|
||||
{
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
letter-spacing: -0.01em;
|
||||
margin: 8px 0 3px 0;
|
||||
}
|
||||
|
||||
h6
|
||||
{
|
||||
font-size: 100%;
|
||||
letter-spacing: -0.01em;
|
||||
margin: 6px 0 3px 0;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
table
|
||||
{
|
||||
border-spacing: 0;
|
||||
border: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
td, th
|
||||
{
|
||||
border: 1px solid #ddd;
|
||||
margin: 0px;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
padding: 4px 6px;
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
thead tr
|
||||
{
|
||||
background-color: #ddd;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
th { border-right: 1px solid #aaa; }
|
||||
tr > th:last-child { border-right: 1px solid #ddd; }
|
||||
|
||||
.ancestors, .attribs { color: #999; }
|
||||
.ancestors a, .attribs a
|
||||
{
|
||||
color: #999 !important;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.clear
|
||||
{
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.important
|
||||
{
|
||||
font-weight: bold;
|
||||
color: #950B02;
|
||||
}
|
||||
|
||||
.yes-def {
|
||||
text-indent: -1000px;
|
||||
}
|
||||
|
||||
.type-signature {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.name, .signature {
|
||||
font-family: Consolas, Monaco, 'Andale Mono', monospace;
|
||||
}
|
||||
|
||||
.details { margin-top: 14px; border-left: 2px solid #DDD; }
|
||||
.details dt { width: 120px; float: left; padding-left: 10px; padding-top: 6px; }
|
||||
.details dd { margin-left: 70px; }
|
||||
.details ul { margin: 0; }
|
||||
.details ul { list-style-type: none; }
|
||||
.details li { margin-left: 30px; padding-top: 6px; }
|
||||
.details pre.prettyprint { margin: 0 }
|
||||
.details .object-value { padding-top: 0; }
|
||||
|
||||
.description {
|
||||
margin-bottom: 1em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.code-caption
|
||||
{
|
||||
font-style: italic;
|
||||
font-size: 107%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.source
|
||||
{
|
||||
border: 1px solid #ddd;
|
||||
width: 80%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.prettyprint.source {
|
||||
width: inherit;
|
||||
}
|
||||
|
||||
.source code
|
||||
{
|
||||
font-size: 100%;
|
||||
line-height: 18px;
|
||||
display: block;
|
||||
padding: 4px 12px;
|
||||
margin: 0;
|
||||
background-color: #fff;
|
||||
color: #4D4E53;
|
||||
}
|
||||
|
||||
.prettyprint code span.line
|
||||
{
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.prettyprint.linenums
|
||||
{
|
||||
padding-left: 70px;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.prettyprint.linenums ol
|
||||
{
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.prettyprint.linenums li
|
||||
{
|
||||
border-left: 3px #ddd solid;
|
||||
}
|
||||
|
||||
.prettyprint.linenums li.selected,
|
||||
.prettyprint.linenums li.selected *
|
||||
{
|
||||
background-color: lightyellow;
|
||||
}
|
||||
|
||||
.prettyprint.linenums li *
|
||||
{
|
||||
-webkit-user-select: text;
|
||||
-moz-user-select: text;
|
||||
-ms-user-select: text;
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
.params .name, .props .name, .name code {
|
||||
color: #4D4E53;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', monospace;
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
.params td.description > p:first-child,
|
||||
.props td.description > p:first-child
|
||||
{
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.params td.description > p:last-child,
|
||||
.props td.description > p:last-child
|
||||
{
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
color: #454545;
|
||||
}
|
||||
111
wiki/styles/prettify-jsdoc.css
Normal file
111
wiki/styles/prettify-jsdoc.css
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/* JSDoc prettify.js theme */
|
||||
|
||||
/* plain text */
|
||||
.pln {
|
||||
color: #000000;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* string content */
|
||||
.str {
|
||||
color: #006400;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* a keyword */
|
||||
.kwd {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* a comment */
|
||||
.com {
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* a type name */
|
||||
.typ {
|
||||
color: #000000;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* a literal value */
|
||||
.lit {
|
||||
color: #006400;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* punctuation */
|
||||
.pun {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* lisp open bracket */
|
||||
.opn {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* lisp close bracket */
|
||||
.clo {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* a markup tag name */
|
||||
.tag {
|
||||
color: #006400;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* a markup attribute name */
|
||||
.atn {
|
||||
color: #006400;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* a markup attribute value */
|
||||
.atv {
|
||||
color: #006400;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* a declaration */
|
||||
.dec {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* a variable name */
|
||||
.var {
|
||||
color: #000000;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* a function name */
|
||||
.fun {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* Specify class=linenums on a pre to get line numbering */
|
||||
ol.linenums {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
132
wiki/styles/prettify-tomorrow.css
Normal file
132
wiki/styles/prettify-tomorrow.css
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
/* Tomorrow Theme */
|
||||
/* Original theme - https://github.com/chriskempson/tomorrow-theme */
|
||||
/* Pretty printing styles. Used with prettify.js. */
|
||||
/* SPAN elements with the classes below are added by prettyprint. */
|
||||
/* plain text */
|
||||
.pln {
|
||||
color: #4d4d4c; }
|
||||
|
||||
@media screen {
|
||||
/* string content */
|
||||
.str {
|
||||
color: #718c00; }
|
||||
|
||||
/* a keyword */
|
||||
.kwd {
|
||||
color: #8959a8; }
|
||||
|
||||
/* a comment */
|
||||
.com {
|
||||
color: #8e908c; }
|
||||
|
||||
/* a type name */
|
||||
.typ {
|
||||
color: #4271ae; }
|
||||
|
||||
/* a literal value */
|
||||
.lit {
|
||||
color: #f5871f; }
|
||||
|
||||
/* punctuation */
|
||||
.pun {
|
||||
color: #4d4d4c; }
|
||||
|
||||
/* lisp open bracket */
|
||||
.opn {
|
||||
color: #4d4d4c; }
|
||||
|
||||
/* lisp close bracket */
|
||||
.clo {
|
||||
color: #4d4d4c; }
|
||||
|
||||
/* a markup tag name */
|
||||
.tag {
|
||||
color: #c82829; }
|
||||
|
||||
/* a markup attribute name */
|
||||
.atn {
|
||||
color: #f5871f; }
|
||||
|
||||
/* a markup attribute value */
|
||||
.atv {
|
||||
color: #3e999f; }
|
||||
|
||||
/* a declaration */
|
||||
.dec {
|
||||
color: #f5871f; }
|
||||
|
||||
/* a variable name */
|
||||
.var {
|
||||
color: #c82829; }
|
||||
|
||||
/* a function name */
|
||||
.fun {
|
||||
color: #4271ae; } }
|
||||
/* Use higher contrast and text-weight for printable form. */
|
||||
@media print, projection {
|
||||
.str {
|
||||
color: #060; }
|
||||
|
||||
.kwd {
|
||||
color: #006;
|
||||
font-weight: bold; }
|
||||
|
||||
.com {
|
||||
color: #600;
|
||||
font-style: italic; }
|
||||
|
||||
.typ {
|
||||
color: #404;
|
||||
font-weight: bold; }
|
||||
|
||||
.lit {
|
||||
color: #044; }
|
||||
|
||||
.pun, .opn, .clo {
|
||||
color: #440; }
|
||||
|
||||
.tag {
|
||||
color: #006;
|
||||
font-weight: bold; }
|
||||
|
||||
.atn {
|
||||
color: #404; }
|
||||
|
||||
.atv {
|
||||
color: #060; } }
|
||||
/* Style */
|
||||
/*
|
||||
pre.prettyprint {
|
||||
background: white;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', monospace;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
border: 1px solid #ccc;
|
||||
padding: 10px; }
|
||||
*/
|
||||
|
||||
/* Specify class=linenums on a pre to get line numbering */
|
||||
ol.linenums {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0; }
|
||||
|
||||
/* IE indents via margin-left */
|
||||
li.L0,
|
||||
li.L1,
|
||||
li.L2,
|
||||
li.L3,
|
||||
li.L4,
|
||||
li.L5,
|
||||
li.L6,
|
||||
li.L7,
|
||||
li.L8,
|
||||
li.L9 {
|
||||
/* */ }
|
||||
|
||||
/* Alternate shading for lines */
|
||||
li.L1,
|
||||
li.L3,
|
||||
li.L5,
|
||||
li.L7,
|
||||
li.L9 {
|
||||
/* */ }
|
||||
444
wiki/templateManager.js.html
Normal file
444
wiki/templateManager.js.html
Normal file
|
|
@ -0,0 +1,444 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: templateManager.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: templateManager.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>import Template from "./Template";
|
||||
import { base64ToUint8, numberToEncoded } from "./utils";
|
||||
|
||||
/** Manages the template system.
|
||||
* This class handles all external requests for template modification, creation, and analysis.
|
||||
* It serves as the central coordinator between template instances and the user interface.
|
||||
* @since 0.55.8
|
||||
* @example
|
||||
* // JSON structure for a template
|
||||
* {
|
||||
* "whoami": "BlueMarble",
|
||||
* "scriptVersion": "1.13.0",
|
||||
* "schemaVersion": "2.1.0",
|
||||
* "templates": {
|
||||
* "0 $Z": {
|
||||
* "name": "My Template",
|
||||
* "enabled": true,
|
||||
* "tiles": {
|
||||
* "1231,0047,183,593": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA",
|
||||
* "1231,0048,183,000": "data:image/png;AAAFCAYAAACNbyblAAAAHElEQVQI12P4"
|
||||
* }
|
||||
* },
|
||||
* "1 $Z": {
|
||||
* "name": "My Template",
|
||||
* "URL": "https://github.com/SwingTheVine/Wplace-BlueMarble/blob/main/dist/assets/Favicon.png",
|
||||
* "URLType": "template",
|
||||
* "enabled": false,
|
||||
* "tiles": {
|
||||
* "375,1846,276,188": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA",
|
||||
* "376,1846,000,188": "data:image/png;AAAFCAYAAACNbyblAAAAHElEQVQI12P4"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
export default class TemplateManager {
|
||||
|
||||
/** The constructor for the {@link TemplateManager} class.
|
||||
* @since 0.55.8
|
||||
*/
|
||||
constructor(name, version, overlay) {
|
||||
|
||||
// Meta
|
||||
this.name = name; // Name of userscript
|
||||
this.version = version; // Version of userscript
|
||||
this.overlay = overlay; // The main instance of the Overlay class
|
||||
this.templatesVersion = '1.0.0'; // Version of JSON schema
|
||||
this.userID = null; // The ID of the current user
|
||||
this.encodingBase = '!#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~'; // Characters to use for encoding/decoding
|
||||
this.tileSize = 1000; // The number of pixels in a tile. Assumes the tile is square
|
||||
this.drawMult = 3; // The enlarged size for each pixel. E.g. when "3", a 1x1 pixel becomes a 1x1 pixel inside a 3x3 area. MUST BE ODD
|
||||
|
||||
// Template
|
||||
this.canvasTemplate = null; // Our canvas
|
||||
this.canvasTemplateZoomed = null; // The template when zoomed out
|
||||
this.canvasTemplateID = 'bm-canvas'; // Our canvas ID
|
||||
this.canvasMainID = 'div#map canvas.maplibregl-canvas'; // The selector for the main canvas
|
||||
this.template = null; // The template image.
|
||||
this.templateState = ''; // The state of the template ('blob', 'proccessing', 'template', etc.)
|
||||
this.templatesArray = []; // All Template instnaces currently loaded (Template)
|
||||
this.templatesJSON = null; // All templates currently loaded (JSON)
|
||||
this.templatesShouldBeDrawn = true; // Should ALL templates be drawn to the canvas?
|
||||
}
|
||||
|
||||
/** Retrieves the pixel art canvas.
|
||||
* If the canvas has been updated/replaced, it retrieves the new one.
|
||||
* @param {string} selector - The CSS selector to use to find the canvas.
|
||||
* @returns {HTMLCanvasElement|null} The canvas as an HTML Canvas Element, or null if the canvas does not exist
|
||||
* @since 0.58.3
|
||||
* @deprecated Not in use since 0.63.25
|
||||
*/
|
||||
/* @__PURE__ */getCanvas() {
|
||||
|
||||
// If the stored canvas is "fresh", return the stored canvas
|
||||
if (document.body.contains(this.canvasTemplate)) {return this.canvasTemplate;}
|
||||
// Else, the stored canvas is "stale", get the canvas again
|
||||
|
||||
// Attempt to find and destroy the "stale" canvas
|
||||
document.getElementById(this.canvasTemplateID)?.remove();
|
||||
|
||||
const canvasMain = document.querySelector(this.canvasMainID);
|
||||
|
||||
const canvasTemplateNew = document.createElement('canvas');
|
||||
canvasTemplateNew.id = this.canvasTemplateID;
|
||||
canvasTemplateNew.className = 'maplibregl-canvas';
|
||||
canvasTemplateNew.style.position = 'absolute';
|
||||
canvasTemplateNew.style.top = '0';
|
||||
canvasTemplateNew.style.left = '0';
|
||||
canvasTemplateNew.style.height = `${canvasMain?.clientHeight * (window.devicePixelRatio || 1)}px`;
|
||||
canvasTemplateNew.style.width = `${canvasMain?.clientWidth * (window.devicePixelRatio || 1)}px`;
|
||||
canvasTemplateNew.height = canvasMain?.clientHeight * (window.devicePixelRatio || 1);
|
||||
canvasTemplateNew.width = canvasMain?.clientWidth * (window.devicePixelRatio || 1);
|
||||
canvasTemplateNew.style.zIndex = '8999';
|
||||
canvasTemplateNew.style.pointerEvents = 'none';
|
||||
canvasMain?.parentElement?.appendChild(canvasTemplateNew); // Append the newCanvas as a child of the parent of the main canvas
|
||||
this.canvasTemplate = canvasTemplateNew; // Store the new canvas
|
||||
|
||||
window.addEventListener('move', this.onMove);
|
||||
window.addEventListener('zoom', this.onZoom);
|
||||
window.addEventListener('resize', this.onResize);
|
||||
|
||||
return this.canvasTemplate; // Return the new canvas
|
||||
}
|
||||
|
||||
/** Creates the JSON object to store templates in
|
||||
* @returns {{ whoami: string, scriptVersion: string, schemaVersion: string, templates: Object }} The JSON object
|
||||
* @since 0.65.4
|
||||
*/
|
||||
async createJSON() {
|
||||
return {
|
||||
"whoami": this.name.replace(' ', ''), // Name of userscript without spaces
|
||||
"scriptVersion": this.version, // Version of userscript
|
||||
"schemaVersion": this.templatesVersion, // Version of JSON schema
|
||||
"templates": {} // The templates
|
||||
};
|
||||
}
|
||||
|
||||
/** Creates the template from the inputed file blob
|
||||
* @param {File} blob - The file blob to create a template from
|
||||
* @param {string} name - The display name of the template
|
||||
* @param {Array<number, number, number, number>} coords - The coordinates of the top left corner of the template
|
||||
* @since 0.65.77
|
||||
*/
|
||||
async createTemplate(blob, name, coords) {
|
||||
|
||||
// Creates the JSON object if it does not already exist
|
||||
if (!this.templatesJSON) {this.templatesJSON = await this.createJSON(); console.log(`Creating JSON...`);}
|
||||
|
||||
this.overlay.handleDisplayStatus(`Creating template at ${coords.join(', ')}...`);
|
||||
|
||||
// Creates a new template instance
|
||||
const template = new Template({
|
||||
displayName: name,
|
||||
sortID: 0, // Object.keys(this.templatesJSON.templates).length || 0, // Uncomment this to enable multiple templates (1/2)
|
||||
authorID: numberToEncoded(this.userID || 0, this.encodingBase),
|
||||
file: blob,
|
||||
coords: coords
|
||||
});
|
||||
//template.chunked = await template.createTemplateTiles(this.tileSize); // Chunks the tiles
|
||||
const { templateTiles, templateTilesBuffers } = await template.createTemplateTiles(this.tileSize); // Chunks the tiles
|
||||
template.chunked = templateTiles; // Stores the chunked tile bitmaps
|
||||
|
||||
// Appends a child into the templates object
|
||||
// The child's name is the number of templates already in the list (sort order) plus the encoded player ID
|
||||
this.templatesJSON.templates[`${template.sortID} ${template.authorID}`] = {
|
||||
"name": template.displayName, // Display name of template
|
||||
"coords": coords.join(', '), // The coords of the template
|
||||
"enabled": true,
|
||||
"tiles": templateTilesBuffers // Stores the chunked tile buffers
|
||||
};
|
||||
|
||||
this.templatesArray = []; // Remove this to enable multiple templates (2/2)
|
||||
this.templatesArray.push(template); // Pushes the Template object instance to the Template Array
|
||||
|
||||
// ==================== PIXEL COUNT DISPLAY SYSTEM ====================
|
||||
// Display pixel count statistics with internationalized number formatting
|
||||
// This provides immediate feedback to users about template complexity and size
|
||||
const pixelCountFormatted = new Intl.NumberFormat().format(template.pixelCount);
|
||||
this.overlay.handleDisplayStatus(`Template created at ${coords.join(', ')}! Total pixels: ${pixelCountFormatted}`);
|
||||
|
||||
console.log(Object.keys(this.templatesJSON.templates).length);
|
||||
console.log(this.templatesJSON);
|
||||
console.log(this.templatesArray);
|
||||
console.log(JSON.stringify(this.templatesJSON));
|
||||
|
||||
await this.#storeTemplates();
|
||||
}
|
||||
|
||||
/** Generates a {@link Template} class instance from the JSON object template
|
||||
*/
|
||||
#loadTemplate() {
|
||||
|
||||
}
|
||||
|
||||
/** Stores the JSON object of the loaded templates into TamperMonkey (GreaseMonkey) storage.
|
||||
* @since 0.72.7
|
||||
*/
|
||||
async #storeTemplates() {
|
||||
GM.setValue('bmTemplates', JSON.stringify(this.templatesJSON));
|
||||
}
|
||||
|
||||
/** Deletes a template from the JSON object.
|
||||
* Also delete's the corrosponding {@link Template} class instance
|
||||
*/
|
||||
deleteTemplate() {
|
||||
|
||||
}
|
||||
|
||||
/** Disables the template from view
|
||||
*/
|
||||
async disableTemplate() {
|
||||
|
||||
// Creates the JSON object if it does not already exist
|
||||
if (!this.templatesJSON) {this.templatesJSON = await this.createJSON(); console.log(`Creating JSON...`);}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/** Draws all templates on the specified tile.
|
||||
* This method handles the rendering of template overlays on individual tiles.
|
||||
* @param {File} tileBlob - The pixels that are placed on a tile
|
||||
* @param {Array<number>} tileCoords - The tile coordinates [x, y]
|
||||
* @since 0.65.77
|
||||
*/
|
||||
async drawTemplateOnTile(tileBlob, tileCoords) {
|
||||
|
||||
// Returns early if no templates should be drawn
|
||||
if (!this.templatesShouldBeDrawn) {return tileBlob;}
|
||||
|
||||
const drawSize = this.tileSize * this.drawMult; // Calculate draw multiplier for scaling
|
||||
|
||||
// Format tile coordinates with proper padding for consistent lookup
|
||||
tileCoords = tileCoords[0].toString().padStart(4, '0') + ',' + tileCoords[1].toString().padStart(4, '0');
|
||||
|
||||
console.log(`Searching for templates in tile: "${tileCoords}"`);
|
||||
|
||||
const templateArray = this.templatesArray; // Stores a copy for sorting
|
||||
console.log(templateArray);
|
||||
|
||||
// Sorts the array of Template class instances. 0 = first = lowest draw priority
|
||||
templateArray.sort((a, b) => {return a.sortID - b.sortID;});
|
||||
|
||||
console.log(templateArray);
|
||||
|
||||
// Retrieves the relavent template tile blobs
|
||||
const templatesToDraw = templateArray
|
||||
.map(template => {
|
||||
const matchingTiles = Object.keys(template.chunked).filter(tile =>
|
||||
tile.startsWith(tileCoords)
|
||||
);
|
||||
|
||||
if (matchingTiles.length === 0) {return null;} // Return null when nothing is found
|
||||
|
||||
// Retrieves the blobs of the templates for this tile
|
||||
const matchingTileBlobs = matchingTiles.map(tile => {
|
||||
|
||||
const coords = tile.split(','); // [x, y, x, y] Tile/pixel coordinates
|
||||
|
||||
return {
|
||||
bitmap: template.chunked[tile],
|
||||
tileCoords: [coords[0], coords[1]],
|
||||
pixelCoords: [coords[2], coords[3]]
|
||||
}
|
||||
});
|
||||
|
||||
return matchingTileBlobs?.[0];
|
||||
})
|
||||
.filter(Boolean);
|
||||
|
||||
console.log(templatesToDraw);
|
||||
|
||||
const templateCount = templatesToDraw?.length || 0; // Number of templates to draw on this tile
|
||||
console.log(`templateCount = ${templateCount}`);
|
||||
|
||||
if (templateCount > 0) {
|
||||
|
||||
// Calculate total pixel count for templates actively being displayed in this tile
|
||||
const totalPixels = templateArray
|
||||
.filter(template => {
|
||||
// Filter templates to include only those with tiles matching current coordinates
|
||||
// This ensures we count pixels only for templates actually being rendered
|
||||
const matchingTiles = Object.keys(template.chunked).filter(tile =>
|
||||
tile.startsWith(tileCoords)
|
||||
);
|
||||
return matchingTiles.length > 0;
|
||||
})
|
||||
.reduce((sum, template) => sum + (template.pixelCount || 0), 0);
|
||||
|
||||
// Format pixel count with locale-appropriate thousands separators for better readability
|
||||
// Examples: "1,234,567" (US), "1.234.567" (DE), "1 234 567" (FR)
|
||||
const pixelCountFormatted = new Intl.NumberFormat().format(totalPixels);
|
||||
|
||||
// Display status information about the templates being rendered
|
||||
this.overlay.handleDisplayStatus(
|
||||
`Displaying ${templateCount} template${templateCount == 1 ? '' : 's'}.\nTotal pixels: ${pixelCountFormatted}`
|
||||
);
|
||||
} else {
|
||||
this.overlay.handleDisplayStatus(`Displaying ${templateCount} templates.`);
|
||||
}
|
||||
|
||||
const tileBitmap = await createImageBitmap(tileBlob);
|
||||
|
||||
const canvas = new OffscreenCanvas(drawSize, drawSize);
|
||||
const context = canvas.getContext('2d');
|
||||
|
||||
context.imageSmoothingEnabled = false; // Nearest neighbor
|
||||
|
||||
// Tells the canvas to ignore anything outside of this area
|
||||
context.beginPath();
|
||||
context.rect(0, 0, drawSize, drawSize);
|
||||
context.clip();
|
||||
|
||||
context.clearRect(0, 0, drawSize, drawSize); // Draws transparent background
|
||||
context.drawImage(tileBitmap, 0, 0, drawSize, drawSize);
|
||||
|
||||
// For each template in this tile, draw them.
|
||||
for (const template of templatesToDraw) {
|
||||
console.log(`Template:`);
|
||||
console.log(template);
|
||||
|
||||
// Draws the each template on the tile based on it's relative position
|
||||
context.drawImage(template.bitmap, Number(template.pixelCoords[0]) * this.drawMult, Number(template.pixelCoords[1]) * this.drawMult);
|
||||
}
|
||||
|
||||
return await canvas.convertToBlob({ type: 'image/png' });
|
||||
}
|
||||
|
||||
/** Imports the JSON object, and appends it to any JSON object already loaded
|
||||
* @param {string} json - The JSON string to parse
|
||||
*/
|
||||
importJSON(json) {
|
||||
|
||||
console.log(`Importing JSON...`);
|
||||
console.log(json);
|
||||
|
||||
// If the passed in JSON is a Blue Marble template object...
|
||||
if (json?.whoami == 'BlueMarble') {
|
||||
this.#parseBlueMarble(json); // ...parse the template object as Blue Marble
|
||||
}
|
||||
}
|
||||
|
||||
/** Parses the Blue Marble JSON object
|
||||
* @param {string} json - The JSON string to parse
|
||||
* @since 0.72.13
|
||||
*/
|
||||
async #parseBlueMarble(json) {
|
||||
|
||||
console.log(`Parsing BlueMarble...`);
|
||||
|
||||
const templates = json.templates;
|
||||
|
||||
console.log(`BlueMarble length: ${Object.keys(templates).length}`);
|
||||
|
||||
if (Object.keys(templates).length > 0) {
|
||||
|
||||
for (const template in templates) {
|
||||
|
||||
const templateKey = template;
|
||||
const templateValue = templates[template];
|
||||
console.log(templateKey);
|
||||
|
||||
if (templates.hasOwnProperty(template)) {
|
||||
|
||||
const templateKeyArray = templateKey.split(' '); // E.g., "0 $Z" -> ["0", "$Z"]
|
||||
const sortID = Number(templateKeyArray?.[0]); // Sort ID of the template
|
||||
const authorID = templateKeyArray?.[1] || '0'; // User ID of the person who exported the template
|
||||
const displayName = templateValue.name || `Template ${sortID || ''}`; // Display name of the template
|
||||
//const coords = templateValue?.coords?.split(',').map(Number); // "1,2,3,4" -> [1, 2, 3, 4]
|
||||
const tilesbase64 = templateValue.tiles;
|
||||
const templateTiles = {}; // Stores the template bitmap tiles for each tile.
|
||||
|
||||
for (const tile in tilesbase64) {
|
||||
console.log(tile);
|
||||
if (tilesbase64.hasOwnProperty(tile)) {
|
||||
const encodedTemplateBase64 = tilesbase64[tile];
|
||||
const templateUint8Array = base64ToUint8(encodedTemplateBase64); // Base 64 -> Uint8Array
|
||||
|
||||
const templateBlob = new Blob([templateUint8Array], { type: "image/png" }); // Uint8Array -> Blob
|
||||
const templateBitmap = await createImageBitmap(templateBlob) // Blob -> Bitmap
|
||||
templateTiles[tile] = templateBitmap;
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a new Template class instance
|
||||
const template = new Template({
|
||||
displayName: displayName,
|
||||
sortID: sortID || this.templatesArray?.length || 0,
|
||||
authorID: authorID || '',
|
||||
//coords: coords
|
||||
});
|
||||
template.chunked = templateTiles;
|
||||
this.templatesArray.push(template);
|
||||
console.log(this.templatesArray);
|
||||
console.log(`^^^ This ^^^`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Parses the OSU! Place JSON object
|
||||
*/
|
||||
#parseOSU() {
|
||||
|
||||
}
|
||||
|
||||
/** Sets the `templatesShouldBeDrawn` boolean to a value.
|
||||
* @param {boolean} value - The value to set the boolean to
|
||||
* @since 0.73.7
|
||||
*/
|
||||
setTemplatesShouldBeDrawn(value) {
|
||||
this.templatesShouldBeDrawn = value;
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="module.exports.html">exports</a></li><li><a href="module.exports_module.exports.html">exports</a></li></ul><h3>Global</h3><ul><li><a href="global.html#addBr">addBr</a></li><li><a href="global.html#addButton">addButton</a></li><li><a href="global.html#addButtonHelp">addButtonHelp</a></li><li><a href="global.html#addCheckbox">addCheckbox</a></li><li><a href="global.html#addDiv">addDiv</a></li><li><a href="global.html#addHeader">addHeader</a></li><li><a href="global.html#addHr">addHr</a></li><li><a href="global.html#addImg">addImg</a></li><li><a href="global.html#addInput">addInput</a></li><li><a href="global.html#addInputFile">addInputFile</a></li><li><a href="global.html#addP">addP</a></li><li><a href="global.html#addSmall">addSmall</a></li><li><a href="global.html#addTextarea">addTextarea</a></li><li><a href="global.html#base64ToUint8">base64ToUint8</a></li><li><a href="global.html#buildElement">buildElement</a></li><li><a href="global.html#buildOverlay">buildOverlay</a></li><li><a href="global.html#buildOverlayMain">buildOverlayMain</a></li><li><a href="global.html#consoleError">consoleError</a></li><li><a href="global.html#consoleLog">consoleLog</a></li><li><a href="global.html#consoleWarn">consoleWarn</a></li><li><a href="global.html#createJSON">createJSON</a></li><li><a href="global.html#createObserverBody">createObserverBody</a></li><li><a href="global.html#createTemplate">createTemplate</a></li><li><a href="global.html#createTemplateTiles">createTemplateTiles</a></li><li><a href="global.html#deleteTemplate">deleteTemplate</a></li><li><a href="global.html#disableTemplate">disableTemplate</a></li><li><a href="global.html#drawTemplateOnTile">drawTemplateOnTile</a></li><li><a href="global.html#escapeHTML">escapeHTML</a></li><li><a href="global.html#getObserverBody">getObserverBody</a></li><li><a href="global.html#handleDisplayError">handleDisplayError</a></li><li><a href="global.html#handleDisplayStatus">handleDisplayStatus</a></li><li><a href="global.html#handleDrag">handleDrag</a></li><li><a href="global.html#importJSON">importJSON</a></li><li><a href="global.html#inject">inject</a></li><li><a href="global.html#negativeSafeModulo">negativeSafeModulo</a></li><li><a href="global.html#numberToEncoded">numberToEncoded</a></li><li><a href="global.html#observe">observe</a></li><li><a href="global.html#observeBlack">observeBlack</a></li><li><a href="global.html#serverTPtoDisplayTP">serverTPtoDisplayTP</a></li><li><a href="global.html#setApiManager">setApiManager</a></li><li><a href="global.html#setTemplatesShouldBeDrawn">setTemplatesShouldBeDrawn</a></li><li><a href="global.html#spontaneousResponseListener">spontaneousResponseListener</a></li><li><a href="global.html#uint8ToBase64">uint8ToBase64</a></li><li><a href="global.html#updateInnerHTML">updateInnerHTML</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Fri Aug 08 2025 15:52:04 GMT-0400 (Eastern Daylight Time)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
||||
178
wiki/utils.js.html
Normal file
178
wiki/utils.js.html
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: utils.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: utils.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>
|
||||
|
||||
/** Sanitizes HTML to display as plain-text.
|
||||
* This prevents some Cross Site Scripting (XSS).
|
||||
* This is handy when you are displaying user-made data, and you *must* use innerHTML.
|
||||
* @param {string} text - The text to sanitize
|
||||
* @returns {string} HTML escaped string
|
||||
* @since 0.44.2
|
||||
* @example
|
||||
* const paragraph = document.createElement('p');
|
||||
* paragraph.innerHTML = escapeHTML('<u>Foobar.</u>');
|
||||
* // Output:
|
||||
* // (Does not include the paragraph element)
|
||||
* // (Output is not HTML formatted)
|
||||
* <p>
|
||||
* "<u>Foobar.</u>"
|
||||
* </p>
|
||||
*/
|
||||
export function escapeHTML(text) {
|
||||
const div = document.createElement('div'); // Creates a div
|
||||
div.textContent = text; // Puts the text in a PLAIN-TEXT property
|
||||
return div.innerHTML; // Returns the HTML property of the div
|
||||
}
|
||||
|
||||
/** Converts the server tile-pixel coordinate system to the displayed tile-pixel coordinate system.
|
||||
* @param {string[]} tile - The tile to convert (as an array like ["12", "124"])
|
||||
* @param {string[]} pixel - The pixel to convert (as an array like ["12", "124"])
|
||||
* @returns {number[]} [tile, pixel]
|
||||
* @since 0.42.4
|
||||
* @example
|
||||
* console.log(serverTPtoDisplayTP(['12', '123'], ['34', '567'])); // [34, 3567]
|
||||
*/
|
||||
export function serverTPtoDisplayTP(tile, pixel) {
|
||||
return [((parseInt(tile[0]) % 4) * 1000) + parseInt(pixel[0]), ((parseInt(tile[1]) % 4) * 1000) + parseInt(pixel[1])];
|
||||
}
|
||||
|
||||
/** Negative-Safe Modulo. You can pass negative numbers into this.
|
||||
* @param {number} a - The first number
|
||||
* @param {number} b - The second number
|
||||
* @returns {number} Result
|
||||
* @author osuplace
|
||||
* @since 0.55.8
|
||||
*/
|
||||
export function negativeSafeModulo(a, b) {
|
||||
return (a % b + b) % b;
|
||||
}
|
||||
|
||||
/** Bypasses terser's stripping of console function calls.
|
||||
* This is so the non-obfuscated code will contain debugging console calls, but the distributed version won't.
|
||||
* However, the distributed version needs to call the console somehow, so this wrapper function is how.
|
||||
* This is the same as `console.log()`.
|
||||
* @param {...any} args - Arguments to be passed into the `log()` function of the Console
|
||||
* @since 0.58.9
|
||||
*/
|
||||
export function consoleLog(...args) {((consoleLog) => consoleLog(...args))(console.log);}
|
||||
|
||||
/** Bypasses terser's stripping of console function calls.
|
||||
* This is so the non-obfuscated code will contain debugging console calls, but the distributed version won't.
|
||||
* However, the distributed version needs to call the console somehow, so this wrapper function is how.
|
||||
* This is the same as `console.error()`.
|
||||
* @param {...any} args - Arguments to be passed into the `error()` function of the Console
|
||||
* @since 0.58.13
|
||||
*/
|
||||
export function consoleError(...args) {((consoleError) => consoleError(...args))(console.error);}
|
||||
|
||||
/** Bypasses terser's stripping of console function calls.
|
||||
* This is so the non-obfuscated code will contain debugging console calls, but the distributed version won't.
|
||||
* However, the distributed version needs to call the console somehow, so this wrapper function is how.
|
||||
* This is the same as `console.warn()`.
|
||||
* @param {...any} args - Arguments to be passed into the `warn()` function of the Console
|
||||
* @since 0.58.13
|
||||
*/
|
||||
export function consoleWarn(...args) {((consoleWarn) => consoleWarn(...args))(console.warn);}
|
||||
|
||||
/** Encodes a number into a custom encoded string.
|
||||
* @param {number} number - The number to encode
|
||||
* @param {string} encoding - The characters to use when encoding
|
||||
* @since 0.65.2
|
||||
* @returns {string} Encoded string
|
||||
* @example
|
||||
* const encode = '012abcABC'; // Base 9
|
||||
* console.log(numberToEncoded(0, encode)); // 0
|
||||
* console.log(numberToEncoded(5, encode)); // c
|
||||
* console.log(numberToEncoded(15, encode)); // 1A
|
||||
* console.log(numberToEncoded(12345, encode)); // 1BCaA
|
||||
*/
|
||||
export function numberToEncoded(number, encoding) {
|
||||
|
||||
if (number === 0) return encoding[0]; // End quickly if number equals 0. No special calculation needed
|
||||
|
||||
let result = ''; // The encoded string
|
||||
const base = encoding.length; // The number of characters used, which determines the base
|
||||
|
||||
// Base conversion algorithm
|
||||
while (number > 0) {
|
||||
result = encoding[number % base] + result; // Find's the character's encoded value determined by the modulo of the base
|
||||
number = Math.floor(number / base); // Divides the number by the base so the next iteration can find the next modulo character
|
||||
}
|
||||
|
||||
return result; // The final encoded string
|
||||
}
|
||||
|
||||
/** Converts a Uint8 array to base64 using the browser's built-in binary to ASCII function
|
||||
* @param {Uint8Array} uint8 - The Uint8Array to convert
|
||||
* @returns {Uint8Array} The base64 encoded Uint8Array
|
||||
* @since 0.72.9
|
||||
*/
|
||||
export function uint8ToBase64(uint8) {
|
||||
let binary = '';
|
||||
for (let i = 0; i < uint8.length; i++) {
|
||||
binary += String.fromCharCode(uint8[i]);
|
||||
}
|
||||
return btoa(binary); // Binary to ASCII
|
||||
}
|
||||
|
||||
/** Decodes a base 64 encoded Uint8 array using the browser's built-in ASCII to binary function
|
||||
* @param {Uint8Array} base64 - The base 64 encoded Uint8Array to convert
|
||||
* @returns {Uint8Array} The decoded Uint8Array
|
||||
* @since 0.72.9
|
||||
*/
|
||||
export function base64ToUint8(base64) {
|
||||
const binary = atob(base64); // ASCII to Binary
|
||||
const array = new Uint8Array(binary.length);
|
||||
for (let i = 0; i < binary.length; i++) {
|
||||
array[i] = binary.charCodeAt(i);
|
||||
}
|
||||
return array;
|
||||
}</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="module.exports.html">exports</a></li><li><a href="module.exports_module.exports.html">exports</a></li></ul><h3>Global</h3><ul><li><a href="global.html#addBr">addBr</a></li><li><a href="global.html#addButton">addButton</a></li><li><a href="global.html#addButtonHelp">addButtonHelp</a></li><li><a href="global.html#addCheckbox">addCheckbox</a></li><li><a href="global.html#addDiv">addDiv</a></li><li><a href="global.html#addHeader">addHeader</a></li><li><a href="global.html#addHr">addHr</a></li><li><a href="global.html#addImg">addImg</a></li><li><a href="global.html#addInput">addInput</a></li><li><a href="global.html#addInputFile">addInputFile</a></li><li><a href="global.html#addP">addP</a></li><li><a href="global.html#addSmall">addSmall</a></li><li><a href="global.html#addTextarea">addTextarea</a></li><li><a href="global.html#base64ToUint8">base64ToUint8</a></li><li><a href="global.html#buildElement">buildElement</a></li><li><a href="global.html#buildOverlay">buildOverlay</a></li><li><a href="global.html#buildOverlayMain">buildOverlayMain</a></li><li><a href="global.html#consoleError">consoleError</a></li><li><a href="global.html#consoleLog">consoleLog</a></li><li><a href="global.html#consoleWarn">consoleWarn</a></li><li><a href="global.html#createJSON">createJSON</a></li><li><a href="global.html#createObserverBody">createObserverBody</a></li><li><a href="global.html#createTemplate">createTemplate</a></li><li><a href="global.html#createTemplateTiles">createTemplateTiles</a></li><li><a href="global.html#deleteTemplate">deleteTemplate</a></li><li><a href="global.html#disableTemplate">disableTemplate</a></li><li><a href="global.html#drawTemplateOnTile">drawTemplateOnTile</a></li><li><a href="global.html#escapeHTML">escapeHTML</a></li><li><a href="global.html#getObserverBody">getObserverBody</a></li><li><a href="global.html#handleDisplayError">handleDisplayError</a></li><li><a href="global.html#handleDisplayStatus">handleDisplayStatus</a></li><li><a href="global.html#handleDrag">handleDrag</a></li><li><a href="global.html#importJSON">importJSON</a></li><li><a href="global.html#inject">inject</a></li><li><a href="global.html#negativeSafeModulo">negativeSafeModulo</a></li><li><a href="global.html#numberToEncoded">numberToEncoded</a></li><li><a href="global.html#observe">observe</a></li><li><a href="global.html#observeBlack">observeBlack</a></li><li><a href="global.html#serverTPtoDisplayTP">serverTPtoDisplayTP</a></li><li><a href="global.html#setApiManager">setApiManager</a></li><li><a href="global.html#setTemplatesShouldBeDrawn">setTemplatesShouldBeDrawn</a></li><li><a href="global.html#spontaneousResponseListener">spontaneousResponseListener</a></li><li><a href="global.html#uint8ToBase64">uint8ToBase64</a></li><li><a href="global.html#updateInnerHTML">updateInnerHTML</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Fri Aug 08 2025 15:52:04 GMT-0400 (Eastern Daylight Time)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in a new issue