mirror of https://github.com/vuejs/vue.git
				
				
				
			
		
			
	
	
		
			9524 lines
		
	
	
		
			232 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
		
		
			
		
	
	
			9524 lines
		
	
	
		
			232 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
|  | /*! | ||
|  |  * Vue.js v1.0.15 | ||
|  |  * (c) 2016 Evan You | ||
|  |  * Released under the MIT License. | ||
|  |  */ | ||
|  | 'use strict'; | ||
|  | 
 | ||
|  | function set(obj, key, val) { | ||
|  |   if (hasOwn(obj, key)) { | ||
|  |     obj[key] = val; | ||
|  |     return; | ||
|  |   } | ||
|  |   if (obj._isVue) { | ||
|  |     set(obj._data, key, val); | ||
|  |     return; | ||
|  |   } | ||
|  |   var ob = obj.__ob__; | ||
|  |   if (!ob) { | ||
|  |     obj[key] = val; | ||
|  |     return; | ||
|  |   } | ||
|  |   ob.convert(key, val); | ||
|  |   ob.dep.notify(); | ||
|  |   if (ob.vms) { | ||
|  |     var i = ob.vms.length; | ||
|  |     while (i--) { | ||
|  |       var vm = ob.vms[i]; | ||
|  |       vm._proxy(key); | ||
|  |       vm._digest(); | ||
|  |     } | ||
|  |   } | ||
|  |   return val; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Delete a property and trigger change if necessary. | ||
|  |  * | ||
|  |  * @param {Object} obj | ||
|  |  * @param {String} key | ||
|  |  */ | ||
|  | 
 | ||
|  | function del(obj, key) { | ||
|  |   if (!hasOwn(obj, key)) { | ||
|  |     return; | ||
|  |   } | ||
|  |   delete obj[key]; | ||
|  |   var ob = obj.__ob__; | ||
|  |   if (!ob) { | ||
|  |     return; | ||
|  |   } | ||
|  |   ob.dep.notify(); | ||
|  |   if (ob.vms) { | ||
|  |     var i = ob.vms.length; | ||
|  |     while (i--) { | ||
|  |       var vm = ob.vms[i]; | ||
|  |       vm._unproxy(key); | ||
|  |       vm._digest(); | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | 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$1(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 non-enumerable 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]'; | ||
|  | 
 | ||
|  | var isIE9 = inBrowser && navigator.userAgent.toLowerCase().indexOf('msie 9.0') > 0; | ||
|  | 
 | ||
|  | var isAndroid = inBrowser && navigator.userAgent.toLowerCase().indexOf('android') > 0; | ||
|  | 
 | ||
|  | 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') { | ||
|  |     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 { | ||
|  |     timerFunc = setTimeout; | ||
|  |   } | ||
|  |   return function (cb, ctx) { | ||
|  |     var func = ctx ? function () { | ||
|  |       cb.call(ctx); | ||
|  |     } : cb; | ||
|  |     callbacks.push(func); | ||
|  |     if (pending) return; | ||
|  |     pending = true; | ||
|  |     timerFunc(nextTickHandler, 0); | ||
|  |   }; | ||
|  | })(); | ||
|  | 
 | ||
|  | 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; | ||
|  |   if (this.size === this.limit) { | ||
|  |     removed = this.shift(); | ||
|  |   } | ||
|  | 
 | ||
|  |   var entry = this.get(key, true); | ||
|  |   if (!entry) { | ||
|  |     entry = { | ||
|  |       key: key | ||
|  |     }; | ||
|  |     this._keymap[key] = entry; | ||
|  |     if (this.tail) { | ||
|  |       this.tail.newer = entry; | ||
|  |       entry.older = this.tail; | ||
|  |     } 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} str | ||
|  |  * @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 + '(.+?)' + unsafeClose + '|' + open + '(.+?)' + close, 'g'); | ||
|  |   htmlRE = new RegExp('^' + unsafeOpen + '.*' + 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; | ||
|  |   } | ||
|  |   text = text.replace(/\n/g, ''); | ||
|  |   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$1 = /[^|]\|[^|]/; | ||
|  | function inlineFilters(exp, single) { | ||
|  |   if (!filterRE$1.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$1 = 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 or not to handle fully object properties which | ||
|  |    * are already backed by getters and seters. Depending on | ||
|  |    * use case and environment, this might introduce non-neglible | ||
|  |    * performance penalties. | ||
|  |    */ | ||
|  |   convertAllProperties: false, | ||
|  | 
 | ||
|  |   /** | ||
|  |    * 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; | ||
|  | 
 | ||
|  | if (process.env.NODE_ENV !== 'production') { | ||
|  |   (function () { | ||
|  |     var hasConsole = typeof console !== 'undefined'; | ||
|  |     warn = function (msg, e) { | ||
|  |       if (hasConsole && (!config.silent || config.debug)) { | ||
|  |         console.warn('[Vue warn]: ' + msg); | ||
|  |         /* istanbul ignore if */ | ||
|  |         if (config.debug) { | ||
|  |           if (e) { | ||
|  |             throw e; | ||
|  |           } else { | ||
|  |             console.warn(new Error('Warning Stack Trace').stack); | ||
|  |           } | ||
|  |         } | ||
|  |       } | ||
|  |     }; | ||
|  |   })(); | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * 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); | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Query an element selector if it's not an element already. | ||
|  |  * | ||
|  |  * @param {String|Element} el | ||
|  |  * @return {Element} | ||
|  |  */ | ||
|  | 
 | ||
|  | function query(el) { | ||
|  |   if (typeof el === 'string') { | ||
|  |     var selector = el; | ||
|  |     el = document.querySelector(el); | ||
|  |     if (!el) { | ||
|  |       process.env.NODE_ENV !== 'production' && warn('Cannot find element: ' + selector); | ||
|  |     } | ||
|  |   } | ||
|  |   return el; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Check if a node is in the document. | ||
|  |  * Note: document.documentElement.contains should work here | ||
|  |  * but always returns false for comment nodes in phantomjs, | ||
|  |  * making unit tests difficult. This is fixed by doing the | ||
|  |  * contains() check on the node's parentNode instead of | ||
|  |  * the node itself. | ||
|  |  * | ||
|  |  * @param {Node} node | ||
|  |  * @return {Boolean} | ||
|  |  */ | ||
|  | 
 | ||
|  | function inDoc(node) { | ||
|  |   var doc = document.documentElement; | ||
|  |   var parent = node && node.parentNode; | ||
|  |   return doc === node || doc === parent || !!(parent && parent.nodeType === 1 && doc.contains(parent)); | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Get and remove an attribute from a node. | ||
|  |  * | ||
|  |  * @param {Node} node | ||
|  |  * @param {String} _attr | ||
|  |  */ | ||
|  | 
 | ||
|  | function getAttr(node, _attr) { | ||
|  |   var val = node.getAttribute(_attr); | ||
|  |   if (val !== null) { | ||
|  |     node.removeAttribute(_attr); | ||
|  |   } | ||
|  |   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 | ||
|  |  */ | ||
|  | 
 | ||
|  | function on$1(el, event, cb) { | ||
|  |   el.addEventListener(event, cb); | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Remove event listener shorthand. | ||
|  |  * | ||
|  |  * @param {Element} el | ||
|  |  * @param {String} event | ||
|  |  * @param {Function} cb | ||
|  |  */ | ||
|  | 
 | ||
|  | function off(el, event, cb) { | ||
|  |   el.removeEventListener(event, cb); | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * 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 && !(el instanceof SVGElement)) { | ||
|  |     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 = ' ' + (el.getAttribute('class') || '') + ' '; | ||
|  |     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 = ' ' + (el.getAttribute('class') || '') + ' '; | ||
|  |     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} | ||
|  |  */ | ||
|  | 
 | ||
|  | function extractContent(el, asFragment) { | ||
|  |   var child; | ||
|  |   var rawContent; | ||
|  |   /* istanbul ignore if */ | ||
|  |   if (isTemplate(el) && el.content instanceof DocumentFragment) { | ||
|  |     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 textNodes inside a parent. | ||
|  |  * | ||
|  |  * @param {Node} node | ||
|  |  */ | ||
|  | 
 | ||
|  | function trimNode(node) { | ||
|  |   trim(node, node.firstChild); | ||
|  |   trim(node, node.lastChild); | ||
|  | } | ||
|  | 
 | ||
|  | function trim(parent, node) { | ||
|  |   if (node && node.nodeType === 3 && !node.data.trim()) { | ||
|  |     parent.removeChild(node); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * 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.__vue_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(); | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | 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)$/; | ||
|  | var reservedTagRE = /^(slot|partial|component)$/; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Check if an element is a component, if yes return its | ||
|  |  * component id. | ||
|  |  * | ||
|  |  * @param {Element} el | ||
|  |  * @param {Object} options | ||
|  |  * @return {Object|undefined} | ||
|  |  */ | ||
|  | 
 | ||
|  | function checkComponentAttr(el, options) { | ||
|  |   var tag = el.tagName.toLowerCase(); | ||
|  |   var hasAttrs = el.hasAttributes(); | ||
|  |   if (!commonTagRE.test(tag) && !reservedTagRE.test(tag)) { | ||
|  |     if (resolveAsset(options, 'components', tag)) { | ||
|  |       return { id: tag }; | ||
|  |     } else { | ||
|  |       var is = hasAttrs && getIsBinding(el); | ||
|  |       if (is) { | ||
|  |         return is; | ||
|  |       } else if (process.env.NODE_ENV !== 'production') { | ||
|  |         if (tag.indexOf('-') > -1 || /HTMLUnknownElement/.test(el.toString()) && | ||
|  |         // Chrome returns unknown for several HTML5 elements.
 | ||
|  |         // https://code.google.com/p/chromium/issues/detail?id=540526
 | ||
|  |         !/^(data|time|rtc|rb)$/.test(tag)) { | ||
|  |           warn('Unknown custom element: <' + tag + '> - did you ' + 'register the component correctly?'); | ||
|  |         } | ||
|  |       } | ||
|  |     } | ||
|  |   } else if (hasAttrs) { | ||
|  |     return getIsBinding(el); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Get "is" binding from an element. | ||
|  |  * | ||
|  |  * @param {Element} el | ||
|  |  * @return {Object|undefined} | ||
|  |  */ | ||
|  | 
 | ||
|  | function getIsBinding(el) { | ||
|  |   // dynamic syntax
 | ||
|  |   var exp = getAttr(el, 'is'); | ||
|  |   if (exp != null) { | ||
|  |     return { id: exp }; | ||
|  |   } else { | ||
|  |     exp = getBindAttr(el, 'is'); | ||
|  |     if (exp != null) { | ||
|  |       return { id: exp, dynamic: true }; | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * 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) { | ||
|  |   var key = prop.path; | ||
|  |   value = coerceProp(prop, value); | ||
|  |   vm[key] = vm._data[key] = assertProp(prop, value) ? value : undefined; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Assert whether a prop is valid. | ||
|  |  * | ||
|  |  * @param {Object} prop | ||
|  |  * @param {*} value | ||
|  |  */ | ||
|  | 
 | ||
|  | function assertProp(prop, value) { | ||
|  |   // if a prop is not provided and is not required,
 | ||
|  |   // skip the check.
 | ||
|  |   if (prop.raw === null && !prop.required) { | ||
|  |     return true; | ||
|  |   } | ||
|  |   var options = prop.options; | ||
|  |   var type = options.type; | ||
|  |   var valid = true; | ||
|  |   var expectedType; | ||
|  |   if (type) { | ||
|  |     if (type === String) { | ||
|  |       expectedType = 'string'; | ||
|  |       valid = typeof value === expectedType; | ||
|  |     } else if (type === Number) { | ||
|  |       expectedType = 'number'; | ||
|  |       valid = typeof value === 'number'; | ||
|  |     } else if (type === Boolean) { | ||
|  |       expectedType = 'boolean'; | ||
|  |       valid = typeof value === 'boolean'; | ||
|  |     } else if (type === Function) { | ||
|  |       expectedType = 'function'; | ||
|  |       valid = typeof value === 'function'; | ||
|  |     } else if (type === Object) { | ||
|  |       expectedType = 'object'; | ||
|  |       valid = isPlainObject(value); | ||
|  |     } else if (type === Array) { | ||
|  |       expectedType = 'array'; | ||
|  |       valid = isArray(value); | ||
|  |     } else { | ||
|  |       valid = value instanceof type; | ||
|  |     } | ||
|  |   } | ||
|  |   if (!valid) { | ||
|  |     process.env.NODE_ENV !== 'production' && warn('Invalid prop: type check failed for ' + prop.path + '="' + prop.raw + '".' + ' Expected ' + formatType(expectedType) + ', got ' + formatValue(value) + '.'); | ||
|  |     return false; | ||
|  |   } | ||
|  |   var validator = options.validator; | ||
|  |   if (validator) { | ||
|  |     if (!validator.call(null, value)) { | ||
|  |       process.env.NODE_ENV !== 'production' && warn('Invalid prop: custom validator check failed for ' + prop.path + '="' + prop.raw + '"'); | ||
|  |       return false; | ||
|  |     } | ||
|  |   } | ||
|  |   return true; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Force parsing value with coerce option. | ||
|  |  * | ||
|  |  * @param {*} value | ||
|  |  * @param {Object} options | ||
|  |  * @return {*} | ||
|  |  */ | ||
|  | 
 | ||
|  | function coerceProp(prop, value) { | ||
|  |   var coerce = prop.options.coerce; | ||
|  |   if (!coerce) { | ||
|  |     return value; | ||
|  |   } | ||
|  |   // coerce is a function
 | ||
|  |   return coerce(value); | ||
|  | } | ||
|  | 
 | ||
|  | function formatType(val) { | ||
|  |   return val ? val.charAt(0).toUpperCase() + val.slice(1) : 'custom type'; | ||
|  | } | ||
|  | 
 | ||
|  | function formatValue(val) { | ||
|  |   return Object.prototype.toString.call(val).slice(8, -1); | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * 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') { | ||
|  |       process.env.NODE_ENV !== 'production' && warn('The "data" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.'); | ||
|  |       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') { | ||
|  |     process.env.NODE_ENV !== 'production' && warn('The "el" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.'); | ||
|  |     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 = function (parentVal, childVal) { | ||
|  |   return childVal ? parentVal ? parentVal.concat(childVal) : isArray(childVal) ? childVal : [childVal] : parentVal; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * 0.11 deprecation warning | ||
|  |  */ | ||
|  | 
 | ||
|  | strats.paramAttributes = function () { | ||
|  |   /* istanbul ignore next */ | ||
|  |   process.env.NODE_ENV !== 'production' && warn('"paramAttributes" option has been deprecated in 0.12. ' + 'Use "props" instead.'); | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Assets | ||
|  |  * | ||
|  |  * When a vm is present (instance creation), we need to do | ||
|  |  * a three-way merge between constructor options, instance | ||
|  |  * options and parent options. | ||
|  |  */ | ||
|  | 
 | ||
|  | function mergeAssets(parentVal, childVal) { | ||
|  |   var res = Object.create(parentVal); | ||
|  |   return childVal ? extend(res, guardArrayAssets(childVal)) : res; | ||
|  | } | ||
|  | 
 | ||
|  | config._assetTypes.forEach(function (type) { | ||
|  |   strats[type + 's'] = mergeAssets; | ||
|  | }); | ||
|  | 
 | ||
|  | /** | ||
|  |  * Events & Watchers. | ||
|  |  * | ||
|  |  * Events & watchers hashes should not overwrite one | ||
|  |  * another, so we merge them as arrays. | ||
|  |  */ | ||
|  | 
 | ||
|  | strats.watch = strats.events = function (parentVal, childVal) { | ||
|  |   if (!childVal) return parentVal; | ||
|  |   if (!parentVal) return childVal; | ||
|  |   var ret = {}; | ||
|  |   extend(ret, parentVal); | ||
|  |   for (var key in childVal) { | ||
|  |     var parent = ret[key]; | ||
|  |     var child = childVal[key]; | ||
|  |     if (parent && !isArray(parent)) { | ||
|  |       parent = [parent]; | ||
|  |     } | ||
|  |     ret[key] = parent ? parent.concat(child) : [child]; | ||
|  |   } | ||
|  |   return ret; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Other object hashes. | ||
|  |  */ | ||
|  | 
 | ||
|  | strats.props = strats.methods = strats.computed = function (parentVal, childVal) { | ||
|  |   if (!childVal) return parentVal; | ||
|  |   if (!parentVal) return childVal; | ||
|  |   var ret = Object.create(null); | ||
|  |   extend(ret, parentVal); | ||
|  |   extend(ret, childVal); | ||
|  |   return ret; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * 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 def; | ||
|  |     var ids = Object.keys(components); | ||
|  |     for (var i = 0, l = ids.length; i < l; i++) { | ||
|  |       var key = ids[i]; | ||
|  |       if (commonTagRE.test(key) || reservedTagRE.test(key)) { | ||
|  |         process.env.NODE_ENV !== 'production' && warn('Do not use built-in or reserved HTML elements as component ' + 'id: ' + key); | ||
|  |         continue; | ||
|  |       } | ||
|  |       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) { | ||
|  |         process.env.NODE_ENV !== '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); | ||
|  |   var options = {}; | ||
|  |   var key; | ||
|  |   if (child.mixins) { | ||
|  |     for (var i = 0, l = child.mixins.length; i < l; i++) { | ||
|  |       parent = mergeOptions(parent, child.mixins[i], vm); | ||
|  |     } | ||
|  |   } | ||
|  |   for (key in parent) { | ||
|  |     mergeField(key); | ||
|  |   } | ||
|  |   for (key in child) { | ||
|  |     if (!hasOwn(parent, key)) { | ||
|  |       mergeField(key); | ||
|  |     } | ||
|  |   } | ||
|  |   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 | ||
|  |  * @return {Object|Function} | ||
|  |  */ | ||
|  | 
 | ||
|  | function resolveAsset(options, type, id) { | ||
|  |   var assets = options[type]; | ||
|  |   var camelizedId; | ||
|  |   return assets[id] || | ||
|  |   // camelCase ID
 | ||
|  |   assets[camelizedId = camelize(id)] || | ||
|  |   // Pascal Case ID
 | ||
|  |   assets[camelizedId.charAt(0).toUpperCase() + camelizedId.slice(1)]; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Assert asset exists | ||
|  |  */ | ||
|  | 
 | ||
|  | function assertAsset(val, type, id) { | ||
|  |   if (!val) { | ||
|  |     process.env.NODE_ENV !== 'production' && warn('Failed to resolve ' + type + ': ' + id); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | 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. | ||
|  |  * | ||
|  |  * @param {Number} index | ||
|  |  * @param {*} val | ||
|  |  */ | ||
|  | 
 | ||
|  | 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 uid$3 = 0; | ||
|  | 
 | ||
|  | /** | ||
|  |  * A dep is an observable that can have multiple | ||
|  |  * directives subscribing to it. | ||
|  |  * | ||
|  |  * @constructor | ||
|  |  */ | ||
|  | function Dep() { | ||
|  |   this.id = uid$3++; | ||
|  |   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 arrayKeys = Object.getOwnPropertyNames(arrayMethods); | ||
|  | 
 | ||
|  | /** | ||
|  |  * 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} proto | ||
|  |  */ | ||
|  | 
 | ||
|  | function protoAugment(target, src) { | ||
|  |   target.__proto__ = src; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * 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 ((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(); | ||
|  | 
 | ||
|  |   // cater for pre-defined getter/setters
 | ||
|  |   var getter, setter; | ||
|  |   if (config.convertAllProperties) { | ||
|  |     var property = Object.getOwnPropertyDescriptor(obj, key); | ||
|  |     if (property && property.configurable === false) { | ||
|  |       return; | ||
|  |     } | ||
|  |     getter = property && property.get; | ||
|  |     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$1, | ||
|  | 	toArray: toArray, | ||
|  | 	extend: extend, | ||
|  | 	isObject: isObject, | ||
|  | 	isPlainObject: isPlainObject, | ||
|  | 	def: def, | ||
|  | 	debounce: _debounce, | ||
|  | 	indexOf: indexOf, | ||
|  | 	cancellable: cancellable, | ||
|  | 	looseEqual: looseEqual, | ||
|  | 	isArray: isArray, | ||
|  | 	hasProto: hasProto, | ||
|  | 	inBrowser: inBrowser, | ||
|  | 	isIE9: isIE9, | ||
|  | 	isAndroid: isAndroid, | ||
|  | 	get transitionProp () { return transitionProp; }, | ||
|  | 	get transitionEndEvent () { return transitionEndEvent; }, | ||
|  | 	get animationProp () { return animationProp; }, | ||
|  | 	get animationEndEvent () { return animationEndEvent; }, | ||
|  | 	nextTick: nextTick, | ||
|  | 	query: query, | ||
|  | 	inDoc: inDoc, | ||
|  | 	getAttr: getAttr, | ||
|  | 	getBindAttr: getBindAttr, | ||
|  | 	hasBindAttr: hasBindAttr, | ||
|  | 	before: before, | ||
|  | 	after: after, | ||
|  | 	remove: remove, | ||
|  | 	prepend: prepend, | ||
|  | 	replace: replace, | ||
|  | 	on: on$1, | ||
|  | 	off: off, | ||
|  | 	setClass: setClass, | ||
|  | 	addClass: addClass, | ||
|  | 	removeClass: removeClass, | ||
|  | 	extractContent: extractContent, | ||
|  | 	trimNode: trimNode, | ||
|  | 	isTemplate: isTemplate, | ||
|  | 	createAnchor: createAnchor, | ||
|  | 	findRef: findRef, | ||
|  | 	mapNodeRange: mapNodeRange, | ||
|  | 	removeNodeRange: removeNodeRange, | ||
|  | 	mergeOptions: mergeOptions, | ||
|  | 	resolveAsset: resolveAsset, | ||
|  | 	assertAsset: assertAsset, | ||
|  | 	checkComponentAttr: checkComponentAttr, | ||
|  | 	initProp: initProp, | ||
|  | 	assertProp: assertProp, | ||
|  | 	coerceProp: coerceProp, | ||
|  | 	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 = false; | ||
|  |     this._unlinkFn = null; | ||
|  | 
 | ||
|  |     // context:
 | ||
|  |     // if this is a transcluded component, context
 | ||
|  |     // will be the common parent vm of this instance
 | ||
|  |     // and its host.
 | ||
|  |     this._context = options._context || this.$parent; | ||
|  | 
 | ||
|  |     // scope:
 | ||
|  |     // if this is inside an inline v-for, the scope
 | ||
|  |     // will be the intermediate scope created for this
 | ||
|  |     // repeat fragment. this is used for linking props
 | ||
|  |     // and container directives.
 | ||
|  |     this._scope = options._scope; | ||
|  | 
 | ||
|  |     // fragment:
 | ||
|  |     // if this instance is compiled inside a Fragment, it
 | ||
|  |     // needs to reigster itself as a child of that fragment
 | ||
|  |     // for attach/detach to work properly.
 | ||
|  |     this._frag = options._frag; | ||
|  |     if (this._frag) { | ||
|  |       this._frag.children.push(this); | ||
|  |     } | ||
|  | 
 | ||
|  |     // push self into parent / transclusion host
 | ||
|  |     if (this.$parent) { | ||
|  |       this.$parent.$children.push(this); | ||
|  |     } | ||
|  | 
 | ||
|  |     // merge options.
 | ||
|  |     options = this.$options = mergeOptions(this.constructor.options, options, this); | ||
|  | 
 | ||
|  |     // set ref
 | ||
|  |     this._updateRef(); | ||
|  | 
 | ||
|  |     // initialize data as empty object.
 | ||
|  |     // it will be filled up in _initScope().
 | ||
|  |     this._data = {}; | ||
|  | 
 | ||
|  |     // call init hook
 | ||
|  |     this._callHook('init'); | ||
|  | 
 | ||
|  |     // initialize data observation and scope inheritance.
 | ||
|  |     this._initState(); | ||
|  | 
 | ||
|  |     // setup event system and option events.
 | ||
|  |     this._initEvents(); | ||
|  | 
 | ||
|  |     // call created hook
 | ||
|  |     this._callHook('created'); | ||
|  | 
 | ||
|  |     // if `el` option is passed, start compilation.
 | ||
|  |     if (options.el) { | ||
|  |       this.$mount(options.el); | ||
|  |     } | ||
|  |   }; | ||
|  | } | ||
|  | 
 | ||
|  | var pathCache = new Cache(1000); | ||
|  | 
 | ||
|  | // actions
 | ||
|  | var APPEND = 0; | ||
|  | var PUSH = 1; | ||
|  | var INC_SUB_PATH_DEPTH = 2; | ||
|  | var PUSH_SUB_PATH = 3; | ||
|  | 
 | ||
|  | // states
 | ||
|  | var BEFORE_PATH = 0; | ||
|  | var IN_PATH = 1; | ||
|  | var BEFORE_IDENT = 2; | ||
|  | var IN_IDENT = 3; | ||
|  | var IN_SUB_PATH = 4; | ||
|  | var IN_SINGLE_QUOTE = 5; | ||
|  | var IN_DOUBLE_QUOTE = 6; | ||
|  | var AFTER_PATH = 7; | ||
|  | var ERROR = 8; | ||
|  | 
 | ||
|  | var pathStateMachine = []; | ||
|  | 
 | ||
|  | pathStateMachine[BEFORE_PATH] = { | ||
|  |   'ws': [BEFORE_PATH], | ||
|  |   'ident': [IN_IDENT, APPEND], | ||
|  |   '[': [IN_SUB_PATH], | ||
|  |   'eof': [AFTER_PATH] | ||
|  | }; | ||
|  | 
 | ||
|  | pathStateMachine[IN_PATH] = { | ||
|  |   'ws': [IN_PATH], | ||
|  |   '.': [BEFORE_IDENT], | ||
|  |   '[': [IN_SUB_PATH], | ||
|  |   'eof': [AFTER_PATH] | ||
|  | }; | ||
|  | 
 | ||
|  | pathStateMachine[BEFORE_IDENT] = { | ||
|  |   'ws': [BEFORE_IDENT], | ||
|  |   'ident': [IN_IDENT, APPEND] | ||
|  | }; | ||
|  | 
 | ||
|  | pathStateMachine[IN_IDENT] = { | ||
|  |   'ident': [IN_IDENT, APPEND], | ||
|  |   '0': [IN_IDENT, APPEND], | ||
|  |   'number': [IN_IDENT, APPEND], | ||
|  |   'ws': [IN_PATH, PUSH], | ||
|  |   '.': [BEFORE_IDENT, PUSH], | ||
|  |   '[': [IN_SUB_PATH, PUSH], | ||
|  |   'eof': [AFTER_PATH, PUSH] | ||
|  | }; | ||
|  | 
 | ||
|  | pathStateMachine[IN_SUB_PATH] = { | ||
|  |   "'": [IN_SINGLE_QUOTE, APPEND], | ||
|  |   '"': [IN_DOUBLE_QUOTE, APPEND], | ||
|  |   '[': [IN_SUB_PATH, INC_SUB_PATH_DEPTH], | ||
|  |   ']': [IN_PATH, PUSH_SUB_PATH], | ||
|  |   'eof': ERROR, | ||
|  |   'else': [IN_SUB_PATH, APPEND] | ||
|  | }; | ||
|  | 
 | ||
|  | pathStateMachine[IN_SINGLE_QUOTE] = { | ||
|  |   "'": [IN_SUB_PATH, APPEND], | ||
|  |   'eof': ERROR, | ||
|  |   'else': [IN_SINGLE_QUOTE, APPEND] | ||
|  | }; | ||
|  | 
 | ||
|  | pathStateMachine[IN_DOUBLE_QUOTE] = { | ||
|  |   '"': [IN_SUB_PATH, APPEND], | ||
|  |   'eof': ERROR, | ||
|  |   'else': [IN_DOUBLE_QUOTE, APPEND] | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Determine the type of a character in a keypath. | ||
|  |  * | ||
|  |  * @param {Char} ch | ||
|  |  * @return {String} type | ||
|  |  */ | ||
|  | 
 | ||
|  | function getPathCharType(ch) { | ||
|  |   if (ch === undefined) { | ||
|  |     return 'eof'; | ||
|  |   } | ||
|  | 
 | ||
|  |   var code = ch.charCodeAt(0); | ||
|  | 
 | ||
|  |   switch (code) { | ||
|  |     case 0x5B: // [
 | ||
|  |     case 0x5D: // ]
 | ||
|  |     case 0x2E: // .
 | ||
|  |     case 0x22: // "
 | ||
|  |     case 0x27: // '
 | ||
|  |     case 0x30: | ||
|  |       // 0
 | ||
|  |       return ch; | ||
|  | 
 | ||
|  |     case 0x5F: // _
 | ||
|  |     case 0x24: | ||
|  |       // $
 | ||
|  |       return 'ident'; | ||
|  | 
 | ||
|  |     case 0x20: // Space
 | ||
|  |     case 0x09: // Tab
 | ||
|  |     case 0x0A: // Newline
 | ||
|  |     case 0x0D: // Return
 | ||
|  |     case 0xA0: // No-break space
 | ||
|  |     case 0xFEFF: // Byte Order Mark
 | ||
|  |     case 0x2028: // Line Separator
 | ||
|  |     case 0x2029: | ||
|  |       // Paragraph Separator
 | ||
|  |       return 'ws'; | ||
|  |   } | ||
|  | 
 | ||
|  |   // a-z, A-Z
 | ||
|  |   if (code >= 0x61 && code <= 0x7A || code >= 0x41 && code <= 0x5A) { | ||
|  |     return 'ident'; | ||
|  |   } | ||
|  | 
 | ||
|  |   // 1-9
 | ||
|  |   if (code >= 0x31 && code <= 0x39) { | ||
|  |     return 'number'; | ||
|  |   } | ||
|  | 
 | ||
|  |   return 'else'; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Format a subPath, return its plain form if it is | ||
|  |  * a literal string or number. Otherwise prepend the | ||
|  |  * dynamic indicator (*). | ||
|  |  * | ||
|  |  * @param {String} path | ||
|  |  * @return {String} | ||
|  |  */ | ||
|  | 
 | ||
|  | function formatSubPath(path) { | ||
|  |   var trimmed = path.trim(); | ||
|  |   // invalid leading 0
 | ||
|  |   if (path.charAt(0) === '0' && isNaN(path)) { | ||
|  |     return false; | ||
|  |   } | ||
|  |   return isLiteral(trimmed) ? stripQuotes(trimmed) : '*' + trimmed; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Parse a string path into an array of segments | ||
|  |  * | ||
|  |  * @param {String} path | ||
|  |  * @return {Array|undefined} | ||
|  |  */ | ||
|  | 
 | ||
|  | function parse(path) { | ||
|  |   var keys = []; | ||
|  |   var index = -1; | ||
|  |   var mode = BEFORE_PATH; | ||
|  |   var subPathDepth = 0; | ||
|  |   var c, newChar, key, type, transition, action, typeMap; | ||
|  | 
 | ||
|  |   var actions = []; | ||
|  | 
 | ||
|  |   actions[PUSH] = function () { | ||
|  |     if (key !== undefined) { | ||
|  |       keys.push(key); | ||
|  |       key = undefined; | ||
|  |     } | ||
|  |   }; | ||
|  | 
 | ||
|  |   actions[APPEND] = function () { | ||
|  |     if (key === undefined) { | ||
|  |       key = newChar; | ||
|  |     } else { | ||
|  |       key += newChar; | ||
|  |     } | ||
|  |   }; | ||
|  | 
 | ||
|  |   actions[INC_SUB_PATH_DEPTH] = function () { | ||
|  |     actions[APPEND](); | ||
|  |     subPathDepth++; | ||
|  |   }; | ||
|  | 
 | ||
|  |   actions[PUSH_SUB_PATH] = function () { | ||
|  |     if (subPathDepth > 0) { | ||
|  |       subPathDepth--; | ||
|  |       mode = IN_SUB_PATH; | ||
|  |       actions[APPEND](); | ||
|  |     } else { | ||
|  |       subPathDepth = 0; | ||
|  |       key = formatSubPath(key); | ||
|  |       if (key === false) { | ||
|  |         return false; | ||
|  |       } else { | ||
|  |         actions[PUSH](); | ||
|  |       } | ||
|  |     } | ||
|  |   }; | ||
|  | 
 | ||
|  |   function maybeUnescapeQuote() { | ||
|  |     var nextChar = path[index + 1]; | ||
|  |     if (mode === IN_SINGLE_QUOTE && nextChar === "'" || mode === IN_DOUBLE_QUOTE && nextChar === '"') { | ||
|  |       index++; | ||
|  |       newChar = '\\' + nextChar; | ||
|  |       actions[APPEND](); | ||
|  |       return true; | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   while (mode != null) { | ||
|  |     index++; | ||
|  |     c = path[index]; | ||
|  | 
 | ||
|  |     if (c === '\\' && maybeUnescapeQuote()) { | ||
|  |       continue; | ||
|  |     } | ||
|  | 
 | ||
|  |     type = getPathCharType(c); | ||
|  |     typeMap = pathStateMachine[mode]; | ||
|  |     transition = typeMap[type] || typeMap['else'] || ERROR; | ||
|  | 
 | ||
|  |     if (transition === ERROR) { | ||
|  |       return; // parse error
 | ||
|  |     } | ||
|  | 
 | ||
|  |     mode = transition[0]; | ||
|  |     action = actions[transition[1]]; | ||
|  |     if (action) { | ||
|  |       newChar = transition[2]; | ||
|  |       newChar = newChar === undefined ? c : newChar; | ||
|  |       if (action() === false) { | ||
|  |         return; | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     if (mode === AFTER_PATH) { | ||
|  |       keys.raw = path; | ||
|  |       return keys; | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * External parse that check for a cache hit first | ||
|  |  * | ||
|  |  * @param {String} path | ||
|  |  * @return {Array|undefined} | ||
|  |  */ | ||
|  | 
 | ||
|  | function parsePath(path) { | ||
|  |   var hit = pathCache.get(path); | ||
|  |   if (!hit) { | ||
|  |     hit = parse(path); | ||
|  |     if (hit) { | ||
|  |       pathCache.put(path, hit); | ||
|  |     } | ||
|  |   } | ||
|  |   return hit; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Get from an object from a path string | ||
|  |  * | ||
|  |  * @param {Object} obj | ||
|  |  * @param {String} path | ||
|  |  */ | ||
|  | 
 | ||
|  | function getPath(obj, path) { | ||
|  |   return parseExpression(path).get(obj); | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Warn against setting non-existent root path on a vm. | ||
|  |  */ | ||
|  | 
 | ||
|  | var warnNonExistent; | ||
|  | if (process.env.NODE_ENV !== 'production') { | ||
|  |   warnNonExistent = function (path) { | ||
|  |     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.'); | ||
|  |   }; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Set on an object from a path | ||
|  |  * | ||
|  |  * @param {Object} obj | ||
|  |  * @param {String | Array} path | ||
|  |  * @param {*} val | ||
|  |  */ | ||
|  | 
 | ||
|  | function setPath(obj, path, val) { | ||
|  |   var original = obj; | ||
|  |   if (typeof path === 'string') { | ||
|  |     path = parse(path); | ||
|  |   } | ||
|  |   if (!path || !isObject(obj)) { | ||
|  |     return false; | ||
|  |   } | ||
|  |   var last, key; | ||
|  |   for (var i = 0, l = path.length; i < l; i++) { | ||
|  |     last = obj; | ||
|  |     key = path[i]; | ||
|  |     if (key.charAt(0) === '*') { | ||
|  |       key = parseExpression(key.slice(1)).get.call(original, original); | ||
|  |     } | ||
|  |     if (i < l - 1) { | ||
|  |       obj = obj[key]; | ||
|  |       if (!isObject(obj)) { | ||
|  |         obj = {}; | ||
|  |         if (process.env.NODE_ENV !== 'production' && last._isVue) { | ||
|  |           warnNonExistent(path); | ||
|  |         } | ||
|  |         set(last, key, obj); | ||
|  |       } | ||
|  |     } else { | ||
|  |       if (isArray(obj)) { | ||
|  |         obj.$set(key, val); | ||
|  |       } else if (key in obj) { | ||
|  |         obj[key] = val; | ||
|  |       } else { | ||
|  |         if (process.env.NODE_ENV !== 'production' && obj._isVue) { | ||
|  |           warnNonExistent(path); | ||
|  |         } | ||
|  |         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,' + 'proctected,static,interface,private,public'; | ||
|  | var improperKeywordsRE = new RegExp('^(' + improperKeywords.replace(/,/g, '\\b|') + '\\b)'); | ||
|  | 
 | ||
|  | var wsRE = /\s/g; | ||
|  | var newlineRE = /\n/g; | ||
|  | var saveRE = /[\{,]\s*[\w\$_]+\s*:|('(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*")|new |typeof |void /g; | ||
|  | var restoreRE = /"(\d+)"/g; | ||
|  | var pathTestRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['.*?'\]|\[".*?"\]|\[\d+\]|\[[A-Za-z_$][\w$]*\])*$/; | ||
|  | var identRE = /[^\w$\.](?:[A-Za-z_$][\w$]*)/g; | ||
|  | var booleanLiteralRE = /^(?:true|false)$/; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Save / Rewrite / Restore | ||
|  |  * | ||
|  |  * When rewriting paths found in an expression, it is | ||
|  |  * possible for the same letter sequences to be found in | ||
|  |  * strings and Object literal property keys. Therefore we | ||
|  |  * remove and store these parts in a temporary array, and | ||
|  |  * restore them after the path rewrite. | ||
|  |  */ | ||
|  | 
 | ||
|  | var saved = []; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Save replacer | ||
|  |  * | ||
|  |  * The save regex can match two possible cases: | ||
|  |  * 1. An opening object literal | ||
|  |  * 2. A string | ||
|  |  * If matched as a plain string, we need to escape its | ||
|  |  * newlines, since the string needs to be preserved when | ||
|  |  * generating the function body. | ||
|  |  * | ||
|  |  * @param {String} str | ||
|  |  * @param {String} isString - str if matched as a string | ||
|  |  * @return {String} - placeholder with index | ||
|  |  */ | ||
|  | 
 | ||
|  | function save(str, isString) { | ||
|  |   var i = saved.length; | ||
|  |   saved[i] = isString ? str.replace(newlineRE, '\\n') : str; | ||
|  |   return '"' + i + '"'; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Path rewrite replacer | ||
|  |  * | ||
|  |  * @param {String} raw | ||
|  |  * @return {String} | ||
|  |  */ | ||
|  | 
 | ||
|  | function rewrite(raw) { | ||
|  |   var c = raw.charAt(0); | ||
|  |   var path = raw.slice(1); | ||
|  |   if (allowedKeywordsRE.test(path)) { | ||
|  |     return raw; | ||
|  |   } else { | ||
|  |     path = path.indexOf('"') > -1 ? path.replace(restoreRE, restore) : path; | ||
|  |     return c + 'scope.' + path; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Restore replacer | ||
|  |  * | ||
|  |  * @param {String} str | ||
|  |  * @param {String} i - matched save index | ||
|  |  * @return {String} | ||
|  |  */ | ||
|  | 
 | ||
|  | function restore(str, i) { | ||
|  |   return saved[i]; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Rewrite an expression, prefixing all path accessors with | ||
|  |  * `scope.` and generate getter/setter functions. | ||
|  |  * | ||
|  |  * @param {String} exp | ||
|  |  * @return {Function} | ||
|  |  */ | ||
|  | 
 | ||
|  | function compileGetter(exp) { | ||
|  |   if (improperKeywordsRE.test(exp)) { | ||
|  |     process.env.NODE_ENV !== 'production' && warn('Avoid using reserved keywords in expression: ' + exp); | ||
|  |   } | ||
|  |   // reset state
 | ||
|  |   saved.length = 0; | ||
|  |   // save strings and object literal keys
 | ||
|  |   var body = exp.replace(saveRE, save).replace(wsRE, ''); | ||
|  |   // rewrite all paths
 | ||
|  |   // pad 1 space here becaue the regex matches 1 extra char
 | ||
|  |   body = (' ' + body).replace(identRE, rewrite).replace(restoreRE, restore); | ||
|  |   return makeGetterFn(body); | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Build a getter function. Requires eval. | ||
|  |  * | ||
|  |  * We isolate the try/catch so it doesn't affect the | ||
|  |  * optimization of the parse function when it is not called. | ||
|  |  * | ||
|  |  * @param {String} body | ||
|  |  * @return {Function|undefined} | ||
|  |  */ | ||
|  | 
 | ||
|  | function makeGetterFn(body) { | ||
|  |   try { | ||
|  |     return new Function('scope', 'return ' + body + ';'); | ||
|  |   } catch (e) { | ||
|  |     process.env.NODE_ENV !== 'production' && warn('Invalid expression. ' + 'Generated function body: ' + body); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Compile a setter function for the expression. | ||
|  |  * | ||
|  |  * @param {String} exp | ||
|  |  * @return {Function|undefined} | ||
|  |  */ | ||
|  | 
 | ||
|  | function compileSetter(exp) { | ||
|  |   var path = parsePath(exp); | ||
|  |   if (path) { | ||
|  |     return function (scope, val) { | ||
|  |       setPath(scope, path, val); | ||
|  |     }; | ||
|  |   } else { | ||
|  |     process.env.NODE_ENV !== 'production' && warn('Invalid setter expression: ' + exp); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Parse an expression into re-written getter/setters. | ||
|  |  * | ||
|  |  * @param {String} exp | ||
|  |  * @param {Boolean} needSet | ||
|  |  * @return {Function} | ||
|  |  */ | ||
|  | 
 | ||
|  | function parseExpression(exp, needSet) { | ||
|  |   exp = exp.trim(); | ||
|  |   // try cache
 | ||
|  |   var hit = expressionCache.get(exp); | ||
|  |   if (hit) { | ||
|  |     if (needSet && !hit.set) { | ||
|  |       hit.set = compileSetter(hit.exp); | ||
|  |     } | ||
|  |     return hit; | ||
|  |   } | ||
|  |   var res = { exp: exp }; | ||
|  |   res.get = isSimplePath(exp) && exp.indexOf('[') < 0 | ||
|  |   // optimized super simple getter
 | ||
|  |   ? makeGetterFn('scope.' + exp) | ||
|  |   // dynamic getter
 | ||
|  |   : compileGetter(exp); | ||
|  |   if (needSet) { | ||
|  |     res.set = compileSetter(exp); | ||
|  |   } | ||
|  |   expressionCache.put(exp, res); | ||
|  |   return res; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Check if an expression is a simple path. | ||
|  |  * | ||
|  |  * @param {String} exp | ||
|  |  * @return {Boolean} | ||
|  |  */ | ||
|  | 
 | ||
|  | function isSimplePath(exp) { | ||
|  |   return pathTestRE.test(exp) && | ||
|  |   // don't treat true/false as paths
 | ||
|  |   !booleanLiteralRE.test(exp) && | ||
|  |   // Math constants e.g. Math.PI, Math.E etc.
 | ||
|  |   exp.slice(0, 5) !== 'Math.'; | ||
|  | } | ||
|  | 
 | ||
|  | var expression = Object.freeze({ | ||
|  |   parseExpression: parseExpression, | ||
|  |   isSimplePath: isSimplePath | ||
|  | }); | ||
|  | 
 | ||
|  | // we have two separate queues: one for directive updates
 | ||
|  | // and one for user watcher registered via $watch().
 | ||
|  | // we want to guarantee directive updates to be called
 | ||
|  | // before user watchers so that when user watchers are
 | ||
|  | // triggered, the DOM would have already been in updated
 | ||
|  | // state.
 | ||
|  | var queue = []; | ||
|  | var userQueue = []; | ||
|  | var has = {}; | ||
|  | var circular = {}; | ||
|  | var waiting = false; | ||
|  | var internalQueueDepleted = false; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Reset the batcher's state. | ||
|  |  */ | ||
|  | 
 | ||
|  | function resetBatcherState() { | ||
|  |   queue = []; | ||
|  |   userQueue = []; | ||
|  |   has = {}; | ||
|  |   circular = {}; | ||
|  |   waiting = internalQueueDepleted = false; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Flush both queues and run the watchers. | ||
|  |  */ | ||
|  | 
 | ||
|  | function flushBatcherQueue() { | ||
|  |   runBatcherQueue(queue); | ||
|  |   internalQueueDepleted = true; | ||
|  |   runBatcherQueue(userQueue); | ||
|  |   // dev tool hook
 | ||
|  |   /* istanbul ignore if */ | ||
|  |   if (process.env.NODE_ENV !== 'production') { | ||
|  |     if (inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__) { | ||
|  |       window.__VUE_DEVTOOLS_GLOBAL_HOOK__.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 (process.env.NODE_ENV !== 'production' && has[id] != null) { | ||
|  |       circular[id] = (circular[id] || 0) + 1; | ||
|  |       if (circular[id] > config._maxUpdateCount) { | ||
|  |         queue.splice(has[id], 1); | ||
|  |         warn('You may have an infinite update loop for watcher ' + 'with expression: ' + watcher.expression); | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Push a watcher into the watcher queue. | ||
|  |  * Jobs with duplicate IDs will be skipped unless it's | ||
|  |  * pushed when the queue is being flushed. | ||
|  |  * | ||
|  |  * @param {Watcher} watcher | ||
|  |  *   properties: | ||
|  |  *   - {Number} id | ||
|  |  *   - {Function} run | ||
|  |  */ | ||
|  | 
 | ||
|  | function pushWatcher(watcher) { | ||
|  |   var id = watcher.id; | ||
|  |   if (has[id] == null) { | ||
|  |     // if an internal watcher is pushed, but the internal
 | ||
|  |     // queue is already depleted, we run it immediately.
 | ||
|  |     if (internalQueueDepleted && !watcher.user) { | ||
|  |       watcher.run(); | ||
|  |       return; | ||
|  |     } | ||
|  |     // 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} expression | ||
|  |  * @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 = isFn ? expOrFn.toString() : expOrFn; | ||
|  |   this.cb = cb; | ||
|  |   this.id = ++uid$2; // uid for batching
 | ||
|  |   this.active = true; | ||
|  |   this.dirty = this.lazy; // for lazy watchers
 | ||
|  |   this.deps = Object.create(null); | ||
|  |   this.newDeps = null; | ||
|  |   this.prevError = null; // for async error stacks
 | ||
|  |   // parse expression for getter/setter
 | ||
|  |   if (isFn) { | ||
|  |     this.getter = expOrFn; | ||
|  |     this.setter = undefined; | ||
|  |   } else { | ||
|  |     var res = parseExpression(expOrFn, this.twoWay); | ||
|  |     this.getter = res.get; | ||
|  |     this.setter = res.set; | ||
|  |   } | ||
|  |   this.value = this.lazy ? undefined : this.get(); | ||
|  |   // state for avoiding false triggers for deep and Array
 | ||
|  |   // watchers during vm._digest()
 | ||
|  |   this.queued = this.shallow = false; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Add a dependency to this directive. | ||
|  |  * | ||
|  |  * @param {Dep} dep | ||
|  |  */ | ||
|  | 
 | ||
|  | Watcher.prototype.addDep = function (dep) { | ||
|  |   var id = dep.id; | ||
|  |   if (!this.newDeps[id]) { | ||
|  |     this.newDeps[id] = dep; | ||
|  |     if (!this.deps[id]) { | ||
|  |       this.deps[id] = dep; | ||
|  |       dep.addSub(this); | ||
|  |     } | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Evaluate the getter, and re-collect dependencies. | ||
|  |  */ | ||
|  | 
 | ||
|  | Watcher.prototype.get = function () { | ||
|  |   this.beforeGet(); | ||
|  |   var scope = this.scope || this.vm; | ||
|  |   var value; | ||
|  |   try { | ||
|  |     value = this.getter.call(scope, scope); | ||
|  |   } catch (e) { | ||
|  |     if (process.env.NODE_ENV !== 'production' && config.warnExpressionErrors) { | ||
|  |       warn('Error when evaluating expression "' + this.expression + '". ' + (config.debug ? '' : 'Turn on debug mode to see stack trace.'), e); | ||
|  |     } | ||
|  |   } | ||
|  |   // "touch" every property so they are all tracked as
 | ||
|  |   // dependencies for deep watching
 | ||
|  |   if (this.deep) { | ||
|  |     traverse(value); | ||
|  |   } | ||
|  |   if (this.preProcess) { | ||
|  |     value = this.preProcess(value); | ||
|  |   } | ||
|  |   if (this.filters) { | ||
|  |     value = scope._applyFilters(value, null, this.filters, false); | ||
|  |   } | ||
|  |   if (this.postProcess) { | ||
|  |     value = this.postProcess(value); | ||
|  |   } | ||
|  |   this.afterGet(); | ||
|  |   return value; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Set the corresponding value with the setter. | ||
|  |  * | ||
|  |  * @param {*} value | ||
|  |  */ | ||
|  | 
 | ||
|  | Watcher.prototype.set = function (value) { | ||
|  |   var scope = this.scope || this.vm; | ||
|  |   if (this.filters) { | ||
|  |     value = scope._applyFilters(value, this.value, this.filters, true); | ||
|  |   } | ||
|  |   try { | ||
|  |     this.setter.call(scope, scope, value); | ||
|  |   } catch (e) { | ||
|  |     if (process.env.NODE_ENV !== 'production' && config.warnExpressionErrors) { | ||
|  |       warn('Error when evaluating setter "' + this.expression + '"', e); | ||
|  |     } | ||
|  |   } | ||
|  |   // two-way sync for v-for alias
 | ||
|  |   var forContext = scope.$forContext; | ||
|  |   if (forContext && forContext.alias === this.expression) { | ||
|  |     if (forContext.filters) { | ||
|  |       process.env.NODE_ENV !== 'production' && warn('It seems you are using two-way binding on ' + 'a v-for alias (' + this.expression + '), and the ' + 'v-for has filters. This will not work properly. ' + 'Either remove the filters or use an array of ' + 'objects and bind to object properties instead.'); | ||
|  |       return; | ||
|  |     } | ||
|  |     forContext._withLock(function () { | ||
|  |       if (scope.$key) { | ||
|  |         // original is an object
 | ||
|  |         forContext.rawValue[scope.$key] = value; | ||
|  |       } else { | ||
|  |         forContext.rawValue.$set(scope.$index, value); | ||
|  |       } | ||
|  |     }); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Prepare for dependency collection. | ||
|  |  */ | ||
|  | 
 | ||
|  | Watcher.prototype.beforeGet = function () { | ||
|  |   Dep.target = this; | ||
|  |   this.newDeps = Object.create(null); | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Clean up for dependency collection. | ||
|  |  */ | ||
|  | 
 | ||
|  | Watcher.prototype.afterGet = function () { | ||
|  |   Dep.target = null; | ||
|  |   var ids = Object.keys(this.deps); | ||
|  |   var i = ids.length; | ||
|  |   while (i--) { | ||
|  |     var id = ids[i]; | ||
|  |     if (!this.newDeps[id]) { | ||
|  |       this.deps[id].removeSub(this); | ||
|  |     } | ||
|  |   } | ||
|  |   this.deps = this.newDeps; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Subscriber interface. | ||
|  |  * Will be called when a dependency changes. | ||
|  |  * | ||
|  |  * @param {Boolean} shallow | ||
|  |  */ | ||
|  | 
 | ||
|  | Watcher.prototype.update = function (shallow) { | ||
|  |   if (this.lazy) { | ||
|  |     this.dirty = true; | ||
|  |   } else if (this.sync || !config.async) { | ||
|  |     this.run(); | ||
|  |   } else { | ||
|  |     // if queued, only overwrite shallow with non-shallow,
 | ||
|  |     // but not the other way around.
 | ||
|  |     this.shallow = this.queued ? shallow ? this.shallow : false : !!shallow; | ||
|  |     this.queued = true; | ||
|  |     // record before-push error stack in debug mode
 | ||
|  |     /* istanbul ignore if */ | ||
|  |     if (process.env.NODE_ENV !== 'production' && config.debug) { | ||
|  |       this.prevError = new Error('[vue] async stack trace'); | ||
|  |     } | ||
|  |     pushWatcher(this); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Batcher job interface. | ||
|  |  * Will be called by the batcher. | ||
|  |  */ | ||
|  | 
 | ||
|  | Watcher.prototype.run = function () { | ||
|  |   if (this.active) { | ||
|  |     var value = this.get(); | ||
|  |     if (value !== this.value || | ||
|  |     // Deep watchers and watchers on Object/Arrays should fire even
 | ||
|  |     // when the value is the same, because the value may
 | ||
|  |     // have mutated; but only do so if this is a
 | ||
|  |     // non-shallow update (caused by a vm digest).
 | ||
|  |     (isObject(value) || this.deep) && !this.shallow) { | ||
|  |       // set new value
 | ||
|  |       var oldValue = this.value; | ||
|  |       this.value = value; | ||
|  |       // in debug + async mode, when a watcher callbacks
 | ||
|  |       // throws, we also throw the saved before-push error
 | ||
|  |       // so the full cross-tick stack trace is available.
 | ||
|  |       var prevError = this.prevError; | ||
|  |       /* istanbul ignore if */ | ||
|  |       if (process.env.NODE_ENV !== 'production' && config.debug && prevError) { | ||
|  |         this.prevError = null; | ||
|  |         try { | ||
|  |           this.cb.call(this.vm, value, oldValue); | ||
|  |         } catch (e) { | ||
|  |           nextTick(function () { | ||
|  |             throw prevError; | ||
|  |           }, 0); | ||
|  |           throw e; | ||
|  |         } | ||
|  |       } else { | ||
|  |         this.cb.call(this.vm, value, oldValue); | ||
|  |       } | ||
|  |     } | ||
|  |     this.queued = this.shallow = false; | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Evaluate the value of the watcher. | ||
|  |  * This only gets called for lazy watchers. | ||
|  |  */ | ||
|  | 
 | ||
|  | Watcher.prototype.evaluate = function () { | ||
|  |   // avoid overwriting another watcher that is being
 | ||
|  |   // collected.
 | ||
|  |   var current = Dep.target; | ||
|  |   this.value = this.get(); | ||
|  |   this.dirty = false; | ||
|  |   Dep.target = current; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Depend on all deps collected by this watcher. | ||
|  |  */ | ||
|  | 
 | ||
|  | Watcher.prototype.depend = function () { | ||
|  |   var depIds = Object.keys(this.deps); | ||
|  |   var i = depIds.length; | ||
|  |   while (i--) { | ||
|  |     this.deps[depIds[i]].depend(); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Remove self from all dependencies' subcriber list. | ||
|  |  */ | ||
|  | 
 | ||
|  | Watcher.prototype.teardown = function () { | ||
|  |   if (this.active) { | ||
|  |     // remove self from vm's watcher list
 | ||
|  |     // we can skip this if the vm if being destroyed
 | ||
|  |     // which can improve teardown performance.
 | ||
|  |     if (!this.vm._isBeingDestroyed) { | ||
|  |       this.vm._watchers.$remove(this); | ||
|  |     } | ||
|  |     var depIds = Object.keys(this.deps); | ||
|  |     var i = depIds.length; | ||
|  |     while (i--) { | ||
|  |       this.deps[depIds[i]].removeSub(this); | ||
|  |     } | ||
|  |     this.active = false; | ||
|  |     this.vm = this.cb = this.value = null; | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Recrusively traverse an object to evoke all converted | ||
|  |  * getters, so that every nested property inside the object | ||
|  |  * is collected as a "deep" dependency. | ||
|  |  * | ||
|  |  * @param {*} val | ||
|  |  */ | ||
|  | 
 | ||
|  | function traverse(val) { | ||
|  |   var i, keys; | ||
|  |   if (isArray(val)) { | ||
|  |     i = val.length; | ||
|  |     while (i--) traverse(val[i]); | ||
|  |   } else if (isObject(val)) { | ||
|  |     keys = Object.keys(val); | ||
|  |     i = keys.length; | ||
|  |     while (i--) traverse(val[keys[i]]); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | var cloak = { | ||
|  |   bind: function bind() { | ||
|  |     var el = this.el; | ||
|  |     this.vm.$once('pre-hook:compiled', function () { | ||
|  |       el.removeAttribute('v-cloak'); | ||
|  |     }); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | var ref = { | ||
|  |   bind: function bind() { | ||
|  |     process.env.NODE_ENV !== 'production' && warn('v-ref:' + this.arg + ' must be used on a child ' + 'component. Found on <' + this.el.tagName.toLowerCase() + '>.'); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | var ON = 700; | ||
|  | var MODEL = 800; | ||
|  | var BIND = 850; | ||
|  | var TRANSITION = 1100; | ||
|  | var EL = 1500; | ||
|  | var COMPONENT = 1500; | ||
|  | var PARTIAL = 1750; | ||
|  | var FOR = 2000; | ||
|  | var IF = 2000; | ||
|  | var SLOT = 2100; | ||
|  | 
 | ||
|  | 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 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) { | ||
|  |         value = value.replace(importantRE, '').trim(); | ||
|  |       } | ||
|  |       this.el.style.setProperty(prop, value, isImportant); | ||
|  |     } else { | ||
|  |       this.el.style.removeProperty(prop); | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * 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'); | ||
|  |   } | ||
|  |   if (camel in testEl.style) { | ||
|  |     return prop; | ||
|  |   } | ||
|  |   var i = prefixes.length; | ||
|  |   var prefixed; | ||
|  |   while (i--) { | ||
|  |     prefixed = camelPrefixes[i] + upper; | ||
|  |     if (prefixed in testEl.style) { | ||
|  |       return prefixes[i] + prop; | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | // 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 should set a hidden property for
 | ||
|  | // binding v-model to object values
 | ||
|  | var modelProps = { | ||
|  |   value: '_value', | ||
|  |   'true-value': '_trueValue', | ||
|  |   'false-value': '_falseValue' | ||
|  | }; | ||
|  | 
 | ||
|  | var bind = { | ||
|  | 
 | ||
|  |   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')) { | ||
|  |         process.env.NODE_ENV !== 'production' && warn(attr + '="' + descriptor.raw + '": ' + 'attribute interpolation is not allowed in Vue.js ' + 'directives and special attributes.'); | ||
|  |         this.el.removeAttribute(attr); | ||
|  |         this.invalid = true; | ||
|  |       } | ||
|  | 
 | ||
|  |       /* istanbul ignore if */ | ||
|  |       if (process.env.NODE_ENV !== '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.'); | ||
|  |         } | ||
|  | 
 | ||
|  |         // 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.'); | ||
|  |         } | ||
|  |       } | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   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 (!interp && attrWithPropsRE.test(attr) && attr in el) { | ||
|  |       el[attr] = attr === 'value' ? value == null // IE9 will set input.value to "null" for null...
 | ||
|  |       ? '' : value : value; | ||
|  |     } | ||
|  |     // 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 (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); | ||
|  |       } else { | ||
|  |         el.setAttribute(attr, value); | ||
|  |       } | ||
|  |     } else { | ||
|  |       el.removeAttribute(attr); | ||
|  |     } | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | // keyCode aliases
 | ||
|  | var keyCodes = { | ||
|  |   esc: 27, | ||
|  |   tab: 9, | ||
|  |   enter: 13, | ||
|  |   space: 32, | ||
|  |   'delete': 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]; | ||
|  |   }); | ||
|  |   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); | ||
|  |   }; | ||
|  | } | ||
|  | 
 | ||
|  | var on = { | ||
|  | 
 | ||
|  |   acceptStatement: true, | ||
|  |   priority: ON, | ||
|  | 
 | ||
|  |   bind: function bind() { | ||
|  |     // deal with iframes
 | ||
|  |     if (this.el.tagName === 'IFRAME' && this.arg !== 'load') { | ||
|  |       var self = this; | ||
|  |       this.iframeBind = function () { | ||
|  |         on$1(self.el.contentWindow, self.arg, self.handler); | ||
|  |       }; | ||
|  |       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') { | ||
|  |       process.env.NODE_ENV !== 'production' && warn('v-on:' + this.arg + '="' + this.expression + '" expects a function value, ' + 'got ' + handler); | ||
|  |       return; | ||
|  |     } | ||
|  | 
 | ||
|  |     // apply modifiers
 | ||
|  |     if (this.modifiers.stop) { | ||
|  |       handler = stopFilter(handler); | ||
|  |     } | ||
|  |     if (this.modifiers.prevent) { | ||
|  |       handler = preventFilter(handler); | ||
|  |     } | ||
|  |     // key filter
 | ||
|  |     var keys = Object.keys(this.modifiers).filter(function (key) { | ||
|  |       return key !== 'stop' && key !== 'prevent'; | ||
|  |     }); | ||
|  |     if (keys.length) { | ||
|  |       handler = keyFilter(handler, keys); | ||
|  |     } | ||
|  | 
 | ||
|  |     this.reset(); | ||
|  |     this.handler = handler; | ||
|  | 
 | ||
|  |     if (this.iframeBind) { | ||
|  |       this.iframeBind(); | ||
|  |     } else { | ||
|  |       on$1(this.el, this.arg, this.handler); | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   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 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 select = { | ||
|  | 
 | ||
|  |   bind: function bind() { | ||
|  |     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', 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 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 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) { | ||
|  |       jQuery(el).on('change', this.listener); | ||
|  |       if (!lazy) { | ||
|  |         jQuery(el).on('input', this.listener); | ||
|  |       } | ||
|  |     } else { | ||
|  |       this.on('change', this.listener); | ||
|  |       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) { | ||
|  |     this.el.value = _toString(value); | ||
|  |   }, | ||
|  | 
 | ||
|  |   unbind: function unbind() { | ||
|  |     var el = this.el; | ||
|  |     if (this.hasjQuery) { | ||
|  |       jQuery(el).off('change', this.listener); | ||
|  |       jQuery(el).off('input', this.listener); | ||
|  |     } | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | 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) { | ||
|  |       process.env.NODE_ENV !== 'production' && warn('It seems you are using a read-only filter with ' + 'v-model. You might want to use a two-way filter ' + 'to ensure correct behavior.'); | ||
|  |     } | ||
|  |     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 { | ||
|  |       process.env.NODE_ENV !== 'production' && warn('v-model does not support element type: ' + tag); | ||
|  |       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(); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | 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 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) && node.content instanceof DocumentFragment; | ||
|  | } | ||
|  | 
 | ||
|  | var tagRE$1 = /<([\w:]+)/; | ||
|  | var entityRE = /&#?\w+?;/; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Convert a string template to a DocumentFragment. | ||
|  |  * Determines correct wrapping by tag types. Wrapping | ||
|  |  * strategy found in jQuery & component/domify. | ||
|  |  * | ||
|  |  * @param {String} templateString | ||
|  |  * @param {Boolean} raw | ||
|  |  * @return {DocumentFragment} | ||
|  |  */ | ||
|  | 
 | ||
|  | function stringToFragment(templateString, raw) { | ||
|  |   // try a cache hit first
 | ||
|  |   var hit = templateCache.get(templateString); | ||
|  |   if (hit) { | ||
|  |     return hit; | ||
|  |   } | ||
|  | 
 | ||
|  |   var frag = document.createDocumentFragment(); | ||
|  |   var tagMatch = templateString.match(tagRE$1); | ||
|  |   var entityMatch = entityRE.test(templateString); | ||
|  | 
 | ||
|  |   if (!tagMatch && !entityMatch) { | ||
|  |     // text only, return a single text node.
 | ||
|  |     frag.appendChild(document.createTextNode(templateString)); | ||
|  |   } else { | ||
|  | 
 | ||
|  |     var tag = tagMatch && tagMatch[1]; | ||
|  |     var wrap = map[tag] || map.efault; | ||
|  |     var depth = wrap[0]; | ||
|  |     var prefix = wrap[1]; | ||
|  |     var suffix = wrap[2]; | ||
|  |     var node = document.createElement('div'); | ||
|  | 
 | ||
|  |     var templateStringToUse = raw ? templateString : templateString.trim(); | ||
|  |     node.innerHTML = prefix + templateStringToUse + 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); | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   templateCache.put(templateString, frag); | ||
|  |   return frag; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Convert a template node to a DocumentFragment. | ||
|  |  * | ||
|  |  * @param {Node} node | ||
|  |  * @return {DocumentFragment} | ||
|  |  */ | ||
|  | 
 | ||
|  | function nodeToFragment(node) { | ||
|  |   // if its a template tag and the browser supports it,
 | ||
|  |   // its content is already a document fragment.
 | ||
|  |   if (isRealTemplate(node)) { | ||
|  |     trimNode(node.content); | ||
|  |     return node.content; | ||
|  |   } | ||
|  |   // script template
 | ||
|  |   if (node.tagName === 'SCRIPT') { | ||
|  |     return stringToFragment(node.textContent); | ||
|  |   } | ||
|  |   // normal node, clone it to avoid mutating the original
 | ||
|  |   var clonedNode = cloneNode(node); | ||
|  |   var frag = document.createDocumentFragment(); | ||
|  |   var child; | ||
|  |   /* eslint-disable no-cond-assign */ | ||
|  |   while (child = clonedNode.firstChild) { | ||
|  |     /* eslint-enable no-cond-assign */ | ||
|  |     frag.appendChild(child); | ||
|  |   } | ||
|  |   trimNode(frag); | ||
|  |   return frag; | ||
|  | } | ||
|  | 
 | ||
|  | // Test for the presence of the Safari template cloning bug
 | ||
|  | // https://bugs.webkit.org/showug.cgi?id=137755
 | ||
|  | var hasBrokenTemplate = (function () { | ||
|  |   /* istanbul ignore else */ | ||
|  |   if (inBrowser) { | ||
|  |     var a = document.createElement('div'); | ||
|  |     a.innerHTML = '<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) { | ||
|  |   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 (template instanceof DocumentFragment) { | ||
|  |     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 | ||
|  | }); | ||
|  | 
 | ||
|  | /** | ||
|  |  * 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] | ||
|  |  */ | ||
|  | 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].__vue_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.__vfrag__ = 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.__vfrag__ = null; | ||
|  |   this.unlink(); | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Call attach hook for a Vue instance. | ||
|  |  * | ||
|  |  * @param {Vue} child | ||
|  |  */ | ||
|  | 
 | ||
|  | function attach(child) { | ||
|  |   if (!child._isAttached) { | ||
|  |     child._callHook('attached'); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Call detach hook for a Vue instance. | ||
|  |  * | ||
|  |  * @param {Vue} child | ||
|  |  */ | ||
|  | 
 | ||
|  | function detach(child) { | ||
|  |   if (child._isAttached) { | ||
|  |     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)) { | ||
|  |     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 : el.outerHTML); | ||
|  |     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 vIf = { | ||
|  | 
 | ||
|  |   priority: IF, | ||
|  | 
 | ||
|  |   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.elseFactory = new FragmentFactory(this.vm, next); | ||
|  |       } | ||
|  |       // check main block
 | ||
|  |       this.anchor = createAnchor('v-if'); | ||
|  |       replace(el, this.anchor); | ||
|  |       this.factory = new FragmentFactory(this.vm, el); | ||
|  |     } else { | ||
|  |       process.env.NODE_ENV !== 'production' && warn('v-if="' + this.expression + '" cannot be ' + 'used on an instance root element.'); | ||
|  |       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; | ||
|  |     } | ||
|  |     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.elseFactory && !this.elseFrag) { | ||
|  |       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(); | ||
|  |     } | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | var uid$1 = 0; | ||
|  | 
 | ||
|  | var vFor = { | ||
|  | 
 | ||
|  |   priority: FOR, | ||
|  | 
 | ||
|  |   params: ['track-by', 'stagger', 'enter-stagger', 'leave-stagger'], | ||
|  | 
 | ||
|  |   bind: function bind() { | ||
|  |     // support "item in items" syntax
 | ||
|  |     var inMatch = this.expression.match(/(.*) in (.*)/); | ||
|  |     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) { | ||
|  |       process.env.NODE_ENV !== 'production' && warn('Alias is required in v-for.'); | ||
|  |       return; | ||
|  |     } | ||
|  | 
 | ||
|  |     // uid as a cache identifier
 | ||
|  |     this.id = '__v-for__' + ++uid$1; | ||
|  | 
 | ||
|  |     // 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) { | ||
|  |           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; | ||
|  |     for (i = 0, l = oldFrags.length; i < l; i++) { | ||
|  |       frag = oldFrags[i]; | ||
|  |       if (!frag.reused) { | ||
|  |         this.deleteCachedFrag(frag); | ||
|  |         this.remove(frag, removalIndex++, totalRemoved, inDocument); | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     // 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
 | ||
|  |     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.__vfrag__ = frag; | ||
|  |       } | ||
|  |       after(anchor, prevEl); | ||
|  |       var op = frag.staggerCb = cancellable(function () { | ||
|  |         frag.staggerCb = null; | ||
|  |         frag.before(anchor); | ||
|  |         remove(anchor); | ||
|  |       }); | ||
|  |       setTimeout(op, staggerAmount); | ||
|  |     } else { | ||
|  |       frag.before(prevEl.nextSibling); | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   /** | ||
|  |    * 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 = trackByKey ? trackByKey === '$index' ? index : value[trackByKey] : key || value; | ||
|  |       if (!cache[id]) { | ||
|  |         cache[id] = frag; | ||
|  |       } else if (trackByKey !== '$index') { | ||
|  |         process.env.NODE_ENV !== 'production' && this.warnDuplicate(value); | ||
|  |       } | ||
|  |     } else { | ||
|  |       id = this.id; | ||
|  |       if (hasOwn(value, id)) { | ||
|  |         if (value[id] === null) { | ||
|  |           value[id] = frag; | ||
|  |         } else { | ||
|  |           process.env.NODE_ENV !== 'production' && this.warnDuplicate(value); | ||
|  |         } | ||
|  |       } else { | ||
|  |         def(value, id, frag); | ||
|  |       } | ||
|  |     } | ||
|  |     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 = trackByKey ? trackByKey === '$index' ? index : value[trackByKey] : key || value; | ||
|  |       frag = this.cache[id]; | ||
|  |     } else { | ||
|  |       frag = value[this.id]; | ||
|  |     } | ||
|  |     if (frag && (frag.reused || frag.fresh)) { | ||
|  |       process.env.NODE_ENV !== '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 = trackByKey ? trackByKey === '$index' ? index : value[trackByKey] : key || value; | ||
|  |       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 | ||
|  |    * wathcer'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') { | ||
|  |         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.__vfrag__; | ||
|  |   while ((!frag || frag.forId !== id || !frag.inserted) && el !== anchor) { | ||
|  |     el = el.previousSibling; | ||
|  |     /* istanbul ignore if */ | ||
|  |     if (!el) return; | ||
|  |     frag = el.__vfrag__; | ||
|  |   } | ||
|  |   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(n); | ||
|  |   while (++i < n) { | ||
|  |     ret[i] = i; | ||
|  |   } | ||
|  |   return ret; | ||
|  | } | ||
|  | 
 | ||
|  | if (process.env.NODE_ENV !== '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.'); | ||
|  |   }; | ||
|  | } | ||
|  | 
 | ||
|  | 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); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | var text = { | ||
|  | 
 | ||
|  |   bind: function bind() { | ||
|  |     this.attr = this.el.nodeType === 3 ? 'data' : 'textContent'; | ||
|  |   }, | ||
|  | 
 | ||
|  |   update: function update(value) { | ||
|  |     this.el[this.attr] = _toString(value); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | // must export plain object
 | ||
|  | var publicDirectives = { | ||
|  |   text: text, | ||
|  |   html: html, | ||
|  |   'for': vFor, | ||
|  |   'if': vIf, | ||
|  |   show: show, | ||
|  |   model: model, | ||
|  |   on: on, | ||
|  |   bind: bind, | ||
|  |   el: el, | ||
|  |   ref: ref, | ||
|  |   cloak: cloak | ||
|  | }; | ||
|  | 
 | ||
|  | 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'; | ||
|  | 
 | ||
|  | /** | ||
|  |  * 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 (process.env.NODE_ENV !== 'production') { | ||
|  |     if (this.type && this.type !== TYPE_TRANSITION && this.type !== TYPE_ANIMATION) { | ||
|  |       warn('invalid CSS transition type for transition="' + this.id + '": ' + this.type); | ||
|  |     } | ||
|  |   } | ||
|  |   // bind
 | ||
|  |   var self = this;['enterNextTick', 'enterDone', 'leaveNextTick', 'leaveDone'].forEach(function (m) { | ||
|  |     self[m] = bind$1(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 () { | ||
|  | 
 | ||
|  |   // Important hack:
 | ||
|  |   // in Chrome, if a just-entered element is applied the
 | ||
|  |   // leave class while its interpolated property still has
 | ||
|  |   // a very small value (within one frame), Chrome will
 | ||
|  |   // skip the leave transition entirely and not firing the
 | ||
|  |   // transtionend event. Therefore we need to protected
 | ||
|  |   // against such cases using a one-frame timeout.
 | ||
|  |   this.justEntered = true; | ||
|  |   var self = this; | ||
|  |   setTimeout(function () { | ||
|  |     self.justEntered = false; | ||
|  |   }, 17); | ||
|  | 
 | ||
|  |   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$1(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) { | ||
|  |   return !(el.offsetWidth || el.offsetHeight || el.getClientRects().length); | ||
|  | } | ||
|  | 
 | ||
|  | var transition = { | ||
|  | 
 | ||
|  |   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'; | ||
|  |     // apply on closest vm
 | ||
|  |     el.__v_trans = new Transition(el, id, hooks, this.el.__vue__ || this.vm); | ||
|  |     if (oldId) { | ||
|  |       removeClass(el, oldId + '-transition'); | ||
|  |     } | ||
|  |     addClass(el, id + '-transition'); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | 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) { | ||
|  |       val = coerceProp(prop, val); | ||
|  |       if (assertProp(prop, val)) { | ||
|  |         child[childKey] = 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 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'); | ||
|  |       // 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 { | ||
|  |       process.env.NODE_ENV !== '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. | ||
|  |    */ | ||
|  | 
 | ||
|  |   resolveComponent: function resolveComponent(id, cb) { | ||
|  |     var self = this; | ||
|  |     this.pendingComponentCb = cancellable(function (Component) { | ||
|  |       self.ComponentName = Component.options.name || id; | ||
|  |       self.Component = Component; | ||
|  |       cb(); | ||
|  |     }); | ||
|  |     this.vm._resolveComponent(id, 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 activateHook = this.Component.options.activate; | ||
|  |     var cached = this.getCached(); | ||
|  |     var newComponent = this.build(); | ||
|  |     if (activateHook && !cached) { | ||
|  |       this.waitingFor = newComponent; | ||
|  |       activateHook.call(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 (process.env.NODE_ENV !== 'production' && this.el.hasAttribute('transition') && child._isFragment) { | ||
|  |         warn('Transitions will not work on a fragment instance. ' + 'Template: ' + child.$options.template); | ||
|  |       } | ||
|  |       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) { | ||
|  |       this.waitingFor.$destroy(); | ||
|  |       this.waitingFor = null; | ||
|  |     } | ||
|  |     var child = this.childVM; | ||
|  |     if (!child || this.keepAlive) { | ||
|  |       if (child) { | ||
|  |         // remove ref
 | ||
|  |         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 (process.env.NODE_ENV !== 'production') { | ||
|  |       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; | ||
|  |     } | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | var vClass = { | ||
|  | 
 | ||
|  |   deep: true, | ||
|  | 
 | ||
|  |   update: function update(value) { | ||
|  |     if (value && typeof value === 'string') { | ||
|  |       this.handleObject(stringToObject(value)); | ||
|  |     } else if (isPlainObject(value)) { | ||
|  |       this.handleObject(value); | ||
|  |     } else if (isArray(value)) { | ||
|  |       this.handleArray(value); | ||
|  |     } else { | ||
|  |       this.cleanup(); | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   handleObject: function handleObject(value) { | ||
|  |     this.cleanup(value); | ||
|  |     var keys = this.prevKeys = Object.keys(value); | ||
|  |     for (var i = 0, l = keys.length; i < l; i++) { | ||
|  |       var key = keys[i]; | ||
|  |       if (value[key]) { | ||
|  |         addClass(this.el, key); | ||
|  |       } else { | ||
|  |         removeClass(this.el, key); | ||
|  |       } | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   handleArray: function handleArray(value) { | ||
|  |     this.cleanup(value); | ||
|  |     for (var i = 0, l = value.length; i < l; i++) { | ||
|  |       if (value[i]) { | ||
|  |         addClass(this.el, value[i]); | ||
|  |       } | ||
|  |     } | ||
|  |     this.prevKeys = value.slice(); | ||
|  |   }, | ||
|  | 
 | ||
|  |   cleanup: function cleanup(value) { | ||
|  |     if (this.prevKeys) { | ||
|  |       var i = this.prevKeys.length; | ||
|  |       while (i--) { | ||
|  |         var key = this.prevKeys[i]; | ||
|  |         if (key && (!value || !contains$1(value, key))) { | ||
|  |           removeClass(this.el, key); | ||
|  |         } | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | function stringToObject(value) { | ||
|  |   var res = {}; | ||
|  |   var keys = value.trim().split(/\s+/); | ||
|  |   var i = keys.length; | ||
|  |   while (i--) { | ||
|  |     res[keys[i]] = true; | ||
|  |   } | ||
|  |   return res; | ||
|  | } | ||
|  | 
 | ||
|  | function contains$1(value, key) { | ||
|  |   return isArray(value) ? value.indexOf(key) > -1 : hasOwn(value, key); | ||
|  | } | ||
|  | 
 | ||
|  | var internalDirectives = { | ||
|  |   style: style, | ||
|  |   'class': vClass, | ||
|  |   component: component, | ||
|  |   prop: propDef, | ||
|  |   transition: transition | ||
|  | }; | ||
|  | 
 | ||
|  | 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 | ||
|  |  * @return {Function} propsLinkFn | ||
|  |  */ | ||
|  | 
 | ||
|  | function compileProps(el, propOptions) { | ||
|  |   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 (process.env.NODE_ENV !== 'production' && name === '$data') { | ||
|  |       warn('Do not use $data as prop.'); | ||
|  |       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)) { | ||
|  |       process.env.NODE_ENV !== 'production' && warn('Invalid prop key: "' + name + '". Prop keys ' + 'must be valid identifiers.'); | ||
|  |       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 (process.env.NODE_ENV !== '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); | ||
|  |         } | ||
|  |       } | ||
|  |       prop.parentPath = value; | ||
|  | 
 | ||
|  |       // warn required two-way
 | ||
|  |       if (process.env.NODE_ENV !== 'production' && options.twoWay && prop.mode !== propBindingModes.TWO_WAY) { | ||
|  |         warn('Prop "' + name + '" expects a two-way binding type.'); | ||
|  |       } | ||
|  |     } else if ((value = getAttr(el, attr)) !== null) { | ||
|  |       // has literal binding!
 | ||
|  |       prop.raw = value; | ||
|  |     } else if (options.required) { | ||
|  |       // warn missing required
 | ||
|  |       process.env.NODE_ENV !== 'production' && warn('Missing required prop: ' + name); | ||
|  |     } | ||
|  |     // 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 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 (raw === null) { | ||
|  |         // initialize absent prop
 | ||
|  |         initProp(vm, prop, getDefault(vm, options)); | ||
|  |       } else if (prop.dynamic) { | ||
|  |         // dynamic prop
 | ||
|  |         if (vm._context) { | ||
|  |           if (prop.mode === propBindingModes.ONE_TIME) { | ||
|  |             // one time binding
 | ||
|  |             value = (scope || vm._context).$get(prop.parentPath); | ||
|  |             initProp(vm, prop, value); | ||
|  |           } else { | ||
|  |             // dynamic binding
 | ||
|  |             vm._bindDir({ | ||
|  |               name: 'prop', | ||
|  |               def: propDef, | ||
|  |               prop: prop | ||
|  |             }, null, null, scope); // el, host, scope
 | ||
|  |           } | ||
|  |         } else { | ||
|  |             process.env.NODE_ENV !== 'production' && warn('Cannot bind dynamic prop on a root instance' + ' with no parent: ' + prop.name + '="' + raw + '"'); | ||
|  |           } | ||
|  |       } 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
 | ||
|  |         value = options.type === Boolean && raw === '' ? true : raw; | ||
|  |         initProp(vm, prop, value); | ||
|  |       } | ||
|  |     } | ||
|  |   }; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Get the default value of a prop. | ||
|  |  * | ||
|  |  * @param {Vue} vm | ||
|  |  * @param {Object} options | ||
|  |  * @return {*} | ||
|  |  */ | ||
|  | 
 | ||
|  | function getDefault(vm, options) { | ||
|  |   // no default, return undefined
 | ||
|  |   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)) { | ||
|  |     process.env.NODE_ENV !== 'production' && warn('Object/Array as default prop values will be shared ' + 'across multiple instances. Use a factory function ' + 'to return the default value instead.'); | ||
|  |   } | ||
|  |   // call factory function for non-Function types
 | ||
|  |   return typeof def === 'function' && options.type !== Function ? def.call(vm) : def; | ||
|  | } | ||
|  | 
 | ||
|  | // special binding prefixes
 | ||
|  | var bindRE = /^v-bind:|^:/; | ||
|  | var onRE = /^v-on:|^@/; | ||
|  | var argRE = /:(.*)$/; | ||
|  | var modifierRE = /\.[^\.]+/g; | ||
|  | var transitionRE = /^(v-bind:|:)?transition$/; | ||
|  | 
 | ||
|  | // terminal directives
 | ||
|  | var terminalDirectives = ['for', 'if']; | ||
|  | 
 | ||
|  | // default directive priority
 | ||
|  | var DEFAULT_PRIORITY = 1000; | ||
|  | 
 | ||
|  | /** | ||
|  |  * 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) && el.tagName !== 'SCRIPT' && 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) { | ||
|  |   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 (!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); | ||
|  |   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 {Vue} vm | ||
|  |  * @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 (process.env.NODE_ENV !== '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 && node.tagName !== 'SCRIPT') { | ||
|  |     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(); | ||
|  |   // check terminal directives (for & if)
 | ||
|  |   if (hasAttrs) { | ||
|  |     linkFn = checkTerminalDirectives(el, 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(el.attributes, 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: publicDirectives[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 = 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; | ||
|  |   // special case: give named slot a higher priority
 | ||
|  |   // than unnamed slots
 | ||
|  |   if (tag === 'slot' && hasBindAttr(el, 'name')) { | ||
|  |     tag = '_namedSlot'; | ||
|  |   } | ||
|  |   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 {Object} options | ||
|  |  * @return {Function} terminalLinkFn | ||
|  |  */ | ||
|  | 
 | ||
|  | function checkTerminalDirectives(el, 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 value, dirName; | ||
|  |   for (var i = 0, l = terminalDirectives.length; i < l; i++) { | ||
|  |     dirName = terminalDirectives[i]; | ||
|  |     value = el.getAttribute('v-' + dirName); | ||
|  |     if (value != null) { | ||
|  |       return makeTerminalNodeLinkFn(el, dirName, value, options); | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | 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] | ||
|  |  * @return {Function} terminalLinkFn | ||
|  |  */ | ||
|  | 
 | ||
|  | function makeTerminalNodeLinkFn(el, dirName, value, options, def) { | ||
|  |   var parsed = parseDirective(value); | ||
|  |   var descriptor = { | ||
|  |     name: dirName, | ||
|  |     expression: parsed.expression, | ||
|  |     filters: parsed.filters, | ||
|  |     raw: value, | ||
|  |     // either an element directive, or if/for
 | ||
|  |     def: def || publicDirectives[dirName] | ||
|  |   }; | ||
|  |   // 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; | ||
|  |   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', publicDirectives.bind, tokens); | ||
|  |       // warn against mixing mustaches with v-bind
 | ||
|  |       if (process.env.NODE_ENV !== '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.'); | ||
|  |         } | ||
|  |       } | ||
|  |     } 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', publicDirectives.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', publicDirectives.bind); | ||
|  |             } | ||
|  |           } else | ||
|  | 
 | ||
|  |             // normal directives
 | ||
|  |             if (name.indexOf('v-') === 0) { | ||
|  |               // check arg
 | ||
|  |               arg = (arg = name.match(argRE)) && arg[1]; | ||
|  |               if (arg) { | ||
|  |                 name = name.replace(argRE, ''); | ||
|  |               } | ||
|  |               // extract directive name
 | ||
|  |               dirName = name.slice(2); | ||
|  | 
 | ||
|  |               // skip v-else (when used with v-show)
 | ||
|  |               if (dirName === 'else') { | ||
|  |                 continue; | ||
|  |               } | ||
|  | 
 | ||
|  |               dirDef = resolveAsset(options, 'directives', dirName); | ||
|  | 
 | ||
|  |               if (process.env.NODE_ENV !== 'production') { | ||
|  |                 assertAsset(dirDef, 'directive', dirName); | ||
|  |               } | ||
|  | 
 | ||
|  |               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; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | 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 (el instanceof DocumentFragment) { | ||
|  |     // 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) { | ||
|  |         process.env.NODE_ENV !== '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 { | ||
|  |     process.env.NODE_ENV !== '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.split(/\s+/).forEach(function (cls) { | ||
|  |         addClass(to, cls); | ||
|  |       }); | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | var compiler = Object.freeze({ | ||
|  | 	compile: compile, | ||
|  | 	compileAndLinkProps: compileAndLinkProps, | ||
|  | 	compileRoot: compileRoot, | ||
|  | 	terminalDirectives: terminalDirectives, | ||
|  | 	transclude: transclude | ||
|  | }); | ||
|  | 
 | ||
|  | 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) { | ||
|  |       process.env.NODE_ENV !== 'production' && warn('Props will not be compiled if no `el` option is ' + 'provided at instantiation.'); | ||
|  |     } | ||
|  |     // 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 propsData = this._data; | ||
|  |     var optionsDataFn = this.$options.data; | ||
|  |     var optionsData = optionsDataFn && optionsDataFn(); | ||
|  |     if (optionsData) { | ||
|  |       this._data = optionsData; | ||
|  |       for (var prop in propsData) { | ||
|  |         if (process.env.NODE_ENV !== 'production' && hasOwn(optionsData, prop)) { | ||
|  |           warn('Data field "' + prop + '" is already defined ' + 'as a prop. Use prop default value instead.'); | ||
|  |         } | ||
|  |         if (this._props[prop].raw !== null || !hasOwn(optionsData, prop)) { | ||
|  |           set(optionsData, prop, propsData[prop]); | ||
|  |         } | ||
|  |       } | ||
|  |     } | ||
|  |     var data = this._data; | ||
|  |     // proxy data on instance
 | ||
|  |     var keys = Object.keys(data); | ||
|  |     var i, key; | ||
|  |     i = keys.length; | ||
|  |     while (i--) { | ||
|  |       key = keys[i]; | ||
|  |       this._proxy(key); | ||
|  |     } | ||
|  |     // 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$1(userDef.get, this) : noop; | ||
|  |           def.set = userDef.set ? bind$1(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$1(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, handler; | ||
|  |     for (var i = 0, l = attrs.length; i < l; i++) { | ||
|  |       name = attrs[i].name; | ||
|  |       if (eventRE.test(name)) { | ||
|  |         name = name.replace(eventRE, ''); | ||
|  |         handler = (vm._scope || vm._context).$eval(attrs[i].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 { | ||
|  |         process.env.NODE_ENV !== 'production' && warn('Unknown method: "' + handler + '" when ' + 'registering callback for ' + action + ': "' + key + '".'); | ||
|  |       } | ||
|  |     } 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() {} | ||
|  | 
 | ||
|  | /** | ||
|  |  * 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 {String} name | ||
|  |  * @param {Node} el | ||
|  |  * @param {Vue} vm | ||
|  |  * @param {Object} descriptor | ||
|  |  *                 - {String} name | ||
|  |  *                 - {Object} def | ||
|  |  *                 - {String} expression | ||
|  |  *                 - {Array<Object>} [filters] | ||
|  |  *                 - {Boolean} literal | ||
|  |  *                 - {String} attr | ||
|  |  *                 - {String} raw | ||
|  |  * @param {Object} def - directive definition object | ||
|  |  * @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 (process.env.NODE_ENV !== '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. | ||
|  |  * | ||
|  |  * @param {Object} def | ||
|  |  */ | ||
|  | 
 | ||
|  | 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; | ||
|  |     } | ||
|  |     var preProcess = this._preProcess ? bind$1(this._preProcess, this) : null; | ||
|  |     var postProcess = this._postProcess ? bind$1(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 = 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 (process.env.NODE_ENV !== '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 | ||
|  |  */ | ||
|  | 
 | ||
|  | Directive.prototype.on = function (event, handler) { | ||
|  |   on$1(this.el, event, handler);(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 (process.env.NODE_ENV !== '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 | ||
|  |    * @return {Element} | ||
|  |    */ | ||
|  | 
 | ||
|  |   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); | ||
|  | 
 | ||
|  |     // 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'); | ||
|  |     return el; | ||
|  |   }; | ||
|  | 
 | ||
|  |   /** | ||
|  |    * Initialize instance element. Called in the public | ||
|  |    * $mount() method. | ||
|  |    * | ||
|  |    * @param {Element} el | ||
|  |    */ | ||
|  | 
 | ||
|  |   Vue.prototype._initElement = function (el) { | ||
|  |     if (el instanceof DocumentFragment) { | ||
|  |       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 {String} name - directive name | ||
|  |    * @param {Node} node   - target node | ||
|  |    * @param {Object} desc - parsed directive descriptor | ||
|  |    * @param {Object} def  - directive definition object | ||
|  |    * @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.__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[i]; | ||
|  |       fn = resolveAsset(this.$options, 'filters', filter.name); | ||
|  |       if (process.env.NODE_ENV !== 'production') { | ||
|  |         assertAsset(fn, 'filter', filter.name); | ||
|  |       } | ||
|  |       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} id | ||
|  |    * @param {Function} cb | ||
|  |    */ | ||
|  | 
 | ||
|  |   Vue.prototype._resolveComponent = function (id, cb) { | ||
|  |     var factory = resolveAsset(this.$options, 'components', id); | ||
|  |     if (process.env.NODE_ENV !== 'production') { | ||
|  |       assertAsset(factory, 'component', id); | ||
|  |     } | ||
|  |     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(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) { | ||
|  |           process.env.NODE_ENV !== 'production' && warn('Failed to resolve async component: ' + id + '. ' + (reason ? '\nReason: ' + reason : '')); | ||
|  |         }); | ||
|  |       } | ||
|  |     } else { | ||
|  |       // normal component
 | ||
|  |       cb(factory); | ||
|  |     } | ||
|  |   }; | ||
|  | } | ||
|  | 
 | ||
|  | function globalAPI (Vue) { | ||
|  | 
 | ||
|  |   /** | ||
|  |    * 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$1, | ||
|  |     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 (process.env.NODE_ENV !== 'production') { | ||
|  |       if (!/^[a-zA-Z][\w-]+$/.test(name)) { | ||
|  |         warn('Invalid component name: ' + name); | ||
|  |         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) { | ||
|  |     return new Function('return function ' + classify(name) + ' (options) { this._init(options) }')(); | ||
|  |   } | ||
|  | 
 | ||
|  |   /** | ||
|  |    * 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 (process.env.NODE_ENV !== '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)) { | ||
|  |           definition.name = id; | ||
|  |           definition = Vue.extend(definition); | ||
|  |         } | ||
|  |         this.options[type + 's'][id] = definition; | ||
|  |         return definition; | ||
|  |       } | ||
|  |     }; | ||
|  |   }); | ||
|  | } | ||
|  | 
 | ||
|  | var filterRE = /[^|]\|[^|]/; | ||
|  | 
 | ||
|  | 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 && !isSimplePath(exp)) { | ||
|  |         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.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) { | ||
|  |       for (var key in this.$options.computed) { | ||
|  |         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) { | ||
|  |       process.env.NODE_ENV !== 'production' && warn('$mount() should be called only once.'); | ||
|  |       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. | ||
|  |    */ | ||
|  | 
 | ||
|  |   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] | ||
|  |    * @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 APIs
 | ||
|  | globalAPI(Vue); | ||
|  | dataAPI(Vue); | ||
|  | domAPI(Vue); | ||
|  | eventsAPI(Vue); | ||
|  | lifecycleAPI(Vue); | ||
|  | 
 | ||
|  | 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 = toArray(arguments, n).reduce(function (prev, cur) { | ||
|  |     return prev.concat(cur); | ||
|  |   }, []); | ||
|  |   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} sortKey | ||
|  |  * @param {String} reverse | ||
|  |  */ | ||
|  | 
 | ||
|  | function orderBy(arr, sortKey, reverse) { | ||
|  |   arr = convertArray(arr); | ||
|  |   if (!sortKey) { | ||
|  |     return arr; | ||
|  |   } | ||
|  |   var order = reverse && reverse < 0 ? -1 : 1; | ||
|  |   // sort on a copy to avoid mutating original array
 | ||
|  |   return arr.slice().sort(function (a, b) { | ||
|  |     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; | ||
|  |   }); | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * 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, Number(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 | ||
|  |    */ | ||
|  | 
 | ||
|  |   currency: function currency(value, _currency) { | ||
|  |     value = parseFloat(value); | ||
|  |     if (!isFinite(value) || !value && value !== 0) return ''; | ||
|  |     _currency = _currency != null ? _currency : '$'; | ||
|  |     var stringified = Math.abs(value).toFixed(2); | ||
|  |     var _int = stringified.slice(0, -3); | ||
|  |     var i = _int.length % 3; | ||
|  |     var head = i > 0 ? _int.slice(0, i) + (_int.length > 3 ? ',' : '') : ''; | ||
|  |     var _float = stringified.slice(-3); | ||
|  |     var sign = value < 0 ? '-' : ''; | ||
|  |     return _currency + sign + 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); | ||
|  |     return args.length > 1 ? args[value % 10 - 1] || args[args.length - 1] : 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); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | 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); | ||
|  |     if (process.env.NODE_ENV !== 'production') { | ||
|  |       assertAsset(partial, 'partial', id); | ||
|  |     } | ||
|  |     if (partial) { | ||
|  |       this.factory = new FragmentFactory(this.vm, partial); | ||
|  |       vIf.insert.call(this); | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   unbind: function unbind() { | ||
|  |     if (this.frag) { | ||
|  |       this.frag.destroy(); | ||
|  |     } | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | // This is the elementDirective that handles <content>
 | ||
|  | // transclusions. It relies on the raw content of an
 | ||
|  | // instance being stored as `$options._content` during
 | ||
|  | // the transclude phase.
 | ||
|  | 
 | ||
|  | // We are exporting two versions, one for named and one
 | ||
|  | // for unnamed, because the unnamed slots must be compiled
 | ||
|  | // AFTER all named slots have selected their content. So
 | ||
|  | // we need to give them different priorities in the compilation
 | ||
|  | // process. (See #1965)
 | ||
|  | 
 | ||
|  | var slot = { | ||
|  | 
 | ||
|  |   priority: SLOT, | ||
|  | 
 | ||
|  |   bind: function bind() { | ||
|  |     var host = this.vm; | ||
|  |     var raw = host.$options._content; | ||
|  |     if (!raw) { | ||
|  |       this.fallback(); | ||
|  |       return; | ||
|  |     } | ||
|  |     var context = host._context; | ||
|  |     var slotName = this.params && this.params.name; | ||
|  |     if (!slotName) { | ||
|  |       // Default slot
 | ||
|  |       this.tryCompile(extractFragment(raw.childNodes, raw, true), context, host); | ||
|  |     } else { | ||
|  |       // Named slot
 | ||
|  |       var selector = '[slot="' + slotName + '"]'; | ||
|  |       var nodes = raw.querySelectorAll(selector); | ||
|  |       if (nodes.length) { | ||
|  |         this.tryCompile(extractFragment(nodes, raw), context, host); | ||
|  |       } else { | ||
|  |         this.fallback(); | ||
|  |       } | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   tryCompile: function tryCompile(content, context, host) { | ||
|  |     if (content.hasChildNodes()) { | ||
|  |       this.compile(content, context, host); | ||
|  |     } else { | ||
|  |       this.fallback(); | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   compile: function compile(content, context, host) { | ||
|  |     if (content && context) { | ||
|  |       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 namedSlot = extend(extend({}, slot), { | ||
|  |   priority: slot.priority + 1, | ||
|  |   params: ['name'] | ||
|  | }); | ||
|  | 
 | ||
|  | /** | ||
|  |  * Extract qualified content nodes from a node list. | ||
|  |  * | ||
|  |  * @param {NodeList} nodes | ||
|  |  * @param {Element} parent | ||
|  |  * @param {Boolean} main | ||
|  |  * @return {DocumentFragment} | ||
|  |  */ | ||
|  | 
 | ||
|  | function extractFragment(nodes, parent, main) { | ||
|  |   var frag = document.createDocumentFragment(); | ||
|  |   for (var i = 0, l = nodes.length; i < l; i++) { | ||
|  |     var node = nodes[i]; | ||
|  |     // if this is the main outlet, we want to skip all
 | ||
|  |     // previously selected nodes;
 | ||
|  |     // otherwise, we want to mark the node as selected.
 | ||
|  |     // clone the node so the original raw content remains
 | ||
|  |     // intact. this ensures proper re-compilation in cases
 | ||
|  |     // where the outlet is inside a conditional block
 | ||
|  |     if (main && !node.__v_selected) { | ||
|  |       append(node); | ||
|  |     } else if (!main && node.parentNode === parent) { | ||
|  |       node.__v_selected = true; | ||
|  |       append(node); | ||
|  |     } | ||
|  |   } | ||
|  |   return frag; | ||
|  | 
 | ||
|  |   function append(node) { | ||
|  |     if (isTemplate(node) && !node.hasAttribute('v-if') && !node.hasAttribute('v-for')) { | ||
|  |       node = parseTemplate(node); | ||
|  |     } | ||
|  |     node = cloneNode(node); | ||
|  |     frag.appendChild(node); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | var elementDirectives = { | ||
|  |   slot: slot, | ||
|  |   _namedSlot: namedSlot, // same as slot but with higher priority
 | ||
|  |   partial: partial | ||
|  | }; | ||
|  | 
 | ||
|  | Vue.version = '1.0.15'; | ||
|  | 
 | ||
|  | /** | ||
|  |  * 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: publicDirectives, | ||
|  |   elementDirectives: elementDirectives, | ||
|  |   filters: filters, | ||
|  |   transitions: {}, | ||
|  |   components: {}, | ||
|  |   partials: {}, | ||
|  |   replace: true | ||
|  | }; | ||
|  | 
 | ||
|  | // devtools global hook
 | ||
|  | /* istanbul ignore if */ | ||
|  | if (process.env.NODE_ENV !== 'production' && inBrowser) { | ||
|  |   if (window.__VUE_DEVTOOLS_GLOBAL_HOOK__) { | ||
|  |     window.__VUE_DEVTOOLS_GLOBAL_HOOK__.emit('init', Vue); | ||
|  |   } else if (/Chrome\/\d+/.test(navigator.userAgent)) { | ||
|  |     console.log('Download the Vue Devtools for a better development experience:\n' + 'https://github.com/vuejs/vue-devtools'); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | module.exports = Vue; |