{"version":3,"file":"app_page_loading.js","sources":["../../../frontend/src/app_page_loading/main.js"],"sourcesContent":["/**\r\n * Shared page-navigation loader (ADR 0005 / industrialization step 3b).\r\n * Same behaviour as legacy static/js/app_page_loading.js — classic script before </body>.\r\n */\r\n\r\nconst SHOW_DELAY_MS = 150;\r\n/** Hide loader if click never left the page (file download / cancelled nav). */\r\nconst STUCK_NAVIGATION_MS = 2000;\r\n/** Pathnames that typically return Content-Disposition: attachment (no document nav). */\r\nconst DOWNLOAD_PATH_RE = /\\.(csv|pdf|ics|xlsx|xls|zip|docx?|odt|rtf|txt)(?:$|[/?#])/i;\r\n\r\nlet loader = null;\r\nlet showTimer = null;\r\nlet stuckTimer = null;\r\nlet navigationPending = false;\r\n\r\nfunction getLoader() {\r\n  if (!loader) {\r\n    loader = document.getElementById('app-page-loader');\r\n  }\r\n  return loader;\r\n}\r\n\r\nfunction clearShowTimer() {\r\n  if (showTimer) {\r\n    clearTimeout(showTimer);\r\n    showTimer = null;\r\n  }\r\n}\r\n\r\nfunction clearStuckTimer() {\r\n  if (stuckTimer) {\r\n    clearTimeout(stuckTimer);\r\n    stuckTimer = null;\r\n  }\r\n}\r\n\r\nfunction hidePageLoader() {\r\n  clearShowTimer();\r\n  clearStuckTimer();\r\n  navigationPending = false;\r\n  const el = getLoader();\r\n  if (!el) {\r\n    return;\r\n  }\r\n  el.classList.remove('is-visible');\r\n  el.setAttribute('hidden', '');\r\n  el.setAttribute('aria-hidden', 'true');\r\n}\r\n\r\nfunction showPageLoader() {\r\n  const el = getLoader();\r\n  if (!el) {\r\n    return;\r\n  }\r\n  el.classList.add('is-visible');\r\n  el.removeAttribute('hidden');\r\n  el.setAttribute('aria-hidden', 'false');\r\n}\r\n\r\nfunction scheduleShowPageLoader() {\r\n  if (navigationPending) {\r\n    return;\r\n  }\r\n  navigationPending = true;\r\n  clearShowTimer();\r\n  clearStuckTimer();\r\n  showTimer = setTimeout(() => {\r\n    showTimer = null;\r\n    if (navigationPending) {\r\n      showPageLoader();\r\n      // Attachment downloads and cancelled navigations never fire pageshow/load again.\r\n      stuckTimer = setTimeout(() => {\r\n        stuckTimer = null;\r\n        if (navigationPending && document.readyState === 'complete') {\r\n          hidePageLoader();\r\n        }\r\n      }, STUCK_NAVIGATION_MS);\r\n    }\r\n  }, SHOW_DELAY_MS);\r\n}\r\n\r\nfunction isModifiedClick(event) {\r\n  return event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0;\r\n}\r\n\r\nfunction looksLikeFileDownload(url) {\r\n  return DOWNLOAD_PATH_RE.test(url.pathname);\r\n}\r\n\r\nfunction shouldIgnoreLink(anchor) {\r\n  if (!anchor || anchor.getAttribute('data-no-page-loader') != null) {\r\n    return true;\r\n  }\r\n  if (anchor.hasAttribute('download')) {\r\n    return true;\r\n  }\r\n  const target = (anchor.getAttribute('target') || '').toLowerCase();\r\n  if (target && target !== '_self') {\r\n    return true;\r\n  }\r\n  const href = anchor.getAttribute('href');\r\n  if (!href || href.charAt(0) === '#') {\r\n    return true;\r\n  }\r\n  const lower = href.toLowerCase();\r\n  if (\r\n    lower.indexOf('mailto:') === 0 ||\r\n    lower.indexOf('tel:') === 0 ||\r\n    lower.indexOf('javascript:') === 0\r\n  ) {\r\n    return true;\r\n  }\r\n  let url;\r\n  try {\r\n    url = new URL(href, window.location.href);\r\n  } catch (_e) {\r\n    return true;\r\n  }\r\n  if (url.origin !== window.location.origin) {\r\n    return true;\r\n  }\r\n  if (looksLikeFileDownload(url)) {\r\n    return true;\r\n  }\r\n  if (\r\n    url.pathname === window.location.pathname &&\r\n    url.search === window.location.search &&\r\n    url.hash\r\n  ) {\r\n    return true;\r\n  }\r\n  return false;\r\n}\r\n\r\nfunction shouldIgnoreForm(form) {\r\n  if (!form || form.getAttribute('data-no-page-loader') != null) {\r\n    return true;\r\n  }\r\n  const target = (form.getAttribute('target') || '').toLowerCase();\r\n  if (target && target !== '_self') {\r\n    return true;\r\n  }\r\n  if ((form.getAttribute('method') || '').toLowerCase() === 'dialog') {\r\n    return true;\r\n  }\r\n  return false;\r\n}\r\n\r\nfunction onDocumentClick(event) {\r\n  if (isModifiedClick(event) || event.defaultPrevented) {\r\n    return;\r\n  }\r\n  const anchor = event.target.closest ? event.target.closest('a[href]') : null;\r\n  if (!anchor || shouldIgnoreLink(anchor)) {\r\n    return;\r\n  }\r\n  scheduleShowPageLoader();\r\n}\r\n\r\nfunction onDocumentSubmit(event) {\r\n  if (event.defaultPrevented) {\r\n    return;\r\n  }\r\n  const form = event.target;\r\n  if (!form || form.tagName !== 'FORM' || shouldIgnoreForm(form)) {\r\n    return;\r\n  }\r\n  scheduleShowPageLoader();\r\n}\r\n\r\nfunction onPageReady() {\r\n  hidePageLoader();\r\n}\r\n\r\ndocument.addEventListener('click', onDocumentClick, true);\r\ndocument.addEventListener('submit', onDocumentSubmit, true);\r\nwindow.addEventListener('pageshow', onPageReady);\r\nwindow.addEventListener('pagehide', () => {\r\n  clearShowTimer();\r\n  clearStuckTimer();\r\n});\r\n\r\nif (document.readyState === 'loading') {\r\n  document.addEventListener('DOMContentLoaded', onPageReady);\r\n} else {\r\n  hidePageLoader();\r\n}\r\nwindow.addEventListener('load', onPageReady);\r\n"],"names":["DOWNLOAD_PATH_RE","loader","showTimer","stuckTimer","navigationPending","getLoader","clearShowTimer","clearStuckTimer","hidePageLoader","el","showPageLoader","scheduleShowPageLoader","isModifiedClick","event","looksLikeFileDownload","url","shouldIgnoreLink","anchor","target","href","lower","shouldIgnoreForm","form","onDocumentClick","onDocumentSubmit","onPageReady"],"mappings":"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"}