aboutsummaryrefslogtreecommitdiff
path: root/assets/javascript/finder.js
diff options
context:
space:
mode:
Diffstat (limited to 'assets/javascript/finder.js')
-rw-r--r--assets/javascript/finder.js132
1 files changed, 0 insertions, 132 deletions
diff --git a/assets/javascript/finder.js b/assets/javascript/finder.js
deleted file mode 100644
index 925a135..0000000
--- a/assets/javascript/finder.js
+++ /dev/null
@@ -1,132 +0,0 @@
-(() => {
- /** @typedef {{ key: string; elem: HTMLElement; labelElem: HTMLElement | null }} Match */
-
- const addRoot = () => {
- const root = document.createElement('div');
- document.body.appendChild(root);
- return root;
- }
-
- /**
- * @param match {Match}
- * @return {Promise<HTMLElement | null>}
- */
- const createLabelElem = (match) => new Promise((resolve, reject) => {
- const label = Object.assign(document.createElement('div'), {
- className: '__nullbrowser_findlabel',
- textContent: match.key,
- });
- requestAnimationFrame(() => {
- const rect = match.elem.getBoundingClientRect();
- if (rect.top < 0 | rect.top > window.innerHeight) return reject(null);
- if (rect.left < 0 | rect.left > window.innerWidth) return reject(null);
-
- resolve(label);
- requestAnimationFrame(() => {
- Object.assign(label.style, {
- position: 'fixed',
- zIndex: 999999999, // maybe a few more 9s will do
- top: `${rect.top}px`,
- left: `${rect.left}px`,
- backgroundColor: 'yellow',
- border: '1px solid #000',
- boxShadow: '0 0 3px #555',
- color: '#222',
- padding: '1px 2px',
- fontSize: '10px',
- fontWeight: 'bold',
- fontFamily: 'monospace',
- });
- });
- });
- });
-
- const finder = {
- /** @type {string} */
- keys: '',
- /** @type {Array<Match>} */
- matches: [],
- /** @type {HTMLElement | null} */
- labelsRoot: null,
- /** @type {boolean} */
- openInNewView: false,
-
- stop() {
- finder.matches = [];
- finder.keys = '';
- [...(finder.labelsRoot?.children ?? [])].forEach(child => {
- child.remove();
- });
- },
-
- /**
- * @param selector {string}
- * @param new_view {boolean}
- */
- start(selector, new_view) {
- finder.stop()
- finder.labelsRoot ??= addRoot();
- finder.createMatches(selector);
- finder.openInNewView = new_view;
- },
-
- /** @param char {string} */
- filterOutByKey(char) {
- if (!/[0-9]+/.test(char)) return; // NOTE: temporary
-
- finder.keys = finder.keys + char;
- finder.matches = finder.matches.filter(m => {
- const isMatch = m.key.startsWith(finder.keys);
- if (!isMatch) {
- m.labelElem?.remove();
- return false;
- }
- return true;
- });
- if (finder.matches.length <= 1) {
- const match = finder.matches[0]
- finder.stop();
- if (match) {
- if (match.elem?.href) {
- if (finder.openInNewView) {
- window.open(match.elem?.href)
- } else {
- location.href = match.elem?.href
- }
- } else {
- match.elem?.click()
- }
- }
- }
- },
-
- /** @param selector {string} */
- createMatches(selector) {
- finder.matches = [];
- const elements = document.querySelectorAll(selector);
-
- const matches = [...elements].map(async (elem, index) => {
- /** @type {Match} */
- const match = {
- elem,
- key: `${index}`.padStart(`${elements.length}`.length, '0'),
- labelElem: null,
- }
- match.labelElem = await createLabelElem(match);
- return match
- });
-
- Promise.allSettled(matches).then(matches => {
- matches.forEach(result => {
- if (result.status !== 'fulfilled') return;
- if (result.value.labelElem)
- finder.labelsRoot.appendChild(result.value.labelElem)
- finder.matches.push(result.value)
- });
- });
- },
- };
-
- window._nullbrowser ||= {};
- window._nullbrowser.finder ||= finder;
-})();