diff options
author | Thedro Neely <thedroneely@gmail.com> | 2024-01-06 19:16:12 -0500 |
---|---|---|
committer | Thedro Neely <thedroneely@gmail.com> | 2024-01-06 19:16:12 -0500 |
commit | 6d745f1e8c7b870524e01ee7a4886db38634e2ae (patch) | |
tree | 4d5964c37fb3d66ed07e5ac0fad46a54d76e979d /public/js/app.js | |
parent | 3c1a341d42994efd4addb942c623bff18b2d034c (diff) | |
download | thedroneely.com-6d745f1e8c7b870524e01ee7a4886db38634e2ae.tar.gz thedroneely.com-6d745f1e8c7b870524e01ee7a4886db38634e2ae.tar.bz2 thedroneely.com-6d745f1e8c7b870524e01ee7a4886db38634e2ae.zip |
app/partials: Unify headers
Make easier to maintain. Use native upload and add htm.
Diffstat (limited to 'public/js/app.js')
-rw-r--r-- | public/js/app.js | 638 |
1 files changed, 359 insertions, 279 deletions
diff --git a/public/js/app.js b/public/js/app.js index b8413e6..0d540ce 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -1,108 +1,108 @@ /** * General Functions */ -function posf (f, a) { for (var i=0; i < a.length; i++) { if (f(a[i])) {return i;} } return -1; } -function apos (x, a) { return (typeof x == 'function') ? posf(x,a) : Array.prototype.indexOf.call(a,x); } -function arem (a, x) { var i = apos(x, a); if (i >= 0) { a.splice(i, 1); } return a; } -function afind (x, a) { var i = apos(x, a); return (i >= 0) ? a[i] : null; } -function addClass (el, cl) { if (el) { var a = el.className.split(' '); if (!afind(cl, a)) { a.unshift(cl); el.className = a.join(' '); } } } -function remClass (el, cl) { if (el) { var a = el.className.split(' '); arem(a, cl); el.className = a.join(' '); } } -function runOnce(action) { runOnce = function(){}; action(); } - -/* - * Context Menu functions - */ -function contextMenuHide(element) { - for (var i = 0; i < element.length; i++) { - element[i].checked = false; +function once(action) { once = function(){}; action(); } + +function contextMenuHide(elements) { + for (var i = 0; i < elements.length; i++) { + elements[i].checked = false; } } -function contextMenuHideOutside(element, event) { - for (var i = 0; i < element.length; i++) { - let notClicked = !element[i].contains(event.target); - if (notClicked && contextMenuInputs[i].checked === true) { contextMenuHide(contextMenuInputs); } +function contextMenuHideOutside(elements, targets, event) { + for (var i = 0; i < elements.length; i++) { + let notClicked = !elements[i].contains(event.target); + if (notClicked && targets[i].checked === true) { contextMenuHide(targets); } } } /** * Remove url query string and hash */ -var url = window.location.href.split('?')[0]; -window.history.replaceState(null, '', url); +var url = self.location.href.split('?')[0]; +self.history.replaceState(null, '', url); /** * Load events */ -var settings = { pager: {} }; - -window.addEventListener('DOMContentLoaded', function() { - if (history.scrollRestoration) { history.scrollRestoration = 'manual'; } - if (localStorage['settings']) { settings = JSON.parse(localStorage['settings']); } - var hash = document.getElementById(location.hash.slice(1)); - var hashInURL = window.location.href.indexOf("#") >= 0; - if (hashInURL && document.body.contains(hash)) { - settings['pager'][url] = window.pageYOffset; - localStorage['settings'] = JSON.stringify(settings); - hash.scrollIntoView(); - return; - } - if (settings['pager'][url] > 0) { window.scrollTo(0, settings['pager'][url]); return; } - settings['pager'][url] = window.pageYOffset; - localStorage['settings'] = JSON.stringify(settings); -}); - -/* - * Click events - */ -document.addEventListener('click', function(event) { - contextMenuHideOutside(contextMenus, event); -}); - -/* - * Touch start events - */ -document.addEventListener('touchstart', function(event) { - contextMenuHideOutside(contextMenus, event); -}); - -/** - * Scroll events - */ -var previousPosition = window.pageYOffset; -var navbar = document.getElementById("navbar"); -var navbarHeight = navbar.offsetHeight; -var scrolls = 0; - -var contextMenus = document.getElementsByTagName('context-menu-container'); -var contextMenuInputs = document.querySelectorAll('context-menu-container input'); - -window.addEventListener('scroll', function() { - - contextMenuHide(contextMenuInputs); - - var currentPosition = window.pageYOffset; - var velocity = previousPosition - currentPosition; +var pager = {}; + +self.addEventListener('DOMContentLoaded', function() { + (function () { + if (history.scrollRestoration) { history.scrollRestoration = 'manual'; } + if (localStorage['pager']) { pager = JSON.parse(localStorage['pager']); } + var hash = self.location.hash.slice(1) && document.getElementById(self.location.hash.slice(1)); + var hashInURL = self.location.href.indexOf("#") >= 0; + if (hashInURL && document.body.contains(hash)) { + pager[url] = self.pageYOffset; + localStorage['pager'] = JSON.stringify(pager); + return hash.scrollIntoView(); + } + if (pager[url] > 0) { return self.scrollTo(0, pager[url]); } + pager[url] = self.pageYOffset; + localStorage['pager'] = JSON.stringify(pager); + })(); + + /** + * Scroll events + */ + var scrolls = 0; + var previousPosition = self.pageYOffset; + var navbar = document.getElementById("navbar"); + var navbarHeight = navbar.offsetHeight; + + var contextMenus = document.getElementsByTagName('context-menu-container'); + var contextMenuInputs = document.querySelectorAll('context-menu-container input'); + + self.addEventListener('scroll', function() { + contextMenuHide(contextMenuInputs); + + var currentPosition = self.pageYOffset; + var velocity = previousPosition - currentPosition; + + pager[url] = currentPosition; + localStorage['pager'] = JSON.stringify(pager); + + if (scrolls > 3) { + if (velocity > 75 || currentPosition < navbarHeight) { + navbar.classList.remove('hide'); + } else if (velocity < -25) { + navbar.classList.add('hide'); + } else if (currentPosition > navbarHeight) { + once(function () { navbar.classList.add('hide'); }); + } + } + previousPosition = currentPosition; + scrolls++; + }); - settings['pager'][url] = currentPosition; - localStorage['settings'] = JSON.stringify(settings); + /* + * Click events + */ + self.addEventListener('click', function(event) { + contextMenuHideOutside(contextMenus, contextMenuInputs, event); + }); - if (scrolls > 3) { - if (velocity > 75 || currentPosition < navbarHeight) { - remClass(navbar, 'hide'); - } else if (velocity < -25) { - addClass(navbar, 'hide'); - } else if (currentPosition > navbarHeight) { - runOnce(function () { addClass(navbar, 'hide'); }); - } - } + /* + * Touch start events + */ + self.addEventListener('touchstart', function(event) { + contextMenuHideOutside(contextMenus, contextMenuInputs, event); + }); - previousPosition = currentPosition; - scrolls++; -}); + /* + * Hash change events + */ + self.addEventListener("hashchange", function () { + document.getElementById(self.location.hash.slice(1)).scrollIntoView(); + }); -window.addEventListener("hashchange", function () { - document.getElementById(location.hash.slice(1)).scrollIntoView(); + /** + * Activate Medium Zoom + */ + var imageZoom = mediumZoom('[data-image-zoom]'); + imageZoom.on('open', function() { navbar.classList.add('hide'); }); + imageZoom.on('close', function() { navbar.classList.remove('hide'); }); }); /** @@ -594,248 +594,328 @@ window.addEventListener("hashchange", function () { return mediumZoom; }); - -/** - * Activate Medium Zoom - */ -var imageZoom = mediumZoom('[data-image-zoom]'); -imageZoom.on('open', function() { addClass(navbar, 'hide'); }); -imageZoom.on('close', function() { remClass(navbar, 'hide'); }); - - -/** - * Instant Page v3.0.0 - (C) 2019 Alexandre Dieulot - https://instant.page/license - */ -let mouseoverTimer; -let lastTouchTimestamp; -const prefetches = new Set(); -const prefetchElement = document.createElement('link'); -const isSupported = prefetchElement.relList && prefetchElement.relList.supports && prefetchElement.relList.supports('prefetch') - && window.IntersectionObserver && 'isIntersecting' in IntersectionObserverEntry.prototype; -const allowQueryString = 'instantAllowQueryString' in document.body.dataset; -const allowExternalLinks = 'instantAllowExternalLinks' in document.body.dataset; -const useWhitelist = 'instantWhitelist' in document.body.dataset; - -let delayOnHover = 65; -let useMousedown = false; -let useMousedownOnly = false; -let useViewport = false; -if ('instantIntensity' in document.body.dataset) { - const intensity = document.body.dataset.instantIntensity; - - if (intensity.substr(0, 'mousedown'.length) == 'mousedown') { - useMousedown = true; - if (intensity == 'mousedown-only') { - useMousedownOnly = true; - } - } - else if (intensity.substr(0, 'viewport'.length) == 'viewport') { - if (!(navigator.connection && (navigator.connection.saveData || navigator.connection.effectiveType.includes('2g')))) { - if (intensity == "viewport") { - /* Biggest iPhone resolution (which we want): 414 × 896 = 370944 +(function () { + self.addEventListener("DOMContentLoaded", function () { + /*! instant.page v5.1.0 - (C) 2019-2020 Alexandre Dieulot - https://instant.page/license */ + + let mouseoverTimer; + let lastTouchTimestamp; + const prefetches = new Set(); + const prefetchElement = document.createElement("link"); + const isSupported = prefetchElement.relList && + prefetchElement.relList.supports && + prefetchElement.relList.supports("prefetch") && + window.IntersectionObserver && + "isIntersecting" in IntersectionObserverEntry.prototype; + const allowQueryString = "instantAllowQueryString" in document.body.dataset; + const allowExternalLinks = "instantAllowExternalLinks" in + document.body.dataset; + const useWhitelist = "instantWhitelist" in document.body.dataset; + const mousedownShortcut = "instantMousedownShortcut" in + document.body.dataset; + const DELAY_TO_NOT_BE_CONSIDERED_A_TOUCH_INITIATED_ACTION = 1111; + + let delayOnHover = 65; + let useMousedown = false; + let useMousedownOnly = false; + let useViewport = false; + + if ("instantIntensity" in document.body.dataset) { + const intensity = document.body.dataset.instantIntensity; + + if (intensity.substr(0, "mousedown".length) == "mousedown") { + useMousedown = true; + if (intensity == "mousedown-only") { + useMousedownOnly = true; + } + } else if (intensity.substr(0, "viewport".length) == "viewport") { + if ( + !(navigator.connection && + (navigator.connection.saveData || + (navigator.connection.effectiveType && + navigator.connection.effectiveType.includes("2g")))) + ) { + if (intensity == "viewport") { + /* Biggest iPhone resolution (which we want): 414 × 896 = 370944 * Small 7" tablet resolution (which we don’t want): 600 × 1024 = 614400 * Note that the viewport (which we check here) is smaller than the resolution due to the UI’s chrome */ - if (document.documentElement.clientWidth * document.documentElement.clientHeight < 450000) { - useViewport = true; + if ( + document.documentElement.clientWidth * + document.documentElement.clientHeight < 450000 + ) { + useViewport = true; + } + } else if (intensity == "viewport-all") { + useViewport = true; + } + } + } else { + const milliseconds = parseInt(intensity); + if (!isNaN(milliseconds)) { + delayOnHover = milliseconds; } } - else if (intensity == "viewport-all") { - useViewport = true; - } - } - } - else { - const milliseconds = parseInt(intensity); - if (!isNaN(milliseconds)) { - delayOnHover = milliseconds; } - } -} -if (isSupported) { - const eventListenersOptions = { - capture: true, - passive: true, - }; + if (isSupported) { + const eventListenersOptions = { + capture: true, + passive: true, + }; - if (!useMousedownOnly) { - document.addEventListener('touchstart', touchstartListener, eventListenersOptions); - } + if (!useMousedownOnly) { + document.addEventListener( + "touchstart", + touchstartListener, + eventListenersOptions, + ); + } - if (!useMousedown) { - document.addEventListener('mouseover', mouseoverListener, eventListenersOptions); - } - else { - document.addEventListener('mousedown', mousedownListener, eventListenersOptions); - } + if (!useMousedown) { + document.addEventListener( + "mouseover", + mouseoverListener, + eventListenersOptions, + ); + } else if (!mousedownShortcut) { + document.addEventListener( + "mousedown", + mousedownListener, + eventListenersOptions, + ); + } + + if (mousedownShortcut) { + document.addEventListener( + "mousedown", + mousedownShortcutListener, + eventListenersOptions, + ); + } + + if (useViewport) { + let triggeringFunction; + if (window.requestIdleCallback) { + triggeringFunction = function (callback) { + requestIdleCallback(callback, { + timeout: 1500, + }); + }; + } else { + triggeringFunction = function (callback) { + callback(); + }; + } - if (useViewport) { - let triggeringFunction; - if (window.requestIdleCallback) { - triggeringFunction = function(callback) { - requestIdleCallback(callback, { - timeout: 1500, + triggeringFunction(function () { + const intersectionObserver = new IntersectionObserver( + function (entries) { + entries.forEach(function (entry) { + if (entry.isIntersecting) { + const linkElement = entry.target; + intersectionObserver.unobserve(linkElement); + preload(linkElement.href); + } + }); + }, + ); + + document.querySelectorAll("a").forEach(function (linkElement) { + if (isPreloadable(linkElement)) { + intersectionObserver.observe(linkElement); + } + }); }); - }; + } } - else { - triggeringFunction = function(callback) { - callback(); - }; + + function touchstartListener(event) { + /* Chrome on Android calls mouseover before touchcancel so `lastTouchTimestamp` + * must be assigned on touchstart to be measured on mouseover. */ + lastTouchTimestamp = performance.now(); + + const linkElement = event.target.closest("a"); + + if (!isPreloadable(linkElement)) { + return; + } + + preload(linkElement.href); } - triggeringFunction(function() { - const intersectionObserver = new IntersectionObserver(function(entries) { - entries.forEach(function(entry) { - if (entry.isIntersecting) { - const linkElement = entry.target; - intersectionObserver.unobserve(linkElement); - preload(linkElement.href); - } - }); - }); + function mouseoverListener(event) { + if ( + performance.now() - lastTouchTimestamp < + DELAY_TO_NOT_BE_CONSIDERED_A_TOUCH_INITIATED_ACTION + ) { + return; + } - document.querySelectorAll('a').forEach(function(linkElement) { - if (isPreloadable(linkElement)) { - intersectionObserver.observe(linkElement); - } - }); - }); - } -} + const linkElement = event.target.closest("a"); -function touchstartListener(event) { - /* Chrome on Android calls mouseover before touchcancel so `lastTouchTimestamp` - * must be assigned on touchstart to be measured on mouseover. */ - lastTouchTimestamp = performance.now(); + if (!isPreloadable(linkElement)) { + return; + } - const linkElement = event.target.closest('a'); + linkElement.addEventListener("mouseout", mouseoutListener, { + passive: true, + }); - if (!isPreloadable(linkElement)) { - return; - } + mouseoverTimer = setTimeout(function () { + preload(linkElement.href); + mouseoverTimer = undefined; + }, delayOnHover); + } - preload(linkElement.href); -} + function mousedownListener(event) { + const linkElement = event.target.closest("a"); -function mouseoverListener(event) { - if (performance.now() - lastTouchTimestamp < 1100) { - return; - } + if (!isPreloadable(linkElement)) { + return; + } - const linkElement = event.target.closest('a'); + preload(linkElement.href); + } - if (!isPreloadable(linkElement)) { - return; - } + function mouseoutListener(event) { + if ( + event.relatedTarget && + event.target.closest("a") == event.relatedTarget.closest("a") + ) { + return; + } - linkElement.addEventListener('mouseout', mouseoutListener, {passive: true}); + if (mouseoverTimer) { + clearTimeout(mouseoverTimer); + mouseoverTimer = undefined; + } + } - mouseoverTimer = setTimeout(function() { - preload(linkElement.href); - mouseoverTimer = undefined; - }, delayOnHover); -} + function mousedownShortcutListener(event) { + if ( + performance.now() - lastTouchTimestamp < + DELAY_TO_NOT_BE_CONSIDERED_A_TOUCH_INITIATED_ACTION + ) { + return; + } -function mousedownListener(event) { - const linkElement = event.target.closest('a'); + const linkElement = event.target.closest("a"); - if (!isPreloadable(linkElement)) { - return; - } + if (event.which > 1 || event.metaKey || event.ctrlKey) { + return; + } - preload(linkElement.href); -} + if (!linkElement) { + return; + } -function mouseoutListener(event) { - if (event.relatedTarget && event.target.closest('a') == event.relatedTarget.closest('a')) { - return; - } + linkElement.addEventListener("click", function (event) { + if (event.detail == 1337) { + return; + } - if (mouseoverTimer) { - clearTimeout(mouseoverTimer); - mouseoverTimer = undefined; - } -} + event.preventDefault(); + }, { capture: true, passive: false, once: true }); -function isPreloadable(linkElement) { - if (!linkElement || !linkElement.href) { - return; - } + const customEvent = new MouseEvent("click", { + view: window, + bubbles: true, + cancelable: false, + detail: 1337, + }); + linkElement.dispatchEvent(customEvent); + } - if (useWhitelist && !('instant' in linkElement.dataset)) { - return; - } + function isPreloadable(linkElement) { + if (!linkElement || !linkElement.href) { + return; + } - if (!allowExternalLinks && linkElement.origin != location.origin && !('instant' in linkElement.dataset)) { - return; - } + if (useWhitelist && !("instant" in linkElement.dataset)) { + return; + } - if (!['http:', 'https:'].includes(linkElement.protocol)) { - return; - } + if ( + !allowExternalLinks && linkElement.origin != location.origin && + !("instant" in linkElement.dataset) + ) { + return; + } - if (linkElement.protocol == 'http:' && location.protocol == 'https:') { - return; - } + if (!["http:", "https:"].includes(linkElement.protocol)) { + return; + } - if (!allowQueryString && linkElement.search && !('instant' in linkElement.dataset)) { - return; - } + if (linkElement.protocol == "http:" && location.protocol == "https:") { + return; + } - if (linkElement.hash && linkElement.pathname + linkElement.search == location.pathname + location.search) { - return; - } + if ( + !allowQueryString && linkElement.search && + !("instant" in linkElement.dataset) + ) { + return; + } - if ('noInstant' in linkElement.dataset) { - return; - } + if ( + linkElement.hash && + linkElement.pathname + linkElement.search == + location.pathname + location.search + ) { + return; + } - return true; -} + if ("noInstant" in linkElement.dataset) { + return; + } -function preload(url) { - if (prefetches.has(url)) { - return; - } + return true; + } + + function preload(url) { + if (prefetches.has(url)) { + return; + } - const prefetcher = document.createElement('link'); - prefetcher.rel = 'prefetch'; - prefetcher.href = url; - document.head.appendChild(prefetcher); + const prefetcher = document.createElement("link"); + prefetcher.rel = "prefetch"; + prefetcher.href = url; + document.head.appendChild(prefetcher); - prefetches.add(url); -} + prefetches.add(url); + } + }); +})(); /** * Dictionary Access Copyright (C) 2006, Paul Lutus https://arachnoid.com/javascript/dictionary_access.js GPLv2+ */ (function () { - const options = - "targetWindow,width=700,height=500,toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes"; + self.addEventListener("DOMContentLoaded", function () { + const options = "targetWindow,width=700,height=500,toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes"; - self.addEventListener("keydown", function (event) { - if (event.repeat && event.key === "d") { - selection(dictionary); - } - }); + self.addEventListener("keydown", function (event) { + if (event.repeat && event.key === "d") { + selection(dictionary); + } + }); - function selection(execute) { - let phrase = "" + window.getSelection(); - phrase = phrase.replace(/[!.:?,;"]/g, ""); - phrase = phrase.replace(/^\s*(\S*?)\s*$/g, "$1"); - if (phrase && phrase > "" && phrase.length > 1) { - execute(phrase); + function selection(execute) { + let phrase = "" + window.getSelection(); + phrase = phrase.replace(/[!.:?,;"]/g, ""); + phrase = phrase.replace(/^\s*(\S*?)\s*$/g, "$1"); + if (phrase && phrase > "" && phrase.length > 1) { + execute(phrase); + } } - } - function dictionary(word) { - window.open( - "https://www.merriam-webster.com/dictionary/" + - encodeURIComponent(word), - "Definitions", - options, - ); - } + function dictionary(word) { + window.open( + "https://www.merriam-webster.com/dictionary/" + encodeURIComponent(word), + "Definitions", + options, + ); + } + }); })(); |