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 |   65 +++++++++++++++++++++++---------
 1 files changed, 47 insertions(+), 18 deletions(-)

diff --git a/assets/js/concise/UtilityFunctions.js b/assets/js/concise/UtilityFunctions.js
index fe2f543..d80a661 100644
--- a/assets/js/concise/UtilityFunctions.js
+++ b/assets/js/concise/UtilityFunctions.js
@@ -389,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);
@@ -407,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);
@@ -440,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