From c32ed859f4abd1591c882f4f2a6ee16b1ec275e2 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Tue, 12 May 2026 14:03:27 +0000
Subject: [PATCH] =A little form recovery magic

---
 assets/js/concise/UtilityFunctions.js |   50 +++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/assets/js/concise/UtilityFunctions.js b/assets/js/concise/UtilityFunctions.js
index 6772ebf..ca5944e 100644
--- a/assets/js/concise/UtilityFunctions.js
+++ b/assets/js/concise/UtilityFunctions.js
@@ -413,14 +413,18 @@
 	}
 }
 
-window.prefixInput = function(input, prefix, wrapper = null, replace = false) {
+window.prefixInput = function(input, prefix, wrapper = null, replace = false, name = false) {
 	if (!input) {
 		console.warn('prefixInput called with null/undefined input');
 		return;
 	}
+	// console.log('Prefixing input: ', input);
+	// console.log('With prefix: ', prefix);
+	// console.log('Wrapper: ', wrapper);
 	const oldId = input.id;
 	const newId = replace ? prefix : `${prefix}${input.name}`;
-
+	// console.log('Old ID: ', oldId);
+	// console.log('New ID: ', newId);
 	// Search for label within wrapper if provided, otherwise use existing logic
 	let label = null;
 
@@ -444,7 +448,9 @@
 	}
 
 	input.id = newId;
-	input.name = newId;
+	if (name) {
+		input.name = newId;
+	}
 }
 
 /**
@@ -893,6 +899,9 @@
 	return ui;
 }
 
+window.sleep = async function (ms = 50) {
+	return new Promise(resolve => setTimeout(resolve, ms));
+};
 
 class DebouncedActions {
 	constructor() {
@@ -995,3 +1004,38 @@
 updateMaxScroll();
 updateScrollProgress(lastY);
 
+
+
+window.decodeHTMLEntities = function(text) {
+	if (!window.decodeHelper) {
+		window.decodeHelper = document.createElement('textarea');
+	}
+
+	window.decodeHelper.innerHTML = text;
+	return window.decodeHelper.value;
+}
+
+
+window.focusNextElement = function() {
+	//add all elements we want to include in our selection
+	var focussableElements =
+		'a:not([disabled]), button:not([disabled]), input[type=text]:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])';
+	if (document.activeElement && document.activeElement.form) {
+		var focussable = Array.prototype.filter.call(
+			document.activeElement.form.querySelectorAll(focussableElements),
+			function (element) {
+				//check for visibility while always include the current activeElement
+				return (
+					element.offsetWidth > 0 ||
+					element.offsetHeight > 0 ||
+					element === document.activeElement
+				);
+			}
+		);
+		var index = focussable.indexOf(document.activeElement);
+		if (index > -1) {
+			var nextElement = focussable[index + 1] || focussable[0];
+			nextElement.focus();
+		}
+	}
+}

--
Gitblit v1.10.0