diff --git a/README.md b/README.md index 089d58c..9685f64 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,33 @@ Vue wrapper for [`dragula`][1]. +## Status + +WIP attempting to make example work with Vue 2.x + +### Changelog + +- Changed life cycle method `ready` to `mounted` +- Using `$nextTick` callback as recommended in Vue2 guide +- Using `this.$dragula` to access dragula extension/plugin via Vue prototype global inherited by components + +### TODO + +Check new [directives API](https://vuejs.org/v2/guide/custom-directive.html) and modify as needed: + +`bind`: called only once, when the directive is first bound to the element. This is where you can do one-time setup work. + +`inserted`: called when the bound element has been inserted into its parent node (this only guarantees parent node presence, not necessarily in-document). + +`update`: called after the containing component has updated, but possibly before its children have updated. The directive’s value may or may not have changed, but you can skip unnecessary updates by comparing the binding’s current and old values (see below on hook arguments). + +`componentUpdated`: called after the containing component and its children have updated. + +`unbind`: called only once, when the directive is unbound from the element. + + +Currently, `bind`, `update` and `unbind` hooks are used. + ## Install #### CommonJS @@ -87,3 +114,95 @@ new Vue({ | removeModel | bagName, el, container, removeIndex | model was synced, removeIndex exposed | [1]: https://github.com/bevacqua/dragula + +## Development + +Following npm scripts are included: + +- `npm run build` to build new distribution in `/dist` +- `npm run dev` run example in dev mode +- `npm run lint` lint code using ESlint + +How to view the example? Start a simple Http server, like the pythong [simplehttpserver](http://angusjune.github.io/blog/2014/08/16/python-3-dot-x-no-module-named-simplehttpserver/) + +`python -m http.server` + +The open in browser: `open localhost:8000` + +## Issues on Vue 2 + +``` + function ready () { + + domReadyTime = Date.now() ; + + // First, check if it's a PRE and exit if not + var bodyChildren = document.body.childNodes ; +``` + +``` +Exception: +TypeError: Cannot read property 'childNodes' of null at HTMLDocument.ready +``` + +### Recommendations + +Basically, the example needs to use proper `.vue` templates to work as discussed [here](https://github.com/vuejs-templates/webpack/issues/215) + +So please update example to use webpack or better yet, create demo app using basic Vue2 setup with webpack :) + +I've started such a [demo app](https://github.com/kristianmandrup/vue2-dragula-demo) but having problems :() + +I don't yet understand the Vue2 plugin architecture! Please help out... + +### Vue 2 Plugin + +Trying to add dragula as a [Vue 2 plugin](https://vuejs.org/v2/guide/plugins.html) + +```js + // 3. inject some component options + Vue.mixin({ + created: function () { + // something logic ... + } + ... + }) + // 4. add an instance method + Vue.prototype.$myMethod = function (options) { + // something logic ... + } +``` + +Looks correct to add `$dragula` to `Vue.prototype` as shown [here](https://github.com/aarondfrancis/vue-model/blob/master/src/VueModel.js#L99) + +```js +function plugin (Vue, options = {}) { + if (plugin.installed) { + console.warn('[vue-dragula] already installed.') + } + + console.log('Add Dragula plugin:', options) + VueDragula(Vue, options) +} +``` + + +We then call the function in `vue-dragula.js` which adds `$dragula` to `Vue.prototype` in accordance with Vue 2 specs on plugins. +What is missing!?!?! WTF!!! + +```js +export default function (Vue, options = {}) { + const service = new DragulaService(Vue) + + let name = 'globalBag' + let drake + + console.log('Adding Dragula as plugin...') + Vue.$dragula = { + options: service.setOptions.bind(service), + find: service.find.bind(service), + eventBus: service.eventBus + } + Vue.prototype.$dragula = Vue.$dragula +} +``` \ No newline at end of file diff --git a/dist/vue-dragula.js b/dist/vue-dragula.js index f56ccf4..120f841 100644 --- a/dist/vue-dragula.js +++ b/dist/vue-dragula.js @@ -1,5 +1,5 @@ /*! - * vue-dragula v1.3.0 + * vue-dragula v2.0.0 * (c) 2016 Yichang Liu * Released under the MIT License. */ @@ -9,43 +9,10 @@ (global.vueDragula = factory()); }(this, function () { 'use strict'; - var babelHelpers = {}; - babelHelpers.typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { - return typeof obj; - } : function (obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; - }; - - babelHelpers.classCallCheck = function (instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } - }; - - babelHelpers.createClass = function () { - function defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } - } - - return function (Constructor, protoProps, staticProps) { - if (protoProps) defineProperties(Constructor.prototype, protoProps); - if (staticProps) defineProperties(Constructor, staticProps); - return Constructor; - }; - }(); - - babelHelpers; - - var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {} function interopDefault(ex) { - return ex && (typeof ex === 'undefined' ? 'undefined' : babelHelpers.typeof(ex)) === 'object' && 'default' in ex ? ex['default'] : ex; + return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex; } function createCommonjsModule(fn, module) { @@ -565,8 +532,8 @@ var require$$0$3 = Object.freeze({ // see also: https://github.com/bevacqua/dragula/issues/208 item.focus(); // fixes https://github.com/bevacqua/dragula/issues/176 } else { - e.preventDefault(); // fixes https://github.com/bevacqua/dragula/issues/155 - } + e.preventDefault(); // fixes https://github.com/bevacqua/dragula/issues/155 + } } } @@ -1104,6 +1071,143 @@ var require$$0$3 = Object.freeze({ var dragula$1 = interopDefault(dragula); + var asyncGenerator = function () { + function AwaitValue(value) { + this.value = value; + } + + function AsyncGenerator(gen) { + var front, back; + + function send(key, arg) { + return new Promise(function (resolve, reject) { + var request = { + key: key, + arg: arg, + resolve: resolve, + reject: reject, + next: null + }; + + if (back) { + back = back.next = request; + } else { + front = back = request; + resume(key, arg); + } + }); + } + + function resume(key, arg) { + try { + var result = gen[key](arg); + var value = result.value; + + if (value instanceof AwaitValue) { + Promise.resolve(value.value).then(function (arg) { + resume("next", arg); + }, function (arg) { + resume("throw", arg); + }); + } else { + settle(result.done ? "return" : "normal", result.value); + } + } catch (err) { + settle("throw", err); + } + } + + function settle(type, value) { + switch (type) { + case "return": + front.resolve({ + value: value, + done: true + }); + break; + + case "throw": + front.reject(value); + break; + + default: + front.resolve({ + value: value, + done: false + }); + break; + } + + front = front.next; + + if (front) { + resume(front.key, front.arg); + } else { + back = null; + } + } + + this._invoke = send; + + if (typeof gen.return !== "function") { + this.return = undefined; + } + } + + if (typeof Symbol === "function" && Symbol.asyncIterator) { + AsyncGenerator.prototype[Symbol.asyncIterator] = function () { + return this; + }; + } + + AsyncGenerator.prototype.next = function (arg) { + return this._invoke("next", arg); + }; + + AsyncGenerator.prototype.throw = function (arg) { + return this._invoke("throw", arg); + }; + + AsyncGenerator.prototype.return = function (arg) { + return this._invoke("return", arg); + }; + + return { + wrap: function (fn) { + return function () { + return new AsyncGenerator(fn.apply(this, arguments)); + }; + }, + await: function (value) { + return new AwaitValue(value); + } + }; + }(); + + var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + }; + + var createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + if (!dragula$1) { throw new Error('[vue-dragula] cannot locate dragula.'); } @@ -1119,16 +1223,18 @@ var require$$0$3 = Object.freeze({ var DragulaService = function () { function DragulaService(Vue) { - babelHelpers.classCallCheck(this, DragulaService); + classCallCheck(this, DragulaService); + console.log('Create Dragula service'); this.bags = []; // bag store this.eventBus = new Vue(); this.events = ['cancel', 'cloned', 'drag', 'dragend', 'drop', 'out', 'over', 'remove', 'shadow', 'dropModel', 'removeModel']; } - babelHelpers.createClass(DragulaService, [{ + createClass(DragulaService, [{ key: 'add', value: function add(name, drake) { + console.log('Dragula: add', name); var bag = this.find(name); if (bag) { throw new Error('Bag named: "' + name + '" already exists.'); @@ -1149,6 +1255,7 @@ var require$$0$3 = Object.freeze({ }, { key: 'find', value: function find(name) { + console.log('Dragula: find', name); var bags = this.bags; for (var i = 0; i < bags.length; i++) { if (bags[i].name === name) { @@ -1161,6 +1268,8 @@ var require$$0$3 = Object.freeze({ value: function handleModels(name, drake) { var _this2 = this; + console.log('Dragula: handleModels', name); + if (drake.registered) { // do not register events twice return; @@ -1268,21 +1377,27 @@ var require$$0$3 = Object.freeze({ } function VueDragula (Vue) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var service = new DragulaService(Vue); var name = 'globalBag'; var drake = void 0; - Vue.vueDragula = { + console.log('Adding Dragula as plugin...'); + Vue.$dragula = { options: service.setOptions.bind(service), find: service.find.bind(service), eventBus: service.eventBus }; + Vue.prototype.$dragula = Vue.$dragula; Vue.directive('dragula', { params: ['bag'], bind: function bind(container, binding, vnode) { + console.log('bind Dragula', container); + var bagName = vnode ? vnode.data.attrs.bag // Vue 2 : this.params.bag; // Vue 1 if (!vnode) { @@ -1305,6 +1420,8 @@ var require$$0$3 = Object.freeze({ service.handleModels(name, drake); }, update: function update(container, binding, vnode, oldVnode) { + console.log('update Dragula', container); + var newValue = vnode ? binding.value // Vue 2 : container; // Vue 1 if (!newValue) { @@ -1337,6 +1454,8 @@ var require$$0$3 = Object.freeze({ } }, unbind: function unbind(container, binding, vnode) { + console.log('unbind Dragula', container); + var unbindBagName = 'globalBag'; var bagName = vnode ? vnode.data.attrs.bag // Vue 2 : this.params.bag; // Vue 1 @@ -1359,13 +1478,14 @@ var require$$0$3 = Object.freeze({ } function plugin(Vue) { - var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (plugin.installed) { console.warn('[vue-dragula] already installed.'); } - VueDragula(Vue); + console.log('Add Dragula plugin:', options); + VueDragula(Vue, options); } plugin.version = '1.0.0'; @@ -1376,8 +1496,8 @@ var require$$0$3 = Object.freeze({ plugin; }); // eslint-disable-line } else if (window.Vue) { - window.Vue.use(plugin); - } + window.Vue.use(plugin); + } return plugin; diff --git a/dist/vue-dragula.min.js b/dist/vue-dragula.min.js index 380a55f..2d10425 100644 --- a/dist/vue-dragula.min.js +++ b/dist/vue-dragula.min.js @@ -1,6 +1,6 @@ /*! - * vue-dragula v1.3.0 + * vue-dragula v2.0.0 * (c) 2016 Yichang Liu * Released under the MIT License. */ -!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):e.vueDragula=n()}(this,function(){"use strict";function e(e){return e&&"object"===("undefined"==typeof e?"undefined":o["typeof"](e))&&"default"in e?e["default"]:e}function n(e,n){return n={exports:{}},e(n,n.exports),n.exports}function t(e){var n=new F(e),t="globalBag",r=void 0;e.vueDragula={options:n.setOptions.bind(n),find:n.find.bind(n),eventBus:n.eventBus},e.directive("dragula",{params:["bag"],bind:function(e,o,i){var a=i?i.data.attrs.bag:this.params.bag;i||(e=this.el),void 0!==a&&0!==a.length&&(t=a);var u=n.find(t);return u?(r=u.drake,void r.containers.push(e)):(r=z({containers:[e]}),n.add(t,r),void n.handleModels(t,r))},update:function(e,o,i,a){var u=i?o.value:e;if(u){var c=i?i.data.attrs.bag:this.params.bag;void 0!==c&&0!==c.length&&(t=c);var l=n.find(t);r=l.drake,r.models||(r.models=[]),i||(e=this.el);var d=n.findModelContainerByContainer(e,r);d?d.model=u:r.models.push({model:u,container:e})}},unbind:function(e,t,r){var o="globalBag",i=r?r.data.attrs.bag:this.params.bag;void 0!==i&&0!==i.length&&(o=i);var a=n.find(o).drake;if(a){var u=a.containers.indexOf(e);u>-1&&a.containers.splice(u,1),0===a.containers.length&&n.destroy(o)}}})}function r(e){arguments.length<=1||void 0===arguments[1]?{}:arguments[1];r.installed&&console.warn("[vue-dragula] already installed."),t(e)}var o={};o["typeof"]="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol?"symbol":typeof e},o.classCallCheck=function(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")},o.createClass=function(){function e(e,n){for(var t=0;t0?e:le.revertOnSpill,t=ie||W,r=v(t),o=F(r);o===!1&&n&&(ie?r&&r.removeChild(ie):Q.insertBefore(t,re)),o||n?de.emit("cancel",t,Q,Q):de.emit("drop",t,r,Q,oe),D()}}function D(){var e=ie||W;I(),K(),e&&C.rm(e,"gu-transit"),ae&&clearTimeout(ae),de.dragging=!1,ce&&de.emit("out",e,ce,Q),de.emit("dragend",e),Q=W=ie=re=oe=ae=ce=null}function F(e,n){var t;return t=void 0!==n?n:G?oe:g(ie||W),e===Q&&t===re}function R(e,n,r){function o(){var o=t(i);if(o===!1)return!1;var a=U(i,e),u=_(i,a,n,r),c=F(i,u);return c?!0:le.accepts(W,i,Q,u)}for(var i=e;i&&!o();)i=v(i);return i}function L(e){function n(e){de.emit(e,l,ce,Q)}function t(){s&&n("over")}function r(){ce&&n("out")}if(G){e.preventDefault();var o=b("clientX",e),i=b("clientY",e),a=o-Z,u=i-ee;G.style.left=a+"px",G.style.top=u+"px";var l=ie||W,d=c(G,o,i),f=R(d,o,i),s=null!==f&&f!==ce;(s||null===f)&&(r(),ce=f,t());var p=v(l);if(f===Q&&ie&&!le.copySortSource)return void(p&&p.removeChild(l));var m,h=U(f,d);if(null!==h)m=_(f,h,o,i);else{if(le.revertOnSpill!==!0||ie)return void(ie&&p&&p.removeChild(l));m=re,f=Q}(null===m&&s||m!==l&&m!==g(l))&&(oe=m,f.insertBefore(l,m),de.emit("shadow",l,f,Q))}}function $(e){C.rm(e,"gu-hide")}function V(e){de.dragging&&C.add(e,"gu-hide")}function J(){if(!G){var e=W.getBoundingClientRect();G=W.cloneNode(!0),G.style.width=f(e)+"px",G.style.height=s(e)+"px",C.rm(G,"gu-transit"),C.add(G,"gu-mirror"),le.mirrorContainer.appendChild(G),r(O,"add","mousemove",L),C.add(le.mirrorContainer,"gu-unselectable"),de.emit("cloned",G,W,"mirror")}}function K(){G&&(C.rm(le.mirrorContainer,"gu-unselectable"),r(O,"remove","mousemove",L),v(G).removeChild(G),G=null)}function U(e,n){for(var t=n;t!==e&&v(t)!==e;)t=v(t);return t===O?null:t}function _(e,n,t,r){function o(){var n,o,i,a=e.children.length;for(n=0;a>n;n++){if(o=e.children[n],i=o.getBoundingClientRect(),u&&i.left+i.width/2>t)return o;if(!u&&i.top+i.height/2>r)return o}return null}function i(){var e=n.getBoundingClientRect();return a(u?t>e.left+f(e)/2:r>e.top+s(e)/2)}function a(e){return e?g(n):n}var u="horizontal"===le.direction,c=n!==e?i():o();return c}function q(e,n){return"boolean"==typeof le.copy?le.copy:le.copy(e,n)}var H=arguments.length;1===H&&Array.isArray(e)===!1&&(n=e,e=[]);var G,Q,W,Z,ee,ne,te,re,oe,ie,ae,ue,ce=null,le=n||{};void 0===le.moves&&(le.moves=d),void 0===le.accepts&&(le.accepts=d),void 0===le.invalid&&(le.invalid=j),void 0===le.containers&&(le.containers=e||[]),void 0===le.isContainer&&(le.isContainer=l),void 0===le.copy&&(le.copy=!1),void 0===le.copySortSource&&(le.copySortSource=!1),void 0===le.revertOnSpill&&(le.revertOnSpill=!1),void 0===le.removeOnSpill&&(le.removeOnSpill=!1),void 0===le.direction&&(le.direction="vertical"),void 0===le.ignoreInputTextSelection&&(le.ignoreInputTextSelection=!0),void 0===le.mirrorContainer&&(le.mirrorContainer=x.body);var de=w({containers:le.containers,start:M,end:X,cancel:A,remove:z,destroy:h,canMove:T,dragging:!1});return le.removeOnSpill===!0&&de.on("over",$).on("out",V),i(),de}function r(e,n,t,r){var o={mouseup:"touchend",mousedown:"touchstart",mousemove:"touchmove"},a={mouseup:"pointerup",mousedown:"pointerdown",mousemove:"pointermove"},u={mouseup:"MSPointerUp",mousedown:"MSPointerDown",mousemove:"MSPointerMove"};i.navigator.pointerEnabled?E[n](e,a[t],r):i.navigator.msPointerEnabled?E[n](e,u[t],r):(E[n](e,o[t],r),E[n](e,t,r))}function o(e){if(void 0!==e.touches)return e.touches.length;if(void 0!==e.which&&0!==e.which)return e.which;if(void 0!==e.buttons)return e.buttons;var n=e.button;return void 0!==n?1&n?1:2&n?3:4&n?2:0:void 0}function a(e){var n=e.getBoundingClientRect();return{left:n.left+u("scrollLeft","pageXOffset"),top:n.top+u("scrollTop","pageYOffset")}}function u(e,n){return"undefined"!=typeof i[n]?i[n]:O.clientHeight?O[e]:x.body[e]}function c(e,n,t){var r,o=e||{},i=o.className;return o.className+=" gu-hide",r=x.elementFromPoint(n,t),o.className=i,r}function l(){return!1}function d(){return!0}function f(e){return e.width||e.right-e.left}function s(e){return e.height||e.bottom-e.top}function v(e){return e.parentNode===x?null:e.parentNode}function p(e){return"INPUT"===e.tagName||"TEXTAREA"===e.tagName||"SELECT"===e.tagName||m(e)}function m(e){return e?"false"===e.contentEditable?!1:"true"===e.contentEditable?!0:m(v(e)):!1}function g(e){function n(){var n=e;do n=n.nextSibling;while(n&&1!==n.nodeType);return n}return e.nextElementSibling||n()}function y(e){return e.targetTouches&&e.targetTouches.length?e.targetTouches[0]:e.changedTouches&&e.changedTouches.length?e.changedTouches[0]:e}function b(e,n){var t=y(n),r={pageX:"clientX",pageY:"clientY"};return e in r&&!(e in t)&&r[e]in t&&(e=r[e]),t[e]}var w=e(h),E=e(M),C=e(P),x=document,O=x.documentElement;n.exports=t}),z=e(Y);if(!z)throw new Error("[vue-dragula] cannot locate dragula.");var A=window.requestAnimationFrame,D=A?function(e){A(function(){A(e)})}:function(e){window.setTimeout(e,50)},F=function(){function e(n){o.classCallCheck(this,e),this.bags=[],this.eventBus=new n,this.events=["cancel","cloned","drag","dragend","drop","out","over","remove","shadow","dropModel","removeModel"]}return o.createClass(e,[{key:"add",value:function(e,n){var t=this.find(e);if(t)throw new Error('Bag named: "'+e+'" already exists.');return t={name:e,drake:n},this.bags.push(t),n.models&&this.handleModels(e,n),t.initEvents||this.setupEvents(t),t}},{key:"find",value:function(e){for(var n=this.bags,t=0;t1&&void 0!==arguments[1]?arguments[1]:{},new $(e)),t="globalBag",r=void 0;console.log("Adding Dragula as plugin..."),e.$dragula={options:n.setOptions.bind(n),find:n.find.bind(n),eventBus:n.eventBus},e.prototype.$dragula=e.$dragula,e.directive("dragula",{params:["bag"],bind:function(e,o,i){console.log("bind Dragula",e);var a=i?i.data.attrs.bag:this.params.bag;i||(e=this.el),void 0!==a&&0!==a.length&&(t=a);var u=n.find(t);return u?(r=u.drake,void r.containers.push(e)):(r=X({containers:[e]}),n.add(t,r),void n.handleModels(t,r))},update:function(e,o,i,a){console.log("update Dragula",e);var u=i?o.value:e;if(u){var c=i?i.data.attrs.bag:this.params.bag;void 0!==c&&0!==c.length&&(t=c);var l=n.find(t);r=l.drake,r.models||(r.models=[]),i||(e=this.el);var d=n.findModelContainerByContainer(e,r);d?d.model=u:r.models.push({model:u,container:e})}},unbind:function(e,t,r){console.log("unbind Dragula",e);var o="globalBag",i=r?r.data.attrs.bag:this.params.bag;void 0!==i&&0!==i.length&&(o=i);var a=n.find(o).drake;if(a){var u=a.containers.indexOf(e);u>-1&&a.containers.splice(u,1),0===a.containers.length&&n.destroy(o)}}})}function r(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};r.installed&&console.warn("[vue-dragula] already installed."),console.log("Add Dragula plugin:",n),t(e,n)}var o="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},i=n(function(e){e.exports=function(e,n){return Array.prototype.slice.call(e,n)}}),a=e(i),u=Object.freeze({default:a}),c=n(function(e){var n,t="function"==typeof setImmediate;n=t?function(e){setImmediate(e)}:"undefined"!=typeof process&&process.nextTick?process.nextTick:function(e){setTimeout(e,0)},e.exports=n}),l=e(c),d=Object.freeze({default:l}),f=n(function(n){var t=e(d);n.exports=function(e,n,r){e&&t(function(){e.apply(r||null,n||[])})}}),s=e(f),v=Object.freeze({default:s}),p=n(function(n){var t=e(u),r=e(v);n.exports=function(e,n){var o=n||{},i={};return void 0===e&&(e={}),e.on=function(n,t){return i[n]?i[n].push(t):i[n]=[t],e},e.once=function(n,t){return t._once=!0,e.on(n,t),e},e.off=function(n,t){var r=arguments.length;if(1===r)delete i[n];else if(0===r)i={};else{var o=i[n];if(!o)return e;o.splice(o.indexOf(t),1)}return e},e.emit=function(){var n=t(arguments);return e.emitterSnapshot(n.shift()).apply(this,n)},e.emitterSnapshot=function(n){var a=(i[n]||[]).slice(0);return function(){var i=t(arguments),u=this||e;if("error"===n&&o.throws!==!1&&!a.length)throw 1===i.length?i[0]:i;return a.forEach(function(t){o.async?r(t,i,u):t.apply(u,i),t._once&&e.off(n,t)}),e}},e}}),m=e(p),g=Object.freeze({default:m}),h=n(function(e){function n(){try{var e=new t("cat",{detail:{foo:"bar"}});return"cat"===e.type&&"bar"===e.detail.foo}catch(e){}return!1}var t=o.CustomEvent;e.exports=n()?t:"function"==typeof document.createEvent?function(e,n){var t=document.createEvent("CustomEvent");return n?t.initCustomEvent(e,n.bubbles,n.cancelable,n.detail):t.initCustomEvent(e,!1,!1,void 0),t}:function(e,n){var t=document.createEventObject();return t.type=e,n?(t.bubbles=Boolean(n.bubbles),t.cancelable=Boolean(n.cancelable),t.detail=n.detail):(t.bubbles=!1,t.cancelable=!1,t.detail=void 0),t}}),y=e(h),b=Object.freeze({default:y}),w=n(function(e){var n=[],t="",r=/^on/;for(t in o)r.test(t)&&n.push(t.slice(2));e.exports=n}),x=e(w),E=Object.freeze({default:x}),C=n(function(n){function t(e,n,t,r){return e.addEventListener(n,t,r)}function r(e,n,t){return e.attachEvent("on"+n,l(e,n,t))}function i(e,n,t,r){return e.removeEventListener(n,t,r)}function a(e,n,t){var r=d(e,n,t);if(r)return e.detachEvent("on"+n,r)}function u(e,n,t){function r(){var e;return p.createEvent?(e=p.createEvent("Event"),e.initEvent(n,!0,!0)):p.createEventObject&&(e=p.createEventObject()),e}function o(){return new s(n,{detail:t})}var i=v.indexOf(n)===-1?o():r();e.dispatchEvent?e.dispatchEvent(i):e.fireEvent("on"+n,i)}function c(e,n,t){return function(n){var r=n||o.event;r.target=r.target||r.srcElement,r.preventDefault=r.preventDefault||function(){r.returnValue=!1},r.stopPropagation=r.stopPropagation||function(){r.cancelBubble=!0},r.which=r.which||r.keyCode,t.call(e,r)}}function l(e,n,t){var r=d(e,n,t)||c(e,n,t);return h.push({wrapper:r,element:e,type:n,fn:t}),r}function d(e,n,t){var r=f(e,n,t);if(r){var o=h[r].wrapper;return h.splice(r,1),o}}function f(e,n,t){var r,o;for(r=0;r0?e:le.revertOnSpill,t=ie||W,r=v(t),o=F(r);o===!1&&n&&(ie?r&&r.removeChild(ie):Q.insertBefore(t,re)),o||n?de.emit("cancel",t,Q,Q):de.emit("drop",t,r,Q,oe),z()}}function z(){var e=ie||W;I(),J(),e&&E.rm(e,"gu-transit"),ae&&clearTimeout(ae),de.dragging=!1,ce&&de.emit("out",e,ce,Q),de.emit("dragend",e),Q=W=ie=re=oe=ae=ce=null}function F(e,n){var t;return t=void 0!==n?n:G?oe:h(ie||W),e===Q&&t===re}function $(e,n,r){function o(){var o=t(i);if(o===!1)return!1;var a=K(i,e),u=U(i,a,n,r),c=F(i,u);return!!c||le.accepts(W,i,Q,u)}for(var i=e;i&&!o();)i=v(i);return i}function R(e){function n(e){de.emit(e,l,ce,Q)}function t(){s&&n("over")}function r(){ce&&n("out")}if(G){e.preventDefault();var o=b("clientX",e),i=b("clientY",e),a=o-Z,u=i-ee;G.style.left=a+"px",G.style.top=u+"px";var l=ie||W,d=c(G,o,i),f=$(d,o,i),s=null!==f&&f!==ce;(s||null===f)&&(r(),ce=f,t());var p=v(l);if(f===Q&&ie&&!le.copySortSource)return void(p&&p.removeChild(l));var m,g=K(f,d);if(null!==g)m=U(f,g,o,i);else{if(le.revertOnSpill!==!0||ie)return void(ie&&p&&p.removeChild(l));m=re,f=Q}(null===m&&s||m!==l&&m!==h(l))&&(oe=m,f.insertBefore(l,m),de.emit("shadow",l,f,Q))}}function _(e){E.rm(e,"gu-hide")}function L(e){de.dragging&&E.add(e,"gu-hide")}function V(){if(!G){var e=W.getBoundingClientRect();G=W.cloneNode(!0),G.style.width=f(e)+"px",G.style.height=s(e)+"px",E.rm(G,"gu-transit"),E.add(G,"gu-mirror"),le.mirrorContainer.appendChild(G),r(O,"add","mousemove",R),E.add(le.mirrorContainer,"gu-unselectable"),de.emit("cloned",G,W,"mirror")}}function J(){G&&(E.rm(le.mirrorContainer,"gu-unselectable"),r(O,"remove","mousemove",R),v(G).removeChild(G),G=null)}function K(e,n){for(var t=n;t!==e&&v(t)!==e;)t=v(t);return t===O?null:t}function U(e,n,t,r){function o(){var n,o,i,a=e.children.length;for(n=0;nt)return o;if(!u&&i.top+i.height/2>r)return o}return null}function i(){var e=n.getBoundingClientRect();return a(u?t>e.left+f(e)/2:r>e.top+s(e)/2)}function a(e){return e?h(n):n}var u="horizontal"===le.direction,c=n!==e?i():o();return c}function q(e,n){return"boolean"==typeof le.copy?le.copy:le.copy(e,n)}var H=arguments.length;1===H&&Array.isArray(e)===!1&&(n=e,e=[]);var G,Q,W,Z,ee,ne,te,re,oe,ie,ae,ue,ce=null,le=n||{};void 0===le.moves&&(le.moves=d),void 0===le.accepts&&(le.accepts=d),void 0===le.invalid&&(le.invalid=j),void 0===le.containers&&(le.containers=e||[]),void 0===le.isContainer&&(le.isContainer=l),void 0===le.copy&&(le.copy=!1),void 0===le.copySortSource&&(le.copySortSource=!1),void 0===le.revertOnSpill&&(le.revertOnSpill=!1),void 0===le.removeOnSpill&&(le.removeOnSpill=!1),void 0===le.direction&&(le.direction="vertical"),void 0===le.ignoreInputTextSelection&&(le.ignoreInputTextSelection=!0),void 0===le.mirrorContainer&&(le.mirrorContainer=C.body);var de=w({containers:le.containers,start:T,end:D,cancel:Y,remove:A,destroy:g,canMove:M,dragging:!1});return le.removeOnSpill===!0&&de.on("over",_).on("out",L),o(),de}function r(e,n,t,r){var i={mouseup:"touchend",mousedown:"touchstart",mousemove:"touchmove"},a={mouseup:"pointerup",mousedown:"pointerdown",mousemove:"pointermove"},u={mouseup:"MSPointerUp",mousedown:"MSPointerDown",mousemove:"MSPointerMove"};o.navigator.pointerEnabled?x[n](e,a[t],r):o.navigator.msPointerEnabled?x[n](e,u[t],r):(x[n](e,i[t],r),x[n](e,t,r))}function i(e){if(void 0!==e.touches)return e.touches.length;if(void 0!==e.which&&0!==e.which)return e.which;if(void 0!==e.buttons)return e.buttons;var n=e.button;return void 0!==n?1&n?1:2&n?3:4&n?2:0:void 0}function a(e){var n=e.getBoundingClientRect();return{left:n.left+u("scrollLeft","pageXOffset"),top:n.top+u("scrollTop","pageYOffset")}}function u(e,n){return"undefined"!=typeof o[n]?o[n]:O.clientHeight?O[e]:C.body[e]}function c(e,n,t){var r,o=e||{},i=o.className;return o.className+=" gu-hide",r=C.elementFromPoint(n,t),o.className=i,r}function l(){return!1}function d(){return!0}function f(e){return e.width||e.right-e.left}function s(e){return e.height||e.bottom-e.top}function v(e){return e.parentNode===C?null:e.parentNode}function p(e){return"INPUT"===e.tagName||"TEXTAREA"===e.tagName||"SELECT"===e.tagName||m(e)}function m(e){return!!e&&("false"!==e.contentEditable&&("true"===e.contentEditable||m(v(e))))}function h(e){function n(){var n=e;do n=n.nextSibling;while(n&&1!==n.nodeType);return n}return e.nextElementSibling||n()}function y(e){return e.targetTouches&&e.targetTouches.length?e.targetTouches[0]:e.changedTouches&&e.changedTouches.length?e.changedTouches[0]:e}function b(e,n){var t=y(n),r={pageX:"clientX",pageY:"clientY"};return e in r&&!(e in t)&&r[e]in t&&(e=r[e]),t[e]}var w=e(g),x=e(M),E=e(I),C=document,O=C.documentElement;n.exports=t}),X=e(P),A=(function(){function e(e){this.value=e}function n(n){function t(e,n){return new Promise(function(t,o){var u={key:e,arg:n,resolve:t,reject:o,next:null};a?a=a.next=u:(i=a=u,r(e,n))})}function r(t,i){try{var a=n[t](i),u=a.value;u instanceof e?Promise.resolve(u.value).then(function(e){r("next",e)},function(e){r("throw",e)}):o(a.done?"return":"normal",a.value)}catch(e){o("throw",e)}}function o(e,n){switch(e){case"return":i.resolve({value:n,done:!0});break;case"throw":i.reject(n);break;default:i.resolve({value:n,done:!1})}i=i.next,i?r(i.key,i.arg):a=null}var i,a;this._invoke=t,"function"!=typeof n.return&&(this.return=void 0)}return"function"==typeof Symbol&&Symbol.asyncIterator&&(n.prototype[Symbol.asyncIterator]=function(){return this}),n.prototype.next=function(e){return this._invoke("next",e)},n.prototype.throw=function(e){return this._invoke("throw",e)},n.prototype.return=function(e){return this._invoke("return",e)},{wrap:function(e){return function(){return new n(e.apply(this,arguments))}},await:function(n){return new e(n)}}}(),function(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}),Y=function(){function e(e,n){for(var t=0;t { + console.log('Comfig $dragula.eventBus', this.$dragula.eventBus) + // since $dragula in on Vue.prototype which all Components inherit from + // you should also be able to do: this.$dragula + this.$dragula.eventBus.$on( + 'drop', + function (args) { + console.log('drop: ' + args[0]) + console.log(this.categories) + } + ) + this.$dragula.eventBus.$on( + 'dropModel', + function (args) { + console.log('dropModel: ' + args) + console.log(this.categories) + } + ) + }) }, methods: { - onClick: function () { - console.log(Vue.vueDragula.find('first-bag')) + onClick () { + console.log(this.$dragula.find('first-bag')) window.alert('click event') }, - testModify: function () { + testModify () { this.categories = [ ['a', 'b', 'c'], ['d', 'e', 'f'] ] } } - }) + }) //.$mount('#app') /***/ }, /* 1 */ /***/ function(module, exports, __webpack_require__) { - /* WEBPACK VAR INJECTION */(function(global, process) {/*! - * Vue.js v1.0.21 - * (c) 2016 Evan You + /* WEBPACK VAR INJECTION */(function(process) {/*! + * Vue.js v2.0.5 + * (c) 2014-2016 Evan You * Released under the MIT License. */ 'use strict'; - function set(obj, key, val) { - if (hasOwn(obj, key)) { - obj[key] = val; - return; - } - if (obj._isVue) { - set(obj._data, key, val); - return; - } - var ob = obj.__ob__; - if (!ob) { - obj[key] = val; - return; - } - ob.convert(key, val); - ob.dep.notify(); - if (ob.vms) { - var i = ob.vms.length; - while (i--) { - var vm = ob.vms[i]; - vm._proxy(key); - vm._digest(); - } - } - return val; - } + /* */ /** - * Delete a property and trigger change if necessary. - * - * @param {Object} obj - * @param {String} key + * Convert a value to a string that is actually rendered. */ - - function del(obj, key) { - if (!hasOwn(obj, key)) { - return; - } - delete obj[key]; - var ob = obj.__ob__; - if (!ob) { - return; - } - ob.dep.notify(); - if (ob.vms) { - var i = ob.vms.length; - while (i--) { - var vm = ob.vms[i]; - vm._unproxy(key); - vm._digest(); - } - } + function _toString (val) { + return val == null + ? '' + : typeof val === 'object' + ? JSON.stringify(val, null, 2) + : String(val) } - var hasOwnProperty = Object.prototype.hasOwnProperty; /** - * Check whether the object has the property. - * - * @param {Object} obj - * @param {String} key - * @return {Boolean} + * Convert a input value to a number for persistence. + * If the conversion fails, return original string. */ - - function hasOwn(obj, key) { - return hasOwnProperty.call(obj, key); + function toNumber (val) { + var n = parseFloat(val, 10); + return (n || n === 0) ? n : val } /** - * Check if an expression is a literal value. - * - * @param {String} exp - * @return {Boolean} + * Make a map and return a function for checking if a key + * is in that map. */ - - var literalValueRE = /^\s?(true|false|-?[\d\.]+|'[^']*'|"[^"]*")\s?$/; - - function isLiteral(exp) { - return literalValueRE.test(exp); + function makeMap ( + str, + expectsLowerCase + ) { + var map = Object.create(null); + var list = str.split(','); + for (var i = 0; i < list.length; i++) { + map[list[i]] = true; + } + return expectsLowerCase + ? function (val) { return map[val.toLowerCase()]; } + : function (val) { return map[val]; } } /** - * Check if a string starts with $ or _ - * - * @param {String} str - * @return {Boolean} + * Check if a tag is a built-in tag. */ - - function isReserved(str) { - var c = (str + '').charCodeAt(0); - return c === 0x24 || c === 0x5F; - } + var isBuiltInTag = makeMap('slot,component', true); /** - * Guard text output, make sure undefined outputs - * empty string - * - * @param {*} value - * @return {String} + * Remove an item from an array */ - - function _toString(value) { - return value == null ? '' : value.toString(); + function remove$1 (arr, item) { + if (arr.length) { + var index = arr.indexOf(item); + if (index > -1) { + return arr.splice(index, 1) + } + } } /** - * Check and convert possible numeric strings to numbers - * before setting back to data - * - * @param {*} value - * @return {*|Number} + * Check whether the object has the property. */ - - function toNumber(value) { - if (typeof value !== 'string') { - return value; - } else { - var parsed = Number(value); - return isNaN(parsed) ? value : parsed; - } + var hasOwnProperty = Object.prototype.hasOwnProperty; + function hasOwn (obj, key) { + return hasOwnProperty.call(obj, key) } /** - * Convert string boolean literals into real booleans. - * - * @param {*} value - * @return {*|Boolean} + * Check if value is primitive */ - - function toBoolean(value) { - return value === 'true' ? true : value === 'false' ? false : value; + function isPrimitive (value) { + return typeof value === 'string' || typeof value === 'number' } /** - * Strip quotes from a string - * - * @param {String} str - * @return {String | false} + * Create a cached version of a pure function. */ - - function stripQuotes(str) { - var a = str.charCodeAt(0); - var b = str.charCodeAt(str.length - 1); - return a === b && (a === 0x22 || a === 0x27) ? str.slice(1, -1) : str; + function cached (fn) { + var cache = Object.create(null); + return function cachedFn (str) { + var hit = cache[str]; + return hit || (cache[str] = fn(str)) + } } /** * Camelize a hyphen-delmited string. - * - * @param {String} str - * @return {String} */ - var camelizeRE = /-(\w)/g; - - function camelize(str) { - return str.replace(camelizeRE, toUpper); - } - - function toUpper(_, c) { - return c ? c.toUpperCase() : ''; - } + var camelize = cached(function (str) { + return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ''; }) + }); /** - * Hyphenate a camelCase string. - * - * @param {String} str - * @return {String} + * Capitalize a string. */ - - var hyphenateRE = /([a-z\d])([A-Z])/g; - - function hyphenate(str) { - return str.replace(hyphenateRE, '$1-$2').toLowerCase(); - } + var capitalize = cached(function (str) { + return str.charAt(0).toUpperCase() + str.slice(1) + }); /** - * Converts hyphen/underscore/slash delimitered names into - * camelized classNames. - * - * e.g. my-component => MyComponent - * some_else => SomeElse - * some/comp => SomeComp - * - * @param {String} str - * @return {String} + * Hyphenate a camelCase string. */ - - var classifyRE = /(?:^|[-_\/])(\w)/g; - - function classify(str) { - return str.replace(classifyRE, toUpper); - } + var hyphenateRE = /([^-])([A-Z])/g; + var hyphenate = cached(function (str) { + return str + .replace(hyphenateRE, '$1-$2') + .replace(hyphenateRE, '$1-$2') + .toLowerCase() + }); /** * Simple bind, faster than native - * - * @param {Function} fn - * @param {Object} ctx - * @return {Function} */ - - function bind(fn, ctx) { - return function (a) { + function bind$1 (fn, ctx) { + function boundFn (a) { var l = arguments.length; - return l ? l > 1 ? fn.apply(ctx, arguments) : fn.call(ctx, a) : fn.call(ctx); - }; + return l + ? l > 1 + ? fn.apply(ctx, arguments) + : fn.call(ctx, a) + : fn.call(ctx) + } + // record original fn length + boundFn._length = fn.length; + return boundFn } /** * Convert an Array-like object to a real Array. - * - * @param {Array-like} list - * @param {Number} [start] - start index - * @return {Array} */ - - function toArray(list, start) { + function toArray (list, start) { start = start || 0; var i = list.length - start; var ret = new Array(i); while (i--) { ret[i] = list[i + start]; } - return ret; + return ret } /** * Mix properties into target object. - * - * @param {Object} to - * @param {Object} from */ - - function extend(to, from) { - var keys = Object.keys(from); - var i = keys.length; - while (i--) { - to[keys[i]] = from[keys[i]]; + function extend (to, _from) { + for (var key in _from) { + to[key] = _from[key]; } - return to; + return to } /** * Quick object check - this is primarily used to tell * Objects from primitive values when we know the value * is a JSON-compliant type. - * - * @param {*} obj - * @return {Boolean} */ - - function isObject(obj) { - return obj !== null && typeof obj === 'object'; + function isObject (obj) { + return obj !== null && typeof obj === 'object' } /** * Strict object type check. Only returns true * for plain JavaScript objects. - * - * @param {*} obj - * @return {Boolean} */ - var toString = Object.prototype.toString; var OBJECT_STRING = '[object Object]'; - - function isPlainObject(obj) { - return toString.call(obj) === OBJECT_STRING; + function isPlainObject (obj) { + return toString.call(obj) === OBJECT_STRING } /** - * Array type check. - * - * @param {*} obj - * @return {Boolean} + * Merge an Array of Objects into a single Object. */ - - var isArray = Array.isArray; + function toObject (arr) { + var res = {}; + for (var i = 0; i < arr.length; i++) { + if (arr[i]) { + extend(res, arr[i]); + } + } + return res + } /** - * Define a property. - * - * @param {Object} obj - * @param {String} key - * @param {*} val - * @param {Boolean} [enumerable] + * Perform no operation. */ - - function def(obj, key, val, enumerable) { - Object.defineProperty(obj, key, { - value: val, - enumerable: !!enumerable, - writable: true, - configurable: true - }); - } + function noop () {} /** - * Debounce a function so it only gets called after the - * input stops arriving after the given wait period. - * - * @param {Function} func - * @param {Number} wait - * @return {Function} - the debounced function + * Always return false. */ + var no = function () { return false; }; - function _debounce(func, wait) { - var timeout, args, context, timestamp, result; - var later = function later() { - var last = Date.now() - timestamp; - if (last < wait && last >= 0) { - timeout = setTimeout(later, wait - last); - } else { - timeout = null; - result = func.apply(context, args); - if (!timeout) context = args = null; - } - }; - return function () { - context = this; - args = arguments; - timestamp = Date.now(); - if (!timeout) { - timeout = setTimeout(later, wait); - } - return result; - }; + /** + * Generate a static keys string from compiler modules. + */ + function genStaticKeys (modules) { + return modules.reduce(function (keys, m) { + return keys.concat(m.staticKeys || []) + }, []).join(',') } /** - * Manual indexOf because it's slightly faster than - * native. - * - * @param {Array} arr - * @param {*} obj + * Check if two values are loosely equal - that is, + * if they are plain objects, do they have the same shape? */ + function looseEqual (a, b) { + /* eslint-disable eqeqeq */ + return a == b || ( + isObject(a) && isObject(b) + ? JSON.stringify(a) === JSON.stringify(b) + : false + ) + /* eslint-enable eqeqeq */ + } - function indexOf(arr, obj) { - var i = arr.length; - while (i--) { - if (arr[i] === obj) return i; + function looseIndexOf (arr, val) { + for (var i = 0; i < arr.length; i++) { + if (looseEqual(arr[i], val)) { return i } } - return -1; + return -1 } + /* */ + + var config = { + /** + * Option merge strategies (used in core/util/options) + */ + optionMergeStrategies: Object.create(null), + + /** + * Whether to suppress warnings. + */ + silent: false, + + /** + * Whether to enable devtools + */ + devtools: process.env.NODE_ENV !== 'production', + + /** + * Error handler for watcher errors + */ + errorHandler: null, + + /** + * Ignore certain custom elements + */ + ignoredElements: null, + + /** + * Custom user key aliases for v-on + */ + keyCodes: Object.create(null), + + /** + * Check if a tag is reserved so that it cannot be registered as a + * component. This is platform-dependent and may be overwritten. + */ + isReservedTag: no, + + /** + * Check if a tag is an unknown element. + * Platform-dependent. + */ + isUnknownElement: no, + + /** + * Get the namespace of an element + */ + getTagNamespace: noop, + + /** + * Check if an attribute must be bound using property, e.g. value + * Platform-dependent. + */ + mustUseProp: no, + + /** + * List of asset types that a component can own. + */ + _assetTypes: [ + 'component', + 'directive', + 'filter' + ], + + /** + * List of lifecycle hooks. + */ + _lifecycleHooks: [ + 'beforeCreate', + 'created', + 'beforeMount', + 'mounted', + 'beforeUpdate', + 'updated', + 'beforeDestroy', + 'destroyed', + 'activated', + 'deactivated' + ], + + /** + * Max circular updates allowed in a scheduler flush cycle. + */ + _maxUpdateCount: 100, + + /** + * Server rendering? + */ + _isServer: process.env.VUE_ENV === 'server' + }; + + /* */ + /** - * Make a cancellable version of an async callback. - * - * @param {Function} fn - * @return {Function} + * Check if a string starts with $ or _ */ - - function cancellable(fn) { - var cb = function cb() { - if (!cb.cancelled) { - return fn.apply(this, arguments); - } - }; - cb.cancel = function () { - cb.cancelled = true; - }; - return cb; + function isReserved (str) { + var c = (str + '').charCodeAt(0); + return c === 0x24 || c === 0x5F } /** - * Check if two values are loosely equal - that is, - * if they are plain objects, do they have the same shape? - * - * @param {*} a - * @param {*} b - * @return {Boolean} + * Define a property. */ + function def (obj, key, val, enumerable) { + Object.defineProperty(obj, key, { + value: val, + enumerable: !!enumerable, + writable: true, + configurable: true + }); + } - function looseEqual(a, b) { - /* eslint-disable eqeqeq */ - return a == b || (isObject(a) && isObject(b) ? JSON.stringify(a) === JSON.stringify(b) : false); - /* eslint-enable eqeqeq */ + /** + * Parse simple path. + */ + var bailRE = /[^\w.$]/; + function parsePath (path) { + if (bailRE.test(path)) { + return + } else { + var segments = path.split('.'); + return function (obj) { + for (var i = 0; i < segments.length; i++) { + if (!obj) { return } + obj = obj[segments[i]]; + } + return obj + } + } } - var hasProto = ('__proto__' in {}); + /* */ + /* globals MutationObserver */ - // Browser environment sniffing - var inBrowser = typeof window !== 'undefined' && Object.prototype.toString.call(window) !== '[object Object]'; + // can we use __proto__? + var hasProto = '__proto__' in {}; - // detect devtools - var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__; + // Browser environment sniffing + var inBrowser = + typeof window !== 'undefined' && + Object.prototype.toString.call(window) !== '[object Object]'; - // UA sniffing for working around browser-specific quirks var UA = inBrowser && window.navigator.userAgent.toLowerCase(); + var isIE = UA && /msie|trident/.test(UA); var isIE9 = UA && UA.indexOf('msie 9.0') > 0; + var isEdge = UA && UA.indexOf('edge/') > 0; var isAndroid = UA && UA.indexOf('android') > 0; + var isIOS = UA && /iphone|ipad|ipod|ios/.test(UA); - var transitionProp = undefined; - var transitionEndEvent = undefined; - var animationProp = undefined; - var animationEndEvent = undefined; + // detect devtools + var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__; - // Transition property/event sniffing - if (inBrowser && !isIE9) { - var isWebkitTrans = window.ontransitionend === undefined && window.onwebkittransitionend !== undefined; - var isWebkitAnim = window.onanimationend === undefined && window.onwebkitanimationend !== undefined; - transitionProp = isWebkitTrans ? 'WebkitTransition' : 'transition'; - transitionEndEvent = isWebkitTrans ? 'webkitTransitionEnd' : 'transitionend'; - animationProp = isWebkitAnim ? 'WebkitAnimation' : 'animation'; - animationEndEvent = isWebkitAnim ? 'webkitAnimationEnd' : 'animationend'; + /* istanbul ignore next */ + function isNative (Ctor) { + return /native code/.test(Ctor.toString()) } /** - * Defer a task to execute it asynchronously. Ideally this - * should be executed as a microtask, so we leverage - * MutationObserver if it's available, and fallback to - * setTimeout(0). - * - * @param {Function} cb - * @param {Object} ctx + * Defer a task to execute it asynchronously. */ - var nextTick = (function () { var callbacks = []; var pending = false; var timerFunc; - function nextTickHandler() { + + function nextTickHandler () { pending = false; var copies = callbacks.slice(0); - callbacks = []; + callbacks.length = 0; for (var i = 0; i < copies.length; i++) { copies[i](); } } + // the nextTick behavior leverages the microtask queue, which can be accessed + // via either native Promise.then or MutationObserver. + // MutationObserver has wider support, however it is seriously bugged in + // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It + // completely stops working after triggering a few times... so, if native + // Promise is available, we will use it: /* istanbul ignore if */ - if (typeof MutationObserver !== 'undefined') { + if (typeof Promise !== 'undefined' && isNative(Promise)) { + var p = Promise.resolve(); + timerFunc = function () { + p.then(nextTickHandler); + // in problematic UIWebViews, Promise.then doesn't completely break, but + // it can get stuck in a weird state where callbacks are pushed into the + // microtask queue but the queue isn't being flushed, until the browser + // needs to do some other work, e.g. handle a timer. Therefore we can + // "force" the microtask queue to be flushed by adding an empty timer. + if (isIOS) { setTimeout(noop); } + }; + } else if (typeof MutationObserver !== 'undefined' && ( + isNative(MutationObserver) || + // PhantomJS and iOS 7.x + MutationObserver.toString() === '[object MutationObserverConstructor]' + )) { + // use MutationObserver where native Promise is not available, + // e.g. PhantomJS IE11, iOS7, Android 4.4 var counter = 1; var observer = new MutationObserver(nextTickHandler); - var textNode = document.createTextNode(counter); + var textNode = document.createTextNode(String(counter)); observer.observe(textNode, { characterData: true }); timerFunc = function () { counter = (counter + 1) % 2; - textNode.data = counter; + textNode.data = String(counter); }; } else { - // webpack attempts to inject a shim for setImmediate - // if it is used as a global, so we have to work around that to - // avoid bundling unnecessary code. - var context = inBrowser ? window : typeof global !== 'undefined' ? global : {}; - timerFunc = context.setImmediate || setTimeout; - } - return function (cb, ctx) { - var func = ctx ? function () { - cb.call(ctx); - } : cb; + // fallback to setTimeout + /* istanbul ignore next */ + timerFunc = function () { + setTimeout(nextTickHandler, 0); + }; + } + + return function queueNextTick (cb, ctx) { + var func = ctx + ? function () { cb.call(ctx); } + : cb; callbacks.push(func); - if (pending) return; - pending = true; - timerFunc(nextTickHandler, 0); - }; + if (!pending) { + pending = true; + timerFunc(); + } + } })(); - function Cache(limit) { - this.size = 0; - this.limit = limit; - this.head = this.tail = undefined; - this._keymap = Object.create(null); + var _Set; + /* istanbul ignore if */ + if (typeof Set !== 'undefined' && isNative(Set)) { + // use native Set when available. + _Set = Set; + } else { + // a non-standard Set polyfill that only works with primitive keys. + _Set = (function () { + function Set () { + this.set = Object.create(null); + } + Set.prototype.has = function has (key) { + return this.set[key] !== undefined + }; + Set.prototype.add = function add (key) { + this.set[key] = 1; + }; + Set.prototype.clear = function clear () { + this.set = Object.create(null); + }; + + return Set; + }()); } - var p = Cache.prototype; + /* not type checking this file because flow doesn't play well with Proxy */ - /** - * Put into the cache associated with . - * Returns the entry which was removed to make room for - * the new entry. Otherwise undefined is returned. - * (i.e. if there was enough room already). - * - * @param {String} key - * @param {*} value - * @return {Entry|undefined} - */ + var hasProxy; + var proxyHandlers; + var initProxy; - p.put = function (key, value) { - var removed; - if (this.size === this.limit) { - removed = this.shift(); - } + if (process.env.NODE_ENV !== 'production') { + var allowedGlobals = makeMap( + 'Infinity,undefined,NaN,isFinite,isNaN,' + + 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + + 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' + + 'require' // for Webpack/Browserify + ); + + hasProxy = + typeof Proxy !== 'undefined' && + Proxy.toString().match(/native code/); + + proxyHandlers = { + has: function has (target, key) { + var has = key in target; + var isAllowed = allowedGlobals(key) || key.charAt(0) === '_'; + if (!has && !isAllowed) { + warn( + "Property or method \"" + key + "\" is not defined on the instance but " + + "referenced during render. Make sure to declare reactive data " + + "properties in the data option.", + target + ); + } + return has || !isAllowed + } + }; - var entry = this.get(key, true); - if (!entry) { - entry = { - key: key - }; - this._keymap[key] = entry; - if (this.tail) { - this.tail.newer = entry; - entry.older = this.tail; + initProxy = function initProxy (vm) { + if (hasProxy) { + vm._renderProxy = new Proxy(vm, proxyHandlers); } else { - this.head = entry; + vm._renderProxy = vm; } - this.tail = entry; - this.size++; - } - entry.value = value; + }; + } - return removed; - }; + /* */ - /** - * Purge the least recently used (oldest) entry from the - * cache. Returns the removed entry or undefined if the - * cache was empty. - */ - p.shift = function () { - var entry = this.head; - if (entry) { - this.head = this.head.newer; - this.head.older = undefined; - entry.newer = entry.older = undefined; - this._keymap[entry.key] = undefined; - this.size--; - } - return entry; - }; + var uid$2 = 0; /** - * Get and register recent use of . Returns the value - * associated with or undefined if not in cache. - * - * @param {String} key - * @param {Boolean} returnEntry - * @return {Entry|*} - */ + * A dep is an observable that can have multiple + * directives subscribing to it. + */ + var Dep = function Dep () { + this.id = uid$2++; + this.subs = []; + }; - p.get = function (key, returnEntry) { - var entry = this._keymap[key]; - if (entry === undefined) return; - if (entry === this.tail) { - return returnEntry ? entry : entry.value; - } - // HEAD--------------TAIL - // <.older .newer> - // <--- add direction -- - // A B C E - if (entry.newer) { - if (entry === this.head) { - this.head = entry.newer; - } - entry.newer.older = entry.older; // C <-- E. - } - if (entry.older) { - entry.older.newer = entry.newer; // C. --> E - } - entry.newer = undefined; // D --x - entry.older = this.tail; // D. --> E - if (this.tail) { - this.tail.newer = entry; // E. <-- D + Dep.prototype.addSub = function addSub (sub) { + this.subs.push(sub); + }; + + Dep.prototype.removeSub = function removeSub (sub) { + remove$1(this.subs, sub); + }; + + Dep.prototype.depend = function depend () { + if (Dep.target) { + Dep.target.addDep(this); } - this.tail = entry; - return returnEntry ? entry : entry.value; }; - var cache$1 = new Cache(1000); - var filterTokenRE = /[^\s'"]+|'[^']*'|"[^"]*"/g; - var reservedArgRE = /^in$|^-?\d+/; + Dep.prototype.notify = function notify () { + // stablize the subscriber list first + var subs = this.subs.slice(); + for (var i = 0, l = subs.length; i < l; i++) { + subs[i].update(); + } + }; - /** - * Parser state - */ + // the current target watcher being evaluated. + // this is globally unique because there could be only one + // watcher being evaluated at any time. + Dep.target = null; + var targetStack = []; - var str; - var dir; - var c; - var prev; - var i; - var l; - var lastFilterIndex; - var inSingle; - var inDouble; - var curly; - var square; - var paren; - /** - * Push a filter to the current directive object - */ + function pushTarget (_target) { + if (Dep.target) { targetStack.push(Dep.target); } + Dep.target = _target; + } - function pushFilter() { - var exp = str.slice(lastFilterIndex, i).trim(); - var filter; - if (exp) { - filter = {}; - var tokens = exp.match(filterTokenRE); - filter.name = tokens[0]; - if (tokens.length > 1) { - filter.args = tokens.slice(1).map(processFilterArg); - } - } - if (filter) { - (dir.filters = dir.filters || []).push(filter); - } - lastFilterIndex = i + 1; + function popTarget () { + Dep.target = targetStack.pop(); } + /* */ + + + var queue = []; + var has$1 = {}; + var circular = {}; + var waiting = false; + var flushing = false; + var index = 0; + /** - * Check if an argument is dynamic and strip quotes. - * - * @param {String} arg - * @return {Object} + * Reset the scheduler's state. */ - - function processFilterArg(arg) { - if (reservedArgRE.test(arg)) { - return { - value: toNumber(arg), - dynamic: false - }; - } else { - var stripped = stripQuotes(arg); - var dynamic = stripped === arg; - return { - value: dynamic ? arg : stripped, - dynamic: dynamic - }; + function resetSchedulerState () { + queue.length = 0; + has$1 = {}; + if (process.env.NODE_ENV !== 'production') { + circular = {}; } + waiting = flushing = false; } /** - * Parse a directive value and extract the expression - * and its filters into a descriptor. - * - * Example: - * - * "a + 1 | uppercase" will yield: - * { - * expression: 'a + 1', - * filters: [ - * { name: 'uppercase', args: null } - * ] - * } - * - * @param {String} s - * @return {Object} + * Flush both queues and run the watchers. */ + function flushSchedulerQueue () { + flushing = true; - function parseDirective(s) { - var hit = cache$1.get(s); - if (hit) { - return hit; - } - - // reset parser state - str = s; - inSingle = inDouble = false; - curly = square = paren = 0; - lastFilterIndex = 0; - dir = {}; - - for (i = 0, l = str.length; i < l; i++) { - prev = c; - c = str.charCodeAt(i); - if (inSingle) { - // check single quote - if (c === 0x27 && prev !== 0x5C) inSingle = !inSingle; - } else if (inDouble) { - // check double quote - if (c === 0x22 && prev !== 0x5C) inDouble = !inDouble; - } else if (c === 0x7C && // pipe - str.charCodeAt(i + 1) !== 0x7C && str.charCodeAt(i - 1) !== 0x7C) { - if (dir.expression == null) { - // first filter, end of expression - lastFilterIndex = i + 1; - dir.expression = str.slice(0, i).trim(); - } else { - // already has filter - pushFilter(); - } - } else { - switch (c) { - case 0x22: - inDouble = true;break; // " - case 0x27: - inSingle = true;break; // ' - case 0x28: - paren++;break; // ( - case 0x29: - paren--;break; // ) - case 0x5B: - square++;break; // [ - case 0x5D: - square--;break; // ] - case 0x7B: - curly++;break; // { - case 0x7D: - curly--;break; // } + // Sort queue before flush. + // This ensures that: + // 1. Components are updated from parent to child. (because parent is always + // created before the child) + // 2. A component's user watchers are run before its render watcher (because + // user watchers are created before the render watcher) + // 3. If a component is destroyed during a parent component's watcher run, + // its watchers can be skipped. + queue.sort(function (a, b) { return a.id - b.id; }); + + // do not cache length because more watchers might be pushed + // as we run existing watchers + for (index = 0; index < queue.length; index++) { + var watcher = queue[index]; + var id = watcher.id; + has$1[id] = null; + watcher.run(); + // in dev build, check and stop circular updates. + if (process.env.NODE_ENV !== 'production' && has$1[id] != null) { + circular[id] = (circular[id] || 0) + 1; + if (circular[id] > config._maxUpdateCount) { + warn( + 'You may have an infinite update loop ' + ( + watcher.user + ? ("in watcher with expression \"" + (watcher.expression) + "\"") + : "in a component render function." + ), + watcher.vm + ); + break } } } - if (dir.expression == null) { - dir.expression = str.slice(0, i).trim(); - } else if (lastFilterIndex !== 0) { - pushFilter(); + // devtool hook + /* istanbul ignore if */ + if (devtools && config.devtools) { + devtools.emit('flush'); } - cache$1.put(s, dir); - return dir; + resetSchedulerState(); } - var directive = Object.freeze({ - parseDirective: parseDirective - }); - - var regexEscapeRE = /[-.*+?^${}()|[\]\/\\]/g; - var cache = undefined; - var tagRE = undefined; - var htmlRE = undefined; /** - * Escape a string so it can be used in a RegExp - * constructor. - * - * @param {String} str + * Push a watcher into the watcher queue. + * Jobs with duplicate IDs will be skipped unless it's + * pushed when the queue is being flushed. */ - - function escapeRegex(str) { - return str.replace(regexEscapeRE, '\\$&'); + function queueWatcher (watcher) { + var id = watcher.id; + if (has$1[id] == null) { + has$1[id] = true; + if (!flushing) { + queue.push(watcher); + } else { + // if already flushing, splice the watcher based on its id + // if already past its id, it will be run next immediately. + var i = queue.length - 1; + while (i >= 0 && queue[i].id > watcher.id) { + i--; + } + queue.splice(Math.max(i, index) + 1, 0, watcher); + } + // queue the flush + if (!waiting) { + waiting = true; + nextTick(flushSchedulerQueue); + } + } } - function compileRegex() { - var open = escapeRegex(config.delimiters[0]); - var close = escapeRegex(config.delimiters[1]); - var unsafeOpen = escapeRegex(config.unsafeDelimiters[0]); - var unsafeClose = escapeRegex(config.unsafeDelimiters[1]); - tagRE = new RegExp(unsafeOpen + '((?:.|\\n)+?)' + unsafeClose + '|' + open + '((?:.|\\n)+?)' + close, 'g'); - htmlRE = new RegExp('^' + unsafeOpen + '.*' + unsafeClose + '$'); - // reset cache - cache = new Cache(1000); - } + /* */ + + var uid$1 = 0; /** - * Parse a template text string into an array of tokens. - * - * @param {String} text - * @return {Array | null} - * - {String} type - * - {String} value - * - {Boolean} [html] - * - {Boolean} [oneTime] + * A watcher parses an expression, collects dependencies, + * and fires callback when the expression value changes. + * This is used for both the $watch() api and directives. */ + var Watcher = function Watcher ( + vm, + expOrFn, + cb, + options + ) { + if ( options === void 0 ) options = {}; - function parseText(text) { - if (!cache) { - compileRegex(); - } - var hit = cache.get(text); - if (hit) { - return hit; - } - if (!tagRE.test(text)) { - return null; - } - var tokens = []; - var lastIndex = tagRE.lastIndex = 0; - var match, index, html, value, first, oneTime; - /* eslint-disable no-cond-assign */ - while (match = tagRE.exec(text)) { - /* eslint-enable no-cond-assign */ - index = match.index; - // push text token - if (index > lastIndex) { - tokens.push({ - value: text.slice(lastIndex, index) - }); + this.vm = vm; + vm._watchers.push(this); + // options + this.deep = !!options.deep; + this.user = !!options.user; + this.lazy = !!options.lazy; + this.sync = !!options.sync; + this.expression = expOrFn.toString(); + this.cb = cb; + this.id = ++uid$1; // uid for batching + this.active = true; + this.dirty = this.lazy; // for lazy watchers + this.deps = []; + this.newDeps = []; + this.depIds = new _Set(); + this.newDepIds = new _Set(); + // parse expression for getter + if (typeof expOrFn === 'function') { + this.getter = expOrFn; + } else { + this.getter = parsePath(expOrFn); + if (!this.getter) { + this.getter = function () {}; + process.env.NODE_ENV !== 'production' && warn( + "Failed watching path: \"" + expOrFn + "\" " + + 'Watcher only accepts simple dot-delimited paths. ' + + 'For full control, use a function instead.', + vm + ); } - // tag token - html = htmlRE.test(match[0]); - value = html ? match[1] : match[2]; - first = value.charCodeAt(0); - oneTime = first === 42; // * - value = oneTime ? value.slice(1) : value; - tokens.push({ - tag: true, - value: value.trim(), - html: html, - oneTime: oneTime - }); - lastIndex = index + match[0].length; - } - if (lastIndex < text.length) { - tokens.push({ - value: text.slice(lastIndex) - }); } - cache.put(text, tokens); - return tokens; - } + this.value = this.lazy + ? undefined + : this.get(); + }; /** - * Format a list of tokens into an expression. - * e.g. tokens parsed from 'a {{b}} c' can be serialized - * into one single expression as '"a " + b + " c"'. - * - * @param {Array} tokens - * @param {Vue} [vm] - * @return {String} + * Evaluate the getter, and re-collect dependencies. */ - - function tokensToExp(tokens, vm) { - if (tokens.length > 1) { - return tokens.map(function (token) { - return formatToken(token, vm); - }).join('+'); - } else { - return formatToken(tokens[0], vm, true); + Watcher.prototype.get = function get () { + pushTarget(this); + var value = this.getter.call(this.vm, this.vm); + // "touch" every property so they are all tracked as + // dependencies for deep watching + if (this.deep) { + traverse(value); } - } + popTarget(); + this.cleanupDeps(); + return value + }; /** - * Format a single token. - * - * @param {Object} token - * @param {Vue} [vm] - * @param {Boolean} [single] - * @return {String} + * Add a dependency to this directive. */ - - function formatToken(token, vm, single) { - return token.tag ? token.oneTime && vm ? '"' + vm.$eval(token.value) + '"' : inlineFilters(token.value, single) : '"' + token.value + '"'; - } + Watcher.prototype.addDep = function addDep (dep) { + var id = dep.id; + if (!this.newDepIds.has(id)) { + this.newDepIds.add(id); + this.newDeps.push(dep); + if (!this.depIds.has(id)) { + dep.addSub(this); + } + } + }; /** - * For an attribute with multiple interpolation tags, - * e.g. attr="some-{{thing | filter}}", in order to combine - * the whole thing into a single watchable expression, we - * have to inline those filters. This function does exactly - * that. This is a bit hacky but it avoids heavy changes - * to directive parser and watcher mechanism. - * - * @param {String} exp - * @param {Boolean} single - * @return {String} + * Clean up for dependency collection. */ + Watcher.prototype.cleanupDeps = function cleanupDeps () { + var this$1 = this; - var filterRE = /[^|]\|[^|]/; - function inlineFilters(exp, single) { - if (!filterRE.test(exp)) { - return single ? exp : '(' + exp + ')'; - } else { - var dir = parseDirective(exp); - if (!dir.filters) { - return '(' + exp + ')'; - } else { - return 'this._applyFilters(' + dir.expression + // value - ',null,' + // oldValue (null for read) - JSON.stringify(dir.filters) + // filter descriptors - ',false)'; // write? + var i = this.deps.length; + while (i--) { + var dep = this$1.deps[i]; + if (!this$1.newDepIds.has(dep.id)) { + dep.removeSub(this$1); } } - } - - var text = Object.freeze({ - compileRegex: compileRegex, - parseText: parseText, - tokensToExp: tokensToExp - }); - - var delimiters = ['{{', '}}']; - var unsafeDelimiters = ['{{{', '}}}']; - - var config = Object.defineProperties({ - - /** - * Whether to print debug messages. - * Also enables stack trace for warnings. - * - * @type {Boolean} - */ - - debug: false, - - /** - * Whether to suppress warnings. - * - * @type {Boolean} - */ - - silent: false, - - /** - * Whether to use async rendering. - */ - - async: true, - - /** - * Whether to warn against errors caught when evaluating - * expressions. - */ - - warnExpressionErrors: true, - - /** - * Whether to allow devtools inspection. - * Disabled by default in production builds. - */ - - devtools: process.env.NODE_ENV !== 'production', - - /** - * Internal flag to indicate the delimiters have been - * changed. - * - * @type {Boolean} - */ - - _delimitersChanged: true, - - /** - * List of asset types that a component can own. - * - * @type {Array} - */ - - _assetTypes: ['component', 'directive', 'elementDirective', 'filter', 'transition', 'partial'], - - /** - * prop binding modes - */ - - _propBindingModes: { - ONE_WAY: 0, - TWO_WAY: 1, - ONE_TIME: 2 - }, - - /** - * Max circular updates allowed in a batcher flush cycle. - */ - - _maxUpdateCount: 100 - - }, { - delimiters: { /** - * Interpolation delimiters. Changing these would trigger - * the text parser to re-compile the regular expressions. - * - * @type {Array} - */ + var tmp = this.depIds; + this.depIds = this.newDepIds; + this.newDepIds = tmp; + this.newDepIds.clear(); + tmp = this.deps; + this.deps = this.newDeps; + this.newDeps = tmp; + this.newDeps.length = 0; + }; - get: function get() { - return delimiters; - }, - set: function set(val) { - delimiters = val; - compileRegex(); - }, - configurable: true, - enumerable: true - }, - unsafeDelimiters: { - get: function get() { - return unsafeDelimiters; - }, - set: function set(val) { - unsafeDelimiters = val; - compileRegex(); - }, - configurable: true, - enumerable: true + /** + * Subscriber interface. + * Will be called when a dependency changes. + */ + Watcher.prototype.update = function update () { + /* istanbul ignore else */ + if (this.lazy) { + this.dirty = true; + } else if (this.sync) { + this.run(); + } else { + queueWatcher(this); } - }); - - var warn = undefined; - var formatComponentName = undefined; - - if (process.env.NODE_ENV !== 'production') { - (function () { - var hasConsole = typeof console !== 'undefined'; + }; - warn = function (msg, vm) { - if (hasConsole && !config.silent) { - console.error('[Vue warn]: ' + msg + (vm ? formatComponentName(vm) : '')); + /** + * Scheduler job interface. + * Will be called by the scheduler. + */ + Watcher.prototype.run = function run () { + if (this.active) { + var value = this.get(); + if ( + value !== this.value || + // Deep watchers and watchers on Object/Arrays should fire even + // when the value is the same, because the value may + // have mutated. + isObject(value) || + this.deep + ) { + // set new value + var oldValue = this.value; + this.value = value; + if (this.user) { + try { + this.cb.call(this.vm, value, oldValue); + } catch (e) { + process.env.NODE_ENV !== 'production' && warn( + ("Error in watcher \"" + (this.expression) + "\""), + this.vm + ); + /* istanbul ignore else */ + if (config.errorHandler) { + config.errorHandler.call(null, e, this.vm); + } else { + throw e + } + } + } else { + this.cb.call(this.vm, value, oldValue); } - }; - - formatComponentName = function (vm) { - var name = vm._isVue ? vm.$options.name : vm.name; - return name ? ' (found in component: <' + hyphenate(name) + '>)' : ''; - }; - })(); - } + } + } + }; /** - * Append with transition. - * - * @param {Element} el - * @param {Element} target - * @param {Vue} vm - * @param {Function} [cb] + * Evaluate the value of the watcher. + * This only gets called for lazy watchers. */ - - function appendWithTransition(el, target, vm, cb) { - applyTransition(el, 1, function () { - target.appendChild(el); - }, vm, cb); - } + Watcher.prototype.evaluate = function evaluate () { + this.value = this.get(); + this.dirty = false; + }; /** - * InsertBefore with transition. - * - * @param {Element} el - * @param {Element} target - * @param {Vue} vm - * @param {Function} [cb] + * Depend on all deps collected by this watcher. */ + Watcher.prototype.depend = function depend () { + var this$1 = this; - function beforeWithTransition(el, target, vm, cb) { - applyTransition(el, 1, function () { - before(el, target); - }, vm, cb); - } + var i = this.deps.length; + while (i--) { + this$1.deps[i].depend(); + } + }; /** - * Remove with transition. - * - * @param {Element} el - * @param {Vue} vm - * @param {Function} [cb] + * Remove self from all dependencies' subscriber list. */ + Watcher.prototype.teardown = function teardown () { + var this$1 = this; - function removeWithTransition(el, vm, cb) { - applyTransition(el, -1, function () { - remove(el); - }, vm, cb); - } + if (this.active) { + // remove self from vm's watcher list + // this is a somewhat expensive operation so we skip it + // if the vm is being destroyed or is performing a v-for + // re-render (the watcher list is then filtered by v-for). + if (!this.vm._isBeingDestroyed && !this.vm._vForRemoving) { + remove$1(this.vm._watchers, this); + } + var i = this.deps.length; + while (i--) { + this$1.deps[i].removeSub(this$1); + } + this.active = false; + } + }; /** - * Apply transitions with an operation callback. - * - * @param {Element} el - * @param {Number} direction - * 1: enter - * -1: leave - * @param {Function} op - the actual DOM operation - * @param {Vue} vm - * @param {Function} [cb] + * Recursively traverse an object to evoke all converted + * getters, so that every nested property inside the object + * is collected as a "deep" dependency. */ + var seenObjects = new _Set(); + function traverse (val) { + seenObjects.clear(); + _traverse(val, seenObjects); + } - function applyTransition(el, direction, op, vm, cb) { - var transition = el.__v_trans; - if (!transition || - // skip if there are no js hooks and CSS transition is - // not supported - !transition.hooks && !transitionEndEvent || - // skip transitions for initial compile - !vm._isCompiled || - // if the vm is being manipulated by a parent directive - // during the parent's compilation phase, skip the - // animation. - vm.$parent && !vm.$parent._isCompiled) { - op(); - if (cb) cb(); - return; - } - var action = direction > 0 ? 'enter' : 'leave'; - transition[action](op, cb); - } - - var transition = Object.freeze({ - appendWithTransition: appendWithTransition, - beforeWithTransition: beforeWithTransition, - removeWithTransition: removeWithTransition, - applyTransition: applyTransition - }); - - /** - * Query an element selector if it's not an element already. - * - * @param {String|Element} el - * @return {Element} - */ - - function query(el) { - if (typeof el === 'string') { - var selector = el; - el = document.querySelector(el); - if (!el) { - process.env.NODE_ENV !== 'production' && warn('Cannot find element: ' + selector); + function _traverse (val, seen) { + var i, keys; + var isA = Array.isArray(val); + if ((!isA && !isObject(val)) || !Object.isExtensible(val)) { + return + } + if (val.__ob__) { + var depId = val.__ob__.dep.id; + if (seen.has(depId)) { + return } + seen.add(depId); } - return el; - } - - /** - * Check if a node is in the document. - * Note: document.documentElement.contains should work here - * but always returns false for comment nodes in phantomjs, - * making unit tests difficult. This is fixed by doing the - * contains() check on the node's parentNode instead of - * the node itself. - * - * @param {Node} node - * @return {Boolean} - */ - - function inDoc(node) { - var doc = document.documentElement; - var parent = node && node.parentNode; - return doc === node || doc === parent || !!(parent && parent.nodeType === 1 && doc.contains(parent)); - } - - /** - * Get and remove an attribute from a node. - * - * @param {Node} node - * @param {String} _attr - */ - - function getAttr(node, _attr) { - var val = node.getAttribute(_attr); - if (val !== null) { - node.removeAttribute(_attr); + if (isA) { + i = val.length; + while (i--) { _traverse(val[i], seen); } + } else { + keys = Object.keys(val); + i = keys.length; + while (i--) { _traverse(val[keys[i]], seen); } } - return val; } - /** - * Get an attribute with colon or v-bind: prefix. - * - * @param {Node} node - * @param {String} name - * @return {String|null} + /* + * not type checking this file because flow doesn't play well with + * dynamically accessing methods on Array prototype */ - function getBindAttr(node, name) { - var val = getAttr(node, ':' + name); - if (val === null) { - val = getAttr(node, 'v-bind:' + name); - } - return val; - } + var arrayProto = Array.prototype; + var arrayMethods = Object.create(arrayProto);[ + 'push', + 'pop', + 'shift', + 'unshift', + 'splice', + 'sort', + 'reverse' + ] + .forEach(function (method) { + // cache original method + var original = arrayProto[method]; + def(arrayMethods, method, function mutator () { + var arguments$1 = arguments; - /** - * Check the presence of a bind attribute. - * - * @param {Node} node - * @param {String} name - * @return {Boolean} - */ + // avoid leaking arguments: + // http://jsperf.com/closure-with-arguments + var i = arguments.length; + var args = new Array(i); + while (i--) { + args[i] = arguments$1[i]; + } + var result = original.apply(this, args); + var ob = this.__ob__; + var inserted; + switch (method) { + case 'push': + inserted = args; + break + case 'unshift': + inserted = args; + break + case 'splice': + inserted = args.slice(2); + break + } + if (inserted) { ob.observeArray(inserted); } + // notify change + ob.dep.notify(); + return result + }); + }); - function hasBindAttr(node, name) { - return node.hasAttribute(name) || node.hasAttribute(':' + name) || node.hasAttribute('v-bind:' + name); - } + /* */ + + var arrayKeys = Object.getOwnPropertyNames(arrayMethods); /** - * Insert el before target - * - * @param {Element} el - * @param {Element} target + * By default, when a reactive property is set, the new value is + * also converted to become reactive. However when passing down props, + * we don't want to force conversion because the value may be a nested value + * under a frozen data structure. Converting it would defeat the optimization. */ - - function before(el, target) { - target.parentNode.insertBefore(el, target); - } + var observerState = { + shouldConvert: true, + isSettingProps: false + }; /** - * Insert el after target - * - * @param {Element} el - * @param {Element} target + * Observer class that are attached to each observed + * object. Once attached, the observer converts target + * object's property keys into getter/setters that + * collect dependencies and dispatches updates. */ - - function after(el, target) { - if (target.nextSibling) { - before(el, target.nextSibling); + var Observer = function Observer (value) { + this.value = value; + this.dep = new Dep(); + this.vmCount = 0; + def(value, '__ob__', this); + if (Array.isArray(value)) { + var augment = hasProto + ? protoAugment + : copyAugment; + augment(value, arrayMethods, arrayKeys); + this.observeArray(value); } else { - target.parentNode.appendChild(el); + this.walk(value); } - } - - /** - * Remove el from DOM - * - * @param {Element} el - */ - - function remove(el) { - el.parentNode.removeChild(el); - } + }; /** - * Prepend el to target - * - * @param {Element} el - * @param {Element} target + * Walk through each property and convert them into + * getter/setters. This method should only be called when + * value type is Object. */ - - function prepend(el, target) { - if (target.firstChild) { - before(el, target.firstChild); - } else { - target.appendChild(el); + Observer.prototype.walk = function walk (obj) { + var keys = Object.keys(obj); + for (var i = 0; i < keys.length; i++) { + defineReactive$$1(obj, keys[i], obj[keys[i]]); } - } + }; /** - * Replace target with el - * - * @param {Element} target - * @param {Element} el + * Observe a list of Array items. */ - - function replace(target, el) { - var parent = target.parentNode; - if (parent) { - parent.replaceChild(el, target); + Observer.prototype.observeArray = function observeArray (items) { + for (var i = 0, l = items.length; i < l; i++) { + observe(items[i]); } - } + }; + + // helpers /** - * Add event listener shorthand. - * - * @param {Element} el - * @param {String} event - * @param {Function} cb - * @param {Boolean} [useCapture] + * Augment an target Object or Array by intercepting + * the prototype chain using __proto__ */ - - function on(el, event, cb, useCapture) { - el.addEventListener(event, cb, useCapture); + function protoAugment (target, src) { + /* eslint-disable no-proto */ + target.__proto__ = src; + /* eslint-enable no-proto */ } /** - * Remove event listener shorthand. + * Augment an target Object or Array by defining + * hidden properties. * - * @param {Element} el - * @param {String} event - * @param {Function} cb + * istanbul ignore next */ - - function off(el, event, cb) { - el.removeEventListener(event, cb); + function copyAugment (target, src, keys) { + for (var i = 0, l = keys.length; i < l; i++) { + var key = keys[i]; + def(target, key, src[key]); + } } /** - * For IE9 compat: when both class and :class are present - * getAttribute('class') returns wrong value... - * - * @param {Element} el - * @return {String} + * Attempt to create an observer instance for a value, + * returns the new observer if successfully observed, + * or the existing observer if the value already has one. */ - - function getClass(el) { - var classname = el.className; - if (typeof classname === 'object') { - classname = classname.baseVal || ''; + function observe (value) { + if (!isObject(value)) { + return + } + var ob; + if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { + ob = value.__ob__; + } else if ( + observerState.shouldConvert && + !config._isServer && + (Array.isArray(value) || isPlainObject(value)) && + Object.isExtensible(value) && + !value._isVue + ) { + ob = new Observer(value); } - return classname; + return ob } /** - * In IE9, setAttribute('class') will result in empty class - * if the element also has the :class attribute; However in - * PhantomJS, setting `className` does not work on SVG elements... - * So we have to do a conditional check here. - * - * @param {Element} el - * @param {String} cls + * Define a reactive property on an Object. */ + function defineReactive$$1 ( + obj, + key, + val, + customSetter + ) { + var dep = new Dep(); - function setClass(el, cls) { - /* istanbul ignore if */ - if (isIE9 && !/svg$/.test(el.namespaceURI)) { - el.className = cls; - } else { - el.setAttribute('class', cls); + var property = Object.getOwnPropertyDescriptor(obj, key); + if (property && property.configurable === false) { + return } - } - /** - * Add class with compatibility for IE & SVG - * - * @param {Element} el - * @param {String} cls - */ + // cater for pre-defined getter/setters + var getter = property && property.get; + var setter = property && property.set; - function addClass(el, cls) { - if (el.classList) { - el.classList.add(cls); - } else { - var cur = ' ' + getClass(el) + ' '; - if (cur.indexOf(' ' + cls + ' ') < 0) { - setClass(el, (cur + cls).trim()); + var childOb = observe(val); + Object.defineProperty(obj, key, { + enumerable: true, + configurable: true, + get: function reactiveGetter () { + var value = getter ? getter.call(obj) : val; + if (Dep.target) { + dep.depend(); + if (childOb) { + childOb.dep.depend(); + } + if (Array.isArray(value)) { + dependArray(value); + } + } + return value + }, + set: function reactiveSetter (newVal) { + var value = getter ? getter.call(obj) : val; + if (newVal === value) { + return + } + if (process.env.NODE_ENV !== 'production' && customSetter) { + customSetter(); + } + if (setter) { + setter.call(obj, newVal); + } else { + val = newVal; + } + childOb = observe(newVal); + dep.notify(); } - } + }); } /** - * Remove class with compatibility for IE & SVG - * - * @param {Element} el - * @param {String} cls + * Set a property on an object. Adds the new property and + * triggers change notification if the property doesn't + * already exist. */ - - function removeClass(el, cls) { - if (el.classList) { - el.classList.remove(cls); - } else { - var cur = ' ' + getClass(el) + ' '; - var tar = ' ' + cls + ' '; - while (cur.indexOf(tar) >= 0) { - cur = cur.replace(tar, ' '); - } - setClass(el, cur.trim()); + function set (obj, key, val) { + if (Array.isArray(obj)) { + obj.length = Math.max(obj.length, key); + obj.splice(key, 1, val); + return val + } + if (hasOwn(obj, key)) { + obj[key] = val; + return + } + var ob = obj.__ob__; + if (obj._isVue || (ob && ob.vmCount)) { + process.env.NODE_ENV !== 'production' && warn( + 'Avoid adding reactive properties to a Vue instance or its root $data ' + + 'at runtime - declare it upfront in the data option.' + ); + return } - if (!el.className) { - el.removeAttribute('class'); + if (!ob) { + obj[key] = val; + return } + defineReactive$$1(ob.value, key, val); + ob.dep.notify(); + return val } /** - * Extract raw content inside an element into a temporary - * container div - * - * @param {Element} el - * @param {Boolean} asFragment - * @return {Element|DocumentFragment} + * Delete a property and trigger change if necessary. */ - - function extractContent(el, asFragment) { - var child; - var rawContent; - /* istanbul ignore if */ - if (isTemplate(el) && isFragment(el.content)) { - el = el.content; + function del (obj, key) { + var ob = obj.__ob__; + if (obj._isVue || (ob && ob.vmCount)) { + process.env.NODE_ENV !== 'production' && warn( + 'Avoid deleting properties on a Vue instance or its root $data ' + + '- just set it to null.' + ); + return } - if (el.hasChildNodes()) { - trimNode(el); - rawContent = asFragment ? document.createDocumentFragment() : document.createElement('div'); - /* eslint-disable no-cond-assign */ - while (child = el.firstChild) { - /* eslint-enable no-cond-assign */ - rawContent.appendChild(child); - } + if (!hasOwn(obj, key)) { + return + } + delete obj[key]; + if (!ob) { + return } - return rawContent; + ob.dep.notify(); } /** - * Trim possible empty head/tail text and comment - * nodes inside a parent. - * - * @param {Node} node + * Collect dependencies on array elements when the array is touched, since + * we cannot intercept array element access like property getters. */ - - function trimNode(node) { - var child; - /* eslint-disable no-sequences */ - while ((child = node.firstChild, isTrimmable(child))) { - node.removeChild(child); - } - while ((child = node.lastChild, isTrimmable(child))) { - node.removeChild(child); + function dependArray (value) { + for (var e = void 0, i = 0, l = value.length; i < l; i++) { + e = value[i]; + e && e.__ob__ && e.__ob__.dep.depend(); + if (Array.isArray(e)) { + dependArray(e); + } } - /* eslint-enable no-sequences */ - } - - function isTrimmable(node) { - return node && (node.nodeType === 3 && !node.data.trim() || node.nodeType === 8); } - /** - * Check if an element is a template tag. - * Note if the template appears inside an SVG its tagName - * will be in lowercase. - * - * @param {Element} el - */ + /* */ - function isTemplate(el) { - return el.tagName && el.tagName.toLowerCase() === 'template'; + function initState (vm) { + vm._watchers = []; + initProps(vm); + initData(vm); + initComputed(vm); + initMethods(vm); + initWatch(vm); } - /** - * Create an "anchor" for performing dom insertion/removals. - * This is used in a number of scenarios: - * - fragment instance - * - v-html - * - v-if - * - v-for - * - component - * - * @param {String} content - * @param {Boolean} persist - IE trashes empty textNodes on - * cloneNode(true), so in certain - * cases the anchor needs to be - * non-empty to be persisted in - * templates. - * @return {Comment|Text} - */ + function initProps (vm) { + var props = vm.$options.props; + if (props) { + var propsData = vm.$options.propsData || {}; + var keys = vm.$options._propKeys = Object.keys(props); + var isRoot = !vm.$parent; + // root instance props should be converted + observerState.shouldConvert = isRoot; + var loop = function ( i ) { + var key = keys[i]; + /* istanbul ignore else */ + if (process.env.NODE_ENV !== 'production') { + defineReactive$$1(vm, key, validateProp(key, props, propsData, vm), function () { + if (vm.$parent && !observerState.isSettingProps) { + warn( + "Avoid mutating a prop directly since the value will be " + + "overwritten whenever the parent component re-renders. " + + "Instead, use a data or computed property based on the prop's " + + "value. Prop being mutated: \"" + key + "\"", + vm + ); + } + }); + } else { + defineReactive$$1(vm, key, validateProp(key, props, propsData, vm)); + } + }; - function createAnchor(content, persist) { - var anchor = config.debug ? document.createComment(content) : document.createTextNode(persist ? ' ' : ''); - anchor.__v_anchor = true; - return anchor; + for (var i = 0; i < keys.length; i++) loop( i ); + observerState.shouldConvert = true; + } } - /** - * Find a component ref attribute that starts with $. - * - * @param {Element} node - * @return {String|undefined} - */ + function initData (vm) { + var data = vm.$options.data; + data = vm._data = typeof data === 'function' + ? data.call(vm) + : data || {}; + if (!isPlainObject(data)) { + data = {}; + process.env.NODE_ENV !== 'production' && warn( + 'data functions should return an object.', + vm + ); + } + // proxy data on instance + var keys = Object.keys(data); + var props = vm.$options.props; + var i = keys.length; + while (i--) { + if (props && hasOwn(props, keys[i])) { + process.env.NODE_ENV !== 'production' && warn( + "The data property \"" + (keys[i]) + "\" is already declared as a prop. " + + "Use prop default value instead.", + vm + ); + } else { + proxy(vm, keys[i]); + } + } + // observe data + observe(data); + data.__ob__ && data.__ob__.vmCount++; + } - var refRE = /^v-ref:/; + var computedSharedDefinition = { + enumerable: true, + configurable: true, + get: noop, + set: noop + }; - function findRef(node) { - if (node.hasAttributes()) { - var attrs = node.attributes; - for (var i = 0, l = attrs.length; i < l; i++) { - var name = attrs[i].name; - if (refRE.test(name)) { - return camelize(name.replace(refRE, '')); + function initComputed (vm) { + var computed = vm.$options.computed; + if (computed) { + for (var key in computed) { + var userDef = computed[key]; + if (typeof userDef === 'function') { + computedSharedDefinition.get = makeComputedGetter(userDef, vm); + computedSharedDefinition.set = noop; + } else { + computedSharedDefinition.get = userDef.get + ? userDef.cache !== false + ? makeComputedGetter(userDef.get, vm) + : bind$1(userDef.get, vm) + : noop; + computedSharedDefinition.set = userDef.set + ? bind$1(userDef.set, vm) + : noop; } + Object.defineProperty(vm, key, computedSharedDefinition); } } } - /** - * Map a function to a range of nodes . - * - * @param {Node} node - * @param {Node} end - * @param {Function} op - */ - - function mapNodeRange(node, end, op) { - var next; - while (node !== end) { - next = node.nextSibling; - op(node); - node = next; + function makeComputedGetter (getter, owner) { + var watcher = new Watcher(owner, getter, noop, { + lazy: true + }); + return function computedGetter () { + if (watcher.dirty) { + watcher.evaluate(); + } + if (Dep.target) { + watcher.depend(); + } + return watcher.value } - op(end); } - /** - * Remove a range of nodes with transition, store - * the nodes in a fragment with correct ordering, - * and call callback when done. - * - * @param {Node} start - * @param {Node} end - * @param {Vue} vm - * @param {DocumentFragment} frag - * @param {Function} cb - */ - - function removeNodeRange(start, end, vm, frag, cb) { - var done = false; - var removed = 0; - var nodes = []; - mapNodeRange(start, end, function (node) { - if (node === end) done = true; - nodes.push(node); - removeWithTransition(node, vm, onRemoved); - }); - function onRemoved() { - removed++; - if (done && removed >= nodes.length) { - for (var i = 0; i < nodes.length; i++) { - frag.appendChild(nodes[i]); + function initMethods (vm) { + var methods = vm.$options.methods; + if (methods) { + for (var key in methods) { + vm[key] = methods[key] == null ? noop : bind$1(methods[key], vm); + if (process.env.NODE_ENV !== 'production') { + methods[key] == null && warn( + "method \"" + key + "\" has an undefined value in the component definition. " + + "Did you reference the function correctly?", + vm + ); + hasOwn(Vue$1.prototype, key) && warn( + ("Avoid overriding Vue's internal method \"" + key + "\"."), + vm + ); } - cb && cb(); } } } - /** - * Check if a node is a DocumentFragment. - * - * @param {Node} node - * @return {Boolean} - */ - - function isFragment(node) { - return node && node.nodeType === 11; + function initWatch (vm) { + var watch = vm.$options.watch; + if (watch) { + for (var key in watch) { + var handler = watch[key]; + if (Array.isArray(handler)) { + for (var i = 0; i < handler.length; i++) { + createWatcher(vm, key, handler[i]); + } + } else { + createWatcher(vm, key, handler); + } + } + } } - /** - * Get outerHTML of elements, taking care - * of SVG elements in IE as well. - * - * @param {Element} el - * @return {String} - */ - - function getOuterHTML(el) { - if (el.outerHTML) { - return el.outerHTML; - } else { - var container = document.createElement('div'); - container.appendChild(el.cloneNode(true)); - return container.innerHTML; + function createWatcher (vm, key, handler) { + var options; + if (isPlainObject(handler)) { + options = handler; + handler = handler.handler; } + if (typeof handler === 'string') { + handler = vm[handler]; + } + vm.$watch(key, handler, options); } - var commonTagRE = /^(div|p|span|img|a|b|i|br|ul|ol|li|h1|h2|h3|h4|h5|h6|code|pre|table|th|td|tr|form|label|input|select|option|nav|article|section|header|footer)$/i; - var reservedTagRE = /^(slot|partial|component)$/i; - - var isUnknownElement = undefined; - if (process.env.NODE_ENV !== 'production') { - isUnknownElement = function (el, tag) { - if (tag.indexOf('-') > -1) { - // http://stackoverflow.com/a/28210364/1070244 - return el.constructor === window.HTMLUnknownElement || el.constructor === window.HTMLElement; - } else { - return (/HTMLUnknownElement/.test(el.toString()) && - // Chrome returns unknown for several HTML5 elements. - // https://code.google.com/p/chromium/issues/detail?id=540526 - !/^(data|time|rtc|rb)$/.test(tag) - ); - } + function stateMixin (Vue) { + // flow somehow has problems with directly declared definition object + // when using Object.defineProperty, so we have to procedurally build up + // the object here. + var dataDef = {}; + dataDef.get = function () { + return this._data }; - } - - /** - * Check if an element is a component, if yes return its - * component id. - * - * @param {Element} el - * @param {Object} options - * @return {Object|undefined} - */ - - function checkComponentAttr(el, options) { - var tag = el.tagName.toLowerCase(); - var hasAttrs = el.hasAttributes(); - if (!commonTagRE.test(tag) && !reservedTagRE.test(tag)) { - if (resolveAsset(options, 'components', tag)) { - return { id: tag }; - } else { - var is = hasAttrs && getIsBinding(el); - if (is) { - return is; - } else if (process.env.NODE_ENV !== 'production') { - var expectedTag = options._componentNameMap && options._componentNameMap[tag]; - if (expectedTag) { - warn('Unknown custom element: <' + tag + '> - ' + 'did you mean <' + expectedTag + '>? ' + 'HTML is case-insensitive, remember to use kebab-case in templates.'); - } else if (isUnknownElement(el, tag)) { - warn('Unknown custom element: <' + tag + '> - did you ' + 'register the component correctly? For recursive components, ' + 'make sure to provide the "name" option.'); - } - } - } - } else if (hasAttrs) { - return getIsBinding(el); + if (process.env.NODE_ENV !== 'production') { + dataDef.set = function (newData) { + warn( + 'Avoid replacing instance root $data. ' + + 'Use nested data properties instead.', + this + ); + }; } - } + Object.defineProperty(Vue.prototype, '$data', dataDef); - /** - * Get "is" binding from an element. - * - * @param {Element} el - * @return {Object|undefined} - */ + Vue.prototype.$set = set; + Vue.prototype.$delete = del; - function getIsBinding(el) { - // dynamic syntax - var exp = getAttr(el, 'is'); - if (exp != null) { - return { id: exp }; - } else { - exp = getBindAttr(el, 'is'); - if (exp != null) { - return { id: exp, dynamic: true }; + Vue.prototype.$watch = function ( + expOrFn, + cb, + options + ) { + var vm = this; + options = options || {}; + options.user = true; + var watcher = new Watcher(vm, expOrFn, cb, options); + if (options.immediate) { + cb.call(vm, watcher.value); } - } - } - - /** - * Option overwriting strategies are functions that handle - * how to merge a parent option value and a child option - * value into the final value. - * - * All strategy functions follow the same signature: - * - * @param {*} parentVal - * @param {*} childVal - * @param {Vue} [vm] - */ - - var strats = config.optionMergeStrategies = Object.create(null); - - /** - * Helper that recursively merges two data objects together. - */ - - function mergeData(to, from) { - var key, toVal, fromVal; - for (key in from) { - toVal = to[key]; - fromVal = from[key]; - if (!hasOwn(to, key)) { - set(to, key, fromVal); - } else if (isObject(toVal) && isObject(fromVal)) { - mergeData(toVal, fromVal); + return function unwatchFn () { + watcher.teardown(); } - } - return to; + }; } - /** - * Data - */ - - strats.data = function (parentVal, childVal, vm) { - if (!vm) { - // in a Vue.extend merge, both should be functions - if (!childVal) { - return parentVal; - } - if (typeof childVal !== 'function') { - process.env.NODE_ENV !== 'production' && warn('The "data" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.', vm); - return parentVal; - } - if (!parentVal) { - return childVal; - } - // when parentVal & childVal are both present, - // we need to return a function that returns the - // merged result of both functions... no need to - // check if parentVal is a function here because - // it has to be a function to pass previous merges. - return function mergedDataFn() { - return mergeData(childVal.call(this), parentVal.call(this)); - }; - } else if (parentVal || childVal) { - return function mergedInstanceDataFn() { - // instance merge - var instanceData = typeof childVal === 'function' ? childVal.call(vm) : childVal; - var defaultData = typeof parentVal === 'function' ? parentVal.call(vm) : undefined; - if (instanceData) { - return mergeData(instanceData, defaultData); - } else { - return defaultData; + function proxy (vm, key) { + if (!isReserved(key)) { + Object.defineProperty(vm, key, { + configurable: true, + enumerable: true, + get: function proxyGetter () { + return vm._data[key] + }, + set: function proxySetter (val) { + vm._data[key] = val; } - }; - } - }; - - /** - * El - */ - - strats.el = function (parentVal, childVal, vm) { - if (!vm && childVal && typeof childVal !== 'function') { - process.env.NODE_ENV !== 'production' && warn('The "el" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.', vm); - return; + }); } - var ret = childVal || parentVal; - // invoke the element factory if this is instance merge - return vm && typeof ret === 'function' ? ret.call(vm) : ret; - }; - - /** - * Hooks and param attributes are merged as arrays. - */ - - strats.init = strats.created = strats.ready = strats.attached = strats.detached = strats.beforeCompile = strats.compiled = strats.beforeDestroy = strats.destroyed = strats.activate = function (parentVal, childVal) { - return childVal ? parentVal ? parentVal.concat(childVal) : isArray(childVal) ? childVal : [childVal] : parentVal; - }; - - /** - * Assets - * - * When a vm is present (instance creation), we need to do - * a three-way merge between constructor options, instance - * options and parent options. - */ - - function mergeAssets(parentVal, childVal) { - var res = Object.create(parentVal); - return childVal ? extend(res, guardArrayAssets(childVal)) : res; } - config._assetTypes.forEach(function (type) { - strats[type + 's'] = mergeAssets; - }); - - /** - * Events & Watchers. - * - * Events & watchers hashes should not overwrite one - * another, so we merge them as arrays. - */ - - strats.watch = strats.events = function (parentVal, childVal) { - if (!childVal) return parentVal; - if (!parentVal) return childVal; - var ret = {}; - extend(ret, parentVal); - for (var key in childVal) { - var parent = ret[key]; - var child = childVal[key]; - if (parent && !isArray(parent)) { - parent = [parent]; - } - ret[key] = parent ? parent.concat(child) : [child]; - } - return ret; - }; - - /** - * Other object hashes. - */ - - strats.props = strats.methods = strats.computed = function (parentVal, childVal) { - if (!childVal) return parentVal; - if (!parentVal) return childVal; - var ret = Object.create(null); - extend(ret, parentVal); - extend(ret, childVal); - return ret; + /* */ + + var VNode = function VNode ( + tag, + data, + children, + text, + elm, + ns, + context, + componentOptions + ) { + this.tag = tag; + this.data = data; + this.children = children; + this.text = text; + this.elm = elm; + this.ns = ns; + this.context = context; + this.functionalContext = undefined; + this.key = data && data.key; + this.componentOptions = componentOptions; + this.child = undefined; + this.parent = undefined; + this.raw = false; + this.isStatic = false; + this.isRootInsert = true; + this.isComment = false; + this.isCloned = false; + this.isOnce = false; }; - /** - * Default strategy. - */ - - var defaultStrat = function defaultStrat(parentVal, childVal) { - return childVal === undefined ? parentVal : childVal; + var emptyVNode = function () { + var node = new VNode(); + node.text = ''; + node.isComment = true; + return node }; - /** - * Make sure component options get converted to actual - * constructors. - * - * @param {Object} options - */ - - function guardComponents(options) { - if (options.components) { - var components = options.components = guardArrayAssets(options.components); - var ids = Object.keys(components); - var def; - if (process.env.NODE_ENV !== 'production') { - var map = options._componentNameMap = {}; - } - for (var i = 0, l = ids.length; i < l; i++) { - var key = ids[i]; - if (commonTagRE.test(key) || reservedTagRE.test(key)) { - process.env.NODE_ENV !== 'production' && warn('Do not use built-in or reserved HTML elements as component ' + 'id: ' + key); - continue; - } - // record a all lowercase <-> kebab-case mapping for - // possible custom element case error warning - if (process.env.NODE_ENV !== 'production') { - map[key.replace(/-/g, '').toLowerCase()] = hyphenate(key); - } - def = components[key]; - if (isPlainObject(def)) { - components[key] = Vue.extend(def); - } + // optimized shallow clone + // used for static nodes and slot nodes because they may be reused across + // multiple renders, cloning them avoids errors when DOM manipulations rely + // on their elm reference. + function cloneVNode (vnode) { + var cloned = new VNode( + vnode.tag, + vnode.data, + vnode.children, + vnode.text, + vnode.elm, + vnode.ns, + vnode.context, + vnode.componentOptions + ); + cloned.isStatic = vnode.isStatic; + cloned.key = vnode.key; + cloned.isCloned = true; + return cloned + } + + function cloneVNodes (vnodes) { + var res = new Array(vnodes.length); + for (var i = 0; i < vnodes.length; i++) { + res[i] = cloneVNode(vnodes[i]); + } + return res + } + + /* */ + + function mergeVNodeHook (def, hookKey, hook, key) { + key = key + hookKey; + var injectedHash = def.__injected || (def.__injected = {}); + if (!injectedHash[key]) { + injectedHash[key] = true; + var oldHook = def[hookKey]; + if (oldHook) { + def[hookKey] = function () { + oldHook.apply(this, arguments); + hook.apply(this, arguments); + }; + } else { + def[hookKey] = hook; } } } - /** - * Ensure all props option syntax are normalized into the - * Object-based format. - * - * @param {Object} options - */ + /* */ - function guardProps(options) { - var props = options.props; - var i, val; - if (isArray(props)) { - options.props = {}; - i = props.length; - while (i--) { - val = props[i]; - if (typeof val === 'string') { - options.props[val] = null; - } else if (val.name) { - options.props[val.name] = val; - } - } - } else if (isPlainObject(props)) { - var keys = Object.keys(props); - i = keys.length; - while (i--) { - val = props[keys[i]]; - if (typeof val === 'function') { - props[keys[i]] = { type: val }; + function updateListeners ( + on, + oldOn, + add, + remove$$1, + vm + ) { + var name, cur, old, fn, event, capture; + for (name in on) { + cur = on[name]; + old = oldOn[name]; + if (!cur) { + process.env.NODE_ENV !== 'production' && warn( + "Invalid handler for event \"" + name + "\": got " + String(cur), + vm + ); + } else if (!old) { + capture = name.charAt(0) === '!'; + event = capture ? name.slice(1) : name; + if (Array.isArray(cur)) { + add(event, (cur.invoker = arrInvoker(cur)), capture); + } else { + if (!cur.invoker) { + fn = cur; + cur = on[name] = {}; + cur.fn = fn; + cur.invoker = fnInvoker(cur); + } + add(event, cur.invoker, capture); } - } - } - } - - /** - * Guard an Array-format assets option and converted it - * into the key-value Object format. - * - * @param {Object|Array} assets - * @return {Object} - */ - - function guardArrayAssets(assets) { - if (isArray(assets)) { - var res = {}; - var i = assets.length; - var asset; - while (i--) { - asset = assets[i]; - var id = typeof asset === 'function' ? asset.options && asset.options.name || asset.id : asset.name || asset.id; - if (!id) { - process.env.NODE_ENV !== 'production' && warn('Array-syntax assets must provide a "name" or "id" field.'); + } else if (cur !== old) { + if (Array.isArray(old)) { + old.length = cur.length; + for (var i = 0; i < old.length; i++) { old[i] = cur[i]; } + on[name] = old; } else { - res[id] = asset; + old.fn = cur; + on[name] = old; } } - return res; - } - return assets; - } - - /** - * Merge two option objects into a new one. - * Core utility used in both instantiation and inheritance. - * - * @param {Object} parent - * @param {Object} child - * @param {Vue} [vm] - if vm is present, indicates this is - * an instantiation merge. - */ - - function mergeOptions(parent, child, vm) { - guardComponents(child); - guardProps(child); - var options = {}; - var key; - if (child.mixins) { - for (var i = 0, l = child.mixins.length; i < l; i++) { - parent = mergeOptions(parent, child.mixins[i], vm); - } - } - for (key in parent) { - mergeField(key); } - for (key in child) { - if (!hasOwn(parent, key)) { - mergeField(key); + for (name in oldOn) { + if (!on[name]) { + event = name.charAt(0) === '!' ? name.slice(1) : name; + remove$$1(event, oldOn[name].invoker); } } - function mergeField(key) { - var strat = strats[key] || defaultStrat; - options[key] = strat(parent[key], child[key], vm, key); - } - return options; } - /** - * Resolve an asset. - * This function is used because child instances need access - * to assets defined in its ancestor chain. - * - * @param {Object} options - * @param {String} type - * @param {String} id - * @param {Boolean} warnMissing - * @return {Object|Function} - */ + function arrInvoker (arr) { + return function (ev) { + var arguments$1 = arguments; - function resolveAsset(options, type, id, warnMissing) { - /* istanbul ignore if */ - if (typeof id !== 'string') { - return; - } - var assets = options[type]; - var camelizedId; - var res = assets[id] || - // camelCase ID - assets[camelizedId = camelize(id)] || - // Pascal Case ID - assets[camelizedId.charAt(0).toUpperCase() + camelizedId.slice(1)]; - if (process.env.NODE_ENV !== 'production' && warnMissing && !res) { - warn('Failed to resolve ' + type.slice(0, -1) + ': ' + id, options); + var single = arguments.length === 1; + for (var i = 0; i < arr.length; i++) { + single ? arr[i](ev) : arr[i].apply(null, arguments$1); + } } - return res; - } - - var uid$1 = 0; - - /** - * A dep is an observable that can have multiple - * directives subscribing to it. - * - * @constructor - */ - function Dep() { - this.id = uid$1++; - this.subs = []; } - // the current target watcher being evaluated. - // this is globally unique because there could be only one - // watcher being evaluated at any time. - Dep.target = null; - - /** - * Add a directive subscriber. - * - * @param {Directive} sub - */ - - Dep.prototype.addSub = function (sub) { - this.subs.push(sub); - }; - - /** - * Remove a directive subscriber. - * - * @param {Directive} sub - */ - - Dep.prototype.removeSub = function (sub) { - this.subs.$remove(sub); - }; - - /** - * Add self as a dependency to the target watcher. - */ - - Dep.prototype.depend = function () { - Dep.target.addDep(this); - }; - - /** - * Notify all subscribers of a new value. - */ - - Dep.prototype.notify = function () { - // stablize the subscriber list first - var subs = toArray(this.subs); - for (var i = 0, l = subs.length; i < l; i++) { - subs[i].update(); - } - }; - - var arrayProto = Array.prototype; - var arrayMethods = Object.create(arrayProto) - - /** - * Intercept mutating methods and emit events - */ - - ;['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(function (method) { - // cache original method - var original = arrayProto[method]; - def(arrayMethods, method, function mutator() { - // avoid leaking arguments: - // http://jsperf.com/closure-with-arguments - var i = arguments.length; - var args = new Array(i); - while (i--) { - args[i] = arguments[i]; - } - var result = original.apply(this, args); - var ob = this.__ob__; - var inserted; - switch (method) { - case 'push': - inserted = args; - break; - case 'unshift': - inserted = args; - break; - case 'splice': - inserted = args.slice(2); - break; - } - if (inserted) ob.observeArray(inserted); - // notify change - ob.dep.notify(); - return result; - }); - }); - - /** - * Swap the element at the given index with a new value - * and emits corresponding event. - * - * @param {Number} index - * @param {*} val - * @return {*} - replaced element - */ - - def(arrayProto, '$set', function $set(index, val) { - if (index >= this.length) { - this.length = Number(index) + 1; - } - return this.splice(index, 1, val)[0]; - }); - - /** - * Convenience method to remove the element at given index or target element reference. - * - * @param {*} item - */ - - def(arrayProto, '$remove', function $remove(item) { - /* istanbul ignore if */ - if (!this.length) return; - var index = indexOf(this, item); - if (index > -1) { - return this.splice(index, 1); - } - }); - - var arrayKeys = Object.getOwnPropertyNames(arrayMethods); - - /** - * By default, when a reactive property is set, the new value is - * also converted to become reactive. However in certain cases, e.g. - * v-for scope alias and props, we don't want to force conversion - * because the value may be a nested value under a frozen data structure. - * - * So whenever we want to set a reactive property without forcing - * conversion on the new value, we wrap that call inside this function. - */ - - var shouldConvert = true; - - function withoutConversion(fn) { - shouldConvert = false; - fn(); - shouldConvert = true; - } - - /** - * Observer class that are attached to each observed - * object. Once attached, the observer converts target - * object's property keys into getter/setters that - * collect dependencies and dispatches updates. - * - * @param {Array|Object} value - * @constructor - */ - - function Observer(value) { - this.value = value; - this.dep = new Dep(); - def(value, '__ob__', this); - if (isArray(value)) { - var augment = hasProto ? protoAugment : copyAugment; - augment(value, arrayMethods, arrayKeys); - this.observeArray(value); - } else { - this.walk(value); - } - } - - // Instance methods - - /** - * Walk through each property and convert them into - * getter/setters. This method should only be called when - * value type is Object. - * - * @param {Object} obj - */ - - Observer.prototype.walk = function (obj) { - var keys = Object.keys(obj); - for (var i = 0, l = keys.length; i < l; i++) { - this.convert(keys[i], obj[keys[i]]); - } - }; - - /** - * Observe a list of Array items. - * - * @param {Array} items - */ - - Observer.prototype.observeArray = function (items) { - for (var i = 0, l = items.length; i < l; i++) { - observe(items[i]); - } - }; - - /** - * Convert a property into getter/setter so we can emit - * the events when the property is accessed/changed. - * - * @param {String} key - * @param {*} val - */ - - Observer.prototype.convert = function (key, val) { - defineReactive(this.value, key, val); - }; - - /** - * Add an owner vm, so that when $set/$delete mutations - * happen we can notify owner vms to proxy the keys and - * digest the watchers. This is only called when the object - * is observed as an instance's root $data. - * - * @param {Vue} vm - */ - - Observer.prototype.addVm = function (vm) { - (this.vms || (this.vms = [])).push(vm); - }; - - /** - * Remove an owner vm. This is called when the object is - * swapped out as an instance's $data object. - * - * @param {Vue} vm - */ - - Observer.prototype.removeVm = function (vm) { - this.vms.$remove(vm); - }; - - // helpers - - /** - * Augment an target Object or Array by intercepting - * the prototype chain using __proto__ - * - * @param {Object|Array} target - * @param {Object} src - */ - - function protoAugment(target, src) { - /* eslint-disable no-proto */ - target.__proto__ = src; - /* eslint-enable no-proto */ - } - - /** - * Augment an target Object or Array by defining - * hidden properties. - * - * @param {Object|Array} target - * @param {Object} proto - */ - - function copyAugment(target, src, keys) { - for (var i = 0, l = keys.length; i < l; i++) { - var key = keys[i]; - def(target, key, src[key]); - } - } - - /** - * Attempt to create an observer instance for a value, - * returns the new observer if successfully observed, - * or the existing observer if the value already has one. - * - * @param {*} value - * @param {Vue} [vm] - * @return {Observer|undefined} - * @static - */ - - function observe(value, vm) { - if (!value || typeof value !== 'object') { - return; - } - var ob; - if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { - ob = value.__ob__; - } else if (shouldConvert && (isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value._isVue) { - ob = new Observer(value); - } - if (ob && vm) { - ob.addVm(vm); - } - return ob; - } - - /** - * Define a reactive property on an Object. - * - * @param {Object} obj - * @param {String} key - * @param {*} val - */ - - function defineReactive(obj, key, val) { - var dep = new Dep(); - - var property = Object.getOwnPropertyDescriptor(obj, key); - if (property && property.configurable === false) { - return; - } - - // cater for pre-defined getter/setters - var getter = property && property.get; - var setter = property && property.set; - - var childOb = observe(val); - Object.defineProperty(obj, key, { - enumerable: true, - configurable: true, - get: function reactiveGetter() { - var value = getter ? getter.call(obj) : val; - if (Dep.target) { - dep.depend(); - if (childOb) { - childOb.dep.depend(); - } - if (isArray(value)) { - for (var e, i = 0, l = value.length; i < l; i++) { - e = value[i]; - e && e.__ob__ && e.__ob__.dep.depend(); - } - } - } - return value; - }, - set: function reactiveSetter(newVal) { - var value = getter ? getter.call(obj) : val; - if (newVal === value) { - return; - } - if (setter) { - setter.call(obj, newVal); - } else { - val = newVal; - } - childOb = observe(newVal); - dep.notify(); - } - }); - } - - - - var util = Object.freeze({ - defineReactive: defineReactive, - set: set, - del: del, - hasOwn: hasOwn, - isLiteral: isLiteral, - isReserved: isReserved, - _toString: _toString, - toNumber: toNumber, - toBoolean: toBoolean, - stripQuotes: stripQuotes, - camelize: camelize, - hyphenate: hyphenate, - classify: classify, - bind: bind, - toArray: toArray, - extend: extend, - isObject: isObject, - isPlainObject: isPlainObject, - def: def, - debounce: _debounce, - indexOf: indexOf, - cancellable: cancellable, - looseEqual: looseEqual, - isArray: isArray, - hasProto: hasProto, - inBrowser: inBrowser, - devtools: devtools, - isIE9: isIE9, - isAndroid: isAndroid, - get transitionProp () { return transitionProp; }, - get transitionEndEvent () { return transitionEndEvent; }, - get animationProp () { return animationProp; }, - get animationEndEvent () { return animationEndEvent; }, - nextTick: nextTick, - query: query, - inDoc: inDoc, - getAttr: getAttr, - getBindAttr: getBindAttr, - hasBindAttr: hasBindAttr, - before: before, - after: after, - remove: remove, - prepend: prepend, - replace: replace, - on: on, - off: off, - setClass: setClass, - addClass: addClass, - removeClass: removeClass, - extractContent: extractContent, - trimNode: trimNode, - isTemplate: isTemplate, - createAnchor: createAnchor, - findRef: findRef, - mapNodeRange: mapNodeRange, - removeNodeRange: removeNodeRange, - isFragment: isFragment, - getOuterHTML: getOuterHTML, - mergeOptions: mergeOptions, - resolveAsset: resolveAsset, - checkComponentAttr: checkComponentAttr, - commonTagRE: commonTagRE, - reservedTagRE: reservedTagRE, - get warn () { return warn; } - }); - - var uid = 0; - - function initMixin (Vue) { - /** - * The main init sequence. This is called for every - * instance, including ones that are created from extended - * constructors. - * - * @param {Object} options - this options object should be - * the result of merging class - * options and the options passed - * in to the constructor. - */ - - Vue.prototype._init = function (options) { - options = options || {}; - - this.$el = null; - this.$parent = options.parent; - this.$root = this.$parent ? this.$parent.$root : this; - this.$children = []; - this.$refs = {}; // child vm references - this.$els = {}; // element references - this._watchers = []; // all watchers as an array - this._directives = []; // all directives - - // a uid - this._uid = uid++; - - // a flag to avoid this being observed - this._isVue = true; - - // events bookkeeping - this._events = {}; // registered callbacks - this._eventsCount = {}; // for $broadcast optimization - - // fragment instance properties - this._isFragment = false; - this._fragment = // @type {DocumentFragment} - this._fragmentStart = // @type {Text|Comment} - this._fragmentEnd = null; // @type {Text|Comment} - - // lifecycle state - this._isCompiled = this._isDestroyed = this._isReady = this._isAttached = this._isBeingDestroyed = this._vForRemoving = false; - this._unlinkFn = null; - - // context: - // if this is a transcluded component, context - // will be the common parent vm of this instance - // and its host. - this._context = options._context || this.$parent; - - // scope: - // if this is inside an inline v-for, the scope - // will be the intermediate scope created for this - // repeat fragment. this is used for linking props - // and container directives. - this._scope = options._scope; - - // fragment: - // if this instance is compiled inside a Fragment, it - // needs to reigster itself as a child of that fragment - // for attach/detach to work properly. - this._frag = options._frag; - if (this._frag) { - this._frag.children.push(this); - } - - // push self into parent / transclusion host - if (this.$parent) { - this.$parent.$children.push(this); - } - - // merge options. - options = this.$options = mergeOptions(this.constructor.options, options, this); - - // set ref - this._updateRef(); - - // initialize data as empty object. - // it will be filled up in _initScope(). - this._data = {}; - - // save raw constructor data before merge - // so that we know which properties are provided at - // instantiation. - this._runtimeData = options.data; - - // call init hook - this._callHook('init'); - - // initialize data observation and scope inheritance. - this._initState(); - - // setup event system and option events. - this._initEvents(); - - // call created hook - this._callHook('created'); - - // if `el` option is passed, start compilation. - if (options.el) { - this.$mount(options.el); - } - }; - } - - var pathCache = new Cache(1000); - - // actions - var APPEND = 0; - var PUSH = 1; - var INC_SUB_PATH_DEPTH = 2; - var PUSH_SUB_PATH = 3; - - // states - var BEFORE_PATH = 0; - var IN_PATH = 1; - var BEFORE_IDENT = 2; - var IN_IDENT = 3; - var IN_SUB_PATH = 4; - var IN_SINGLE_QUOTE = 5; - var IN_DOUBLE_QUOTE = 6; - var AFTER_PATH = 7; - var ERROR = 8; - - var pathStateMachine = []; - - pathStateMachine[BEFORE_PATH] = { - 'ws': [BEFORE_PATH], - 'ident': [IN_IDENT, APPEND], - '[': [IN_SUB_PATH], - 'eof': [AFTER_PATH] - }; - - pathStateMachine[IN_PATH] = { - 'ws': [IN_PATH], - '.': [BEFORE_IDENT], - '[': [IN_SUB_PATH], - 'eof': [AFTER_PATH] - }; - - pathStateMachine[BEFORE_IDENT] = { - 'ws': [BEFORE_IDENT], - 'ident': [IN_IDENT, APPEND] - }; - - pathStateMachine[IN_IDENT] = { - 'ident': [IN_IDENT, APPEND], - '0': [IN_IDENT, APPEND], - 'number': [IN_IDENT, APPEND], - 'ws': [IN_PATH, PUSH], - '.': [BEFORE_IDENT, PUSH], - '[': [IN_SUB_PATH, PUSH], - 'eof': [AFTER_PATH, PUSH] - }; - - pathStateMachine[IN_SUB_PATH] = { - "'": [IN_SINGLE_QUOTE, APPEND], - '"': [IN_DOUBLE_QUOTE, APPEND], - '[': [IN_SUB_PATH, INC_SUB_PATH_DEPTH], - ']': [IN_PATH, PUSH_SUB_PATH], - 'eof': ERROR, - 'else': [IN_SUB_PATH, APPEND] - }; - - pathStateMachine[IN_SINGLE_QUOTE] = { - "'": [IN_SUB_PATH, APPEND], - 'eof': ERROR, - 'else': [IN_SINGLE_QUOTE, APPEND] - }; - - pathStateMachine[IN_DOUBLE_QUOTE] = { - '"': [IN_SUB_PATH, APPEND], - 'eof': ERROR, - 'else': [IN_DOUBLE_QUOTE, APPEND] - }; - - /** - * Determine the type of a character in a keypath. - * - * @param {Char} ch - * @return {String} type - */ - - function getPathCharType(ch) { - if (ch === undefined) { - return 'eof'; - } - - var code = ch.charCodeAt(0); - - switch (code) { - case 0x5B: // [ - case 0x5D: // ] - case 0x2E: // . - case 0x22: // " - case 0x27: // ' - case 0x30: - // 0 - return ch; - - case 0x5F: // _ - case 0x24: - // $ - return 'ident'; - - case 0x20: // Space - case 0x09: // Tab - case 0x0A: // Newline - case 0x0D: // Return - case 0xA0: // No-break space - case 0xFEFF: // Byte Order Mark - case 0x2028: // Line Separator - case 0x2029: - // Paragraph Separator - return 'ws'; - } - - // a-z, A-Z - if (code >= 0x61 && code <= 0x7A || code >= 0x41 && code <= 0x5A) { - return 'ident'; - } - - // 1-9 - if (code >= 0x31 && code <= 0x39) { - return 'number'; - } - - return 'else'; - } - - /** - * Format a subPath, return its plain form if it is - * a literal string or number. Otherwise prepend the - * dynamic indicator (*). - * - * @param {String} path - * @return {String} - */ - - function formatSubPath(path) { - var trimmed = path.trim(); - // invalid leading 0 - if (path.charAt(0) === '0' && isNaN(path)) { - return false; - } - return isLiteral(trimmed) ? stripQuotes(trimmed) : '*' + trimmed; - } - - /** - * Parse a string path into an array of segments - * - * @param {String} path - * @return {Array|undefined} - */ - - function parse(path) { - var keys = []; - var index = -1; - var mode = BEFORE_PATH; - var subPathDepth = 0; - var c, newChar, key, type, transition, action, typeMap; - - var actions = []; - - actions[PUSH] = function () { - if (key !== undefined) { - keys.push(key); - key = undefined; - } - }; - - actions[APPEND] = function () { - if (key === undefined) { - key = newChar; - } else { - key += newChar; - } - }; - - actions[INC_SUB_PATH_DEPTH] = function () { - actions[APPEND](); - subPathDepth++; - }; - - actions[PUSH_SUB_PATH] = function () { - if (subPathDepth > 0) { - subPathDepth--; - mode = IN_SUB_PATH; - actions[APPEND](); - } else { - subPathDepth = 0; - key = formatSubPath(key); - if (key === false) { - return false; - } else { - actions[PUSH](); - } - } - }; - - function maybeUnescapeQuote() { - var nextChar = path[index + 1]; - if (mode === IN_SINGLE_QUOTE && nextChar === "'" || mode === IN_DOUBLE_QUOTE && nextChar === '"') { - index++; - newChar = '\\' + nextChar; - actions[APPEND](); - return true; - } - } - - while (mode != null) { - index++; - c = path[index]; - - if (c === '\\' && maybeUnescapeQuote()) { - continue; - } - - type = getPathCharType(c); - typeMap = pathStateMachine[mode]; - transition = typeMap[type] || typeMap['else'] || ERROR; - - if (transition === ERROR) { - return; // parse error - } - - mode = transition[0]; - action = actions[transition[1]]; - if (action) { - newChar = transition[2]; - newChar = newChar === undefined ? c : newChar; - if (action() === false) { - return; - } - } - - if (mode === AFTER_PATH) { - keys.raw = path; - return keys; - } - } - } - - /** - * External parse that check for a cache hit first - * - * @param {String} path - * @return {Array|undefined} - */ - - function parsePath(path) { - var hit = pathCache.get(path); - if (!hit) { - hit = parse(path); - if (hit) { - pathCache.put(path, hit); - } - } - return hit; - } - - /** - * Get from an object from a path string - * - * @param {Object} obj - * @param {String} path - */ - - function getPath(obj, path) { - return parseExpression(path).get(obj); - } - - /** - * Warn against setting non-existent root path on a vm. - */ - - var warnNonExistent; - if (process.env.NODE_ENV !== 'production') { - warnNonExistent = function (path, vm) { - warn('You are setting a non-existent path "' + path.raw + '" ' + 'on a vm instance. Consider pre-initializing the property ' + 'with the "data" option for more reliable reactivity ' + 'and better performance.', vm); - }; - } - - /** - * Set on an object from a path - * - * @param {Object} obj - * @param {String | Array} path - * @param {*} val - */ - - function setPath(obj, path, val) { - var original = obj; - if (typeof path === 'string') { - path = parse(path); - } - if (!path || !isObject(obj)) { - return false; - } - var last, key; - for (var i = 0, l = path.length; i < l; i++) { - last = obj; - key = path[i]; - if (key.charAt(0) === '*') { - key = parseExpression(key.slice(1)).get.call(original, original); - } - if (i < l - 1) { - obj = obj[key]; - if (!isObject(obj)) { - obj = {}; - if (process.env.NODE_ENV !== 'production' && last._isVue) { - warnNonExistent(path, last); - } - set(last, key, obj); - } - } else { - if (isArray(obj)) { - obj.$set(key, val); - } else if (key in obj) { - obj[key] = val; - } else { - if (process.env.NODE_ENV !== 'production' && obj._isVue) { - warnNonExistent(path, obj); - } - set(obj, key, val); - } - } - } - return true; - } - - var path = Object.freeze({ - parsePath: parsePath, - getPath: getPath, - setPath: setPath - }); - - var expressionCache = new Cache(1000); - - var allowedKeywords = 'Math,Date,this,true,false,null,undefined,Infinity,NaN,' + 'isNaN,isFinite,decodeURI,decodeURIComponent,encodeURI,' + 'encodeURIComponent,parseInt,parseFloat'; - var allowedKeywordsRE = new RegExp('^(' + allowedKeywords.replace(/,/g, '\\b|') + '\\b)'); - - // keywords that don't make sense inside expressions - var improperKeywords = 'break,case,class,catch,const,continue,debugger,default,' + 'delete,do,else,export,extends,finally,for,function,if,' + 'import,in,instanceof,let,return,super,switch,throw,try,' + 'var,while,with,yield,enum,await,implements,package,' + 'protected,static,interface,private,public'; - var improperKeywordsRE = new RegExp('^(' + improperKeywords.replace(/,/g, '\\b|') + '\\b)'); - - var wsRE = /\s/g; - var newlineRE = /\n/g; - var saveRE = /[\{,]\s*[\w\$_]+\s*:|('(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`)|new |typeof |void /g; - var restoreRE = /"(\d+)"/g; - var pathTestRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['.*?'\]|\[".*?"\]|\[\d+\]|\[[A-Za-z_$][\w$]*\])*$/; - var identRE = /[^\w$\.](?:[A-Za-z_$][\w$]*)/g; - var booleanLiteralRE = /^(?:true|false)$/; - - /** - * Save / Rewrite / Restore - * - * When rewriting paths found in an expression, it is - * possible for the same letter sequences to be found in - * strings and Object literal property keys. Therefore we - * remove and store these parts in a temporary array, and - * restore them after the path rewrite. - */ - - var saved = []; - - /** - * Save replacer - * - * The save regex can match two possible cases: - * 1. An opening object literal - * 2. A string - * If matched as a plain string, we need to escape its - * newlines, since the string needs to be preserved when - * generating the function body. - * - * @param {String} str - * @param {String} isString - str if matched as a string - * @return {String} - placeholder with index - */ - - function save(str, isString) { - var i = saved.length; - saved[i] = isString ? str.replace(newlineRE, '\\n') : str; - return '"' + i + '"'; - } - - /** - * Path rewrite replacer - * - * @param {String} raw - * @return {String} - */ - - function rewrite(raw) { - var c = raw.charAt(0); - var path = raw.slice(1); - if (allowedKeywordsRE.test(path)) { - return raw; - } else { - path = path.indexOf('"') > -1 ? path.replace(restoreRE, restore) : path; - return c + 'scope.' + path; - } - } - - /** - * Restore replacer - * - * @param {String} str - * @param {String} i - matched save index - * @return {String} - */ - - function restore(str, i) { - return saved[i]; - } - - /** - * Rewrite an expression, prefixing all path accessors with - * `scope.` and generate getter/setter functions. - * - * @param {String} exp - * @return {Function} - */ - - function compileGetter(exp) { - if (improperKeywordsRE.test(exp)) { - process.env.NODE_ENV !== 'production' && warn('Avoid using reserved keywords in expression: ' + exp); - } - // reset state - saved.length = 0; - // save strings and object literal keys - var body = exp.replace(saveRE, save).replace(wsRE, ''); - // rewrite all paths - // pad 1 space here becaue the regex matches 1 extra char - body = (' ' + body).replace(identRE, rewrite).replace(restoreRE, restore); - return makeGetterFn(body); - } - - /** - * Build a getter function. Requires eval. - * - * We isolate the try/catch so it doesn't affect the - * optimization of the parse function when it is not called. - * - * @param {String} body - * @return {Function|undefined} - */ - - function makeGetterFn(body) { - try { - /* eslint-disable no-new-func */ - return new Function('scope', 'return ' + body + ';'); - /* eslint-enable no-new-func */ - } catch (e) { - process.env.NODE_ENV !== 'production' && warn('Invalid expression. ' + 'Generated function body: ' + body); - } - } - - /** - * Compile a setter function for the expression. - * - * @param {String} exp - * @return {Function|undefined} - */ - - function compileSetter(exp) { - var path = parsePath(exp); - if (path) { - return function (scope, val) { - setPath(scope, path, val); - }; - } else { - process.env.NODE_ENV !== 'production' && warn('Invalid setter expression: ' + exp); - } - } - - /** - * Parse an expression into re-written getter/setters. - * - * @param {String} exp - * @param {Boolean} needSet - * @return {Function} - */ - - function parseExpression(exp, needSet) { - exp = exp.trim(); - // try cache - var hit = expressionCache.get(exp); - if (hit) { - if (needSet && !hit.set) { - hit.set = compileSetter(hit.exp); - } - return hit; - } - var res = { exp: exp }; - res.get = isSimplePath(exp) && exp.indexOf('[') < 0 - // optimized super simple getter - ? makeGetterFn('scope.' + exp) - // dynamic getter - : compileGetter(exp); - if (needSet) { - res.set = compileSetter(exp); - } - expressionCache.put(exp, res); - return res; - } - - /** - * Check if an expression is a simple path. - * - * @param {String} exp - * @return {Boolean} - */ - - function isSimplePath(exp) { - return pathTestRE.test(exp) && - // don't treat true/false as paths - !booleanLiteralRE.test(exp) && - // Math constants e.g. Math.PI, Math.E etc. - exp.slice(0, 5) !== 'Math.'; - } - - var expression = Object.freeze({ - parseExpression: parseExpression, - isSimplePath: isSimplePath - }); - - // we have two separate queues: one for directive updates - // and one for user watcher registered via $watch(). - // we want to guarantee directive updates to be called - // before user watchers so that when user watchers are - // triggered, the DOM would have already been in updated - // state. - - var queueIndex; - var queue = []; - var userQueue = []; - var has = {}; - var circular = {}; - var waiting = false; - var internalQueueDepleted = false; - - /** - * Reset the batcher's state. - */ - - function resetBatcherState() { - queue = []; - userQueue = []; - has = {}; - circular = {}; - waiting = internalQueueDepleted = false; - } - - /** - * Flush both queues and run the watchers. - */ - - function flushBatcherQueue() { - runBatcherQueue(queue); - internalQueueDepleted = true; - runBatcherQueue(userQueue); - // dev tool hook - /* istanbul ignore if */ - if (devtools && config.devtools) { - devtools.emit('flush'); - } - resetBatcherState(); - } - - /** - * Run the watchers in a single queue. - * - * @param {Array} queue - */ - - function runBatcherQueue(queue) { - // do not cache length because more watchers might be pushed - // as we run existing watchers - for (queueIndex = 0; queueIndex < queue.length; queueIndex++) { - var watcher = queue[queueIndex]; - var id = watcher.id; - has[id] = null; - watcher.run(); - // in dev build, check and stop circular updates. - if (process.env.NODE_ENV !== 'production' && has[id] != null) { - circular[id] = (circular[id] || 0) + 1; - if (circular[id] > config._maxUpdateCount) { - warn('You may have an infinite update loop for watcher ' + 'with expression "' + watcher.expression + '"', watcher.vm); - break; - } - } - } - } - - /** - * Push a watcher into the watcher queue. - * Jobs with duplicate IDs will be skipped unless it's - * pushed when the queue is being flushed. - * - * @param {Watcher} watcher - * properties: - * - {Number} id - * - {Function} run - */ - - function pushWatcher(watcher) { - var id = watcher.id; - if (has[id] == null) { - if (internalQueueDepleted && !watcher.user) { - // an internal watcher triggered by a user watcher... - // let's run it immediately after current user watcher is done. - userQueue.splice(queueIndex + 1, 0, watcher); - } else { - // push watcher into appropriate queue - var q = watcher.user ? userQueue : queue; - has[id] = q.length; - q.push(watcher); - // queue the flush - if (!waiting) { - waiting = true; - nextTick(flushBatcherQueue); - } - } - } - } - - var uid$2 = 0; - - /** - * A watcher parses an expression, collects dependencies, - * and fires callback when the expression value changes. - * This is used for both the $watch() api and directives. - * - * @param {Vue} vm - * @param {String|Function} expOrFn - * @param {Function} cb - * @param {Object} options - * - {Array} filters - * - {Boolean} twoWay - * - {Boolean} deep - * - {Boolean} user - * - {Boolean} sync - * - {Boolean} lazy - * - {Function} [preProcess] - * - {Function} [postProcess] - * @constructor - */ - function Watcher(vm, expOrFn, cb, options) { - // mix in options - if (options) { - extend(this, options); - } - var isFn = typeof expOrFn === 'function'; - this.vm = vm; - vm._watchers.push(this); - this.expression = expOrFn; - this.cb = cb; - this.id = ++uid$2; // uid for batching - this.active = true; - this.dirty = this.lazy; // for lazy watchers - this.deps = []; - this.newDeps = []; - this.depIds = Object.create(null); - this.newDepIds = null; - this.prevError = null; // for async error stacks - // parse expression for getter/setter - if (isFn) { - this.getter = expOrFn; - this.setter = undefined; - } else { - var res = parseExpression(expOrFn, this.twoWay); - this.getter = res.get; - this.setter = res.set; - } - this.value = this.lazy ? undefined : this.get(); - // state for avoiding false triggers for deep and Array - // watchers during vm._digest() - this.queued = this.shallow = false; - } - - /** - * Evaluate the getter, and re-collect dependencies. - */ - - Watcher.prototype.get = function () { - this.beforeGet(); - var scope = this.scope || this.vm; - var value; - try { - value = this.getter.call(scope, scope); - } catch (e) { - if (process.env.NODE_ENV !== 'production' && config.warnExpressionErrors) { - warn('Error when evaluating expression ' + '"' + this.expression + '": ' + e.toString(), this.vm); - } - } - // "touch" every property so they are all tracked as - // dependencies for deep watching - if (this.deep) { - traverse(value); - } - if (this.preProcess) { - value = this.preProcess(value); - } - if (this.filters) { - value = scope._applyFilters(value, null, this.filters, false); - } - if (this.postProcess) { - value = this.postProcess(value); - } - this.afterGet(); - return value; - }; - - /** - * Set the corresponding value with the setter. - * - * @param {*} value - */ - - Watcher.prototype.set = function (value) { - var scope = this.scope || this.vm; - if (this.filters) { - value = scope._applyFilters(value, this.value, this.filters, true); - } - try { - this.setter.call(scope, scope, value); - } catch (e) { - if (process.env.NODE_ENV !== 'production' && config.warnExpressionErrors) { - warn('Error when evaluating setter ' + '"' + this.expression + '": ' + e.toString(), this.vm); - } - } - // two-way sync for v-for alias - var forContext = scope.$forContext; - if (forContext && forContext.alias === this.expression) { - if (forContext.filters) { - process.env.NODE_ENV !== 'production' && warn('It seems you are using two-way binding on ' + 'a v-for alias (' + this.expression + '), and the ' + 'v-for has filters. This will not work properly. ' + 'Either remove the filters or use an array of ' + 'objects and bind to object properties instead.', this.vm); - return; - } - forContext._withLock(function () { - if (scope.$key) { - // original is an object - forContext.rawValue[scope.$key] = value; - } else { - forContext.rawValue.$set(scope.$index, value); - } - }); - } - }; - - /** - * Prepare for dependency collection. - */ - - Watcher.prototype.beforeGet = function () { - Dep.target = this; - this.newDepIds = Object.create(null); - this.newDeps.length = 0; - }; - - /** - * Add a dependency to this directive. - * - * @param {Dep} dep - */ - - Watcher.prototype.addDep = function (dep) { - var id = dep.id; - if (!this.newDepIds[id]) { - this.newDepIds[id] = true; - this.newDeps.push(dep); - if (!this.depIds[id]) { - dep.addSub(this); - } - } - }; - - /** - * Clean up for dependency collection. - */ - - Watcher.prototype.afterGet = function () { - Dep.target = null; - var i = this.deps.length; - while (i--) { - var dep = this.deps[i]; - if (!this.newDepIds[dep.id]) { - dep.removeSub(this); - } - } - this.depIds = this.newDepIds; - var tmp = this.deps; - this.deps = this.newDeps; - this.newDeps = tmp; - }; - - /** - * Subscriber interface. - * Will be called when a dependency changes. - * - * @param {Boolean} shallow - */ - - Watcher.prototype.update = function (shallow) { - if (this.lazy) { - this.dirty = true; - } else if (this.sync || !config.async) { - this.run(); - } else { - // if queued, only overwrite shallow with non-shallow, - // but not the other way around. - this.shallow = this.queued ? shallow ? this.shallow : false : !!shallow; - this.queued = true; - // record before-push error stack in debug mode - /* istanbul ignore if */ - if (process.env.NODE_ENV !== 'production' && config.debug) { - this.prevError = new Error('[vue] async stack trace'); - } - pushWatcher(this); - } - }; - - /** - * Batcher job interface. - * Will be called by the batcher. - */ - - Watcher.prototype.run = function () { - if (this.active) { - var value = this.get(); - if (value !== this.value || - // Deep watchers and watchers on Object/Arrays should fire even - // when the value is the same, because the value may - // have mutated; but only do so if this is a - // non-shallow update (caused by a vm digest). - (isObject(value) || this.deep) && !this.shallow) { - // set new value - var oldValue = this.value; - this.value = value; - // in debug + async mode, when a watcher callbacks - // throws, we also throw the saved before-push error - // so the full cross-tick stack trace is available. - var prevError = this.prevError; - /* istanbul ignore if */ - if (process.env.NODE_ENV !== 'production' && config.debug && prevError) { - this.prevError = null; - try { - this.cb.call(this.vm, value, oldValue); - } catch (e) { - nextTick(function () { - throw prevError; - }, 0); - throw e; - } - } else { - this.cb.call(this.vm, value, oldValue); - } - } - this.queued = this.shallow = false; - } - }; - - /** - * Evaluate the value of the watcher. - * This only gets called for lazy watchers. - */ - - Watcher.prototype.evaluate = function () { - // avoid overwriting another watcher that is being - // collected. - var current = Dep.target; - this.value = this.get(); - this.dirty = false; - Dep.target = current; - }; - - /** - * Depend on all deps collected by this watcher. - */ - - Watcher.prototype.depend = function () { - var i = this.deps.length; - while (i--) { - this.deps[i].depend(); - } - }; - - /** - * Remove self from all dependencies' subcriber list. - */ - - Watcher.prototype.teardown = function () { - if (this.active) { - // remove self from vm's watcher list - // this is a somewhat expensive operation so we skip it - // if the vm is being destroyed or is performing a v-for - // re-render (the watcher list is then filtered by v-for). - if (!this.vm._isBeingDestroyed && !this.vm._vForRemoving) { - this.vm._watchers.$remove(this); - } - var i = this.deps.length; - while (i--) { - this.deps[i].removeSub(this); - } - this.active = false; - this.vm = this.cb = this.value = null; - } - }; - - /** - * Recrusively traverse an object to evoke all converted - * getters, so that every nested property inside the object - * is collected as a "deep" dependency. - * - * @param {*} val - */ - - function traverse(val) { - var i, keys; - if (isArray(val)) { - i = val.length; - while (i--) traverse(val[i]); - } else if (isObject(val)) { - keys = Object.keys(val); - i = keys.length; - while (i--) traverse(val[keys[i]]); - } - } - - var text$1 = { - - bind: function bind() { - this.attr = this.el.nodeType === 3 ? 'data' : 'textContent'; - }, - - update: function update(value) { - this.el[this.attr] = _toString(value); - } - }; - - var templateCache = new Cache(1000); - var idSelectorCache = new Cache(1000); - - var map = { - efault: [0, '', ''], - legend: [1, '
', '
'], - tr: [2, '', '
'], - col: [2, '', '
'] - }; - - map.td = map.th = [3, '', '
']; - - map.option = map.optgroup = [1, '']; - - map.thead = map.tbody = map.colgroup = map.caption = map.tfoot = [1, '', '
']; - - map.g = map.defs = map.symbol = map.use = map.image = map.text = map.circle = map.ellipse = map.line = map.path = map.polygon = map.polyline = map.rect = [1, '', '']; - - /** - * Check if a node is a supported template node with a - * DocumentFragment content. - * - * @param {Node} node - * @return {Boolean} - */ - - function isRealTemplate(node) { - return isTemplate(node) && isFragment(node.content); - } - - var tagRE$1 = /<([\w:-]+)/; - var entityRE = /&#?\w+?;/; - - /** - * Convert a string template to a DocumentFragment. - * Determines correct wrapping by tag types. Wrapping - * strategy found in jQuery & component/domify. - * - * @param {String} templateString - * @param {Boolean} raw - * @return {DocumentFragment} - */ - - function stringToFragment(templateString, raw) { - // try a cache hit first - var cacheKey = raw ? templateString : templateString.trim(); - var hit = templateCache.get(cacheKey); - if (hit) { - return hit; - } - - var frag = document.createDocumentFragment(); - var tagMatch = templateString.match(tagRE$1); - var entityMatch = entityRE.test(templateString); - - if (!tagMatch && !entityMatch) { - // text only, return a single text node. - frag.appendChild(document.createTextNode(templateString)); - } else { - var tag = tagMatch && tagMatch[1]; - var wrap = map[tag] || map.efault; - var depth = wrap[0]; - var prefix = wrap[1]; - var suffix = wrap[2]; - var node = document.createElement('div'); - - node.innerHTML = prefix + templateString + suffix; - while (depth--) { - node = node.lastChild; - } - - var child; - /* eslint-disable no-cond-assign */ - while (child = node.firstChild) { - /* eslint-enable no-cond-assign */ - frag.appendChild(child); - } - } - if (!raw) { - trimNode(frag); - } - templateCache.put(cacheKey, frag); - return frag; - } - - /** - * Convert a template node to a DocumentFragment. - * - * @param {Node} node - * @return {DocumentFragment} - */ - - function nodeToFragment(node) { - // if its a template tag and the browser supports it, - // its content is already a document fragment. - if (isRealTemplate(node)) { - trimNode(node.content); - return node.content; - } - // script template - if (node.tagName === 'SCRIPT') { - return stringToFragment(node.textContent); - } - // normal node, clone it to avoid mutating the original - var clonedNode = cloneNode(node); - var frag = document.createDocumentFragment(); - var child; - /* eslint-disable no-cond-assign */ - while (child = clonedNode.firstChild) { - /* eslint-enable no-cond-assign */ - frag.appendChild(child); - } - trimNode(frag); - return frag; - } - - // Test for the presence of the Safari template cloning bug - // https://bugs.webkit.org/showug.cgi?id=137755 - var hasBrokenTemplate = (function () { - /* istanbul ignore else */ - if (inBrowser) { - var a = document.createElement('div'); - a.innerHTML = ''; - return !a.cloneNode(true).firstChild.innerHTML; - } else { - return false; - } - })(); - - // Test for IE10/11 textarea placeholder clone bug - var hasTextareaCloneBug = (function () { - /* istanbul ignore else */ - if (inBrowser) { - var t = document.createElement('textarea'); - t.placeholder = 't'; - return t.cloneNode(true).value === 't'; - } else { - return false; - } - })(); - - /** - * 1. Deal with Safari cloning nested