From ed57c386db34d8693ca75311972d0929ebe5f488 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Mon, 01 Jun 2026 22:23:19 +0000
Subject: [PATCH] =Added some more Schema classes, allowed for override of  array in outputSchema for complex schema, as for timeline post types

---
 assets/js/concise/UtilityFunctions.js |  151 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 135 insertions(+), 16 deletions(-)

diff --git a/assets/js/concise/UtilityFunctions.js b/assets/js/concise/UtilityFunctions.js
index 2381056..d11cdbc 100644
--- a/assets/js/concise/UtilityFunctions.js
+++ b/assets/js/concise/UtilityFunctions.js
@@ -413,26 +413,44 @@
 	}
 }
 
-window.prefixInput = function(input, prefix, replace = false) {
-	let newId = replace ? prefix : `${prefix}${input.name}`;
-	if (input.labels.length > 0) {
-		input.labels?.forEach(label => {
-			label.htmlFor = newId;
-		});
+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;
+
+	if (wrapper) {
+		// Most reliable: search within wrapper by old ID
+		label = wrapper.querySelector(`label[for="${oldId}"]`);
+	} else if (input.labels && input.labels.length > 0) {
+		// Fallback to input.labels if no wrapper provided
+		label = input.labels[0];
+	} else if (input.previousElementSibling?.tagName === 'LABEL') {
+		label = input.previousElementSibling;
+	} else if (input.nextElementSibling?.tagName === 'LABEL') {
+		label = input.nextElementSibling;
 	} else {
-		if (input.nextElementSibling?.tagName === 'LABEL') {
-			input.nextElementSibling.htmlFor = newId;
-		}else if (input.previousElementSibling?.tagName === 'LABEL') {
-			input.previousElementSibling.htmlFor = newId;
-		} else {
-			let label = input.parentElement.querySelector(`label[for="${input.id}"]`);
-			if (label) {
-				label.htmlFor = newId;
-			}
-		}
+		// Final fallback: search up the tree
+		label = input.closest('[data-field]')?.querySelector(`label[for="${oldId}"]`);
+	}
+
+	if (label) {
+		label.htmlFor = newId;
 	}
 
 	input.id = newId;
+	if (name) {
+		input.name = newId;
+	}
 }
 
 /**
@@ -881,6 +899,9 @@
 	return ui;
 }
 
+window.sleep = async function (ms = 50) {
+	return new Promise(resolve => setTimeout(resolve, ms));
+};
 
 class DebouncedActions {
 	constructor() {
@@ -971,15 +992,113 @@
 	{ passive: true }
 );
 
+
+window.previousBGSize = 'Small';
+window.bgSizes = {
+	Small: 500,
+	Med: 768,
+	Large: 1024
+};
+
+window.bgObserver = new IntersectionObserver((entries) => {
+		entries.forEach(entry => {
+			if (entry.isIntersecting) {
+				let newSize = entry.target.dataset[`bg${window.previousBGSize}`];
+				entry.target.style.backgroundImage = `url(${newSize})`;
+				entry.target.dataset.bgImg = window.previousBGSize;
+				window.bgObserver.unobserve(entry.target);
+			}
+		})
+	},
+	{
+		root: null,
+		rootMargin: '0px 0px -100px 0px',
+		threshold: 0
+	});
+
+function updateBG() {
+	let current = window.innerWidth;
+	let newWidth = getBGWidth(current);
+
+	if (newWidth) {
+		window.previousBGSize = newWidth;
+		document.querySelectorAll('[data-bg-img]:not([data-bg-img="'+window.previousBGSize+'"])').forEach(img => {
+			window.bgObserver.observe(img);
+		});
+	}
+
+}
+function getBGWidth(width) {
+	let prev = window.previousBGSize;
+
+	let check = {
+		Small: ['Med','Large'],
+		Med: ['Large'],
+		Large: false
+	};
+
+	if (!check[prev]) {
+		return false;
+	}
+	let next = 'Small';
+
+	check[prev].forEach(w => {
+		if (width => window.bgSizes[w]) {
+			next = w;
+		}
+	});
+	return next;
+}
+
+updateBG();
+
 // Debounced resize to recalc scrollable height
 window.addEventListener('resize', () => {
 	window.debouncer.schedule('recalc-max-scroll', () => {
 		updateMaxScroll();
 		updateScrollProgress(window.scrollY || docEl.scrollTop || 0);
 	}, 20);
+	window.debouncer.schedule('bg-resize', () => {
+		updateBG();
+	});
 });
 
 // Initial setup
 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