From 2c955cebb5f1e01fbdb866b50d296fe9fbd852b8 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Tue, 06 Jan 2026 20:40:03 +0000
Subject: [PATCH] =TaxonomySelector.js and creator refactor complete
---
assets/js/concise/UtilityFunctions.js | 102 ++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 80 insertions(+), 22 deletions(-)
diff --git a/assets/js/concise/UtilityFunctions.js b/assets/js/concise/UtilityFunctions.js
index 4a7b85b..d80a661 100644
--- a/assets/js/concise/UtilityFunctions.js
+++ b/assets/js/concise/UtilityFunctions.js
@@ -25,7 +25,7 @@
* @param {string|Date} dateStr Date to format
* @returns {string} Formatted time string
*/
-window.formatTimeAgo = function(dateStr) {
+window.formatTimeAgo = function(dateStr, dateFormat = 'default') {
const date = dateStr instanceof Date ? dateStr : new Date(dateStr);
const now = new Date();
const diffMs = date - now;
@@ -57,14 +57,43 @@
timeStr = `${minutes} ${minutes === 1 ? 'minute' : 'minutes'}`;
} else {
// Hours
- timeStr = `${hours} ${hours === 1 ? 'hour' : 'hours'}`;
+ timeStr = `about ${hours} ${hours === 1 ? 'hour' : 'hours'}`;
}
} else if (days < 7) {
+ if (days === 1) {
+ return isPast ? 'yesterday' : 'tomorrow';
+ }
+ timeStr = `about ${days} days`;
// Days
timeStr = `${days} ${days === 1 ? 'day' : 'days'}`;
} else {
- // More than a week - just show the date
- return date.toLocaleDateString();
+ // More than a week - show the date based on format
+ if (dateFormat === 'default') {
+ return date.toLocaleDateString();
+ }
+
+ // Parse PHP-style format string
+ const formatMap = {
+ 'Y': date.getFullYear(),
+ 'y': String(date.getFullYear()).slice(-2),
+ 'F': date.toLocaleDateString('en-CA', { month: 'long' }),
+ 'M': date.toLocaleDateString('en-CA', { month: 'short' }),
+ 'm': String(date.getMonth() + 1).padStart(2, '0'),
+ 'n': date.getMonth() + 1,
+ 'd': String(date.getDate()).padStart(2, '0'),
+ 'j': date.getDate(),
+ 'D': date.toLocaleDateString('en-CA', { weekday: 'short' }),
+ 'l': date.toLocaleDateString('en-CA', { weekday: 'long' }),
+ 'H': String(date.getHours()).padStart(2, '0'),
+ 'i': String(date.getMinutes()).padStart(2, '0'),
+ 's': String(date.getSeconds()).padStart(2, '0'),
+ 'h': String(date.getHours() % 12 || 12).padStart(2, '0'),
+ 'g': date.getHours() % 12 || 12,
+ 'A': date.getHours() >= 12 ? 'PM' : 'AM',
+ 'a': date.getHours() >= 12 ? 'pm' : 'am',
+ };
+
+ return dateFormat.replace(/[YyFMmnjDlHishgAa]/g, match => formatMap[match]);
}
// Add appropriate prefix/suffix based on past or future
@@ -360,17 +389,23 @@
* @returns {Promise<unknown>}
*/
window.typeText = function(container, text, speed = 50) {
- container.classList.add('typeText');
return new Promise((resolve) => {
+ // Cancel any existing animation on this container
+ if (container._typeInterval) {
+ clearInterval(container._typeInterval);
+ delete container._typeInterval;
+ }
+
let index = 0;
container.textContent = '';
- const interval = setInterval(() => {
+ container._typeInterval = setInterval(() => {
if (index < text.length) {
container.textContent += text.charAt(index);
index++;
} else {
- clearInterval(interval);
+ clearInterval(container._typeInterval);
+ delete container._typeInterval;
resolve();
}
}, speed);
@@ -378,22 +413,29 @@
}
/**
- * Erases text like a keyboard would. TODO: erase a set word from existing text
+ * Erases text like a keyboard would.
* @param container
* @param speed
* @returns {Promise<unknown>}
*/
window.eraseText = function(container, speed = 10) {
return new Promise((resolve) => {
+ // Cancel any existing animation on this container
+ if (container._eraseInterval) {
+ clearInterval(container._eraseInterval);
+ delete container._eraseInterval;
+ }
+
let text = container.textContent;
let index = text.length;
- const interval = setInterval(() => {
+ container._eraseInterval = setInterval(() => {
if (index > 0) {
index--;
container.textContent = text.substring(0, index);
} else {
- clearInterval(interval);
+ clearInterval(container._eraseInterval);
+ delete container._eraseInterval;
resolve();
}
}, speed);
@@ -411,31 +453,47 @@
* @returns {Function} - Call this function to stop the loop
*/
window.typeLoop = function(container, text, typeSpeed = 50, eraseSpeed = 10, pauseAfterType = 1000, pauseAfterErase = 250) {
+ // Generate unique key for this container
+ const containerId = container.id || container.dataset.typeKey || `type-${Date.now()}`;
+ if (!container.dataset.typeKey) {
+ container.dataset.typeKey = containerId;
+ }
+
+ // Stop any existing loop immediately
+ if (container._stopTyping) {
+ container._stopTyping();
+ }
+
let isRunning = true;
async function loop() {
while (isRunning) {
- // Type the text
await window.typeText(container, text, typeSpeed);
-
- // Wait 1 second
+ if (!isRunning) break;
await new Promise(resolve => setTimeout(resolve, pauseAfterType));
-
- // Erase the text
+ if (!isRunning) break;
await window.eraseText(container, eraseSpeed);
-
- // Wait 0.25 seconds before next iteration
+ if (!isRunning) break;
await new Promise(resolve => setTimeout(resolve, pauseAfterErase));
}
}
- // Start the loop
- loop();
-
- // Return a function to stop the loop
- return function stopLoop() {
+ const stopLoop = function() {
isRunning = false;
+ if (container._typeInterval) {
+ clearInterval(container._typeInterval);
+ delete container._typeInterval;
+ }
+ if (container._eraseInterval) {
+ clearInterval(container._eraseInterval);
+ delete container._eraseInterval;
+ }
};
+
+ container._stopTyping = stopLoop;
+ loop(); // Start immediately
+
+ return stopLoop;
};
window.toCamelCase = function (string) {
--
Gitblit v1.10.0