(() => { var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __objRest = (source, exclude) => { var target = {}; for (var prop in source) if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0) target[prop] = source[prop]; if (source != null && __getOwnPropSymbols) for (var prop of __getOwnPropSymbols(source)) { if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop)) target[prop] = source[prop]; } return target; }; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); // vendor/topbar.js var require_topbar = __commonJS({ "vendor/topbar.js"(exports, module) { (function(window2, document2) { "use strict"; (function() { var lastTime = 0; var vendors = ["ms", "moz", "webkit", "o"]; for (var x = 0; x < vendors.length && !window2.requestAnimationFrame; ++x) { window2.requestAnimationFrame = window2[vendors[x] + "RequestAnimationFrame"]; window2.cancelAnimationFrame = window2[vendors[x] + "CancelAnimationFrame"] || window2[vendors[x] + "CancelRequestAnimationFrame"]; } if (!window2.requestAnimationFrame) window2.requestAnimationFrame = function(callback, element) { var currTime = (/* @__PURE__ */ new Date()).getTime(); var timeToCall = Math.max(0, 16 - (currTime - lastTime)); var id = window2.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; return id; }; if (!window2.cancelAnimationFrame) window2.cancelAnimationFrame = function(id) { clearTimeout(id); }; })(); var canvas, currentProgress, showing, progressTimerId = null, fadeTimerId = null, delayTimerId = null, addEvent = function(elem, type, handler) { if (elem.addEventListener) elem.addEventListener(type, handler, false); else if (elem.attachEvent) elem.attachEvent("on" + type, handler); else elem["on" + type] = handler; }, options = { autoRun: true, barThickness: 3, barColors: { 0: "rgba(26, 188, 156, .9)", ".25": "rgba(52, 152, 219, .9)", ".50": "rgba(241, 196, 15, .9)", ".75": "rgba(230, 126, 34, .9)", "1.0": "rgba(211, 84, 0, .9)" }, shadowBlur: 10, shadowColor: "rgba(0, 0, 0, .6)", className: null }, repaint = function() { canvas.width = window2.innerWidth; canvas.height = options.barThickness * 5; var ctx = canvas.getContext("2d"); ctx.shadowBlur = options.shadowBlur; ctx.shadowColor = options.shadowColor; var lineGradient = ctx.createLinearGradient(0, 0, canvas.width, 0); for (var stop in options.barColors) lineGradient.addColorStop(stop, options.barColors[stop]); ctx.lineWidth = options.barThickness; ctx.beginPath(); ctx.moveTo(0, options.barThickness / 2); ctx.lineTo( Math.ceil(currentProgress * canvas.width), options.barThickness / 2 ); ctx.strokeStyle = lineGradient; ctx.stroke(); }, createCanvas = function() { canvas = document2.createElement("canvas"); var style = canvas.style; style.position = "fixed"; style.top = style.left = style.right = style.margin = style.padding = 0; style.zIndex = 100001; style.display = "none"; if (options.className) canvas.classList.add(options.className); document2.body.appendChild(canvas); addEvent(window2, "resize", repaint); }, topbar2 = { config: function(opts) { for (var key in opts) if (options.hasOwnProperty(key)) options[key] = opts[key]; }, show: function(delay) { if (showing) return; if (delay) { if (delayTimerId) return; delayTimerId = setTimeout(() => topbar2.show(), delay); } else { showing = true; if (fadeTimerId !== null) window2.cancelAnimationFrame(fadeTimerId); if (!canvas) createCanvas(); canvas.style.opacity = 1; canvas.style.display = "block"; topbar2.progress(0); if (options.autoRun) { (function loop() { progressTimerId = window2.requestAnimationFrame(loop); topbar2.progress( "+" + 0.05 * Math.pow(1 - Math.sqrt(currentProgress), 2) ); })(); } } }, progress: function(to) { if (typeof to === "undefined") return currentProgress; if (typeof to === "string") { to = (to.indexOf("+") >= 0 || to.indexOf("-") >= 0 ? currentProgress : 0) + parseFloat(to); } currentProgress = to > 1 ? 1 : to; repaint(); return currentProgress; }, hide: function() { clearTimeout(delayTimerId); delayTimerId = null; if (!showing) return; showing = false; if (progressTimerId != null) { window2.cancelAnimationFrame(progressTimerId); progressTimerId = null; } (function loop() { if (topbar2.progress("+.1") >= 1) { canvas.style.opacity -= 0.05; if (canvas.style.opacity <= 0.05) { canvas.style.display = "none"; fadeTimerId = null; return; } } fadeTimerId = window2.requestAnimationFrame(loop); })(); } }; if (typeof module === "object" && typeof module.exports === "object") { module.exports = topbar2; } else if (typeof define === "function" && define.amd) { define(function() { return topbar2; }); } else { this.topbar = topbar2; } }).call(exports, window, document); } }); // ../deps/phoenix_html/priv/static/phoenix_html.js (function() { var PolyfillEvent = eventConstructor(); function eventConstructor() { if (typeof window.CustomEvent === "function") return window.CustomEvent; function CustomEvent2(event, params2) { params2 = params2 || { bubbles: false, cancelable: false, detail: void 0 }; var evt = document.createEvent("CustomEvent"); evt.initCustomEvent(event, params2.bubbles, params2.cancelable, params2.detail); return evt; } CustomEvent2.prototype = window.Event.prototype; return CustomEvent2; } function buildHiddenInput(name, value) { var input = document.createElement("input"); input.type = "hidden"; input.name = name; input.value = value; return input; } function handleClick(element, targetModifierKey) { var to = element.getAttribute("data-to"), method = buildHiddenInput("_method", element.getAttribute("data-method")), csrf = buildHiddenInput("_csrf_token", element.getAttribute("data-csrf")), form = document.createElement("form"), submit = document.createElement("input"), target = element.getAttribute("target"); form.method = element.getAttribute("data-method") === "get" ? "get" : "post"; form.action = to; form.style.display = "none"; if (target) form.target = target; else if (targetModifierKey) form.target = "_blank"; form.appendChild(csrf); form.appendChild(method); document.body.appendChild(form); submit.type = "submit"; form.appendChild(submit); submit.click(); } window.addEventListener("click", function(e) { var element = e.target; if (e.defaultPrevented) return; while (element && element.getAttribute) { var phoenixLinkEvent = new PolyfillEvent("phoenix.link.click", { "bubbles": true, "cancelable": true }); if (!element.dispatchEvent(phoenixLinkEvent)) { e.preventDefault(); e.stopImmediatePropagation(); return false; } if (element.getAttribute("data-method") && element.getAttribute("data-to")) { handleClick(element, e.metaKey || e.shiftKey); e.preventDefault(); return false; } else { element = element.parentNode; } } }, false); window.addEventListener("phoenix.link.click", function(e) { var message = e.target.getAttribute("data-confirm"); if (message && !window.confirm(message)) { e.preventDefault(); } }, false); })(); // ../deps/phoenix/priv/static/phoenix.mjs var closure = (value) => { if (typeof value === "function") { return value; } else { let closure22 = function() { return value; }; return closure22; } }; var globalSelf = typeof self !== "undefined" ? self : null; var phxWindow = typeof window !== "undefined" ? window : null; var global = globalSelf || phxWindow || global; var DEFAULT_VSN = "2.0.0"; var SOCKET_STATES = { connecting: 0, open: 1, closing: 2, closed: 3 }; var DEFAULT_TIMEOUT = 1e4; var WS_CLOSE_NORMAL = 1e3; var CHANNEL_STATES = { closed: "closed", errored: "errored", joined: "joined", joining: "joining", leaving: "leaving" }; var CHANNEL_EVENTS = { close: "phx_close", error: "phx_error", join: "phx_join", reply: "phx_reply", leave: "phx_leave" }; var TRANSPORTS = { longpoll: "longpoll", websocket: "websocket" }; var XHR_STATES = { complete: 4 }; var Push = class { constructor(channel, event, payload, timeout) { this.channel = channel; this.event = event; this.payload = payload || function() { return {}; }; this.receivedResp = null; this.timeout = timeout; this.timeoutTimer = null; this.recHooks = []; this.sent = false; } /** * * @param {number} timeout */ resend(timeout) { this.timeout = timeout; this.reset(); this.send(); } /** * */ send() { if (this.hasReceived("timeout")) { return; } this.startTimeout(); this.sent = true; this.channel.socket.push({ topic: this.channel.topic, event: this.event, payload: this.payload(), ref: this.ref, join_ref: this.channel.joinRef() }); } /** * * @param {*} status * @param {*} callback */ receive(status, callback) { if (this.hasReceived(status)) { callback(this.receivedResp.response); } this.recHooks.push({ status, callback }); return this; } /** * @private */ reset() { this.cancelRefEvent(); this.ref = null; this.refEvent = null; this.receivedResp = null; this.sent = false; } /** * @private */ matchReceive({ status, response, _ref }) { this.recHooks.filter((h) => h.status === status).forEach((h) => h.callback(response)); } /** * @private */ cancelRefEvent() { if (!this.refEvent) { return; } this.channel.off(this.refEvent); } /** * @private */ cancelTimeout() { clearTimeout(this.timeoutTimer); this.timeoutTimer = null; } /** * @private */ startTimeout() { if (this.timeoutTimer) { this.cancelTimeout(); } this.ref = this.channel.socket.makeRef(); this.refEvent = this.channel.replyEventName(this.ref); this.channel.on(this.refEvent, (payload) => { this.cancelRefEvent(); this.cancelTimeout(); this.receivedResp = payload; this.matchReceive(payload); }); this.timeoutTimer = setTimeout(() => { this.trigger("timeout", {}); }, this.timeout); } /** * @private */ hasReceived(status) { return this.receivedResp && this.receivedResp.status === status; } /** * @private */ trigger(status, response) { this.channel.trigger(this.refEvent, { status, response }); } }; var Timer = class { constructor(callback, timerCalc) { this.callback = callback; this.timerCalc = timerCalc; this.timer = null; this.tries = 0; } reset() { this.tries = 0; clearTimeout(this.timer); } /** * Cancels any previous scheduleTimeout and schedules callback */ scheduleTimeout() { clearTimeout(this.timer); this.timer = setTimeout(() => { this.tries = this.tries + 1; this.callback(); }, this.timerCalc(this.tries + 1)); } }; var Channel = class { constructor(topic, params2, socket) { this.state = CHANNEL_STATES.closed; this.topic = topic; this.params = closure(params2 || {}); this.socket = socket; this.bindings = []; this.bindingRef = 0; this.timeout = this.socket.timeout; this.joinedOnce = false; this.joinPush = new Push(this, CHANNEL_EVENTS.join, this.params, this.timeout); this.pushBuffer = []; this.stateChangeRefs = []; this.rejoinTimer = new Timer(() => { if (this.socket.isConnected()) { this.rejoin(); } }, this.socket.rejoinAfterMs); this.stateChangeRefs.push(this.socket.onError(() => this.rejoinTimer.reset())); this.stateChangeRefs.push( this.socket.onOpen(() => { this.rejoinTimer.reset(); if (this.isErrored()) { this.rejoin(); } }) ); this.joinPush.receive("ok", () => { this.state = CHANNEL_STATES.joined; this.rejoinTimer.reset(); this.pushBuffer.forEach((pushEvent) => pushEvent.send()); this.pushBuffer = []; }); this.joinPush.receive("error", () => { this.state = CHANNEL_STATES.errored; if (this.socket.isConnected()) { this.rejoinTimer.scheduleTimeout(); } }); this.onClose(() => { this.rejoinTimer.reset(); if (this.socket.hasLogger()) this.socket.log("channel", `close ${this.topic} ${this.joinRef()}`); this.state = CHANNEL_STATES.closed; this.socket.remove(this); }); this.onError((reason) => { if (this.socket.hasLogger()) this.socket.log("channel", `error ${this.topic}`, reason); if (this.isJoining()) { this.joinPush.reset(); } this.state = CHANNEL_STATES.errored; if (this.socket.isConnected()) { this.rejoinTimer.scheduleTimeout(); } }); this.joinPush.receive("timeout", () => { if (this.socket.hasLogger()) this.socket.log("channel", `timeout ${this.topic} (${this.joinRef()})`, this.joinPush.timeout); let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), this.timeout); leavePush.send(); this.state = CHANNEL_STATES.errored; this.joinPush.reset(); if (this.socket.isConnected()) { this.rejoinTimer.scheduleTimeout(); } }); this.on(CHANNEL_EVENTS.reply, (payload, ref) => { this.trigger(this.replyEventName(ref), payload); }); } /** * Join the channel * @param {integer} timeout * @returns {Push} */ join(timeout = this.timeout) { if (this.joinedOnce) { throw new Error("tried to join multiple times. 'join' can only be called a single time per channel instance"); } else { this.timeout = timeout; this.joinedOnce = true; this.rejoin(); return this.joinPush; } } /** * Hook into channel close * @param {Function} callback */ onClose(callback) { this.on(CHANNEL_EVENTS.close, callback); } /** * Hook into channel errors * @param {Function} callback */ onError(callback) { return this.on(CHANNEL_EVENTS.error, (reason) => callback(reason)); } /** * Subscribes on channel events * * Subscription returns a ref counter, which can be used later to * unsubscribe the exact event listener * * @example * const ref1 = channel.on("event", do_stuff) * const ref2 = channel.on("event", do_other_stuff) * channel.off("event", ref1) * // Since unsubscription, do_stuff won't fire, * // while do_other_stuff will keep firing on the "event" * * @param {string} event * @param {Function} callback * @returns {integer} ref */ on(event, callback) { let ref = this.bindingRef++; this.bindings.push({ event, ref, callback }); return ref; } /** * Unsubscribes off of channel events * * Use the ref returned from a channel.on() to unsubscribe one * handler, or pass nothing for the ref to unsubscribe all * handlers for the given event. * * @example * // Unsubscribe the do_stuff handler * const ref1 = channel.on("event", do_stuff) * channel.off("event", ref1) * * // Unsubscribe all handlers from event * channel.off("event") * * @param {string} event * @param {integer} ref */ off(event, ref) { this.bindings = this.bindings.filter((bind) => { return !(bind.event === event && (typeof ref === "undefined" || ref === bind.ref)); }); } /** * @private */ canPush() { return this.socket.isConnected() && this.isJoined(); } /** * Sends a message `event` to phoenix with the payload `payload`. * Phoenix receives this in the `handle_in(event, payload, socket)` * function. if phoenix replies or it times out (default 10000ms), * then optionally the reply can be received. * * @example * channel.push("event") * .receive("ok", payload => console.log("phoenix replied:", payload)) * .receive("error", err => console.log("phoenix errored", err)) * .receive("timeout", () => console.log("timed out pushing")) * @param {string} event * @param {Object} payload * @param {number} [timeout] * @returns {Push} */ push(event, payload, timeout = this.timeout) { payload = payload || {}; if (!this.joinedOnce) { throw new Error(`tried to push '${event}' to '${this.topic}' before joining. Use channel.join() before pushing events`); } let pushEvent = new Push(this, event, function() { return payload; }, timeout); if (this.canPush()) { pushEvent.send(); } else { pushEvent.startTimeout(); this.pushBuffer.push(pushEvent); } return pushEvent; } /** Leaves the channel * * Unsubscribes from server events, and * instructs channel to terminate on server * * Triggers onClose() hooks * * To receive leave acknowledgements, use the `receive` * hook to bind to the server ack, ie: * * @example * channel.leave().receive("ok", () => alert("left!") ) * * @param {integer} timeout * @returns {Push} */ leave(timeout = this.timeout) { this.rejoinTimer.reset(); this.joinPush.cancelTimeout(); this.state = CHANNEL_STATES.leaving; let onClose = () => { if (this.socket.hasLogger()) this.socket.log("channel", `leave ${this.topic}`); this.trigger(CHANNEL_EVENTS.close, "leave"); }; let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), timeout); leavePush.receive("ok", () => onClose()).receive("timeout", () => onClose()); leavePush.send(); if (!this.canPush()) { leavePush.trigger("ok", {}); } return leavePush; } /** * Overridable message hook * * Receives all events for specialized message handling * before dispatching to the channel callbacks. * * Must return the payload, modified or unmodified * @param {string} event * @param {Object} payload * @param {integer} ref * @returns {Object} */ onMessage(_event, payload, _ref) { return payload; } /** * @private */ isMember(topic, event, payload, joinRef) { if (this.topic !== topic) { return false; } if (joinRef && joinRef !== this.joinRef()) { if (this.socket.hasLogger()) this.socket.log("channel", "dropping outdated message", { topic, event, payload, joinRef }); return false; } else { return true; } } /** * @private */ joinRef() { return this.joinPush.ref; } /** * @private */ rejoin(timeout = this.timeout) { if (this.isLeaving()) { return; } this.socket.leaveOpenTopic(this.topic); this.state = CHANNEL_STATES.joining; this.joinPush.resend(timeout); } /** * @private */ trigger(event, payload, ref, joinRef) { let handledPayload = this.onMessage(event, payload, ref, joinRef); if (payload && !handledPayload) { throw new Error("channel onMessage callbacks must return the payload, modified or unmodified"); } let eventBindings = this.bindings.filter((bind) => bind.event === event); for (let i = 0; i < eventBindings.length; i++) { let bind = eventBindings[i]; bind.callback(handledPayload, ref, joinRef || this.joinRef()); } } /** * @private */ replyEventName(ref) { return `chan_reply_${ref}`; } /** * @private */ isClosed() { return this.state === CHANNEL_STATES.closed; } /** * @private */ isErrored() { return this.state === CHANNEL_STATES.errored; } /** * @private */ isJoined() { return this.state === CHANNEL_STATES.joined; } /** * @private */ isJoining() { return this.state === CHANNEL_STATES.joining; } /** * @private */ isLeaving() { return this.state === CHANNEL_STATES.leaving; } }; var Ajax = class { static request(method, endPoint, accept, body, timeout, ontimeout, callback) { if (global.XDomainRequest) { let req = new global.XDomainRequest(); return this.xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback); } else { let req = new global.XMLHttpRequest(); return this.xhrRequest(req, method, endPoint, accept, body, timeout, ontimeout, callback); } } static xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback) { req.timeout = timeout; req.open(method, endPoint); req.onload = () => { let response = this.parseJSON(req.responseText); callback && callback(response); }; if (ontimeout) { req.ontimeout = ontimeout; } req.onprogress = () => { }; req.send(body); return req; } static xhrRequest(req, method, endPoint, accept, body, timeout, ontimeout, callback) { req.open(method, endPoint, true); req.timeout = timeout; req.setRequestHeader("Content-Type", accept); req.onerror = () => callback && callback(null); req.onreadystatechange = () => { if (req.readyState === XHR_STATES.complete && callback) { let response = this.parseJSON(req.responseText); callback(response); } }; if (ontimeout) { req.ontimeout = ontimeout; } req.send(body); return req; } static parseJSON(resp) { if (!resp || resp === "") { return null; } try { return JSON.parse(resp); } catch (e) { console && console.log("failed to parse JSON response", resp); return null; } } static serialize(obj, parentKey) { let queryStr = []; for (var key in obj) { if (!Object.prototype.hasOwnProperty.call(obj, key)) { continue; } let paramKey = parentKey ? `${parentKey}[${key}]` : key; let paramVal = obj[key]; if (typeof paramVal === "object") { queryStr.push(this.serialize(paramVal, paramKey)); } else { queryStr.push(encodeURIComponent(paramKey) + "=" + encodeURIComponent(paramVal)); } } return queryStr.join("&"); } static appendParams(url, params2) { if (Object.keys(params2).length === 0) { return url; } let prefix = url.match(/\?/) ? "&" : "?"; return `${url}${prefix}${this.serialize(params2)}`; } }; var arrayBufferToBase64 = (buffer) => { let binary = ""; let bytes = new Uint8Array(buffer); let len = bytes.byteLength; for (let i = 0; i < len; i++) { binary += String.fromCharCode(bytes[i]); } return btoa(binary); }; var LongPoll = class { constructor(endPoint) { this.endPoint = null; this.token = null; this.skipHeartbeat = true; this.reqs = /* @__PURE__ */ new Set(); this.awaitingBatchAck = false; this.currentBatch = null; this.currentBatchTimer = null; this.batchBuffer = []; this.onopen = function() { }; this.onerror = function() { }; this.onmessage = function() { }; this.onclose = function() { }; this.pollEndpoint = this.normalizeEndpoint(endPoint); this.readyState = SOCKET_STATES.connecting; setTimeout(() => this.poll(), 0); } normalizeEndpoint(endPoint) { return endPoint.replace("ws://", "http://").replace("wss://", "https://").replace(new RegExp("(.*)/" + TRANSPORTS.websocket), "$1/" + TRANSPORTS.longpoll); } endpointURL() { return Ajax.appendParams(this.pollEndpoint, { token: this.token }); } closeAndRetry(code, reason, wasClean) { this.close(code, reason, wasClean); this.readyState = SOCKET_STATES.connecting; } ontimeout() { this.onerror("timeout"); this.closeAndRetry(1005, "timeout", false); } isActive() { return this.readyState === SOCKET_STATES.open || this.readyState === SOCKET_STATES.connecting; } poll() { this.ajax("GET", "application/json", null, () => this.ontimeout(), (resp) => { if (resp) { var { status, token, messages } = resp; this.token = token; } else { status = 0; } switch (status) { case 200: messages.forEach((msg) => { setTimeout(() => this.onmessage({ data: msg }), 0); }); this.poll(); break; case 204: this.poll(); break; case 410: this.readyState = SOCKET_STATES.open; this.onopen({}); this.poll(); break; case 403: this.onerror(403); this.close(1008, "forbidden", false); break; case 0: case 500: this.onerror(500); this.closeAndRetry(1011, "internal server error", 500); break; default: throw new Error(`unhandled poll status ${status}`); } }); } // we collect all pushes within the current event loop by // setTimeout 0, which optimizes back-to-back procedural // pushes against an empty buffer send(body) { if (typeof body !== "string") { body = arrayBufferToBase64(body); } if (this.currentBatch) { this.currentBatch.push(body); } else if (this.awaitingBatchAck) { this.batchBuffer.push(body); } else { this.currentBatch = [body]; this.currentBatchTimer = setTimeout(() => { this.batchSend(this.currentBatch); this.currentBatch = null; }, 0); } } batchSend(messages) { this.awaitingBatchAck = true; this.ajax("POST", "application/x-ndjson", messages.join("\n"), () => this.onerror("timeout"), (resp) => { this.awaitingBatchAck = false; if (!resp || resp.status !== 200) { this.onerror(resp && resp.status); this.closeAndRetry(1011, "internal server error", false); } else if (this.batchBuffer.length > 0) { this.batchSend(this.batchBuffer); this.batchBuffer = []; } }); } close(code, reason, wasClean) { for (let req of this.reqs) { req.abort(); } this.readyState = SOCKET_STATES.closed; let opts = Object.assign({ code: 1e3, reason: void 0, wasClean: true }, { code, reason, wasClean }); this.batchBuffer = []; clearTimeout(this.currentBatchTimer); this.currentBatchTimer = null; if (typeof CloseEvent !== "undefined") { this.onclose(new CloseEvent("close", opts)); } else { this.onclose(opts); } } ajax(method, contentType, body, onCallerTimeout, callback) { let req; let ontimeout = () => { this.reqs.delete(req); onCallerTimeout(); }; req = Ajax.request(method, this.endpointURL(), contentType, body, this.timeout, ontimeout, (resp) => { this.reqs.delete(req); if (this.isActive()) { callback(resp); } }); this.reqs.add(req); } }; var serializer_default = { HEADER_LENGTH: 1, META_LENGTH: 4, KINDS: { push: 0, reply: 1, broadcast: 2 }, encode(msg, callback) { if (msg.payload.constructor === ArrayBuffer) { return callback(this.binaryEncode(msg)); } else { let payload = [msg.join_ref, msg.ref, msg.topic, msg.event, msg.payload]; return callback(JSON.stringify(payload)); } }, decode(rawPayload, callback) { if (rawPayload.constructor === ArrayBuffer) { return callback(this.binaryDecode(rawPayload)); } else { let [join_ref, ref, topic, event, payload] = JSON.parse(rawPayload); return callback({ join_ref, ref, topic, event, payload }); } }, // private binaryEncode(message) { let { join_ref, ref, event, topic, payload } = message; let metaLength = this.META_LENGTH + join_ref.length + ref.length + topic.length + event.length; let header = new ArrayBuffer(this.HEADER_LENGTH + metaLength); let view = new DataView(header); let offset = 0; view.setUint8(offset++, this.KINDS.push); view.setUint8(offset++, join_ref.length); view.setUint8(offset++, ref.length); view.setUint8(offset++, topic.length); view.setUint8(offset++, event.length); Array.from(join_ref, (char) => view.setUint8(offset++, char.charCodeAt(0))); Array.from(ref, (char) => view.setUint8(offset++, char.charCodeAt(0))); Array.from(topic, (char) => view.setUint8(offset++, char.charCodeAt(0))); Array.from(event, (char) => view.setUint8(offset++, char.charCodeAt(0))); var combined = new Uint8Array(header.byteLength + payload.byteLength); combined.set(new Uint8Array(header), 0); combined.set(new Uint8Array(payload), header.byteLength); return combined.buffer; }, binaryDecode(buffer) { let view = new DataView(buffer); let kind = view.getUint8(0); let decoder = new TextDecoder(); switch (kind) { case this.KINDS.push: return this.decodePush(buffer, view, decoder); case this.KINDS.reply: return this.decodeReply(buffer, view, decoder); case this.KINDS.broadcast: return this.decodeBroadcast(buffer, view, decoder); } }, decodePush(buffer, view, decoder) { let joinRefSize = view.getUint8(1); let topicSize = view.getUint8(2); let eventSize = view.getUint8(3); let offset = this.HEADER_LENGTH + this.META_LENGTH - 1; let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize)); offset = offset + joinRefSize; let topic = decoder.decode(buffer.slice(offset, offset + topicSize)); offset = offset + topicSize; let event = decoder.decode(buffer.slice(offset, offset + eventSize)); offset = offset + eventSize; let data = buffer.slice(offset, buffer.byteLength); return { join_ref: joinRef, ref: null, topic, event, payload: data }; }, decodeReply(buffer, view, decoder) { let joinRefSize = view.getUint8(1); let refSize = view.getUint8(2); let topicSize = view.getUint8(3); let eventSize = view.getUint8(4); let offset = this.HEADER_LENGTH + this.META_LENGTH; let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize)); offset = offset + joinRefSize; let ref = decoder.decode(buffer.slice(offset, offset + refSize)); offset = offset + refSize; let topic = decoder.decode(buffer.slice(offset, offset + topicSize)); offset = offset + topicSize; let event = decoder.decode(buffer.slice(offset, offset + eventSize)); offset = offset + eventSize; let data = buffer.slice(offset, buffer.byteLength); let payload = { status: event, response: data }; return { join_ref: joinRef, ref, topic, event: CHANNEL_EVENTS.reply, payload }; }, decodeBroadcast(buffer, view, decoder) { let topicSize = view.getUint8(1); let eventSize = view.getUint8(2); let offset = this.HEADER_LENGTH + 2; let topic = decoder.decode(buffer.slice(offset, offset + topicSize)); offset = offset + topicSize; let event = decoder.decode(buffer.slice(offset, offset + eventSize)); offset = offset + eventSize; let data = buffer.slice(offset, buffer.byteLength); return { join_ref: null, ref: null, topic, event, payload: data }; } }; var Socket = class { constructor(endPoint, opts = {}) { this.stateChangeCallbacks = { open: [], close: [], error: [], message: [] }; this.channels = []; this.sendBuffer = []; this.ref = 0; this.timeout = opts.timeout || DEFAULT_TIMEOUT; this.transport = opts.transport || global.WebSocket || LongPoll; this.longPollFallbackMs = opts.longPollFallbackMs; this.fallbackTimer = null; this.sessionStore = opts.sessionStorage || global.sessionStorage; this.establishedConnections = 0; this.defaultEncoder = serializer_default.encode.bind(serializer_default); this.defaultDecoder = serializer_default.decode.bind(serializer_default); this.closeWasClean = false; this.binaryType = opts.binaryType || "arraybuffer"; this.connectClock = 1; if (this.transport !== LongPoll) { this.encode = opts.encode || this.defaultEncoder; this.decode = opts.decode || this.defaultDecoder; } else { this.encode = this.defaultEncoder; this.decode = this.defaultDecoder; } let awaitingConnectionOnPageShow = null; if (phxWindow && phxWindow.addEventListener) { phxWindow.addEventListener("pagehide", (_e) => { if (this.conn) { this.disconnect(); awaitingConnectionOnPageShow = this.connectClock; } }); phxWindow.addEventListener("pageshow", (_e) => { if (awaitingConnectionOnPageShow === this.connectClock) { awaitingConnectionOnPageShow = null; this.connect(); } }); } this.heartbeatIntervalMs = opts.heartbeatIntervalMs || 3e4; this.rejoinAfterMs = (tries) => { if (opts.rejoinAfterMs) { return opts.rejoinAfterMs(tries); } else { return [1e3, 2e3, 5e3][tries - 1] || 1e4; } }; this.reconnectAfterMs = (tries) => { if (opts.reconnectAfterMs) { return opts.reconnectAfterMs(tries); } else { return [10, 50, 100, 150, 200, 250, 500, 1e3, 2e3][tries - 1] || 5e3; } }; this.logger = opts.logger || null; if (!this.logger && opts.debug) { this.logger = (kind, msg, data) => { console.log(`${kind}: ${msg}`, data); }; } this.longpollerTimeout = opts.longpollerTimeout || 2e4; this.params = closure(opts.params || {}); this.endPoint = `${endPoint}/${TRANSPORTS.websocket}`; this.vsn = opts.vsn || DEFAULT_VSN; this.heartbeatTimeoutTimer = null; this.heartbeatTimer = null; this.pendingHeartbeatRef = null; this.reconnectTimer = new Timer(() => { this.teardown(() => this.connect()); }, this.reconnectAfterMs); } /** * Returns the LongPoll transport reference */ getLongPollTransport() { return LongPoll; } /** * Disconnects and replaces the active transport * * @param {Function} newTransport - The new transport class to instantiate * */ replaceTransport(newTransport) { this.connectClock++; this.closeWasClean = true; clearTimeout(this.fallbackTimer); this.reconnectTimer.reset(); if (this.conn) { this.conn.close(); this.conn = null; } this.transport = newTransport; } /** * Returns the socket protocol * * @returns {string} */ protocol() { return location.protocol.match(/^https/) ? "wss" : "ws"; } /** * The fully qualified socket url * * @returns {string} */ endPointURL() { let uri = Ajax.appendParams( Ajax.appendParams(this.endPoint, this.params()), { vsn: this.vsn } ); if (uri.charAt(0) !== "/") { return uri; } if (uri.charAt(1) === "/") { return `${this.protocol()}:${uri}`; } return `${this.protocol()}://${location.host}${uri}`; } /** * Disconnects the socket * * See https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes for valid status codes. * * @param {Function} callback - Optional callback which is called after socket is disconnected. * @param {integer} code - A status code for disconnection (Optional). * @param {string} reason - A textual description of the reason to disconnect. (Optional) */ disconnect(callback, code, reason) { this.connectClock++; this.closeWasClean = true; clearTimeout(this.fallbackTimer); this.reconnectTimer.reset(); this.teardown(callback, code, reason); } /** * * @param {Object} params - The params to send when connecting, for example `{user_id: userToken}` * * Passing params to connect is deprecated; pass them in the Socket constructor instead: * `new Socket("/socket", {params: {user_id: userToken}})`. */ connect(params2) { if (params2) { console && console.log("passing params to connect is deprecated. Instead pass :params to the Socket constructor"); this.params = closure(params2); } if (this.conn) { return; } if (this.longPollFallbackMs && this.transport !== LongPoll) { this.connectWithFallback(LongPoll, this.longPollFallbackMs); } else { this.transportConnect(); } } /** * Logs the message. Override `this.logger` for specialized logging. noops by default * @param {string} kind * @param {string} msg * @param {Object} data */ log(kind, msg, data) { this.logger && this.logger(kind, msg, data); } /** * Returns true if a logger has been set on this socket. */ hasLogger() { return this.logger !== null; } /** * Registers callbacks for connection open events * * @example socket.onOpen(function(){ console.info("the socket was opened") }) * * @param {Function} callback */ onOpen(callback) { let ref = this.makeRef(); this.stateChangeCallbacks.open.push([ref, callback]); return ref; } /** * Registers callbacks for connection close events * @param {Function} callback */ onClose(callback) { let ref = this.makeRef(); this.stateChangeCallbacks.close.push([ref, callback]); return ref; } /** * Registers callbacks for connection error events * * @example socket.onError(function(error){ alert("An error occurred") }) * * @param {Function} callback */ onError(callback) { let ref = this.makeRef(); this.stateChangeCallbacks.error.push([ref, callback]); return ref; } /** * Registers callbacks for connection message events * @param {Function} callback */ onMessage(callback) { let ref = this.makeRef(); this.stateChangeCallbacks.message.push([ref, callback]); return ref; } /** * Pings the server and invokes the callback with the RTT in milliseconds * @param {Function} callback * * Returns true if the ping was pushed or false if unable to be pushed. */ ping(callback) { if (!this.isConnected()) { return false; } let ref = this.makeRef(); let startTime = Date.now(); this.push({ topic: "phoenix", event: "heartbeat", payload: {}, ref }); let onMsgRef = this.onMessage((msg) => { if (msg.ref === ref) { this.off([onMsgRef]); callback(Date.now() - startTime); } }); return true; } /** * @private */ transportConnect() { this.connectClock++; this.closeWasClean = false; this.conn = new this.transport(this.endPointURL()); this.conn.binaryType = this.binaryType; this.conn.timeout = this.longpollerTimeout; this.conn.onopen = () => this.onConnOpen(); this.conn.onerror = (error) => this.onConnError(error); this.conn.onmessage = (event) => this.onConnMessage(event); this.conn.onclose = (event) => this.onConnClose(event); } getSession(key) { return this.sessionStore && this.sessionStore.getItem(key); } storeSession(key, val) { this.sessionStore && this.sessionStore.setItem(key, val); } connectWithFallback(fallbackTransport, fallbackThreshold = 2500) { clearTimeout(this.fallbackTimer); let established = false; let primaryTransport = true; let openRef, errorRef; let fallback = (reason) => { this.log("transport", `falling back to ${fallbackTransport.name}...`, reason); this.off([openRef, errorRef]); primaryTransport = false; this.storeSession("phx:longpoll", "true"); this.replaceTransport(fallbackTransport); this.transportConnect(); }; if (this.getSession("phx:longpoll")) { return fallback("memorized"); } this.fallbackTimer = setTimeout(fallback, fallbackThreshold); errorRef = this.onError((reason) => { this.log("transport", "error", reason); if (primaryTransport && !established) { clearTimeout(this.fallbackTimer); fallback(reason); } }); this.onOpen(() => { established = true; if (!primaryTransport) { return console.log("transport", `established ${fallbackTransport.name} fallback`); } clearTimeout(this.fallbackTimer); this.fallbackTimer = setTimeout(fallback, fallbackThreshold); this.ping((rtt) => { this.log("transport", "connected to primary after", rtt); clearTimeout(this.fallbackTimer); }); }); this.transportConnect(); } clearHeartbeats() { clearTimeout(this.heartbeatTimer); clearTimeout(this.heartbeatTimeoutTimer); } onConnOpen() { if (this.hasLogger()) this.log("transport", `${this.transport.name} connected to ${this.endPointURL()}`); this.closeWasClean = false; this.establishedConnections++; this.flushSendBuffer(); this.reconnectTimer.reset(); this.resetHeartbeat(); this.stateChangeCallbacks.open.forEach(([, callback]) => callback()); } /** * @private */ heartbeatTimeout() { if (this.pendingHeartbeatRef) { this.pendingHeartbeatRef = null; if (this.hasLogger()) { this.log("transport", "heartbeat timeout. Attempting to re-establish connection"); } this.triggerChanError(); this.closeWasClean = false; this.teardown(() => this.reconnectTimer.scheduleTimeout(), WS_CLOSE_NORMAL, "heartbeat timeout"); } } resetHeartbeat() { if (this.conn && this.conn.skipHeartbeat) { return; } this.pendingHeartbeatRef = null; this.clearHeartbeats(); this.heartbeatTimer = setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs); } teardown(callback, code, reason) { if (!this.conn) { return callback && callback(); } this.waitForBufferDone(() => { if (this.conn) { if (code) { this.conn.close(code, reason || ""); } else { this.conn.close(); } } this.waitForSocketClosed(() => { if (this.conn) { this.conn.onopen = function() { }; this.conn.onerror = function() { }; this.conn.onmessage = function() { }; this.conn.onclose = function() { }; this.conn = null; } callback && callback(); }); }); } waitForBufferDone(callback, tries = 1) { if (tries === 5 || !this.conn || !this.conn.bufferedAmount) { callback(); return; } setTimeout(() => { this.waitForBufferDone(callback, tries + 1); }, 150 * tries); } waitForSocketClosed(callback, tries = 1) { if (tries === 5 || !this.conn || this.conn.readyState === SOCKET_STATES.closed) { callback(); return; } setTimeout(() => { this.waitForSocketClosed(callback, tries + 1); }, 150 * tries); } onConnClose(event) { let closeCode = event && event.code; if (this.hasLogger()) this.log("transport", "close", event); this.triggerChanError(); this.clearHeartbeats(); if (!this.closeWasClean && closeCode !== 1e3) { this.reconnectTimer.scheduleTimeout(); } this.stateChangeCallbacks.close.forEach(([, callback]) => callback(event)); } /** * @private */ onConnError(error) { if (this.hasLogger()) this.log("transport", error); let transportBefore = this.transport; let establishedBefore = this.establishedConnections; this.stateChangeCallbacks.error.forEach(([, callback]) => { callback(error, transportBefore, establishedBefore); }); if (transportBefore === this.transport || establishedBefore > 0) { this.triggerChanError(); } } /** * @private */ triggerChanError() { this.channels.forEach((channel) => { if (!(channel.isErrored() || channel.isLeaving() || channel.isClosed())) { channel.trigger(CHANNEL_EVENTS.error); } }); } /** * @returns {string} */ connectionState() { switch (this.conn && this.conn.readyState) { case SOCKET_STATES.connecting: return "connecting"; case SOCKET_STATES.open: return "open"; case SOCKET_STATES.closing: return "closing"; default: return "closed"; } } /** * @returns {boolean} */ isConnected() { return this.connectionState() === "open"; } /** * @private * * @param {Channel} */ remove(channel) { this.off(channel.stateChangeRefs); this.channels = this.channels.filter((c) => c.joinRef() !== channel.joinRef()); } /** * Removes `onOpen`, `onClose`, `onError,` and `onMessage` registrations. * * @param {refs} - list of refs returned by calls to * `onOpen`, `onClose`, `onError,` and `onMessage` */ off(refs) { for (let key in this.stateChangeCallbacks) { this.stateChangeCallbacks[key] = this.stateChangeCallbacks[key].filter(([ref]) => { return refs.indexOf(ref) === -1; }); } } /** * Initiates a new channel for the given topic * * @param {string} topic * @param {Object} chanParams - Parameters for the channel * @returns {Channel} */ channel(topic, chanParams = {}) { let chan = new Channel(topic, chanParams, this); this.channels.push(chan); return chan; } /** * @param {Object} data */ push(data) { if (this.hasLogger()) { let { topic, event, payload, ref, join_ref } = data; this.log("push", `${topic} ${event} (${join_ref}, ${ref})`, payload); } if (this.isConnected()) { this.encode(data, (result) => this.conn.send(result)); } else { this.sendBuffer.push(() => this.encode(data, (result) => this.conn.send(result))); } } /** * Return the next message ref, accounting for overflows * @returns {string} */ makeRef() { let newRef = this.ref + 1; if (newRef === this.ref) { this.ref = 0; } else { this.ref = newRef; } return this.ref.toString(); } sendHeartbeat() { if (this.pendingHeartbeatRef && !this.isConnected()) { return; } this.pendingHeartbeatRef = this.makeRef(); this.push({ topic: "phoenix", event: "heartbeat", payload: {}, ref: this.pendingHeartbeatRef }); this.heartbeatTimeoutTimer = setTimeout(() => this.heartbeatTimeout(), this.heartbeatIntervalMs); } flushSendBuffer() { if (this.isConnected() && this.sendBuffer.length > 0) { this.sendBuffer.forEach((callback) => callback()); this.sendBuffer = []; } } onConnMessage(rawMessage) { this.decode(rawMessage.data, (msg) => { let { topic, event, payload, ref, join_ref } = msg; if (ref && ref === this.pendingHeartbeatRef) { this.clearHeartbeats(); this.pendingHeartbeatRef = null; this.heartbeatTimer = setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs); } if (this.hasLogger()) this.log("receive", `${payload.status || ""} ${topic} ${event} ${ref && "(" + ref + ")" || ""}`, payload); for (let i = 0; i < this.channels.length; i++) { const channel = this.channels[i]; if (!channel.isMember(topic, event, payload, join_ref)) { continue; } channel.trigger(event, payload, ref, join_ref); } for (let i = 0; i < this.stateChangeCallbacks.message.length; i++) { let [, callback] = this.stateChangeCallbacks.message[i]; callback(msg); } }); } leaveOpenTopic(topic) { let dupChannel = this.channels.find((c) => c.topic === topic && (c.isJoined() || c.isJoining())); if (dupChannel) { if (this.hasLogger()) this.log("transport", `leaving duplicate topic "${topic}"`); dupChannel.leave(); } } }; // js/app.js var import_topbar = __toESM(require_topbar()); // ../deps/phoenix_live_view/priv/static/phoenix_live_view.esm.js var CONSECUTIVE_RELOADS = "consecutive-reloads"; var MAX_RELOADS = 10; var RELOAD_JITTER_MIN = 5e3; var RELOAD_JITTER_MAX = 1e4; var FAILSAFE_JITTER = 3e4; var PHX_EVENT_CLASSES = [ "phx-click-loading", "phx-change-loading", "phx-submit-loading", "phx-keydown-loading", "phx-keyup-loading", "phx-blur-loading", "phx-focus-loading", "phx-hook-loading" ]; var PHX_COMPONENT = "data-phx-component"; var PHX_LIVE_LINK = "data-phx-link"; var PHX_TRACK_STATIC = "track-static"; var PHX_LINK_STATE = "data-phx-link-state"; var PHX_REF = "data-phx-ref"; var PHX_REF_SRC = "data-phx-ref-src"; var PHX_TRACK_UPLOADS = "track-uploads"; var PHX_UPLOAD_REF = "data-phx-upload-ref"; var PHX_PREFLIGHTED_REFS = "data-phx-preflighted-refs"; var PHX_DONE_REFS = "data-phx-done-refs"; var PHX_DROP_TARGET = "drop-target"; var PHX_ACTIVE_ENTRY_REFS = "data-phx-active-refs"; var PHX_LIVE_FILE_UPDATED = "phx:live-file:updated"; var PHX_SKIP = "data-phx-skip"; var PHX_MAGIC_ID = "data-phx-id"; var PHX_PRUNE = "data-phx-prune"; var PHX_PAGE_LOADING = "page-loading"; var PHX_CONNECTED_CLASS = "phx-connected"; var PHX_LOADING_CLASS = "phx-loading"; var PHX_NO_FEEDBACK_CLASS = "phx-no-feedback"; var PHX_ERROR_CLASS = "phx-error"; var PHX_CLIENT_ERROR_CLASS = "phx-client-error"; var PHX_SERVER_ERROR_CLASS = "phx-server-error"; var PHX_PARENT_ID = "data-phx-parent-id"; var PHX_MAIN = "data-phx-main"; var PHX_ROOT_ID = "data-phx-root-id"; var PHX_VIEWPORT_TOP = "viewport-top"; var PHX_VIEWPORT_BOTTOM = "viewport-bottom"; var PHX_TRIGGER_ACTION = "trigger-action"; var PHX_FEEDBACK_FOR = "feedback-for"; var PHX_FEEDBACK_GROUP = "feedback-group"; var PHX_HAS_FOCUSED = "phx-has-focused"; var FOCUSABLE_INPUTS = ["text", "textarea", "number", "email", "password", "search", "tel", "url", "date", "time", "datetime-local", "color", "range"]; var CHECKABLE_INPUTS = ["checkbox", "radio"]; var PHX_HAS_SUBMITTED = "phx-has-submitted"; var PHX_SESSION = "data-phx-session"; var PHX_VIEW_SELECTOR = `[${PHX_SESSION}]`; var PHX_STICKY = "data-phx-sticky"; var PHX_STATIC = "data-phx-static"; var PHX_READONLY = "data-phx-readonly"; var PHX_DISABLED = "data-phx-disabled"; var PHX_DISABLE_WITH = "disable-with"; var PHX_DISABLE_WITH_RESTORE = "data-phx-disable-with-restore"; var PHX_HOOK = "hook"; var PHX_DEBOUNCE = "debounce"; var PHX_THROTTLE = "throttle"; var PHX_UPDATE = "update"; var PHX_STREAM = "stream"; var PHX_STREAM_REF = "data-phx-stream"; var PHX_KEY = "key"; var PHX_PRIVATE = "phxPrivate"; var PHX_AUTO_RECOVER = "auto-recover"; var PHX_LV_DEBUG = "phx:live-socket:debug"; var PHX_LV_PROFILE = "phx:live-socket:profiling"; var PHX_LV_LATENCY_SIM = "phx:live-socket:latency-sim"; var PHX_PROGRESS = "progress"; var PHX_MOUNTED = "mounted"; var LOADER_TIMEOUT = 1; var BEFORE_UNLOAD_LOADER_TIMEOUT = 200; var BINDING_PREFIX = "phx-"; var PUSH_TIMEOUT = 3e4; var DEBOUNCE_TRIGGER = "debounce-trigger"; var THROTTLED = "throttled"; var DEBOUNCE_PREV_KEY = "debounce-prev-key"; var DEFAULTS = { debounce: 300, throttle: 300 }; var DYNAMICS = "d"; var STATIC = "s"; var ROOT = "r"; var COMPONENTS = "c"; var EVENTS = "e"; var REPLY = "r"; var TITLE = "t"; var TEMPLATES = "p"; var STREAM = "stream"; var EntryUploader = class { constructor(entry, chunkSize, liveSocket2) { this.liveSocket = liveSocket2; this.entry = entry; this.offset = 0; this.chunkSize = chunkSize; this.chunkTimer = null; this.errored = false; this.uploadChannel = liveSocket2.channel(`lvu:${entry.ref}`, { token: entry.metadata() }); } error(reason) { if (this.errored) { return; } this.uploadChannel.leave(); this.errored = true; clearTimeout(this.chunkTimer); this.entry.error(reason); } upload() { this.uploadChannel.onError((reason) => this.error(reason)); this.uploadChannel.join().receive("ok", (_data) => this.readNextChunk()).receive("error", (reason) => this.error(reason)); } isDone() { return this.offset >= this.entry.file.size; } readNextChunk() { let reader = new window.FileReader(); let blob = this.entry.file.slice(this.offset, this.chunkSize + this.offset); reader.onload = (e) => { if (e.target.error === null) { this.offset += e.target.result.byteLength; this.pushChunk(e.target.result); } else { return logError("Read error: " + e.target.error); } }; reader.readAsArrayBuffer(blob); } pushChunk(chunk) { if (!this.uploadChannel.isJoined()) { return; } this.uploadChannel.push("chunk", chunk).receive("ok", () => { this.entry.progress(this.offset / this.entry.file.size * 100); if (!this.isDone()) { this.chunkTimer = setTimeout(() => this.readNextChunk(), this.liveSocket.getLatencySim() || 0); } }).receive("error", ({ reason }) => this.error(reason)); } }; var logError = (msg, obj) => console.error && console.error(msg, obj); var isCid = (cid) => { let type = typeof cid; return type === "number" || type === "string" && /^(0|[1-9]\d*)$/.test(cid); }; function detectDuplicateIds() { let ids = /* @__PURE__ */ new Set(); let elems = document.querySelectorAll("*[id]"); for (let i = 0, len = elems.length; i < len; i++) { if (ids.has(elems[i].id)) { console.error(`Multiple IDs detected: ${elems[i].id}. Ensure unique element ids.`); } else { ids.add(elems[i].id); } } } var debug = (view, kind, msg, obj) => { if (view.liveSocket.isDebugEnabled()) { console.log(`${view.id} ${kind}: ${msg} - `, obj); } }; var closure2 = (val) => typeof val === "function" ? val : function() { return val; }; var clone = (obj) => { return JSON.parse(JSON.stringify(obj)); }; var closestPhxBinding = (el, binding, borderEl) => { do { if (el.matches(`[${binding}]`) && !el.disabled) { return el; } el = el.parentElement || el.parentNode; } while (el !== null && el.nodeType === 1 && !(borderEl && borderEl.isSameNode(el) || el.matches(PHX_VIEW_SELECTOR))); return null; }; var isObject = (obj) => { return obj !== null && typeof obj === "object" && !(obj instanceof Array); }; var isEqualObj = (obj1, obj2) => JSON.stringify(obj1) === JSON.stringify(obj2); var isEmpty = (obj) => { for (let x in obj) { return false; } return true; }; var maybe = (el, callback) => el && callback(el); var channelUploader = function(entries, onError, resp, liveSocket2) { entries.forEach((entry) => { let entryUploader = new EntryUploader(entry, resp.config.chunk_size, liveSocket2); entryUploader.upload(); }); }; var Browser = { canPushState() { return typeof history.pushState !== "undefined"; }, dropLocal(localStorage, namespace, subkey) { return localStorage.removeItem(this.localKey(namespace, subkey)); }, updateLocal(localStorage, namespace, subkey, initial, func) { let current = this.getLocal(localStorage, namespace, subkey); let key = this.localKey(namespace, subkey); let newVal = current === null ? initial : func(current); localStorage.setItem(key, JSON.stringify(newVal)); return newVal; }, getLocal(localStorage, namespace, subkey) { return JSON.parse(localStorage.getItem(this.localKey(namespace, subkey))); }, updateCurrentState(callback) { if (!this.canPushState()) { return; } history.replaceState(callback(history.state || {}), "", window.location.href); }, pushState(kind, meta, to) { if (this.canPushState()) { if (to !== window.location.href) { if (meta.type == "redirect" && meta.scroll) { let currentState = history.state || {}; currentState.scroll = meta.scroll; history.replaceState(currentState, "", window.location.href); } delete meta.scroll; history[kind + "State"](meta, "", to || null); let hashEl = this.getHashTargetEl(window.location.hash); if (hashEl) { hashEl.scrollIntoView(); } else if (meta.type === "redirect") { window.scroll(0, 0); } } } else { this.redirect(to); } }, setCookie(name, value) { document.cookie = `${name}=${value}`; }, getCookie(name) { return document.cookie.replace(new RegExp(`(?:(?:^|.*;s*)${name}s*=s*([^;]*).*$)|^.*$`), "$1"); }, redirect(toURL, flash) { if (flash) { Browser.setCookie("__phoenix_flash__", flash + "; max-age=60000; path=/"); } window.location = toURL; }, localKey(namespace, subkey) { return `${namespace}-${subkey}`; }, getHashTargetEl(maybeHash) { let hash = maybeHash.toString().substring(1); if (hash === "") { return; } return document.getElementById(hash) || document.querySelector(`a[name="${hash}"]`); } }; var browser_default = Browser; var ARIA = { focusMain() { let target = document.querySelector("main h1, main, h1"); if (target) { let origTabIndex = target.tabIndex; target.tabIndex = -1; target.focus(); target.tabIndex = origTabIndex; } }, anyOf(instance, classes) { return classes.find((name) => instance instanceof name); }, isFocusable(el, interactiveOnly) { return el instanceof HTMLAnchorElement && el.rel !== "ignore" || el instanceof HTMLAreaElement && el.href !== void 0 || !el.disabled && this.anyOf(el, [HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement, HTMLButtonElement]) || el instanceof HTMLIFrameElement || (el.tabIndex > 0 || !interactiveOnly && el.getAttribute("tabindex") !== null && el.getAttribute("aria-hidden") !== "true"); }, attemptFocus(el, interactiveOnly) { if (this.isFocusable(el, interactiveOnly)) { try { el.focus(); } catch (e) { } } return !!document.activeElement && document.activeElement.isSameNode(el); }, focusFirstInteractive(el) { let child = el.firstElementChild; while (child) { if (this.attemptFocus(child, true) || this.focusFirstInteractive(child, true)) { return true; } child = child.nextElementSibling; } }, focusFirst(el) { let child = el.firstElementChild; while (child) { if (this.attemptFocus(child) || this.focusFirst(child)) { return true; } child = child.nextElementSibling; } }, focusLast(el) { let child = el.lastElementChild; while (child) { if (this.attemptFocus(child) || this.focusLast(child)) { return true; } child = child.previousElementSibling; } } }; var aria_default = ARIA; var focusStack = null; var default_transition_time = 200; var JS = { exec(eventType, phxEvent, view, sourceEl, defaults) { let [defaultKind, defaultArgs] = defaults || [null, { callback: defaults && defaults.callback }]; let commands = phxEvent.charAt(0) === "[" ? JSON.parse(phxEvent) : [[defaultKind, defaultArgs]]; commands.forEach(([kind, args]) => { if (kind === defaultKind && defaultArgs.data) { args.data = Object.assign(args.data || {}, defaultArgs.data); args.callback = args.callback || defaultArgs.callback; } this.filterToEls(sourceEl, args).forEach((el) => { this[`exec_${kind}`](eventType, phxEvent, view, sourceEl, el, args); }); }); }, isVisible(el) { return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length > 0); }, isInViewport(el) { const rect = el.getBoundingClientRect(); const windowHeight = window.innerHeight || document.documentElement.clientHeight; const windowWidth = window.innerWidth || document.documentElement.clientWidth; return rect.right > 0 && rect.bottom > 0 && rect.left < windowWidth && rect.top < windowHeight; }, exec_exec(eventType, phxEvent, view, sourceEl, el, { attr, to }) { let nodes = to ? dom_default.all(document, to) : [sourceEl]; nodes.forEach((node) => { let encodedJS = node.getAttribute(attr); if (!encodedJS) { throw new Error(`expected ${attr} to contain JS command on "${to}"`); } view.liveSocket.execJS(node, encodedJS, eventType); }); }, exec_dispatch(eventType, phxEvent, view, sourceEl, el, { to, event, detail, bubbles }) { detail = detail || {}; detail.dispatcher = sourceEl; dom_default.dispatchEvent(el, event, { detail, bubbles }); }, exec_push(eventType, phxEvent, view, sourceEl, el, args) { let { event, data, target, page_loading, loading, value, dispatcher, callback } = args; let pushOpts = { loading, value, target, page_loading: !!page_loading }; let targetSrc = eventType === "change" && dispatcher ? dispatcher : sourceEl; let phxTarget = target || targetSrc.getAttribute(view.binding("target")) || targetSrc; view.withinTargets(phxTarget, (targetView, targetCtx) => { if (!targetView.isConnected()) { return; } if (eventType === "change") { let { newCid, _target } = args; _target = _target || (dom_default.isFormInput(sourceEl) ? sourceEl.name : void 0); if (_target) { pushOpts._target = _target; } targetView.pushInput(sourceEl, targetCtx, newCid, event || phxEvent, pushOpts, callback); } else if (eventType === "submit") { let { submitter } = args; targetView.submitForm(sourceEl, targetCtx, event || phxEvent, submitter, pushOpts, callback); } else { targetView.pushEvent(eventType, sourceEl, targetCtx, event || phxEvent, data, pushOpts, callback); } }); }, exec_navigate(eventType, phxEvent, view, sourceEl, el, { href, replace }) { view.liveSocket.historyRedirect(href, replace ? "replace" : "push"); }, exec_patch(eventType, phxEvent, view, sourceEl, el, { href, replace }) { view.liveSocket.pushHistoryPatch(href, replace ? "replace" : "push", sourceEl); }, exec_focus(eventType, phxEvent, view, sourceEl, el) { window.requestAnimationFrame(() => aria_default.attemptFocus(el)); }, exec_focus_first(eventType, phxEvent, view, sourceEl, el) { window.requestAnimationFrame(() => aria_default.focusFirstInteractive(el) || aria_default.focusFirst(el)); }, exec_push_focus(eventType, phxEvent, view, sourceEl, el) { window.requestAnimationFrame(() => focusStack = el || sourceEl); }, exec_pop_focus(eventType, phxEvent, view, sourceEl, el) { window.requestAnimationFrame(() => { if (focusStack) { focusStack.focus(); } focusStack = null; }); }, exec_add_class(eventType, phxEvent, view, sourceEl, el, { names, transition, time }) { this.addOrRemoveClasses(el, names, [], transition, time, view); }, exec_remove_class(eventType, phxEvent, view, sourceEl, el, { names, transition, time }) { this.addOrRemoveClasses(el, [], names, transition, time, view); }, exec_toggle_class(eventType, phxEvent, view, sourceEl, el, { to, names, transition, time }) { this.toggleClasses(el, names, transition, view); }, exec_toggle_attr(eventType, phxEvent, view, sourceEl, el, { attr: [attr, val1, val2] }) { if (el.hasAttribute(attr)) { if (val2 !== void 0) { if (el.getAttribute(attr) === val1) { this.setOrRemoveAttrs(el, [[attr, val2]], []); } else { this.setOrRemoveAttrs(el, [[attr, val1]], []); } } else { this.setOrRemoveAttrs(el, [], [attr]); } } else { this.setOrRemoveAttrs(el, [[attr, val1]], []); } }, exec_transition(eventType, phxEvent, view, sourceEl, el, { time, transition }) { this.addOrRemoveClasses(el, [], [], transition, time, view); }, exec_toggle(eventType, phxEvent, view, sourceEl, el, { display, ins, outs, time }) { this.toggle(eventType, view, el, display, ins, outs, time); }, exec_show(eventType, phxEvent, view, sourceEl, el, { display, transition, time }) { this.show(eventType, view, el, display, transition, time); }, exec_hide(eventType, phxEvent, view, sourceEl, el, { display, transition, time }) { this.hide(eventType, view, el, display, transition, time); }, exec_set_attr(eventType, phxEvent, view, sourceEl, el, { attr: [attr, val] }) { this.setOrRemoveAttrs(el, [[attr, val]], []); }, exec_remove_attr(eventType, phxEvent, view, sourceEl, el, { attr }) { this.setOrRemoveAttrs(el, [], [attr]); }, show(eventType, view, el, display, transition, time) { if (!this.isVisible(el)) { this.toggle(eventType, view, el, display, transition, null, time); } }, hide(eventType, view, el, display, transition, time) { if (this.isVisible(el)) { this.toggle(eventType, view, el, display, null, transition, time); } }, toggle(eventType, view, el, display, ins, outs, time) { time = time || default_transition_time; let [inClasses, inStartClasses, inEndClasses] = ins || [[], [], []]; let [outClasses, outStartClasses, outEndClasses] = outs || [[], [], []]; if (inClasses.length > 0 || outClasses.length > 0) { if (this.isVisible(el)) { let onStart = () => { this.addOrRemoveClasses(el, outStartClasses, inClasses.concat(inStartClasses).concat(inEndClasses)); window.requestAnimationFrame(() => { this.addOrRemoveClasses(el, outClasses, []); window.requestAnimationFrame(() => this.addOrRemoveClasses(el, outEndClasses, outStartClasses)); }); }; el.dispatchEvent(new Event("phx:hide-start")); view.transition(time, onStart, () => { this.addOrRemoveClasses(el, [], outClasses.concat(outEndClasses)); dom_default.putSticky(el, "toggle", (currentEl) => currentEl.style.display = "none"); el.dispatchEvent(new Event("phx:hide-end")); }); } else { if (eventType === "remove") { return; } let onStart = () => { this.addOrRemoveClasses(el, inStartClasses, outClasses.concat(outStartClasses).concat(outEndClasses)); let stickyDisplay = display || this.defaultDisplay(el); dom_default.putSticky(el, "toggle", (currentEl) => currentEl.style.display = stickyDisplay); window.requestAnimationFrame(() => { this.addOrRemoveClasses(el, inClasses, []); window.requestAnimationFrame(() => this.addOrRemoveClasses(el, inEndClasses, inStartClasses)); }); }; el.dispatchEvent(new Event("phx:show-start")); view.transition(time, onStart, () => { this.addOrRemoveClasses(el, [], inClasses.concat(inEndClasses)); el.dispatchEvent(new Event("phx:show-end")); }); } } else { if (this.isVisible(el)) { window.requestAnimationFrame(() => { el.dispatchEvent(new Event("phx:hide-start")); dom_default.putSticky(el, "toggle", (currentEl) => currentEl.style.display = "none"); el.dispatchEvent(new Event("phx:hide-end")); }); } else { window.requestAnimationFrame(() => { el.dispatchEvent(new Event("phx:show-start")); let stickyDisplay = display || this.defaultDisplay(el); dom_default.putSticky(el, "toggle", (currentEl) => currentEl.style.display = stickyDisplay); el.dispatchEvent(new Event("phx:show-end")); }); } } }, toggleClasses(el, classes, transition, time, view) { window.requestAnimationFrame(() => { let [prevAdds, prevRemoves] = dom_default.getSticky(el, "classes", [[], []]); let newAdds = classes.filter((name) => prevAdds.indexOf(name) < 0 && !el.classList.contains(name)); let newRemoves = classes.filter((name) => prevRemoves.indexOf(name) < 0 && el.classList.contains(name)); this.addOrRemoveClasses(el, newAdds, newRemoves, transition, time, view); }); }, addOrRemoveClasses(el, adds, removes, transition, time, view) { time = time || default_transition_time; let [transitionRun, transitionStart, transitionEnd] = transition || [[], [], []]; if (transitionRun.length > 0) { let onStart = () => { this.addOrRemoveClasses(el, transitionStart, [].concat(transitionRun).concat(transitionEnd)); window.requestAnimationFrame(() => { this.addOrRemoveClasses(el, transitionRun, []); window.requestAnimationFrame(() => this.addOrRemoveClasses(el, transitionEnd, transitionStart)); }); }; let onDone = () => this.addOrRemoveClasses(el, adds.concat(transitionEnd), removes.concat(transitionRun).concat(transitionStart)); return view.transition(time, onStart, onDone); } window.requestAnimationFrame(() => { let [prevAdds, prevRemoves] = dom_default.getSticky(el, "classes", [[], []]); let keepAdds = adds.filter((name) => prevAdds.indexOf(name) < 0 && !el.classList.contains(name)); let keepRemoves = removes.filter((name) => prevRemoves.indexOf(name) < 0 && el.classList.contains(name)); let newAdds = prevAdds.filter((name) => removes.indexOf(name) < 0).concat(keepAdds); let newRemoves = prevRemoves.filter((name) => adds.indexOf(name) < 0).concat(keepRemoves); dom_default.putSticky(el, "classes", (currentEl) => { currentEl.classList.remove(...newRemoves); currentEl.classList.add(...newAdds); return [newAdds, newRemoves]; }); }); }, setOrRemoveAttrs(el, sets, removes) { let [prevSets, prevRemoves] = dom_default.getSticky(el, "attrs", [[], []]); let alteredAttrs = sets.map(([attr, _val]) => attr).concat(removes); let newSets = prevSets.filter(([attr, _val]) => !alteredAttrs.includes(attr)).concat(sets); let newRemoves = prevRemoves.filter((attr) => !alteredAttrs.includes(attr)).concat(removes); dom_default.putSticky(el, "attrs", (currentEl) => { newRemoves.forEach((attr) => currentEl.removeAttribute(attr)); newSets.forEach(([attr, val]) => currentEl.setAttribute(attr, val)); return [newSets, newRemoves]; }); }, hasAllClasses(el, classes) { return classes.every((name) => el.classList.contains(name)); }, isToggledOut(el, outClasses) { return !this.isVisible(el) || this.hasAllClasses(el, outClasses); }, filterToEls(sourceEl, { to }) { return to ? dom_default.all(document, to) : [sourceEl]; }, defaultDisplay(el) { return { tr: "table-row", td: "table-cell" }[el.tagName.toLowerCase()] || "block"; } }; var js_default = JS; var DOM = { byId(id) { return document.getElementById(id) || logError(`no id found for ${id}`); }, removeClass(el, className) { el.classList.remove(className); if (el.classList.length === 0) { el.removeAttribute("class"); } }, all(node, query, callback) { if (!node) { return []; } let array = Array.from(node.querySelectorAll(query)); return callback ? array.forEach(callback) : array; }, childNodeLength(html) { let template = document.createElement("template"); template.innerHTML = html; return template.content.childElementCount; }, isUploadInput(el) { return el.type === "file" && el.getAttribute(PHX_UPLOAD_REF) !== null; }, isAutoUpload(inputEl) { return inputEl.hasAttribute("data-phx-auto-upload"); }, findUploadInputs(node) { const formId = node.id; const inputsOutsideForm = this.all(document, `input[type="file"][${PHX_UPLOAD_REF}][form="${formId}"]`); return this.all(node, `input[type="file"][${PHX_UPLOAD_REF}]`).concat(inputsOutsideForm); }, findComponentNodeList(node, cid) { return this.filterWithinSameLiveView(this.all(node, `[${PHX_COMPONENT}="${cid}"]`), node); }, isPhxDestroyed(node) { return node.id && DOM.private(node, "destroyed") ? true : false; }, wantsNewTab(e) { let wantsNewTab = e.ctrlKey || e.shiftKey || e.metaKey || e.button && e.button === 1; let isDownload = e.target instanceof HTMLAnchorElement && e.target.hasAttribute("download"); let isTargetBlank = e.target.hasAttribute("target") && e.target.getAttribute("target").toLowerCase() === "_blank"; return wantsNewTab || isTargetBlank || isDownload; }, isUnloadableFormSubmit(e) { let isDialogSubmit = e.target && e.target.getAttribute("method") === "dialog" || e.submitter && e.submitter.getAttribute("formmethod") === "dialog"; if (isDialogSubmit) { return false; } else { return !e.defaultPrevented && !this.wantsNewTab(e); } }, isNewPageClick(e, currentLocation) { let href = e.target instanceof HTMLAnchorElement ? e.target.getAttribute("href") : null; let url; if (e.defaultPrevented || href === null || this.wantsNewTab(e)) { return false; } if (href.startsWith("mailto:") || href.startsWith("tel:")) { return false; } if (e.target.isContentEditable) { return false; } try { url = new URL(href); } catch (e2) { try { url = new URL(href, currentLocation); } catch (e3) { return true; } } if (url.host === currentLocation.host && url.protocol === currentLocation.protocol) { if (url.pathname === currentLocation.pathname && url.search === currentLocation.search) { return url.hash === "" && !url.href.endsWith("#"); } } return url.protocol.startsWith("http"); }, markPhxChildDestroyed(el) { if (this.isPhxChild(el)) { el.setAttribute(PHX_SESSION, ""); } this.putPrivate(el, "destroyed", true); }, findPhxChildrenInFragment(html, parentId) { let template = document.createElement("template"); template.innerHTML = html; return this.findPhxChildren(template.content, parentId); }, isIgnored(el, phxUpdate) { return (el.getAttribute(phxUpdate) || el.getAttribute("data-phx-update")) === "ignore"; }, isPhxUpdate(el, phxUpdate, updateTypes) { return el.getAttribute && updateTypes.indexOf(el.getAttribute(phxUpdate)) >= 0; }, findPhxSticky(el) { return this.all(el, `[${PHX_STICKY}]`); }, findPhxChildren(el, parentId) { return this.all(el, `${PHX_VIEW_SELECTOR}[${PHX_PARENT_ID}="${parentId}"]`); }, findExistingParentCIDs(node, cids) { let parentCids = /* @__PURE__ */ new Set(); let childrenCids = /* @__PURE__ */ new Set(); cids.forEach((cid) => { this.filterWithinSameLiveView(this.all(node, `[${PHX_COMPONENT}="${cid}"]`), node).forEach((parent) => { parentCids.add(cid); this.all(parent, `[${PHX_COMPONENT}]`).map((el) => parseInt(el.getAttribute(PHX_COMPONENT))).forEach((childCID) => childrenCids.add(childCID)); }); }); childrenCids.forEach((childCid) => parentCids.delete(childCid)); return parentCids; }, filterWithinSameLiveView(nodes, parent) { if (parent.querySelector(PHX_VIEW_SELECTOR)) { return nodes.filter((el) => this.withinSameLiveView(el, parent)); } else { return nodes; } }, withinSameLiveView(node, parent) { while (node = node.parentNode) { if (node.isSameNode(parent)) { return true; } if (node.getAttribute(PHX_SESSION) !== null) { return false; } } }, private(el, key) { return el[PHX_PRIVATE] && el[PHX_PRIVATE][key]; }, deletePrivate(el, key) { el[PHX_PRIVATE] && delete el[PHX_PRIVATE][key]; }, putPrivate(el, key, value) { if (!el[PHX_PRIVATE]) { el[PHX_PRIVATE] = {}; } el[PHX_PRIVATE][key] = value; }, updatePrivate(el, key, defaultVal, updateFunc) { let existing = this.private(el, key); if (existing === void 0) { this.putPrivate(el, key, updateFunc(defaultVal)); } else { this.putPrivate(el, key, updateFunc(existing)); } }, copyPrivates(target, source) { if (source[PHX_PRIVATE]) { target[PHX_PRIVATE] = source[PHX_PRIVATE]; } }, putTitle(str) { let titleEl = document.querySelector("title"); if (titleEl) { let { prefix, suffix } = titleEl.dataset; document.title = `${prefix || ""}${str}${suffix || ""}`; } else { document.title = str; } }, debounce(el, event, phxDebounce, defaultDebounce, phxThrottle, defaultThrottle, asyncFilter, callback) { let debounce = el.getAttribute(phxDebounce); let throttle = el.getAttribute(phxThrottle); if (debounce === "") { debounce = defaultDebounce; } if (throttle === "") { throttle = defaultThrottle; } let value = debounce || throttle; switch (value) { case null: return callback(); case "blur": if (this.once(el, "debounce-blur")) { el.addEventListener("blur", () => callback()); } return; default: let timeout = parseInt(value); let trigger = () => throttle ? this.deletePrivate(el, THROTTLED) : callback(); let currentCycle = this.incCycle(el, DEBOUNCE_TRIGGER, trigger); if (isNaN(timeout)) { return logError(`invalid throttle/debounce value: ${value}`); } if (throttle) { let newKeyDown = false; if (event.type === "keydown") { let prevKey = this.private(el, DEBOUNCE_PREV_KEY); this.putPrivate(el, DEBOUNCE_PREV_KEY, event.key); newKeyDown = prevKey !== event.key; } if (!newKeyDown && this.private(el, THROTTLED)) { return false; } else { callback(); const t = setTimeout(() => { if (asyncFilter()) { this.triggerCycle(el, DEBOUNCE_TRIGGER); } }, timeout); this.putPrivate(el, THROTTLED, t); } } else { setTimeout(() => { if (asyncFilter()) { this.triggerCycle(el, DEBOUNCE_TRIGGER, currentCycle); } }, timeout); } let form = el.form; if (form && this.once(form, "bind-debounce")) { form.addEventListener("submit", () => { Array.from(new FormData(form).entries(), ([name]) => { let input = form.querySelector(`[name="${name}"]`); this.incCycle(input, DEBOUNCE_TRIGGER); this.deletePrivate(input, THROTTLED); }); }); } if (this.once(el, "bind-debounce")) { el.addEventListener("blur", () => { clearTimeout(this.private(el, THROTTLED)); this.triggerCycle(el, DEBOUNCE_TRIGGER); }); } } }, triggerCycle(el, key, currentCycle) { let [cycle, trigger] = this.private(el, key); if (!currentCycle) { currentCycle = cycle; } if (currentCycle === cycle) { this.incCycle(el, key); trigger(); } }, once(el, key) { if (this.private(el, key) === true) { return false; } this.putPrivate(el, key, true); return true; }, incCycle(el, key, trigger = function() { }) { let [currentCycle] = this.private(el, key) || [0, trigger]; currentCycle++; this.putPrivate(el, key, [currentCycle, trigger]); return currentCycle; }, maybeAddPrivateHooks(el, phxViewportTop, phxViewportBottom) { if (el.hasAttribute && (el.hasAttribute(phxViewportTop) || el.hasAttribute(phxViewportBottom))) { el.setAttribute("data-phx-hook", "Phoenix.InfiniteScroll"); } }, isFeedbackContainer(el, phxFeedbackFor) { return el.hasAttribute && el.hasAttribute(phxFeedbackFor); }, maybeHideFeedback(container, feedbackContainers, phxFeedbackFor, phxFeedbackGroup) { const feedbackResults = {}; feedbackContainers.forEach((el) => { if (!container.contains(el)) return; const feedback = el.getAttribute(phxFeedbackFor); if (!feedback) { js_default.addOrRemoveClasses(el, [], [PHX_NO_FEEDBACK_CLASS]); return; } if (feedbackResults[feedback] === true) { this.hideFeedback(el); return; } feedbackResults[feedback] = this.shouldHideFeedback(container, feedback, phxFeedbackGroup); if (feedbackResults[feedback] === true) { this.hideFeedback(el); } }); }, hideFeedback(container) { js_default.addOrRemoveClasses(container, [PHX_NO_FEEDBACK_CLASS], []); }, shouldHideFeedback(container, nameOrGroup, phxFeedbackGroup) { const query = `[name="${nameOrGroup}"], [name="${nameOrGroup}[]"], [${phxFeedbackGroup}="${nameOrGroup}"]`; let focused = false; DOM.all(container, query, (input) => { if (this.private(input, PHX_HAS_FOCUSED) || this.private(input, PHX_HAS_SUBMITTED)) { focused = true; } }); return !focused; }, feedbackSelector(input, phxFeedbackFor, phxFeedbackGroup) { let query = `[${phxFeedbackFor}="${input.name}"], [${phxFeedbackFor}="${input.name.replace(/\[\]$/, "")}"]`; if (input.getAttribute(phxFeedbackGroup)) { query += `,[${phxFeedbackFor}="${input.getAttribute(phxFeedbackGroup)}"]`; } return query; }, resetForm(form, phxFeedbackFor, phxFeedbackGroup) { Array.from(form.elements).forEach((input) => { let query = this.feedbackSelector(input, phxFeedbackFor, phxFeedbackGroup); this.deletePrivate(input, PHX_HAS_FOCUSED); this.deletePrivate(input, PHX_HAS_SUBMITTED); this.all(document, query, (feedbackEl) => { js_default.addOrRemoveClasses(feedbackEl, [PHX_NO_FEEDBACK_CLASS], []); }); }); }, showError(inputEl, phxFeedbackFor, phxFeedbackGroup) { if (inputEl.name) { let query = this.feedbackSelector(inputEl, phxFeedbackFor, phxFeedbackGroup); this.all(document, query, (el) => { js_default.addOrRemoveClasses(el, [], [PHX_NO_FEEDBACK_CLASS]); }); } }, isPhxChild(node) { return node.getAttribute && node.getAttribute(PHX_PARENT_ID); }, isPhxSticky(node) { return node.getAttribute && node.getAttribute(PHX_STICKY) !== null; }, isChildOfAny(el, parents) { return !!parents.find((parent) => parent.contains(el)); }, firstPhxChild(el) { return this.isPhxChild(el) ? el : this.all(el, `[${PHX_PARENT_ID}]`)[0]; }, dispatchEvent(target, name, opts = {}) { let defaultBubble = true; let isUploadTarget = target.nodeName === "INPUT" && target.type === "file"; if (isUploadTarget && name === "click") { defaultBubble = false; } let bubbles = opts.bubbles === void 0 ? defaultBubble : !!opts.bubbles; let eventOpts = { bubbles, cancelable: true, detail: opts.detail || {} }; let event = name === "click" ? new MouseEvent("click", eventOpts) : new CustomEvent(name, eventOpts); target.dispatchEvent(event); }, cloneNode(node, html) { if (typeof html === "undefined") { return node.cloneNode(true); } else { let cloned = node.cloneNode(false); cloned.innerHTML = html; return cloned; } }, mergeAttrs(target, source, opts = {}) { let exclude = new Set(opts.exclude || []); let isIgnored = opts.isIgnored; let sourceAttrs = source.attributes; for (let i = sourceAttrs.length - 1; i >= 0; i--) { let name = sourceAttrs[i].name; if (!exclude.has(name)) { const sourceValue = source.getAttribute(name); if (target.getAttribute(name) !== sourceValue && (!isIgnored || isIgnored && name.startsWith("data-"))) { target.setAttribute(name, sourceValue); } } else { if (name === "value" && target.value === source.value) { target.setAttribute("value", source.getAttribute(name)); } } } let targetAttrs = target.attributes; for (let i = targetAttrs.length - 1; i >= 0; i--) { let name = targetAttrs[i].name; if (isIgnored) { if (name.startsWith("data-") && !source.hasAttribute(name) && ![PHX_REF, PHX_REF_SRC].includes(name)) { target.removeAttribute(name); } } else { if (!source.hasAttribute(name)) { target.removeAttribute(name); } } } }, mergeFocusedInput(target, source) { if (!(target instanceof HTMLSelectElement)) { DOM.mergeAttrs(target, source, { exclude: ["value"] }); } if (source.readOnly) { target.setAttribute("readonly", true); } else { target.removeAttribute("readonly"); } }, hasSelectionRange(el) { return el.setSelectionRange && (el.type === "text" || el.type === "textarea"); }, restoreFocus(focused, selectionStart, selectionEnd) { if (focused instanceof HTMLSelectElement) { focused.focus(); } if (!DOM.isTextualInput(focused)) { return; } let wasFocused = focused.matches(":focus"); if (focused.readOnly) { focused.blur(); } if (!wasFocused) { focused.focus(); } if (this.hasSelectionRange(focused)) { focused.setSelectionRange(selectionStart, selectionEnd); } }, isFormInput(el) { return /^(?:input|select|textarea)$/i.test(el.tagName) && el.type !== "button"; }, syncAttrsToProps(el) { if (el instanceof HTMLInputElement && CHECKABLE_INPUTS.indexOf(el.type.toLocaleLowerCase()) >= 0) { el.checked = el.getAttribute("checked") !== null; } }, isTextualInput(el) { return FOCUSABLE_INPUTS.indexOf(el.type) >= 0; }, isNowTriggerFormExternal(el, phxTriggerExternal) { return el.getAttribute && el.getAttribute(phxTriggerExternal) !== null; }, syncPendingRef(fromEl, toEl, disableWith) { let ref = fromEl.getAttribute(PHX_REF); if (ref === null) { return true; } let refSrc = fromEl.getAttribute(PHX_REF_SRC); if (DOM.isFormInput(fromEl) || fromEl.getAttribute(disableWith) !== null) { if (DOM.isUploadInput(fromEl)) { DOM.mergeAttrs(fromEl, toEl, { isIgnored: true }); } DOM.putPrivate(fromEl, PHX_REF, toEl); return false; } else { PHX_EVENT_CLASSES.forEach((className) => { fromEl.classList.contains(className) && toEl.classList.add(className); }); toEl.setAttribute(PHX_REF, ref); toEl.setAttribute(PHX_REF_SRC, refSrc); return true; } }, cleanChildNodes(container, phxUpdate) { if (DOM.isPhxUpdate(container, phxUpdate, ["append", "prepend"])) { let toRemove = []; container.childNodes.forEach((childNode) => { if (!childNode.id) { let isEmptyTextNode = childNode.nodeType === Node.TEXT_NODE && childNode.nodeValue.trim() === ""; if (!isEmptyTextNode) { logError(`only HTML element tags with an id are allowed inside containers with phx-update. removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}" `); } toRemove.push(childNode); } }); toRemove.forEach((childNode) => childNode.remove()); } }, replaceRootContainer(container, tagName, attrs) { let retainedAttrs = /* @__PURE__ */ new Set(["id", PHX_SESSION, PHX_STATIC, PHX_MAIN, PHX_ROOT_ID]); if (container.tagName.toLowerCase() === tagName.toLowerCase()) { Array.from(container.attributes).filter((attr) => !retainedAttrs.has(attr.name.toLowerCase())).forEach((attr) => container.removeAttribute(attr.name)); Object.keys(attrs).filter((name) => !retainedAttrs.has(name.toLowerCase())).forEach((attr) => container.setAttribute(attr, attrs[attr])); return container; } else { let newContainer = document.createElement(tagName); Object.keys(attrs).forEach((attr) => newContainer.setAttribute(attr, attrs[attr])); retainedAttrs.forEach((attr) => newContainer.setAttribute(attr, container.getAttribute(attr))); newContainer.innerHTML = container.innerHTML; container.replaceWith(newContainer); return newContainer; } }, getSticky(el, name, defaultVal) { let op = (DOM.private(el, "sticky") || []).find(([existingName]) => name === existingName); if (op) { let [_name, _op, stashedResult] = op; return stashedResult; } else { return typeof defaultVal === "function" ? defaultVal() : defaultVal; } }, deleteSticky(el, name) { this.updatePrivate(el, "sticky", [], (ops) => { return ops.filter(([existingName, _]) => existingName !== name); }); }, putSticky(el, name, op) { let stashedResult = op(el); this.updatePrivate(el, "sticky", [], (ops) => { let existingIndex = ops.findIndex(([existingName]) => name === existingName); if (existingIndex >= 0) { ops[existingIndex] = [name, op, stashedResult]; } else { ops.push([name, op, stashedResult]); } return ops; }); }, applyStickyOperations(el) { let ops = DOM.private(el, "sticky"); if (!ops) { return; } ops.forEach(([name, op, _stashed]) => this.putSticky(el, name, op)); } }; var dom_default = DOM; var UploadEntry = class { static isActive(fileEl, file) { let isNew = file._phxRef === void 0; let activeRefs = fileEl.getAttribute(PHX_ACTIVE_ENTRY_REFS).split(","); let isActive = activeRefs.indexOf(LiveUploader.genFileRef(file)) >= 0; return file.size > 0 && (isNew || isActive); } static isPreflighted(fileEl, file) { let preflightedRefs = fileEl.getAttribute(PHX_PREFLIGHTED_REFS).split(","); let isPreflighted = preflightedRefs.indexOf(LiveUploader.genFileRef(file)) >= 0; return isPreflighted && this.isActive(fileEl, file); } static isPreflightInProgress(file) { return file._preflightInProgress === true; } static markPreflightInProgress(file) { file._preflightInProgress = true; } constructor(fileEl, file, view, autoUpload) { this.ref = LiveUploader.genFileRef(file); this.fileEl = fileEl; this.file = file; this.view = view; this.meta = null; this._isCancelled = false; this._isDone = false; this._progress = 0; this._lastProgressSent = -1; this._onDone = function() { }; this._onElUpdated = this.onElUpdated.bind(this); this.fileEl.addEventListener(PHX_LIVE_FILE_UPDATED, this._onElUpdated); this.autoUpload = autoUpload; } metadata() { return this.meta; } progress(progress) { this._progress = Math.floor(progress); if (this._progress > this._lastProgressSent) { if (this._progress >= 100) { this._progress = 100; this._lastProgressSent = 100; this._isDone = true; this.view.pushFileProgress(this.fileEl, this.ref, 100, () => { LiveUploader.untrackFile(this.fileEl, this.file); this._onDone(); }); } else { this._lastProgressSent = this._progress; this.view.pushFileProgress(this.fileEl, this.ref, this._progress); } } } isCancelled() { return this._isCancelled; } cancel() { this.file._preflightInProgress = false; this._isCancelled = true; this._isDone = true; this._onDone(); } isDone() { return this._isDone; } error(reason = "failed") { this.fileEl.removeEventListener(PHX_LIVE_FILE_UPDATED, this._onElUpdated); this.view.pushFileProgress(this.fileEl, this.ref, { error: reason }); if (!this.isAutoUpload()) { LiveUploader.clearFiles(this.fileEl); } } isAutoUpload() { return this.autoUpload; } onDone(callback) { this._onDone = () => { this.fileEl.removeEventListener(PHX_LIVE_FILE_UPDATED, this._onElUpdated); callback(); }; } onElUpdated() { let activeRefs = this.fileEl.getAttribute(PHX_ACTIVE_ENTRY_REFS).split(","); if (activeRefs.indexOf(this.ref) === -1) { LiveUploader.untrackFile(this.fileEl, this.file); this.cancel(); } } toPreflightPayload() { return { last_modified: this.file.lastModified, name: this.file.name, relative_path: this.file.webkitRelativePath, size: this.file.size, type: this.file.type, ref: this.ref, meta: typeof this.file.meta === "function" ? this.file.meta() : void 0 }; } uploader(uploaders) { if (this.meta.uploader) { let callback = uploaders[this.meta.uploader] || logError(`no uploader configured for ${this.meta.uploader}`); return { name: this.meta.uploader, callback }; } else { return { name: "channel", callback: channelUploader }; } } zipPostFlight(resp) { this.meta = resp.entries[this.ref]; if (!this.meta) { logError(`no preflight upload response returned with ref ${this.ref}`, { input: this.fileEl, response: resp }); } } }; var liveUploaderFileRef = 0; var LiveUploader = class { static genFileRef(file) { let ref = file._phxRef; if (ref !== void 0) { return ref; } else { file._phxRef = (liveUploaderFileRef++).toString(); return file._phxRef; } } static getEntryDataURL(inputEl, ref, callback) { let file = this.activeFiles(inputEl).find((file2) => this.genFileRef(file2) === ref); callback(URL.createObjectURL(file)); } static hasUploadsInProgress(formEl) { let active = 0; dom_default.findUploadInputs(formEl).forEach((input) => { if (input.getAttribute(PHX_PREFLIGHTED_REFS) !== input.getAttribute(PHX_DONE_REFS)) { active++; } }); return active > 0; } static serializeUploads(inputEl) { let files = this.activeFiles(inputEl); let fileData = {}; files.forEach((file) => { let entry = { path: inputEl.name }; let uploadRef = inputEl.getAttribute(PHX_UPLOAD_REF); fileData[uploadRef] = fileData[uploadRef] || []; entry.ref = this.genFileRef(file); entry.last_modified = file.lastModified; entry.name = file.name || entry.ref; entry.relative_path = file.webkitRelativePath; entry.type = file.type; entry.size = file.size; if (typeof file.meta === "function") { entry.meta = file.meta(); } fileData[uploadRef].push(entry); }); return fileData; } static clearFiles(inputEl) { inputEl.value = null; inputEl.removeAttribute(PHX_UPLOAD_REF); dom_default.putPrivate(inputEl, "files", []); } static untrackFile(inputEl, file) { dom_default.putPrivate(inputEl, "files", dom_default.private(inputEl, "files").filter((f) => !Object.is(f, file))); } static trackFiles(inputEl, files, dataTransfer) { if (inputEl.getAttribute("multiple") !== null) { let newFiles = files.filter((file) => !this.activeFiles(inputEl).find((f) => Object.is(f, file))); dom_default.updatePrivate(inputEl, "files", [], (existing) => existing.concat(newFiles)); inputEl.value = null; } else { if (dataTransfer && dataTransfer.files.length > 0) { inputEl.files = dataTransfer.files; } dom_default.putPrivate(inputEl, "files", files); } } static activeFileInputs(formEl) { let fileInputs = dom_default.findUploadInputs(formEl); return Array.from(fileInputs).filter((el) => el.files && this.activeFiles(el).length > 0); } static activeFiles(input) { return (dom_default.private(input, "files") || []).filter((f) => UploadEntry.isActive(input, f)); } static inputsAwaitingPreflight(formEl) { let fileInputs = dom_default.findUploadInputs(formEl); return Array.from(fileInputs).filter((input) => this.filesAwaitingPreflight(input).length > 0); } static filesAwaitingPreflight(input) { return this.activeFiles(input).filter((f) => !UploadEntry.isPreflighted(input, f) && !UploadEntry.isPreflightInProgress(f)); } static markPreflightInProgress(entries) { entries.forEach((entry) => UploadEntry.markPreflightInProgress(entry.file)); } constructor(inputEl, view, onComplete) { this.autoUpload = dom_default.isAutoUpload(inputEl); this.view = view; this.onComplete = onComplete; this._entries = Array.from(LiveUploader.filesAwaitingPreflight(inputEl) || []).map((file) => new UploadEntry(inputEl, file, view, this.autoUpload)); LiveUploader.markPreflightInProgress(this._entries); this.numEntriesInProgress = this._entries.length; } isAutoUpload() { return this.autoUpload; } entries() { return this._entries; } initAdapterUpload(resp, onError, liveSocket2) { this._entries = this._entries.map((entry) => { if (entry.isCancelled()) { this.numEntriesInProgress--; if (this.numEntriesInProgress === 0) { this.onComplete(); } } else { entry.zipPostFlight(resp); entry.onDone(() => { this.numEntriesInProgress--; if (this.numEntriesInProgress === 0) { this.onComplete(); } }); } return entry; }); let groupedEntries = this._entries.reduce((acc, entry) => { if (!entry.meta) { return acc; } let { name, callback } = entry.uploader(liveSocket2.uploaders); acc[name] = acc[name] || { callback, entries: [] }; acc[name].entries.push(entry); return acc; }, {}); for (let name in groupedEntries) { let { callback, entries } = groupedEntries[name]; callback(entries, onError, resp, liveSocket2); } } }; var Hooks = { LiveFileUpload: { activeRefs() { return this.el.getAttribute(PHX_ACTIVE_ENTRY_REFS); }, preflightedRefs() { return this.el.getAttribute(PHX_PREFLIGHTED_REFS); }, mounted() { this.preflightedWas = this.preflightedRefs(); }, updated() { let newPreflights = this.preflightedRefs(); if (this.preflightedWas !== newPreflights) { this.preflightedWas = newPreflights; if (newPreflights === "") { this.__view.cancelSubmit(this.el.form); } } if (this.activeRefs() === "") { this.el.value = null; } this.el.dispatchEvent(new CustomEvent(PHX_LIVE_FILE_UPDATED)); } }, LiveImgPreview: { mounted() { this.ref = this.el.getAttribute("data-phx-entry-ref"); this.inputEl = document.getElementById(this.el.getAttribute(PHX_UPLOAD_REF)); LiveUploader.getEntryDataURL(this.inputEl, this.ref, (url) => { this.url = url; this.el.src = url; }); }, destroyed() { URL.revokeObjectURL(this.url); } }, FocusWrap: { mounted() { this.focusStart = this.el.firstElementChild; this.focusEnd = this.el.lastElementChild; this.focusStart.addEventListener("focus", () => aria_default.focusLast(this.el)); this.focusEnd.addEventListener("focus", () => aria_default.focusFirst(this.el)); this.el.addEventListener("phx:show-end", () => this.el.focus()); if (window.getComputedStyle(this.el).display !== "none") { aria_default.focusFirst(this.el); } } } }; var findScrollContainer = (el) => { if (["scroll", "auto"].indexOf(getComputedStyle(el).overflowY) >= 0) return el; if (document.documentElement === el) return null; return findScrollContainer(el.parentElement); }; var scrollTop = (scrollContainer) => { if (scrollContainer) { return scrollContainer.scrollTop; } else { return document.documentElement.scrollTop || document.body.scrollTop; } }; var bottom = (scrollContainer) => { if (scrollContainer) { return scrollContainer.getBoundingClientRect().bottom; } else { return window.innerHeight || document.documentElement.clientHeight; } }; var top = (scrollContainer) => { if (scrollContainer) { return scrollContainer.getBoundingClientRect().top; } else { return 0; } }; var isAtViewportTop = (el, scrollContainer) => { let rect = el.getBoundingClientRect(); return rect.top >= top(scrollContainer) && rect.left >= 0 && rect.top <= bottom(scrollContainer); }; var isAtViewportBottom = (el, scrollContainer) => { let rect = el.getBoundingClientRect(); return rect.right >= top(scrollContainer) && rect.left >= 0 && rect.bottom <= bottom(scrollContainer); }; var isWithinViewport = (el, scrollContainer) => { let rect = el.getBoundingClientRect(); return rect.top >= top(scrollContainer) && rect.left >= 0 && rect.top <= bottom(scrollContainer); }; Hooks.InfiniteScroll = { mounted() { this.scrollContainer = findScrollContainer(this.el); let scrollBefore = scrollTop(this.scrollContainer); let topOverran = false; let throttleInterval = 500; let pendingOp = null; let onTopOverrun = this.throttle(throttleInterval, (topEvent, firstChild) => { pendingOp = () => true; this.liveSocket.execJSHookPush(this.el, topEvent, { id: firstChild.id, _overran: true }, () => { pendingOp = null; }); }); let onFirstChildAtTop = this.throttle(throttleInterval, (topEvent, firstChild) => { pendingOp = () => firstChild.scrollIntoView({ block: "start" }); this.liveSocket.execJSHookPush(this.el, topEvent, { id: firstChild.id }, () => { pendingOp = null; window.requestAnimationFrame(() => { if (!isWithinViewport(firstChild, this.scrollContainer)) { firstChild.scrollIntoView({ block: "start" }); } }); }); }); let onLastChildAtBottom = this.throttle(throttleInterval, (bottomEvent, lastChild) => { pendingOp = () => lastChild.scrollIntoView({ block: "end" }); this.liveSocket.execJSHookPush(this.el, bottomEvent, { id: lastChild.id }, () => { pendingOp = null; window.requestAnimationFrame(() => { if (!isWithinViewport(lastChild, this.scrollContainer)) { lastChild.scrollIntoView({ block: "end" }); } }); }); }); this.onScroll = (_e) => { let scrollNow = scrollTop(this.scrollContainer); if (pendingOp) { scrollBefore = scrollNow; return pendingOp(); } let rect = this.el.getBoundingClientRect(); let topEvent = this.el.getAttribute(this.liveSocket.binding("viewport-top")); let bottomEvent = this.el.getAttribute(this.liveSocket.binding("viewport-bottom")); let lastChild = this.el.lastElementChild; let firstChild = this.el.firstElementChild; let isScrollingUp = scrollNow < scrollBefore; let isScrollingDown = scrollNow > scrollBefore; if (isScrollingUp && topEvent && !topOverran && rect.top >= 0) { topOverran = true; onTopOverrun(topEvent, firstChild); } else if (isScrollingDown && topOverran && rect.top <= 0) { topOverran = false; } if (topEvent && isScrollingUp && isAtViewportTop(firstChild, this.scrollContainer)) { onFirstChildAtTop(topEvent, firstChild); } else if (bottomEvent && isScrollingDown && isAtViewportBottom(lastChild, this.scrollContainer)) { onLastChildAtBottom(bottomEvent, lastChild); } scrollBefore = scrollNow; }; if (this.scrollContainer) { this.scrollContainer.addEventListener("scroll", this.onScroll); } else { window.addEventListener("scroll", this.onScroll); } }, destroyed() { if (this.scrollContainer) { this.scrollContainer.removeEventListener("scroll", this.onScroll); } else { window.removeEventListener("scroll", this.onScroll); } }, throttle(interval, callback) { let lastCallAt = 0; let timer; return (...args) => { let now = Date.now(); let remainingTime = interval - (now - lastCallAt); if (remainingTime <= 0 || remainingTime > interval) { if (timer) { clearTimeout(timer); timer = null; } lastCallAt = now; callback(...args); } else if (!timer) { timer = setTimeout(() => { lastCallAt = Date.now(); timer = null; callback(...args); }, remainingTime); } }; } }; var hooks_default = Hooks; var DOMPostMorphRestorer = class { constructor(containerBefore, containerAfter, updateType) { let idsBefore = /* @__PURE__ */ new Set(); let idsAfter = new Set([...containerAfter.children].map((child) => child.id)); let elementsToModify = []; Array.from(containerBefore.children).forEach((child) => { if (child.id) { idsBefore.add(child.id); if (idsAfter.has(child.id)) { let previousElementId = child.previousElementSibling && child.previousElementSibling.id; elementsToModify.push({ elementId: child.id, previousElementId }); } } }); this.containerId = containerAfter.id; this.updateType = updateType; this.elementsToModify = elementsToModify; this.elementIdsToAdd = [...idsAfter].filter((id) => !idsBefore.has(id)); } perform() { let container = dom_default.byId(this.containerId); this.elementsToModify.forEach((elementToModify) => { if (elementToModify.previousElementId) { maybe(document.getElementById(elementToModify.previousElementId), (previousElem) => { maybe(document.getElementById(elementToModify.elementId), (elem) => { let isInRightPlace = elem.previousElementSibling && elem.previousElementSibling.id == previousElem.id; if (!isInRightPlace) { previousElem.insertAdjacentElement("afterend", elem); } }); }); } else { maybe(document.getElementById(elementToModify.elementId), (elem) => { let isInRightPlace = elem.previousElementSibling == null; if (!isInRightPlace) { container.insertAdjacentElement("afterbegin", elem); } }); } }); if (this.updateType == "prepend") { this.elementIdsToAdd.reverse().forEach((elemId) => { maybe(document.getElementById(elemId), (elem) => container.insertAdjacentElement("afterbegin", elem)); }); } } }; var DOCUMENT_FRAGMENT_NODE = 11; function morphAttrs(fromNode, toNode) { var toNodeAttrs = toNode.attributes; var attr; var attrName; var attrNamespaceURI; var attrValue; var fromValue; if (toNode.nodeType === DOCUMENT_FRAGMENT_NODE || fromNode.nodeType === DOCUMENT_FRAGMENT_NODE) { return; } for (var i = toNodeAttrs.length - 1; i >= 0; i--) { attr = toNodeAttrs[i]; attrName = attr.name; attrNamespaceURI = attr.namespaceURI; attrValue = attr.value; if (attrNamespaceURI) { attrName = attr.localName || attrName; fromValue = fromNode.getAttributeNS(attrNamespaceURI, attrName); if (fromValue !== attrValue) { if (attr.prefix === "xmlns") { attrName = attr.name; } fromNode.setAttributeNS(attrNamespaceURI, attrName, attrValue); } } else { fromValue = fromNode.getAttribute(attrName); if (fromValue !== attrValue) { fromNode.setAttribute(attrName, attrValue); } } } var fromNodeAttrs = fromNode.attributes; for (var d = fromNodeAttrs.length - 1; d >= 0; d--) { attr = fromNodeAttrs[d]; attrName = attr.name; attrNamespaceURI = attr.namespaceURI; if (attrNamespaceURI) { attrName = attr.localName || attrName; if (!toNode.hasAttributeNS(attrNamespaceURI, attrName)) { fromNode.removeAttributeNS(attrNamespaceURI, attrName); } } else { if (!toNode.hasAttribute(attrName)) { fromNode.removeAttribute(attrName); } } } } var range; var NS_XHTML = "http://www.w3.org/1999/xhtml"; var doc = typeof document === "undefined" ? void 0 : document; var HAS_TEMPLATE_SUPPORT = !!doc && "content" in doc.createElement("template"); var HAS_RANGE_SUPPORT = !!doc && doc.createRange && "createContextualFragment" in doc.createRange(); function createFragmentFromTemplate(str) { var template = doc.createElement("template"); template.innerHTML = str; return template.content.childNodes[0]; } function createFragmentFromRange(str) { if (!range) { range = doc.createRange(); range.selectNode(doc.body); } var fragment = range.createContextualFragment(str); return fragment.childNodes[0]; } function createFragmentFromWrap(str) { var fragment = doc.createElement("body"); fragment.innerHTML = str; return fragment.childNodes[0]; } function toElement(str) { str = str.trim(); if (HAS_TEMPLATE_SUPPORT) { return createFragmentFromTemplate(str); } else if (HAS_RANGE_SUPPORT) { return createFragmentFromRange(str); } return createFragmentFromWrap(str); } function compareNodeNames(fromEl, toEl) { var fromNodeName = fromEl.nodeName; var toNodeName = toEl.nodeName; var fromCodeStart, toCodeStart; if (fromNodeName === toNodeName) { return true; } fromCodeStart = fromNodeName.charCodeAt(0); toCodeStart = toNodeName.charCodeAt(0); if (fromCodeStart <= 90 && toCodeStart >= 97) { return fromNodeName === toNodeName.toUpperCase(); } else if (toCodeStart <= 90 && fromCodeStart >= 97) { return toNodeName === fromNodeName.toUpperCase(); } else { return false; } } function createElementNS(name, namespaceURI) { return !namespaceURI || namespaceURI === NS_XHTML ? doc.createElement(name) : doc.createElementNS(namespaceURI, name); } function moveChildren(fromEl, toEl) { var curChild = fromEl.firstChild; while (curChild) { var nextChild = curChild.nextSibling; toEl.appendChild(curChild); curChild = nextChild; } return toEl; } function syncBooleanAttrProp(fromEl, toEl, name) { if (fromEl[name] !== toEl[name]) { fromEl[name] = toEl[name]; if (fromEl[name]) { fromEl.setAttribute(name, ""); } else { fromEl.removeAttribute(name); } } } var specialElHandlers = { OPTION: function(fromEl, toEl) { var parentNode = fromEl.parentNode; if (parentNode) { var parentName = parentNode.nodeName.toUpperCase(); if (parentName === "OPTGROUP") { parentNode = parentNode.parentNode; parentName = parentNode && parentNode.nodeName.toUpperCase(); } if (parentName === "SELECT" && !parentNode.hasAttribute("multiple")) { if (fromEl.hasAttribute("selected") && !toEl.selected) { fromEl.setAttribute("selected", "selected"); fromEl.removeAttribute("selected"); } parentNode.selectedIndex = -1; } } syncBooleanAttrProp(fromEl, toEl, "selected"); }, INPUT: function(fromEl, toEl) { syncBooleanAttrProp(fromEl, toEl, "checked"); syncBooleanAttrProp(fromEl, toEl, "disabled"); if (fromEl.value !== toEl.value) { fromEl.value = toEl.value; } if (!toEl.hasAttribute("value")) { fromEl.removeAttribute("value"); } }, TEXTAREA: function(fromEl, toEl) { var newValue = toEl.value; if (fromEl.value !== newValue) { fromEl.value = newValue; } var firstChild = fromEl.firstChild; if (firstChild) { var oldValue = firstChild.nodeValue; if (oldValue == newValue || !newValue && oldValue == fromEl.placeholder) { return; } firstChild.nodeValue = newValue; } }, SELECT: function(fromEl, toEl) { if (!toEl.hasAttribute("multiple")) { var selectedIndex = -1; var i = 0; var curChild = fromEl.firstChild; var optgroup; var nodeName; while (curChild) { nodeName = curChild.nodeName && curChild.nodeName.toUpperCase(); if (nodeName === "OPTGROUP") { optgroup = curChild; curChild = optgroup.firstChild; } else { if (nodeName === "OPTION") { if (curChild.hasAttribute("selected")) { selectedIndex = i; break; } i++; } curChild = curChild.nextSibling; if (!curChild && optgroup) { curChild = optgroup.nextSibling; optgroup = null; } } } fromEl.selectedIndex = selectedIndex; } } }; var ELEMENT_NODE = 1; var DOCUMENT_FRAGMENT_NODE$1 = 11; var TEXT_NODE = 3; var COMMENT_NODE = 8; function noop() { } function defaultGetNodeKey(node) { if (node) { return node.getAttribute && node.getAttribute("id") || node.id; } } function morphdomFactory(morphAttrs2) { return function morphdom2(fromNode, toNode, options) { if (!options) { options = {}; } if (typeof toNode === "string") { if (fromNode.nodeName === "#document" || fromNode.nodeName === "HTML" || fromNode.nodeName === "BODY") { var toNodeHtml = toNode; toNode = doc.createElement("html"); toNode.innerHTML = toNodeHtml; } else { toNode = toElement(toNode); } } else if (toNode.nodeType === DOCUMENT_FRAGMENT_NODE$1) { toNode = toNode.firstElementChild; } var getNodeKey = options.getNodeKey || defaultGetNodeKey; var onBeforeNodeAdded = options.onBeforeNodeAdded || noop; var onNodeAdded = options.onNodeAdded || noop; var onBeforeElUpdated = options.onBeforeElUpdated || noop; var onElUpdated = options.onElUpdated || noop; var onBeforeNodeDiscarded = options.onBeforeNodeDiscarded || noop; var onNodeDiscarded = options.onNodeDiscarded || noop; var onBeforeElChildrenUpdated = options.onBeforeElChildrenUpdated || noop; var skipFromChildren = options.skipFromChildren || noop; var addChild = options.addChild || function(parent, child) { return parent.appendChild(child); }; var childrenOnly = options.childrenOnly === true; var fromNodesLookup = /* @__PURE__ */ Object.create(null); var keyedRemovalList = []; function addKeyedRemoval(key) { keyedRemovalList.push(key); } function walkDiscardedChildNodes(node, skipKeyedNodes) { if (node.nodeType === ELEMENT_NODE) { var curChild = node.firstChild; while (curChild) { var key = void 0; if (skipKeyedNodes && (key = getNodeKey(curChild))) { addKeyedRemoval(key); } else { onNodeDiscarded(curChild); if (curChild.firstChild) { walkDiscardedChildNodes(curChild, skipKeyedNodes); } } curChild = curChild.nextSibling; } } } function removeNode(node, parentNode, skipKeyedNodes) { if (onBeforeNodeDiscarded(node) === false) { return; } if (parentNode) { parentNode.removeChild(node); } onNodeDiscarded(node); walkDiscardedChildNodes(node, skipKeyedNodes); } function indexTree(node) { if (node.nodeType === ELEMENT_NODE || node.nodeType === DOCUMENT_FRAGMENT_NODE$1) { var curChild = node.firstChild; while (curChild) { var key = getNodeKey(curChild); if (key) { fromNodesLookup[key] = curChild; } indexTree(curChild); curChild = curChild.nextSibling; } } } indexTree(fromNode); function handleNodeAdded(el) { onNodeAdded(el); var curChild = el.firstChild; while (curChild) { var nextSibling = curChild.nextSibling; var key = getNodeKey(curChild); if (key) { var unmatchedFromEl = fromNodesLookup[key]; if (unmatchedFromEl && compareNodeNames(curChild, unmatchedFromEl)) { curChild.parentNode.replaceChild(unmatchedFromEl, curChild); morphEl(unmatchedFromEl, curChild); } else { handleNodeAdded(curChild); } } else { handleNodeAdded(curChild); } curChild = nextSibling; } } function cleanupFromEl(fromEl, curFromNodeChild, curFromNodeKey) { while (curFromNodeChild) { var fromNextSibling = curFromNodeChild.nextSibling; if (curFromNodeKey = getNodeKey(curFromNodeChild)) { addKeyedRemoval(curFromNodeKey); } else { removeNode(curFromNodeChild, fromEl, true); } curFromNodeChild = fromNextSibling; } } function morphEl(fromEl, toEl, childrenOnly2) { var toElKey = getNodeKey(toEl); if (toElKey) { delete fromNodesLookup[toElKey]; } if (!childrenOnly2) { if (onBeforeElUpdated(fromEl, toEl) === false) { return; } morphAttrs2(fromEl, toEl); onElUpdated(fromEl); if (onBeforeElChildrenUpdated(fromEl, toEl) === false) { return; } } if (fromEl.nodeName !== "TEXTAREA") { morphChildren(fromEl, toEl); } else { specialElHandlers.TEXTAREA(fromEl, toEl); } } function morphChildren(fromEl, toEl) { var skipFrom = skipFromChildren(fromEl, toEl); var curToNodeChild = toEl.firstChild; var curFromNodeChild = fromEl.firstChild; var curToNodeKey; var curFromNodeKey; var fromNextSibling; var toNextSibling; var matchingFromEl; outer: while (curToNodeChild) { toNextSibling = curToNodeChild.nextSibling; curToNodeKey = getNodeKey(curToNodeChild); while (!skipFrom && curFromNodeChild) { fromNextSibling = curFromNodeChild.nextSibling; if (curToNodeChild.isSameNode && curToNodeChild.isSameNode(curFromNodeChild)) { curToNodeChild = toNextSibling; curFromNodeChild = fromNextSibling; continue outer; } curFromNodeKey = getNodeKey(curFromNodeChild); var curFromNodeType = curFromNodeChild.nodeType; var isCompatible = void 0; if (curFromNodeType === curToNodeChild.nodeType) { if (curFromNodeType === ELEMENT_NODE) { if (curToNodeKey) { if (curToNodeKey !== curFromNodeKey) { if (matchingFromEl = fromNodesLookup[curToNodeKey]) { if (fromNextSibling === matchingFromEl) { isCompatible = false; } else { fromEl.insertBefore(matchingFromEl, curFromNodeChild); if (curFromNodeKey) { addKeyedRemoval(curFromNodeKey); } else { removeNode(curFromNodeChild, fromEl, true); } curFromNodeChild = matchingFromEl; curFromNodeKey = getNodeKey(curFromNodeChild); } } else { isCompatible = false; } } } else if (curFromNodeKey) { isCompatible = false; } isCompatible = isCompatible !== false && compareNodeNames(curFromNodeChild, curToNodeChild); if (isCompatible) { morphEl(curFromNodeChild, curToNodeChild); } } else if (curFromNodeType === TEXT_NODE || curFromNodeType == COMMENT_NODE) { isCompatible = true; if (curFromNodeChild.nodeValue !== curToNodeChild.nodeValue) { curFromNodeChild.nodeValue = curToNodeChild.nodeValue; } } } if (isCompatible) { curToNodeChild = toNextSibling; curFromNodeChild = fromNextSibling; continue outer; } if (curFromNodeKey) { addKeyedRemoval(curFromNodeKey); } else { removeNode(curFromNodeChild, fromEl, true); } curFromNodeChild = fromNextSibling; } if (curToNodeKey && (matchingFromEl = fromNodesLookup[curToNodeKey]) && compareNodeNames(matchingFromEl, curToNodeChild)) { if (!skipFrom) { addChild(fromEl, matchingFromEl); } morphEl(matchingFromEl, curToNodeChild); } else { var onBeforeNodeAddedResult = onBeforeNodeAdded(curToNodeChild); if (onBeforeNodeAddedResult !== false) { if (onBeforeNodeAddedResult) { curToNodeChild = onBeforeNodeAddedResult; } if (curToNodeChild.actualize) { curToNodeChild = curToNodeChild.actualize(fromEl.ownerDocument || doc); } addChild(fromEl, curToNodeChild); handleNodeAdded(curToNodeChild); } } curToNodeChild = toNextSibling; curFromNodeChild = fromNextSibling; } cleanupFromEl(fromEl, curFromNodeChild, curFromNodeKey); var specialElHandler = specialElHandlers[fromEl.nodeName]; if (specialElHandler) { specialElHandler(fromEl, toEl); } } var morphedNode = fromNode; var morphedNodeType = morphedNode.nodeType; var toNodeType = toNode.nodeType; if (!childrenOnly) { if (morphedNodeType === ELEMENT_NODE) { if (toNodeType === ELEMENT_NODE) { if (!compareNodeNames(fromNode, toNode)) { onNodeDiscarded(fromNode); morphedNode = moveChildren(fromNode, createElementNS(toNode.nodeName, toNode.namespaceURI)); } } else { morphedNode = toNode; } } else if (morphedNodeType === TEXT_NODE || morphedNodeType === COMMENT_NODE) { if (toNodeType === morphedNodeType) { if (morphedNode.nodeValue !== toNode.nodeValue) { morphedNode.nodeValue = toNode.nodeValue; } return morphedNode; } else { morphedNode = toNode; } } } if (morphedNode === toNode) { onNodeDiscarded(fromNode); } else { if (toNode.isSameNode && toNode.isSameNode(morphedNode)) { return; } morphEl(morphedNode, toNode, childrenOnly); if (keyedRemovalList) { for (var i = 0, len = keyedRemovalList.length; i < len; i++) { var elToRemove = fromNodesLookup[keyedRemovalList[i]]; if (elToRemove) { removeNode(elToRemove, elToRemove.parentNode, false); } } } } if (!childrenOnly && morphedNode !== fromNode && fromNode.parentNode) { if (morphedNode.actualize) { morphedNode = morphedNode.actualize(fromNode.ownerDocument || doc); } fromNode.parentNode.replaceChild(morphedNode, fromNode); } return morphedNode; }; } var morphdom = morphdomFactory(morphAttrs); var morphdom_esm_default = morphdom; var DOMPatch = class { static patchEl(fromEl, toEl, activeElement) { morphdom_esm_default(fromEl, toEl, { childrenOnly: false, onBeforeElUpdated: (fromEl2, toEl2) => { if (activeElement && activeElement.isSameNode(fromEl2) && dom_default.isFormInput(fromEl2)) { dom_default.mergeFocusedInput(fromEl2, toEl2); return false; } } }); } constructor(view, container, id, html, streams, targetCID) { this.view = view; this.liveSocket = view.liveSocket; this.container = container; this.id = id; this.rootID = view.root.id; this.html = html; this.streams = streams; this.streamInserts = {}; this.streamComponentRestore = {}; this.targetCID = targetCID; this.cidPatch = isCid(this.targetCID); this.pendingRemoves = []; this.phxRemove = this.liveSocket.binding("remove"); this.callbacks = { beforeadded: [], beforeupdated: [], beforephxChildAdded: [], afteradded: [], afterupdated: [], afterdiscarded: [], afterphxChildAdded: [], aftertransitionsDiscarded: [] }; } before(kind, callback) { this.callbacks[`before${kind}`].push(callback); } after(kind, callback) { this.callbacks[`after${kind}`].push(callback); } trackBefore(kind, ...args) { this.callbacks[`before${kind}`].forEach((callback) => callback(...args)); } trackAfter(kind, ...args) { this.callbacks[`after${kind}`].forEach((callback) => callback(...args)); } markPrunableContentForRemoval() { let phxUpdate = this.liveSocket.binding(PHX_UPDATE); dom_default.all(this.container, `[${phxUpdate}=append] > *, [${phxUpdate}=prepend] > *`, (el) => { el.setAttribute(PHX_PRUNE, ""); }); } perform(isJoinPatch) { let { view, liveSocket: liveSocket2, container, html } = this; let targetContainer = this.isCIDPatch() ? this.targetCIDContainer(html) : container; if (this.isCIDPatch() && !targetContainer) { return; } let focused = liveSocket2.getActiveElement(); let { selectionStart, selectionEnd } = focused && dom_default.hasSelectionRange(focused) ? focused : {}; let phxUpdate = liveSocket2.binding(PHX_UPDATE); let phxFeedbackFor = liveSocket2.binding(PHX_FEEDBACK_FOR); let phxFeedbackGroup = liveSocket2.binding(PHX_FEEDBACK_GROUP); let disableWith = liveSocket2.binding(PHX_DISABLE_WITH); let phxViewportTop = liveSocket2.binding(PHX_VIEWPORT_TOP); let phxViewportBottom = liveSocket2.binding(PHX_VIEWPORT_BOTTOM); let phxTriggerExternal = liveSocket2.binding(PHX_TRIGGER_ACTION); let added = []; let feedbackContainers = []; let updates = []; let appendPrependUpdates = []; let externalFormTriggered = null; function morph(targetContainer2, source) { morphdom_esm_default(targetContainer2, source, { childrenOnly: targetContainer2.getAttribute(PHX_COMPONENT) === null, getNodeKey: (node) => { if (dom_default.isPhxDestroyed(node)) { return null; } if (isJoinPatch) { return node.id; } return node.id || node.getAttribute && node.getAttribute(PHX_MAGIC_ID); }, skipFromChildren: (from) => { return from.getAttribute(phxUpdate) === PHX_STREAM; }, addChild: (parent, child) => { let { ref, streamAt } = this.getStreamInsert(child); if (ref === void 0) { return parent.appendChild(child); } this.setStreamRef(child, ref); if (streamAt === 0) { parent.insertAdjacentElement("afterbegin", child); } else if (streamAt === -1) { parent.appendChild(child); } else if (streamAt > 0) { let sibling = Array.from(parent.children)[streamAt]; parent.insertBefore(child, sibling); } }, onBeforeNodeAdded: (el) => { dom_default.maybeAddPrivateHooks(el, phxViewportTop, phxViewportBottom); this.trackBefore("added", el); let morphedEl = el; if (!isJoinPatch && this.streamComponentRestore[el.id]) { morphedEl = this.streamComponentRestore[el.id]; delete this.streamComponentRestore[el.id]; morph.bind(this)(morphedEl, el); } return morphedEl; }, onNodeAdded: (el) => { if (el.getAttribute) { this.maybeReOrderStream(el, true); } if (dom_default.isFeedbackContainer(el, phxFeedbackFor)) feedbackContainers.push(el); if (el instanceof HTMLImageElement && el.srcset) { el.srcset = el.srcset; } else if (el instanceof HTMLVideoElement && el.autoplay) { el.play(); } if (dom_default.isNowTriggerFormExternal(el, phxTriggerExternal)) { externalFormTriggered = el; } if (dom_default.isPhxChild(el) && view.ownsElement(el) || dom_default.isPhxSticky(el) && view.ownsElement(el.parentNode)) { this.trackAfter("phxChildAdded", el); } added.push(el); }, onNodeDiscarded: (el) => this.onNodeDiscarded(el), onBeforeNodeDiscarded: (el) => { if (el.getAttribute && el.getAttribute(PHX_PRUNE) !== null) { return true; } if (el.parentElement !== null && el.id && dom_default.isPhxUpdate(el.parentElement, phxUpdate, [PHX_STREAM, "append", "prepend"])) { return false; } if (this.maybePendingRemove(el)) { return false; } if (this.skipCIDSibling(el)) { return false; } return true; }, onElUpdated: (el) => { if (dom_default.isNowTriggerFormExternal(el, phxTriggerExternal)) { externalFormTriggered = el; } updates.push(el); this.maybeReOrderStream(el, false); }, onBeforeElUpdated: (fromEl, toEl) => { dom_default.maybeAddPrivateHooks(toEl, phxViewportTop, phxViewportBottom); if (dom_default.isFeedbackContainer(fromEl, phxFeedbackFor) || dom_default.isFeedbackContainer(toEl, phxFeedbackFor)) { feedbackContainers.push(fromEl); feedbackContainers.push(toEl); } dom_default.cleanChildNodes(toEl, phxUpdate); if (this.skipCIDSibling(toEl)) { this.maybeReOrderStream(fromEl); return false; } if (dom_default.isPhxSticky(fromEl)) { return false; } if (dom_default.isIgnored(fromEl, phxUpdate) || fromEl.form && fromEl.form.isSameNode(externalFormTriggered)) { this.trackBefore("updated", fromEl, toEl); dom_default.mergeAttrs(fromEl, toEl, { isIgnored: true }); updates.push(fromEl); dom_default.applyStickyOperations(fromEl); return false; } if (fromEl.type === "number" && (fromEl.validity && fromEl.validity.badInput)) { return false; } if (!dom_default.syncPendingRef(fromEl, toEl, disableWith)) { if (dom_default.isUploadInput(fromEl)) { this.trackBefore("updated", fromEl, toEl); updates.push(fromEl); } dom_default.applyStickyOperations(fromEl); return false; } if (dom_default.isPhxChild(toEl)) { let prevSession = fromEl.getAttribute(PHX_SESSION); dom_default.mergeAttrs(fromEl, toEl, { exclude: [PHX_STATIC] }); if (prevSession !== "") { fromEl.setAttribute(PHX_SESSION, prevSession); } fromEl.setAttribute(PHX_ROOT_ID, this.rootID); dom_default.applyStickyOperations(fromEl); return false; } dom_default.copyPrivates(toEl, fromEl); let isFocusedFormEl = focused && fromEl.isSameNode(focused) && dom_default.isFormInput(fromEl); let focusedSelectChanged = isFocusedFormEl && this.isChangedSelect(fromEl, toEl); if (isFocusedFormEl && fromEl.type !== "hidden" && !focusedSelectChanged) { this.trackBefore("updated", fromEl, toEl); dom_default.mergeFocusedInput(fromEl, toEl); dom_default.syncAttrsToProps(fromEl); updates.push(fromEl); dom_default.applyStickyOperations(fromEl); return false; } else { if (focusedSelectChanged) { fromEl.blur(); } if (dom_default.isPhxUpdate(toEl, phxUpdate, ["append", "prepend"])) { appendPrependUpdates.push(new DOMPostMorphRestorer(fromEl, toEl, toEl.getAttribute(phxUpdate))); } dom_default.syncAttrsToProps(toEl); dom_default.applyStickyOperations(toEl); this.trackBefore("updated", fromEl, toEl); return true; } } }); } this.trackBefore("added", container); this.trackBefore("updated", container, container); liveSocket2.time("morphdom", () => { this.streams.forEach(([ref, inserts, deleteIds, reset]) => { inserts.forEach(([key, streamAt, limit]) => { this.streamInserts[key] = { ref, streamAt, limit, reset }; }); if (reset !== void 0) { dom_default.all(container, `[${PHX_STREAM_REF}="${ref}"]`, (child) => { this.removeStreamChildElement(child); }); } deleteIds.forEach((id) => { let child = container.querySelector(`[id="${id}"]`); if (child) { this.removeStreamChildElement(child); } }); }); if (isJoinPatch) { dom_default.all(this.container, `[${phxUpdate}=${PHX_STREAM}]`, (el) => { this.liveSocket.owner(el, (view2) => { if (view2 === this.view) { Array.from(el.children).forEach((child) => { this.removeStreamChildElement(child); }); } }); }); } morph.bind(this)(targetContainer, html); }); if (liveSocket2.isDebugEnabled()) { detectDuplicateIds(); } if (appendPrependUpdates.length > 0) { liveSocket2.time("post-morph append/prepend restoration", () => { appendPrependUpdates.forEach((update) => update.perform()); }); } dom_default.maybeHideFeedback(targetContainer, feedbackContainers, phxFeedbackFor, phxFeedbackGroup); liveSocket2.silenceEvents(() => dom_default.restoreFocus(focused, selectionStart, selectionEnd)); dom_default.dispatchEvent(document, "phx:update"); added.forEach((el) => this.trackAfter("added", el)); updates.forEach((el) => this.trackAfter("updated", el)); this.transitionPendingRemoves(); if (externalFormTriggered) { liveSocket2.unload(); Object.getPrototypeOf(externalFormTriggered).submit.call(externalFormTriggered); } return true; } onNodeDiscarded(el) { if (dom_default.isPhxChild(el) || dom_default.isPhxSticky(el)) { this.liveSocket.destroyViewByEl(el); } this.trackAfter("discarded", el); } maybePendingRemove(node) { if (node.getAttribute && node.getAttribute(this.phxRemove) !== null) { this.pendingRemoves.push(node); return true; } else { return false; } } removeStreamChildElement(child) { if (this.streamInserts[child.id]) { this.streamComponentRestore[child.id] = child; child.remove(); } else { if (!this.maybePendingRemove(child)) { child.remove(); this.onNodeDiscarded(child); } } } getStreamInsert(el) { let insert = el.id ? this.streamInserts[el.id] : {}; return insert || {}; } setStreamRef(el, ref) { dom_default.putSticky(el, PHX_STREAM_REF, (el2) => el2.setAttribute(PHX_STREAM_REF, ref)); } maybeReOrderStream(el, isNew) { let { ref, streamAt, reset } = this.getStreamInsert(el); if (streamAt === void 0) { return; } this.setStreamRef(el, ref); if (!reset && !isNew) { return; } if (!el.parentElement) { return; } if (streamAt === 0) { el.parentElement.insertBefore(el, el.parentElement.firstElementChild); } else if (streamAt > 0) { let children = Array.from(el.parentElement.children); let oldIndex = children.indexOf(el); if (streamAt >= children.length - 1) { el.parentElement.appendChild(el); } else { let sibling = children[streamAt]; if (oldIndex > streamAt) { el.parentElement.insertBefore(el, sibling); } else { el.parentElement.insertBefore(el, sibling.nextElementSibling); } } } this.maybeLimitStream(el); } maybeLimitStream(el) { let { limit } = this.getStreamInsert(el); let children = limit !== null && Array.from(el.parentElement.children); if (limit && limit < 0 && children.length > limit * -1) { children.slice(0, children.length + limit).forEach((child) => this.removeStreamChildElement(child)); } else if (limit && limit >= 0 && children.length > limit) { children.slice(limit).forEach((child) => this.removeStreamChildElement(child)); } } transitionPendingRemoves() { let { pendingRemoves, liveSocket: liveSocket2 } = this; if (pendingRemoves.length > 0) { liveSocket2.transitionRemoves(pendingRemoves); liveSocket2.requestDOMUpdate(() => { pendingRemoves.forEach((el) => { let child = dom_default.firstPhxChild(el); if (child) { liveSocket2.destroyViewByEl(child); } el.remove(); }); this.trackAfter("transitionsDiscarded", pendingRemoves); }); } } isChangedSelect(fromEl, toEl) { if (!(fromEl instanceof HTMLSelectElement) || fromEl.multiple) { return false; } if (fromEl.options.length !== toEl.options.length) { return true; } let fromSelected = fromEl.selectedOptions[0]; let toSelected = toEl.selectedOptions[0]; if (fromSelected && fromSelected.hasAttribute("selected")) { toSelected.setAttribute("selected", fromSelected.getAttribute("selected")); } return !fromEl.isEqualNode(toEl); } isCIDPatch() { return this.cidPatch; } skipCIDSibling(el) { return el.nodeType === Node.ELEMENT_NODE && el.hasAttribute(PHX_SKIP); } targetCIDContainer(html) { if (!this.isCIDPatch()) { return; } let [first, ...rest] = dom_default.findComponentNodeList(this.container, this.targetCID); if (rest.length === 0 && dom_default.childNodeLength(html) === 1) { return first; } else { return first && first.parentNode; } } indexOf(parent, child) { return Array.from(parent.children).indexOf(child); } }; var VOID_TAGS = /* @__PURE__ */ new Set([ "area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr" ]); var quoteChars = /* @__PURE__ */ new Set(["'", '"']); var modifyRoot = (html, attrs, clearInnerHTML) => { let i = 0; let insideComment = false; let beforeTag, afterTag, tag, tagNameEndsAt, id, newHTML; let lookahead = html.match(/^(\s*(?:\s*)*)<([^\s\/>]+)/); if (lookahead === null) { throw new Error(`malformed html ${html}`); } i = lookahead[0].length; beforeTag = lookahead[1]; tag = lookahead[2]; tagNameEndsAt = i; for (i; i < html.length; i++) { if (html.charAt(i) === ">") { break; } if (html.charAt(i) === "=") { let isId = html.slice(i - 3, i) === " id"; i++; let char = html.charAt(i); if (quoteChars.has(char)) { let attrStartsAt = i; i++; for (i; i < html.length; i++) { if (html.charAt(i) === char) { break; } } if (isId) { id = html.slice(attrStartsAt + 1, i); break; } } } } let closeAt = html.length - 1; insideComment = false; while (closeAt >= beforeTag.length + tag.length) { let char = html.charAt(closeAt); if (insideComment) { if (char === "-" && html.slice(closeAt - 3, closeAt) === "" && html.slice(closeAt - 2, closeAt) === "--") { insideComment = true; closeAt -= 3; } else if (char === ">") { break; } else { closeAt -= 1; } } afterTag = html.slice(closeAt + 1, html.length); let attrsStr = Object.keys(attrs).map((attr) => attrs[attr] === true ? attr : `${attr}="${attrs[attr]}"`).join(" "); if (clearInnerHTML) { let idAttrStr = id ? ` id="${id}"` : ""; if (VOID_TAGS.has(tag)) { newHTML = `<${tag}${idAttrStr}${attrsStr === "" ? "" : " "}${attrsStr}/>`; } else { newHTML = `<${tag}${idAttrStr}${attrsStr === "" ? "" : " "}${attrsStr}>`; } } else { let rest = html.slice(tagNameEndsAt, closeAt + 1); newHTML = `<${tag}${attrsStr === "" ? "" : " "}${attrsStr}${rest}`; } return [newHTML, beforeTag, afterTag]; }; var Rendered = class { static extract(diff) { let { [REPLY]: reply, [EVENTS]: events, [TITLE]: title } = diff; delete diff[REPLY]; delete diff[EVENTS]; delete diff[TITLE]; return { diff, title, reply: reply || null, events: events || [] }; } constructor(viewId, rendered) { this.viewId = viewId; this.rendered = {}; this.magicId = 0; this.mergeDiff(rendered); } parentViewId() { return this.viewId; } toString(onlyCids) { let [str, streams] = this.recursiveToString(this.rendered, this.rendered[COMPONENTS], onlyCids, true, {}); return [str, streams]; } recursiveToString(rendered, components = rendered[COMPONENTS], onlyCids, changeTracking, rootAttrs) { onlyCids = onlyCids ? new Set(onlyCids) : null; let output = { buffer: "", components, onlyCids, streams: /* @__PURE__ */ new Set() }; this.toOutputBuffer(rendered, null, output, changeTracking, rootAttrs); return [output.buffer, output.streams]; } componentCIDs(diff) { return Object.keys(diff[COMPONENTS] || {}).map((i) => parseInt(i)); } isComponentOnlyDiff(diff) { if (!diff[COMPONENTS]) { return false; } return Object.keys(diff).length === 1; } getComponent(diff, cid) { return diff[COMPONENTS][cid]; } resetRender(cid) { if (this.rendered[COMPONENTS][cid]) { this.rendered[COMPONENTS][cid].reset = true; } } mergeDiff(diff) { let newc = diff[COMPONENTS]; let cache = {}; delete diff[COMPONENTS]; this.rendered = this.mutableMerge(this.rendered, diff); this.rendered[COMPONENTS] = this.rendered[COMPONENTS] || {}; if (newc) { let oldc = this.rendered[COMPONENTS]; for (let cid in newc) { newc[cid] = this.cachedFindComponent(cid, newc[cid], oldc, newc, cache); } for (let cid in newc) { oldc[cid] = newc[cid]; } diff[COMPONENTS] = newc; } } cachedFindComponent(cid, cdiff, oldc, newc, cache) { if (cache[cid]) { return cache[cid]; } else { let ndiff, stat, scid = cdiff[STATIC]; if (isCid(scid)) { let tdiff; if (scid > 0) { tdiff = this.cachedFindComponent(scid, newc[scid], oldc, newc, cache); } else { tdiff = oldc[-scid]; } stat = tdiff[STATIC]; ndiff = this.cloneMerge(tdiff, cdiff, true); ndiff[STATIC] = stat; } else { ndiff = cdiff[STATIC] !== void 0 || oldc[cid] === void 0 ? cdiff : this.cloneMerge(oldc[cid], cdiff, false); } cache[cid] = ndiff; return ndiff; } } mutableMerge(target, source) { if (source[STATIC] !== void 0) { return source; } else { this.doMutableMerge(target, source); return target; } } doMutableMerge(target, source) { for (let key in source) { let val = source[key]; let targetVal = target[key]; let isObjVal = isObject(val); if (isObjVal && val[STATIC] === void 0 && isObject(targetVal)) { this.doMutableMerge(targetVal, val); } else { target[key] = val; } } if (target[ROOT]) { target.newRender = true; } } cloneMerge(target, source, pruneMagicId) { let merged = __spreadValues(__spreadValues({}, target), source); for (let key in merged) { let val = source[key]; let targetVal = target[key]; if (isObject(val) && val[STATIC] === void 0 && isObject(targetVal)) { merged[key] = this.cloneMerge(targetVal, val, pruneMagicId); } else if (val === void 0 && isObject(targetVal)) { merged[key] = this.cloneMerge(targetVal, {}, pruneMagicId); } } if (pruneMagicId) { delete merged.magicId; delete merged.newRender; } else if (target[ROOT]) { merged.newRender = true; } return merged; } componentToString(cid) { let [str, streams] = this.recursiveCIDToString(this.rendered[COMPONENTS], cid, null); let [strippedHTML, _before, _after] = modifyRoot(str, {}); return [strippedHTML, streams]; } pruneCIDs(cids) { cids.forEach((cid) => delete this.rendered[COMPONENTS][cid]); } get() { return this.rendered; } isNewFingerprint(diff = {}) { return !!diff[STATIC]; } templateStatic(part, templates) { if (typeof part === "number") { return templates[part]; } else { return part; } } nextMagicID() { this.magicId++; return `m${this.magicId}-${this.parentViewId()}`; } toOutputBuffer(rendered, templates, output, changeTracking, rootAttrs = {}) { if (rendered[DYNAMICS]) { return this.comprehensionToBuffer(rendered, templates, output); } let { [STATIC]: statics } = rendered; statics = this.templateStatic(statics, templates); let isRoot = rendered[ROOT]; let prevBuffer = output.buffer; if (isRoot) { output.buffer = ""; } if (changeTracking && isRoot && !rendered.magicId) { rendered.newRender = true; rendered.magicId = this.nextMagicID(); } output.buffer += statics[0]; for (let i = 1; i < statics.length; i++) { this.dynamicToBuffer(rendered[i - 1], templates, output, changeTracking); output.buffer += statics[i]; } if (isRoot) { let skip = false; let attrs; if (changeTracking || rendered.magicId) { skip = changeTracking && !rendered.newRender; attrs = __spreadValues({ [PHX_MAGIC_ID]: rendered.magicId }, rootAttrs); } else { attrs = rootAttrs; } if (skip) { attrs[PHX_SKIP] = true; } let [newRoot, commentBefore, commentAfter] = modifyRoot(output.buffer, attrs, skip); rendered.newRender = false; output.buffer = prevBuffer + commentBefore + newRoot + commentAfter; } } comprehensionToBuffer(rendered, templates, output) { let { [DYNAMICS]: dynamics, [STATIC]: statics, [STREAM]: stream } = rendered; let [_ref, _inserts, deleteIds, reset] = stream || [null, {}, [], null]; statics = this.templateStatic(statics, templates); let compTemplates = templates || rendered[TEMPLATES]; for (let d = 0; d < dynamics.length; d++) { let dynamic = dynamics[d]; output.buffer += statics[0]; for (let i = 1; i < statics.length; i++) { let changeTracking = false; this.dynamicToBuffer(dynamic[i - 1], compTemplates, output, changeTracking); output.buffer += statics[i]; } } if (stream !== void 0 && (rendered[DYNAMICS].length > 0 || deleteIds.length > 0 || reset)) { delete rendered[STREAM]; rendered[DYNAMICS] = []; output.streams.add(stream); } } dynamicToBuffer(rendered, templates, output, changeTracking) { if (typeof rendered === "number") { let [str, streams] = this.recursiveCIDToString(output.components, rendered, output.onlyCids); output.buffer += str; output.streams = /* @__PURE__ */ new Set([...output.streams, ...streams]); } else if (isObject(rendered)) { this.toOutputBuffer(rendered, templates, output, changeTracking, {}); } else { output.buffer += rendered; } } recursiveCIDToString(components, cid, onlyCids) { let component = components[cid] || logError(`no component for CID ${cid}`, components); let attrs = { [PHX_COMPONENT]: cid }; let skip = onlyCids && !onlyCids.has(cid); component.newRender = !skip; component.magicId = `c${cid}-${this.parentViewId()}`; let changeTracking = !component.reset; let [html, streams] = this.recursiveToString(component, components, onlyCids, changeTracking, attrs); delete component.reset; return [html, streams]; } }; var viewHookID = 1; var ViewHook = class { static makeID() { return viewHookID++; } static elementID(el) { return el.phxHookId; } constructor(view, el, callbacks) { this.__view = view; this.liveSocket = view.liveSocket; this.__callbacks = callbacks; this.__listeners = /* @__PURE__ */ new Set(); this.__isDisconnected = false; this.el = el; this.el.phxHookId = this.constructor.makeID(); for (let key in this.__callbacks) { this[key] = this.__callbacks[key]; } } __mounted() { this.mounted && this.mounted(); } __updated() { this.updated && this.updated(); } __beforeUpdate() { this.beforeUpdate && this.beforeUpdate(); } __destroyed() { this.destroyed && this.destroyed(); } __reconnected() { if (this.__isDisconnected) { this.__isDisconnected = false; this.reconnected && this.reconnected(); } } __disconnected() { this.__isDisconnected = true; this.disconnected && this.disconnected(); } pushEvent(event, payload = {}, onReply = function() { }) { return this.__view.pushHookEvent(this.el, null, event, payload, onReply); } pushEventTo(phxTarget, event, payload = {}, onReply = function() { }) { return this.__view.withinTargets(phxTarget, (view, targetCtx) => { return view.pushHookEvent(this.el, targetCtx, event, payload, onReply); }); } handleEvent(event, callback) { let callbackRef = (customEvent, bypass) => bypass ? event : callback(customEvent.detail); window.addEventListener(`phx:${event}`, callbackRef); this.__listeners.add(callbackRef); return callbackRef; } removeHandleEvent(callbackRef) { let event = callbackRef(null, true); window.removeEventListener(`phx:${event}`, callbackRef); this.__listeners.delete(callbackRef); } upload(name, files) { return this.__view.dispatchUploads(null, name, files); } uploadTo(phxTarget, name, files) { return this.__view.withinTargets(phxTarget, (view, targetCtx) => { view.dispatchUploads(targetCtx, name, files); }); } __cleanup__() { this.__listeners.forEach((callbackRef) => this.removeHandleEvent(callbackRef)); } }; var serializeForm = (form, metadata, onlyNames = []) => { const _a = metadata, { submitter } = _a, meta = __objRest(_a, ["submitter"]); let injectedElement; if (submitter && submitter.name) { const input = document.createElement("input"); input.type = "hidden"; const formId = submitter.getAttribute("form"); if (formId) { input.setAttribute("form", formId); } input.name = submitter.name; input.value = submitter.value; submitter.parentElement.insertBefore(input, submitter); injectedElement = input; } const formData = new FormData(form); const toRemove = []; formData.forEach((val, key, _index) => { if (val instanceof File) { toRemove.push(key); } }); toRemove.forEach((key) => formData.delete(key)); const params2 = new URLSearchParams(); for (let [key, val] of formData.entries()) { if (onlyNames.length === 0 || onlyNames.indexOf(key) >= 0) { params2.append(key, val); } } if (submitter && injectedElement) { submitter.parentElement.removeChild(injectedElement); } for (let metaKey in meta) { params2.append(metaKey, meta[metaKey]); } return params2.toString(); }; var View = class { constructor(el, liveSocket2, parentView, flash, liveReferer) { this.isDead = false; this.liveSocket = liveSocket2; this.flash = flash; this.parent = parentView; this.root = parentView ? parentView.root : this; this.el = el; this.id = this.el.id; this.ref = 0; this.childJoins = 0; this.loaderTimer = null; this.pendingDiffs = []; this.pendingForms = /* @__PURE__ */ new Set(); this.redirect = false; this.href = null; this.joinCount = this.parent ? this.parent.joinCount - 1 : 0; this.joinPending = true; this.destroyed = false; this.joinCallback = function(onDone) { onDone && onDone(); }; this.stopCallback = function() { }; this.pendingJoinOps = this.parent ? null : []; this.viewHooks = {}; this.formSubmits = []; this.children = this.parent ? null : {}; this.root.children[this.id] = {}; this.channel = this.liveSocket.channel(`lv:${this.id}`, () => { let url = this.href && this.expandURL(this.href); return { redirect: this.redirect ? url : void 0, url: this.redirect ? void 0 : url || void 0, params: this.connectParams(liveReferer), session: this.getSession(), static: this.getStatic(), flash: this.flash }; }); } setHref(href) { this.href = href; } setRedirect(href) { this.redirect = true; this.href = href; } isMain() { return this.el.hasAttribute(PHX_MAIN); } connectParams(liveReferer) { let params2 = this.liveSocket.params(this.el); let manifest = dom_default.all(document, `[${this.binding(PHX_TRACK_STATIC)}]`).map((node) => node.src || node.href).filter((url) => typeof url === "string"); if (manifest.length > 0) { params2["_track_static"] = manifest; } params2["_mounts"] = this.joinCount; params2["_live_referer"] = liveReferer; return params2; } isConnected() { return this.channel.canPush(); } getSession() { return this.el.getAttribute(PHX_SESSION); } getStatic() { let val = this.el.getAttribute(PHX_STATIC); return val === "" ? null : val; } destroy(callback = function() { }) { this.destroyAllChildren(); this.destroyed = true; delete this.root.children[this.id]; if (this.parent) { delete this.root.children[this.parent.id][this.id]; } clearTimeout(this.loaderTimer); let onFinished = () => { callback(); for (let id in this.viewHooks) { this.destroyHook(this.viewHooks[id]); } }; dom_default.markPhxChildDestroyed(this.el); this.log("destroyed", () => ["the child has been removed from the parent"]); this.channel.leave().receive("ok", onFinished).receive("error", onFinished).receive("timeout", onFinished); } setContainerClasses(...classes) { this.el.classList.remove(PHX_CONNECTED_CLASS, PHX_LOADING_CLASS, PHX_ERROR_CLASS, PHX_CLIENT_ERROR_CLASS, PHX_SERVER_ERROR_CLASS); this.el.classList.add(...classes); } showLoader(timeout) { clearTimeout(this.loaderTimer); if (timeout) { this.loaderTimer = setTimeout(() => this.showLoader(), timeout); } else { for (let id in this.viewHooks) { this.viewHooks[id].__disconnected(); } this.setContainerClasses(PHX_LOADING_CLASS); } } execAll(binding) { dom_default.all(this.el, `[${binding}]`, (el) => this.liveSocket.execJS(el, el.getAttribute(binding))); } hideLoader() { clearTimeout(this.loaderTimer); this.setContainerClasses(PHX_CONNECTED_CLASS); this.execAll(this.binding("connected")); } triggerReconnected() { for (let id in this.viewHooks) { this.viewHooks[id].__reconnected(); } } log(kind, msgCallback) { this.liveSocket.log(this, kind, msgCallback); } transition(time, onStart, onDone = function() { }) { this.liveSocket.transition(time, onStart, onDone); } withinTargets(phxTarget, callback) { if (phxTarget instanceof HTMLElement || phxTarget instanceof SVGElement) { return this.liveSocket.owner(phxTarget, (view) => callback(view, phxTarget)); } if (isCid(phxTarget)) { let targets = dom_default.findComponentNodeList(this.el, phxTarget); if (targets.length === 0) { logError(`no component found matching phx-target of ${phxTarget}`); } else { callback(this, parseInt(phxTarget)); } } else { let targets = Array.from(document.querySelectorAll(phxTarget)); if (targets.length === 0) { logError(`nothing found matching the phx-target selector "${phxTarget}"`); } targets.forEach((target) => this.liveSocket.owner(target, (view) => callback(view, target))); } } applyDiff(type, rawDiff, callback) { this.log(type, () => ["", clone(rawDiff)]); let { diff, reply, events, title } = Rendered.extract(rawDiff); callback({ diff, reply, events }); if (title) { window.requestAnimationFrame(() => dom_default.putTitle(title)); } } onJoin(resp) { let { rendered, container } = resp; if (container) { let [tag, attrs] = container; this.el = dom_default.replaceRootContainer(this.el, tag, attrs); } this.childJoins = 0; this.joinPending = true; this.flash = null; browser_default.dropLocal(this.liveSocket.localStorage, window.location.pathname, CONSECUTIVE_RELOADS); this.applyDiff("mount", rendered, ({ diff, events }) => { this.rendered = new Rendered(this.id, diff); let [html, streams] = this.renderContainer(null, "join"); this.dropPendingRefs(); let forms = this.formsForRecovery(html).filter(([form, newForm, newCid]) => { return !this.pendingForms.has(form.id); }); this.joinCount++; if (forms.length > 0) { forms.forEach(([form, newForm, newCid], i) => { this.pendingForms.add(form.id); this.pushFormRecovery(form, newCid, (resp2) => { this.pendingForms.delete(form.id); if (i === forms.length - 1) { this.onJoinComplete(resp2, html, streams, events); } }); }); } else { this.onJoinComplete(resp, html, streams, events); } }); } dropPendingRefs() { dom_default.all(document, `[${PHX_REF_SRC}="${this.id}"][${PHX_REF}]`, (el) => { el.removeAttribute(PHX_REF); el.removeAttribute(PHX_REF_SRC); }); } onJoinComplete({ live_patch }, html, streams, events) { this.pendingForms.clear(); if (this.joinCount > 1 || this.parent && !this.parent.isJoinPending()) { return this.applyJoinPatch(live_patch, html, streams, events); } let newChildren = dom_default.findPhxChildrenInFragment(html, this.id).filter((toEl) => { let fromEl = toEl.id && this.el.querySelector(`[id="${toEl.id}"]`); let phxStatic = fromEl && fromEl.getAttribute(PHX_STATIC); if (phxStatic) { toEl.setAttribute(PHX_STATIC, phxStatic); } if (fromEl) { fromEl.setAttribute(PHX_ROOT_ID, this.root.id); } return this.joinChild(toEl); }); if (newChildren.length === 0) { if (this.parent) { this.root.pendingJoinOps.push([this, () => this.applyJoinPatch(live_patch, html, streams, events)]); this.parent.ackJoin(this); } else { this.onAllChildJoinsComplete(); this.applyJoinPatch(live_patch, html, streams, events); } } else { this.root.pendingJoinOps.push([this, () => this.applyJoinPatch(live_patch, html, streams, events)]); } } attachTrueDocEl() { this.el = dom_default.byId(this.id); this.el.setAttribute(PHX_ROOT_ID, this.root.id); } execNewMounted() { let phxViewportTop = this.binding(PHX_VIEWPORT_TOP); let phxViewportBottom = this.binding(PHX_VIEWPORT_BOTTOM); dom_default.all(this.el, `[${phxViewportTop}], [${phxViewportBottom}]`, (hookEl) => { dom_default.maybeAddPrivateHooks(hookEl, phxViewportTop, phxViewportBottom); this.maybeAddNewHook(hookEl); }); dom_default.all(this.el, `[${this.binding(PHX_HOOK)}], [data-phx-${PHX_HOOK}]`, (hookEl) => { this.maybeAddNewHook(hookEl); }); dom_default.all(this.el, `[${this.binding(PHX_MOUNTED)}]`, (el) => this.maybeMounted(el)); } applyJoinPatch(live_patch, html, streams, events) { this.attachTrueDocEl(); let patch = new DOMPatch(this, this.el, this.id, html, streams, null); patch.markPrunableContentForRemoval(); this.performPatch(patch, false, true); this.joinNewChildren(); this.execNewMounted(); this.joinPending = false; this.liveSocket.dispatchEvents(events); this.applyPendingUpdates(); if (live_patch) { let { kind, to } = live_patch; this.liveSocket.historyPatch(to, kind); } this.hideLoader(); if (this.joinCount > 1) { this.triggerReconnected(); } this.stopCallback(); } triggerBeforeUpdateHook(fromEl, toEl) { this.liveSocket.triggerDOM("onBeforeElUpdated", [fromEl, toEl]); let hook = this.getHook(fromEl); let isIgnored = hook && dom_default.isIgnored(fromEl, this.binding(PHX_UPDATE)); if (hook && !fromEl.isEqualNode(toEl) && !(isIgnored && isEqualObj(fromEl.dataset, toEl.dataset))) { hook.__beforeUpdate(); return hook; } } maybeMounted(el) { let phxMounted = el.getAttribute(this.binding(PHX_MOUNTED)); let hasBeenInvoked = phxMounted && dom_default.private(el, "mounted"); if (phxMounted && !hasBeenInvoked) { this.liveSocket.execJS(el, phxMounted); dom_default.putPrivate(el, "mounted", true); } } maybeAddNewHook(el, force) { let newHook = this.addHook(el); if (newHook) { newHook.__mounted(); } } performPatch(patch, pruneCids, isJoinPatch = false) { let removedEls = []; let phxChildrenAdded = false; let updatedHookIds = /* @__PURE__ */ new Set(); patch.after("added", (el) => { this.liveSocket.triggerDOM("onNodeAdded", [el]); let phxViewportTop = this.binding(PHX_VIEWPORT_TOP); let phxViewportBottom = this.binding(PHX_VIEWPORT_BOTTOM); dom_default.maybeAddPrivateHooks(el, phxViewportTop, phxViewportBottom); this.maybeAddNewHook(el); if (el.getAttribute) { this.maybeMounted(el); } }); patch.after("phxChildAdded", (el) => { if (dom_default.isPhxSticky(el)) { this.liveSocket.joinRootViews(); } else { phxChildrenAdded = true; } }); patch.before("updated", (fromEl, toEl) => { let hook = this.triggerBeforeUpdateHook(fromEl, toEl); if (hook) { updatedHookIds.add(fromEl.id); } }); patch.after("updated", (el) => { if (updatedHookIds.has(el.id)) { this.getHook(el).__updated(); } }); patch.after("discarded", (el) => { if (el.nodeType === Node.ELEMENT_NODE) { removedEls.push(el); } }); patch.after("transitionsDiscarded", (els) => this.afterElementsRemoved(els, pruneCids)); patch.perform(isJoinPatch); this.afterElementsRemoved(removedEls, pruneCids); return phxChildrenAdded; } afterElementsRemoved(elements, pruneCids) { let destroyedCIDs = []; elements.forEach((parent) => { let components = dom_default.all(parent, `[${PHX_COMPONENT}]`); let hooks = dom_default.all(parent, `[${this.binding(PHX_HOOK)}]`); components.concat(parent).forEach((el) => { let cid = this.componentID(el); if (isCid(cid) && destroyedCIDs.indexOf(cid) === -1) { destroyedCIDs.push(cid); } }); hooks.concat(parent).forEach((hookEl) => { let hook = this.getHook(hookEl); hook && this.destroyHook(hook); }); }); if (pruneCids) { this.maybePushComponentsDestroyed(destroyedCIDs); } } joinNewChildren() { dom_default.findPhxChildren(this.el, this.id).forEach((el) => this.joinChild(el)); } getChildById(id) { return this.root.children[this.id][id]; } getDescendentByEl(el) { if (el.id === this.id) { return this; } else { return this.children[el.getAttribute(PHX_PARENT_ID)][el.id]; } } destroyDescendent(id) { for (let parentId in this.root.children) { for (let childId in this.root.children[parentId]) { if (childId === id) { return this.root.children[parentId][childId].destroy(); } } } } joinChild(el) { let child = this.getChildById(el.id); if (!child) { let view = new View(el, this.liveSocket, this); this.root.children[this.id][view.id] = view; view.join(); this.childJoins++; return true; } } isJoinPending() { return this.joinPending; } ackJoin(_child) { this.childJoins--; if (this.childJoins === 0) { if (this.parent) { this.parent.ackJoin(this); } else { this.onAllChildJoinsComplete(); } } } onAllChildJoinsComplete() { this.joinCallback(() => { this.pendingJoinOps.forEach(([view, op]) => { if (!view.isDestroyed()) { op(); } }); this.pendingJoinOps = []; }); } update(diff, events) { if (this.isJoinPending() || this.liveSocket.hasPendingLink() && this.root.isMain()) { return this.pendingDiffs.push({ diff, events }); } this.rendered.mergeDiff(diff); let phxChildrenAdded = false; if (this.rendered.isComponentOnlyDiff(diff)) { this.liveSocket.time("component patch complete", () => { let parentCids = dom_default.findExistingParentCIDs(this.el, this.rendered.componentCIDs(diff)); parentCids.forEach((parentCID) => { if (this.componentPatch(this.rendered.getComponent(diff, parentCID), parentCID)) { phxChildrenAdded = true; } }); }); } else if (!isEmpty(diff)) { this.liveSocket.time("full patch complete", () => { let [html, streams] = this.renderContainer(diff, "update"); let patch = new DOMPatch(this, this.el, this.id, html, streams, null); phxChildrenAdded = this.performPatch(patch, true); }); } this.liveSocket.dispatchEvents(events); if (phxChildrenAdded) { this.joinNewChildren(); } } renderContainer(diff, kind) { return this.liveSocket.time(`toString diff (${kind})`, () => { let tag = this.el.tagName; let cids = diff ? this.rendered.componentCIDs(diff) : null; let [html, streams] = this.rendered.toString(cids); return [`<${tag}>${html}`, streams]; }); } componentPatch(diff, cid) { if (isEmpty(diff)) return false; let [html, streams] = this.rendered.componentToString(cid); let patch = new DOMPatch(this, this.el, this.id, html, streams, cid); let childrenAdded = this.performPatch(patch, true); return childrenAdded; } getHook(el) { return this.viewHooks[ViewHook.elementID(el)]; } addHook(el) { if (ViewHook.elementID(el) || !el.getAttribute) { return; } let hookName = el.getAttribute(`data-phx-${PHX_HOOK}`) || el.getAttribute(this.binding(PHX_HOOK)); if (hookName && !this.ownsElement(el)) { return; } let callbacks = this.liveSocket.getHookCallbacks(hookName); if (callbacks) { if (!el.id) { logError(`no DOM ID for hook "${hookName}". Hooks require a unique ID on each element.`, el); } let hook = new ViewHook(this, el, callbacks); this.viewHooks[ViewHook.elementID(hook.el)] = hook; return hook; } else if (hookName !== null) { logError(`unknown hook found for "${hookName}"`, el); } } destroyHook(hook) { hook.__destroyed(); hook.__cleanup__(); delete this.viewHooks[ViewHook.elementID(hook.el)]; } applyPendingUpdates() { this.pendingDiffs.forEach(({ diff, events }) => this.update(diff, events)); this.pendingDiffs = []; this.eachChild((child) => child.applyPendingUpdates()); } eachChild(callback) { let children = this.root.children[this.id] || {}; for (let id in children) { callback(this.getChildById(id)); } } onChannel(event, cb) { this.liveSocket.onChannel(this.channel, event, (resp) => { if (this.isJoinPending()) { this.root.pendingJoinOps.push([this, () => cb(resp)]); } else { this.liveSocket.requestDOMUpdate(() => cb(resp)); } }); } bindChannel() { this.liveSocket.onChannel(this.channel, "diff", (rawDiff) => { this.liveSocket.requestDOMUpdate(() => { this.applyDiff("update", rawDiff, ({ diff, events }) => this.update(diff, events)); }); }); this.onChannel("redirect", ({ to, flash }) => this.onRedirect({ to, flash })); this.onChannel("live_patch", (redir) => this.onLivePatch(redir)); this.onChannel("live_redirect", (redir) => this.onLiveRedirect(redir)); this.channel.onError((reason) => this.onError(reason)); this.channel.onClose((reason) => this.onClose(reason)); } destroyAllChildren() { this.eachChild((child) => child.destroy()); } onLiveRedirect(redir) { let { to, kind, flash } = redir; let url = this.expandURL(to); this.liveSocket.historyRedirect(url, kind, flash); } onLivePatch(redir) { let { to, kind } = redir; this.href = this.expandURL(to); this.liveSocket.historyPatch(to, kind); } expandURL(to) { return to.startsWith("/") ? `${window.location.protocol}//${window.location.host}${to}` : to; } onRedirect({ to, flash }) { this.liveSocket.redirect(to, flash); } isDestroyed() { return this.destroyed; } joinDead() { this.isDead = true; } join(callback) { this.showLoader(this.liveSocket.loaderTimeout); this.bindChannel(); if (this.isMain()) { this.stopCallback = this.liveSocket.withPageLoading({ to: this.href, kind: "initial" }); } this.joinCallback = (onDone) => { onDone = onDone || function() { }; callback ? callback(this.joinCount, onDone) : onDone(); }; this.liveSocket.wrapPush(this, { timeout: false }, () => { return this.channel.join().receive("ok", (data) => { if (!this.isDestroyed()) { this.liveSocket.requestDOMUpdate(() => this.onJoin(data)); } }).receive("error", (resp) => !this.isDestroyed() && this.onJoinError(resp)).receive("timeout", () => !this.isDestroyed() && this.onJoinError({ reason: "timeout" })); }); } onJoinError(resp) { if (resp.reason === "reload") { this.log("error", () => [`failed mount with ${resp.status}. Falling back to page request`, resp]); if (this.isMain()) { this.onRedirect({ to: this.href }); } return; } else if (resp.reason === "unauthorized" || resp.reason === "stale") { this.log("error", () => ["unauthorized live_redirect. Falling back to page request", resp]); if (this.isMain()) { this.onRedirect({ to: this.href }); } return; } if (resp.redirect || resp.live_redirect) { this.joinPending = false; this.channel.leave(); } if (resp.redirect) { return this.onRedirect(resp.redirect); } if (resp.live_redirect) { return this.onLiveRedirect(resp.live_redirect); } this.displayError([PHX_LOADING_CLASS, PHX_ERROR_CLASS, PHX_SERVER_ERROR_CLASS]); this.log("error", () => ["unable to join", resp]); if (this.liveSocket.isConnected()) { this.liveSocket.reloadWithJitter(this); } } onClose(reason) { if (this.isDestroyed()) { return; } if (this.liveSocket.hasPendingLink() && reason !== "leave") { return this.liveSocket.reloadWithJitter(this); } this.destroyAllChildren(); this.liveSocket.dropActiveElement(this); if (document.activeElement) { document.activeElement.blur(); } if (this.liveSocket.isUnloaded()) { this.showLoader(BEFORE_UNLOAD_LOADER_TIMEOUT); } } onError(reason) { this.onClose(reason); if (this.liveSocket.isConnected()) { this.log("error", () => ["view crashed", reason]); } if (!this.liveSocket.isUnloaded()) { if (this.liveSocket.isConnected()) { this.displayError([PHX_LOADING_CLASS, PHX_ERROR_CLASS, PHX_SERVER_ERROR_CLASS]); } else { this.displayError([PHX_LOADING_CLASS, PHX_ERROR_CLASS, PHX_CLIENT_ERROR_CLASS]); } } } displayError(classes) { if (this.isMain()) { dom_default.dispatchEvent(window, "phx:page-loading-start", { detail: { to: this.href, kind: "error" } }); } this.showLoader(); this.setContainerClasses(...classes); this.execAll(this.binding("disconnected")); } pushWithReply(refGenerator, event, payload, onReply = function() { }) { if (!this.isConnected()) { return; } let [ref, [el], opts] = refGenerator ? refGenerator() : [null, [], {}]; let onLoadingDone = function() { }; if (opts.page_loading || el && el.getAttribute(this.binding(PHX_PAGE_LOADING)) !== null) { onLoadingDone = this.liveSocket.withPageLoading({ kind: "element", target: el }); } if (typeof payload.cid !== "number") { delete payload.cid; } return this.liveSocket.wrapPush(this, { timeout: true }, () => { return this.channel.push(event, payload, PUSH_TIMEOUT).receive("ok", (resp) => { let finish = (hookReply) => { if (resp.redirect) { this.onRedirect(resp.redirect); } if (resp.live_patch) { this.onLivePatch(resp.live_patch); } if (resp.live_redirect) { this.onLiveRedirect(resp.live_redirect); } onLoadingDone(); onReply(resp, hookReply); }; if (resp.diff) { this.liveSocket.requestDOMUpdate(() => { this.applyDiff("update", resp.diff, ({ diff, reply, events }) => { if (ref !== null) { this.undoRefs(ref); } this.update(diff, events); finish(reply); }); }); } else { if (ref !== null) { this.undoRefs(ref); } finish(null); } }); }); } undoRefs(ref) { if (!this.isConnected()) { return; } dom_default.all(document, `[${PHX_REF_SRC}="${this.id}"][${PHX_REF}="${ref}"]`, (el) => { let disabledVal = el.getAttribute(PHX_DISABLED); let readOnlyVal = el.getAttribute(PHX_READONLY); el.removeAttribute(PHX_REF); el.removeAttribute(PHX_REF_SRC); if (readOnlyVal !== null) { el.readOnly = readOnlyVal === "true" ? true : false; el.removeAttribute(PHX_READONLY); } if (disabledVal !== null) { el.disabled = disabledVal === "true" ? true : false; el.removeAttribute(PHX_DISABLED); } PHX_EVENT_CLASSES.forEach((className) => dom_default.removeClass(el, className)); let disableRestore = el.getAttribute(PHX_DISABLE_WITH_RESTORE); if (disableRestore !== null) { el.innerText = disableRestore; el.removeAttribute(PHX_DISABLE_WITH_RESTORE); } let toEl = dom_default.private(el, PHX_REF); if (toEl) { let hook = this.triggerBeforeUpdateHook(el, toEl); DOMPatch.patchEl(el, toEl, this.liveSocket.getActiveElement()); if (hook) { hook.__updated(); } dom_default.deletePrivate(el, PHX_REF); } }); } putRef(elements, event, opts = {}) { let newRef = this.ref++; let disableWith = this.binding(PHX_DISABLE_WITH); if (opts.loading) { elements = elements.concat(dom_default.all(document, opts.loading)); } elements.forEach((el) => { el.classList.add(`phx-${event}-loading`); el.setAttribute(PHX_REF, newRef); el.setAttribute(PHX_REF_SRC, this.el.id); let disableText = el.getAttribute(disableWith); if (disableText !== null) { if (!el.getAttribute(PHX_DISABLE_WITH_RESTORE)) { el.setAttribute(PHX_DISABLE_WITH_RESTORE, el.innerText); } if (disableText !== "") { el.innerText = disableText; } el.setAttribute(PHX_DISABLED, el.getAttribute(PHX_DISABLED) || el.disabled); el.setAttribute("disabled", ""); } }); return [newRef, elements, opts]; } componentID(el) { let cid = el.getAttribute && el.getAttribute(PHX_COMPONENT); return cid ? parseInt(cid) : null; } targetComponentID(target, targetCtx, opts = {}) { if (isCid(targetCtx)) { return targetCtx; } let cidOrSelector = opts.target || target.getAttribute(this.binding("target")); if (isCid(cidOrSelector)) { return parseInt(cidOrSelector); } else if (targetCtx && (cidOrSelector !== null || opts.target)) { return this.closestComponentID(targetCtx); } else { return null; } } closestComponentID(targetCtx) { if (isCid(targetCtx)) { return targetCtx; } else if (targetCtx) { return maybe(targetCtx.closest(`[${PHX_COMPONENT}]`), (el) => this.ownsElement(el) && this.componentID(el)); } else { return null; } } pushHookEvent(el, targetCtx, event, payload, onReply) { if (!this.isConnected()) { this.log("hook", () => ["unable to push hook event. LiveView not connected", event, payload]); return false; } let [ref, els, opts] = this.putRef([el], "hook"); this.pushWithReply(() => [ref, els, opts], "event", { type: "hook", event, value: payload, cid: this.closestComponentID(targetCtx) }, (resp, reply) => onReply(reply, ref)); return ref; } extractMeta(el, meta, value) { let prefix = this.binding("value-"); for (let i = 0; i < el.attributes.length; i++) { if (!meta) { meta = {}; } let name = el.attributes[i].name; if (name.startsWith(prefix)) { meta[name.replace(prefix, "")] = el.getAttribute(name); } } if (el.value !== void 0 && !(el instanceof HTMLFormElement)) { if (!meta) { meta = {}; } meta.value = el.value; if (el.tagName === "INPUT" && CHECKABLE_INPUTS.indexOf(el.type) >= 0 && !el.checked) { delete meta.value; } } if (value) { if (!meta) { meta = {}; } for (let key in value) { meta[key] = value[key]; } } return meta; } pushEvent(type, el, targetCtx, phxEvent, meta, opts = {}, onReply) { this.pushWithReply(() => this.putRef([el], type, opts), "event", { type, event: phxEvent, value: this.extractMeta(el, meta, opts.value), cid: this.targetComponentID(el, targetCtx, opts) }, (resp, reply) => onReply && onReply(reply)); } pushFileProgress(fileEl, entryRef, progress, onReply = function() { }) { this.liveSocket.withinOwners(fileEl.form, (view, targetCtx) => { view.pushWithReply(null, "progress", { event: fileEl.getAttribute(view.binding(PHX_PROGRESS)), ref: fileEl.getAttribute(PHX_UPLOAD_REF), entry_ref: entryRef, progress, cid: view.targetComponentID(fileEl.form, targetCtx) }, onReply); }); } pushInput(inputEl, targetCtx, forceCid, phxEvent, opts, callback) { let uploads; let cid = isCid(forceCid) ? forceCid : this.targetComponentID(inputEl.form, targetCtx, opts); let refGenerator = () => this.putRef([inputEl, inputEl.form], "change", opts); let formData; let meta = this.extractMeta(inputEl.form); if (inputEl instanceof HTMLButtonElement) { meta.submitter = inputEl; } if (inputEl.getAttribute(this.binding("change"))) { formData = serializeForm(inputEl.form, __spreadValues({ _target: opts._target }, meta), [inputEl.name]); } else { formData = serializeForm(inputEl.form, __spreadValues({ _target: opts._target }, meta)); } if (dom_default.isUploadInput(inputEl) && inputEl.files && inputEl.files.length > 0) { LiveUploader.trackFiles(inputEl, Array.from(inputEl.files)); } uploads = LiveUploader.serializeUploads(inputEl); let event = { type: "form", event: phxEvent, value: formData, uploads, cid }; this.pushWithReply(refGenerator, "event", event, (resp) => { dom_default.showError(inputEl, this.liveSocket.binding(PHX_FEEDBACK_FOR), this.liveSocket.binding(PHX_FEEDBACK_GROUP)); if (dom_default.isUploadInput(inputEl) && dom_default.isAutoUpload(inputEl)) { if (LiveUploader.filesAwaitingPreflight(inputEl).length > 0) { let [ref, _els] = refGenerator(); this.uploadFiles(inputEl.form, targetCtx, ref, cid, (_uploads) => { callback && callback(resp); this.triggerAwaitingSubmit(inputEl.form); this.undoRefs(ref); }); } } else { callback && callback(resp); } }); } triggerAwaitingSubmit(formEl) { let awaitingSubmit = this.getScheduledSubmit(formEl); if (awaitingSubmit) { let [_el, _ref, _opts, callback] = awaitingSubmit; this.cancelSubmit(formEl); callback(); } } getScheduledSubmit(formEl) { return this.formSubmits.find(([el, _ref, _opts, _callback]) => el.isSameNode(formEl)); } scheduleSubmit(formEl, ref, opts, callback) { if (this.getScheduledSubmit(formEl)) { return true; } this.formSubmits.push([formEl, ref, opts, callback]); } cancelSubmit(formEl) { this.formSubmits = this.formSubmits.filter(([el, ref, _callback]) => { if (el.isSameNode(formEl)) { this.undoRefs(ref); return false; } else { return true; } }); } disableForm(formEl, opts = {}) { let filterIgnored = (el) => { let userIgnored = closestPhxBinding(el, `${this.binding(PHX_UPDATE)}=ignore`, el.form); return !(userIgnored || closestPhxBinding(el, "data-phx-update=ignore", el.form)); }; let filterDisables = (el) => { return el.hasAttribute(this.binding(PHX_DISABLE_WITH)); }; let filterButton = (el) => el.tagName == "BUTTON"; let filterInput = (el) => ["INPUT", "TEXTAREA", "SELECT"].includes(el.tagName); let formElements = Array.from(formEl.elements); let disables = formElements.filter(filterDisables); let buttons = formElements.filter(filterButton).filter(filterIgnored); let inputs = formElements.filter(filterInput).filter(filterIgnored); buttons.forEach((button) => { button.setAttribute(PHX_DISABLED, button.disabled); button.disabled = true; }); inputs.forEach((input) => { input.setAttribute(PHX_READONLY, input.readOnly); input.readOnly = true; if (input.files) { input.setAttribute(PHX_DISABLED, input.disabled); input.disabled = true; } }); formEl.setAttribute(this.binding(PHX_PAGE_LOADING), ""); return this.putRef([formEl].concat(disables).concat(buttons).concat(inputs), "submit", opts); } pushFormSubmit(formEl, targetCtx, phxEvent, submitter, opts, onReply) { let refGenerator = () => this.disableForm(formEl, opts); let cid = this.targetComponentID(formEl, targetCtx); if (LiveUploader.hasUploadsInProgress(formEl)) { let [ref, _els] = refGenerator(); let push = () => this.pushFormSubmit(formEl, targetCtx, phxEvent, submitter, opts, onReply); return this.scheduleSubmit(formEl, ref, opts, push); } else if (LiveUploader.inputsAwaitingPreflight(formEl).length > 0) { let [ref, els] = refGenerator(); let proxyRefGen = () => [ref, els, opts]; this.uploadFiles(formEl, targetCtx, ref, cid, (uploads) => { if (LiveUploader.inputsAwaitingPreflight(formEl).length > 0) { return this.undoRefs(ref); } let meta = this.extractMeta(formEl); let formData = serializeForm(formEl, __spreadValues({ submitter }, meta)); this.pushWithReply(proxyRefGen, "event", { type: "form", event: phxEvent, value: formData, cid }, onReply); }); } else if (!(formEl.hasAttribute(PHX_REF) && formEl.classList.contains("phx-submit-loading"))) { let meta = this.extractMeta(formEl); let formData = serializeForm(formEl, __spreadValues({ submitter }, meta)); this.pushWithReply(refGenerator, "event", { type: "form", event: phxEvent, value: formData, cid }, onReply); } } uploadFiles(formEl, targetCtx, ref, cid, onComplete) { let joinCountAtUpload = this.joinCount; let inputEls = LiveUploader.activeFileInputs(formEl); let numFileInputsInProgress = inputEls.length; inputEls.forEach((inputEl) => { let uploader = new LiveUploader(inputEl, this, () => { numFileInputsInProgress--; if (numFileInputsInProgress === 0) { onComplete(); } }); let entries = uploader.entries().map((entry) => entry.toPreflightPayload()); if (entries.length === 0) { numFileInputsInProgress--; return; } let payload = { ref: inputEl.getAttribute(PHX_UPLOAD_REF), entries, cid: this.targetComponentID(inputEl.form, targetCtx) }; this.log("upload", () => ["sending preflight request", payload]); this.pushWithReply(null, "allow_upload", payload, (resp) => { this.log("upload", () => ["got preflight response", resp]); uploader.entries().forEach((entry) => { if (resp.entries && !resp.entries[entry.ref]) { this.handleFailedEntryPreflight(entry.ref, "failed preflight", uploader); } }); if (resp.error || Object.keys(resp.entries).length === 0) { this.undoRefs(ref); let errors = resp.error || []; errors.map(([entry_ref, reason]) => { this.handleFailedEntryPreflight(entry_ref, reason, uploader); }); } else { let onError = (callback) => { this.channel.onError(() => { if (this.joinCount === joinCountAtUpload) { callback(); } }); }; uploader.initAdapterUpload(resp, onError, this.liveSocket); } }); }); } handleFailedEntryPreflight(uploadRef, reason, uploader) { if (uploader.isAutoUpload()) { let entry = uploader.entries().find((entry2) => entry2.ref === uploadRef.toString()); if (entry) { entry.cancel(); } } else { uploader.entries().map((entry) => entry.cancel()); } this.log("upload", () => [`error for entry ${uploadRef}`, reason]); } dispatchUploads(targetCtx, name, filesOrBlobs) { let targetElement = this.targetCtxElement(targetCtx) || this.el; let inputs = dom_default.findUploadInputs(targetElement).filter((el) => el.name === name); if (inputs.length === 0) { logError(`no live file inputs found matching the name "${name}"`); } else if (inputs.length > 1) { logError(`duplicate live file inputs found matching the name "${name}"`); } else { dom_default.dispatchEvent(inputs[0], PHX_TRACK_UPLOADS, { detail: { files: filesOrBlobs } }); } } targetCtxElement(targetCtx) { if (isCid(targetCtx)) { let [target] = dom_default.findComponentNodeList(this.el, targetCtx); return target; } else if (targetCtx) { return targetCtx; } else { return null; } } pushFormRecovery(form, newCid, callback) { this.liveSocket.withinOwners(form, (view, targetCtx) => { let phxChange = this.binding("change"); let inputs = Array.from(form.elements).filter((el) => dom_default.isFormInput(el) && el.name && !el.hasAttribute(phxChange)); if (inputs.length === 0) { return; } inputs.forEach((input2) => input2.hasAttribute(PHX_UPLOAD_REF) && LiveUploader.clearFiles(input2)); let input = inputs.find((el) => el.type !== "hidden") || inputs[0]; let phxEvent = form.getAttribute(this.binding(PHX_AUTO_RECOVER)) || form.getAttribute(this.binding("change")); js_default.exec("change", phxEvent, view, input, ["push", { _target: input.name, newCid, callback }]); }); } pushLinkPatch(href, targetEl, callback) { let linkRef = this.liveSocket.setPendingLink(href); let refGen = targetEl ? () => this.putRef([targetEl], "click") : null; let fallback = () => this.liveSocket.redirect(window.location.href); let url = href.startsWith("/") ? `${location.protocol}//${location.host}${href}` : href; let push = this.pushWithReply(refGen, "live_patch", { url }, (resp) => { this.liveSocket.requestDOMUpdate(() => { if (resp.link_redirect) { this.liveSocket.replaceMain(href, null, callback, linkRef); } else { if (this.liveSocket.commitPendingLink(linkRef)) { this.href = href; } this.applyPendingUpdates(); callback && callback(linkRef); } }); }); if (push) { push.receive("timeout", fallback); } else { fallback(); } } formsForRecovery(html) { if (this.joinCount === 0) { return []; } let phxChange = this.binding("change"); let template = document.createElement("template"); template.innerHTML = html; return dom_default.all(this.el, `form[${phxChange}]`).filter((form) => form.id && this.ownsElement(form)).filter((form) => form.elements.length > 0).filter((form) => form.getAttribute(this.binding(PHX_AUTO_RECOVER)) !== "ignore").map((form) => { const phxChangeValue = CSS.escape(form.getAttribute(phxChange)); let newForm = template.content.querySelector(`form[id="${form.id}"][${phxChange}="${phxChangeValue}"]`); if (newForm) { return [form, newForm, this.targetComponentID(newForm)]; } else { return [form, form, this.targetComponentID(form)]; } }).filter(([form, newForm, newCid]) => newForm); } maybePushComponentsDestroyed(destroyedCIDs) { let willDestroyCIDs = destroyedCIDs.filter((cid) => { return dom_default.findComponentNodeList(this.el, cid).length === 0; }); if (willDestroyCIDs.length > 0) { willDestroyCIDs.forEach((cid) => this.rendered.resetRender(cid)); this.pushWithReply(null, "cids_will_destroy", { cids: willDestroyCIDs }, () => { let completelyDestroyCIDs = willDestroyCIDs.filter((cid) => { return dom_default.findComponentNodeList(this.el, cid).length === 0; }); if (completelyDestroyCIDs.length > 0) { this.pushWithReply(null, "cids_destroyed", { cids: completelyDestroyCIDs }, (resp) => { this.rendered.pruneCIDs(resp.cids); }); } }); } } ownsElement(el) { let parentViewEl = el.closest(PHX_VIEW_SELECTOR); return el.getAttribute(PHX_PARENT_ID) === this.id || parentViewEl && parentViewEl.id === this.id || !parentViewEl && this.isDead; } submitForm(form, targetCtx, phxEvent, submitter, opts = {}) { dom_default.putPrivate(form, PHX_HAS_SUBMITTED, true); const phxFeedbackFor = this.liveSocket.binding(PHX_FEEDBACK_FOR); const phxFeedbackGroup = this.liveSocket.binding(PHX_FEEDBACK_GROUP); const inputs = Array.from(form.elements); inputs.forEach((input) => dom_default.putPrivate(input, PHX_HAS_SUBMITTED, true)); this.liveSocket.blurActiveElement(this); this.pushFormSubmit(form, targetCtx, phxEvent, submitter, opts, () => { inputs.forEach((input) => dom_default.showError(input, phxFeedbackFor, phxFeedbackGroup)); this.liveSocket.restorePreviouslyActiveFocus(); }); } binding(kind) { return this.liveSocket.binding(kind); } }; var LiveSocket = class { constructor(url, phxSocket, opts = {}) { this.unloaded = false; if (!phxSocket || phxSocket.constructor.name === "Object") { throw new Error(` a phoenix Socket must be provided as the second argument to the LiveSocket constructor. For example: import {Socket} from "phoenix" import {LiveSocket} from "phoenix_live_view" let liveSocket = new LiveSocket("/live", Socket, {...}) `); } this.socket = new phxSocket(url, opts); this.bindingPrefix = opts.bindingPrefix || BINDING_PREFIX; this.opts = opts; this.params = closure2(opts.params || {}); this.viewLogger = opts.viewLogger; this.metadataCallbacks = opts.metadata || {}; this.defaults = Object.assign(clone(DEFAULTS), opts.defaults || {}); this.activeElement = null; this.prevActive = null; this.silenced = false; this.main = null; this.outgoingMainEl = null; this.clickStartedAtTarget = null; this.linkRef = 1; this.roots = {}; this.href = window.location.href; this.pendingLink = null; this.currentLocation = clone(window.location); this.hooks = opts.hooks || {}; this.uploaders = opts.uploaders || {}; this.loaderTimeout = opts.loaderTimeout || LOADER_TIMEOUT; this.reloadWithJitterTimer = null; this.maxReloads = opts.maxReloads || MAX_RELOADS; this.reloadJitterMin = opts.reloadJitterMin || RELOAD_JITTER_MIN; this.reloadJitterMax = opts.reloadJitterMax || RELOAD_JITTER_MAX; this.failsafeJitter = opts.failsafeJitter || FAILSAFE_JITTER; this.localStorage = opts.localStorage || window.localStorage; this.sessionStorage = opts.sessionStorage || window.sessionStorage; this.boundTopLevelEvents = false; this.domCallbacks = Object.assign({ onNodeAdded: closure2(), onBeforeElUpdated: closure2() }, opts.dom || {}); this.transitions = new TransitionSet(); window.addEventListener("pagehide", (_e) => { this.unloaded = true; }); this.socket.onOpen(() => { if (this.isUnloaded()) { window.location.reload(); } }); } isProfileEnabled() { return this.sessionStorage.getItem(PHX_LV_PROFILE) === "true"; } isDebugEnabled() { return this.sessionStorage.getItem(PHX_LV_DEBUG) === "true"; } isDebugDisabled() { return this.sessionStorage.getItem(PHX_LV_DEBUG) === "false"; } enableDebug() { this.sessionStorage.setItem(PHX_LV_DEBUG, "true"); } enableProfiling() { this.sessionStorage.setItem(PHX_LV_PROFILE, "true"); } disableDebug() { this.sessionStorage.setItem(PHX_LV_DEBUG, "false"); } disableProfiling() { this.sessionStorage.removeItem(PHX_LV_PROFILE); } enableLatencySim(upperBoundMs) { this.enableDebug(); console.log("latency simulator enabled for the duration of this browser session. Call disableLatencySim() to disable"); this.sessionStorage.setItem(PHX_LV_LATENCY_SIM, upperBoundMs); } disableLatencySim() { this.sessionStorage.removeItem(PHX_LV_LATENCY_SIM); } getLatencySim() { let str = this.sessionStorage.getItem(PHX_LV_LATENCY_SIM); return str ? parseInt(str) : null; } getSocket() { return this.socket; } connect() { if (window.location.hostname === "localhost" && !this.isDebugDisabled()) { this.enableDebug(); } let doConnect = () => { if (this.joinRootViews()) { this.bindTopLevelEvents(); this.socket.connect(); } else if (this.main) { this.socket.connect(); } else { this.bindTopLevelEvents({ dead: true }); } this.joinDeadView(); }; if (["complete", "loaded", "interactive"].indexOf(document.readyState) >= 0) { doConnect(); } else { document.addEventListener("DOMContentLoaded", () => doConnect()); } } disconnect(callback) { clearTimeout(this.reloadWithJitterTimer); this.socket.disconnect(callback); } replaceTransport(transport) { clearTimeout(this.reloadWithJitterTimer); this.socket.replaceTransport(transport); this.connect(); } execJS(el, encodedJS, eventType = null) { this.owner(el, (view) => js_default.exec(eventType, encodedJS, view, el)); } execJSHookPush(el, phxEvent, data, callback) { this.withinOwners(el, (view) => { js_default.exec("hook", phxEvent, view, el, ["push", { data, callback }]); }); } unload() { if (this.unloaded) { return; } if (this.main && this.isConnected()) { this.log(this.main, "socket", () => ["disconnect for page nav"]); } this.unloaded = true; this.destroyAllViews(); this.disconnect(); } triggerDOM(kind, args) { this.domCallbacks[kind](...args); } time(name, func) { if (!this.isProfileEnabled() || !console.time) { return func(); } console.time(name); let result = func(); console.timeEnd(name); return result; } log(view, kind, msgCallback) { if (this.viewLogger) { let [msg, obj] = msgCallback(); this.viewLogger(view, kind, msg, obj); } else if (this.isDebugEnabled()) { let [msg, obj] = msgCallback(); debug(view, kind, msg, obj); } } requestDOMUpdate(callback) { this.transitions.after(callback); } transition(time, onStart, onDone = function() { }) { this.transitions.addTransition(time, onStart, onDone); } onChannel(channel, event, cb) { channel.on(event, (data) => { let latency = this.getLatencySim(); if (!latency) { cb(data); } else { setTimeout(() => cb(data), latency); } }); } wrapPush(view, opts, push) { let latency = this.getLatencySim(); let oldJoinCount = view.joinCount; if (!latency) { if (this.isConnected() && opts.timeout) { return push().receive("timeout", () => { if (view.joinCount === oldJoinCount && !view.isDestroyed()) { this.reloadWithJitter(view, () => { this.log(view, "timeout", () => ["received timeout while communicating with server. Falling back to hard refresh for recovery"]); }); } }); } else { return push(); } } let fakePush = { receives: [], receive(kind, cb) { this.receives.push([kind, cb]); } }; setTimeout(() => { if (view.isDestroyed()) { return; } fakePush.receives.reduce((acc, [kind, cb]) => acc.receive(kind, cb), push()); }, latency); return fakePush; } reloadWithJitter(view, log) { clearTimeout(this.reloadWithJitterTimer); this.disconnect(); let minMs = this.reloadJitterMin; let maxMs = this.reloadJitterMax; let afterMs = Math.floor(Math.random() * (maxMs - minMs + 1)) + minMs; let tries = browser_default.updateLocal(this.localStorage, window.location.pathname, CONSECUTIVE_RELOADS, 0, (count) => count + 1); if (tries > this.maxReloads) { afterMs = this.failsafeJitter; } this.reloadWithJitterTimer = setTimeout(() => { if (view.isDestroyed() || view.isConnected()) { return; } view.destroy(); log ? log() : this.log(view, "join", () => [`encountered ${tries} consecutive reloads`]); if (tries > this.maxReloads) { this.log(view, "join", () => [`exceeded ${this.maxReloads} consecutive reloads. Entering failsafe mode`]); } if (this.hasPendingLink()) { window.location = this.pendingLink; } else { window.location.reload(); } }, afterMs); } getHookCallbacks(name) { return name && name.startsWith("Phoenix.") ? hooks_default[name.split(".")[1]] : this.hooks[name]; } isUnloaded() { return this.unloaded; } isConnected() { return this.socket.isConnected(); } getBindingPrefix() { return this.bindingPrefix; } binding(kind) { return `${this.getBindingPrefix()}${kind}`; } channel(topic, params2) { return this.socket.channel(topic, params2); } joinDeadView() { let body = document.body; if (body && !this.isPhxView(body) && !this.isPhxView(document.firstElementChild)) { let view = this.newRootView(body); view.setHref(this.getHref()); view.joinDead(); if (!this.main) { this.main = view; } window.requestAnimationFrame(() => view.execNewMounted()); } } joinRootViews() { let rootsFound = false; dom_default.all(document, `${PHX_VIEW_SELECTOR}:not([${PHX_PARENT_ID}])`, (rootEl) => { if (!this.getRootById(rootEl.id)) { let view = this.newRootView(rootEl); view.setHref(this.getHref()); view.join(); if (rootEl.hasAttribute(PHX_MAIN)) { this.main = view; } } rootsFound = true; }); return rootsFound; } redirect(to, flash) { this.unload(); browser_default.redirect(to, flash); } replaceMain(href, flash, callback = null, linkRef = this.setPendingLink(href)) { let liveReferer = this.currentLocation.href; this.outgoingMainEl = this.outgoingMainEl || this.main.el; let newMainEl = dom_default.cloneNode(this.outgoingMainEl, ""); this.main.showLoader(this.loaderTimeout); this.main.destroy(); this.main = this.newRootView(newMainEl, flash, liveReferer); this.main.setRedirect(href); this.transitionRemoves(null, true); this.main.join((joinCount, onDone) => { if (joinCount === 1 && this.commitPendingLink(linkRef)) { this.requestDOMUpdate(() => { dom_default.findPhxSticky(document).forEach((el) => newMainEl.appendChild(el)); this.outgoingMainEl.replaceWith(newMainEl); this.outgoingMainEl = null; callback && callback(linkRef); onDone(); }); } }); } transitionRemoves(elements, skipSticky) { let removeAttr = this.binding("remove"); elements = elements || dom_default.all(document, `[${removeAttr}]`); if (skipSticky) { const stickies = dom_default.findPhxSticky(document) || []; elements = elements.filter((el) => !dom_default.isChildOfAny(el, stickies)); } elements.forEach((el) => { this.execJS(el, el.getAttribute(removeAttr), "remove"); }); } isPhxView(el) { return el.getAttribute && el.getAttribute(PHX_SESSION) !== null; } newRootView(el, flash, liveReferer) { let view = new View(el, this, null, flash, liveReferer); this.roots[view.id] = view; return view; } owner(childEl, callback) { let view = maybe(childEl.closest(PHX_VIEW_SELECTOR), (el) => this.getViewByEl(el)) || this.main; if (view) { callback(view); } } withinOwners(childEl, callback) { this.owner(childEl, (view) => callback(view, childEl)); } getViewByEl(el) { let rootId = el.getAttribute(PHX_ROOT_ID); return maybe(this.getRootById(rootId), (root) => root.getDescendentByEl(el)); } getRootById(id) { return this.roots[id]; } destroyAllViews() { for (let id in this.roots) { this.roots[id].destroy(); delete this.roots[id]; } this.main = null; } destroyViewByEl(el) { let root = this.getRootById(el.getAttribute(PHX_ROOT_ID)); if (root && root.id === el.id) { root.destroy(); delete this.roots[root.id]; } else if (root) { root.destroyDescendent(el.id); } } setActiveElement(target) { if (this.activeElement === target) { return; } this.activeElement = target; let cancel = () => { if (target === this.activeElement) { this.activeElement = null; } target.removeEventListener("mouseup", this); target.removeEventListener("touchend", this); }; target.addEventListener("mouseup", cancel); target.addEventListener("touchend", cancel); } getActiveElement() { if (document.activeElement === document.body) { return this.activeElement || document.activeElement; } else { return document.activeElement || document.body; } } dropActiveElement(view) { if (this.prevActive && view.ownsElement(this.prevActive)) { this.prevActive = null; } } restorePreviouslyActiveFocus() { if (this.prevActive && this.prevActive !== document.body) { this.prevActive.focus(); } } blurActiveElement() { this.prevActive = this.getActiveElement(); if (this.prevActive !== document.body) { this.prevActive.blur(); } } bindTopLevelEvents({ dead } = {}) { if (this.boundTopLevelEvents) { return; } this.boundTopLevelEvents = true; this.socket.onClose((event) => { if (event && event.code === 1e3 && this.main) { return this.reloadWithJitter(this.main); } }); document.body.addEventListener("click", function() { }); window.addEventListener("pageshow", (e) => { if (e.persisted) { this.getSocket().disconnect(); this.withPageLoading({ to: window.location.href, kind: "redirect" }); window.location.reload(); } }, true); if (!dead) { this.bindNav(); } this.bindClicks(); if (!dead) { this.bindForms(); } this.bind({ keyup: "keyup", keydown: "keydown" }, (e, type, view, targetEl, phxEvent, phxTarget) => { let matchKey = targetEl.getAttribute(this.binding(PHX_KEY)); let pressedKey = e.key && e.key.toLowerCase(); if (matchKey && matchKey.toLowerCase() !== pressedKey) { return; } let data = __spreadValues({ key: e.key }, this.eventMeta(type, e, targetEl)); js_default.exec(type, phxEvent, view, targetEl, ["push", { data }]); }); this.bind({ blur: "focusout", focus: "focusin" }, (e, type, view, targetEl, phxEvent, phxTarget) => { if (!phxTarget) { let data = __spreadValues({ key: e.key }, this.eventMeta(type, e, targetEl)); js_default.exec(type, phxEvent, view, targetEl, ["push", { data }]); } }); this.bind({ blur: "blur", focus: "focus" }, (e, type, view, targetEl, phxEvent, phxTarget) => { if (phxTarget === "window") { let data = this.eventMeta(type, e, targetEl); js_default.exec(type, phxEvent, view, targetEl, ["push", { data }]); } }); window.addEventListener("dragover", (e) => e.preventDefault()); window.addEventListener("drop", (e) => { e.preventDefault(); let dropTargetId = maybe(closestPhxBinding(e.target, this.binding(PHX_DROP_TARGET)), (trueTarget) => { return trueTarget.getAttribute(this.binding(PHX_DROP_TARGET)); }); let dropTarget = dropTargetId && document.getElementById(dropTargetId); let files = Array.from(e.dataTransfer.files || []); if (!dropTarget || dropTarget.disabled || files.length === 0 || !(dropTarget.files instanceof FileList)) { return; } LiveUploader.trackFiles(dropTarget, files, e.dataTransfer); dropTarget.dispatchEvent(new Event("input", { bubbles: true })); }); this.on(PHX_TRACK_UPLOADS, (e) => { let uploadTarget = e.target; if (!dom_default.isUploadInput(uploadTarget)) { return; } let files = Array.from(e.detail.files || []).filter((f) => f instanceof File || f instanceof Blob); LiveUploader.trackFiles(uploadTarget, files); uploadTarget.dispatchEvent(new Event("input", { bubbles: true })); }); } eventMeta(eventName, e, targetEl) { let callback = this.metadataCallbacks[eventName]; return callback ? callback(e, targetEl) : {}; } setPendingLink(href) { this.linkRef++; this.pendingLink = href; return this.linkRef; } commitPendingLink(linkRef) { if (this.linkRef !== linkRef) { return false; } else { this.href = this.pendingLink; this.pendingLink = null; return true; } } getHref() { return this.href; } hasPendingLink() { return !!this.pendingLink; } bind(events, callback) { for (let event in events) { let browserEventName = events[event]; this.on(browserEventName, (e) => { let binding = this.binding(event); let windowBinding = this.binding(`window-${event}`); let targetPhxEvent = e.target.getAttribute && e.target.getAttribute(binding); if (targetPhxEvent) { this.debounce(e.target, e, browserEventName, () => { this.withinOwners(e.target, (view) => { callback(e, event, view, e.target, targetPhxEvent, null); }); }); } else { dom_default.all(document, `[${windowBinding}]`, (el) => { let phxEvent = el.getAttribute(windowBinding); this.debounce(el, e, browserEventName, () => { this.withinOwners(el, (view) => { callback(e, event, view, el, phxEvent, "window"); }); }); }); } }); } } bindClicks() { window.addEventListener("mousedown", (e) => this.clickStartedAtTarget = e.target); this.bindClick("click", "click", false); this.bindClick("mousedown", "capture-click", true); } bindClick(eventName, bindingName, capture) { let click = this.binding(bindingName); window.addEventListener(eventName, (e) => { let target = null; if (capture) { target = e.target.matches(`[${click}]`) ? e.target : e.target.querySelector(`[${click}]`); } else { if (e.detail === 0) this.clickStartedAtTarget = e.target; let clickStartedAtTarget = this.clickStartedAtTarget || e.target; target = closestPhxBinding(clickStartedAtTarget, click); this.dispatchClickAway(e, clickStartedAtTarget); this.clickStartedAtTarget = null; } let phxEvent = target && target.getAttribute(click); if (!phxEvent) { if (!capture && dom_default.isNewPageClick(e, window.location)) { this.unload(); } return; } if (target.getAttribute("href") === "#") { e.preventDefault(); } if (target.hasAttribute(PHX_REF)) { return; } this.debounce(target, e, "click", () => { this.withinOwners(target, (view) => { js_default.exec("click", phxEvent, view, target, ["push", { data: this.eventMeta("click", e, target) }]); }); }); }, capture); } dispatchClickAway(e, clickStartedAt) { let phxClickAway = this.binding("click-away"); dom_default.all(document, `[${phxClickAway}]`, (el) => { if (!(el.isSameNode(clickStartedAt) || el.contains(clickStartedAt))) { this.withinOwners(el, (view) => { let phxEvent = el.getAttribute(phxClickAway); if (js_default.isVisible(el) && js_default.isInViewport(el)) { js_default.exec("click", phxEvent, view, el, ["push", { data: this.eventMeta("click", e, e.target) }]); } }); } }); } bindNav() { if (!browser_default.canPushState()) { return; } if (history.scrollRestoration) { history.scrollRestoration = "manual"; } let scrollTimer = null; window.addEventListener("scroll", (_e) => { clearTimeout(scrollTimer); scrollTimer = setTimeout(() => { browser_default.updateCurrentState((state) => Object.assign(state, { scroll: window.scrollY })); }, 100); }); window.addEventListener("popstate", (event) => { if (!this.registerNewLocation(window.location)) { return; } let { type, id, root, scroll } = event.state || {}; let href = window.location.href; dom_default.dispatchEvent(window, "phx:navigate", { detail: { href, patch: type === "patch", pop: true } }); this.requestDOMUpdate(() => { if (this.main.isConnected() && (type === "patch" && id === this.main.id)) { this.main.pushLinkPatch(href, null, () => { this.maybeScroll(scroll); }); } else { this.replaceMain(href, null, () => { if (root) { this.replaceRootHistory(); } this.maybeScroll(scroll); }); } }); }, false); window.addEventListener("click", (e) => { let target = closestPhxBinding(e.target, PHX_LIVE_LINK); let type = target && target.getAttribute(PHX_LIVE_LINK); if (!type || !this.isConnected() || !this.main || dom_default.wantsNewTab(e)) { return; } let href = target.href instanceof SVGAnimatedString ? target.href.baseVal : target.href; let linkState = target.getAttribute(PHX_LINK_STATE); e.preventDefault(); e.stopImmediatePropagation(); if (this.pendingLink === href) { return; } this.requestDOMUpdate(() => { if (type === "patch") { this.pushHistoryPatch(href, linkState, target); } else if (type === "redirect") { this.historyRedirect(href, linkState); } else { throw new Error(`expected ${PHX_LIVE_LINK} to be "patch" or "redirect", got: ${type}`); } let phxClick = target.getAttribute(this.binding("click")); if (phxClick) { this.requestDOMUpdate(() => this.execJS(target, phxClick, "click")); } }); }, false); } maybeScroll(scroll) { if (typeof scroll === "number") { requestAnimationFrame(() => { window.scrollTo(0, scroll); }); } } dispatchEvent(event, payload = {}) { dom_default.dispatchEvent(window, `phx:${event}`, { detail: payload }); } dispatchEvents(events) { events.forEach(([event, payload]) => this.dispatchEvent(event, payload)); } withPageLoading(info, callback) { dom_default.dispatchEvent(window, "phx:page-loading-start", { detail: info }); let done = () => dom_default.dispatchEvent(window, "phx:page-loading-stop", { detail: info }); return callback ? callback(done) : done; } pushHistoryPatch(href, linkState, targetEl) { if (!this.isConnected() || !this.main.isMain()) { return browser_default.redirect(href); } this.withPageLoading({ to: href, kind: "patch" }, (done) => { this.main.pushLinkPatch(href, targetEl, (linkRef) => { this.historyPatch(href, linkState, linkRef); done(); }); }); } historyPatch(href, linkState, linkRef = this.setPendingLink(href)) { if (!this.commitPendingLink(linkRef)) { return; } browser_default.pushState(linkState, { type: "patch", id: this.main.id }, href); dom_default.dispatchEvent(window, "phx:navigate", { detail: { patch: true, href, pop: false } }); this.registerNewLocation(window.location); } historyRedirect(href, linkState, flash) { if (!this.isConnected() || !this.main.isMain()) { return browser_default.redirect(href, flash); } if (/^\/$|^\/[^\/]+.*$/.test(href)) { let { protocol, host } = window.location; href = `${protocol}//${host}${href}`; } let scroll = window.scrollY; this.withPageLoading({ to: href, kind: "redirect" }, (done) => { this.replaceMain(href, flash, (linkRef) => { if (linkRef === this.linkRef) { browser_default.pushState(linkState, { type: "redirect", id: this.main.id, scroll }, href); dom_default.dispatchEvent(window, "phx:navigate", { detail: { href, patch: false, pop: false } }); this.registerNewLocation(window.location); } done(); }); }); } replaceRootHistory() { browser_default.pushState("replace", { root: true, type: "patch", id: this.main.id }); } registerNewLocation(newLocation) { let { pathname, search } = this.currentLocation; if (pathname + search === newLocation.pathname + newLocation.search) { return false; } else { this.currentLocation = clone(newLocation); return true; } } bindForms() { let iterations = 0; let externalFormSubmitted = false; this.on("submit", (e) => { let phxSubmit = e.target.getAttribute(this.binding("submit")); let phxChange = e.target.getAttribute(this.binding("change")); if (!externalFormSubmitted && phxChange && !phxSubmit) { externalFormSubmitted = true; e.preventDefault(); this.withinOwners(e.target, (view) => { view.disableForm(e.target); window.requestAnimationFrame(() => { if (dom_default.isUnloadableFormSubmit(e)) { this.unload(); } e.target.submit(); }); }); } }, true); this.on("submit", (e) => { let phxEvent = e.target.getAttribute(this.binding("submit")); if (!phxEvent) { if (dom_default.isUnloadableFormSubmit(e)) { this.unload(); } return; } e.preventDefault(); e.target.disabled = true; this.withinOwners(e.target, (view) => { js_default.exec("submit", phxEvent, view, e.target, ["push", { submitter: e.submitter }]); }); }, false); for (let type of ["change", "input"]) { this.on(type, (e) => { let phxChange = this.binding("change"); let input = e.target; let inputEvent = input.getAttribute(phxChange); let formEvent = input.form && input.form.getAttribute(phxChange); let phxEvent = inputEvent || formEvent; if (!phxEvent) { return; } if (input.type === "number" && input.validity && input.validity.badInput) { return; } let dispatcher = inputEvent ? input : input.form; let currentIterations = iterations; iterations++; let { at, type: lastType } = dom_default.private(input, "prev-iteration") || {}; if (at === currentIterations - 1 && type === "change" && lastType === "input") { return; } dom_default.putPrivate(input, "prev-iteration", { at: currentIterations, type }); this.debounce(input, e, type, () => { this.withinOwners(dispatcher, (view) => { dom_default.putPrivate(input, PHX_HAS_FOCUSED, true); if (!dom_default.isTextualInput(input)) { this.setActiveElement(input); } js_default.exec("change", phxEvent, view, input, ["push", { _target: e.target.name, dispatcher }]); }); }); }, false); } this.on("reset", (e) => { let form = e.target; dom_default.resetForm(form, this.binding(PHX_FEEDBACK_FOR), this.binding(PHX_FEEDBACK_GROUP)); let input = Array.from(form.elements).find((el) => el.type === "reset"); if (input) { window.requestAnimationFrame(() => { input.dispatchEvent(new Event("input", { bubbles: true, cancelable: false })); }); } }); } debounce(el, event, eventType, callback) { if (eventType === "blur" || eventType === "focusout") { return callback(); } let phxDebounce = this.binding(PHX_DEBOUNCE); let phxThrottle = this.binding(PHX_THROTTLE); let defaultDebounce = this.defaults.debounce.toString(); let defaultThrottle = this.defaults.throttle.toString(); this.withinOwners(el, (view) => { let asyncFilter = () => !view.isDestroyed() && document.body.contains(el); dom_default.debounce(el, event, phxDebounce, defaultDebounce, phxThrottle, defaultThrottle, asyncFilter, () => { callback(); }); }); } silenceEvents(callback) { this.silenced = true; callback(); this.silenced = false; } on(event, callback) { window.addEventListener(event, (e) => { if (!this.silenced) { callback(e); } }); } }; var TransitionSet = class { constructor() { this.transitions = /* @__PURE__ */ new Set(); this.pendingOps = []; } reset() { this.transitions.forEach((timer) => { clearTimeout(timer); this.transitions.delete(timer); }); this.flushPendingOps(); } after(callback) { if (this.size() === 0) { callback(); } else { this.pushPendingOp(callback); } } addTransition(time, onStart, onDone) { onStart(); let timer = setTimeout(() => { this.transitions.delete(timer); onDone(); this.flushPendingOps(); }, time); this.transitions.add(timer); } pushPendingOp(op) { this.pendingOps.push(op); } size() { return this.transitions.size; } flushPendingOps() { if (this.size() > 0) { return; } let op = this.pendingOps.shift(); if (op) { op(); this.flushPendingOps(); } } }; // js/app.js var socketPath = document.querySelector("html").getAttribute("phx-socket") || "/live"; var csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content"); var Hooks2 = {}; var editors = {}; Hooks2.JsonEditor = { mounted() { const inputId = this.el.getAttribute("data-input-id"); const hook = this; this.editor = new JSONEditor( this.el, { onChangeText: (json2) => { const target = document.getElementById(inputId); try { JSON.parse(json2); target.value = json2; target.dispatchEvent(new Event("change", { bubbles: true })); } catch (_e) { } }, onChange: () => { try { const target = document.getElementById(inputId); json = hook.editor.get(); target.value = JSON.stringify(json); target.dispatchEvent(new Event("change", { bubbles: true })); } catch (_e) { } }, onModeChange: (newMode) => { hook.mode = newMode; }, modes: ["text", "tree"] }, JSON.parse(document.getElementById(inputId).value) ); editors[this.el.id] = this.editor; } }; Hooks2.JsonEditorSource = { updated() { try { let editor = editors[this.el.getAttribute("data-editor-id")]; if (editor.getMode() === "tree") { editor.update(JSON.parse(this.el.value)); } else { if (editor.get() !== JSON.parse(this.el.value)) { editor.setText(this.el.value); } else { } } } catch (_e) { } } }; Hooks2.JsonView = { updated() { const json2 = JSON.parse(this.el.getAttribute("data-json")); this.editor = new JSONEditor( this.el, { mode: "preview" }, json2 ); }, mounted() { const json2 = JSON.parse(this.el.getAttribute("data-json")); this.editor = new JSONEditor( this.el, { mode: "preview" }, json2 ); } }; var init = (element) => new EasyMDE({ element, initialValue: element.getAttribute("value") }); Hooks2.MarkdownEditor = { mounted() { const id = this.el.getAttribute("data-target-id"); const el = document.getElementById(id); const easyMDE = init(el); easyMDE.codemirror.on("change", () => { el.value = easyMDE.value(); el.dispatchEvent(new Event("change", { bubbles: true })); }); } }; Hooks2.Actor = { mounted() { this.handleEvent("set_actor", (payload) => { document.cookie = "actor_resource=" + payload.resource + ";path=/"; document.cookie = "actor_primary_key=" + payload.primary_key + ";path=/"; document.cookie = "actor_action=" + payload.action + ";path=/"; document.cookie = "actor_domain=" + payload.domain + ";path=/"; document.cookie = "actor_tenant=" + payload.tenant + ";path=/"; }); this.handleEvent("clear_actor", () => { document.cookie = "actor_resource=;path=/"; document.cookie = "actor_primary_key=;path=/"; document.cookie = "actor_action=;path=/"; document.cookie = "actor_tenant=;path=/"; document.cookie = "actor_domain=;path=/"; document.cookie = "actor_authorizing=false;path=/"; document.cookie = "actor_paused=true;path=/"; }); this.handleEvent("toggle_authorizing", (payload) => { document.cookie = "actor_authorizing=" + payload.authorizing + ";path=/"; }); this.handleEvent("toggle_actor_paused", (payload) => { document.cookie = "actor_paused=" + payload.actor_paused + ";path=/"; }); } }; Hooks2.Tenant = { mounted() { this.handleEvent("set_tenant", (payload) => { document.cookie = "tenant=" + payload.tenant + ";path=/"; }); this.handleEvent("clear_tenant", () => { document.cookie = "tenant=;path=/"; }); } }; Hooks2.MaintainAttrs = { attrs() { return this.el.getAttribute("data-attrs").split(", "); }, beforeUpdate() { this.prevAttrs = this.attrs().map((name) => [ name, this.el.getAttribute(name) ]); }, updated() { this.prevAttrs.forEach(([name, val]) => this.el.setAttribute(name, val)); } }; function getCookie(name) { var re = new RegExp(name + "=([^;]+)"); var value = re.exec(document.cookie); return value != null ? unescape(value[1]) : null; } var params = () => { return { _csrf_token: csrfToken, tenant: getCookie("tenant"), actor_resource: getCookie("actor_resource"), actor_primary_key: getCookie("actor_primary_key"), actor_tenant: getCookie("actor_tenant"), actor_action: getCookie("actor_action"), actor_domain: getCookie("actor_domain"), actor_authorizing: getCookie("actor_authorizing"), actor_paused: getCookie("actor_paused") }; }; var liveSocket = new LiveSocket(socketPath, Socket, { params, hooks: Hooks2, dom: { onBeforeElUpdated(from, to) { if (from._x_dataStack) { window.Alpine.clone(from, to); } } } }); import_topbar.default.config({ barColors: { 0: "#29d" }, shadowColor: "rgba(0, 0, 0, .3)" }); window.addEventListener("phx:page-loading-start", (_info) => import_topbar.default.show(300)); window.addEventListener("phx:page-loading-stop", (_info) => import_topbar.default.hide()); liveSocket.connect(); liveSocket.enableDebug(); window.liveSocket = liveSocket; })(); /** * @license MIT * topbar 2.0.0, 2023-02-04 * https://buunguyen.github.io/topbar * Copyright (c) 2021 Buu Nguyen */