Jake Vanderwerf
9 days ago 47e77f9fac1155c536b2b87fec552c7fcce66fa6
assets/js/concise/UtilityFunctions.js
@@ -413,30 +413,44 @@
   }
}
window.prefixInput = function(input, prefix, replace = false) {
window.prefixInput = function(input, prefix, wrapper = null, replace = false, name = false) {
   if (!input) {
      console.warn('prefixInput called with null/undefined input');
      return;
   }
   let newId = replace ? prefix : `${prefix}${input.name}`;
   if (input.labels && input.labels.length > 0) {
      input.labels?.forEach(label => {
         label.htmlFor = newId;
      });
   } else if (input.previousElementSibling?.tagName === 'label') {
      let label = input.previousElementSibling;
      if (label) label.htmlFor = newId;
   } else if (input.nextElementSibling?.tagName === 'label') {
      let label = input.nextElementSibling;
      if (label) label.htmlFor = newId;
   }else {
      let label = input.closest('[data-field]')?.querySelector(`label[for="${input.id}"]`);
      if (label) {
         label.htmlFor = newId;
      }
   // 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 {
      // 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;
   }
}
/**
@@ -885,6 +899,9 @@
   return ui;
}
window.sleep = async function (ms = 50) {
   return new Promise(resolve => setTimeout(resolve, ms));
};
class DebouncedActions {
   constructor() {
@@ -975,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();
      }
   }
}