diff options
Diffstat (limited to 'static/js/timeago.ts')
-rw-r--r-- | static/js/timeago.ts | 113 |
1 files changed, 75 insertions, 38 deletions
diff --git a/static/js/timeago.ts b/static/js/timeago.ts index af974fc..7c1973d 100644 --- a/static/js/timeago.ts +++ b/static/js/timeago.ts @@ -8,49 +8,86 @@ style: "long", }); - const date = () => { - [...document.querySelectorAll("time")] - .forEach( - (element) => { - try { - const time: millisecond = new Date(element.dateTime) || new Date(); - const interval: second = ((new Date().getTime() - time.getTime()) / 1000); - - const seconds: number = Math.floor(interval); - const minutes: number = Math.floor(seconds / 60); - const hours: number = Math.floor(minutes / 60); - const days: number = Math.floor(hours / 24); - - if (Math.sign(seconds) === 1) { - if (seconds <= 60) { return element.textContent = relative.format(-1 * seconds, "second",); } - if (minutes <= 120) { return element.textContent = relative.format(-1 * minutes, "minute",); } - if (hours <= 48) { return element.textContent = relative.format(-1 * hours, "hour",); } - if (days <= 60) { return element.textContent = relative.format(-1 * days, "day",); } - } - - if (Math.sign(seconds) === -1) { - if (-1 * days >= 60) { return element.textContent = relative.format(-1 * days, "day",); } - if (-1 * hours >= 48) { return element.textContent = relative.format(-1 * hours, "hour",); } - if (-1 * minutes >= 120) { return element.textContent = relative.format(-1 * minutes, "minute",); } - if (-1 * seconds >= 0) { return element.textContent = relative.format(-1 * seconds, "second",); } - } - - } catch (error) { - console.error( - "Error: Unable to resolve relative time format!", - error, - ); - } - }, - ); + function viewport(element) { + const options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : { offset: 250 }; + const view = element.getBoundingClientRect(); + return view.top >= -options.offset + && view.left >= -options.offset + && view.bottom <= (self.innerHeight || document.documentElement.clientHeight) + options.offset + && view.right <= (self.innerWidth || document.documentElement.clientWidth) + options.offset; } + const date = function (update) { + const elements = document.querySelectorAll("time"); + for (let i = 0; i < elements.length; ++i) { + const offscreen = !viewport(elements[i]); + const hidden = elements[i].offsetParent === null; + if ((update === "viewport") && (offscreen || hidden)) continue; + + (function (element) { + try { + if (element.dataset.type === "disabled") return; + + const time: millisecond = new Date(element.dateTime) || new Date(); + const interval: second = ((new Date().getTime() - time.getTime()) / 1000); + + const seconds: number = Math.round(interval); + const minutes: number = Math.round(seconds / 60); + const hours: number = Math.round(minutes / 60); + const days: number = Math.round(hours / 24); + + const past = Math.sign(seconds) === 1; + const future = Math.sign(seconds) === -1; + + let tiny = function (string, place) { + return string.split(" ").slice(0, place).join(" ") + string.split(" ")[place].charAt(0); + } + + if (element.dataset.type === "default") { tiny = function (string) { return string; }; } + + if (element.dataset.type === "localDate") { + return element.textContent = new Intl.DateTimeFormat([], { dateStyle: "medium", }).format(time).replace(",", ""); + } + + if (element.dataset.type === "localTime") { + return element.textContent = new Intl.DateTimeFormat([], { + hour12: false, + timeStyle: "short", + }).format(time) + " " + new Intl.DateTimeFormat([], { timeZoneName: "short" }).format(time).split(" ")[1]; + } + + if (past) { + if (seconds <= 60) { return element.textContent = tiny(relative.format(-1 * seconds, "second",), 1); } + if (minutes <= 120) { return element.textContent = tiny(relative.format(-1 * minutes, "minute",), 1); } + if (hours <= 48) { return element.textContent = tiny(relative.format(-1 * hours, "hour",), 1); } + if (days <= 7) { return element.textContent = tiny(relative.format(-1 * days, "day",), 1); } + } + + if (future) { + if (-1 * days >= 4) { return element.textContent = tiny(relative.format(-1 * days, "day",), 2); } + if (-1 * hours >= 3) { return element.textContent = tiny(relative.format(-1 * hours, "hour",), 2); } + if (-1 * minutes >= 2) { return element.textContent = tiny(relative.format(-1 * minutes, "minute",), 2); } + if (-1 * seconds >= 1) { return element.textContent = tiny(relative.format(-1 * seconds, "second",), 2); } + } + } catch (error) { + console.error("ERROR: Relative time resolution failed", error); + } + })(elements[i]); + } + }; + const substitution = setInterval(date, 4); - self.addEventListener("load", () => { - setTimeout(() => { + ["scroll", "URLChangedCustomEvent"].forEach(function (event) { + self.addEventListener(event, function () { + date("viewport"); + }); + }); + + self.addEventListener("DOMContentLoaded", function () { + setTimeout(function () { clearInterval(substitution); - setInterval(date, 1000); + setInterval(function () { date("viewport"); }, 1000); }, 1000); }); })(); |