Constant RUNTIME_JS
Source pub const RUNTIME_JS: &[u8] = b"/*! Spark \xe2\x80\x94 Anvilforge\'s reactive component runtime.\n * Loaded via @sparkScripts; binds spark:* attributes and round-trips to\n * /_spark/update. No external dependencies.\n */\n(function () {\n \'use strict\';\n\n // \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 Boot data (from `window.__spark_boot` emitted by @sparkScripts) \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n var BOOT = (window && window.__spark_boot) || {\n csrf: \'\',\n endpoint: \'/_spark/update\',\n mounts: [],\n };\n\n function csrfHeaders() {\n return {\n \'Content-Type\': \'application/json\',\n \'X-CSRF-TOKEN\': BOOT.csrf || \'\',\n Accept: \'application/json\',\n };\n }\n\n // \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 Component registry \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n // Each component is identified by its root element\'s `spark:id` attribute.\n // We don\'t keep state in JS; the snapshot lives on the DOM as `spark:snapshot`.\n function componentRoot(el) {\n while (el && el.nodeType === 1) {\n if (el.hasAttribute && el.hasAttribute(\'spark:id\')) return el;\n el = el.parentNode;\n }\n return null;\n }\n\n function snapshotOf(root) {\n return root.getAttribute(\'spark:snapshot\') || \'\';\n }\n\n function setSnapshot(root, wire) {\n root.setAttribute(\'spark:snapshot\', wire);\n }\n\n // \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 morphdom-lite \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n // Minimal DOM morphing. Preserves focus on inputs and respects spark:ignore.\n function morph(fromNode, toNode) {\n if (fromNode.nodeType !== toNode.nodeType) {\n fromNode.parentNode && fromNode.parentNode.replaceChild(toNode, fromNode);\n return toNode;\n }\n if (fromNode.nodeType === 3) {\n if (fromNode.nodeValue !== toNode.nodeValue) fromNode.nodeValue = toNode.nodeValue;\n return fromNode;\n }\n if (fromNode.nodeType !== 1) return fromNode;\n if (fromNode.tagName !== toNode.tagName) {\n fromNode.parentNode && fromNode.parentNode.replaceChild(toNode, fromNode);\n return toNode;\n }\n if (fromNode.hasAttribute && fromNode.hasAttribute(\'spark:ignore\')) return fromNode;\n\n // Attributes: diff sets.\n var fromAttrs = fromNode.attributes;\n for (var i = fromAttrs.length - 1; i >= 0; i--) {\n var name = fromAttrs[i].name;\n if (!toNode.hasAttribute(name)) fromNode.removeAttribute(name);\n }\n var toAttrs = toNode.attributes;\n for (var j = 0; j < toAttrs.length; j++) {\n var a = toAttrs[j];\n if (fromNode.getAttribute(a.name) !== a.value) {\n fromNode.setAttribute(a.name, a.value);\n }\n }\n\n // Form value preservation: inputs with spark:model keep user-typed value\n // unless server explicitly changed it.\n if (\n fromNode.tagName === \'INPUT\' ||\n fromNode.tagName === \'TEXTAREA\' ||\n fromNode.tagName === \'SELECT\'\n ) {\n if (fromNode.hasAttribute(\'spark:model\')) {\n var newVal = toNode.getAttribute(\'value\');\n if (newVal !== null && fromNode.value !== newVal) {\n fromNode.value = newVal;\n }\n }\n }\n\n // Children: pairwise morph + tail adjust.\n var fc = fromNode.firstChild;\n var tc = toNode.firstChild;\n while (fc || tc) {\n if (!tc) {\n var nextFc = fc.nextSibling;\n fromNode.removeChild(fc);\n fc = nextFc;\n continue;\n }\n if (!fc) {\n var nextTc = tc.nextSibling;\n fromNode.appendChild(tc);\n tc = nextTc;\n continue;\n }\n var nextFromSibling = fc.nextSibling;\n var nextToSibling = tc.nextSibling;\n morph(fc, tc);\n fc = nextFromSibling;\n tc = nextToSibling;\n }\n return fromNode;\n }\n\n function parseHtml(html) {\n var wrapper = document.createElement(\'div\');\n wrapper.innerHTML = html.trim();\n return wrapper.firstChild;\n }\n\n // \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 Request batching \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n function sendUpdate(componentRoot, payload) {\n return fetch(BOOT.endpoint || \'/_spark/update\', {\n method: \'POST\',\n headers: csrfHeaders(),\n body: JSON.stringify({\n _token: BOOT.csrf || \'\',\n components: [\n Object.assign(\n { snapshot: snapshotOf(componentRoot), updates: [], calls: [] },\n payload\n ),\n ],\n }),\n })\n .then(function (resp) {\n if (resp.status === 419) {\n // Snapshot expired \xe2\x80\x94 reload.\n window.location.reload();\n throw new Error(\'snapshot expired\');\n }\n if (!resp.ok) {\n return resp.text().then(function (t) {\n throw new Error(\'spark: \' + resp.status + \' \' + t);\n });\n }\n return resp.json();\n })\n .then(function (body) {\n if (!body || !body.components || !body.components.length) return;\n var result = body.components[0];\n applyResult(componentRoot, result);\n });\n }\n\n function applyResult(currentRoot, result) {\n // Set the new snapshot first so the boot reflection sees it.\n setSnapshot(currentRoot, result.snapshot);\n\n // Apply islands (partial morph) if present; else morph the whole subtree.\n if (result.effects && result.effects.islands && result.effects.islands.length) {\n result.effects.islands.forEach(function (island) {\n var target = currentRoot.querySelector(\n \'[spark\\\\:island=\"\' + island.name + \'\"]\'\n );\n if (!target) return;\n var fragment = parseHtml(island.html);\n if (fragment) morph(target, fragment);\n });\n } else if (result.html) {\n var newRoot = parseHtml(result.html);\n if (newRoot) morph(currentRoot, newRoot);\n }\n\n // Side effects.\n if (result.effects) {\n (result.effects.dispatched || []).forEach(function (d) {\n window.dispatchEvent(new CustomEvent(d.event, { detail: d.payload }));\n });\n (result.effects.emitted || []).forEach(function (e) {\n window.dispatchEvent(\n new CustomEvent(\'spark:emit:\' + e.event, { detail: e.payload })\n );\n });\n if (result.effects.redirect) {\n window.location.href = result.effects.redirect;\n }\n }\n }\n\n // \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 Event binding \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n // We attach a small set of capturing handlers at document level. Each handler\n // walks up to the nearest spark:* attribute and dispatches accordingly.\n\n function parseAction(value) {\n // Accepts `methodName` or `methodName(arg1, arg2)`.\n var m = /^([A-Za-z_][A-Za-z0-9_]*)(\\((.*)\\))?$/.exec((value || \'\').trim());\n if (!m) return null;\n var method = m[1];\n var argsList = (m[3] || \'\').trim();\n var params = [];\n if (argsList.length) {\n // Naive split on top-level commas. Wrapped strings respected.\n params = splitCommaArgs(argsList).map(function (a) {\n return parseLiteral(a.trim());\n });\n }\n return { method: method, params: params };\n }\n\n function splitCommaArgs(s) {\n var out = [];\n var depth = 0;\n var inString = null;\n var start = 0;\n for (var i = 0; i < s.length; i++) {\n var c = s.charAt(i);\n if (inString) {\n if (c === inString && s.charAt(i - 1) !== \'\\\\\') inString = null;\n continue;\n }\n if (c === \'\"\' || c === \"\'\") { inString = c; continue; }\n if (c === \'(\' || c === \'[\' || c === \'{\') depth++;\n else if (c === \')\' || c === \']\' || c === \'}\') depth--;\n else if (c === \',\' && depth === 0) {\n out.push(s.substring(start, i));\n start = i + 1;\n }\n }\n if (start < s.length) out.push(s.substring(start));\n return out;\n }\n\n function parseLiteral(s) {\n if (s === \'true\') return true;\n if (s === \'false\') return false;\n if (s === \'null\') return null;\n if (/^-?\\d+$/.test(s)) return parseInt(s, 10);\n if (/^-?\\d+\\.\\d+$/.test(s)) return parseFloat(s);\n if ((s.startsWith(\'\"\') && s.endsWith(\'\"\')) || (s.startsWith(\"\'\") && s.endsWith(\"\'\"))) {\n return s.substring(1, s.length - 1);\n }\n return s; // fall through as raw string\n }\n\n function dispatchAction(root, parsed, opts) {\n if (!root || !parsed) return;\n var calls = [{ method: parsed.method, params: parsed.params, island: opts && opts.island }];\n return sendUpdate(root, { calls: calls });\n }\n\n function dispatchUpdate(root, name, value) {\n if (!root) return;\n var updates = [{ name: name, value: value }];\n return sendUpdate(root, { updates: updates });\n }\n\n // \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 spark:click \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n document.addEventListener(\'click\', function (event) {\n var el = event.target;\n while (el && el !== document) {\n if (el.hasAttribute && el.hasAttribute(\'spark:click\')) {\n var action = parseAction(el.getAttribute(\'spark:click\'));\n if (!action) return;\n var root = componentRoot(el);\n if (!root) return;\n toggleLoading(root, true);\n dispatchAction(root, action).finally(function () { toggleLoading(root, false); });\n return;\n }\n el = el.parentNode;\n }\n });\n\n // \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 spark:submit \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n document.addEventListener(\'submit\', function (event) {\n var form = event.target;\n if (!form || !form.hasAttribute || !form.hasAttribute(\'spark:submit\')) return;\n event.preventDefault();\n var action = parseAction(form.getAttribute(\'spark:submit\'));\n if (!action) return;\n var root = componentRoot(form);\n if (!root) return;\n var data = new FormData(form);\n var updates = [];\n data.forEach(function (val, key) { updates.push({ name: key, value: val }); });\n var calls = [{ method: action.method, params: action.params }];\n toggleLoading(root, true);\n sendUpdate(root, { updates: updates, calls: calls }).finally(function () {\n toggleLoading(root, false);\n });\n });\n\n // \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 spark:keydown.<key> \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n document.addEventListener(\'keydown\', function (event) {\n var el = event.target;\n while (el && el !== document) {\n if (el.attributes) {\n for (var i = 0; i < el.attributes.length; i++) {\n var attr = el.attributes[i];\n var m = /^spark:keydown\\.(.+)$/.exec(attr.name);\n if (m && m[1].toLowerCase() === event.key.toLowerCase()) {\n var action = parseAction(attr.value);\n if (!action) return;\n var root = componentRoot(el);\n if (!root) return;\n dispatchAction(root, action);\n return;\n }\n }\n }\n el = el.parentNode;\n }\n });\n\n // \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 spark:model[.modifiers] \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n var pendingModel = new WeakMap();\n function findModelAttr(el) {\n if (!el.attributes) return null;\n for (var i = 0; i < el.attributes.length; i++) {\n var a = el.attributes[i];\n if (a.name === \'spark:model\' || a.name.indexOf(\'spark:model.\') === 0) {\n return { attr: a.name, value: a.value };\n }\n }\n return null;\n }\n\n function handleModelChange(el, event) {\n var info = findModelAttr(el);\n if (!info) return;\n var modifiers = info.attr.split(\'.\').slice(1);\n var live = modifiers.indexOf(\'live\') !== -1;\n var lazy = modifiers.indexOf(\'lazy\') !== -1;\n var debounceModifier = modifiers.find(function (m) { return /^debounce$/.test(m); });\n var hasDebounceMs = false;\n var debounceMs = 300;\n for (var i = 0; i < modifiers.length; i++) {\n var ms = /^(\\d+)ms$/.exec(modifiers[i]);\n if (ms) { debounceMs = parseInt(ms[1], 10); hasDebounceMs = true; }\n }\n var name = info.value;\n var value = (el.type === \'checkbox\') ? !!el.checked : el.value;\n var root = componentRoot(el);\n if (!root) return;\n if (lazy && event.type !== \'change\' && event.type !== \'blur\') return;\n if (!live && !lazy && event.type !== \'input\' && event.type !== \'change\') return;\n\n var dispatch = function () {\n dispatchUpdate(root, name, value);\n pendingModel.delete(el);\n };\n\n if (live || hasDebounceMs || debounceModifier) {\n var existing = pendingModel.get(el);\n if (existing) clearTimeout(existing);\n pendingModel.set(el, setTimeout(dispatch, debounceMs));\n } else {\n dispatch();\n }\n }\n\n document.addEventListener(\'input\', function (event) {\n handleModelChange(event.target, event);\n });\n document.addEventListener(\'change\', function (event) {\n handleModelChange(event.target, event);\n });\n document.addEventListener(\'blur\', function (event) {\n handleModelChange(event.target, event);\n }, true);\n\n // \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 spark:loading toggles \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n function toggleLoading(root, isLoading) {\n if (!root) return;\n var elems = root.querySelectorAll(\'[spark\\\\:loading], [spark\\\\:loading\\\\.remove], [spark\\\\:loading\\\\.attr]\');\n elems.forEach(function (el) {\n // Delay support: spark:loading.delay.200ms\n var hasDelay = false;\n var delayMs = 200;\n for (var i = 0; i < el.attributes.length; i++) {\n var name = el.attributes[i].name;\n if (name.indexOf(\'spark:loading.delay.\') === 0) {\n hasDelay = true;\n var m = /(\\d+)ms/.exec(name);\n if (m) delayMs = parseInt(m[1], 10);\n }\n }\n var remove = el.hasAttribute(\'spark:loading.remove\');\n var attrToggle = el.getAttribute(\'spark:loading.attr\');\n\n var apply = function () {\n if (attrToggle) {\n if (isLoading) el.setAttribute(attrToggle, \'\');\n else el.removeAttribute(attrToggle);\n return;\n }\n if (remove) {\n el.style.display = isLoading ? \'none\' : \'\';\n return;\n }\n el.style.display = isLoading ? \'\' : \'none\';\n };\n\n if (hasDelay && isLoading) {\n el.__sparkLoadingTimer = setTimeout(apply, delayMs);\n } else {\n if (el.__sparkLoadingTimer) {\n clearTimeout(el.__sparkLoadingTimer);\n el.__sparkLoadingTimer = null;\n }\n apply();\n }\n });\n }\n\n // Default hide for any spark:loading element on first paint.\n function initLoadingDefaults() {\n document.querySelectorAll(\'[spark\\\\:loading]\').forEach(function (el) {\n if (!el.hasAttribute(\'spark:loading.remove\') && !el.hasAttribute(\'spark:loading.attr\')) {\n el.style.display = \'none\';\n }\n });\n }\n\n // \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 spark:poll[.<ms>] \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n function initPolling() {\n document.querySelectorAll(\'[spark\\\\:poll]\').forEach(function (el) {\n var attr = null;\n for (var i = 0; i < el.attributes.length; i++) {\n if (el.attributes[i].name.indexOf(\'spark:poll\') === 0) {\n attr = el.attributes[i];\n break;\n }\n }\n if (!attr) return;\n var ms = 2000;\n var m = /spark:poll\\.(\\d+)ms/.exec(attr.name);\n if (m) ms = parseInt(m[1], 10);\n var action = parseAction(attr.value || \'refresh\');\n if (!action) return;\n var root = componentRoot(el);\n if (!root) return;\n setInterval(function () {\n if (document.hidden) return;\n dispatchAction(root, action);\n }, ms);\n });\n }\n\n // \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 Echo (WebSocket) subscription for #[spark::on] listeners \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n function initEchoSubscriptions() {\n if (!BOOT.mounts || !BOOT.mounts.length) return;\n // We try to use Laravel Echo if loaded; otherwise we fall back to raw\n // WebSocket against Bellows\' Pusher-protocol endpoint.\n var hasEcho = window.Echo && typeof window.Echo.channel === \'function\';\n BOOT.mounts.forEach(function (mount) {\n (mount.listeners || []).forEach(function (eventName) {\n if (hasEcho) {\n var channel = inferChannel(eventName);\n window.Echo.channel(channel).listen(\'.\' + eventName, function (payload) {\n triggerBroadcast(mount.id, eventName, payload);\n });\n }\n });\n });\n }\n function inferChannel(eventName) {\n var dot = eventName.indexOf(\'.\');\n return dot > 0 ? eventName.substring(0, dot) : eventName;\n }\n function triggerBroadcast(componentId, eventName, payload) {\n var root = document.querySelector(\'[spark\\\\:id=\"\' + componentId + \'\"]\');\n if (!root) return;\n var calls = [{ method: \'__on_broadcast\', params: [eventName, payload || null] }];\n sendUpdate(root, { calls: calls });\n }\n\n // \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80 Public API \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n var Spark = {\n start: function () {\n initLoadingDefaults();\n initPolling();\n initEchoSubscriptions();\n },\n boot: BOOT,\n dispatch: function (event, payload) {\n window.dispatchEvent(new CustomEvent(event, { detail: payload }));\n },\n on: function (event, fn) {\n window.addEventListener(\'spark:emit:\' + event, function (e) {\n fn(e.detail);\n });\n },\n request: function (componentId, payload) {\n var root = document.querySelector(\'[spark\\\\:id=\"\' + componentId + \'\"]\');\n if (root) sendUpdate(root, payload);\n },\n };\n window.Spark = Spark;\n\n if (document.readyState === \'loading\') {\n document.addEventListener(\'DOMContentLoaded\', function () { Spark.start(); });\n } else {\n Spark.start();\n }\n})();\n";