Comparing version 1.7.0 to 1.8.0
@@ -1,2 +0,2 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).Alpine=t()}(this,(function(){"use strict";function e(){return navigator.userAgent.includes("Node.js")||navigator.userAgent.includes("jsdom")}function t(e,i,n=!0){if(e.hasAttribute("x-data")&&!n)return;i(e);let a=e.firstElementChild;for(;a;)t(a,i,!1),a=a.nextElementSibling}function i(e,t,i={}){return new Function(["$data",...Object.keys(i)],`var result; with($data) { result = ${e} }; return result`)(t,...Object.values(i))}function n(e,t,i={}){return new Function(["dataContext",...Object.keys(i)],`with(dataContext) { ${e} }`)(t,...Object.values(i))}function a(e){const t=r(e.name);return/x-(on|bind|data|text|html|model|if|show|cloak|transition|ref)/.test(t)}function s(e,t){return Array.from(e.attributes).filter(a).map(e=>{const t=r(e.name),i=t.match(/x-(on|bind|data|text|html|model|if|show|cloak|transition|ref)/),n=t.match(/:([a-zA-Z\-]+)/),a=t.match(/\.[^.\]]+(?=[^\]]*$)/g)||[];return{type:i?i[1]:null,value:n?n[1]:null,modifiers:a.map(e=>e.replace(".","")),expression:e.value}}).filter(e=>!t||e.type===t)}function r(e){return e.startsWith("@")?e.replace("@","x-on:"):e.startsWith(":")?e.replace(":","x-bind:"):e}function o(e,t,i=!1){i&&t();const n=s(e,"transition");n.length<1&&t(),u(e,(n.find(e=>"enter"===e.value)||{expression:""}).expression.split(" ").filter(e=>""!==e),(n.find(e=>"enter-start"===e.value)||{expression:""}).expression.split(" ").filter(e=>""!==e),(n.find(e=>"enter-end"===e.value)||{expression:""}).expression.split(" ").filter(e=>""!==e),t,()=>{})}function l(e,t,i=!1){i&&t();const n=s(e,"transition");n.length<1&&t(),u(e,(n.find(e=>"leave"===e.value)||{expression:""}).expression.split(" ").filter(e=>""!==e),(n.find(e=>"leave-start"===e.value)||{expression:""}).expression.split(" ").filter(e=>""!==e),(n.find(e=>"leave-end"===e.value)||{expression:""}).expression.split(" ").filter(e=>""!==e),()=>{},t)}function u(e,t,i,n,a,s){e.classList.add(...i),e.classList.add(...t),requestAnimationFrame(()=>{const r=1e3*Number(getComputedStyle(e).transitionDuration.replace("s",""));a(),requestAnimationFrame(()=>{e.classList.remove(...i),e.classList.add(...n),setTimeout(()=>{s(),e.isConnected&&(e.classList.remove(...t),e.classList.remove(...n))},r)})})}class c{constructor(e){this.$el=e;const t=this.$el.getAttribute("x-data"),a=""===t?"{}":t,s=this.$el.getAttribute("x-init"),r=this.$el.getAttribute("x-created"),o=this.$el.getAttribute("x-mounted"),l=i(a,{});var u;this.$data=this.wrapDataInObservable(l),Object.keys(l).forEach(e=>{"function"==typeof l[e]&&(l[e]=l[e].bind(this.$data))}),l.$el=this.$el,l.$refs=this.getRefsProxy(),l.$nextTick=e=>{this.delayRunByATick(e)},this.tickStack=[],this.collectingTickCallbacks=!1,s&&(this.pauseReactivity=!0,u=i(this.$el.getAttribute("x-init"),this.$data),this.pauseReactivity=!1),r&&(console.warn('AlpineJS Warning: "x-created" is depricated and will be removed in the next major version. Use "x-init" instead.'),this.pauseReactivity=!0,n(this.$el.getAttribute("x-created"),this.$data),this.pauseReactivity=!1),this.initializeElements(),this.listenForNewElementsToInitialize(),"function"==typeof u&&u.call(this.$data),o&&(console.warn('AlpineJS Warning: "x-mounted" is depricated and will be removed in the next major version. Use "x-init" (with a callback return) for the same behavior.'),n(o,this.$data))}wrapDataInObservable(e){this.concernedData=[];var t=this;const i=e=>({set(i,n,a){const s=e?`${e}.${n}`:n,r=Reflect.set(i,n,a);if(!t.pauseReactivity)return-1===t.concernedData.indexOf(s)&&t.concernedData.push(s),t.refresh(),r},get(t,n){if("isProxy"===n)return!0;if(t[n]&&t[n].isProxy)return t[n];if(t[n]&&t[n]instanceof Node)return t[n];if("object"==typeof t[n]&&null!==t[n]){const a=e?`${e}.${n}`:n;return new Proxy(t[n],i(a))}return t[n]}});return new Proxy(e,i())}delayRunByATick(e){this.collectingTickCallbacks?this.tickStack.push(e):e()}startTick(){this.collectingTickCallbacks=!0}clearAndEndTick(){this.tickStack.forEach(e=>e()),this.tickStack=[],this.collectingTickCallbacks=!1}initializeElements(){t(this.$el,e=>{this.initializeElement(e)})}initializeElement(e){s(e).forEach(({type:t,value:i,modifiers:n,expression:a})=>{switch(t){case"on":var s=i;this.registerListener(e,s,n,a);break;case"model":s="select"===e.tagName.toLowerCase()||["checkbox","radio"].includes(e.type)||n.includes("lazy")?"change":"input";const t=this.generateExpressionForXModelListener(e,n,a);this.registerListener(e,s,n,t);var r="value",{output:o}=this.evaluateReturnExpression(a);this.updateAttributeValue(e,r,o);break;case"bind":r=i;var{output:o}=this.evaluateReturnExpression(a);this.updateAttributeValue(e,r,o);break;case"text":var{output:o}=this.evaluateReturnExpression(a);this.updateTextValue(e,o);break;case"html":var{output:o}=this.evaluateReturnExpression(a);this.updateHtmlValue(e,o);break;case"show":var{output:o}=this.evaluateReturnExpression(a);this.updateVisibility(e,o,!0);break;case"if":var{output:o}=this.evaluateReturnExpression(a);this.updatePresence(e,o);break;case"cloak":e.removeAttribute("x-cloak")}})}listenForNewElementsToInitialize(){const e=this.$el;new MutationObserver(e=>{for(let t=0;t<e.length;t++){if(!e[t].target.closest("[x-data]").isSameNode(this.$el))return;if("attributes"===e[t].type&&"x-data"===e[t].attributeName){const n=i(e[t].target.getAttribute("x-data"),{});Object.keys(n).forEach(e=>{this.$data[e]!==n[e]&&(this.$data[e]=n[e])})}e[t].addedNodes.length>0&&e[t].addedNodes.forEach(e=>{1===e.nodeType&&(e.matches("[x-data]")||s(e).length>0&&this.initializeElement(e))})}}).observe(e,{childList:!0,attributes:!0,subtree:!0})}refresh(){var e=this;const i={model:({el:t,output:i})=>{e.updateAttributeValue(t,"value",i)},bind:({el:t,attrName:i,output:n})=>{e.updateAttributeValue(t,i,n)},text:({el:t,output:i})=>{e.updateTextValue(t,i)},html:({el:t,output:i})=>{e.updateHtmlValue(t,i)},show:({el:t,output:i})=>{e.updateVisibility(t,i)},if:({el:t,output:i})=>{e.updatePresence(t,i)}};var n,a,r,o;this.startTick(),(n=(i,n)=>{t(i,n),e.concernedData=[],e.clearAndEndTick()},a=5,function(){var e=this,t=arguments,i=function(){o=null,r||n.apply(e,t)},s=r&&!o;clearTimeout(o),o=setTimeout(i,a),s&&n.apply(e,t)})(this.$el,(function(t){s(t).forEach(({type:n,value:a,expression:s})=>{if(i[n]){var{output:r,deps:o}=e.evaluateReturnExpression(s);e.concernedData.filter(e=>o.includes(e)).length>0&&i[n]({el:t,attrName:a,output:r})}})}))}generateExpressionForXModelListener(e,t,i){var n="";return n="checkbox"===e.type?Array.isArray(this.$data[i])?`$event.target.checked ? ${i}.concat([$event.target.value]) : ${i}.filter(i => i !== $event.target.value)`:"$event.target.checked":"select"===e.tagName.toLowerCase()&&e.multiple?t.includes("number")?"Array.from($event.target.selectedOptions).map(option => { return parseFloat(option.value || option.text) })":"Array.from($event.target.selectedOptions).map(option => { return option.value || option.text })":t.includes("number")?"parseFloat($event.target.value)":t.includes("trim")?"$event.target.value.trim()":"$event.target.value","radio"===e.type&&(e.hasAttribute("name")||e.setAttribute("name",i)),`${i} = ${n}`}registerListener(e,t,i,n){if(i.includes("away")){const a=s=>{e.contains(s.target)||e.offsetWidth<1&&e.offsetHeight<1||(this.runListenerHandler(n,s),i.includes("once")&&document.removeEventListener(t,a))};document.addEventListener(t,a)}else{const a=i.includes("window")?window:i.includes("document")?document:e,s=e=>{const r=i.filter(e=>"window"!==e).filter(e=>"document"!==e);"keydown"===t&&r.length>0&&!r.includes(e.key.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[_\s]/,"-").toLowerCase())||(i.includes("prevent")&&e.preventDefault(),i.includes("stop")&&e.stopPropagation(),this.runListenerHandler(n,e),i.includes("once")&&a.removeEventListener(t,s))};a.addEventListener(t,s)}}runListenerHandler(e,t){this.evaluateCommandExpression(e,{$event:t})}evaluateReturnExpression(e){var t=[];const n=e=>({get(i,a){if("symbol"==typeof a)return;const s=e?`${e}.${a}`:a;return"object"!=typeof i[a]||null===i[a]||Array.isArray(i[a])?(t.push(s),i[a]):new Proxy(i[a],n(s))}});return{output:i(e,new Proxy(this.$data,n())),deps:t}}evaluateCommandExpression(e,t){n(e,this.$data,t)}updateTextValue(e,t){e.innerText=t}updateHtmlValue(e,t){e.innerHTML=t}updateVisibility(e,t,i=!1){t?o(e,()=>{1===e.style.length&&""!==e.style.display?e.removeAttribute("style"):e.style.removeProperty("display")},i):l(e,()=>{e.style.display="none"},i)}updatePresence(e,t){"template"!==e.nodeName.toLowerCase()&&console.warn("Alpine: [x-if] directive should only be added to <template> tags.");const i=e.nextElementSibling&&!0===e.nextElementSibling.__x_inserted_me;if(t&&!i){const t=document.importNode(e.content,!0);e.parentElement.insertBefore(t,e.nextElementSibling),e.nextElementSibling.__x_inserted_me=!0,o(e.nextElementSibling,()=>{})}else!t&&i&&l(e.nextElementSibling,()=>{e.nextElementSibling.remove()})}updateAttributeValue(e,t,i){if("value"===t)if("radio"===e.type)e.checked=e.value==i;else if("checkbox"===e.type)if(Array.isArray(i)){let t=!1;i.forEach(i=>{i==e.value&&(t=!0)}),e.checked=t}else e.checked=!!i;else"SELECT"===e.tagName?this.updateSelect(e,i):e.value=i;else"class"===t?"string"==typeof i?e.setAttribute("class",i):Array.isArray(i)?e.setAttribute("class",i.join(" ")):Object.keys(i).forEach(t=>{i[t]?t.split(" ").forEach(t=>e.classList.add(t)):t.split(" ").forEach(t=>e.classList.remove(t))}):["disabled","readonly","required","checked","hidden"].includes(t)?i?e.setAttribute(t,""):e.removeAttribute(t):e.setAttribute(t,i)}updateSelect(e,t){const i=[].concat(t).map(e=>e+"");Array.from(e.options).forEach(e=>{e.selected=i.includes(e.value||e.text)})}getRefsProxy(){var e=this;return new Proxy({},{get(i,n){return"isProxy"===n||(t(e.$el,e=>{e.hasAttribute("x-ref")&&e.getAttribute("x-ref")===n&&(a=e)}),a);var a}})}}const d={start:async function(){e()||await new Promise(e=>{"loading"==document.readyState?document.addEventListener("DOMContentLoaded",e):e()}),this.discoverComponents(e=>{this.initializeComponent(e)}),document.addEventListener("turbolinks:load",()=>{this.discoverUninitializedComponents(e=>{this.initializeComponent(e)})}),this.listenForNewUninitializedComponentsAtRunTime(e=>{this.initializeComponent(e)})},discoverComponents:function(e){document.querySelectorAll("[x-data]").forEach(t=>{e(t)})},discoverUninitializedComponents:function(e){const t=document.querySelectorAll("[x-data]");Array.from(t).filter(e=>void 0===e.__x).forEach(t=>{e(t)})},listenForNewUninitializedComponentsAtRunTime:function(e){const t=document.querySelector("body");new MutationObserver(t=>{for(let i=0;i<t.length;i++)t[i].addedNodes.length>0&&t[i].addedNodes.forEach(t=>{1===t.nodeType&&t.matches("[x-data]")&&e(t)})}).observe(t,{childList:!0,attributes:!0,subtree:!0})},initializeComponent:function(e){e.__x=new c(e)}};return e()||(window.Alpine=d,window.Alpine.start()),d})); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).Alpine=t()}(this,(function(){"use strict";function e(e){for(var t=e.concat(),i=0;i<t.length;++i)for(var n=i+1;n<t.length;++n)t[i]===t[n]&&t.splice(n--,1);return t}function t(){return navigator.userAgent.includes("Node.js")||navigator.userAgent.includes("jsdom")}function i(e,t,n=!0){if(e.hasAttribute("x-data")&&!n)return;t(e);let s=e.firstElementChild;for(;s;)i(s,t,!1),s=s.nextElementSibling}function n(e,t,i={}){return new Function(["$data",...Object.keys(i)],`var result; with($data) { result = ${e} }; return result`)(t,...Object.values(i))}function s(e,t,i={}){return new Function(["dataContext",...Object.keys(i)],`with(dataContext) { ${e} }`)(t,...Object.values(i))}function a(e){const t=o(e.name);return/x-(on|bind|data|text|html|model|if|show|cloak|transition|ref)/.test(t)}function r(e,t){return Array.from(e.attributes).filter(a).map(e=>{const t=o(e.name),i=t.match(/x-(on|bind|data|text|html|model|if|show|cloak|transition|ref)/),n=t.match(/:([a-zA-Z\-:]+)/),s=t.match(/\.[^.\]]+(?=[^\]]*$)/g)||[];return{type:i?i[1]:null,value:n?n[1]:null,modifiers:s.map(e=>e.replace(".","")),expression:e.value}}).filter(e=>!t||e.type===t)}function o(e){return e.startsWith("@")?e.replace("@","x-on:"):e.startsWith(":")?e.replace(":","x-bind:"):e}function l(e,t,i=!1){i&&t();const n=r(e,"transition");n.length<1&&t(),u(e,(n.find(e=>"enter"===e.value)||{expression:""}).expression.split(" ").filter(e=>""!==e),(n.find(e=>"enter-start"===e.value)||{expression:""}).expression.split(" ").filter(e=>""!==e),(n.find(e=>"enter-end"===e.value)||{expression:""}).expression.split(" ").filter(e=>""!==e),t,()=>{})}function c(e,t,i=!1){i&&t();const n=r(e,"transition");n.length<1&&t(),u(e,(n.find(e=>"leave"===e.value)||{expression:""}).expression.split(" ").filter(e=>""!==e),(n.find(e=>"leave-start"===e.value)||{expression:""}).expression.split(" ").filter(e=>""!==e),(n.find(e=>"leave-end"===e.value)||{expression:""}).expression.split(" ").filter(e=>""!==e),()=>{},t)}function u(e,t,i,n,s,a){e.classList.add(...i),e.classList.add(...t),requestAnimationFrame(()=>{const r=1e3*Number(getComputedStyle(e).transitionDuration.replace("s",""));s(),requestAnimationFrame(()=>{e.classList.remove(...i),e.classList.add(...n),setTimeout(()=>{a(),e.isConnected&&(e.classList.remove(...t),e.classList.remove(...n))},r)})})}class d{constructor(e){this.$el=e;const t=this.$el.getAttribute("x-data"),i=""===t?"{}":t,a=this.$el.getAttribute("x-init"),r=this.$el.getAttribute("x-created"),o=this.$el.getAttribute("x-mounted"),l=n(i,{});var c;this.$data=this.wrapDataInObservable(l),l.$el=this.$el,l.$refs=this.getRefsProxy(),this.nextTickStack=[],l.$nextTick=e=>{this.nextTickStack.push(e)},a&&(this.pauseReactivity=!0,c=n(this.$el.getAttribute("x-init"),this.$data),this.pauseReactivity=!1),r&&(console.warn('AlpineJS Warning: "x-created" is deprecated and will be removed in the next major version. Use "x-init" instead.'),this.pauseReactivity=!0,s(this.$el.getAttribute("x-created"),this.$data),this.pauseReactivity=!1),this.initializeElements(),this.listenForNewElementsToInitialize(),"function"==typeof c&&c.call(this.$data),o&&(console.warn('AlpineJS Warning: "x-mounted" is deprecated and will be removed in the next major version. Use "x-init" (with a callback return) for the same behavior.'),s(o,this.$data))}wrapDataInObservable(e){var t=this;const i={set(e,i,n){const s=Reflect.set(e,i,n);var a,r,o;if(!t.pauseReactivity)return(a=()=>{for(t.refresh();t.nextTickStack.length>0;)t.nextTickStack.shift()()},r=0,function(){var e=this,t=arguments,i=function(){o=null,a.apply(e,t)};clearTimeout(o),o=setTimeout(i,r)})(),s},get:(e,t)=>e[t]&&e[t].isRefsProxy?e[t]:e[t]&&e[t]instanceof Node?e[t]:"object"==typeof e[t]&&null!==e[t]?new Proxy(e[t],i):e[t]};return new Proxy(e,i)}initializeElements(){i(this.$el,e=>{this.initializeElement(e)})}initializeElement(e){e.hasAttribute("class")&&r(e).length>0&&(e.__originalClasses=e.getAttribute("class").split(" ")),this.registerListeners(e),this.resolveBoundAttributes(e,!0)}registerListeners(e){r(e).forEach(({type:t,value:i,modifiers:n,expression:s})=>{switch(t){case"on":var a=i;this.registerListener(e,a,n,s);break;case"model":a="select"===e.tagName.toLowerCase()||["checkbox","radio"].includes(e.type)||n.includes("lazy")?"change":"input";const t=this.generateExpressionForXModelListener(e,n,s);this.registerListener(e,a,n,t)}})}resolveBoundAttributes(e,t=!1){r(e).forEach(({type:i,value:n,modifiers:s,expression:a})=>{switch(i){case"model":var r="value",o=this.evaluateReturnExpression(a);this.updateAttributeValue(e,r,o);break;case"bind":r=n,o=this.evaluateReturnExpression(a);this.updateAttributeValue(e,r,o);break;case"text":o=this.evaluateReturnExpression(a);this.updateTextValue(e,o);break;case"html":o=this.evaluateReturnExpression(a);this.updateHtmlValue(e,o);break;case"show":o=this.evaluateReturnExpression(a);this.updateVisibility(e,o,t);break;case"if":o=this.evaluateReturnExpression(a);this.updatePresence(e,o);break;case"cloak":e.removeAttribute("x-cloak")}})}listenForNewElementsToInitialize(){const e=this.$el;new MutationObserver(e=>{for(let t=0;t<e.length;t++){if(!e[t].target.closest("[x-data]").isSameNode(this.$el))return;if("attributes"===e[t].type&&"x-data"===e[t].attributeName){const i=n(e[t].target.getAttribute("x-data"),{});Object.keys(i).forEach(e=>{this.$data[e]!==i[e]&&(this.$data[e]=i[e])})}e[t].addedNodes.length>0&&e[t].addedNodes.forEach(e=>{1===e.nodeType&&(e.matches("[x-data]")||r(e).length>0&&this.initializeElement(e))})}}).observe(e,{childList:!0,attributes:!0,subtree:!0})}refresh(){i(this.$el,e=>{this.resolveBoundAttributes(e)})}generateExpressionForXModelListener(e,t,i){var n="";return n="checkbox"===e.type?Array.isArray(this.$data[i])?`$event.target.checked ? ${i}.concat([$event.target.value]) : ${i}.filter(i => i !== $event.target.value)`:"$event.target.checked":"select"===e.tagName.toLowerCase()&&e.multiple?t.includes("number")?"Array.from($event.target.selectedOptions).map(option => { return parseFloat(option.value || option.text) })":"Array.from($event.target.selectedOptions).map(option => { return option.value || option.text })":t.includes("number")?"parseFloat($event.target.value)":t.includes("trim")?"$event.target.value.trim()":"$event.target.value","radio"===e.type&&(e.hasAttribute("name")||e.setAttribute("name",i)),`${i} = ${n}`}registerListener(e,t,i,n){if(i.includes("away")){const s=a=>{e.contains(a.target)||e.offsetWidth<1&&e.offsetHeight<1||(this.runListenerHandler(n,a),i.includes("once")&&document.removeEventListener(t,s))};document.addEventListener(t,s)}else{const s=i.includes("window")?window:i.includes("document")?document:e,a=e=>{const r=i.filter(e=>"window"!==e).filter(e=>"document"!==e);"keydown"===t&&r.length>0&&!r.includes(function(e){switch(e){case" ":case"Spacebar":return"space";default:return e.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[_\s]/,"-").toLowerCase()}}(e.key))||(i.includes("prevent")&&e.preventDefault(),i.includes("stop")&&e.stopPropagation(),this.runListenerHandler(n,e),i.includes("once")&&s.removeEventListener(t,a))};s.addEventListener(t,a)}}runListenerHandler(e,t){this.evaluateCommandExpression(e,{$event:t})}evaluateReturnExpression(e){return n(e,this.$data)}evaluateCommandExpression(e,t){s(e,this.$data,t)}updateTextValue(e,t){e.innerText=t}updateHtmlValue(e,t){e.innerHTML=t}updateVisibility(e,t,i=!1){t?l(e,()=>{1===e.style.length&&""!==e.style.display?e.removeAttribute("style"):e.style.removeProperty("display")},i):c(e,()=>{e.style.display="none"},i)}updatePresence(e,t){"template"!==e.nodeName.toLowerCase()&&console.warn("Alpine: [x-if] directive should only be added to <template> tags.");const i=e.nextElementSibling&&!0===e.nextElementSibling.__x_inserted_me;if(t&&!i){const t=document.importNode(e.content,!0);e.parentElement.insertBefore(t,e.nextElementSibling),e.nextElementSibling.__x_inserted_me=!0,l(e.nextElementSibling,()=>{})}else!t&&i&&c(e.nextElementSibling,()=>{e.nextElementSibling.remove()})}updateAttributeValue(t,i,n){if("value"===i)if("radio"===t.type)t.checked=t.value==n;else if("checkbox"===t.type)if(Array.isArray(n)){let e=!1;n.forEach(i=>{i==t.value&&(e=!0)}),t.checked=e}else t.checked=!!n;else"SELECT"===t.tagName?this.updateSelect(t,n):t.value=n;else if("class"===i)if(Array.isArray(n)){const i=t.__originalClasses||[];t.setAttribute("class",e(i.concat(n)).join(" "))}else if("object"==typeof n)Object.keys(n).forEach(e=>{n[e]?e.split(" ").forEach(e=>t.classList.add(e)):e.split(" ").forEach(e=>t.classList.remove(e))});else{const i=t.__originalClasses||[],s=n.split(" ");t.setAttribute("class",e(i.concat(s)).join(" "))}else["disabled","readonly","required","checked","hidden"].includes(i)?n?t.setAttribute(i,""):t.removeAttribute(i):t.setAttribute(i,n)}updateSelect(e,t){const i=[].concat(t).map(e=>e+"");Array.from(e.options).forEach(e=>{e.selected=i.includes(e.value||e.text)})}getRefsProxy(){var e=this;return new Proxy({},{get(t,n){return"isRefsProxy"===n||(i(e.$el,e=>{e.hasAttribute("x-ref")&&e.getAttribute("x-ref")===n&&(s=e)}),s);var s}})}}const h={start:async function(){t()||await new Promise(e=>{"loading"==document.readyState?document.addEventListener("DOMContentLoaded",e):e()}),this.discoverComponents(e=>{this.initializeComponent(e)}),document.addEventListener("turbolinks:load",()=>{this.discoverUninitializedComponents(e=>{this.initializeComponent(e)})}),this.listenForNewUninitializedComponentsAtRunTime(e=>{this.initializeComponent(e)})},discoverComponents:function(e){document.querySelectorAll("[x-data]").forEach(t=>{e(t)})},discoverUninitializedComponents:function(e){const t=document.querySelectorAll("[x-data]");Array.from(t).filter(e=>void 0===e.__x).forEach(t=>{e(t)})},listenForNewUninitializedComponentsAtRunTime:function(e){const t=document.querySelector("body");new MutationObserver(t=>{for(let i=0;i<t.length;i++)t[i].addedNodes.length>0&&t[i].addedNodes.forEach(t=>{1===t.nodeType&&t.matches("[x-data]")&&e(t)})}).observe(t,{childList:!0,attributes:!0,subtree:!0})},initializeComponent:function(e){e.__x=new d(e)}};return t()||(window.Alpine=h,window.Alpine.start()),h})); | ||
//# sourceMappingURL=alpine.js.map |
{ | ||
"main": "dist/alpine.js", | ||
"name": "alpinejs", | ||
"version": "1.7.0", | ||
"version": "1.8.0", | ||
"repository": { | ||
@@ -6,0 +6,0 @@ "type": "git", |
@@ -17,3 +17,3 @@ # Alpine.js | ||
```html | ||
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v1.7.0/dist/alpine.js" defer></script> | ||
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v1.8.0/dist/alpine.js" defer></script> | ||
``` | ||
@@ -20,0 +20,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { walkSkippingNestedComponents, kebabCase, saferEval, saferEvalNoReturn, getXAttrs, debounce, transitionIn, transitionOut } from './utils' | ||
import { arrayUnique, walkSkippingNestedComponents, keyToModifier, saferEval, saferEvalNoReturn, getXAttrs, debounce, transitionIn, transitionOut } from './utils' | ||
@@ -18,10 +18,2 @@ export default class Component { | ||
// Walk through the raw data and set the "this" context of any functions | ||
// to the observable, so data manipulations are reactive. | ||
Object.keys(unobservedData).forEach(key => { | ||
if (typeof unobservedData[key] === 'function') { | ||
unobservedData[key] = unobservedData[key].bind(this.$data) | ||
} | ||
}) | ||
// After making user-supplied data methods reactive, we can now add | ||
@@ -31,10 +23,8 @@ // our magic properties to the original data for access. | ||
unobservedData.$refs = this.getRefsProxy() | ||
this.nextTickStack = [] | ||
unobservedData.$nextTick = (callback) => { | ||
this.delayRunByATick(callback) | ||
this.nextTickStack.push(callback) | ||
} | ||
// For $nextTick(). | ||
this.tickStack = [] | ||
this.collectingTickCallbacks = false | ||
var initReturnedCallback | ||
@@ -50,3 +40,3 @@ if (initExpression) { | ||
if (createdExpression) { | ||
console.warn('AlpineJS Warning: "x-created" is depricated and will be removed in the next major version. Use "x-init" instead.') | ||
console.warn('AlpineJS Warning: "x-created" is deprecated and will be removed in the next major version. Use "x-init" instead.') | ||
this.pauseReactivity = true | ||
@@ -71,3 +61,3 @@ saferEvalNoReturn(this.$el.getAttribute('x-created'), this.$data) | ||
if (mountedExpression) { | ||
console.warn('AlpineJS Warning: "x-mounted" is depricated and will be removed in the next major version. Use "x-init" (with a callback return) for the same behavior.') | ||
console.warn('AlpineJS Warning: "x-mounted" is deprecated and will be removed in the next major version. Use "x-init" (with a callback return) for the same behavior.') | ||
// Run an "x-mounted" hook to allow the user to do stuff after | ||
@@ -80,10 +70,6 @@ // Alpine's got it's grubby little paws all over everything. | ||
wrapDataInObservable(data) { | ||
this.concernedData = [] | ||
var self = this | ||
const proxyHandler = keyPrefix => ({ | ||
const proxyHandler = { | ||
set(obj, property, value) { | ||
const propertyName = keyPrefix ? `${keyPrefix}.${property}` : property | ||
const setWasSuccessful = Reflect.set(obj, property, value) | ||
@@ -94,7 +80,10 @@ | ||
if (self.concernedData.indexOf(propertyName) === -1) { | ||
self.concernedData.push(propertyName) | ||
} | ||
debounce(() => { | ||
self.refresh() | ||
self.refresh() | ||
// Walk through the $nextTick stack and clear it as we go. | ||
while (self.nextTickStack.length > 0) { | ||
self.nextTickStack.shift()() | ||
} | ||
}, 0)() | ||
@@ -104,8 +93,5 @@ return setWasSuccessful | ||
get(target, key) { | ||
// This is because there is no way to do something like `typeof foo === 'Proxy'`. | ||
if (key === 'isProxy') return true | ||
// If the property we are trying to get is a proxy, just return it. | ||
// Like in the case of $refs | ||
if (target[key] && target[key].isProxy) return target[key] | ||
if (target[key] && target[key].isRefsProxy) return target[key] | ||
@@ -116,6 +102,5 @@ // If property is a DOM node, just return it. (like in the case of this.$el) | ||
// If accessing a nested property, retur this proxy recursively. | ||
// This enables reactivity on setting nested data. | ||
if (typeof target[key] === 'object' && target[key] !== null) { | ||
const propertyName = keyPrefix ? `${keyPrefix}.${key}` : key | ||
return new Proxy(target[key], proxyHandler(propertyName)) | ||
return new Proxy(target[key], proxyHandler) | ||
} | ||
@@ -126,26 +111,7 @@ | ||
} | ||
}) | ||
return new Proxy(data, proxyHandler()) | ||
} | ||
delayRunByATick(callback) { | ||
if (this.collectingTickCallbacks) { | ||
this.tickStack.push(callback) | ||
} else { | ||
callback() | ||
} | ||
} | ||
startTick() { | ||
this.collectingTickCallbacks = true | ||
return new Proxy(data, proxyHandler) | ||
} | ||
clearAndEndTick() { | ||
this.tickStack.forEach(callable => callable()) | ||
this.tickStack = [] | ||
this.collectingTickCallbacks = false | ||
} | ||
initializeElements() { | ||
@@ -158,2 +124,13 @@ walkSkippingNestedComponents(this.$el, el => { | ||
initializeElement(el) { | ||
// To support class attribute merging, we have to know what the element's | ||
// original class attribute looked like for reference. | ||
if (el.hasAttribute('class') && getXAttrs(el).length > 0) { | ||
el.__originalClasses = el.getAttribute('class').split(' ') | ||
} | ||
this.registerListeners(el) | ||
this.resolveBoundAttributes(el, true) | ||
} | ||
registerListeners(el) { | ||
getXAttrs(el).forEach(({ type, value, modifiers, expression }) => { | ||
@@ -177,5 +154,15 @@ switch (type) { | ||
this.registerListener(el, event, modifiers, listenerExpression) | ||
break; | ||
default: | ||
break; | ||
} | ||
}) | ||
} | ||
resolveBoundAttributes(el, initialUpdate = false) { | ||
getXAttrs(el).forEach(({ type, value, modifiers, expression }) => { | ||
switch (type) { | ||
case 'model': | ||
var attrName = 'value' | ||
var { output } = this.evaluateReturnExpression(expression) | ||
var output = this.evaluateReturnExpression(expression) | ||
this.updateAttributeValue(el, attrName, output) | ||
@@ -186,3 +173,3 @@ break; | ||
var attrName = value | ||
var { output } = this.evaluateReturnExpression(expression) | ||
var output = this.evaluateReturnExpression(expression) | ||
this.updateAttributeValue(el, attrName, output) | ||
@@ -192,3 +179,3 @@ break; | ||
case 'text': | ||
var { output } = this.evaluateReturnExpression(expression) | ||
var output = this.evaluateReturnExpression(expression) | ||
this.updateTextValue(el, output) | ||
@@ -198,3 +185,3 @@ break; | ||
case 'html': | ||
var { output } = this.evaluateReturnExpression(expression) | ||
var output = this.evaluateReturnExpression(expression) | ||
this.updateHtmlValue(el, output) | ||
@@ -204,8 +191,8 @@ break; | ||
case 'show': | ||
var { output } = this.evaluateReturnExpression(expression) | ||
this.updateVisibility(el, output, true) | ||
var output = this.evaluateReturnExpression(expression) | ||
this.updateVisibility(el, output, initialUpdate) | ||
break; | ||
case 'if': | ||
var { output } = this.evaluateReturnExpression(expression) | ||
var output = this.evaluateReturnExpression(expression) | ||
this.updatePresence(el, output) | ||
@@ -266,32 +253,4 @@ break; | ||
refresh() { | ||
var self = this | ||
const actionByDirectiveType = { | ||
'model': ({el, output}) => { self.updateAttributeValue(el, 'value', output) }, | ||
'bind': ({el, attrName, output}) => { self.updateAttributeValue(el, attrName, output) }, | ||
'text': ({el, output}) => { self.updateTextValue(el, output) }, | ||
'html': ({el, output}) => { self.updateHtmlValue(el, output) }, | ||
'show': ({el, output}) => { self.updateVisibility(el, output) }, | ||
'if': ({el, output}) => { self.updatePresence(el, output) }, | ||
} | ||
const walkThenClearDependancyTracker = (rootEl, callback) => { | ||
walkSkippingNestedComponents(rootEl, callback) | ||
self.concernedData = [] | ||
self.clearAndEndTick() | ||
} | ||
this.startTick() | ||
debounce(walkThenClearDependancyTracker, 5)(this.$el, function (el) { | ||
getXAttrs(el).forEach(({ type, value, expression }) => { | ||
if (! actionByDirectiveType[type]) return | ||
var { output, deps } = self.evaluateReturnExpression(expression) | ||
if (self.concernedData.filter(i => deps.includes(i)).length > 0) { | ||
(actionByDirectiveType[type])({ el, attrName: value, output }) | ||
} | ||
}) | ||
walkSkippingNestedComponents(this.$el, el => { | ||
this.resolveBoundAttributes(el) | ||
}) | ||
@@ -357,3 +316,3 @@ } | ||
if (event === 'keydown' && modifiersWithoutWindowOrDocument.length > 0 && ! modifiersWithoutWindowOrDocument.includes(kebabCase(e.key))) return | ||
if (event === 'keydown' && modifiersWithoutWindowOrDocument.length > 0 && ! modifiersWithoutWindowOrDocument.includes(keyToModifier(e.key))) return | ||
@@ -381,32 +340,3 @@ if (modifiers.includes('prevent')) e.preventDefault() | ||
evaluateReturnExpression(expression) { | ||
var affectedDataKeys = [] | ||
const proxyHandler = prefix => ({ | ||
get(object, prop) { | ||
// Sometimes non-proxyable values are accessed. These are of type "symbol". | ||
// We can ignore them. | ||
if (typeof prop === 'symbol') return | ||
const propertyName = prefix ? `${prefix}.${prop}` : prop | ||
// If we are accessing an object prop, we'll make this proxy recursive to build | ||
// a nested dependancy key. | ||
if (typeof object[prop] === 'object' && object[prop] !== null && ! Array.isArray(object[prop])) { | ||
return new Proxy(object[prop], proxyHandler(propertyName)) | ||
} | ||
affectedDataKeys.push(propertyName) | ||
return object[prop] | ||
} | ||
}) | ||
const proxiedData = new Proxy(this.$data, proxyHandler()) | ||
const result = saferEval(expression, proxiedData) | ||
return { | ||
output: result, | ||
deps: affectedDataKeys | ||
} | ||
return saferEval(expression, this.$data) | ||
} | ||
@@ -488,8 +418,6 @@ | ||
} else if (attrName === 'class') { | ||
if (typeof value === 'string') { | ||
el.setAttribute('class', value) | ||
} else if (Array.isArray(value)) { | ||
el.setAttribute('class', value.join(' ')) | ||
} else { | ||
// Use the class object syntax that vue uses to toggle them. | ||
if (Array.isArray(value)) { | ||
const originalClasses = el.__originalClasses || [] | ||
el.setAttribute('class', arrayUnique(originalClasses.concat(value)).join(' ')) | ||
} else if (typeof value === 'object') { | ||
Object.keys(value).forEach(classNames => { | ||
@@ -502,2 +430,6 @@ if (value[classNames]) { | ||
}) | ||
} else { | ||
const originalClasses = el.__originalClasses || [] | ||
const newClasses = value.split(' ') | ||
el.setAttribute('class', arrayUnique(originalClasses.concat(newClasses)).join(' ')) | ||
} | ||
@@ -533,3 +465,3 @@ } else if (['disabled', 'readonly', 'required', 'checked', 'hidden'].includes(attrName)) { | ||
get(object, property) { | ||
if (property === 'isProxy') return true | ||
if (property === 'isRefsProxy') return true | ||
@@ -536,0 +468,0 @@ var ref |
@@ -14,2 +14,14 @@ | ||
export function arrayUnique(array) { | ||
var a = array.concat(); | ||
for(var i=0; i<a.length; ++i) { | ||
for(var j=i+1; j<a.length; ++j) { | ||
if(a[i] === a[j]) | ||
a.splice(j--, 1); | ||
} | ||
} | ||
return a; | ||
} | ||
export function isTesting() { | ||
@@ -24,2 +36,12 @@ return navigator.userAgent, navigator.userAgent.includes("Node.js") | ||
export function keyToModifier(key) { | ||
switch (key) { | ||
case ' ': | ||
case 'Spacebar': | ||
return 'space' | ||
default: | ||
return kebabCase(key) | ||
} | ||
} | ||
export function walkSkippingNestedComponents(el, callback, isRoot = true) { | ||
@@ -39,19 +61,13 @@ if (el.hasAttribute('x-data') && ! isRoot) return | ||
export function debounce(func, wait, immediate) { | ||
var timeout; | ||
export function debounce(func, wait) { | ||
var timeout | ||
return function () { | ||
var context = this, args = arguments; | ||
var context = this, args = arguments | ||
var later = function () { | ||
timeout = null; | ||
if (!immediate) func.apply(context, args); | ||
}; | ||
var callNow = immediate && !timeout; | ||
clearTimeout(timeout); | ||
timeout = setTimeout(later, wait); | ||
if (callNow) func.apply(context, args); | ||
}; | ||
}; | ||
export function onlyUnique(value, index, self) { | ||
return self.indexOf(value) === index; | ||
timeout = null | ||
func.apply(context, args) | ||
} | ||
clearTimeout(timeout) | ||
timeout = setTimeout(later, wait) | ||
} | ||
} | ||
@@ -86,3 +102,3 @@ | ||
const typeMatch = name.match(/x-(on|bind|data|text|html|model|if|show|cloak|transition|ref)/) | ||
const valueMatch = name.match(/:([a-zA-Z\-]+)/) | ||
const valueMatch = name.match(/:([a-zA-Z\-:]+)/) | ||
const modifiers = name.match(/\.[^.\]]+(?=[^\]]*$)/g) || [] | ||
@@ -89,0 +105,0 @@ |
@@ -20,2 +20,61 @@ import Alpine from 'alpinejs' | ||
test('class attribute bindings are merged by string syntax', async () => { | ||
document.body.innerHTML = ` | ||
<div x-data="{ isOn: false }"> | ||
<span class="foo" x-bind:class="isOn ? 'bar': ''"></span> | ||
<button @click="isOn = ! isOn"></button> | ||
</div> | ||
` | ||
Alpine.start() | ||
expect(document.querySelector('span').classList.contains('foo')).toBeTruthy() | ||
expect(document.querySelector('span').classList.contains('bar')).toBeFalsy() | ||
document.querySelector('button').click() | ||
await wait(() => { | ||
expect(document.querySelector('span').classList.contains('foo')).toBeTruthy() | ||
expect(document.querySelector('span').classList.contains('bar')).toBeTruthy() | ||
}) | ||
document.querySelector('button').click() | ||
await wait(() => { | ||
expect(document.querySelector('span').classList.contains('foo')).toBeTruthy() | ||
expect(document.querySelector('span').classList.contains('bar')).toBeFalsy() | ||
}) | ||
}) | ||
test('class attribute bindings are merged by array syntax', async () => { | ||
document.body.innerHTML = ` | ||
<div x-data="{ isOn: false }"> | ||
<span class="foo" x-bind:class="isOn ? ['bar', 'baz']: ['bar']"></span> | ||
<button @click="isOn = ! isOn"></button> | ||
</div> | ||
` | ||
Alpine.start() | ||
expect(document.querySelector('span').classList.contains('foo')).toBeTruthy() | ||
expect(document.querySelector('span').classList.contains('bar')).toBeTruthy() | ||
expect(document.querySelector('span').classList.contains('baz')).toBeFalsy() | ||
document.querySelector('button').click() | ||
await wait(() => { | ||
expect(document.querySelector('span').classList.contains('foo')).toBeTruthy() | ||
expect(document.querySelector('span').classList.contains('bar')).toBeTruthy() | ||
expect(document.querySelector('span').classList.contains('baz')).toBeTruthy() | ||
}) | ||
document.querySelector('button').click() | ||
await wait(() => { | ||
expect(document.querySelector('span').classList.contains('foo')).toBeTruthy() | ||
expect(document.querySelector('span').classList.contains('bar')).toBeTruthy() | ||
expect(document.querySelector('span').classList.contains('baz')).toBeFalsy() | ||
}) | ||
}) | ||
test('class attribute bindings are removed by object syntax', async () => { | ||
@@ -33,2 +92,14 @@ document.body.innerHTML = ` | ||
test('class attribute bindings are added by string syntax', async () => { | ||
document.body.innerHTML = ` | ||
<div x-data="{ initialClass: 'foo' }"> | ||
<span x-bind:class="initialClass"></span> | ||
</div> | ||
` | ||
Alpine.start() | ||
expect(document.querySelector('span').classList.contains('foo')).toBeTruthy() | ||
}) | ||
test('class attribute bindings are added by object syntax', async () => { | ||
@@ -84,14 +155,2 @@ document.body.innerHTML = ` | ||
test('class attribute bindings are removed by array syntax', async () => { | ||
document.body.innerHTML = ` | ||
<div x-data="{}"> | ||
<span class="foo" x-bind:class="[]"></span> | ||
</div> | ||
` | ||
Alpine.start() | ||
expect(document.querySelector('span').classList.contains('foo')).toBeFalsy() | ||
}) | ||
test('class attribute bindings are added by array syntax', async () => { | ||
@@ -98,0 +157,0 @@ document.body.innerHTML = ` |
@@ -33,1 +33,34 @@ import Alpine from 'alpinejs' | ||
}) | ||
test('x-data can use attributes from a reusable function', async () => { | ||
document.body.innerHTML = ` | ||
<div x-data="test()"> | ||
<span x-text="foo"></span> | ||
</div> | ||
` | ||
test = function() { | ||
return { | ||
foo: 'bar', | ||
} | ||
} | ||
Alpine.start() | ||
expect(document.querySelector('span').innerText).toEqual('bar') | ||
}) | ||
test('functions in x-data are reactive', async () => { | ||
document.body.innerHTML = ` | ||
<div x-data="{ foo: 'bar', getFoo() {return this.foo}}"> | ||
<span x-text="getFoo()"></span> | ||
<button x-on:click="foo = 'baz'"></button> | ||
</div> | ||
` | ||
Alpine.start() | ||
expect(document.querySelector('span').innerText).toEqual('bar') | ||
document.querySelector('button').click() | ||
await wait(() => { expect(document.querySelector('span').innerText).toEqual('baz') }) | ||
}) |
@@ -145,3 +145,3 @@ import Alpine from 'alpinejs' | ||
<div x-data="{ count: 0 }"> | ||
<input type="text" x-on:keydown="count++" x-on:keydown.enter="count++"> | ||
<input type="text" x-on:keydown="count++" x-on:keydown.enter="count++" x-on:keydown.space="count++"> | ||
@@ -160,5 +160,13 @@ <span x-text="count"></span> | ||
fireEvent.keyDown(document.querySelector('input'), { key: ' ' }) | ||
await wait(() => { expect(document.querySelector('span').innerText).toEqual(4) }) | ||
fireEvent.keyDown(document.querySelector('input'), { key: 'Spacebar' }) | ||
await wait(() => { expect(document.querySelector('span').innerText).toEqual(6) }) | ||
fireEvent.keyDown(document.querySelector('input'), { key: 'Escape' }) | ||
await wait(() => { expect(document.querySelector('span').innerText).toEqual(3) }) | ||
await wait(() => { expect(document.querySelector('span').innerText).toEqual(7) }) | ||
}) | ||
@@ -228,1 +236,22 @@ | ||
}) | ||
test('event with colon', async () => { | ||
document.body.innerHTML = ` | ||
<div x-data="{ foo: 'bar' }"> | ||
<div x-on:my:event.document="foo = 'baz'"></div> | ||
<span x-bind:foo="foo"></span> | ||
</div> | ||
` | ||
Alpine.start() | ||
expect(document.querySelector('span').getAttribute('foo')).toEqual('bar') | ||
var event = new CustomEvent('my:event'); | ||
document.dispatchEvent(event); | ||
await wait(() => { expect(document.querySelector('span').getAttribute('foo')).toEqual('baz') }) | ||
}) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
155405
1892