diff options
author | Phil Hughes <me@iamphill.com> | 2016-08-17 17:28:36 +0100 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2016-08-17 17:28:36 +0100 |
commit | dc550aced5ce5e2e44d8d864bbc798c4df7f8843 (patch) | |
tree | fee7469ac7a0ac27f3d063ecdbe33c881cca911d /vendor/assets | |
parent | d5327b4efb731719fa1aaad994cea6ddbb1718f7 (diff) | |
download | gitlab-ce-dc550aced5ce5e2e44d8d864bbc798c4df7f8843.tar.gz |
Removed vue assets
Diffstat (limited to 'vendor/assets')
-rw-r--r-- | vendor/assets/javascripts/vue-resource.js | 7 | ||||
-rw-r--r-- | vendor/assets/javascripts/vue.js | 10073 |
2 files changed, 0 insertions, 10080 deletions
diff --git a/vendor/assets/javascripts/vue-resource.js b/vendor/assets/javascripts/vue-resource.js deleted file mode 100644 index 8508b9c3b4d..00000000000 --- a/vendor/assets/javascripts/vue-resource.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * vue-resource v0.9.3 - * https://github.com/vuejs/vue-resource - * Released under the MIT License. - */ - -!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):t.VueResource=n()}(this,function(){"use strict";function t(t){this.state=Z,this.value=void 0,this.deferred=[];var n=this;try{t(function(t){n.resolve(t)},function(t){n.reject(t)})}catch(e){n.reject(e)}}function n(t,n){t instanceof nt?this.promise=t:this.promise=new nt(t.bind(n)),this.context=n}function e(t){rt=t.util,ot=t.config.debug||!t.config.silent}function o(t){"undefined"!=typeof console&&ot&&console.warn("[VueResource warn]: "+t)}function r(t){"undefined"!=typeof console&&console.error(t)}function i(t,n){return rt.nextTick(t,n)}function u(t){return t.replace(/^\s*|\s*$/g,"")}function s(t){return"string"==typeof t}function c(t){return t===!0||t===!1}function a(t){return"function"==typeof t}function f(t){return null!==t&&"object"==typeof t}function h(t){return f(t)&&Object.getPrototypeOf(t)==Object.prototype}function p(t){return"undefined"!=typeof FormData&&t instanceof FormData}function l(t,e,o){var r=n.resolve(t);return arguments.length<2?r:r.then(e,o)}function d(t,n,e){return e=e||{},a(e)&&(e=e.call(n)),v(t.bind({$vm:n,$options:e}),t,{$options:e})}function m(t,n){var e,o;if("number"==typeof t.length)for(e=0;e<t.length;e++)n.call(t[e],t[e],e);else if(f(t))for(o in t)t.hasOwnProperty(o)&&n.call(t[o],t[o],o);return t}function v(t){var n=it.slice.call(arguments,1);return n.forEach(function(n){g(t,n,!0)}),t}function y(t){var n=it.slice.call(arguments,1);return n.forEach(function(n){for(var e in n)void 0===t[e]&&(t[e]=n[e])}),t}function b(t){var n=it.slice.call(arguments,1);return n.forEach(function(n){g(t,n)}),t}function g(t,n,e){for(var o in n)e&&(h(n[o])||ut(n[o]))?(h(n[o])&&!h(t[o])&&(t[o]={}),ut(n[o])&&!ut(t[o])&&(t[o]=[]),g(t[o],n[o],e)):void 0!==n[o]&&(t[o]=n[o])}function w(t,n){var e=n(t);return s(t.root)&&!e.match(/^(https?:)?\//)&&(e=t.root+"/"+e),e}function T(t,n){var e=Object.keys(R.options.params),o={},r=n(t);return m(t.params,function(t,n){e.indexOf(n)===-1&&(o[n]=t)}),o=R.params(o),o&&(r+=(r.indexOf("?")==-1?"?":"&")+o),r}function j(t,n,e){var o=E(t),r=o.expand(n);return e&&e.push.apply(e,o.vars),r}function E(t){var n=["+","#",".","/",";","?","&"],e=[];return{vars:e,expand:function(o){return t.replace(/\{([^\{\}]+)\}|([^\{\}]+)/g,function(t,r,i){if(r){var u=null,s=[];if(n.indexOf(r.charAt(0))!==-1&&(u=r.charAt(0),r=r.substr(1)),r.split(/,/g).forEach(function(t){var n=/([^:\*]*)(?::(\d+)|(\*))?/.exec(t);s.push.apply(s,x(o,u,n[1],n[2]||n[3])),e.push(n[1])}),u&&"+"!==u){var c=",";return"?"===u?c="&":"#"!==u&&(c=u),(0!==s.length?u:"")+s.join(c)}return s.join(",")}return $(i)})}}}function x(t,n,e,o){var r=t[e],i=[];if(O(r)&&""!==r)if("string"==typeof r||"number"==typeof r||"boolean"==typeof r)r=r.toString(),o&&"*"!==o&&(r=r.substring(0,parseInt(o,10))),i.push(C(n,r,P(n)?e:null));else if("*"===o)Array.isArray(r)?r.filter(O).forEach(function(t){i.push(C(n,t,P(n)?e:null))}):Object.keys(r).forEach(function(t){O(r[t])&&i.push(C(n,r[t],t))});else{var u=[];Array.isArray(r)?r.filter(O).forEach(function(t){u.push(C(n,t))}):Object.keys(r).forEach(function(t){O(r[t])&&(u.push(encodeURIComponent(t)),u.push(C(n,r[t].toString())))}),P(n)?i.push(encodeURIComponent(e)+"="+u.join(",")):0!==u.length&&i.push(u.join(","))}else";"===n?i.push(encodeURIComponent(e)):""!==r||"&"!==n&&"?"!==n?""===r&&i.push(""):i.push(encodeURIComponent(e)+"=");return i}function O(t){return void 0!==t&&null!==t}function P(t){return";"===t||"&"===t||"?"===t}function C(t,n,e){return n="+"===t||"#"===t?$(n):encodeURIComponent(n),e?encodeURIComponent(e)+"="+n:n}function $(t){return t.split(/(%[0-9A-Fa-f]{2})/g).map(function(t){return/%[0-9A-Fa-f]/.test(t)||(t=encodeURI(t)),t}).join("")}function U(t){var n=[],e=j(t.url,t.params,n);return n.forEach(function(n){delete t.params[n]}),e}function R(t,n){var e,o=this||{},r=t;return s(t)&&(r={url:t,params:n}),r=v({},R.options,o.$options,r),R.transforms.forEach(function(t){e=A(t,e,o.$vm)}),e(r)}function A(t,n,e){return function(o){return t.call(e,o,n)}}function S(t,n,e){var o,r=ut(n),i=h(n);m(n,function(n,u){o=f(n)||ut(n),e&&(u=e+"["+(i||o?u:"")+"]"),!e&&r?t.add(n.name,n.value):o?S(t,n,u):t.add(u,n)})}function k(t){return new n(function(n){var e=new XDomainRequest,o=function(o){var r=t.respondWith(e.responseText,{status:e.status,statusText:e.statusText});n(r)};t.abort=function(){return e.abort()},e.open(t.method,t.getUrl(),!0),e.timeout=0,e.onload=o,e.onerror=o,e.ontimeout=function(){},e.onprogress=function(){},e.send(t.getBody())})}function H(t,n){!c(t.crossOrigin)&&I(t)&&(t.crossOrigin=!0),t.crossOrigin&&(ht||(t.client=k),delete t.emulateHTTP),n()}function I(t){var n=R.parse(R(t));return n.protocol!==ft.protocol||n.host!==ft.host}function L(t,n){t.emulateJSON&&h(t.body)&&(t.body=R.params(t.body),t.headers["Content-Type"]="application/x-www-form-urlencoded"),p(t.body)&&delete t.headers["Content-Type"],h(t.body)&&(t.body=JSON.stringify(t.body)),n(function(t){var n=t.headers["Content-Type"];if(s(n)&&0===n.indexOf("application/json"))try{t.data=t.json()}catch(e){t.data=null}else t.data=t.text()})}function q(t){return new n(function(n){var e,o,r=t.jsonp||"callback",i="_jsonp"+Math.random().toString(36).substr(2),u=null;e=function(e){var r=0;"load"===e.type&&null!==u?r=200:"error"===e.type&&(r=404),n(t.respondWith(u,{status:r})),delete window[i],document.body.removeChild(o)},t.params[r]=i,window[i]=function(t){u=JSON.stringify(t)},o=document.createElement("script"),o.src=t.getUrl(),o.type="text/javascript",o.async=!0,o.onload=e,o.onerror=e,document.body.appendChild(o)})}function N(t,n){"JSONP"==t.method&&(t.client=q),n(function(n){"JSONP"==t.method&&(n.data=n.json())})}function D(t,n){a(t.before)&&t.before.call(this,t),n()}function J(t,n){t.emulateHTTP&&/^(PUT|PATCH|DELETE)$/i.test(t.method)&&(t.headers["X-HTTP-Method-Override"]=t.method,t.method="POST"),n()}function M(t,n){t.method=t.method.toUpperCase(),t.headers=st({},V.headers.common,t.crossOrigin?{}:V.headers.custom,V.headers[t.method.toLowerCase()],t.headers),n()}function X(t,n){var e;t.timeout&&(e=setTimeout(function(){t.abort()},t.timeout)),n(function(t){clearTimeout(e)})}function W(t){return new n(function(n){var e=new XMLHttpRequest,o=function(o){var r=t.respondWith("response"in e?e.response:e.responseText,{status:1223===e.status?204:e.status,statusText:1223===e.status?"No Content":u(e.statusText),headers:B(e.getAllResponseHeaders())});n(r)};t.abort=function(){return e.abort()},e.open(t.method,t.getUrl(),!0),e.timeout=0,e.onload=o,e.onerror=o,t.progress&&("GET"===t.method?e.addEventListener("progress",t.progress):/^(POST|PUT)$/i.test(t.method)&&e.upload.addEventListener("progress",t.progress)),t.credentials===!0&&(e.withCredentials=!0),m(t.headers||{},function(t,n){e.setRequestHeader(n,t)}),e.send(t.getBody())})}function B(t){var n,e,o,r={};return m(u(t).split("\n"),function(t){o=t.indexOf(":"),e=u(t.slice(0,o)),n=u(t.slice(o+1)),r[e]?ut(r[e])?r[e].push(n):r[e]=[r[e],n]:r[e]=n}),r}function F(t){function e(e){return new n(function(n){function s(){r=i.pop(),a(r)?r.call(t,e,c):(o("Invalid interceptor of type "+typeof r+", must be a function"),c())}function c(e){if(a(e))u.unshift(e);else if(f(e))return u.forEach(function(n){e=l(e,function(e){return n.call(t,e)||e})}),void l(e,n);s()}s()},t)}var r,i=[G],u=[];return f(t)||(t=null),e.use=function(t){i.push(t)},e}function G(t,n){var e=t.client||W;n(e(t))}function V(t){var e=this||{},o=F(e.$vm);return y(t||{},e.$options,V.options),V.interceptors.forEach(function(t){o.use(t)}),o(new dt(t)).then(function(t){return t.ok?t:n.reject(t)},function(t){return t instanceof Error&&r(t),n.reject(t)})}function _(t,n,e,o){var r=this||{},i={};return e=st({},_.actions,e),m(e,function(e,u){e=v({url:t,params:n||{}},o,e),i[u]=function(){return(r.$http||V)(z(e,arguments))}}),i}function z(t,n){var e,o=st({},t),r={};switch(n.length){case 2:r=n[0],e=n[1];break;case 1:/^(POST|PUT|PATCH)$/i.test(o.method)?e=n[0]:r=n[0];break;case 0:break;default:throw"Expected up to 4 arguments [params, body], got "+n.length+" arguments"}return o.body=e,o.params=st({},o.params,r),o}function K(t){K.installed||(e(t),t.url=R,t.http=V,t.resource=_,t.Promise=n,Object.defineProperties(t.prototype,{$url:{get:function(){return d(t.url,this,this.$options.url)}},$http:{get:function(){return d(t.http,this,this.$options.http)}},$resource:{get:function(){return t.resource.bind(this)}},$promise:{get:function(){var n=this;return function(e){return new t.Promise(e,n)}}}}))}var Q=0,Y=1,Z=2;t.reject=function(n){return new t(function(t,e){e(n)})},t.resolve=function(n){return new t(function(t,e){t(n)})},t.all=function(n){return new t(function(e,o){function r(t){return function(o){u[t]=o,i+=1,i===n.length&&e(u)}}var i=0,u=[];0===n.length&&e(u);for(var s=0;s<n.length;s+=1)t.resolve(n[s]).then(r(s),o)})},t.race=function(n){return new t(function(e,o){for(var r=0;r<n.length;r+=1)t.resolve(n[r]).then(e,o)})};var tt=t.prototype;tt.resolve=function(t){var n=this;if(n.state===Z){if(t===n)throw new TypeError("Promise settled with itself.");var e=!1;try{var o=t&&t.then;if(null!==t&&"object"==typeof t&&"function"==typeof o)return void o.call(t,function(t){e||n.resolve(t),e=!0},function(t){e||n.reject(t),e=!0})}catch(r){return void(e||n.reject(r))}n.state=Q,n.value=t,n.notify()}},tt.reject=function(t){var n=this;if(n.state===Z){if(t===n)throw new TypeError("Promise settled with itself.");n.state=Y,n.value=t,n.notify()}},tt.notify=function(){var t=this;i(function(){if(t.state!==Z)for(;t.deferred.length;){var n=t.deferred.shift(),e=n[0],o=n[1],r=n[2],i=n[3];try{t.state===Q?r("function"==typeof e?e.call(void 0,t.value):t.value):t.state===Y&&("function"==typeof o?r(o.call(void 0,t.value)):i(t.value))}catch(u){i(u)}}})},tt.then=function(n,e){var o=this;return new t(function(t,r){o.deferred.push([n,e,t,r]),o.notify()})},tt["catch"]=function(t){return this.then(void 0,t)};var nt=window.Promise||t;n.all=function(t,e){return new n(nt.all(t),e)},n.resolve=function(t,e){return new n(nt.resolve(t),e)},n.reject=function(t,e){return new n(nt.reject(t),e)},n.race=function(t,e){return new n(nt.race(t),e)};var et=n.prototype;et.bind=function(t){return this.context=t,this},et.then=function(t,e){return t&&t.bind&&this.context&&(t=t.bind(this.context)),e&&e.bind&&this.context&&(e=e.bind(this.context)),new n(this.promise.then(t,e),this.context)},et["catch"]=function(t){return t&&t.bind&&this.context&&(t=t.bind(this.context)),new n(this.promise["catch"](t),this.context)},et["finally"]=function(t){return this.then(function(n){return t.call(this),n},function(n){return t.call(this),nt.reject(n)})};var ot=!1,rt={},it=[],ut=Array.isArray,st=Object.assign||b,ct=document.documentMode,at=document.createElement("a");R.options={url:"",root:null,params:{}},R.transforms=[U,T,w],R.params=function(t){var n=[],e=encodeURIComponent;return n.add=function(t,n){a(n)&&(n=n()),null===n&&(n=""),this.push(e(t)+"="+e(n))},S(n,t),n.join("&").replace(/%20/g,"+")},R.parse=function(t){return ct&&(at.href=t,t=at.href),at.href=t,{href:at.href,protocol:at.protocol?at.protocol.replace(/:$/,""):"",port:at.port,host:at.host,hostname:at.hostname,pathname:"/"===at.pathname.charAt(0)?at.pathname:"/"+at.pathname,search:at.search?at.search.replace(/^\?/,""):"",hash:at.hash?at.hash.replace(/^#/,""):""}};var ft=R.parse(location.href),ht="withCredentials"in new XMLHttpRequest,pt=function(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")},lt=function(){function t(n,e){var o=e.url,r=e.headers,i=e.status,u=e.statusText;pt(this,t),this.url=o,this.body=n,this.headers=r||{},this.status=i||0,this.statusText=u||"",this.ok=i>=200&&i<300}return t.prototype.text=function(){return this.body},t.prototype.blob=function(){return new Blob([this.body])},t.prototype.json=function(){return JSON.parse(this.body)},t}(),dt=function(){function t(n){pt(this,t),this.method="GET",this.body=null,this.params={},this.headers={},st(this,n)}return t.prototype.getUrl=function(){return R(this)},t.prototype.getBody=function(){return this.body},t.prototype.respondWith=function(t,n){return new lt(t,st(n||{},{url:this.getUrl()}))},t}(),mt={"X-Requested-With":"XMLHttpRequest"},vt={Accept:"application/json, text/plain, */*"},yt={"Content-Type":"application/json;charset=utf-8"};return V.options={},V.headers={put:yt,post:yt,patch:yt,"delete":yt,custom:mt,common:vt},V.interceptors=[D,X,J,L,N,M,H],["get","delete","head","jsonp"].forEach(function(t){V[t]=function(n,e){return this(st(e||{},{url:n,method:t}))}}),["post","put","patch"].forEach(function(t){V[t]=function(n,e,o){return this(st(o||{},{url:n,method:t,body:e}))}}),_.actions={get:{method:"GET"},save:{method:"POST"},query:{method:"GET"},update:{method:"PUT"},remove:{method:"DELETE"},"delete":{method:"DELETE"}},"undefined"!=typeof window&&window.Vue&&window.Vue.use(K),K}); diff --git a/vendor/assets/javascripts/vue.js b/vendor/assets/javascripts/vue.js deleted file mode 100644 index 3c5e06254d4..00000000000 --- a/vendor/assets/javascripts/vue.js +++ /dev/null @@ -1,10073 +0,0 @@ -/*! - * Vue.js v1.0.26 - * (c) 2016 Evan You - * Released under the MIT License. - */ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global.Vue = factory()); -}(this, function () { '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 - */ - - function del(obj, key) { - if (!hasOwn(obj, key)) { - return; - } - delete obj[key]; - var ob = obj.__ob__; - if (!ob) { - if (obj._isVue) { - delete obj._data[key]; - obj._digest(); - } - return; - } - ob.dep.notify(); - if (ob.vms) { - var i = ob.vms.length; - while (i--) { - var vm = ob.vms[i]; - vm._unproxy(key); - vm._digest(); - } - } - } - - var hasOwnProperty = Object.prototype.hasOwnProperty; - /** - * Check whether the object has the property. - * - * @param {Object} obj - * @param {String} key - * @return {Boolean} - */ - - function hasOwn(obj, key) { - return hasOwnProperty.call(obj, key); - } - - /** - * Check if an expression is a literal value. - * - * @param {String} exp - * @return {Boolean} - */ - - var literalValueRE = /^\s?(true|false|-?[\d\.]+|'[^']*'|"[^"]*")\s?$/; - - function isLiteral(exp) { - return literalValueRE.test(exp); - } - - /** - * Check if a string starts with $ or _ - * - * @param {String} str - * @return {Boolean} - */ - - function isReserved(str) { - var c = (str + '').charCodeAt(0); - return c === 0x24 || c === 0x5F; - } - - /** - * Guard text output, make sure undefined outputs - * empty string - * - * @param {*} value - * @return {String} - */ - - function _toString(value) { - return value == null ? '' : value.toString(); - } - - /** - * Check and convert possible numeric strings to numbers - * before setting back to data - * - * @param {*} value - * @return {*|Number} - */ - - function toNumber(value) { - if (typeof value !== 'string') { - return value; - } else { - var parsed = Number(value); - return isNaN(parsed) ? value : parsed; - } - } - - /** - * Convert string boolean literals into real booleans. - * - * @param {*} value - * @return {*|Boolean} - */ - - function toBoolean(value) { - return value === 'true' ? true : value === 'false' ? false : value; - } - - /** - * Strip quotes from a string - * - * @param {String} str - * @return {String | false} - */ - - 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; - } - - /** - * 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() : ''; - } - - /** - * Hyphenate a camelCase string. - * - * @param {String} str - * @return {String} - */ - - var hyphenateRE = /([a-z\d])([A-Z])/g; - - function hyphenate(str) { - return str.replace(hyphenateRE, '$1-$2').toLowerCase(); - } - - /** - * 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} - */ - - var classifyRE = /(?:^|[-_\/])(\w)/g; - - function classify(str) { - return str.replace(classifyRE, toUpper); - } - - /** - * Simple bind, faster than native - * - * @param {Function} fn - * @param {Object} ctx - * @return {Function} - */ - - function bind(fn, ctx) { - return function (a) { - var l = arguments.length; - return l ? l > 1 ? fn.apply(ctx, arguments) : fn.call(ctx, a) : fn.call(ctx); - }; - } - - /** - * Convert an Array-like object to a real Array. - * - * @param {Array-like} list - * @param {Number} [start] - start index - * @return {Array} - */ - - 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; - } - - /** - * 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]]; - } - 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'; - } - - /** - * 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; - } - - /** - * Array type check. - * - * @param {*} obj - * @return {Boolean} - */ - - var isArray = Array.isArray; - - /** - * Define a property. - * - * @param {Object} obj - * @param {String} key - * @param {*} val - * @param {Boolean} [enumerable] - */ - - function def(obj, key, val, enumerable) { - Object.defineProperty(obj, key, { - value: val, - enumerable: !!enumerable, - writable: true, - configurable: true - }); - } - - /** - * 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 - */ - - 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; - }; - } - - /** - * Manual indexOf because it's slightly faster than - * native. - * - * @param {Array} arr - * @param {*} obj - */ - - function indexOf(arr, obj) { - var i = arr.length; - while (i--) { - if (arr[i] === obj) return i; - } - return -1; - } - - /** - * Make a cancellable version of an async callback. - * - * @param {Function} fn - * @return {Function} - */ - - function cancellable(fn) { - var cb = function cb() { - if (!cb.cancelled) { - return fn.apply(this, arguments); - } - }; - cb.cancel = function () { - cb.cancelled = true; - }; - return cb; - } - - /** - * 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} - */ - - function looseEqual(a, b) { - /* eslint-disable eqeqeq */ - return a == b || (isObject(a) && isObject(b) ? JSON.stringify(a) === JSON.stringify(b) : false); - /* eslint-enable eqeqeq */ - } - - var hasProto = ('__proto__' in {}); - - // Browser environment sniffing - var inBrowser = typeof window !== 'undefined' && Object.prototype.toString.call(window) !== '[object Object]'; - - // detect devtools - var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__; - - // UA sniffing for working around browser-specific quirks - var UA = inBrowser && window.navigator.userAgent.toLowerCase(); - var isIE = UA && UA.indexOf('trident') > 0; - var isIE9 = UA && UA.indexOf('msie 9.0') > 0; - var isAndroid = UA && UA.indexOf('android') > 0; - var isIos = UA && /(iphone|ipad|ipod|ios)/i.test(UA); - var iosVersionMatch = isIos && UA.match(/os ([\d_]+)/); - var iosVersion = iosVersionMatch && iosVersionMatch[1].split('_'); - - // detecting iOS UIWebView by indexedDB - var hasMutationObserverBug = iosVersion && Number(iosVersion[0]) >= 9 && Number(iosVersion[1]) >= 3 && !window.indexedDB; - - var transitionProp = undefined; - var transitionEndEvent = undefined; - var animationProp = undefined; - var animationEndEvent = undefined; - - // 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'; - } - - /** - * 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 - */ - - var nextTick = (function () { - var callbacks = []; - var pending = false; - var timerFunc; - function nextTickHandler() { - pending = false; - var copies = callbacks.slice(0); - callbacks = []; - for (var i = 0; i < copies.length; i++) { - copies[i](); - } - } - - /* istanbul ignore if */ - if (typeof MutationObserver !== 'undefined' && !hasMutationObserverBug) { - var counter = 1; - var observer = new MutationObserver(nextTickHandler); - var textNode = document.createTextNode(counter); - observer.observe(textNode, { - characterData: true - }); - timerFunc = function () { - counter = (counter + 1) % 2; - textNode.data = 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; - callbacks.push(func); - if (pending) return; - pending = true; - timerFunc(nextTickHandler, 0); - }; - })(); - - var _Set = undefined; - /* istanbul ignore if */ - if (typeof Set !== 'undefined' && Set.toString().match(/native code/)) { - // use native Set when available. - _Set = Set; - } else { - // a non-standard Set polyfill that only works with primitive keys. - _Set = function () { - this.set = Object.create(null); - }; - _Set.prototype.has = function (key) { - return this.set[key] !== undefined; - }; - _Set.prototype.add = function (key) { - this.set[key] = 1; - }; - _Set.prototype.clear = function () { - this.set = Object.create(null); - }; - } - - function Cache(limit) { - this.size = 0; - this.limit = limit; - this.head = this.tail = undefined; - this._keymap = Object.create(null); - } - - var p = Cache.prototype; - - /** - * Put <value> into the cache associated with <key>. - * 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} - */ - - p.put = function (key, value) { - var removed; - - var entry = this.get(key, true); - if (!entry) { - if (this.size === this.limit) { - removed = this.shift(); - } - entry = { - key: key - }; - this._keymap[key] = entry; - if (this.tail) { - this.tail.newer = entry; - entry.older = this.tail; - } else { - this.head = entry; - } - 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; - }; - - /** - * Get and register recent use of <key>. Returns the value - * associated with <key> or undefined if not in cache. - * - * @param {String} key - * @param {Boolean} returnEntry - * @return {Entry|*} - */ - - 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 <D> 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 - } - this.tail = entry; - return returnEntry ? entry : entry.value; - }; - - var cache$1 = new Cache(1000); - var filterTokenRE = /[^\s'"]+|'[^']*'|"[^"]*"/g; - var reservedArgRE = /^in$|^-?\d+/; - - /** - * Parser state - */ - - 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 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; - } - - /** - * Check if an argument is dynamic and strip quotes. - * - * @param {String} arg - * @return {Object} - */ - - 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 - }; - } - } - - /** - * 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} - */ - - 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; // } - } - } - } - - if (dir.expression == null) { - dir.expression = str.slice(0, i).trim(); - } else if (lastFilterIndex !== 0) { - pushFilter(); - } - - cache$1.put(s, dir); - return dir; - } - -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 - */ - - function escapeRegex(str) { - return str.replace(regexEscapeRE, '\\$&'); - } - - 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 + '((?:.|\\n)+?)' + unsafeClose + '$'); - // reset cache - cache = new Cache(1000); - } - - /** - * Parse a template text string into an array of tokens. - * - * @param {String} text - * @return {Array<Object> | null} - * - {String} type - * - {String} value - * - {Boolean} [html] - * - {Boolean} [oneTime] - */ - - 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) - }); - } - // 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; - } - - /** - * 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} - */ - - 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); - } - } - - /** - * Format a single token. - * - * @param {Object} token - * @param {Vue} [vm] - * @param {Boolean} [single] - * @return {String} - */ - - function formatToken(token, vm, single) { - return token.tag ? token.oneTime && vm ? '"' + vm.$eval(token.value) + '"' : inlineFilters(token.value, single) : '"' + token.value + '"'; - } - - /** - * 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} - */ - - 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 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: 'development' !== '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<String>} - */ - - 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 - } - }); - - var warn = undefined; - var formatComponentName = undefined; - - if ('development' !== 'production') { - (function () { - var hasConsole = typeof console !== 'undefined'; - - warn = function (msg, vm) { - if (hasConsole && !config.silent) { - console.error('[Vue warn]: ' + msg + (vm ? formatComponentName(vm) : '')); - } - }; - - 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] - */ - - function appendWithTransition(el, target, vm, cb) { - applyTransition(el, 1, function () { - target.appendChild(el); - }, vm, cb); - } - - /** - * InsertBefore with transition. - * - * @param {Element} el - * @param {Element} target - * @param {Vue} vm - * @param {Function} [cb] - */ - - function beforeWithTransition(el, target, vm, cb) { - applyTransition(el, 1, function () { - before(el, target); - }, vm, cb); - } - - /** - * Remove with transition. - * - * @param {Element} el - * @param {Vue} vm - * @param {Function} [cb] - */ - - function removeWithTransition(el, vm, cb) { - applyTransition(el, -1, function () { - remove(el); - }, vm, cb); - } - - /** - * 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] - */ - - 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) { - 'development' !== 'production' && warn('Cannot find element: ' + selector); - } - } - 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) { - if (!node) return false; - var doc = node.ownerDocument.documentElement; - var parent = 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); - } - return val; - } - - /** - * Get an attribute with colon or v-bind: prefix. - * - * @param {Node} node - * @param {String} name - * @return {String|null} - */ - - function getBindAttr(node, name) { - var val = getAttr(node, ':' + name); - if (val === null) { - val = getAttr(node, 'v-bind:' + name); - } - return val; - } - - /** - * Check the presence of a bind attribute. - * - * @param {Node} node - * @param {String} name - * @return {Boolean} - */ - - function hasBindAttr(node, name) { - return node.hasAttribute(name) || node.hasAttribute(':' + name) || node.hasAttribute('v-bind:' + name); - } - - /** - * Insert el before target - * - * @param {Element} el - * @param {Element} target - */ - - function before(el, target) { - target.parentNode.insertBefore(el, target); - } - - /** - * Insert el after target - * - * @param {Element} el - * @param {Element} target - */ - - function after(el, target) { - if (target.nextSibling) { - before(el, target.nextSibling); - } else { - target.parentNode.appendChild(el); - } - } - - /** - * Remove el from DOM - * - * @param {Element} el - */ - - function remove(el) { - el.parentNode.removeChild(el); - } - - /** - * Prepend el to target - * - * @param {Element} el - * @param {Element} target - */ - - function prepend(el, target) { - if (target.firstChild) { - before(el, target.firstChild); - } else { - target.appendChild(el); - } - } - - /** - * Replace target with el - * - * @param {Element} target - * @param {Element} el - */ - - function replace(target, el) { - var parent = target.parentNode; - if (parent) { - parent.replaceChild(el, target); - } - } - - /** - * Add event listener shorthand. - * - * @param {Element} el - * @param {String} event - * @param {Function} cb - * @param {Boolean} [useCapture] - */ - - function on(el, event, cb, useCapture) { - el.addEventListener(event, cb, useCapture); - } - - /** - * Remove event listener shorthand. - * - * @param {Element} el - * @param {String} event - * @param {Function} cb - */ - - function off(el, event, cb) { - el.removeEventListener(event, cb); - } - - /** - * For IE9 compat: when both class and :class are present - * getAttribute('class') returns wrong value... - * - * @param {Element} el - * @return {String} - */ - - function getClass(el) { - var classname = el.className; - if (typeof classname === 'object') { - classname = classname.baseVal || ''; - } - return classname; - } - - /** - * 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 - */ - - function setClass(el, cls) { - /* istanbul ignore if */ - if (isIE9 && !/svg$/.test(el.namespaceURI)) { - el.className = cls; - } else { - el.setAttribute('class', cls); - } - } - - /** - * Add class with compatibility for IE & SVG - * - * @param {Element} el - * @param {String} cls - */ - - 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()); - } - } - } - - /** - * Remove class with compatibility for IE & SVG - * - * @param {Element} el - * @param {String} cls - */ - - 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()); - } - if (!el.className) { - el.removeAttribute('class'); - } - } - - /** - * Extract raw content inside an element into a temporary - * container div - * - * @param {Element} el - * @param {Boolean} asFragment - * @return {Element|DocumentFragment} - */ - - function extractContent(el, asFragment) { - var child; - var rawContent; - /* istanbul ignore if */ - if (isTemplate(el) && isFragment(el.content)) { - el = el.content; - } - 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); - } - } - return rawContent; - } - - /** - * Trim possible empty head/tail text and comment - * nodes inside a parent. - * - * @param {Node} node - */ - - 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); - } - /* 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'; - } - - /** - * 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 createAnchor(content, persist) { - var anchor = config.debug ? document.createComment(content) : document.createTextNode(persist ? ' ' : ''); - anchor.__v_anchor = true; - return anchor; - } - - /** - * Find a component ref attribute that starts with $. - * - * @param {Element} node - * @return {String|undefined} - */ - - var refRE = /^v-ref:/; - - 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, '')); - } - } - } - } - - /** - * 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; - } - 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]); - } - cb && cb(); - } - } - } - - /** - * Check if a node is a DocumentFragment. - * - * @param {Node} node - * @return {Boolean} - */ - - function isFragment(node) { - return node && node.nodeType === 11; - } - - /** - * 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; - } - } - - 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 ('development' !== '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 - // Firefox returns unknown for some "Interactive elements." - !/^(data|time|rtc|rb|details|dialog|summary)$/.test(tag) - ); - } - }; - } - - /** - * 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, options); - if (is) { - return is; - } else if ('development' !== '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, options); - } - } - - /** - * Get "is" binding from an element. - * - * @param {Element} el - * @param {Object} options - * @return {Object|undefined} - */ - - function getIsBinding(el, options) { - // dynamic syntax - var exp = el.getAttribute('is'); - if (exp != null) { - if (resolveAsset(options, 'components', exp)) { - el.removeAttribute('is'); - return { id: exp }; - } - } else { - exp = getBindAttr(el, 'is'); - if (exp != null) { - return { id: exp, dynamic: true }; - } - } - } - - /** - * 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 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') { - 'development' !== '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; - } - }; - } - }; - - /** - * El - */ - - strats.el = function (parentVal, childVal, vm) { - if (!vm && childVal && typeof childVal !== 'function') { - 'development' !== '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 || null); - 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; - }; - - /** - * Default strategy. - */ - - var defaultStrat = function defaultStrat(parentVal, childVal) { - return childVal === undefined ? parentVal : childVal; - }; - - /** - * 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 ('development' !== '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)) { - 'development' !== '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 ('development' !== 'production') { - map[key.replace(/-/g, '').toLowerCase()] = hyphenate(key); - } - def = components[key]; - if (isPlainObject(def)) { - components[key] = Vue.extend(def); - } - } - } - } - - /** - * 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 }; - } - } - } - } - - /** - * 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) { - 'development' !== 'production' && warn('Array-syntax assets must provide a "name" or "id" field.'); - } else { - res[id] = asset; - } - } - 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); - if ('development' !== 'production') { - if (child.propsData && !vm) { - warn('propsData can only be used as an instantiation option.'); - } - } - var options = {}; - var key; - if (child['extends']) { - parent = typeof child['extends'] === 'function' ? mergeOptions(parent, child['extends'].options, vm) : mergeOptions(parent, child['extends'], vm); - } - if (child.mixins) { - for (var i = 0, l = child.mixins.length; i < l; i++) { - var mixin = child.mixins[i]; - var mixinOptions = mixin.prototype instanceof Vue ? mixin.options : mixin; - parent = mergeOptions(parent, mixinOptions, vm); - } - } - for (key in parent) { - mergeField(key); - } - for (key in child) { - if (!hasOwn(parent, key)) { - mergeField(key); - } - } - 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 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 ('development' !== 'production' && warnMissing && !res) { - warn('Failed to resolve ' + type.slice(0, -1) + ': ' + id, options); - } - 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, - isIE: isIE, - isIE9: isIE9, - isAndroid: isAndroid, - isIos: isIos, - iosVersionMatch: iosVersionMatch, - iosVersion: iosVersion, - hasMutationObserverBug: hasMutationObserverBug, - get transitionProp () { return transitionProp; }, - get transitionEndEvent () { return transitionEndEvent; }, - get animationProp () { return animationProp; }, - get animationEndEvent () { return animationEndEvent; }, - nextTick: nextTick, - get _Set () { return _Set; }, - 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 _initData(). - this._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 ('development' !== '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 ('development' !== '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 ('development' !== '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 literalValueRE$1 = /^(?:true|false|null|undefined|Infinity|NaN)$/; - - function noop() {} - - /** - * 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)) { - 'development' !== '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 because 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) { - if ('development' !== 'production') { - /* istanbul ignore if */ - if (e.toString().match(/unsafe-eval|CSP/)) { - warn('It seems you are using the default build of Vue.js in an environment ' + 'with Content Security Policy that prohibits unsafe-eval. ' + 'Use the CSP-compliant build instead: ' + 'http://vuejs.org/guide/installation.html#CSP-compliant-build'); - } else { - warn('Invalid expression. ' + 'Generated function body: ' + body); - } - } - return noop; - } - } - - /** - * 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 { - 'development' !== '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 literal values as paths - !literalValueRE$1.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 queue = []; - var userQueue = []; - var has = {}; - var circular = {}; - var waiting = false; - - /** - * Reset the batcher's state. - */ - - function resetBatcherState() { - queue.length = 0; - userQueue.length = 0; - has = {}; - circular = {}; - waiting = false; - } - - /** - * Flush both queues and run the watchers. - */ - - function flushBatcherQueue() { - var _again = true; - - _function: while (_again) { - _again = false; - - runBatcherQueue(queue); - runBatcherQueue(userQueue); - // user watchers triggered more watchers, - // keep flushing until it depletes - if (queue.length) { - _again = true; - continue _function; - } - // 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 (var i = 0; i < queue.length; i++) { - var watcher = queue[i]; - var id = watcher.id; - has[id] = null; - watcher.run(); - // in dev build, check and stop circular updates. - if ('development' !== '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; - } - } - } - queue.length = 0; - } - - /** - * 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) { - // 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 = new _Set(); - this.newDepIds = new _Set(); - 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 ('development' !== '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 ('development' !== '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) { - 'development' !== '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; - }; - - /** - * Add a dependency to this directive. - * - * @param {Dep} dep - */ - - Watcher.prototype.addDep = function (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); - } - } - }; - - /** - * 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.has(dep.id)) { - dep.removeSub(this); - } - } - 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; - }; - - /** - * 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 ('development' !== '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 ('development' !== '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 - */ - - var seenObjects = new _Set(); - function traverse(val, seen) { - var i = undefined, - keys = undefined; - if (!seen) { - seen = seenObjects; - seen.clear(); - } - var isA = isArray(val); - var isO = isObject(val); - if ((isA || isO) && Object.isExtensible(val)) { - if (val.__ob__) { - var depId = val.__ob__.dep.id; - if (seen.has(depId)) { - return; - } else { - seen.add(depId); - } - } - if (isA) { - i = val.length; - while (i--) traverse(val[i], seen); - } else if (isO) { - keys = Object.keys(val); - i = keys.length; - while (i--) traverse(val[keys[i]], seen); - } - } - } - - 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, '<fieldset>', '</fieldset>'], - tr: [2, '<table><tbody>', '</tbody></table>'], - col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'] - }; - - map.td = map.th = [3, '<table><tbody><tr>', '</tr></tbody></table>']; - - map.option = map.optgroup = [1, '<select multiple="multiple">', '</select>']; - - map.thead = map.tbody = map.colgroup = map.caption = map.tfoot = [1, '<table>', '</table>']; - - 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, '<svg ' + 'xmlns="http://www.w3.org/2000/svg" ' + 'xmlns:xlink="http://www.w3.org/1999/xlink" ' + 'xmlns:ev="http://www.w3.org/2001/xml-events"' + 'version="1.1">', '</svg>']; - - /** - * 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+?;/; - var commentRE = /<!--/; - - /** - * 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); - var commentMatch = commentRE.test(templateString); - - if (!tagMatch && !entityMatch && !commentMatch) { - // 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. However, iOS Safari has - // bug when using directly cloned template content with touch - // events and can cause crashes when the nodes are removed from DOM, so we - // have to treat template elements as string templates. (#2805) - /* istanbul ignore if */ - if (isRealTemplate(node)) { - return stringToFragment(node.innerHTML); - } - // 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 = '<template>1</template>'; - 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 <template> bug by - * manually cloning all template instances. - * 2. Deal with IE10/11 textarea placeholder bug by setting - * the correct value after cloning. - * - * @param {Element|DocumentFragment} node - * @return {Element|DocumentFragment} - */ - - function cloneNode(node) { - /* istanbul ignore if */ - if (!node.querySelectorAll) { - return node.cloneNode(); - } - var res = node.cloneNode(true); - var i, original, cloned; - /* istanbul ignore if */ - if (hasBrokenTemplate) { - var tempClone = res; - if (isRealTemplate(node)) { - node = node.content; - tempClone = res.content; - } - original = node.querySelectorAll('template'); - if (original.length) { - cloned = tempClone.querySelectorAll('template'); - i = cloned.length; - while (i--) { - cloned[i].parentNode.replaceChild(cloneNode(original[i]), cloned[i]); - } - } - } - /* istanbul ignore if */ - if (hasTextareaCloneBug) { - if (node.tagName === 'TEXTAREA') { - res.value = node.value; - } else { - original = node.querySelectorAll('textarea'); - if (original.length) { - cloned = res.querySelectorAll('textarea'); - i = cloned.length; - while (i--) { - cloned[i].value = original[i].value; - } - } - } - } - return res; - } - - /** - * Process the template option and normalizes it into a - * a DocumentFragment that can be used as a partial or a - * instance template. - * - * @param {*} template - * Possible values include: - * - DocumentFragment object - * - Node object of type Template - * - id selector: '#some-template-id' - * - template string: '<div><span>{{msg}}</span></div>' - * @param {Boolean} shouldClone - * @param {Boolean} raw - * inline HTML interpolation. Do not check for id - * selector and keep whitespace in the string. - * @return {DocumentFragment|undefined} - */ - - function parseTemplate(template, shouldClone, raw) { - var node, frag; - - // if the template is already a document fragment, - // do nothing - if (isFragment(template)) { - trimNode(template); - return shouldClone ? cloneNode(template) : template; - } - - if (typeof template === 'string') { - // id selector - if (!raw && template.charAt(0) === '#') { - // id selector can be cached too - frag = idSelectorCache.get(template); - if (!frag) { - node = document.getElementById(template.slice(1)); - if (node) { - frag = nodeToFragment(node); - // save selector to cache - idSelectorCache.put(template, frag); - } - } - } else { - // normal string template - frag = stringToFragment(template, raw); - } - } else if (template.nodeType) { - // a direct node - frag = nodeToFragment(template); - } - - return frag && shouldClone ? cloneNode(frag) : frag; - } - -var template = Object.freeze({ - cloneNode: cloneNode, - parseTemplate: parseTemplate - }); - - var html = { - - bind: function bind() { - // a comment node means this is a binding for - // {{{ inline unescaped html }}} - if (this.el.nodeType === 8) { - // hold nodes - this.nodes = []; - // replace the placeholder with proper anchor - this.anchor = createAnchor('v-html'); - replace(this.el, this.anchor); - } - }, - - update: function update(value) { - value = _toString(value); - if (this.nodes) { - this.swap(value); - } else { - this.el.innerHTML = value; - } - }, - - swap: function swap(value) { - // remove old nodes - var i = this.nodes.length; - while (i--) { - remove(this.nodes[i]); - } - // convert new value to a fragment - // do not attempt to retrieve from id selector - var frag = parseTemplate(value, true, true); - // save a reference to these nodes so we can remove later - this.nodes = toArray(frag.childNodes); - before(frag, this.anchor); - } - }; - - /** - * Abstraction for a partially-compiled fragment. - * Can optionally compile content with a child scope. - * - * @param {Function} linker - * @param {Vue} vm - * @param {DocumentFragment} frag - * @param {Vue} [host] - * @param {Object} [scope] - * @param {Fragment} [parentFrag] - */ - function Fragment(linker, vm, frag, host, scope, parentFrag) { - this.children = []; - this.childFrags = []; - this.vm = vm; - this.scope = scope; - this.inserted = false; - this.parentFrag = parentFrag; - if (parentFrag) { - parentFrag.childFrags.push(this); - } - this.unlink = linker(vm, frag, host, scope, this); - var single = this.single = frag.childNodes.length === 1 && - // do not go single mode if the only node is an anchor - !frag.childNodes[0].__v_anchor; - if (single) { - this.node = frag.childNodes[0]; - this.before = singleBefore; - this.remove = singleRemove; - } else { - this.node = createAnchor('fragment-start'); - this.end = createAnchor('fragment-end'); - this.frag = frag; - prepend(this.node, frag); - frag.appendChild(this.end); - this.before = multiBefore; - this.remove = multiRemove; - } - this.node.__v_frag = this; - } - - /** - * Call attach/detach for all components contained within - * this fragment. Also do so recursively for all child - * fragments. - * - * @param {Function} hook - */ - - Fragment.prototype.callHook = function (hook) { - var i, l; - for (i = 0, l = this.childFrags.length; i < l; i++) { - this.childFrags[i].callHook(hook); - } - for (i = 0, l = this.children.length; i < l; i++) { - hook(this.children[i]); - } - }; - - /** - * Insert fragment before target, single node version - * - * @param {Node} target - * @param {Boolean} withTransition - */ - - function singleBefore(target, withTransition) { - this.inserted = true; - var method = withTransition !== false ? beforeWithTransition : before; - method(this.node, target, this.vm); - if (inDoc(this.node)) { - this.callHook(attach); - } - } - - /** - * Remove fragment, single node version - */ - - function singleRemove() { - this.inserted = false; - var shouldCallRemove = inDoc(this.node); - var self = this; - this.beforeRemove(); - removeWithTransition(this.node, this.vm, function () { - if (shouldCallRemove) { - self.callHook(detach); - } - self.destroy(); - }); - } - - /** - * Insert fragment before target, multi-nodes version - * - * @param {Node} target - * @param {Boolean} withTransition - */ - - function multiBefore(target, withTransition) { - this.inserted = true; - var vm = this.vm; - var method = withTransition !== false ? beforeWithTransition : before; - mapNodeRange(this.node, this.end, function (node) { - method(node, target, vm); - }); - if (inDoc(this.node)) { - this.callHook(attach); - } - } - - /** - * Remove fragment, multi-nodes version - */ - - function multiRemove() { - this.inserted = false; - var self = this; - var shouldCallRemove = inDoc(this.node); - this.beforeRemove(); - removeNodeRange(this.node, this.end, this.vm, this.frag, function () { - if (shouldCallRemove) { - self.callHook(detach); - } - self.destroy(); - }); - } - - /** - * Prepare the fragment for removal. - */ - - Fragment.prototype.beforeRemove = function () { - var i, l; - for (i = 0, l = this.childFrags.length; i < l; i++) { - // call the same method recursively on child - // fragments, depth-first - this.childFrags[i].beforeRemove(false); - } - for (i = 0, l = this.children.length; i < l; i++) { - // Call destroy for all contained instances, - // with remove:false and defer:true. - // Defer is necessary because we need to - // keep the children to call detach hooks - // on them. - this.children[i].$destroy(false, true); - } - var dirs = this.unlink.dirs; - for (i = 0, l = dirs.length; i < l; i++) { - // disable the watchers on all the directives - // so that the rendered content stays the same - // during removal. - dirs[i]._watcher && dirs[i]._watcher.teardown(); - } - }; - - /** - * Destroy the fragment. - */ - - Fragment.prototype.destroy = function () { - if (this.parentFrag) { - this.parentFrag.childFrags.$remove(this); - } - this.node.__v_frag = null; - this.unlink(); - }; - - /** - * Call attach hook for a Vue instance. - * - * @param {Vue} child - */ - - function attach(child) { - if (!child._isAttached && inDoc(child.$el)) { - child._callHook('attached'); - } - } - - /** - * Call detach hook for a Vue instance. - * - * @param {Vue} child - */ - - function detach(child) { - if (child._isAttached && !inDoc(child.$el)) { - child._callHook('detached'); - } - } - - var linkerCache = new Cache(5000); - - /** - * A factory that can be used to create instances of a - * fragment. Caches the compiled linker if possible. - * - * @param {Vue} vm - * @param {Element|String} el - */ - function FragmentFactory(vm, el) { - this.vm = vm; - var template; - var isString = typeof el === 'string'; - if (isString || isTemplate(el) && !el.hasAttribute('v-if')) { - template = parseTemplate(el, true); - } else { - template = document.createDocumentFragment(); - template.appendChild(el); - } - this.template = template; - // linker can be cached, but only for components - var linker; - var cid = vm.constructor.cid; - if (cid > 0) { - var cacheId = cid + (isString ? el : getOuterHTML(el)); - linker = linkerCache.get(cacheId); - if (!linker) { - linker = compile(template, vm.$options, true); - linkerCache.put(cacheId, linker); - } - } else { - linker = compile(template, vm.$options, true); - } - this.linker = linker; - } - - /** - * Create a fragment instance with given host and scope. - * - * @param {Vue} host - * @param {Object} scope - * @param {Fragment} parentFrag - */ - - FragmentFactory.prototype.create = function (host, scope, parentFrag) { - var frag = cloneNode(this.template); - return new Fragment(this.linker, this.vm, frag, host, scope, parentFrag); - }; - - var ON = 700; - var MODEL = 800; - var BIND = 850; - var TRANSITION = 1100; - var EL = 1500; - var COMPONENT = 1500; - var PARTIAL = 1750; - var IF = 2100; - var FOR = 2200; - var SLOT = 2300; - - var uid$3 = 0; - - var vFor = { - - priority: FOR, - terminal: true, - - params: ['track-by', 'stagger', 'enter-stagger', 'leave-stagger'], - - bind: function bind() { - // support "item in/of items" syntax - var inMatch = this.expression.match(/(.*) (?:in|of) (.*)/); - if (inMatch) { - var itMatch = inMatch[1].match(/\((.*),(.*)\)/); - if (itMatch) { - this.iterator = itMatch[1].trim(); - this.alias = itMatch[2].trim(); - } else { - this.alias = inMatch[1].trim(); - } - this.expression = inMatch[2]; - } - - if (!this.alias) { - 'development' !== 'production' && warn('Invalid v-for expression "' + this.descriptor.raw + '": ' + 'alias is required.', this.vm); - return; - } - - // uid as a cache identifier - this.id = '__v-for__' + ++uid$3; - - // check if this is an option list, - // so that we know if we need to update the <select>'s - // v-model when the option list has changed. - // because v-model has a lower priority than v-for, - // the v-model is not bound here yet, so we have to - // retrive it in the actual updateModel() function. - var tag = this.el.tagName; - this.isOption = (tag === 'OPTION' || tag === 'OPTGROUP') && this.el.parentNode.tagName === 'SELECT'; - - // setup anchor nodes - this.start = createAnchor('v-for-start'); - this.end = createAnchor('v-for-end'); - replace(this.el, this.end); - before(this.start, this.end); - - // cache - this.cache = Object.create(null); - - // fragment factory - this.factory = new FragmentFactory(this.vm, this.el); - }, - - update: function update(data) { - this.diff(data); - this.updateRef(); - this.updateModel(); - }, - - /** - * Diff, based on new data and old data, determine the - * minimum amount of DOM manipulations needed to make the - * DOM reflect the new data Array. - * - * The algorithm diffs the new data Array by storing a - * hidden reference to an owner vm instance on previously - * seen data. This allows us to achieve O(n) which is - * better than a levenshtein distance based algorithm, - * which is O(m * n). - * - * @param {Array} data - */ - - diff: function diff(data) { - // check if the Array was converted from an Object - var item = data[0]; - var convertedFromObject = this.fromObject = isObject(item) && hasOwn(item, '$key') && hasOwn(item, '$value'); - - var trackByKey = this.params.trackBy; - var oldFrags = this.frags; - var frags = this.frags = new Array(data.length); - var alias = this.alias; - var iterator = this.iterator; - var start = this.start; - var end = this.end; - var inDocument = inDoc(start); - var init = !oldFrags; - var i, l, frag, key, value, primitive; - - // First pass, go through the new Array and fill up - // the new frags array. If a piece of data has a cached - // instance for it, we reuse it. Otherwise build a new - // instance. - for (i = 0, l = data.length; i < l; i++) { - item = data[i]; - key = convertedFromObject ? item.$key : null; - value = convertedFromObject ? item.$value : item; - primitive = !isObject(value); - frag = !init && this.getCachedFrag(value, i, key); - if (frag) { - // reusable fragment - frag.reused = true; - // update $index - frag.scope.$index = i; - // update $key - if (key) { - frag.scope.$key = key; - } - // update iterator - if (iterator) { - frag.scope[iterator] = key !== null ? key : i; - } - // update data for track-by, object repeat & - // primitive values. - if (trackByKey || convertedFromObject || primitive) { - withoutConversion(function () { - frag.scope[alias] = value; - }); - } - } else { - // new isntance - frag = this.create(value, alias, i, key); - frag.fresh = !init; - } - frags[i] = frag; - if (init) { - frag.before(end); - } - } - - // we're done for the initial render. - if (init) { - return; - } - - // Second pass, go through the old fragments and - // destroy those who are not reused (and remove them - // from cache) - var removalIndex = 0; - var totalRemoved = oldFrags.length - frags.length; - // when removing a large number of fragments, watcher removal - // turns out to be a perf bottleneck, so we batch the watcher - // removals into a single filter call! - this.vm._vForRemoving = true; - for (i = 0, l = oldFrags.length; i < l; i++) { - frag = oldFrags[i]; - if (!frag.reused) { - this.deleteCachedFrag(frag); - this.remove(frag, removalIndex++, totalRemoved, inDocument); - } - } - this.vm._vForRemoving = false; - if (removalIndex) { - this.vm._watchers = this.vm._watchers.filter(function (w) { - return w.active; - }); - } - - // Final pass, move/insert new fragments into the - // right place. - var targetPrev, prevEl, currentPrev; - var insertionIndex = 0; - for (i = 0, l = frags.length; i < l; i++) { - frag = frags[i]; - // this is the frag that we should be after - targetPrev = frags[i - 1]; - prevEl = targetPrev ? targetPrev.staggerCb ? targetPrev.staggerAnchor : targetPrev.end || targetPrev.node : start; - if (frag.reused && !frag.staggerCb) { - currentPrev = findPrevFrag(frag, start, this.id); - if (currentPrev !== targetPrev && (!currentPrev || - // optimization for moving a single item. - // thanks to suggestions by @livoras in #1807 - findPrevFrag(currentPrev, start, this.id) !== targetPrev)) { - this.move(frag, prevEl); - } - } else { - // new instance, or still in stagger. - // insert with updated stagger index. - this.insert(frag, insertionIndex++, prevEl, inDocument); - } - frag.reused = frag.fresh = false; - } - }, - - /** - * Create a new fragment instance. - * - * @param {*} value - * @param {String} alias - * @param {Number} index - * @param {String} [key] - * @return {Fragment} - */ - - create: function create(value, alias, index, key) { - var host = this._host; - // create iteration scope - var parentScope = this._scope || this.vm; - var scope = Object.create(parentScope); - // ref holder for the scope - scope.$refs = Object.create(parentScope.$refs); - scope.$els = Object.create(parentScope.$els); - // make sure point $parent to parent scope - scope.$parent = parentScope; - // for two-way binding on alias - scope.$forContext = this; - // define scope properties - // important: define the scope alias without forced conversion - // so that frozen data structures remain non-reactive. - withoutConversion(function () { - defineReactive(scope, alias, value); - }); - defineReactive(scope, '$index', index); - if (key) { - defineReactive(scope, '$key', key); - } else if (scope.$key) { - // avoid accidental fallback - def(scope, '$key', null); - } - if (this.iterator) { - defineReactive(scope, this.iterator, key !== null ? key : index); - } - var frag = this.factory.create(host, scope, this._frag); - frag.forId = this.id; - this.cacheFrag(value, frag, index, key); - return frag; - }, - - /** - * Update the v-ref on owner vm. - */ - - updateRef: function updateRef() { - var ref = this.descriptor.ref; - if (!ref) return; - var hash = (this._scope || this.vm).$refs; - var refs; - if (!this.fromObject) { - refs = this.frags.map(findVmFromFrag); - } else { - refs = {}; - this.frags.forEach(function (frag) { - refs[frag.scope.$key] = findVmFromFrag(frag); - }); - } - hash[ref] = refs; - }, - - /** - * For option lists, update the containing v-model on - * parent <select>. - */ - - updateModel: function updateModel() { - if (this.isOption) { - var parent = this.start.parentNode; - var model = parent && parent.__v_model; - if (model) { - model.forceUpdate(); - } - } - }, - - /** - * Insert a fragment. Handles staggering. - * - * @param {Fragment} frag - * @param {Number} index - * @param {Node} prevEl - * @param {Boolean} inDocument - */ - - insert: function insert(frag, index, prevEl, inDocument) { - if (frag.staggerCb) { - frag.staggerCb.cancel(); - frag.staggerCb = null; - } - var staggerAmount = this.getStagger(frag, index, null, 'enter'); - if (inDocument && staggerAmount) { - // create an anchor and insert it synchronously, - // so that we can resolve the correct order without - // worrying about some elements not inserted yet - var anchor = frag.staggerAnchor; - if (!anchor) { - anchor = frag.staggerAnchor = createAnchor('stagger-anchor'); - anchor.__v_frag = frag; - } - after(anchor, prevEl); - var op = frag.staggerCb = cancellable(function () { - frag.staggerCb = null; - frag.before(anchor); - remove(anchor); - }); - setTimeout(op, staggerAmount); - } else { - var target = prevEl.nextSibling; - /* istanbul ignore if */ - if (!target) { - // reset end anchor position in case the position was messed up - // by an external drag-n-drop library. - after(this.end, prevEl); - target = this.end; - } - frag.before(target); - } - }, - - /** - * Remove a fragment. Handles staggering. - * - * @param {Fragment} frag - * @param {Number} index - * @param {Number} total - * @param {Boolean} inDocument - */ - - remove: function remove(frag, index, total, inDocument) { - if (frag.staggerCb) { - frag.staggerCb.cancel(); - frag.staggerCb = null; - // it's not possible for the same frag to be removed - // twice, so if we have a pending stagger callback, - // it means this frag is queued for enter but removed - // before its transition started. Since it is already - // destroyed, we can just leave it in detached state. - return; - } - var staggerAmount = this.getStagger(frag, index, total, 'leave'); - if (inDocument && staggerAmount) { - var op = frag.staggerCb = cancellable(function () { - frag.staggerCb = null; - frag.remove(); - }); - setTimeout(op, staggerAmount); - } else { - frag.remove(); - } - }, - - /** - * Move a fragment to a new position. - * Force no transition. - * - * @param {Fragment} frag - * @param {Node} prevEl - */ - - move: function move(frag, prevEl) { - // fix a common issue with Sortable: - // if prevEl doesn't have nextSibling, this means it's - // been dragged after the end anchor. Just re-position - // the end anchor to the end of the container. - /* istanbul ignore if */ - if (!prevEl.nextSibling) { - this.end.parentNode.appendChild(this.end); - } - frag.before(prevEl.nextSibling, false); - }, - - /** - * Cache a fragment using track-by or the object key. - * - * @param {*} value - * @param {Fragment} frag - * @param {Number} index - * @param {String} [key] - */ - - cacheFrag: function cacheFrag(value, frag, index, key) { - var trackByKey = this.params.trackBy; - var cache = this.cache; - var primitive = !isObject(value); - var id; - if (key || trackByKey || primitive) { - id = getTrackByKey(index, key, value, trackByKey); - if (!cache[id]) { - cache[id] = frag; - } else if (trackByKey !== '$index') { - 'development' !== 'production' && this.warnDuplicate(value); - } - } else { - id = this.id; - if (hasOwn(value, id)) { - if (value[id] === null) { - value[id] = frag; - } else { - 'development' !== 'production' && this.warnDuplicate(value); - } - } else if (Object.isExtensible(value)) { - def(value, id, frag); - } else if ('development' !== 'production') { - warn('Frozen v-for objects cannot be automatically tracked, make sure to ' + 'provide a track-by key.'); - } - } - frag.raw = value; - }, - - /** - * Get a cached fragment from the value/index/key - * - * @param {*} value - * @param {Number} index - * @param {String} key - * @return {Fragment} - */ - - getCachedFrag: function getCachedFrag(value, index, key) { - var trackByKey = this.params.trackBy; - var primitive = !isObject(value); - var frag; - if (key || trackByKey || primitive) { - var id = getTrackByKey(index, key, value, trackByKey); - frag = this.cache[id]; - } else { - frag = value[this.id]; - } - if (frag && (frag.reused || frag.fresh)) { - 'development' !== 'production' && this.warnDuplicate(value); - } - return frag; - }, - - /** - * Delete a fragment from cache. - * - * @param {Fragment} frag - */ - - deleteCachedFrag: function deleteCachedFrag(frag) { - var value = frag.raw; - var trackByKey = this.params.trackBy; - var scope = frag.scope; - var index = scope.$index; - // fix #948: avoid accidentally fall through to - // a parent repeater which happens to have $key. - var key = hasOwn(scope, '$key') && scope.$key; - var primitive = !isObject(value); - if (trackByKey || key || primitive) { - var id = getTrackByKey(index, key, value, trackByKey); - this.cache[id] = null; - } else { - value[this.id] = null; - frag.raw = null; - } - }, - - /** - * Get the stagger amount for an insertion/removal. - * - * @param {Fragment} frag - * @param {Number} index - * @param {Number} total - * @param {String} type - */ - - getStagger: function getStagger(frag, index, total, type) { - type = type + 'Stagger'; - var trans = frag.node.__v_trans; - var hooks = trans && trans.hooks; - var hook = hooks && (hooks[type] || hooks.stagger); - return hook ? hook.call(frag, index, total) : index * parseInt(this.params[type] || this.params.stagger, 10); - }, - - /** - * Pre-process the value before piping it through the - * filters. This is passed to and called by the watcher. - */ - - _preProcess: function _preProcess(value) { - // regardless of type, store the un-filtered raw value. - this.rawValue = value; - return value; - }, - - /** - * Post-process the value after it has been piped through - * the filters. This is passed to and called by the watcher. - * - * It is necessary for this to be called during the - * watcher's dependency collection phase because we want - * the v-for to update when the source Object is mutated. - */ - - _postProcess: function _postProcess(value) { - if (isArray(value)) { - return value; - } else if (isPlainObject(value)) { - // convert plain object to array. - var keys = Object.keys(value); - var i = keys.length; - var res = new Array(i); - var key; - while (i--) { - key = keys[i]; - res[i] = { - $key: key, - $value: value[key] - }; - } - return res; - } else { - if (typeof value === 'number' && !isNaN(value)) { - value = range(value); - } - return value || []; - } - }, - - unbind: function unbind() { - if (this.descriptor.ref) { - (this._scope || this.vm).$refs[this.descriptor.ref] = null; - } - if (this.frags) { - var i = this.frags.length; - var frag; - while (i--) { - frag = this.frags[i]; - this.deleteCachedFrag(frag); - frag.destroy(); - } - } - } - }; - - /** - * Helper to find the previous element that is a fragment - * anchor. This is necessary because a destroyed frag's - * element could still be lingering in the DOM before its - * leaving transition finishes, but its inserted flag - * should have been set to false so we can skip them. - * - * If this is a block repeat, we want to make sure we only - * return frag that is bound to this v-for. (see #929) - * - * @param {Fragment} frag - * @param {Comment|Text} anchor - * @param {String} id - * @return {Fragment} - */ - - function findPrevFrag(frag, anchor, id) { - var el = frag.node.previousSibling; - /* istanbul ignore if */ - if (!el) return; - frag = el.__v_frag; - while ((!frag || frag.forId !== id || !frag.inserted) && el !== anchor) { - el = el.previousSibling; - /* istanbul ignore if */ - if (!el) return; - frag = el.__v_frag; - } - return frag; - } - - /** - * Find a vm from a fragment. - * - * @param {Fragment} frag - * @return {Vue|undefined} - */ - - function findVmFromFrag(frag) { - var node = frag.node; - // handle multi-node frag - if (frag.end) { - while (!node.__vue__ && node !== frag.end && node.nextSibling) { - node = node.nextSibling; - } - } - return node.__vue__; - } - - /** - * Create a range array from given number. - * - * @param {Number} n - * @return {Array} - */ - - function range(n) { - var i = -1; - var ret = new Array(Math.floor(n)); - while (++i < n) { - ret[i] = i; - } - return ret; - } - - /** - * Get the track by key for an item. - * - * @param {Number} index - * @param {String} key - * @param {*} value - * @param {String} [trackByKey] - */ - - function getTrackByKey(index, key, value, trackByKey) { - return trackByKey ? trackByKey === '$index' ? index : trackByKey.charAt(0).match(/\w/) ? getPath(value, trackByKey) : value[trackByKey] : key || value; - } - - if ('development' !== 'production') { - vFor.warnDuplicate = function (value) { - warn('Duplicate value found in v-for="' + this.descriptor.raw + '": ' + JSON.stringify(value) + '. Use track-by="$index" if ' + 'you are expecting duplicate values.', this.vm); - }; - } - - var vIf = { - - priority: IF, - terminal: true, - - bind: function bind() { - var el = this.el; - if (!el.__vue__) { - // check else block - var next = el.nextElementSibling; - if (next && getAttr(next, 'v-else') !== null) { - remove(next); - this.elseEl = next; - } - // check main block - this.anchor = createAnchor('v-if'); - replace(el, this.anchor); - } else { - 'development' !== 'production' && warn('v-if="' + this.expression + '" cannot be ' + 'used on an instance root element.', this.vm); - this.invalid = true; - } - }, - - update: function update(value) { - if (this.invalid) return; - if (value) { - if (!this.frag) { - this.insert(); - } - } else { - this.remove(); - } - }, - - insert: function insert() { - if (this.elseFrag) { - this.elseFrag.remove(); - this.elseFrag = null; - } - // lazy init factory - if (!this.factory) { - this.factory = new FragmentFactory(this.vm, this.el); - } - this.frag = this.factory.create(this._host, this._scope, this._frag); - this.frag.before(this.anchor); - }, - - remove: function remove() { - if (this.frag) { - this.frag.remove(); - this.frag = null; - } - if (this.elseEl && !this.elseFrag) { - if (!this.elseFactory) { - this.elseFactory = new FragmentFactory(this.elseEl._context || this.vm, this.elseEl); - } - this.elseFrag = this.elseFactory.create(this._host, this._scope, this._frag); - this.elseFrag.before(this.anchor); - } - }, - - unbind: function unbind() { - if (this.frag) { - this.frag.destroy(); - } - if (this.elseFrag) { - this.elseFrag.destroy(); - } - } - }; - - var show = { - - bind: function bind() { - // check else block - var next = this.el.nextElementSibling; - if (next && getAttr(next, 'v-else') !== null) { - this.elseEl = next; - } - }, - - update: function update(value) { - this.apply(this.el, value); - if (this.elseEl) { - this.apply(this.elseEl, !value); - } - }, - - apply: function apply(el, value) { - if (inDoc(el)) { - applyTransition(el, value ? 1 : -1, toggle, this.vm); - } else { - toggle(); - } - function toggle() { - el.style.display = value ? '' : 'none'; - } - } - }; - - var text$2 = { - - bind: function bind() { - var self = this; - var el = this.el; - var isRange = el.type === 'range'; - var lazy = this.params.lazy; - var number = this.params.number; - var debounce = this.params.debounce; - - // handle composition events. - // http://blog.evanyou.me/2014/01/03/composition-event/ - // skip this for Android because it handles composition - // events quite differently. Android doesn't trigger - // composition events for language input methods e.g. - // Chinese, but instead triggers them for spelling - // suggestions... (see Discussion/#162) - var composing = false; - if (!isAndroid && !isRange) { - this.on('compositionstart', function () { - composing = true; - }); - this.on('compositionend', function () { - composing = false; - // in IE11 the "compositionend" event fires AFTER - // the "input" event, so the input handler is blocked - // at the end... have to call it here. - // - // #1327: in lazy mode this is unecessary. - if (!lazy) { - self.listener(); - } - }); - } - - // prevent messing with the input when user is typing, - // and force update on blur. - this.focused = false; - if (!isRange && !lazy) { - this.on('focus', function () { - self.focused = true; - }); - this.on('blur', function () { - self.focused = false; - // do not sync value after fragment removal (#2017) - if (!self._frag || self._frag.inserted) { - self.rawListener(); - } - }); - } - - // Now attach the main listener - this.listener = this.rawListener = function () { - if (composing || !self._bound) { - return; - } - var val = number || isRange ? toNumber(el.value) : el.value; - self.set(val); - // force update on next tick to avoid lock & same value - // also only update when user is not typing - nextTick(function () { - if (self._bound && !self.focused) { - self.update(self._watcher.value); - } - }); - }; - - // apply debounce - if (debounce) { - this.listener = _debounce(this.listener, debounce); - } - - // Support jQuery events, since jQuery.trigger() doesn't - // trigger native events in some cases and some plugins - // rely on $.trigger() - // - // We want to make sure if a listener is attached using - // jQuery, it is also removed with jQuery, that's why - // we do the check for each directive instance and - // store that check result on itself. This also allows - // easier test coverage control by unsetting the global - // jQuery variable in tests. - this.hasjQuery = typeof jQuery === 'function'; - if (this.hasjQuery) { - var method = jQuery.fn.on ? 'on' : 'bind'; - jQuery(el)[method]('change', this.rawListener); - if (!lazy) { - jQuery(el)[method]('input', this.listener); - } - } else { - this.on('change', this.rawListener); - if (!lazy) { - this.on('input', this.listener); - } - } - - // IE9 doesn't fire input event on backspace/del/cut - if (!lazy && isIE9) { - this.on('cut', function () { - nextTick(self.listener); - }); - this.on('keyup', function (e) { - if (e.keyCode === 46 || e.keyCode === 8) { - self.listener(); - } - }); - } - - // set initial value if present - if (el.hasAttribute('value') || el.tagName === 'TEXTAREA' && el.value.trim()) { - this.afterBind = this.listener; - } - }, - - update: function update(value) { - // #3029 only update when the value changes. This prevent - // browsers from overwriting values like selectionStart - value = _toString(value); - if (value !== this.el.value) this.el.value = value; - }, - - unbind: function unbind() { - var el = this.el; - if (this.hasjQuery) { - var method = jQuery.fn.off ? 'off' : 'unbind'; - jQuery(el)[method]('change', this.listener); - jQuery(el)[method]('input', this.listener); - } - } - }; - - var radio = { - - bind: function bind() { - var self = this; - var el = this.el; - - this.getValue = function () { - // value overwrite via v-bind:value - if (el.hasOwnProperty('_value')) { - return el._value; - } - var val = el.value; - if (self.params.number) { - val = toNumber(val); - } - return val; - }; - - this.listener = function () { - self.set(self.getValue()); - }; - this.on('change', this.listener); - - if (el.hasAttribute('checked')) { - this.afterBind = this.listener; - } - }, - - update: function update(value) { - this.el.checked = looseEqual(value, this.getValue()); - } - }; - - var select = { - - bind: function bind() { - var _this = this; - - var self = this; - var el = this.el; - - // method to force update DOM using latest value. - this.forceUpdate = function () { - if (self._watcher) { - self.update(self._watcher.get()); - } - }; - - // check if this is a multiple select - var multiple = this.multiple = el.hasAttribute('multiple'); - - // attach listener - this.listener = function () { - var value = getValue(el, multiple); - value = self.params.number ? isArray(value) ? value.map(toNumber) : toNumber(value) : value; - self.set(value); - }; - this.on('change', this.listener); - - // if has initial value, set afterBind - var initValue = getValue(el, multiple, true); - if (multiple && initValue.length || !multiple && initValue !== null) { - this.afterBind = this.listener; - } - - // All major browsers except Firefox resets - // selectedIndex with value -1 to 0 when the element - // is appended to a new parent, therefore we have to - // force a DOM update whenever that happens... - this.vm.$on('hook:attached', function () { - nextTick(_this.forceUpdate); - }); - if (!inDoc(el)) { - nextTick(this.forceUpdate); - } - }, - - update: function update(value) { - var el = this.el; - el.selectedIndex = -1; - var multi = this.multiple && isArray(value); - var options = el.options; - var i = options.length; - var op, val; - while (i--) { - op = options[i]; - val = op.hasOwnProperty('_value') ? op._value : op.value; - /* eslint-disable eqeqeq */ - op.selected = multi ? indexOf$1(value, val) > -1 : looseEqual(value, val); - /* eslint-enable eqeqeq */ - } - }, - - unbind: function unbind() { - /* istanbul ignore next */ - this.vm.$off('hook:attached', this.forceUpdate); - } - }; - - /** - * Get select value - * - * @param {SelectElement} el - * @param {Boolean} multi - * @param {Boolean} init - * @return {Array|*} - */ - - function getValue(el, multi, init) { - var res = multi ? [] : null; - var op, val, selected; - for (var i = 0, l = el.options.length; i < l; i++) { - op = el.options[i]; - selected = init ? op.hasAttribute('selected') : op.selected; - if (selected) { - val = op.hasOwnProperty('_value') ? op._value : op.value; - if (multi) { - res.push(val); - } else { - return val; - } - } - } - return res; - } - - /** - * Native Array.indexOf uses strict equal, but in this - * case we need to match string/numbers with custom equal. - * - * @param {Array} arr - * @param {*} val - */ - - function indexOf$1(arr, val) { - var i = arr.length; - while (i--) { - if (looseEqual(arr[i], val)) { - return i; - } - } - return -1; - } - - var checkbox = { - - bind: function bind() { - var self = this; - var el = this.el; - - this.getValue = function () { - return el.hasOwnProperty('_value') ? el._value : self.params.number ? toNumber(el.value) : el.value; - }; - - function getBooleanValue() { - var val = el.checked; - if (val && el.hasOwnProperty('_trueValue')) { - return el._trueValue; - } - if (!val && el.hasOwnProperty('_falseValue')) { - return el._falseValue; - } - return val; - } - - this.listener = function () { - var model = self._watcher.value; - if (isArray(model)) { - var val = self.getValue(); - if (el.checked) { - if (indexOf(model, val) < 0) { - model.push(val); - } - } else { - model.$remove(val); - } - } else { - self.set(getBooleanValue()); - } - }; - - this.on('change', this.listener); - if (el.hasAttribute('checked')) { - this.afterBind = this.listener; - } - }, - - update: function update(value) { - var el = this.el; - if (isArray(value)) { - el.checked = indexOf(value, this.getValue()) > -1; - } else { - if (el.hasOwnProperty('_trueValue')) { - el.checked = looseEqual(value, el._trueValue); - } else { - el.checked = !!value; - } - } - } - }; - - var handlers = { - text: text$2, - radio: radio, - select: select, - checkbox: checkbox - }; - - var model = { - - priority: MODEL, - twoWay: true, - handlers: handlers, - params: ['lazy', 'number', 'debounce'], - - /** - * Possible elements: - * <select> - * <textarea> - * <input type="*"> - * - text - * - checkbox - * - radio - * - number - */ - - bind: function bind() { - // friendly warning... - this.checkFilters(); - if (this.hasRead && !this.hasWrite) { - 'development' !== 'production' && warn('It seems you are using a read-only filter with ' + 'v-model="' + this.descriptor.raw + '". ' + 'You might want to use a two-way filter to ensure correct behavior.', this.vm); - } - var el = this.el; - var tag = el.tagName; - var handler; - if (tag === 'INPUT') { - handler = handlers[el.type] || handlers.text; - } else if (tag === 'SELECT') { - handler = handlers.select; - } else if (tag === 'TEXTAREA') { - handler = handlers.text; - } else { - 'development' !== 'production' && warn('v-model does not support element type: ' + tag, this.vm); - return; - } - el.__v_model = this; - handler.bind.call(this); - this.update = handler.update; - this._unbind = handler.unbind; - }, - - /** - * Check read/write filter stats. - */ - - checkFilters: function checkFilters() { - var filters = this.filters; - if (!filters) return; - var i = filters.length; - while (i--) { - var filter = resolveAsset(this.vm.$options, 'filters', filters[i].name); - if (typeof filter === 'function' || filter.read) { - this.hasRead = true; - } - if (filter.write) { - this.hasWrite = true; - } - } - }, - - unbind: function unbind() { - this.el.__v_model = null; - this._unbind && this._unbind(); - } - }; - - // keyCode aliases - var keyCodes = { - esc: 27, - tab: 9, - enter: 13, - space: 32, - 'delete': [8, 46], - up: 38, - left: 37, - right: 39, - down: 40 - }; - - function keyFilter(handler, keys) { - var codes = keys.map(function (key) { - var charCode = key.charCodeAt(0); - if (charCode > 47 && charCode < 58) { - return parseInt(key, 10); - } - if (key.length === 1) { - charCode = key.toUpperCase().charCodeAt(0); - if (charCode > 64 && charCode < 91) { - return charCode; - } - } - return keyCodes[key]; - }); - codes = [].concat.apply([], codes); - return function keyHandler(e) { - if (codes.indexOf(e.keyCode) > -1) { - return handler.call(this, e); - } - }; - } - - function stopFilter(handler) { - return function stopHandler(e) { - e.stopPropagation(); - return handler.call(this, e); - }; - } - - function preventFilter(handler) { - return function preventHandler(e) { - e.preventDefault(); - return handler.call(this, e); - }; - } - - function selfFilter(handler) { - return function selfHandler(e) { - if (e.target === e.currentTarget) { - return handler.call(this, e); - } - }; - } - - var on$1 = { - - priority: ON, - acceptStatement: true, - keyCodes: keyCodes, - - bind: function bind() { - // deal with iframes - if (this.el.tagName === 'IFRAME' && this.arg !== 'load') { - var self = this; - this.iframeBind = function () { - on(self.el.contentWindow, self.arg, self.handler, self.modifiers.capture); - }; - this.on('load', this.iframeBind); - } - }, - - update: function update(handler) { - // stub a noop for v-on with no value, - // e.g. @mousedown.prevent - if (!this.descriptor.raw) { - handler = function () {}; - } - - if (typeof handler !== 'function') { - 'development' !== 'production' && warn('v-on:' + this.arg + '="' + this.expression + '" expects a function value, ' + 'got ' + handler, this.vm); - return; - } - - // apply modifiers - if (this.modifiers.stop) { - handler = stopFilter(handler); - } - if (this.modifiers.prevent) { - handler = preventFilter(handler); - } - if (this.modifiers.self) { - handler = selfFilter(handler); - } - // key filter - var keys = Object.keys(this.modifiers).filter(function (key) { - return key !== 'stop' && key !== 'prevent' && key !== 'self' && key !== 'capture'; - }); - if (keys.length) { - handler = keyFilter(handler, keys); - } - - this.reset(); - this.handler = handler; - - if (this.iframeBind) { - this.iframeBind(); - } else { - on(this.el, this.arg, this.handler, this.modifiers.capture); - } - }, - - reset: function reset() { - var el = this.iframeBind ? this.el.contentWindow : this.el; - if (this.handler) { - off(el, this.arg, this.handler); - } - }, - - unbind: function unbind() { - this.reset(); - } - }; - - var prefixes = ['-webkit-', '-moz-', '-ms-']; - var camelPrefixes = ['Webkit', 'Moz', 'ms']; - var importantRE = /!important;?$/; - var propCache = Object.create(null); - - var testEl = null; - - var style = { - - deep: true, - - update: function update(value) { - if (typeof value === 'string') { - this.el.style.cssText = value; - } else if (isArray(value)) { - this.handleObject(value.reduce(extend, {})); - } else { - this.handleObject(value || {}); - } - }, - - handleObject: function handleObject(value) { - // cache object styles so that only changed props - // are actually updated. - var cache = this.cache || (this.cache = {}); - var name, val; - for (name in cache) { - if (!(name in value)) { - this.handleSingle(name, null); - delete cache[name]; - } - } - for (name in value) { - val = value[name]; - if (val !== cache[name]) { - cache[name] = val; - this.handleSingle(name, val); - } - } - }, - - handleSingle: function handleSingle(prop, value) { - prop = normalize(prop); - if (!prop) return; // unsupported prop - // cast possible numbers/booleans into strings - if (value != null) value += ''; - if (value) { - var isImportant = importantRE.test(value) ? 'important' : ''; - if (isImportant) { - /* istanbul ignore if */ - if ('development' !== 'production') { - warn('It\'s probably a bad idea to use !important with inline rules. ' + 'This feature will be deprecated in a future version of Vue.'); - } - value = value.replace(importantRE, '').trim(); - this.el.style.setProperty(prop.kebab, value, isImportant); - } else { - this.el.style[prop.camel] = value; - } - } else { - this.el.style[prop.camel] = ''; - } - } - - }; - - /** - * Normalize a CSS property name. - * - cache result - * - auto prefix - * - camelCase -> dash-case - * - * @param {String} prop - * @return {String} - */ - - function normalize(prop) { - if (propCache[prop]) { - return propCache[prop]; - } - var res = prefix(prop); - propCache[prop] = propCache[res] = res; - return res; - } - - /** - * Auto detect the appropriate prefix for a CSS property. - * https://gist.github.com/paulirish/523692 - * - * @param {String} prop - * @return {String} - */ - - function prefix(prop) { - prop = hyphenate(prop); - var camel = camelize(prop); - var upper = camel.charAt(0).toUpperCase() + camel.slice(1); - if (!testEl) { - testEl = document.createElement('div'); - } - var i = prefixes.length; - var prefixed; - if (camel !== 'filter' && camel in testEl.style) { - return { - kebab: prop, - camel: camel - }; - } - while (i--) { - prefixed = camelPrefixes[i] + upper; - if (prefixed in testEl.style) { - return { - kebab: prefixes[i] + prop, - camel: prefixed - }; - } - } - } - - // xlink - var xlinkNS = 'http://www.w3.org/1999/xlink'; - var xlinkRE = /^xlink:/; - - // check for attributes that prohibit interpolations - var disallowedInterpAttrRE = /^v-|^:|^@|^(?:is|transition|transition-mode|debounce|track-by|stagger|enter-stagger|leave-stagger)$/; - // these attributes should also set their corresponding properties - // because they only affect the initial state of the element - var attrWithPropsRE = /^(?:value|checked|selected|muted)$/; - // these attributes expect enumrated values of "true" or "false" - // but are not boolean attributes - var enumeratedAttrRE = /^(?:draggable|contenteditable|spellcheck)$/; - - // these attributes should set a hidden property for - // binding v-model to object values - var modelProps = { - value: '_value', - 'true-value': '_trueValue', - 'false-value': '_falseValue' - }; - - var bind$1 = { - - priority: BIND, - - bind: function bind() { - var attr = this.arg; - var tag = this.el.tagName; - // should be deep watch on object mode - if (!attr) { - this.deep = true; - } - // handle interpolation bindings - var descriptor = this.descriptor; - var tokens = descriptor.interp; - if (tokens) { - // handle interpolations with one-time tokens - if (descriptor.hasOneTime) { - this.expression = tokensToExp(tokens, this._scope || this.vm); - } - - // only allow binding on native attributes - if (disallowedInterpAttrRE.test(attr) || attr === 'name' && (tag === 'PARTIAL' || tag === 'SLOT')) { - 'development' !== 'production' && warn(attr + '="' + descriptor.raw + '": ' + 'attribute interpolation is not allowed in Vue.js ' + 'directives and special attributes.', this.vm); - this.el.removeAttribute(attr); - this.invalid = true; - } - - /* istanbul ignore if */ - if ('development' !== 'production') { - var raw = attr + '="' + descriptor.raw + '": '; - // warn src - if (attr === 'src') { - warn(raw + 'interpolation in "src" attribute will cause ' + 'a 404 request. Use v-bind:src instead.', this.vm); - } - - // warn style - if (attr === 'style') { - warn(raw + 'interpolation in "style" attribute will cause ' + 'the attribute to be discarded in Internet Explorer. ' + 'Use v-bind:style instead.', this.vm); - } - } - } - }, - - update: function update(value) { - if (this.invalid) { - return; - } - var attr = this.arg; - if (this.arg) { - this.handleSingle(attr, value); - } else { - this.handleObject(value || {}); - } - }, - - // share object handler with v-bind:class - handleObject: style.handleObject, - - handleSingle: function handleSingle(attr, value) { - var el = this.el; - var interp = this.descriptor.interp; - if (this.modifiers.camel) { - attr = camelize(attr); - } - if (!interp && attrWithPropsRE.test(attr) && attr in el) { - var attrValue = attr === 'value' ? value == null // IE9 will set input.value to "null" for null... - ? '' : value : value; - - if (el[attr] !== attrValue) { - el[attr] = attrValue; - } - } - // set model props - var modelProp = modelProps[attr]; - if (!interp && modelProp) { - el[modelProp] = value; - // update v-model if present - var model = el.__v_model; - if (model) { - model.listener(); - } - } - // do not set value attribute for textarea - if (attr === 'value' && el.tagName === 'TEXTAREA') { - el.removeAttribute(attr); - return; - } - // update attribute - if (enumeratedAttrRE.test(attr)) { - el.setAttribute(attr, value ? 'true' : 'false'); - } else if (value != null && value !== false) { - if (attr === 'class') { - // handle edge case #1960: - // class interpolation should not overwrite Vue transition class - if (el.__v_trans) { - value += ' ' + el.__v_trans.id + '-transition'; - } - setClass(el, value); - } else if (xlinkRE.test(attr)) { - el.setAttributeNS(xlinkNS, attr, value === true ? '' : value); - } else { - el.setAttribute(attr, value === true ? '' : value); - } - } else { - el.removeAttribute(attr); - } - } - }; - - var el = { - - priority: EL, - - bind: function bind() { - /* istanbul ignore if */ - if (!this.arg) { - return; - } - var id = this.id = camelize(this.arg); - var refs = (this._scope || this.vm).$els; - if (hasOwn(refs, id)) { - refs[id] = this.el; - } else { - defineReactive(refs, id, this.el); - } - }, - - unbind: function unbind() { - var refs = (this._scope || this.vm).$els; - if (refs[this.id] === this.el) { - refs[this.id] = null; - } - } - }; - - var ref = { - bind: function bind() { - 'development' !== 'production' && warn('v-ref:' + this.arg + ' must be used on a child ' + 'component. Found on <' + this.el.tagName.toLowerCase() + '>.', this.vm); - } - }; - - var cloak = { - bind: function bind() { - var el = this.el; - this.vm.$once('pre-hook:compiled', function () { - el.removeAttribute('v-cloak'); - }); - } - }; - - // must export plain object - var directives = { - text: text$1, - html: html, - 'for': vFor, - 'if': vIf, - show: show, - model: model, - on: on$1, - bind: bind$1, - el: el, - ref: ref, - cloak: cloak - }; - - var vClass = { - - deep: true, - - update: function update(value) { - if (!value) { - this.cleanup(); - } else if (typeof value === 'string') { - this.setClass(value.trim().split(/\s+/)); - } else { - this.setClass(normalize$1(value)); - } - }, - - setClass: function setClass(value) { - this.cleanup(value); - for (var i = 0, l = value.length; i < l; i++) { - var val = value[i]; - if (val) { - apply(this.el, val, addClass); - } - } - this.prevKeys = value; - }, - - cleanup: function cleanup(value) { - var prevKeys = this.prevKeys; - if (!prevKeys) return; - var i = prevKeys.length; - while (i--) { - var key = prevKeys[i]; - if (!value || value.indexOf(key) < 0) { - apply(this.el, key, removeClass); - } - } - } - }; - - /** - * Normalize objects and arrays (potentially containing objects) - * into array of strings. - * - * @param {Object|Array<String|Object>} value - * @return {Array<String>} - */ - - function normalize$1(value) { - var res = []; - if (isArray(value)) { - for (var i = 0, l = value.length; i < l; i++) { - var _key = value[i]; - if (_key) { - if (typeof _key === 'string') { - res.push(_key); - } else { - for (var k in _key) { - if (_key[k]) res.push(k); - } - } - } - } - } else if (isObject(value)) { - for (var key in value) { - if (value[key]) res.push(key); - } - } - return res; - } - - /** - * Add or remove a class/classes on an element - * - * @param {Element} el - * @param {String} key The class name. This may or may not - * contain a space character, in such a - * case we'll deal with multiple class - * names at once. - * @param {Function} fn - */ - - function apply(el, key, fn) { - key = key.trim(); - if (key.indexOf(' ') === -1) { - fn(el, key); - return; - } - // The key contains one or more space characters. - // Since a class name doesn't accept such characters, we - // treat it as multiple classes. - var keys = key.split(/\s+/); - for (var i = 0, l = keys.length; i < l; i++) { - fn(el, keys[i]); - } - } - - var component = { - - priority: COMPONENT, - - params: ['keep-alive', 'transition-mode', 'inline-template'], - - /** - * Setup. Two possible usages: - * - * - static: - * <comp> or <div v-component="comp"> - * - * - dynamic: - * <component :is="view"> - */ - - bind: function bind() { - if (!this.el.__vue__) { - // keep-alive cache - this.keepAlive = this.params.keepAlive; - if (this.keepAlive) { - this.cache = {}; - } - // check inline-template - if (this.params.inlineTemplate) { - // extract inline template as a DocumentFragment - this.inlineTemplate = extractContent(this.el, true); - } - // component resolution related state - this.pendingComponentCb = this.Component = null; - // transition related state - this.pendingRemovals = 0; - this.pendingRemovalCb = null; - // create a ref anchor - this.anchor = createAnchor('v-component'); - replace(this.el, this.anchor); - // remove is attribute. - // this is removed during compilation, but because compilation is - // cached, when the component is used elsewhere this attribute - // will remain at link time. - this.el.removeAttribute('is'); - this.el.removeAttribute(':is'); - // remove ref, same as above - if (this.descriptor.ref) { - this.el.removeAttribute('v-ref:' + hyphenate(this.descriptor.ref)); - } - // if static, build right now. - if (this.literal) { - this.setComponent(this.expression); - } - } else { - 'development' !== 'production' && warn('cannot mount component "' + this.expression + '" ' + 'on already mounted element: ' + this.el); - } - }, - - /** - * Public update, called by the watcher in the dynamic - * literal scenario, e.g. <component :is="view"> - */ - - update: function update(value) { - if (!this.literal) { - this.setComponent(value); - } - }, - - /** - * Switch dynamic components. May resolve the component - * asynchronously, and perform transition based on - * specified transition mode. Accepts a few additional - * arguments specifically for vue-router. - * - * The callback is called when the full transition is - * finished. - * - * @param {String} value - * @param {Function} [cb] - */ - - setComponent: function setComponent(value, cb) { - this.invalidatePending(); - if (!value) { - // just remove current - this.unbuild(true); - this.remove(this.childVM, cb); - this.childVM = null; - } else { - var self = this; - this.resolveComponent(value, function () { - self.mountComponent(cb); - }); - } - }, - - /** - * Resolve the component constructor to use when creating - * the child vm. - * - * @param {String|Function} value - * @param {Function} cb - */ - - resolveComponent: function resolveComponent(value, cb) { - var self = this; - this.pendingComponentCb = cancellable(function (Component) { - self.ComponentName = Component.options.name || (typeof value === 'string' ? value : null); - self.Component = Component; - cb(); - }); - this.vm._resolveComponent(value, this.pendingComponentCb); - }, - - /** - * Create a new instance using the current constructor and - * replace the existing instance. This method doesn't care - * whether the new component and the old one are actually - * the same. - * - * @param {Function} [cb] - */ - - mountComponent: function mountComponent(cb) { - // actual mount - this.unbuild(true); - var self = this; - var activateHooks = this.Component.options.activate; - var cached = this.getCached(); - var newComponent = this.build(); - if (activateHooks && !cached) { - this.waitingFor = newComponent; - callActivateHooks(activateHooks, newComponent, function () { - if (self.waitingFor !== newComponent) { - return; - } - self.waitingFor = null; - self.transition(newComponent, cb); - }); - } else { - // update ref for kept-alive component - if (cached) { - newComponent._updateRef(); - } - this.transition(newComponent, cb); - } - }, - - /** - * When the component changes or unbinds before an async - * constructor is resolved, we need to invalidate its - * pending callback. - */ - - invalidatePending: function invalidatePending() { - if (this.pendingComponentCb) { - this.pendingComponentCb.cancel(); - this.pendingComponentCb = null; - } - }, - - /** - * Instantiate/insert a new child vm. - * If keep alive and has cached instance, insert that - * instance; otherwise build a new one and cache it. - * - * @param {Object} [extraOptions] - * @return {Vue} - the created instance - */ - - build: function build(extraOptions) { - var cached = this.getCached(); - if (cached) { - return cached; - } - if (this.Component) { - // default options - var options = { - name: this.ComponentName, - el: cloneNode(this.el), - template: this.inlineTemplate, - // make sure to add the child with correct parent - // if this is a transcluded component, its parent - // should be the transclusion host. - parent: this._host || this.vm, - // if no inline-template, then the compiled - // linker can be cached for better performance. - _linkerCachable: !this.inlineTemplate, - _ref: this.descriptor.ref, - _asComponent: true, - _isRouterView: this._isRouterView, - // if this is a transcluded component, context - // will be the common parent vm of this instance - // and its host. - _context: this.vm, - // 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. - _scope: this._scope, - // pass in the owner fragment of this component. - // this is necessary so that the fragment can keep - // track of its contained components in order to - // call attach/detach hooks for them. - _frag: this._frag - }; - // extra options - // in 1.0.0 this is used by vue-router only - /* istanbul ignore if */ - if (extraOptions) { - extend(options, extraOptions); - } - var child = new this.Component(options); - if (this.keepAlive) { - this.cache[this.Component.cid] = child; - } - /* istanbul ignore if */ - if ('development' !== 'production' && this.el.hasAttribute('transition') && child._isFragment) { - warn('Transitions will not work on a fragment instance. ' + 'Template: ' + child.$options.template, child); - } - return child; - } - }, - - /** - * Try to get a cached instance of the current component. - * - * @return {Vue|undefined} - */ - - getCached: function getCached() { - return this.keepAlive && this.cache[this.Component.cid]; - }, - - /** - * Teardown the current child, but defers cleanup so - * that we can separate the destroy and removal steps. - * - * @param {Boolean} defer - */ - - unbuild: function unbuild(defer) { - if (this.waitingFor) { - if (!this.keepAlive) { - this.waitingFor.$destroy(); - } - this.waitingFor = null; - } - var child = this.childVM; - if (!child || this.keepAlive) { - if (child) { - // remove ref - child._inactive = true; - child._updateRef(true); - } - return; - } - // the sole purpose of `deferCleanup` is so that we can - // "deactivate" the vm right now and perform DOM removal - // later. - child.$destroy(false, defer); - }, - - /** - * Remove current destroyed child and manually do - * the cleanup after removal. - * - * @param {Function} cb - */ - - remove: function remove(child, cb) { - var keepAlive = this.keepAlive; - if (child) { - // we may have a component switch when a previous - // component is still being transitioned out. - // we want to trigger only one lastest insertion cb - // when the existing transition finishes. (#1119) - this.pendingRemovals++; - this.pendingRemovalCb = cb; - var self = this; - child.$remove(function () { - self.pendingRemovals--; - if (!keepAlive) child._cleanup(); - if (!self.pendingRemovals && self.pendingRemovalCb) { - self.pendingRemovalCb(); - self.pendingRemovalCb = null; - } - }); - } else if (cb) { - cb(); - } - }, - - /** - * Actually swap the components, depending on the - * transition mode. Defaults to simultaneous. - * - * @param {Vue} target - * @param {Function} [cb] - */ - - transition: function transition(target, cb) { - var self = this; - var current = this.childVM; - // for devtool inspection - if (current) current._inactive = true; - target._inactive = false; - this.childVM = target; - switch (self.params.transitionMode) { - case 'in-out': - target.$before(self.anchor, function () { - self.remove(current, cb); - }); - break; - case 'out-in': - self.remove(current, function () { - target.$before(self.anchor, cb); - }); - break; - default: - self.remove(current); - target.$before(self.anchor, cb); - } - }, - - /** - * Unbind. - */ - - unbind: function unbind() { - this.invalidatePending(); - // Do not defer cleanup when unbinding - this.unbuild(); - // destroy all keep-alive cached instances - if (this.cache) { - for (var key in this.cache) { - this.cache[key].$destroy(); - } - this.cache = null; - } - } - }; - - /** - * Call activate hooks in order (asynchronous) - * - * @param {Array} hooks - * @param {Vue} vm - * @param {Function} cb - */ - - function callActivateHooks(hooks, vm, cb) { - var total = hooks.length; - var called = 0; - hooks[0].call(vm, next); - function next() { - if (++called >= total) { - cb(); - } else { - hooks[called].call(vm, next); - } - } - } - - var propBindingModes = config._propBindingModes; - var empty = {}; - - // regexes - var identRE$1 = /^[$_a-zA-Z]+[\w$]*$/; - var settablePathRE = /^[A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*|\[[^\[\]]+\])*$/; - - /** - * Compile props on a root element and return - * a props link function. - * - * @param {Element|DocumentFragment} el - * @param {Array} propOptions - * @param {Vue} vm - * @return {Function} propsLinkFn - */ - - function compileProps(el, propOptions, vm) { - var props = []; - var names = Object.keys(propOptions); - var i = names.length; - var options, name, attr, value, path, parsed, prop; - while (i--) { - name = names[i]; - options = propOptions[name] || empty; - - if ('development' !== 'production' && name === '$data') { - warn('Do not use $data as prop.', vm); - continue; - } - - // props could contain dashes, which will be - // interpreted as minus calculations by the parser - // so we need to camelize the path here - path = camelize(name); - if (!identRE$1.test(path)) { - 'development' !== 'production' && warn('Invalid prop key: "' + name + '". Prop keys ' + 'must be valid identifiers.', vm); - continue; - } - - prop = { - name: name, - path: path, - options: options, - mode: propBindingModes.ONE_WAY, - raw: null - }; - - attr = hyphenate(name); - // first check dynamic version - if ((value = getBindAttr(el, attr)) === null) { - if ((value = getBindAttr(el, attr + '.sync')) !== null) { - prop.mode = propBindingModes.TWO_WAY; - } else if ((value = getBindAttr(el, attr + '.once')) !== null) { - prop.mode = propBindingModes.ONE_TIME; - } - } - if (value !== null) { - // has dynamic binding! - prop.raw = value; - parsed = parseDirective(value); - value = parsed.expression; - prop.filters = parsed.filters; - // check binding type - if (isLiteral(value) && !parsed.filters) { - // for expressions containing literal numbers and - // booleans, there's no need to setup a prop binding, - // so we can optimize them as a one-time set. - prop.optimizedLiteral = true; - } else { - prop.dynamic = true; - // check non-settable path for two-way bindings - if ('development' !== 'production' && prop.mode === propBindingModes.TWO_WAY && !settablePathRE.test(value)) { - prop.mode = propBindingModes.ONE_WAY; - warn('Cannot bind two-way prop with non-settable ' + 'parent path: ' + value, vm); - } - } - prop.parentPath = value; - - // warn required two-way - if ('development' !== 'production' && options.twoWay && prop.mode !== propBindingModes.TWO_WAY) { - warn('Prop "' + name + '" expects a two-way binding type.', vm); - } - } else if ((value = getAttr(el, attr)) !== null) { - // has literal binding! - prop.raw = value; - } else if ('development' !== 'production') { - // check possible camelCase prop usage - var lowerCaseName = path.toLowerCase(); - value = /[A-Z\-]/.test(name) && (el.getAttribute(lowerCaseName) || el.getAttribute(':' + lowerCaseName) || el.getAttribute('v-bind:' + lowerCaseName) || el.getAttribute(':' + lowerCaseName + '.once') || el.getAttribute('v-bind:' + lowerCaseName + '.once') || el.getAttribute(':' + lowerCaseName + '.sync') || el.getAttribute('v-bind:' + lowerCaseName + '.sync')); - if (value) { - warn('Possible usage error for prop `' + lowerCaseName + '` - ' + 'did you mean `' + attr + '`? HTML is case-insensitive, remember to use ' + 'kebab-case for props in templates.', vm); - } else if (options.required) { - // warn missing required - warn('Missing required prop: ' + name, vm); - } - } - // push prop - props.push(prop); - } - return makePropsLinkFn(props); - } - - /** - * Build a function that applies props to a vm. - * - * @param {Array} props - * @return {Function} propsLinkFn - */ - - function makePropsLinkFn(props) { - return function propsLinkFn(vm, scope) { - // store resolved props info - vm._props = {}; - var inlineProps = vm.$options.propsData; - var i = props.length; - var prop, path, options, value, raw; - while (i--) { - prop = props[i]; - raw = prop.raw; - path = prop.path; - options = prop.options; - vm._props[path] = prop; - if (inlineProps && hasOwn(inlineProps, path)) { - initProp(vm, prop, inlineProps[path]); - }if (raw === null) { - // initialize absent prop - initProp(vm, prop, undefined); - } else if (prop.dynamic) { - // dynamic prop - if (prop.mode === propBindingModes.ONE_TIME) { - // one time binding - value = (scope || vm._context || vm).$get(prop.parentPath); - initProp(vm, prop, value); - } else { - if (vm._context) { - // dynamic binding - vm._bindDir({ - name: 'prop', - def: propDef, - prop: prop - }, null, null, scope); // el, host, scope - } else { - // root instance - initProp(vm, prop, vm.$get(prop.parentPath)); - } - } - } else if (prop.optimizedLiteral) { - // optimized literal, cast it and just set once - var stripped = stripQuotes(raw); - value = stripped === raw ? toBoolean(toNumber(raw)) : stripped; - initProp(vm, prop, value); - } else { - // string literal, but we need to cater for - // Boolean props with no value, or with same - // literal value (e.g. disabled="disabled") - // see https://github.com/vuejs/vue-loader/issues/182 - value = options.type === Boolean && (raw === '' || raw === hyphenate(prop.name)) ? true : raw; - initProp(vm, prop, value); - } - } - }; - } - - /** - * Process a prop with a rawValue, applying necessary coersions, - * default values & assertions and call the given callback with - * processed value. - * - * @param {Vue} vm - * @param {Object} prop - * @param {*} rawValue - * @param {Function} fn - */ - - function processPropValue(vm, prop, rawValue, fn) { - var isSimple = prop.dynamic && isSimplePath(prop.parentPath); - var value = rawValue; - if (value === undefined) { - value = getPropDefaultValue(vm, prop); - } - value = coerceProp(prop, value, vm); - var coerced = value !== rawValue; - if (!assertProp(prop, value, vm)) { - value = undefined; - } - if (isSimple && !coerced) { - withoutConversion(function () { - fn(value); - }); - } else { - fn(value); - } - } - - /** - * Set a prop's initial value on a vm and its data object. - * - * @param {Vue} vm - * @param {Object} prop - * @param {*} value - */ - - function initProp(vm, prop, value) { - processPropValue(vm, prop, value, function (value) { - defineReactive(vm, prop.path, value); - }); - } - - /** - * Update a prop's value on a vm. - * - * @param {Vue} vm - * @param {Object} prop - * @param {*} value - */ - - function updateProp(vm, prop, value) { - processPropValue(vm, prop, value, function (value) { - vm[prop.path] = value; - }); - } - - /** - * Get the default value of a prop. - * - * @param {Vue} vm - * @param {Object} prop - * @return {*} - */ - - function getPropDefaultValue(vm, prop) { - // no default, return undefined - var options = prop.options; - if (!hasOwn(options, 'default')) { - // absent boolean value defaults to false - return options.type === Boolean ? false : undefined; - } - var def = options['default']; - // warn against non-factory defaults for Object & Array - if (isObject(def)) { - 'development' !== 'production' && warn('Invalid default value for prop "' + prop.name + '": ' + 'Props with type Object/Array must use a factory function ' + 'to return the default value.', vm); - } - // call factory function for non-Function types - return typeof def === 'function' && options.type !== Function ? def.call(vm) : def; - } - - /** - * Assert whether a prop is valid. - * - * @param {Object} prop - * @param {*} value - * @param {Vue} vm - */ - - function assertProp(prop, value, vm) { - if (!prop.options.required && ( // non-required - prop.raw === null || // abscent - value == null) // null or undefined - ) { - return true; - } - var options = prop.options; - var type = options.type; - var valid = !type; - var expectedTypes = []; - if (type) { - if (!isArray(type)) { - type = [type]; - } - for (var i = 0; i < type.length && !valid; i++) { - var assertedType = assertType(value, type[i]); - expectedTypes.push(assertedType.expectedType); - valid = assertedType.valid; - } - } - if (!valid) { - if ('development' !== 'production') { - warn('Invalid prop: type check failed for prop "' + prop.name + '".' + ' Expected ' + expectedTypes.map(formatType).join(', ') + ', got ' + formatValue(value) + '.', vm); - } - return false; - } - var validator = options.validator; - if (validator) { - if (!validator(value)) { - 'development' !== 'production' && warn('Invalid prop: custom validator check failed for prop "' + prop.name + '".', vm); - return false; - } - } - return true; - } - - /** - * Force parsing value with coerce option. - * - * @param {*} value - * @param {Object} options - * @return {*} - */ - - function coerceProp(prop, value, vm) { - var coerce = prop.options.coerce; - if (!coerce) { - return value; - } - if (typeof coerce === 'function') { - return coerce(value); - } else { - 'development' !== 'production' && warn('Invalid coerce for prop "' + prop.name + '": expected function, got ' + typeof coerce + '.', vm); - return value; - } - } - - /** - * Assert the type of a value - * - * @param {*} value - * @param {Function} type - * @return {Object} - */ - - function assertType(value, type) { - var valid; - var expectedType; - if (type === String) { - expectedType = 'string'; - valid = typeof value === expectedType; - } else if (type === Number) { - expectedType = 'number'; - valid = typeof value === expectedType; - } else if (type === Boolean) { - expectedType = 'boolean'; - valid = typeof value === expectedType; - } else if (type === Function) { - expectedType = 'function'; - valid = typeof value === expectedType; - } else if (type === Object) { - expectedType = 'object'; - valid = isPlainObject(value); - } else if (type === Array) { - expectedType = 'array'; - valid = isArray(value); - } else { - valid = value instanceof type; - } - return { - valid: valid, - expectedType: expectedType - }; - } - - /** - * Format type for output - * - * @param {String} type - * @return {String} - */ - - function formatType(type) { - return type ? type.charAt(0).toUpperCase() + type.slice(1) : 'custom type'; - } - - /** - * Format value - * - * @param {*} value - * @return {String} - */ - - function formatValue(val) { - return Object.prototype.toString.call(val).slice(8, -1); - } - - var bindingModes = config._propBindingModes; - - var propDef = { - - bind: function bind() { - var child = this.vm; - var parent = child._context; - // passed in from compiler directly - var prop = this.descriptor.prop; - var childKey = prop.path; - var parentKey = prop.parentPath; - var twoWay = prop.mode === bindingModes.TWO_WAY; - - var parentWatcher = this.parentWatcher = new Watcher(parent, parentKey, function (val) { - updateProp(child, prop, val); - }, { - twoWay: twoWay, - filters: prop.filters, - // important: props need to be observed on the - // v-for scope if present - scope: this._scope - }); - - // set the child initial value. - initProp(child, prop, parentWatcher.value); - - // setup two-way binding - if (twoWay) { - // important: defer the child watcher creation until - // the created hook (after data observation) - var self = this; - child.$once('pre-hook:created', function () { - self.childWatcher = new Watcher(child, childKey, function (val) { - parentWatcher.set(val); - }, { - // ensure sync upward before parent sync down. - // this is necessary in cases e.g. the child - // mutates a prop array, then replaces it. (#1683) - sync: true - }); - }); - } - }, - - unbind: function unbind() { - this.parentWatcher.teardown(); - if (this.childWatcher) { - this.childWatcher.teardown(); - } - } - }; - - var queue$1 = []; - var queued = false; - - /** - * Push a job into the queue. - * - * @param {Function} job - */ - - function pushJob(job) { - queue$1.push(job); - if (!queued) { - queued = true; - nextTick(flush); - } - } - - /** - * Flush the queue, and do one forced reflow before - * triggering transitions. - */ - - function flush() { - // Force layout - var f = document.documentElement.offsetHeight; - for (var i = 0; i < queue$1.length; i++) { - queue$1[i](); - } - queue$1 = []; - queued = false; - // dummy return, so js linters don't complain about - // unused variable f - return f; - } - - var TYPE_TRANSITION = 'transition'; - var TYPE_ANIMATION = 'animation'; - var transDurationProp = transitionProp + 'Duration'; - var animDurationProp = animationProp + 'Duration'; - - /** - * If a just-entered element is applied the - * leave class while its enter transition hasn't started yet, - * and the transitioned property has the same value for both - * enter/leave, then the leave transition will be skipped and - * the transitionend event never fires. This function ensures - * its callback to be called after a transition has started - * by waiting for double raf. - * - * It falls back to setTimeout on devices that support CSS - * transitions but not raf (e.g. Android 4.2 browser) - since - * these environments are usually slow, we are giving it a - * relatively large timeout. - */ - - var raf = inBrowser && window.requestAnimationFrame; - var waitForTransitionStart = raf - /* istanbul ignore next */ - ? function (fn) { - raf(function () { - raf(fn); - }); - } : function (fn) { - setTimeout(fn, 50); - }; - - /** - * A Transition object that encapsulates the state and logic - * of the transition. - * - * @param {Element} el - * @param {String} id - * @param {Object} hooks - * @param {Vue} vm - */ - function Transition(el, id, hooks, vm) { - this.id = id; - this.el = el; - this.enterClass = hooks && hooks.enterClass || id + '-enter'; - this.leaveClass = hooks && hooks.leaveClass || id + '-leave'; - this.hooks = hooks; - this.vm = vm; - // async state - this.pendingCssEvent = this.pendingCssCb = this.cancel = this.pendingJsCb = this.op = this.cb = null; - this.justEntered = false; - this.entered = this.left = false; - this.typeCache = {}; - // check css transition type - this.type = hooks && hooks.type; - /* istanbul ignore if */ - if ('development' !== 'production') { - if (this.type && this.type !== TYPE_TRANSITION && this.type !== TYPE_ANIMATION) { - warn('invalid CSS transition type for transition="' + this.id + '": ' + this.type, vm); - } - } - // bind - var self = this;['enterNextTick', 'enterDone', 'leaveNextTick', 'leaveDone'].forEach(function (m) { - self[m] = bind(self[m], self); - }); - } - - var p$1 = Transition.prototype; - - /** - * Start an entering transition. - * - * 1. enter transition triggered - * 2. call beforeEnter hook - * 3. add enter class - * 4. insert/show element - * 5. call enter hook (with possible explicit js callback) - * 6. reflow - * 7. based on transition type: - * - transition: - * remove class now, wait for transitionend, - * then done if there's no explicit js callback. - * - animation: - * wait for animationend, remove class, - * then done if there's no explicit js callback. - * - no css transition: - * done now if there's no explicit js callback. - * 8. wait for either done or js callback, then call - * afterEnter hook. - * - * @param {Function} op - insert/show the element - * @param {Function} [cb] - */ - - p$1.enter = function (op, cb) { - this.cancelPending(); - this.callHook('beforeEnter'); - this.cb = cb; - addClass(this.el, this.enterClass); - op(); - this.entered = false; - this.callHookWithCb('enter'); - if (this.entered) { - return; // user called done synchronously. - } - this.cancel = this.hooks && this.hooks.enterCancelled; - pushJob(this.enterNextTick); - }; - - /** - * The "nextTick" phase of an entering transition, which is - * to be pushed into a queue and executed after a reflow so - * that removing the class can trigger a CSS transition. - */ - - p$1.enterNextTick = function () { - var _this = this; - - // prevent transition skipping - this.justEntered = true; - waitForTransitionStart(function () { - _this.justEntered = false; - }); - var enterDone = this.enterDone; - var type = this.getCssTransitionType(this.enterClass); - if (!this.pendingJsCb) { - if (type === TYPE_TRANSITION) { - // trigger transition by removing enter class now - removeClass(this.el, this.enterClass); - this.setupCssCb(transitionEndEvent, enterDone); - } else if (type === TYPE_ANIMATION) { - this.setupCssCb(animationEndEvent, enterDone); - } else { - enterDone(); - } - } else if (type === TYPE_TRANSITION) { - removeClass(this.el, this.enterClass); - } - }; - - /** - * The "cleanup" phase of an entering transition. - */ - - p$1.enterDone = function () { - this.entered = true; - this.cancel = this.pendingJsCb = null; - removeClass(this.el, this.enterClass); - this.callHook('afterEnter'); - if (this.cb) this.cb(); - }; - - /** - * Start a leaving transition. - * - * 1. leave transition triggered. - * 2. call beforeLeave hook - * 3. add leave class (trigger css transition) - * 4. call leave hook (with possible explicit js callback) - * 5. reflow if no explicit js callback is provided - * 6. based on transition type: - * - transition or animation: - * wait for end event, remove class, then done if - * there's no explicit js callback. - * - no css transition: - * done if there's no explicit js callback. - * 7. wait for either done or js callback, then call - * afterLeave hook. - * - * @param {Function} op - remove/hide the element - * @param {Function} [cb] - */ - - p$1.leave = function (op, cb) { - this.cancelPending(); - this.callHook('beforeLeave'); - this.op = op; - this.cb = cb; - addClass(this.el, this.leaveClass); - this.left = false; - this.callHookWithCb('leave'); - if (this.left) { - return; // user called done synchronously. - } - this.cancel = this.hooks && this.hooks.leaveCancelled; - // only need to handle leaveDone if - // 1. the transition is already done (synchronously called - // by the user, which causes this.op set to null) - // 2. there's no explicit js callback - if (this.op && !this.pendingJsCb) { - // if a CSS transition leaves immediately after enter, - // the transitionend event never fires. therefore we - // detect such cases and end the leave immediately. - if (this.justEntered) { - this.leaveDone(); - } else { - pushJob(this.leaveNextTick); - } - } - }; - - /** - * The "nextTick" phase of a leaving transition. - */ - - p$1.leaveNextTick = function () { - var type = this.getCssTransitionType(this.leaveClass); - if (type) { - var event = type === TYPE_TRANSITION ? transitionEndEvent : animationEndEvent; - this.setupCssCb(event, this.leaveDone); - } else { - this.leaveDone(); - } - }; - - /** - * The "cleanup" phase of a leaving transition. - */ - - p$1.leaveDone = function () { - this.left = true; - this.cancel = this.pendingJsCb = null; - this.op(); - removeClass(this.el, this.leaveClass); - this.callHook('afterLeave'); - if (this.cb) this.cb(); - this.op = null; - }; - - /** - * Cancel any pending callbacks from a previously running - * but not finished transition. - */ - - p$1.cancelPending = function () { - this.op = this.cb = null; - var hasPending = false; - if (this.pendingCssCb) { - hasPending = true; - off(this.el, this.pendingCssEvent, this.pendingCssCb); - this.pendingCssEvent = this.pendingCssCb = null; - } - if (this.pendingJsCb) { - hasPending = true; - this.pendingJsCb.cancel(); - this.pendingJsCb = null; - } - if (hasPending) { - removeClass(this.el, this.enterClass); - removeClass(this.el, this.leaveClass); - } - if (this.cancel) { - this.cancel.call(this.vm, this.el); - this.cancel = null; - } - }; - - /** - * Call a user-provided synchronous hook function. - * - * @param {String} type - */ - - p$1.callHook = function (type) { - if (this.hooks && this.hooks[type]) { - this.hooks[type].call(this.vm, this.el); - } - }; - - /** - * Call a user-provided, potentially-async hook function. - * We check for the length of arguments to see if the hook - * expects a `done` callback. If true, the transition's end - * will be determined by when the user calls that callback; - * otherwise, the end is determined by the CSS transition or - * animation. - * - * @param {String} type - */ - - p$1.callHookWithCb = function (type) { - var hook = this.hooks && this.hooks[type]; - if (hook) { - if (hook.length > 1) { - this.pendingJsCb = cancellable(this[type + 'Done']); - } - hook.call(this.vm, this.el, this.pendingJsCb); - } - }; - - /** - * Get an element's transition type based on the - * calculated styles. - * - * @param {String} className - * @return {Number} - */ - - p$1.getCssTransitionType = function (className) { - /* istanbul ignore if */ - if (!transitionEndEvent || - // skip CSS transitions if page is not visible - - // this solves the issue of transitionend events not - // firing until the page is visible again. - // pageVisibility API is supported in IE10+, same as - // CSS transitions. - document.hidden || - // explicit js-only transition - this.hooks && this.hooks.css === false || - // element is hidden - isHidden(this.el)) { - return; - } - var type = this.type || this.typeCache[className]; - if (type) return type; - var inlineStyles = this.el.style; - var computedStyles = window.getComputedStyle(this.el); - var transDuration = inlineStyles[transDurationProp] || computedStyles[transDurationProp]; - if (transDuration && transDuration !== '0s') { - type = TYPE_TRANSITION; - } else { - var animDuration = inlineStyles[animDurationProp] || computedStyles[animDurationProp]; - if (animDuration && animDuration !== '0s') { - type = TYPE_ANIMATION; - } - } - if (type) { - this.typeCache[className] = type; - } - return type; - }; - - /** - * Setup a CSS transitionend/animationend callback. - * - * @param {String} event - * @param {Function} cb - */ - - p$1.setupCssCb = function (event, cb) { - this.pendingCssEvent = event; - var self = this; - var el = this.el; - var onEnd = this.pendingCssCb = function (e) { - if (e.target === el) { - off(el, event, onEnd); - self.pendingCssEvent = self.pendingCssCb = null; - if (!self.pendingJsCb && cb) { - cb(); - } - } - }; - on(el, event, onEnd); - }; - - /** - * Check if an element is hidden - in that case we can just - * skip the transition alltogether. - * - * @param {Element} el - * @return {Boolean} - */ - - function isHidden(el) { - if (/svg$/.test(el.namespaceURI)) { - // SVG elements do not have offset(Width|Height) - // so we need to check the client rect - var rect = el.getBoundingClientRect(); - return !(rect.width || rect.height); - } else { - return !(el.offsetWidth || el.offsetHeight || el.getClientRects().length); - } - } - - var transition$1 = { - - priority: TRANSITION, - - update: function update(id, oldId) { - var el = this.el; - // resolve on owner vm - var hooks = resolveAsset(this.vm.$options, 'transitions', id); - id = id || 'v'; - oldId = oldId || 'v'; - el.__v_trans = new Transition(el, id, hooks, this.vm); - removeClass(el, oldId + '-transition'); - addClass(el, id + '-transition'); - } - }; - - var internalDirectives = { - style: style, - 'class': vClass, - component: component, - prop: propDef, - transition: transition$1 - }; - - // special binding prefixes - var bindRE = /^v-bind:|^:/; - var onRE = /^v-on:|^@/; - var dirAttrRE = /^v-([^:]+)(?:$|:(.*)$)/; - var modifierRE = /\.[^\.]+/g; - var transitionRE = /^(v-bind:|:)?transition$/; - - // default directive priority - var DEFAULT_PRIORITY = 1000; - var DEFAULT_TERMINAL_PRIORITY = 2000; - - /** - * Compile a template and return a reusable composite link - * function, which recursively contains more link functions - * inside. This top level compile function would normally - * be called on instance root nodes, but can also be used - * for partial compilation if the partial argument is true. - * - * The returned composite link function, when called, will - * return an unlink function that tearsdown all directives - * created during the linking phase. - * - * @param {Element|DocumentFragment} el - * @param {Object} options - * @param {Boolean} partial - * @return {Function} - */ - - function compile(el, options, partial) { - // link function for the node itself. - var nodeLinkFn = partial || !options._asComponent ? compileNode(el, options) : null; - // link function for the childNodes - var childLinkFn = !(nodeLinkFn && nodeLinkFn.terminal) && !isScript(el) && el.hasChildNodes() ? compileNodeList(el.childNodes, options) : null; - - /** - * A composite linker function to be called on a already - * compiled piece of DOM, which instantiates all directive - * instances. - * - * @param {Vue} vm - * @param {Element|DocumentFragment} el - * @param {Vue} [host] - host vm of transcluded content - * @param {Object} [scope] - v-for scope - * @param {Fragment} [frag] - link context fragment - * @return {Function|undefined} - */ - - return function compositeLinkFn(vm, el, host, scope, frag) { - // cache childNodes before linking parent, fix #657 - var childNodes = toArray(el.childNodes); - // link - var dirs = linkAndCapture(function compositeLinkCapturer() { - if (nodeLinkFn) nodeLinkFn(vm, el, host, scope, frag); - if (childLinkFn) childLinkFn(vm, childNodes, host, scope, frag); - }, vm); - return makeUnlinkFn(vm, dirs); - }; - } - - /** - * Apply a linker to a vm/element pair and capture the - * directives created during the process. - * - * @param {Function} linker - * @param {Vue} vm - */ - - function linkAndCapture(linker, vm) { - /* istanbul ignore if */ - if ('development' === 'production') {} - var originalDirCount = vm._directives.length; - linker(); - var dirs = vm._directives.slice(originalDirCount); - dirs.sort(directiveComparator); - for (var i = 0, l = dirs.length; i < l; i++) { - dirs[i]._bind(); - } - return dirs; - } - - /** - * Directive priority sort comparator - * - * @param {Object} a - * @param {Object} b - */ - - function directiveComparator(a, b) { - a = a.descriptor.def.priority || DEFAULT_PRIORITY; - b = b.descriptor.def.priority || DEFAULT_PRIORITY; - return a > b ? -1 : a === b ? 0 : 1; - } - - /** - * Linker functions return an unlink function that - * tearsdown all directives instances generated during - * the process. - * - * We create unlink functions with only the necessary - * information to avoid retaining additional closures. - * - * @param {Vue} vm - * @param {Array} dirs - * @param {Vue} [context] - * @param {Array} [contextDirs] - * @return {Function} - */ - - function makeUnlinkFn(vm, dirs, context, contextDirs) { - function unlink(destroying) { - teardownDirs(vm, dirs, destroying); - if (context && contextDirs) { - teardownDirs(context, contextDirs); - } - } - // expose linked directives - unlink.dirs = dirs; - return unlink; - } - - /** - * Teardown partial linked directives. - * - * @param {Vue} vm - * @param {Array} dirs - * @param {Boolean} destroying - */ - - function teardownDirs(vm, dirs, destroying) { - var i = dirs.length; - while (i--) { - dirs[i]._teardown(); - if ('development' !== 'production' && !destroying) { - vm._directives.$remove(dirs[i]); - } - } - } - - /** - * Compile link props on an instance. - * - * @param {Vue} vm - * @param {Element} el - * @param {Object} props - * @param {Object} [scope] - * @return {Function} - */ - - function compileAndLinkProps(vm, el, props, scope) { - var propsLinkFn = compileProps(el, props, vm); - var propDirs = linkAndCapture(function () { - propsLinkFn(vm, scope); - }, vm); - return makeUnlinkFn(vm, propDirs); - } - - /** - * Compile the root element of an instance. - * - * 1. attrs on context container (context scope) - * 2. attrs on the component template root node, if - * replace:true (child scope) - * - * If this is a fragment instance, we only need to compile 1. - * - * @param {Element} el - * @param {Object} options - * @param {Object} contextOptions - * @return {Function} - */ - - function compileRoot(el, options, contextOptions) { - var containerAttrs = options._containerAttrs; - var replacerAttrs = options._replacerAttrs; - var contextLinkFn, replacerLinkFn; - - // only need to compile other attributes for - // non-fragment instances - if (el.nodeType !== 11) { - // for components, container and replacer need to be - // compiled separately and linked in different scopes. - if (options._asComponent) { - // 2. container attributes - if (containerAttrs && contextOptions) { - contextLinkFn = compileDirectives(containerAttrs, contextOptions); - } - if (replacerAttrs) { - // 3. replacer attributes - replacerLinkFn = compileDirectives(replacerAttrs, options); - } - } else { - // non-component, just compile as a normal element. - replacerLinkFn = compileDirectives(el.attributes, options); - } - } else if ('development' !== 'production' && containerAttrs) { - // warn container directives for fragment instances - var names = containerAttrs.filter(function (attr) { - // allow vue-loader/vueify scoped css attributes - return attr.name.indexOf('_v-') < 0 && - // allow event listeners - !onRE.test(attr.name) && - // allow slots - attr.name !== 'slot'; - }).map(function (attr) { - return '"' + attr.name + '"'; - }); - if (names.length) { - var plural = names.length > 1; - warn('Attribute' + (plural ? 's ' : ' ') + names.join(', ') + (plural ? ' are' : ' is') + ' ignored on component ' + '<' + options.el.tagName.toLowerCase() + '> because ' + 'the component is a fragment instance: ' + 'http://vuejs.org/guide/components.html#Fragment-Instance'); - } - } - - options._containerAttrs = options._replacerAttrs = null; - return function rootLinkFn(vm, el, scope) { - // link context scope dirs - var context = vm._context; - var contextDirs; - if (context && contextLinkFn) { - contextDirs = linkAndCapture(function () { - contextLinkFn(context, el, null, scope); - }, context); - } - - // link self - var selfDirs = linkAndCapture(function () { - if (replacerLinkFn) replacerLinkFn(vm, el); - }, vm); - - // return the unlink function that tearsdown context - // container directives. - return makeUnlinkFn(vm, selfDirs, context, contextDirs); - }; - } - - /** - * Compile a node and return a nodeLinkFn based on the - * node type. - * - * @param {Node} node - * @param {Object} options - * @return {Function|null} - */ - - function compileNode(node, options) { - var type = node.nodeType; - if (type === 1 && !isScript(node)) { - return compileElement(node, options); - } else if (type === 3 && node.data.trim()) { - return compileTextNode(node, options); - } else { - return null; - } - } - - /** - * Compile an element and return a nodeLinkFn. - * - * @param {Element} el - * @param {Object} options - * @return {Function|null} - */ - - function compileElement(el, options) { - // preprocess textareas. - // textarea treats its text content as the initial value. - // just bind it as an attr directive for value. - if (el.tagName === 'TEXTAREA') { - var tokens = parseText(el.value); - if (tokens) { - el.setAttribute(':value', tokensToExp(tokens)); - el.value = ''; - } - } - var linkFn; - var hasAttrs = el.hasAttributes(); - var attrs = hasAttrs && toArray(el.attributes); - // check terminal directives (for & if) - if (hasAttrs) { - linkFn = checkTerminalDirectives(el, attrs, options); - } - // check element directives - if (!linkFn) { - linkFn = checkElementDirectives(el, options); - } - // check component - if (!linkFn) { - linkFn = checkComponent(el, options); - } - // normal directives - if (!linkFn && hasAttrs) { - linkFn = compileDirectives(attrs, options); - } - return linkFn; - } - - /** - * Compile a textNode and return a nodeLinkFn. - * - * @param {TextNode} node - * @param {Object} options - * @return {Function|null} textNodeLinkFn - */ - - function compileTextNode(node, options) { - // skip marked text nodes - if (node._skip) { - return removeText; - } - - var tokens = parseText(node.wholeText); - if (!tokens) { - return null; - } - - // mark adjacent text nodes as skipped, - // because we are using node.wholeText to compile - // all adjacent text nodes together. This fixes - // issues in IE where sometimes it splits up a single - // text node into multiple ones. - var next = node.nextSibling; - while (next && next.nodeType === 3) { - next._skip = true; - next = next.nextSibling; - } - - var frag = document.createDocumentFragment(); - var el, token; - for (var i = 0, l = tokens.length; i < l; i++) { - token = tokens[i]; - el = token.tag ? processTextToken(token, options) : document.createTextNode(token.value); - frag.appendChild(el); - } - return makeTextNodeLinkFn(tokens, frag, options); - } - - /** - * Linker for an skipped text node. - * - * @param {Vue} vm - * @param {Text} node - */ - - function removeText(vm, node) { - remove(node); - } - - /** - * Process a single text token. - * - * @param {Object} token - * @param {Object} options - * @return {Node} - */ - - function processTextToken(token, options) { - var el; - if (token.oneTime) { - el = document.createTextNode(token.value); - } else { - if (token.html) { - el = document.createComment('v-html'); - setTokenType('html'); - } else { - // IE will clean up empty textNodes during - // frag.cloneNode(true), so we have to give it - // something here... - el = document.createTextNode(' '); - setTokenType('text'); - } - } - function setTokenType(type) { - if (token.descriptor) return; - var parsed = parseDirective(token.value); - token.descriptor = { - name: type, - def: directives[type], - expression: parsed.expression, - filters: parsed.filters - }; - } - return el; - } - - /** - * Build a function that processes a textNode. - * - * @param {Array<Object>} tokens - * @param {DocumentFragment} frag - */ - - function makeTextNodeLinkFn(tokens, frag) { - return function textNodeLinkFn(vm, el, host, scope) { - var fragClone = frag.cloneNode(true); - var childNodes = toArray(fragClone.childNodes); - var token, value, node; - for (var i = 0, l = tokens.length; i < l; i++) { - token = tokens[i]; - value = token.value; - if (token.tag) { - node = childNodes[i]; - if (token.oneTime) { - value = (scope || vm).$eval(value); - if (token.html) { - replace(node, parseTemplate(value, true)); - } else { - node.data = _toString(value); - } - } else { - vm._bindDir(token.descriptor, node, host, scope); - } - } - } - replace(el, fragClone); - }; - } - - /** - * Compile a node list and return a childLinkFn. - * - * @param {NodeList} nodeList - * @param {Object} options - * @return {Function|undefined} - */ - - function compileNodeList(nodeList, options) { - var linkFns = []; - var nodeLinkFn, childLinkFn, node; - for (var i = 0, l = nodeList.length; i < l; i++) { - node = nodeList[i]; - nodeLinkFn = compileNode(node, options); - childLinkFn = !(nodeLinkFn && nodeLinkFn.terminal) && node.tagName !== 'SCRIPT' && node.hasChildNodes() ? compileNodeList(node.childNodes, options) : null; - linkFns.push(nodeLinkFn, childLinkFn); - } - return linkFns.length ? makeChildLinkFn(linkFns) : null; - } - - /** - * Make a child link function for a node's childNodes. - * - * @param {Array<Function>} linkFns - * @return {Function} childLinkFn - */ - - function makeChildLinkFn(linkFns) { - return function childLinkFn(vm, nodes, host, scope, frag) { - var node, nodeLinkFn, childrenLinkFn; - for (var i = 0, n = 0, l = linkFns.length; i < l; n++) { - node = nodes[n]; - nodeLinkFn = linkFns[i++]; - childrenLinkFn = linkFns[i++]; - // cache childNodes before linking parent, fix #657 - var childNodes = toArray(node.childNodes); - if (nodeLinkFn) { - nodeLinkFn(vm, node, host, scope, frag); - } - if (childrenLinkFn) { - childrenLinkFn(vm, childNodes, host, scope, frag); - } - } - }; - } - - /** - * Check for element directives (custom elements that should - * be resovled as terminal directives). - * - * @param {Element} el - * @param {Object} options - */ - - function checkElementDirectives(el, options) { - var tag = el.tagName.toLowerCase(); - if (commonTagRE.test(tag)) { - return; - } - var def = resolveAsset(options, 'elementDirectives', tag); - if (def) { - return makeTerminalNodeLinkFn(el, tag, '', options, def); - } - } - - /** - * Check if an element is a component. If yes, return - * a component link function. - * - * @param {Element} el - * @param {Object} options - * @return {Function|undefined} - */ - - function checkComponent(el, options) { - var component = checkComponentAttr(el, options); - if (component) { - var ref = findRef(el); - var descriptor = { - name: 'component', - ref: ref, - expression: component.id, - def: internalDirectives.component, - modifiers: { - literal: !component.dynamic - } - }; - var componentLinkFn = function componentLinkFn(vm, el, host, scope, frag) { - if (ref) { - defineReactive((scope || vm).$refs, ref, null); - } - vm._bindDir(descriptor, el, host, scope, frag); - }; - componentLinkFn.terminal = true; - return componentLinkFn; - } - } - - /** - * Check an element for terminal directives in fixed order. - * If it finds one, return a terminal link function. - * - * @param {Element} el - * @param {Array} attrs - * @param {Object} options - * @return {Function} terminalLinkFn - */ - - function checkTerminalDirectives(el, attrs, options) { - // skip v-pre - if (getAttr(el, 'v-pre') !== null) { - return skip; - } - // skip v-else block, but only if following v-if - if (el.hasAttribute('v-else')) { - var prev = el.previousElementSibling; - if (prev && prev.hasAttribute('v-if')) { - return skip; - } - } - - var attr, name, value, modifiers, matched, dirName, rawName, arg, def, termDef; - for (var i = 0, j = attrs.length; i < j; i++) { - attr = attrs[i]; - name = attr.name.replace(modifierRE, ''); - if (matched = name.match(dirAttrRE)) { - def = resolveAsset(options, 'directives', matched[1]); - if (def && def.terminal) { - if (!termDef || (def.priority || DEFAULT_TERMINAL_PRIORITY) > termDef.priority) { - termDef = def; - rawName = attr.name; - modifiers = parseModifiers(attr.name); - value = attr.value; - dirName = matched[1]; - arg = matched[2]; - } - } - } - } - - if (termDef) { - return makeTerminalNodeLinkFn(el, dirName, value, options, termDef, rawName, arg, modifiers); - } - } - - function skip() {} - skip.terminal = true; - - /** - * Build a node link function for a terminal directive. - * A terminal link function terminates the current - * compilation recursion and handles compilation of the - * subtree in the directive. - * - * @param {Element} el - * @param {String} dirName - * @param {String} value - * @param {Object} options - * @param {Object} def - * @param {String} [rawName] - * @param {String} [arg] - * @param {Object} [modifiers] - * @return {Function} terminalLinkFn - */ - - function makeTerminalNodeLinkFn(el, dirName, value, options, def, rawName, arg, modifiers) { - var parsed = parseDirective(value); - var descriptor = { - name: dirName, - arg: arg, - expression: parsed.expression, - filters: parsed.filters, - raw: value, - attr: rawName, - modifiers: modifiers, - def: def - }; - // check ref for v-for and router-view - if (dirName === 'for' || dirName === 'router-view') { - descriptor.ref = findRef(el); - } - var fn = function terminalNodeLinkFn(vm, el, host, scope, frag) { - if (descriptor.ref) { - defineReactive((scope || vm).$refs, descriptor.ref, null); - } - vm._bindDir(descriptor, el, host, scope, frag); - }; - fn.terminal = true; - return fn; - } - - /** - * Compile the directives on an element and return a linker. - * - * @param {Array|NamedNodeMap} attrs - * @param {Object} options - * @return {Function} - */ - - function compileDirectives(attrs, options) { - var i = attrs.length; - var dirs = []; - var attr, name, value, rawName, rawValue, dirName, arg, modifiers, dirDef, tokens, matched; - while (i--) { - attr = attrs[i]; - name = rawName = attr.name; - value = rawValue = attr.value; - tokens = parseText(value); - // reset arg - arg = null; - // check modifiers - modifiers = parseModifiers(name); - name = name.replace(modifierRE, ''); - - // attribute interpolations - if (tokens) { - value = tokensToExp(tokens); - arg = name; - pushDir('bind', directives.bind, tokens); - // warn against mixing mustaches with v-bind - if ('development' !== 'production') { - if (name === 'class' && Array.prototype.some.call(attrs, function (attr) { - return attr.name === ':class' || attr.name === 'v-bind:class'; - })) { - warn('class="' + rawValue + '": Do not mix mustache interpolation ' + 'and v-bind for "class" on the same element. Use one or the other.', options); - } - } - } else - - // special attribute: transition - if (transitionRE.test(name)) { - modifiers.literal = !bindRE.test(name); - pushDir('transition', internalDirectives.transition); - } else - - // event handlers - if (onRE.test(name)) { - arg = name.replace(onRE, ''); - pushDir('on', directives.on); - } else - - // attribute bindings - if (bindRE.test(name)) { - dirName = name.replace(bindRE, ''); - if (dirName === 'style' || dirName === 'class') { - pushDir(dirName, internalDirectives[dirName]); - } else { - arg = dirName; - pushDir('bind', directives.bind); - } - } else - - // normal directives - if (matched = name.match(dirAttrRE)) { - dirName = matched[1]; - arg = matched[2]; - - // skip v-else (when used with v-show) - if (dirName === 'else') { - continue; - } - - dirDef = resolveAsset(options, 'directives', dirName, true); - if (dirDef) { - pushDir(dirName, dirDef); - } - } - } - - /** - * Push a directive. - * - * @param {String} dirName - * @param {Object|Function} def - * @param {Array} [interpTokens] - */ - - function pushDir(dirName, def, interpTokens) { - var hasOneTimeToken = interpTokens && hasOneTime(interpTokens); - var parsed = !hasOneTimeToken && parseDirective(value); - dirs.push({ - name: dirName, - attr: rawName, - raw: rawValue, - def: def, - arg: arg, - modifiers: modifiers, - // conversion from interpolation strings with one-time token - // to expression is differed until directive bind time so that we - // have access to the actual vm context for one-time bindings. - expression: parsed && parsed.expression, - filters: parsed && parsed.filters, - interp: interpTokens, - hasOneTime: hasOneTimeToken - }); - } - - if (dirs.length) { - return makeNodeLinkFn(dirs); - } - } - - /** - * Parse modifiers from directive attribute name. - * - * @param {String} name - * @return {Object} - */ - - function parseModifiers(name) { - var res = Object.create(null); - var match = name.match(modifierRE); - if (match) { - var i = match.length; - while (i--) { - res[match[i].slice(1)] = true; - } - } - return res; - } - - /** - * Build a link function for all directives on a single node. - * - * @param {Array} directives - * @return {Function} directivesLinkFn - */ - - function makeNodeLinkFn(directives) { - return function nodeLinkFn(vm, el, host, scope, frag) { - // reverse apply because it's sorted low to high - var i = directives.length; - while (i--) { - vm._bindDir(directives[i], el, host, scope, frag); - } - }; - } - - /** - * Check if an interpolation string contains one-time tokens. - * - * @param {Array} tokens - * @return {Boolean} - */ - - function hasOneTime(tokens) { - var i = tokens.length; - while (i--) { - if (tokens[i].oneTime) return true; - } - } - - function isScript(el) { - return el.tagName === 'SCRIPT' && (!el.hasAttribute('type') || el.getAttribute('type') === 'text/javascript'); - } - - var specialCharRE = /[^\w\-:\.]/; - - /** - * Process an element or a DocumentFragment based on a - * instance option object. This allows us to transclude - * a template node/fragment before the instance is created, - * so the processed fragment can then be cloned and reused - * in v-for. - * - * @param {Element} el - * @param {Object} options - * @return {Element|DocumentFragment} - */ - - function transclude(el, options) { - // extract container attributes to pass them down - // to compiler, because they need to be compiled in - // parent scope. we are mutating the options object here - // assuming the same object will be used for compile - // right after this. - if (options) { - options._containerAttrs = extractAttrs(el); - } - // for template tags, what we want is its content as - // a documentFragment (for fragment instances) - if (isTemplate(el)) { - el = parseTemplate(el); - } - if (options) { - if (options._asComponent && !options.template) { - options.template = '<slot></slot>'; - } - if (options.template) { - options._content = extractContent(el); - el = transcludeTemplate(el, options); - } - } - if (isFragment(el)) { - // anchors for fragment instance - // passing in `persist: true` to avoid them being - // discarded by IE during template cloning - prepend(createAnchor('v-start', true), el); - el.appendChild(createAnchor('v-end', true)); - } - return el; - } - - /** - * Process the template option. - * If the replace option is true this will swap the $el. - * - * @param {Element} el - * @param {Object} options - * @return {Element|DocumentFragment} - */ - - function transcludeTemplate(el, options) { - var template = options.template; - var frag = parseTemplate(template, true); - if (frag) { - var replacer = frag.firstChild; - var tag = replacer.tagName && replacer.tagName.toLowerCase(); - if (options.replace) { - /* istanbul ignore if */ - if (el === document.body) { - 'development' !== 'production' && warn('You are mounting an instance with a template to ' + '<body>. This will replace <body> entirely. You ' + 'should probably use `replace: false` here.'); - } - // there are many cases where the instance must - // become a fragment instance: basically anything that - // can create more than 1 root nodes. - if ( - // multi-children template - frag.childNodes.length > 1 || - // non-element template - replacer.nodeType !== 1 || - // single nested component - tag === 'component' || resolveAsset(options, 'components', tag) || hasBindAttr(replacer, 'is') || - // element directive - resolveAsset(options, 'elementDirectives', tag) || - // for block - replacer.hasAttribute('v-for') || - // if block - replacer.hasAttribute('v-if')) { - return frag; - } else { - options._replacerAttrs = extractAttrs(replacer); - mergeAttrs(el, replacer); - return replacer; - } - } else { - el.appendChild(frag); - return el; - } - } else { - 'development' !== 'production' && warn('Invalid template option: ' + template); - } - } - - /** - * Helper to extract a component container's attributes - * into a plain object array. - * - * @param {Element} el - * @return {Array} - */ - - function extractAttrs(el) { - if (el.nodeType === 1 && el.hasAttributes()) { - return toArray(el.attributes); - } - } - - /** - * Merge the attributes of two elements, and make sure - * the class names are merged properly. - * - * @param {Element} from - * @param {Element} to - */ - - function mergeAttrs(from, to) { - var attrs = from.attributes; - var i = attrs.length; - var name, value; - while (i--) { - name = attrs[i].name; - value = attrs[i].value; - if (!to.hasAttribute(name) && !specialCharRE.test(name)) { - to.setAttribute(name, value); - } else if (name === 'class' && !parseText(value) && (value = value.trim())) { - value.split(/\s+/).forEach(function (cls) { - addClass(to, cls); - }); - } - } - } - - /** - * Scan and determine slot content distribution. - * We do this during transclusion instead at compile time so that - * the distribution is decoupled from the compilation order of - * the slots. - * - * @param {Element|DocumentFragment} template - * @param {Element} content - * @param {Vue} vm - */ - - function resolveSlots(vm, content) { - if (!content) { - return; - } - var contents = vm._slotContents = Object.create(null); - var el, name; - for (var i = 0, l = content.children.length; i < l; i++) { - el = content.children[i]; - /* eslint-disable no-cond-assign */ - if (name = el.getAttribute('slot')) { - (contents[name] || (contents[name] = [])).push(el); - } - /* eslint-enable no-cond-assign */ - if ('development' !== 'production' && getBindAttr(el, 'slot')) { - warn('The "slot" attribute must be static.', vm.$parent); - } - } - for (name in contents) { - contents[name] = extractFragment(contents[name], content); - } - if (content.hasChildNodes()) { - var nodes = content.childNodes; - if (nodes.length === 1 && nodes[0].nodeType === 3 && !nodes[0].data.trim()) { - return; - } - contents['default'] = extractFragment(content.childNodes, content); - } - } - - /** - * Extract qualified content nodes from a node list. - * - * @param {NodeList} nodes - * @return {DocumentFragment} - */ - - function extractFragment(nodes, parent) { - var frag = document.createDocumentFragment(); - nodes = toArray(nodes); - for (var i = 0, l = nodes.length; i < l; i++) { - var node = nodes[i]; - if (isTemplate(node) && !node.hasAttribute('v-if') && !node.hasAttribute('v-for')) { - parent.removeChild(node); - node = parseTemplate(node, true); - } - frag.appendChild(node); - } - return frag; - } - - - - var compiler = Object.freeze({ - compile: compile, - compileAndLinkProps: compileAndLinkProps, - compileRoot: compileRoot, - transclude: transclude, - resolveSlots: resolveSlots - }); - - function stateMixin (Vue) { - /** - * Accessor for `$data` property, since setting $data - * requires observing the new object and updating - * proxied properties. - */ - - Object.defineProperty(Vue.prototype, '$data', { - get: function get() { - return this._data; - }, - set: function set(newData) { - if (newData !== this._data) { - this._setData(newData); - } - } - }); - - /** - * Setup the scope of an instance, which contains: - * - observed data - * - computed properties - * - user methods - * - meta properties - */ - - Vue.prototype._initState = function () { - this._initProps(); - this._initMeta(); - this._initMethods(); - this._initData(); - this._initComputed(); - }; - - /** - * Initialize props. - */ - - Vue.prototype._initProps = function () { - var options = this.$options; - var el = options.el; - var props = options.props; - if (props && !el) { - 'development' !== 'production' && warn('Props will not be compiled if no `el` option is ' + 'provided at instantiation.', this); - } - // make sure to convert string selectors into element now - el = options.el = query(el); - this._propsUnlinkFn = el && el.nodeType === 1 && props - // props must be linked in proper scope if inside v-for - ? compileAndLinkProps(this, el, props, this._scope) : null; - }; - - /** - * Initialize the data. - */ - - Vue.prototype._initData = function () { - var dataFn = this.$options.data; - var data = this._data = dataFn ? dataFn() : {}; - if (!isPlainObject(data)) { - data = {}; - 'development' !== 'production' && warn('data functions should return an object.', this); - } - var props = this._props; - // proxy data on instance - var keys = Object.keys(data); - var i, key; - i = keys.length; - while (i--) { - key = keys[i]; - // there are two scenarios where we can proxy a data key: - // 1. it's not already defined as a prop - // 2. it's provided via a instantiation option AND there are no - // template prop present - if (!props || !hasOwn(props, key)) { - this._proxy(key); - } else if ('development' !== 'production') { - warn('Data field "' + key + '" is already defined ' + 'as a prop. To provide default value for a prop, use the "default" ' + 'prop option; if you want to pass prop values to an instantiation ' + 'call, use the "propsData" option.', this); - } - } - // observe data - observe(data, this); - }; - - /** - * Swap the instance's $data. Called in $data's setter. - * - * @param {Object} newData - */ - - Vue.prototype._setData = function (newData) { - newData = newData || {}; - var oldData = this._data; - this._data = newData; - var keys, key, i; - // unproxy keys not present in new data - keys = Object.keys(oldData); - i = keys.length; - while (i--) { - key = keys[i]; - if (!(key in newData)) { - this._unproxy(key); - } - } - // proxy keys not already proxied, - // and trigger change for changed values - keys = Object.keys(newData); - i = keys.length; - while (i--) { - key = keys[i]; - if (!hasOwn(this, key)) { - // new property - this._proxy(key); - } - } - oldData.__ob__.removeVm(this); - observe(newData, this); - this._digest(); - }; - - /** - * Proxy a property, so that - * vm.prop === vm._data.prop - * - * @param {String} key - */ - - Vue.prototype._proxy = function (key) { - if (!isReserved(key)) { - // need to store ref to self here - // because these getter/setters might - // be called by child scopes via - // prototype inheritance. - var self = this; - Object.defineProperty(self, key, { - configurable: true, - enumerable: true, - get: function proxyGetter() { - return self._data[key]; - }, - set: function proxySetter(val) { - self._data[key] = val; - } - }); - } - }; - - /** - * Unproxy a property. - * - * @param {String} key - */ - - Vue.prototype._unproxy = function (key) { - if (!isReserved(key)) { - delete this[key]; - } - }; - - /** - * Force update on every watcher in scope. - */ - - Vue.prototype._digest = function () { - for (var i = 0, l = this._watchers.length; i < l; i++) { - this._watchers[i].update(true); // shallow updates - } - }; - - /** - * Setup computed properties. They are essentially - * special getter/setters - */ - - function noop() {} - Vue.prototype._initComputed = function () { - var computed = this.$options.computed; - if (computed) { - for (var key in computed) { - var userDef = computed[key]; - var def = { - enumerable: true, - configurable: true - }; - if (typeof userDef === 'function') { - def.get = makeComputedGetter(userDef, this); - def.set = noop; - } else { - def.get = userDef.get ? userDef.cache !== false ? makeComputedGetter(userDef.get, this) : bind(userDef.get, this) : noop; - def.set = userDef.set ? bind(userDef.set, this) : noop; - } - Object.defineProperty(this, key, def); - } - } - }; - - function makeComputedGetter(getter, owner) { - var watcher = new Watcher(owner, getter, null, { - lazy: true - }); - return function computedGetter() { - if (watcher.dirty) { - watcher.evaluate(); - } - if (Dep.target) { - watcher.depend(); - } - return watcher.value; - }; - } - - /** - * Setup instance methods. Methods must be bound to the - * instance since they might be passed down as a prop to - * child components. - */ - - Vue.prototype._initMethods = function () { - var methods = this.$options.methods; - if (methods) { - for (var key in methods) { - this[key] = bind(methods[key], this); - } - } - }; - - /** - * Initialize meta information like $index, $key & $value. - */ - - Vue.prototype._initMeta = function () { - var metas = this.$options._meta; - if (metas) { - for (var key in metas) { - defineReactive(this, key, metas[key]); - } - } - }; - } - - var eventRE = /^v-on:|^@/; - - function eventsMixin (Vue) { - /** - * Setup the instance's option events & watchers. - * If the value is a string, we pull it from the - * instance's methods by name. - */ - - Vue.prototype._initEvents = function () { - var options = this.$options; - if (options._asComponent) { - registerComponentEvents(this, options.el); - } - registerCallbacks(this, '$on', options.events); - registerCallbacks(this, '$watch', options.watch); - }; - - /** - * Register v-on events on a child component - * - * @param {Vue} vm - * @param {Element} el - */ - - function registerComponentEvents(vm, el) { - var attrs = el.attributes; - var name, value, handler; - for (var i = 0, l = attrs.length; i < l; i++) { - name = attrs[i].name; - if (eventRE.test(name)) { - name = name.replace(eventRE, ''); - // force the expression into a statement so that - // it always dynamically resolves the method to call (#2670) - // kinda ugly hack, but does the job. - value = attrs[i].value; - if (isSimplePath(value)) { - value += '.apply(this, $arguments)'; - } - handler = (vm._scope || vm._context).$eval(value, true); - handler._fromParent = true; - vm.$on(name.replace(eventRE), handler); - } - } - } - - /** - * Register callbacks for option events and watchers. - * - * @param {Vue} vm - * @param {String} action - * @param {Object} hash - */ - - function registerCallbacks(vm, action, hash) { - if (!hash) return; - var handlers, key, i, j; - for (key in hash) { - handlers = hash[key]; - if (isArray(handlers)) { - for (i = 0, j = handlers.length; i < j; i++) { - register(vm, action, key, handlers[i]); - } - } else { - register(vm, action, key, handlers); - } - } - } - - /** - * Helper to register an event/watch callback. - * - * @param {Vue} vm - * @param {String} action - * @param {String} key - * @param {Function|String|Object} handler - * @param {Object} [options] - */ - - function register(vm, action, key, handler, options) { - var type = typeof handler; - if (type === 'function') { - vm[action](key, handler, options); - } else if (type === 'string') { - var methods = vm.$options.methods; - var method = methods && methods[handler]; - if (method) { - vm[action](key, method, options); - } else { - 'development' !== 'production' && warn('Unknown method: "' + handler + '" when ' + 'registering callback for ' + action + ': "' + key + '".', vm); - } - } else if (handler && type === 'object') { - register(vm, action, key, handler.handler, handler); - } - } - - /** - * Setup recursive attached/detached calls - */ - - Vue.prototype._initDOMHooks = function () { - this.$on('hook:attached', onAttached); - this.$on('hook:detached', onDetached); - }; - - /** - * Callback to recursively call attached hook on children - */ - - function onAttached() { - if (!this._isAttached) { - this._isAttached = true; - this.$children.forEach(callAttach); - } - } - - /** - * Iterator to call attached hook - * - * @param {Vue} child - */ - - function callAttach(child) { - if (!child._isAttached && inDoc(child.$el)) { - child._callHook('attached'); - } - } - - /** - * Callback to recursively call detached hook on children - */ - - function onDetached() { - if (this._isAttached) { - this._isAttached = false; - this.$children.forEach(callDetach); - } - } - - /** - * Iterator to call detached hook - * - * @param {Vue} child - */ - - function callDetach(child) { - if (child._isAttached && !inDoc(child.$el)) { - child._callHook('detached'); - } - } - - /** - * Trigger all handlers for a hook - * - * @param {String} hook - */ - - Vue.prototype._callHook = function (hook) { - this.$emit('pre-hook:' + hook); - var handlers = this.$options[hook]; - if (handlers) { - for (var i = 0, j = handlers.length; i < j; i++) { - handlers[i].call(this); - } - } - this.$emit('hook:' + hook); - }; - } - - function noop$1() {} - - /** - * A directive links a DOM element with a piece of data, - * which is the result of evaluating an expression. - * It registers a watcher with the expression and calls - * the DOM update function when a change is triggered. - * - * @param {Object} descriptor - * - {String} name - * - {Object} def - * - {String} expression - * - {Array<Object>} [filters] - * - {Object} [modifiers] - * - {Boolean} literal - * - {String} attr - * - {String} arg - * - {String} raw - * - {String} [ref] - * - {Array<Object>} [interp] - * - {Boolean} [hasOneTime] - * @param {Vue} vm - * @param {Node} el - * @param {Vue} [host] - transclusion host component - * @param {Object} [scope] - v-for scope - * @param {Fragment} [frag] - owner fragment - * @constructor - */ - function Directive(descriptor, vm, el, host, scope, frag) { - this.vm = vm; - this.el = el; - // copy descriptor properties - this.descriptor = descriptor; - this.name = descriptor.name; - this.expression = descriptor.expression; - this.arg = descriptor.arg; - this.modifiers = descriptor.modifiers; - this.filters = descriptor.filters; - this.literal = this.modifiers && this.modifiers.literal; - // private - this._locked = false; - this._bound = false; - this._listeners = null; - // link context - this._host = host; - this._scope = scope; - this._frag = frag; - // store directives on node in dev mode - if ('development' !== 'production' && this.el) { - this.el._vue_directives = this.el._vue_directives || []; - this.el._vue_directives.push(this); - } - } - - /** - * Initialize the directive, mixin definition properties, - * setup the watcher, call definition bind() and update() - * if present. - */ - - Directive.prototype._bind = function () { - var name = this.name; - var descriptor = this.descriptor; - - // remove attribute - if ((name !== 'cloak' || this.vm._isCompiled) && this.el && this.el.removeAttribute) { - var attr = descriptor.attr || 'v-' + name; - this.el.removeAttribute(attr); - } - - // copy def properties - var def = descriptor.def; - if (typeof def === 'function') { - this.update = def; - } else { - extend(this, def); - } - - // setup directive params - this._setupParams(); - - // initial bind - if (this.bind) { - this.bind(); - } - this._bound = true; - - if (this.literal) { - this.update && this.update(descriptor.raw); - } else if ((this.expression || this.modifiers) && (this.update || this.twoWay) && !this._checkStatement()) { - // wrapped updater for context - var dir = this; - if (this.update) { - this._update = function (val, oldVal) { - if (!dir._locked) { - dir.update(val, oldVal); - } - }; - } else { - this._update = noop$1; - } - var preProcess = this._preProcess ? bind(this._preProcess, this) : null; - var postProcess = this._postProcess ? bind(this._postProcess, this) : null; - var watcher = this._watcher = new Watcher(this.vm, this.expression, this._update, // callback - { - filters: this.filters, - twoWay: this.twoWay, - deep: this.deep, - preProcess: preProcess, - postProcess: postProcess, - scope: this._scope - }); - // v-model with inital inline value need to sync back to - // model instead of update to DOM on init. They would - // set the afterBind hook to indicate that. - if (this.afterBind) { - this.afterBind(); - } else if (this.update) { - this.update(watcher.value); - } - } - }; - - /** - * Setup all param attributes, e.g. track-by, - * transition-mode, etc... - */ - - Directive.prototype._setupParams = function () { - if (!this.params) { - return; - } - var params = this.params; - // swap the params array with a fresh object. - this.params = Object.create(null); - var i = params.length; - var key, val, mappedKey; - while (i--) { - key = hyphenate(params[i]); - mappedKey = camelize(key); - val = getBindAttr(this.el, key); - if (val != null) { - // dynamic - this._setupParamWatcher(mappedKey, val); - } else { - // static - val = getAttr(this.el, key); - if (val != null) { - this.params[mappedKey] = val === '' ? true : val; - } - } - } - }; - - /** - * Setup a watcher for a dynamic param. - * - * @param {String} key - * @param {String} expression - */ - - Directive.prototype._setupParamWatcher = function (key, expression) { - var self = this; - var called = false; - var unwatch = (this._scope || this.vm).$watch(expression, function (val, oldVal) { - self.params[key] = val; - // since we are in immediate mode, - // only call the param change callbacks if this is not the first update. - if (called) { - var cb = self.paramWatchers && self.paramWatchers[key]; - if (cb) { - cb.call(self, val, oldVal); - } - } else { - called = true; - } - }, { - immediate: true, - user: false - });(this._paramUnwatchFns || (this._paramUnwatchFns = [])).push(unwatch); - }; - - /** - * Check if the directive is a function caller - * and if the expression is a callable one. If both true, - * we wrap up the expression and use it as the event - * handler. - * - * e.g. on-click="a++" - * - * @return {Boolean} - */ - - Directive.prototype._checkStatement = function () { - var expression = this.expression; - if (expression && this.acceptStatement && !isSimplePath(expression)) { - var fn = parseExpression(expression).get; - var scope = this._scope || this.vm; - var handler = function handler(e) { - scope.$event = e; - fn.call(scope, scope); - scope.$event = null; - }; - if (this.filters) { - handler = scope._applyFilters(handler, null, this.filters); - } - this.update(handler); - return true; - } - }; - - /** - * Set the corresponding value with the setter. - * This should only be used in two-way directives - * e.g. v-model. - * - * @param {*} value - * @public - */ - - Directive.prototype.set = function (value) { - /* istanbul ignore else */ - if (this.twoWay) { - this._withLock(function () { - this._watcher.set(value); - }); - } else if ('development' !== 'production') { - warn('Directive.set() can only be used inside twoWay' + 'directives.'); - } - }; - - /** - * Execute a function while preventing that function from - * triggering updates on this directive instance. - * - * @param {Function} fn - */ - - Directive.prototype._withLock = function (fn) { - var self = this; - self._locked = true; - fn.call(self); - nextTick(function () { - self._locked = false; - }); - }; - - /** - * Convenience method that attaches a DOM event listener - * to the directive element and autometically tears it down - * during unbind. - * - * @param {String} event - * @param {Function} handler - * @param {Boolean} [useCapture] - */ - - Directive.prototype.on = function (event, handler, useCapture) { - on(this.el, event, handler, useCapture);(this._listeners || (this._listeners = [])).push([event, handler]); - }; - - /** - * Teardown the watcher and call unbind. - */ - - Directive.prototype._teardown = function () { - if (this._bound) { - this._bound = false; - if (this.unbind) { - this.unbind(); - } - if (this._watcher) { - this._watcher.teardown(); - } - var listeners = this._listeners; - var i; - if (listeners) { - i = listeners.length; - while (i--) { - off(this.el, listeners[i][0], listeners[i][1]); - } - } - var unwatchFns = this._paramUnwatchFns; - if (unwatchFns) { - i = unwatchFns.length; - while (i--) { - unwatchFns[i](); - } - } - if ('development' !== 'production' && this.el) { - this.el._vue_directives.$remove(this); - } - this.vm = this.el = this._watcher = this._listeners = null; - } - }; - - function lifecycleMixin (Vue) { - /** - * Update v-ref for component. - * - * @param {Boolean} remove - */ - - Vue.prototype._updateRef = function (remove) { - var ref = this.$options._ref; - if (ref) { - var refs = (this._scope || this._context).$refs; - if (remove) { - if (refs[ref] === this) { - refs[ref] = null; - } - } else { - refs[ref] = this; - } - } - }; - - /** - * Transclude, compile and link element. - * - * If a pre-compiled linker is available, that means the - * passed in element will be pre-transcluded and compiled - * as well - all we need to do is to call the linker. - * - * Otherwise we need to call transclude/compile/link here. - * - * @param {Element} el - */ - - Vue.prototype._compile = function (el) { - var options = this.$options; - - // transclude and init element - // transclude can potentially replace original - // so we need to keep reference; this step also injects - // the template and caches the original attributes - // on the container node and replacer node. - var original = el; - el = transclude(el, options); - this._initElement(el); - - // handle v-pre on root node (#2026) - if (el.nodeType === 1 && getAttr(el, 'v-pre') !== null) { - return; - } - - // root is always compiled per-instance, because - // container attrs and props can be different every time. - var contextOptions = this._context && this._context.$options; - var rootLinker = compileRoot(el, options, contextOptions); - - // resolve slot distribution - resolveSlots(this, options._content); - - // compile and link the rest - var contentLinkFn; - var ctor = this.constructor; - // component compilation can be cached - // as long as it's not using inline-template - if (options._linkerCachable) { - contentLinkFn = ctor.linker; - if (!contentLinkFn) { - contentLinkFn = ctor.linker = compile(el, options); - } - } - - // link phase - // make sure to link root with prop scope! - var rootUnlinkFn = rootLinker(this, el, this._scope); - var contentUnlinkFn = contentLinkFn ? contentLinkFn(this, el) : compile(el, options)(this, el); - - // register composite unlink function - // to be called during instance destruction - this._unlinkFn = function () { - rootUnlinkFn(); - // passing destroying: true to avoid searching and - // splicing the directives - contentUnlinkFn(true); - }; - - // finally replace original - if (options.replace) { - replace(original, el); - } - - this._isCompiled = true; - this._callHook('compiled'); - }; - - /** - * Initialize instance element. Called in the public - * $mount() method. - * - * @param {Element} el - */ - - Vue.prototype._initElement = function (el) { - if (isFragment(el)) { - this._isFragment = true; - this.$el = this._fragmentStart = el.firstChild; - this._fragmentEnd = el.lastChild; - // set persisted text anchors to empty - if (this._fragmentStart.nodeType === 3) { - this._fragmentStart.data = this._fragmentEnd.data = ''; - } - this._fragment = el; - } else { - this.$el = el; - } - this.$el.__vue__ = this; - this._callHook('beforeCompile'); - }; - - /** - * Create and bind a directive to an element. - * - * @param {Object} descriptor - parsed directive descriptor - * @param {Node} node - target node - * @param {Vue} [host] - transclusion host component - * @param {Object} [scope] - v-for scope - * @param {Fragment} [frag] - owner fragment - */ - - Vue.prototype._bindDir = function (descriptor, node, host, scope, frag) { - this._directives.push(new Directive(descriptor, this, node, host, scope, frag)); - }; - - /** - * Teardown an instance, unobserves the data, unbind all the - * directives, turn off all the event listeners, etc. - * - * @param {Boolean} remove - whether to remove the DOM node. - * @param {Boolean} deferCleanup - if true, defer cleanup to - * be called later - */ - - Vue.prototype._destroy = function (remove, deferCleanup) { - if (this._isBeingDestroyed) { - if (!deferCleanup) { - this._cleanup(); - } - return; - } - - var destroyReady; - var pendingRemoval; - - var self = this; - // Cleanup should be called either synchronously or asynchronoysly as - // callback of this.$remove(), or if remove and deferCleanup are false. - // In any case it should be called after all other removing, unbinding and - // turning of is done - var cleanupIfPossible = function cleanupIfPossible() { - if (destroyReady && !pendingRemoval && !deferCleanup) { - self._cleanup(); - } - }; - - // remove DOM element - if (remove && this.$el) { - pendingRemoval = true; - this.$remove(function () { - pendingRemoval = false; - cleanupIfPossible(); - }); - } - - this._callHook('beforeDestroy'); - this._isBeingDestroyed = true; - var i; - // remove self from parent. only necessary - // if parent is not being destroyed as well. - var parent = this.$parent; - if (parent && !parent._isBeingDestroyed) { - parent.$children.$remove(this); - // unregister ref (remove: true) - this._updateRef(true); - } - // destroy all children. - i = this.$children.length; - while (i--) { - this.$children[i].$destroy(); - } - // teardown props - if (this._propsUnlinkFn) { - this._propsUnlinkFn(); - } - // teardown all directives. this also tearsdown all - // directive-owned watchers. - if (this._unlinkFn) { - this._unlinkFn(); - } - i = this._watchers.length; - while (i--) { - this._watchers[i].teardown(); - } - // remove reference to self on $el - if (this.$el) { - this.$el.__vue__ = null; - } - - destroyReady = true; - cleanupIfPossible(); - }; - - /** - * Clean up to ensure garbage collection. - * This is called after the leave transition if there - * is any. - */ - - Vue.prototype._cleanup = function () { - if (this._isDestroyed) { - return; - } - // remove self from owner fragment - // do it in cleanup so that we can call $destroy with - // defer right when a fragment is about to be removed. - if (this._frag) { - this._frag.children.$remove(this); - } - // remove reference from data ob - // frozen object may not have observer. - if (this._data && this._data.__ob__) { - this._data.__ob__.removeVm(this); - } - // Clean up references to private properties and other - // instances. preserve reference to _data so that proxy - // accessors still work. The only potential side effect - // here is that mutating the instance after it's destroyed - // may affect the state of other components that are still - // observing the same object, but that seems to be a - // reasonable responsibility for the user rather than - // always throwing an error on them. - this.$el = this.$parent = this.$root = this.$children = this._watchers = this._context = this._scope = this._directives = null; - // call the last hook... - this._isDestroyed = true; - this._callHook('destroyed'); - // turn off all instance listeners. - this.$off(); - }; - } - - function miscMixin (Vue) { - /** - * Apply a list of filter (descriptors) to a value. - * Using plain for loops here because this will be called in - * the getter of any watcher with filters so it is very - * performance sensitive. - * - * @param {*} value - * @param {*} [oldValue] - * @param {Array} filters - * @param {Boolean} write - * @return {*} - */ - - Vue.prototype._applyFilters = function (value, oldValue, filters, write) { - var filter, fn, args, arg, offset, i, l, j, k; - for (i = 0, l = filters.length; i < l; i++) { - filter = filters[write ? l - i - 1 : i]; - fn = resolveAsset(this.$options, 'filters', filter.name, true); - if (!fn) continue; - fn = write ? fn.write : fn.read || fn; - if (typeof fn !== 'function') continue; - args = write ? [value, oldValue] : [value]; - offset = write ? 2 : 1; - if (filter.args) { - for (j = 0, k = filter.args.length; j < k; j++) { - arg = filter.args[j]; - args[j + offset] = arg.dynamic ? this.$get(arg.value) : arg.value; - } - } - value = fn.apply(this, args); - } - return value; - }; - - /** - * Resolve a component, depending on whether the component - * is defined normally or using an async factory function. - * Resolves synchronously if already resolved, otherwise - * resolves asynchronously and caches the resolved - * constructor on the factory. - * - * @param {String|Function} value - * @param {Function} cb - */ - - Vue.prototype._resolveComponent = function (value, cb) { - var factory; - if (typeof value === 'function') { - factory = value; - } else { - factory = resolveAsset(this.$options, 'components', value, true); - } - /* istanbul ignore if */ - if (!factory) { - return; - } - // async component factory - if (!factory.options) { - if (factory.resolved) { - // cached - cb(factory.resolved); - } else if (factory.requested) { - // pool callbacks - factory.pendingCallbacks.push(cb); - } else { - factory.requested = true; - var cbs = factory.pendingCallbacks = [cb]; - factory.call(this, function resolve(res) { - if (isPlainObject(res)) { - res = Vue.extend(res); - } - // cache resolved - factory.resolved = res; - // invoke callbacks - for (var i = 0, l = cbs.length; i < l; i++) { - cbs[i](res); - } - }, function reject(reason) { - 'development' !== 'production' && warn('Failed to resolve async component' + (typeof value === 'string' ? ': ' + value : '') + '. ' + (reason ? '\nReason: ' + reason : '')); - }); - } - } else { - // normal component - cb(factory); - } - }; - } - - var filterRE$1 = /[^|]\|[^|]/; - - function dataAPI (Vue) { - /** - * Get the value from an expression on this vm. - * - * @param {String} exp - * @param {Boolean} [asStatement] - * @return {*} - */ - - Vue.prototype.$get = function (exp, asStatement) { - var res = parseExpression(exp); - if (res) { - if (asStatement) { - var self = this; - return function statementHandler() { - self.$arguments = toArray(arguments); - var result = res.get.call(self, self); - self.$arguments = null; - return result; - }; - } else { - try { - return res.get.call(this, this); - } catch (e) {} - } - } - }; - - /** - * Set the value from an expression on this vm. - * The expression must be a valid left-hand - * expression in an assignment. - * - * @param {String} exp - * @param {*} val - */ - - Vue.prototype.$set = function (exp, val) { - var res = parseExpression(exp, true); - if (res && res.set) { - res.set.call(this, this, val); - } - }; - - /** - * Delete a property on the VM - * - * @param {String} key - */ - - Vue.prototype.$delete = function (key) { - del(this._data, key); - }; - - /** - * Watch an expression, trigger callback when its - * value changes. - * - * @param {String|Function} expOrFn - * @param {Function} cb - * @param {Object} [options] - * - {Boolean} deep - * - {Boolean} immediate - * @return {Function} - unwatchFn - */ - - Vue.prototype.$watch = function (expOrFn, cb, options) { - var vm = this; - var parsed; - if (typeof expOrFn === 'string') { - parsed = parseDirective(expOrFn); - expOrFn = parsed.expression; - } - var watcher = new Watcher(vm, expOrFn, cb, { - deep: options && options.deep, - sync: options && options.sync, - filters: parsed && parsed.filters, - user: !options || options.user !== false - }); - if (options && options.immediate) { - cb.call(vm, watcher.value); - } - return function unwatchFn() { - watcher.teardown(); - }; - }; - - /** - * Evaluate a text directive, including filters. - * - * @param {String} text - * @param {Boolean} [asStatement] - * @return {String} - */ - - Vue.prototype.$eval = function (text, asStatement) { - // check for filters. - if (filterRE$1.test(text)) { - var dir = parseDirective(text); - // the filter regex check might give false positive - // for pipes inside strings, so it's possible that - // we don't get any filters here - var val = this.$get(dir.expression, asStatement); - return dir.filters ? this._applyFilters(val, null, dir.filters) : val; - } else { - // no filter - return this.$get(text, asStatement); - } - }; - - /** - * Interpolate a piece of template text. - * - * @param {String} text - * @return {String} - */ - - Vue.prototype.$interpolate = function (text) { - var tokens = parseText(text); - var vm = this; - if (tokens) { - if (tokens.length === 1) { - return vm.$eval(tokens[0].value) + ''; - } else { - return tokens.map(function (token) { - return token.tag ? vm.$eval(token.value) : token.value; - }).join(''); - } - } else { - return text; - } - }; - - /** - * Log instance data as a plain JS object - * so that it is easier to inspect in console. - * This method assumes console is available. - * - * @param {String} [path] - */ - - Vue.prototype.$log = function (path) { - var data = path ? getPath(this._data, path) : this._data; - if (data) { - data = clean(data); - } - // include computed fields - if (!path) { - var key; - for (key in this.$options.computed) { - data[key] = clean(this[key]); - } - if (this._props) { - for (key in this._props) { - data[key] = clean(this[key]); - } - } - } - console.log(data); - }; - - /** - * "clean" a getter/setter converted object into a plain - * object copy. - * - * @param {Object} - obj - * @return {Object} - */ - - function clean(obj) { - return JSON.parse(JSON.stringify(obj)); - } - } - - function domAPI (Vue) { - /** - * Convenience on-instance nextTick. The callback is - * auto-bound to the instance, and this avoids component - * modules having to rely on the global Vue. - * - * @param {Function} fn - */ - - Vue.prototype.$nextTick = function (fn) { - nextTick(fn, this); - }; - - /** - * Append instance to target - * - * @param {Node} target - * @param {Function} [cb] - * @param {Boolean} [withTransition] - defaults to true - */ - - Vue.prototype.$appendTo = function (target, cb, withTransition) { - return insert(this, target, cb, withTransition, append, appendWithTransition); - }; - - /** - * Prepend instance to target - * - * @param {Node} target - * @param {Function} [cb] - * @param {Boolean} [withTransition] - defaults to true - */ - - Vue.prototype.$prependTo = function (target, cb, withTransition) { - target = query(target); - if (target.hasChildNodes()) { - this.$before(target.firstChild, cb, withTransition); - } else { - this.$appendTo(target, cb, withTransition); - } - return this; - }; - - /** - * Insert instance before target - * - * @param {Node} target - * @param {Function} [cb] - * @param {Boolean} [withTransition] - defaults to true - */ - - Vue.prototype.$before = function (target, cb, withTransition) { - return insert(this, target, cb, withTransition, beforeWithCb, beforeWithTransition); - }; - - /** - * Insert instance after target - * - * @param {Node} target - * @param {Function} [cb] - * @param {Boolean} [withTransition] - defaults to true - */ - - Vue.prototype.$after = function (target, cb, withTransition) { - target = query(target); - if (target.nextSibling) { - this.$before(target.nextSibling, cb, withTransition); - } else { - this.$appendTo(target.parentNode, cb, withTransition); - } - return this; - }; - - /** - * Remove instance from DOM - * - * @param {Function} [cb] - * @param {Boolean} [withTransition] - defaults to true - */ - - Vue.prototype.$remove = function (cb, withTransition) { - if (!this.$el.parentNode) { - return cb && cb(); - } - var inDocument = this._isAttached && inDoc(this.$el); - // if we are not in document, no need to check - // for transitions - if (!inDocument) withTransition = false; - var self = this; - var realCb = function realCb() { - if (inDocument) self._callHook('detached'); - if (cb) cb(); - }; - if (this._isFragment) { - removeNodeRange(this._fragmentStart, this._fragmentEnd, this, this._fragment, realCb); - } else { - var op = withTransition === false ? removeWithCb : removeWithTransition; - op(this.$el, this, realCb); - } - return this; - }; - - /** - * Shared DOM insertion function. - * - * @param {Vue} vm - * @param {Element} target - * @param {Function} [cb] - * @param {Boolean} [withTransition] - * @param {Function} op1 - op for non-transition insert - * @param {Function} op2 - op for transition insert - * @return vm - */ - - function insert(vm, target, cb, withTransition, op1, op2) { - target = query(target); - var targetIsDetached = !inDoc(target); - var op = withTransition === false || targetIsDetached ? op1 : op2; - var shouldCallHook = !targetIsDetached && !vm._isAttached && !inDoc(vm.$el); - if (vm._isFragment) { - mapNodeRange(vm._fragmentStart, vm._fragmentEnd, function (node) { - op(node, target, vm); - }); - cb && cb(); - } else { - op(vm.$el, target, vm, cb); - } - if (shouldCallHook) { - vm._callHook('attached'); - } - return vm; - } - - /** - * Check for selectors - * - * @param {String|Element} el - */ - - function query(el) { - return typeof el === 'string' ? document.querySelector(el) : el; - } - - /** - * Append operation that takes a callback. - * - * @param {Node} el - * @param {Node} target - * @param {Vue} vm - unused - * @param {Function} [cb] - */ - - function append(el, target, vm, cb) { - target.appendChild(el); - if (cb) cb(); - } - - /** - * InsertBefore operation that takes a callback. - * - * @param {Node} el - * @param {Node} target - * @param {Vue} vm - unused - * @param {Function} [cb] - */ - - function beforeWithCb(el, target, vm, cb) { - before(el, target); - if (cb) cb(); - } - - /** - * Remove operation that takes a callback. - * - * @param {Node} el - * @param {Vue} vm - unused - * @param {Function} [cb] - */ - - function removeWithCb(el, vm, cb) { - remove(el); - if (cb) cb(); - } - } - - function eventsAPI (Vue) { - /** - * Listen on the given `event` with `fn`. - * - * @param {String} event - * @param {Function} fn - */ - - Vue.prototype.$on = function (event, fn) { - (this._events[event] || (this._events[event] = [])).push(fn); - modifyListenerCount(this, event, 1); - return this; - }; - - /** - * Adds an `event` listener that will be invoked a single - * time then automatically removed. - * - * @param {String} event - * @param {Function} fn - */ - - Vue.prototype.$once = function (event, fn) { - var self = this; - function on() { - self.$off(event, on); - fn.apply(this, arguments); - } - on.fn = fn; - this.$on(event, on); - return this; - }; - - /** - * Remove the given callback for `event` or all - * registered callbacks. - * - * @param {String} event - * @param {Function} fn - */ - - Vue.prototype.$off = function (event, fn) { - var cbs; - // all - if (!arguments.length) { - if (this.$parent) { - for (event in this._events) { - cbs = this._events[event]; - if (cbs) { - modifyListenerCount(this, event, -cbs.length); - } - } - } - this._events = {}; - return this; - } - // specific event - cbs = this._events[event]; - if (!cbs) { - return this; - } - if (arguments.length === 1) { - modifyListenerCount(this, event, -cbs.length); - this._events[event] = null; - return this; - } - // specific handler - var cb; - var i = cbs.length; - while (i--) { - cb = cbs[i]; - if (cb === fn || cb.fn === fn) { - modifyListenerCount(this, event, -1); - cbs.splice(i, 1); - break; - } - } - return this; - }; - - /** - * Trigger an event on self. - * - * @param {String|Object} event - * @return {Boolean} shouldPropagate - */ - - Vue.prototype.$emit = function (event) { - var isSource = typeof event === 'string'; - event = isSource ? event : event.name; - var cbs = this._events[event]; - var shouldPropagate = isSource || !cbs; - if (cbs) { - cbs = cbs.length > 1 ? toArray(cbs) : cbs; - // this is a somewhat hacky solution to the question raised - // in #2102: for an inline component listener like <comp @test="doThis">, - // the propagation handling is somewhat broken. Therefore we - // need to treat these inline callbacks differently. - var hasParentCbs = isSource && cbs.some(function (cb) { - return cb._fromParent; - }); - if (hasParentCbs) { - shouldPropagate = false; - } - var args = toArray(arguments, 1); - for (var i = 0, l = cbs.length; i < l; i++) { - var cb = cbs[i]; - var res = cb.apply(this, args); - if (res === true && (!hasParentCbs || cb._fromParent)) { - shouldPropagate = true; - } - } - } - return shouldPropagate; - }; - - /** - * Recursively broadcast an event to all children instances. - * - * @param {String|Object} event - * @param {...*} additional arguments - */ - - Vue.prototype.$broadcast = function (event) { - var isSource = typeof event === 'string'; - event = isSource ? event : event.name; - // if no child has registered for this event, - // then there's no need to broadcast. - if (!this._eventsCount[event]) return; - var children = this.$children; - var args = toArray(arguments); - if (isSource) { - // use object event to indicate non-source emit - // on children - args[0] = { name: event, source: this }; - } - for (var i = 0, l = children.length; i < l; i++) { - var child = children[i]; - var shouldPropagate = child.$emit.apply(child, args); - if (shouldPropagate) { - child.$broadcast.apply(child, args); - } - } - return this; - }; - - /** - * Recursively propagate an event up the parent chain. - * - * @param {String} event - * @param {...*} additional arguments - */ - - Vue.prototype.$dispatch = function (event) { - var shouldPropagate = this.$emit.apply(this, arguments); - if (!shouldPropagate) return; - var parent = this.$parent; - var args = toArray(arguments); - // use object event to indicate non-source emit - // on parents - args[0] = { name: event, source: this }; - while (parent) { - shouldPropagate = parent.$emit.apply(parent, args); - parent = shouldPropagate ? parent.$parent : null; - } - return this; - }; - - /** - * Modify the listener counts on all parents. - * This bookkeeping allows $broadcast to return early when - * no child has listened to a certain event. - * - * @param {Vue} vm - * @param {String} event - * @param {Number} count - */ - - var hookRE = /^hook:/; - function modifyListenerCount(vm, event, count) { - var parent = vm.$parent; - // hooks do not get broadcasted so no need - // to do bookkeeping for them - if (!parent || !count || hookRE.test(event)) return; - while (parent) { - parent._eventsCount[event] = (parent._eventsCount[event] || 0) + count; - parent = parent.$parent; - } - } - } - - function lifecycleAPI (Vue) { - /** - * Set instance target element and kick off the compilation - * process. The passed in `el` can be a selector string, an - * existing Element, or a DocumentFragment (for block - * instances). - * - * @param {Element|DocumentFragment|string} el - * @public - */ - - Vue.prototype.$mount = function (el) { - if (this._isCompiled) { - 'development' !== 'production' && warn('$mount() should be called only once.', this); - return; - } - el = query(el); - if (!el) { - el = document.createElement('div'); - } - this._compile(el); - this._initDOMHooks(); - if (inDoc(this.$el)) { - this._callHook('attached'); - ready.call(this); - } else { - this.$once('hook:attached', ready); - } - return this; - }; - - /** - * Mark an instance as ready. - */ - - function ready() { - this._isAttached = true; - this._isReady = true; - this._callHook('ready'); - } - - /** - * Teardown the instance, simply delegate to the internal - * _destroy. - * - * @param {Boolean} remove - * @param {Boolean} deferCleanup - */ - - Vue.prototype.$destroy = function (remove, deferCleanup) { - this._destroy(remove, deferCleanup); - }; - - /** - * Partially compile a piece of DOM and return a - * decompile function. - * - * @param {Element|DocumentFragment} el - * @param {Vue} [host] - * @param {Object} [scope] - * @param {Fragment} [frag] - * @return {Function} - */ - - Vue.prototype.$compile = function (el, host, scope, frag) { - return compile(el, this.$options, true)(this, el, host, scope, frag); - }; - } - - /** - * The exposed Vue constructor. - * - * API conventions: - * - public API methods/properties are prefixed with `$` - * - internal methods/properties are prefixed with `_` - * - non-prefixed properties are assumed to be proxied user - * data. - * - * @constructor - * @param {Object} [options] - * @public - */ - - function Vue(options) { - this._init(options); - } - - // install internals - initMixin(Vue); - stateMixin(Vue); - eventsMixin(Vue); - lifecycleMixin(Vue); - miscMixin(Vue); - - // install instance APIs - dataAPI(Vue); - domAPI(Vue); - eventsAPI(Vue); - lifecycleAPI(Vue); - - var slot = { - - priority: SLOT, - params: ['name'], - - bind: function bind() { - // this was resolved during component transclusion - var name = this.params.name || 'default'; - var content = this.vm._slotContents && this.vm._slotContents[name]; - if (!content || !content.hasChildNodes()) { - this.fallback(); - } else { - this.compile(content.cloneNode(true), this.vm._context, this.vm); - } - }, - - compile: function compile(content, context, host) { - if (content && context) { - if (this.el.hasChildNodes() && content.childNodes.length === 1 && content.childNodes[0].nodeType === 1 && content.childNodes[0].hasAttribute('v-if')) { - // if the inserted slot has v-if - // inject fallback content as the v-else - var elseBlock = document.createElement('template'); - elseBlock.setAttribute('v-else', ''); - elseBlock.innerHTML = this.el.innerHTML; - // the else block should be compiled in child scope - elseBlock._context = this.vm; - content.appendChild(elseBlock); - } - var scope = host ? host._scope : this._scope; - this.unlink = context.$compile(content, host, scope, this._frag); - } - if (content) { - replace(this.el, content); - } else { - remove(this.el); - } - }, - - fallback: function fallback() { - this.compile(extractContent(this.el, true), this.vm); - }, - - unbind: function unbind() { - if (this.unlink) { - this.unlink(); - } - } - }; - - var partial = { - - priority: PARTIAL, - - params: ['name'], - - // watch changes to name for dynamic partials - paramWatchers: { - name: function name(value) { - vIf.remove.call(this); - if (value) { - this.insert(value); - } - } - }, - - bind: function bind() { - this.anchor = createAnchor('v-partial'); - replace(this.el, this.anchor); - this.insert(this.params.name); - }, - - insert: function insert(id) { - var partial = resolveAsset(this.vm.$options, 'partials', id, true); - if (partial) { - this.factory = new FragmentFactory(this.vm, partial); - vIf.insert.call(this); - } - }, - - unbind: function unbind() { - if (this.frag) { - this.frag.destroy(); - } - } - }; - - var elementDirectives = { - slot: slot, - partial: partial - }; - - var convertArray = vFor._postProcess; - - /** - * Limit filter for arrays - * - * @param {Number} n - * @param {Number} offset (Decimal expected) - */ - - function limitBy(arr, n, offset) { - offset = offset ? parseInt(offset, 10) : 0; - n = toNumber(n); - return typeof n === 'number' ? arr.slice(offset, offset + n) : arr; - } - - /** - * Filter filter for arrays - * - * @param {String} search - * @param {String} [delimiter] - * @param {String} ...dataKeys - */ - - function filterBy(arr, search, delimiter) { - arr = convertArray(arr); - if (search == null) { - return arr; - } - if (typeof search === 'function') { - return arr.filter(search); - } - // cast to lowercase string - search = ('' + search).toLowerCase(); - // allow optional `in` delimiter - // because why not - var n = delimiter === 'in' ? 3 : 2; - // extract and flatten keys - var keys = Array.prototype.concat.apply([], toArray(arguments, n)); - var res = []; - var item, key, val, j; - for (var i = 0, l = arr.length; i < l; i++) { - item = arr[i]; - val = item && item.$value || item; - j = keys.length; - if (j) { - while (j--) { - key = keys[j]; - if (key === '$key' && contains(item.$key, search) || contains(getPath(val, key), search)) { - res.push(item); - break; - } - } - } else if (contains(item, search)) { - res.push(item); - } - } - return res; - } - - /** - * Filter filter for arrays - * - * @param {String|Array<String>|Function} ...sortKeys - * @param {Number} [order] - */ - - function orderBy(arr) { - var comparator = null; - var sortKeys = undefined; - arr = convertArray(arr); - - // determine order (last argument) - var args = toArray(arguments, 1); - var order = args[args.length - 1]; - if (typeof order === 'number') { - order = order < 0 ? -1 : 1; - args = args.length > 1 ? args.slice(0, -1) : args; - } else { - order = 1; - } - - // determine sortKeys & comparator - var firstArg = args[0]; - if (!firstArg) { - return arr; - } else if (typeof firstArg === 'function') { - // custom comparator - comparator = function (a, b) { - return firstArg(a, b) * order; - }; - } else { - // string keys. flatten first - sortKeys = Array.prototype.concat.apply([], args); - comparator = function (a, b, i) { - i = i || 0; - return i >= sortKeys.length - 1 ? baseCompare(a, b, i) : baseCompare(a, b, i) || comparator(a, b, i + 1); - }; - } - - function baseCompare(a, b, sortKeyIndex) { - var sortKey = sortKeys[sortKeyIndex]; - if (sortKey) { - if (sortKey !== '$key') { - if (isObject(a) && '$value' in a) a = a.$value; - if (isObject(b) && '$value' in b) b = b.$value; - } - a = isObject(a) ? getPath(a, sortKey) : a; - b = isObject(b) ? getPath(b, sortKey) : b; - } - return a === b ? 0 : a > b ? order : -order; - } - - // sort on a copy to avoid mutating original array - return arr.slice().sort(comparator); - } - - /** - * String contain helper - * - * @param {*} val - * @param {String} search - */ - - function contains(val, search) { - var i; - if (isPlainObject(val)) { - var keys = Object.keys(val); - i = keys.length; - while (i--) { - if (contains(val[keys[i]], search)) { - return true; - } - } - } else if (isArray(val)) { - i = val.length; - while (i--) { - if (contains(val[i], search)) { - return true; - } - } - } else if (val != null) { - return val.toString().toLowerCase().indexOf(search) > -1; - } - } - - var digitsRE = /(\d{3})(?=\d)/g; - - // asset collections must be a plain object. - var filters = { - - orderBy: orderBy, - filterBy: filterBy, - limitBy: limitBy, - - /** - * Stringify value. - * - * @param {Number} indent - */ - - json: { - read: function read(value, indent) { - return typeof value === 'string' ? value : JSON.stringify(value, null, arguments.length > 1 ? indent : 2); - }, - write: function write(value) { - try { - return JSON.parse(value); - } catch (e) { - return value; - } - } - }, - - /** - * 'abc' => 'Abc' - */ - - capitalize: function capitalize(value) { - if (!value && value !== 0) return ''; - value = value.toString(); - return value.charAt(0).toUpperCase() + value.slice(1); - }, - - /** - * 'abc' => 'ABC' - */ - - uppercase: function uppercase(value) { - return value || value === 0 ? value.toString().toUpperCase() : ''; - }, - - /** - * 'AbC' => 'abc' - */ - - lowercase: function lowercase(value) { - return value || value === 0 ? value.toString().toLowerCase() : ''; - }, - - /** - * 12345 => $12,345.00 - * - * @param {String} sign - * @param {Number} decimals Decimal places - */ - - currency: function currency(value, _currency, decimals) { - value = parseFloat(value); - if (!isFinite(value) || !value && value !== 0) return ''; - _currency = _currency != null ? _currency : '$'; - decimals = decimals != null ? decimals : 2; - var stringified = Math.abs(value).toFixed(decimals); - var _int = decimals ? stringified.slice(0, -1 - decimals) : stringified; - var i = _int.length % 3; - var head = i > 0 ? _int.slice(0, i) + (_int.length > 3 ? ',' : '') : ''; - var _float = decimals ? stringified.slice(-1 - decimals) : ''; - var sign = value < 0 ? '-' : ''; - return sign + _currency + head + _int.slice(i).replace(digitsRE, '$1,') + _float; - }, - - /** - * 'item' => 'items' - * - * @params - * an array of strings corresponding to - * the single, double, triple ... forms of the word to - * be pluralized. When the number to be pluralized - * exceeds the length of the args, it will use the last - * entry in the array. - * - * e.g. ['single', 'double', 'triple', 'multiple'] - */ - - pluralize: function pluralize(value) { - var args = toArray(arguments, 1); - var length = args.length; - if (length > 1) { - var index = value % 10 - 1; - return index in args ? args[index] : args[length - 1]; - } else { - return args[0] + (value === 1 ? '' : 's'); - } - }, - - /** - * Debounce a handler function. - * - * @param {Function} handler - * @param {Number} delay = 300 - * @return {Function} - */ - - debounce: function debounce(handler, delay) { - if (!handler) return; - if (!delay) { - delay = 300; - } - return _debounce(handler, delay); - } - }; - - function installGlobalAPI (Vue) { - /** - * Vue and every constructor that extends Vue has an - * associated options object, which can be accessed during - * compilation steps as `this.constructor.options`. - * - * These can be seen as the default options of every - * Vue instance. - */ - - Vue.options = { - directives: directives, - elementDirectives: elementDirectives, - filters: filters, - transitions: {}, - components: {}, - partials: {}, - replace: true - }; - - /** - * Expose useful internals - */ - - Vue.util = util; - Vue.config = config; - Vue.set = set; - Vue['delete'] = del; - Vue.nextTick = nextTick; - - /** - * The following are exposed for advanced usage / plugins - */ - - Vue.compiler = compiler; - Vue.FragmentFactory = FragmentFactory; - Vue.internalDirectives = internalDirectives; - Vue.parsers = { - path: path, - text: text, - template: template, - directive: directive, - expression: expression - }; - - /** - * Each instance constructor, including Vue, has a unique - * cid. This enables us to create wrapped "child - * constructors" for prototypal inheritance and cache them. - */ - - Vue.cid = 0; - var cid = 1; - - /** - * Class inheritance - * - * @param {Object} extendOptions - */ - - Vue.extend = function (extendOptions) { - extendOptions = extendOptions || {}; - var Super = this; - var isFirstExtend = Super.cid === 0; - if (isFirstExtend && extendOptions._Ctor) { - return extendOptions._Ctor; - } - var name = extendOptions.name || Super.options.name; - if ('development' !== 'production') { - if (!/^[a-zA-Z][\w-]*$/.test(name)) { - warn('Invalid component name: "' + name + '". Component names ' + 'can only contain alphanumeric characaters and the hyphen.'); - name = null; - } - } - var Sub = createClass(name || 'VueComponent'); - Sub.prototype = Object.create(Super.prototype); - Sub.prototype.constructor = Sub; - Sub.cid = cid++; - Sub.options = mergeOptions(Super.options, extendOptions); - Sub['super'] = Super; - // allow further extension - Sub.extend = Super.extend; - // create asset registers, so extended classes - // can have their private assets too. - config._assetTypes.forEach(function (type) { - Sub[type] = Super[type]; - }); - // enable recursive self-lookup - if (name) { - Sub.options.components[name] = Sub; - } - // cache constructor - if (isFirstExtend) { - extendOptions._Ctor = Sub; - } - return Sub; - }; - - /** - * A function that returns a sub-class constructor with the - * given name. This gives us much nicer output when - * logging instances in the console. - * - * @param {String} name - * @return {Function} - */ - - function createClass(name) { - /* eslint-disable no-new-func */ - return new Function('return function ' + classify(name) + ' (options) { this._init(options) }')(); - /* eslint-enable no-new-func */ - } - - /** - * Plugin system - * - * @param {Object} plugin - */ - - Vue.use = function (plugin) { - /* istanbul ignore if */ - if (plugin.installed) { - return; - } - // additional parameters - var args = toArray(arguments, 1); - args.unshift(this); - if (typeof plugin.install === 'function') { - plugin.install.apply(plugin, args); - } else { - plugin.apply(null, args); - } - plugin.installed = true; - return this; - }; - - /** - * Apply a global mixin by merging it into the default - * options. - */ - - Vue.mixin = function (mixin) { - Vue.options = mergeOptions(Vue.options, mixin); - }; - - /** - * Create asset registration methods with the following - * signature: - * - * @param {String} id - * @param {*} definition - */ - - config._assetTypes.forEach(function (type) { - Vue[type] = function (id, definition) { - if (!definition) { - return this.options[type + 's'][id]; - } else { - /* istanbul ignore if */ - if ('development' !== 'production') { - if (type === 'component' && (commonTagRE.test(id) || reservedTagRE.test(id))) { - warn('Do not use built-in or reserved HTML elements as component ' + 'id: ' + id); - } - } - if (type === 'component' && isPlainObject(definition)) { - if (!definition.name) { - definition.name = id; - } - definition = Vue.extend(definition); - } - this.options[type + 's'][id] = definition; - return definition; - } - }; - }); - - // expose internal transition API - extend(Vue.transition, transition); - } - - installGlobalAPI(Vue); - - Vue.version = '1.0.26'; - - // devtools global hook - /* istanbul ignore next */ - setTimeout(function () { - if (config.devtools) { - if (devtools) { - devtools.emit('init', Vue); - } else if ('development' !== 'production' && inBrowser && /Chrome\/\d+/.test(window.navigator.userAgent)) { - console.log('Download the Vue Devtools for a better development experience:\n' + 'https://github.com/vuejs/vue-devtools'); - } - } - }, 0); - - return Vue; - -})); |