UNPKG

alpine-turbo-drive-adapter

Version:

Bridge library to enable full support for Alpine components in pages using Turbolinks/Turbo Drive

205 lines (196 loc) 8.8 kB
(function (factory) { typeof define === 'function' && define.amd ? define(factory) : factory(); })((function () { 'use strict'; function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function isValidVersion(required, current) { var requiredArray = required.split('.'); var currentArray = current.split('.'); for (var i = 0; i < requiredArray.length; i++) { if (currentArray[i] && currentArray[i] > requiredArray[i]) { return true; } } return currentArray[requiredArray.length - 1] === requiredArray[requiredArray.length - 1]; } function dispatch(el, name) { var detail = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; el.dispatchEvent(new CustomEvent(name, { detail: detail, bubbles: true, composed: true, cancelable: true })); } var Bridge = /*#__PURE__*/function () { function Bridge() { _classCallCheck(this, Bridge); } return _createClass(Bridge, [{ key: "init", value: function init() { if (!window.Alpine.version || !isValidVersion('3.0.0', window.Alpine.version)) { throw new Error('Invalid Alpine version. Please use Alpine 3.0.0 or above'); } // Tag all cloaked elements on first page load. window.Alpine.mutateDom(function () { document.body.querySelectorAll('[x-cloak]').forEach(function (el) { var _el$getAttribute; el.setAttribute('data-alpine-was-cloaked', (_el$getAttribute = el.getAttribute('x-cloak')) !== null && _el$getAttribute !== void 0 ? _el$getAttribute : ''); }); }); this.configureEventHandlers(); this.monkeyPatchDomSetAttributeToAllowAtSymbols(); } }, { key: "configureEventHandlers", value: function configureEventHandlers() { var renderCallback = function renderCallback(event) { if (event.detail.renderMethod === 'morph') return; if (document.documentElement.hasAttribute('data-turbo-preview')) { return; } dispatch(document, 'alpine:init'); dispatch(document, 'alpine:initializing'); window.Alpine.flushAndStopDeferringMutations(); dispatch(document, 'alpine:initialised'); window.Alpine.mutateDom(function () { document.querySelectorAll('[data-alpine-ignored]').forEach(function (el) { el.removeAttribute('x-ignore'); el.removeAttribute('data-alpine-ignored'); }); }); }; var beforeRenderCallback = function beforeRenderCallback(event) { if (event.detail.renderMethod === 'morph') return; window.Alpine.mutateDom(function () { if (document.documentElement.hasAttribute('data-turbo-preview')) { return; } event.detail.newBody.querySelectorAll('[data-alpine-generated-me],[x-cloak]').forEach(function (el) { if (el.hasAttribute('x-cloak')) { var _el$getAttribute2; el.setAttribute('data-alpine-was-cloaked', (_el$getAttribute2 = el.getAttribute('x-cloak')) !== null && _el$getAttribute2 !== void 0 ? _el$getAttribute2 : ''); } if (el.hasAttribute('data-alpine-generated-me')) { el.removeAttribute('data-alpine-generated-me'); el.remove(); } }); }); window.Alpine.deferMutations(); }; var beforeCacheCallback = function beforeCacheCallback(event) { window.Alpine.mutateDom(function () { document.body.querySelectorAll('[x-for],[x-if],[x-teleport],[data-alpine-was-cloaked]').forEach(function (el) { if (el.hasAttribute('data-alpine-was-cloaked')) { var _el$getAttribute3; el.setAttribute('x-cloak', (_el$getAttribute3 = el.getAttribute('data-alpine-was-cloaked')) !== null && _el$getAttribute3 !== void 0 ? _el$getAttribute3 : ''); el.removeAttribute('data-alpine-was-cloaked'); } if (el.hasAttribute('x-for') && el._x_lookup) { Object.values(el._x_lookup).forEach(function (el) { return el.setAttribute('data-alpine-generated-me', true); }); } if (el.hasAttribute('x-if') && el._x_currentIfEl) { el._x_currentIfEl.setAttribute('data-alpine-generated-me', true); } if (el.hasAttribute('x-teleport') && el._x_teleport) { el._x_teleport.setAttribute('data-alpine-generated-me', true); } }); }); document.querySelectorAll('[data-turbo-permanent]').forEach(function (el) { window.Alpine.mutateDom(function () { if (!el.hasAttribute('x-ignore')) { el.setAttribute('x-ignore', true); el.setAttribute('data-alpine-ignored', true); } el.querySelectorAll('[data-alpine-generated-me]').forEach(function (sub) { sub.removeAttribute('data-alpine-generated-me'); }); }); }); }; // This tricks Alpine into reinitializing a already-initialized // tree, allowing us to avoid destroying the tree first. var beforeMorphElementCallback = function beforeMorphElementCallback(_ref) { var target = _ref.target, newElement = _ref.detail.newElement; if (!newElement && target._x_dataStack) { return window.Alpine.destroyTree(target); } delete target._x_marker; }; var morphElementCallback = function morphElementCallback(_ref2) { var target = _ref2.target, newElement = _ref2.detail.newElement; newElement && target._x_dataStack && window.Alpine.initTree(target); }; document.addEventListener('turbo:render', renderCallback); document.addEventListener('turbo:before-render', beforeRenderCallback); document.addEventListener('turbo:before-cache', beforeCacheCallback); document.addEventListener('turbo:before-morph-element', beforeMorphElementCallback); document.addEventListener('turbo:morph-element', morphElementCallback); } // Taken from https://github.com/alpinejs/alpine/blob/e363181057b3e71e5c03d2b88db576d5094be1c8/packages/morph/src/morph.js#L493 // Turbo/Idiomorph uses Element.setAttribute to morph attributes, which doesn't allow "@" symbols }, { key: "monkeyPatchDomSetAttributeToAllowAtSymbols", value: function monkeyPatchDomSetAttributeToAllowAtSymbols() { var original = Element.prototype.setAttribute; var hostDiv = document.createElement('div'); Element.prototype.setAttribute = function newSetAttribute(name, value) { if (!name.includes('@')) { return original.call(this, name, value); } hostDiv.innerHTML = "<span ".concat(name, "=\"").concat(value, "\"></span>"); var attr = hostDiv.firstElementChild.getAttributeNode(name); hostDiv.firstElementChild.removeAttributeNode(attr); this.setAttributeNode(attr); }; } }]); }(); if (window.Alpine) { console.error('Alpine-turbo-drive-adapter must be included before AlpineJs'); } // Polyfill for legacy browsers if (!Object.getOwnPropertyDescriptor(NodeList.prototype, 'forEach')) { Object.defineProperty(NodeList.prototype, 'forEach', Object.getOwnPropertyDescriptor(Array.prototype, 'forEach')); } document.addEventListener('alpine:init', function () { var bridge = new Bridge(); bridge.init(); }, { once: true }); }));