Created
May 22, 2015 07:32
-
-
Save GirlBossRush/e63d55cd6d2a43c20ee4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Vue.js v0.11.9 | |
* (c) 2015 Evan You | |
* Released under the MIT License. | |
*/ | |
(function webpackUniversalModuleDefinition(root, factory) { | |
if(typeof exports === 'object' && typeof module === 'object') | |
module.exports = factory(); | |
else if(typeof define === 'function' && define.amd) | |
define(factory); | |
else if(typeof exports === 'object') | |
exports["Vue"] = factory(); | |
else | |
root["Vue"] = factory(); | |
})(this, function() { | |
return /******/ (function(modules) { // webpackBootstrap | |
/******/ // The module cache | |
/******/ var installedModules = {}; | |
/******/ // The require function | |
/******/ function __webpack_require__(moduleId) { | |
/******/ // Check if module is in cache | |
/******/ if(installedModules[moduleId]) | |
/******/ return installedModules[moduleId].exports; | |
/******/ // Create a new module (and put it into the cache) | |
/******/ var module = installedModules[moduleId] = { | |
/******/ exports: {}, | |
/******/ id: moduleId, | |
/******/ loaded: false | |
/******/ }; | |
/******/ // Execute the module function | |
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); | |
/******/ // Flag the module as loaded | |
/******/ module.loaded = true; | |
/******/ // Return the exports of the module | |
/******/ return module.exports; | |
/******/ } | |
/******/ // expose the modules object (__webpack_modules__) | |
/******/ __webpack_require__.m = modules; | |
/******/ // expose the module cache | |
/******/ __webpack_require__.c = installedModules; | |
/******/ // __webpack_public_path__ | |
/******/ __webpack_require__.p = ""; | |
/******/ // Load entry module and return exports | |
/******/ return __webpack_require__(0); | |
/******/ }) | |
/************************************************************************/ | |
/******/ ([ | |
/* 0 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var extend = _.extend | |
/** | |
* The exposed Vue constructor. | |
* | |
* API conventions: | |
* - public API methods/properties are prefiexed 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) | |
} | |
/** | |
* Mixin global API | |
*/ | |
extend(Vue, __webpack_require__(1)) | |
/** | |
* 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 : __webpack_require__(12), | |
filters : __webpack_require__(13), | |
partials : {}, | |
transitions : {}, | |
components : {} | |
} | |
/** | |
* Build up the prototype | |
*/ | |
var p = Vue.prototype | |
/** | |
* $data has a setter which does a bunch of | |
* teardown/setup work | |
*/ | |
Object.defineProperty(p, '$data', { | |
get: function () { | |
return this._data | |
}, | |
set: function (newData) { | |
this._setData(newData) | |
} | |
}) | |
/** | |
* Mixin internal instance methods | |
*/ | |
extend(p, __webpack_require__(2)) | |
extend(p, __webpack_require__(3)) | |
extend(p, __webpack_require__(4)) | |
extend(p, __webpack_require__(5)) | |
/** | |
* Mixin public API methods | |
*/ | |
extend(p, __webpack_require__(6)) | |
extend(p, __webpack_require__(7)) | |
extend(p, __webpack_require__(8)) | |
extend(p, __webpack_require__(9)) | |
extend(p, __webpack_require__(10)) | |
module.exports = _.Vue = Vue | |
/***/ }, | |
/* 1 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var mergeOptions = __webpack_require__(14) | |
/** | |
* Expose useful internals | |
*/ | |
exports.util = _ | |
exports.nextTick = _.nextTick | |
exports.config = __webpack_require__(15) | |
exports.compiler = { | |
compile: __webpack_require__(16), | |
transclude: __webpack_require__(17) | |
} | |
exports.parsers = { | |
path: __webpack_require__(18), | |
text: __webpack_require__(19), | |
template: __webpack_require__(20), | |
directive: __webpack_require__(21), | |
expression: __webpack_require__(22) | |
} | |
/** | |
* Each instance constructor, including Vue, has a unique | |
* cid. This enables us to create wrapped "child | |
* constructors" for prototypal inheritance and cache them. | |
*/ | |
exports.cid = 0 | |
var cid = 1 | |
/** | |
* Class inehritance | |
* | |
* @param {Object} extendOptions | |
*/ | |
exports.extend = function (extendOptions) { | |
extendOptions = extendOptions || {} | |
var Super = this | |
var Sub = createClass( | |
extendOptions.name || | |
Super.options.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. | |
createAssetRegisters(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 | |
*/ | |
exports.use = function (plugin) { | |
// 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) | |
} | |
return this | |
} | |
/** | |
* Define asset registration methods on a constructor. | |
* | |
* @param {Function} Constructor | |
*/ | |
var assetTypes = [ | |
'directive', | |
'filter', | |
'partial', | |
'transition' | |
] | |
function createAssetRegisters (Constructor) { | |
/* Asset registration methods share the same signature: | |
* | |
* @param {String} id | |
* @param {*} definition | |
*/ | |
assetTypes.forEach(function (type) { | |
Constructor[type] = function (id, definition) { | |
if (!definition) { | |
return this.options[type + 's'][id] | |
} else { | |
this.options[type + 's'][id] = definition | |
} | |
} | |
}) | |
/** | |
* Component registration needs to automatically invoke | |
* Vue.extend on object values. | |
* | |
* @param {String} id | |
* @param {Object|Function} definition | |
*/ | |
Constructor.component = function (id, definition) { | |
if (!definition) { | |
return this.options.components[id] | |
} else { | |
if (_.isPlainObject(definition)) { | |
definition.name = id | |
definition = _.Vue.extend(definition) | |
} | |
this.options.components[id] = definition | |
} | |
} | |
} | |
createAssetRegisters(exports) | |
/***/ }, | |
/* 2 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var mergeOptions = __webpack_require__(14) | |
/** | |
* 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. | |
*/ | |
exports._init = function (options) { | |
options = options || {} | |
this.$el = null | |
this.$parent = options._parent | |
this.$root = options._root || this | |
this.$ = {} // child vm references | |
this.$$ = {} // element references | |
this._watcherList = [] // all watchers as an array | |
this._watchers = {} // internal watchers as a hash | |
this._userWatchers = {} // user watchers as a hash | |
this._directives = [] // all directives | |
// a flag to avoid this being observed | |
this._isVue = true | |
// events bookkeeping | |
this._events = {} // registered callbacks | |
this._eventsCount = {} // for $broadcast optimization | |
this._eventCancelled = false // for event cancellation | |
// block instance properties | |
this._isBlock = false | |
this._blockStart = // @type {CommentNode} | |
this._blockEnd = null // @type {CommentNode} | |
// lifecycle state | |
this._isCompiled = | |
this._isDestroyed = | |
this._isReady = | |
this._isAttached = | |
this._isBeingDestroyed = false | |
// children | |
this._children = [] | |
this._childCtors = {} | |
// transclusion unlink functions | |
this._containerUnlinkFn = | |
this._contentUnlinkFn = null | |
// transcluded components that belong to the parent. | |
// need to keep track of them so that we can call | |
// attached/detached hooks on them. | |
this._transCpnts = [] | |
this._host = options._host | |
// push self into parent / transclusion host | |
if (this.$parent) { | |
this.$parent._children.push(this) | |
} | |
if (this._host) { | |
this._host._transCpnts.push(this) | |
} | |
// props used in v-repeat diffing | |
this._new = true | |
this._reused = false | |
// merge options. | |
options = this.$options = mergeOptions( | |
this.constructor.options, | |
options, | |
this | |
) | |
// set data after merge. | |
this._data = options.data || {} | |
// initialize data observation and scope inheritance. | |
this._initScope() | |
// 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) | |
} | |
} | |
/***/ }, | |
/* 3 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var inDoc = _.inDoc | |
/** | |
* Setup the instance's option events & watchers. | |
* If the value is a string, we pull it from the | |
* instance's methods by name. | |
*/ | |
exports._initEvents = function () { | |
var options = this.$options | |
registerCallbacks(this, '$on', options.events) | |
registerCallbacks(this, '$watch', options.watch) | |
} | |
/** | |
* 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 {*} handler | |
*/ | |
function register (vm, action, key, handler) { | |
var type = typeof handler | |
if (type === 'function') { | |
vm[action](key, handler) | |
} else if (type === 'string') { | |
var methods = vm.$options.methods | |
var method = methods && methods[handler] | |
if (method) { | |
vm[action](key, method) | |
} else { | |
_.warn( | |
'Unknown method: "' + handler + '" when ' + | |
'registering callback for ' + action + | |
': "' + key + '".' | |
) | |
} | |
} | |
} | |
/** | |
* Setup recursive attached/detached calls | |
*/ | |
exports._initDOMHooks = function () { | |
this.$on('hook:attached', onAttached) | |
this.$on('hook:detached', onDetached) | |
} | |
/** | |
* Callback to recursively call attached hook on children | |
*/ | |
function onAttached () { | |
this._isAttached = true | |
this._children.forEach(callAttach) | |
if (this._transCpnts.length) { | |
this._transCpnts.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 () { | |
this._isAttached = false | |
this._children.forEach(callDetach) | |
if (this._transCpnts.length) { | |
this._transCpnts.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 | |
*/ | |
exports._callHook = function (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) | |
} | |
/***/ }, | |
/* 4 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var Observer = __webpack_require__(49) | |
var Dep = __webpack_require__(23) | |
/** | |
* Setup the scope of an instance, which contains: | |
* - observed data | |
* - computed properties | |
* - user methods | |
* - meta properties | |
*/ | |
exports._initScope = function () { | |
this._initData() | |
this._initComputed() | |
this._initMethods() | |
this._initMeta() | |
} | |
/** | |
* Initialize the data. | |
*/ | |
exports._initData = function () { | |
// proxy data on instance | |
var data = this._data | |
var keys = Object.keys(data) | |
var i = keys.length | |
var key | |
while (i--) { | |
key = keys[i] | |
if (!_.isReserved(key)) { | |
this._proxy(key) | |
} | |
} | |
// observe data | |
Observer.create(data).addVm(this) | |
} | |
/** | |
* Swap the isntance's $data. Called in $data's setter. | |
* | |
* @param {Object} newData | |
*/ | |
exports._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 (!_.isReserved(key) && !(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 (!this.hasOwnProperty(key) && !_.isReserved(key)) { | |
// new property | |
this._proxy(key) | |
} | |
} | |
oldData.__ob__.removeVm(this) | |
Observer.create(newData).addVm(this) | |
this._digest() | |
} | |
/** | |
* Proxy a property, so that | |
* vm.prop === vm._data.prop | |
* | |
* @param {String} key | |
*/ | |
exports._proxy = function (key) { | |
// need to store ref to self here | |
// because these getter/setters might | |
// be called by child instances! | |
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 | |
*/ | |
exports._unproxy = function (key) { | |
delete this[key] | |
} | |
/** | |
* Force update on every watcher in scope. | |
*/ | |
exports._digest = function () { | |
var i = this._watcherList.length | |
while (i--) { | |
this._watcherList[i].update() | |
} | |
var children = this._children | |
i = children.length | |
while (i--) { | |
var child = children[i] | |
if (child.$options.inherit) { | |
child._digest() | |
} | |
} | |
} | |
/** | |
* Setup computed properties. They are essentially | |
* special getter/setters | |
*/ | |
function noop () {} | |
exports._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 = _.bind(userDef, this) | |
def.set = noop | |
} else { | |
def.get = userDef.get | |
? _.bind(userDef.get, this) | |
: noop | |
def.set = userDef.set | |
? _.bind(userDef.set, this) | |
: noop | |
} | |
Object.defineProperty(this, key, def) | |
} | |
} | |
} | |
/** | |
* Setup instance methods. Methods must be bound to the | |
* instance since they might be called by children | |
* inheriting them. | |
*/ | |
exports._initMethods = function () { | |
var methods = this.$options.methods | |
if (methods) { | |
for (var key in methods) { | |
this[key] = _.bind(methods[key], this) | |
} | |
} | |
} | |
/** | |
* Initialize meta information like $index, $key & $value. | |
*/ | |
exports._initMeta = function () { | |
var metas = this.$options._meta | |
if (metas) { | |
for (var key in metas) { | |
this._defineMeta(key, metas[key]) | |
} | |
} | |
} | |
/** | |
* Define a meta property, e.g $index, $key, $value | |
* which only exists on the vm instance but not in $data. | |
* | |
* @param {String} key | |
* @param {*} value | |
*/ | |
exports._defineMeta = function (key, value) { | |
var dep = new Dep() | |
Object.defineProperty(this, key, { | |
enumerable: true, | |
configurable: true, | |
get: function metaGetter () { | |
if (Observer.target) { | |
Observer.target.addDep(dep) | |
} | |
return value | |
}, | |
set: function metaSetter (val) { | |
if (val !== value) { | |
value = val | |
dep.notify() | |
} | |
} | |
}) | |
} | |
/***/ }, | |
/* 5 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var Directive = __webpack_require__(24) | |
var compile = __webpack_require__(16) | |
var transclude = __webpack_require__(17) | |
/** | |
* 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} | |
*/ | |
exports._compile = function (el) { | |
var options = this.$options | |
if (options._linkFn) { | |
// pre-transcluded with linker, just use it | |
this._initElement(el) | |
options._linkFn(this, el) | |
} else { | |
// transclude and init element | |
// transclude can potentially replace original | |
// so we need to keep reference | |
var original = el | |
el = transclude(el, options) | |
this._initElement(el) | |
// compile and link the rest | |
compile(el, options)(this, el) | |
// finally replace original | |
if (options.replace) { | |
_.replace(original, el) | |
} | |
} | |
return el | |
} | |
/** | |
* Initialize instance element. Called in the public | |
* $mount() method. | |
* | |
* @param {Element} el | |
*/ | |
exports._initElement = function (el) { | |
if (el instanceof DocumentFragment) { | |
this._isBlock = true | |
this.$el = this._blockStart = el.firstChild | |
this._blockEnd = el.lastChild | |
this._blockFragment = 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|undefined} host - transclusion host component | |
*/ | |
exports._bindDir = function (name, node, desc, def, host) { | |
this._directives.push( | |
new Directive(name, node, this, desc, def, host) | |
) | |
} | |
/** | |
* 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 | |
*/ | |
exports._destroy = function (remove, deferCleanup) { | |
if (this._isBeingDestroyed) { | |
return | |
} | |
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) { | |
i = parent._children.indexOf(this) | |
parent._children.splice(i, 1) | |
} | |
// same for transclusion host. | |
var host = this._host | |
if (host && !host._isBeingDestroyed) { | |
i = host._transCpnts.indexOf(this) | |
host._transCpnts.splice(i, 1) | |
} | |
// destroy all children. | |
i = this._children.length | |
while (i--) { | |
this._children[i].$destroy() | |
} | |
// teardown all directives. this also tearsdown all | |
// directive-owned watchers. intentionally check for | |
// directives array length on every loop since directives | |
// that manages partial compilation can splice ones out | |
for (i = 0; i < this._directives.length; i++) { | |
this._directives[i]._teardown() | |
} | |
// teardown all user watchers. | |
var watcher | |
for (i in this._userWatchers) { | |
watcher = this._userWatchers[i] | |
if (watcher) { | |
watcher.teardown() | |
} | |
} | |
// remove reference to self on $el | |
if (this.$el) { | |
this.$el.__vue__ = null | |
} | |
// remove DOM element | |
var self = this | |
if (remove && this.$el) { | |
this.$remove(function () { | |
self._cleanup() | |
}) | |
} else if (!deferCleanup) { | |
this._cleanup() | |
} | |
} | |
/** | |
* Clean up to ensure garbage collection. | |
* This is called after the leave transition if there | |
* is any. | |
*/ | |
exports._cleanup = function () { | |
// remove reference from data ob | |
this._data.__ob__.removeVm(this) | |
this._data = | |
this._watchers = | |
this._userWatchers = | |
this._watcherList = | |
this.$el = | |
this.$parent = | |
this.$root = | |
this._children = | |
this._transCpnts = | |
this._directives = null | |
// call the last hook... | |
this._isDestroyed = true | |
this._callHook('destroyed') | |
// turn off all instance listeners. | |
this.$off() | |
} | |
/***/ }, | |
/* 6 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var Watcher = __webpack_require__(25) | |
var Path = __webpack_require__(18) | |
var textParser = __webpack_require__(19) | |
var dirParser = __webpack_require__(21) | |
var expParser = __webpack_require__(22) | |
var filterRE = /[^|]\|[^|]/ | |
/** | |
* Get the value from an expression on this vm. | |
* | |
* @param {String} exp | |
* @return {*} | |
*/ | |
exports.$get = function (exp) { | |
var res = expParser.parse(exp) | |
if (res) { | |
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 | |
*/ | |
exports.$set = function (exp, val) { | |
var res = expParser.parse(exp, true) | |
if (res && res.set) { | |
res.set.call(this, this, val) | |
} | |
} | |
/** | |
* Add a property on the VM | |
* | |
* @param {String} key | |
* @param {*} val | |
*/ | |
exports.$add = function (key, val) { | |
this._data.$add(key, val) | |
} | |
/** | |
* Delete a property on the VM | |
* | |
* @param {String} key | |
*/ | |
exports.$delete = function (key) { | |
this._data.$delete(key) | |
} | |
/** | |
* Watch an expression, trigger callback when its | |
* value changes. | |
* | |
* @param {String} exp | |
* @param {Function} cb | |
* @param {Boolean} [deep] | |
* @param {Boolean} [immediate] | |
* @return {Function} - unwatchFn | |
*/ | |
exports.$watch = function (exp, cb, deep, immediate) { | |
var vm = this | |
var key = deep ? exp + '**deep**' : exp | |
var watcher = vm._userWatchers[key] | |
var wrappedCb = function (val, oldVal) { | |
cb.call(vm, val, oldVal) | |
} | |
if (!watcher) { | |
watcher = vm._userWatchers[key] = | |
new Watcher(vm, exp, wrappedCb, { | |
deep: deep, | |
user: true | |
}) | |
} else { | |
watcher.addCb(wrappedCb) | |
} | |
if (immediate) { | |
wrappedCb(watcher.value) | |
} | |
return function unwatchFn () { | |
watcher.removeCb(wrappedCb) | |
if (!watcher.active) { | |
vm._userWatchers[key] = null | |
} | |
} | |
} | |
/** | |
* Evaluate a text directive, including filters. | |
* | |
* @param {String} text | |
* @return {String} | |
*/ | |
exports.$eval = function (text) { | |
// check for filters. | |
if (filterRE.test(text)) { | |
var dir = dirParser.parse(text)[0] | |
// the filter regex check might give false positive | |
// for pipes inside strings, so it's possible that | |
// we don't get any filters here | |
return dir.filters | |
? _.applyFilters( | |
this.$get(dir.expression), | |
_.resolveFilters(this, dir.filters).read, | |
this | |
) | |
: this.$get(dir.expression) | |
} else { | |
// no filter | |
return this.$get(text) | |
} | |
} | |
/** | |
* Interpolate a piece of template text. | |
* | |
* @param {String} text | |
* @return {String} | |
*/ | |
exports.$interpolate = function (text) { | |
var tokens = textParser.parse(text) | |
var vm = this | |
if (tokens) { | |
return tokens.length === 1 | |
? vm.$eval(tokens[0].value) | |
: 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] | |
*/ | |
exports.$log = function (path) { | |
var data = path | |
? Path.get(this._data, path) | |
: this._data | |
if (data) { | |
data = JSON.parse(JSON.stringify(data)) | |
} | |
console.log(data) | |
} | |
/***/ }, | |
/* 7 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var transition = __webpack_require__(50) | |
/** | |
* Append instance to target | |
* | |
* @param {Node} target | |
* @param {Function} [cb] | |
* @param {Boolean} [withTransition] - defaults to true | |
*/ | |
exports.$appendTo = function (target, cb, withTransition) { | |
return insert( | |
this, target, cb, withTransition, | |
append, transition.append | |
) | |
} | |
/** | |
* Prepend instance to target | |
* | |
* @param {Node} target | |
* @param {Function} [cb] | |
* @param {Boolean} [withTransition] - defaults to true | |
*/ | |
exports.$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 | |
*/ | |
exports.$before = function (target, cb, withTransition) { | |
return insert( | |
this, target, cb, withTransition, | |
before, transition.before | |
) | |
} | |
/** | |
* Insert instance after target | |
* | |
* @param {Node} target | |
* @param {Function} [cb] | |
* @param {Boolean} [withTransition] - defaults to true | |
*/ | |
exports.$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 | |
*/ | |
exports.$remove = function (cb, withTransition) { | |
var inDoc = this._isAttached && _.inDoc(this.$el) | |
// if we are not in document, no need to check | |
// for transitions | |
if (!inDoc) withTransition = false | |
var op | |
var self = this | |
var realCb = function () { | |
if (inDoc) self._callHook('detached') | |
if (cb) cb() | |
} | |
if ( | |
this._isBlock && | |
!this._blockFragment.hasChildNodes() | |
) { | |
op = withTransition === false | |
? append | |
: transition.removeThenAppend | |
blockOp(this, this._blockFragment, op, realCb) | |
} else { | |
op = withTransition === false | |
? remove | |
: transition.remove | |
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._isBlock) { | |
blockOp(vm, target, op, cb) | |
} else { | |
op(vm.$el, target, vm, cb) | |
} | |
if (shouldCallHook) { | |
vm._callHook('attached') | |
} | |
return vm | |
} | |
/** | |
* Execute a transition operation on a block instance, | |
* iterating through all its block nodes. | |
* | |
* @param {Vue} vm | |
* @param {Node} target | |
* @param {Function} op | |
* @param {Function} cb | |
*/ | |
function blockOp (vm, target, op, cb) { | |
var current = vm._blockStart | |
var end = vm._blockEnd | |
var next | |
while (next !== end) { | |
next = current.nextSibling | |
op(current, target, vm) | |
current = next | |
} | |
op(end, target, vm, cb) | |
} | |
/** | |
* 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 before (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 remove (el, vm, cb) { | |
_.remove(el) | |
if (cb) cb() | |
} | |
/***/ }, | |
/* 8 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
/** | |
* Listen on the given `event` with `fn`. | |
* | |
* @param {String} event | |
* @param {Function} fn | |
*/ | |
exports.$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 | |
*/ | |
exports.$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 | |
*/ | |
exports.$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} event | |
*/ | |
exports.$emit = function (event) { | |
this._eventCancelled = false | |
var cbs = this._events[event] | |
if (cbs) { | |
// avoid leaking arguments: | |
// http://jsperf.com/closure-with-arguments | |
var i = arguments.length - 1 | |
var args = new Array(i) | |
while (i--) { | |
args[i] = arguments[i + 1] | |
} | |
i = 0 | |
cbs = cbs.length > 1 | |
? _.toArray(cbs) | |
: cbs | |
for (var l = cbs.length; i < l; i++) { | |
if (cbs[i].apply(this, args) === false) { | |
this._eventCancelled = true | |
} | |
} | |
} | |
return this | |
} | |
/** | |
* Recursively broadcast an event to all children instances. | |
* | |
* @param {String} event | |
* @param {...*} additional arguments | |
*/ | |
exports.$broadcast = function (event) { | |
// if no child has registered for this event, | |
// then there's no need to broadcast. | |
if (!this._eventsCount[event]) return | |
var children = this._children | |
for (var i = 0, l = children.length; i < l; i++) { | |
var child = children[i] | |
child.$emit.apply(child, arguments) | |
if (!child._eventCancelled) { | |
child.$broadcast.apply(child, arguments) | |
} | |
} | |
return this | |
} | |
/** | |
* Recursively propagate an event up the parent chain. | |
* | |
* @param {String} event | |
* @param {...*} additional arguments | |
*/ | |
exports.$dispatch = function () { | |
var parent = this.$parent | |
while (parent) { | |
parent.$emit.apply(parent, arguments) | |
parent = parent._eventCancelled | |
? null | |
: parent.$parent | |
} | |
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 | |
} | |
} | |
/***/ }, | |
/* 9 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
/** | |
* Create a child instance that prototypally inehrits | |
* data on parent. To achieve that we create an intermediate | |
* constructor with its prototype pointing to parent. | |
* | |
* @param {Object} opts | |
* @param {Function} [BaseCtor] | |
* @return {Vue} | |
* @public | |
*/ | |
exports.$addChild = function (opts, BaseCtor) { | |
BaseCtor = BaseCtor || _.Vue | |
opts = opts || {} | |
var parent = this | |
var ChildVue | |
var inherit = opts.inherit !== undefined | |
? opts.inherit | |
: BaseCtor.options.inherit | |
if (inherit) { | |
var ctors = parent._childCtors | |
ChildVue = ctors[BaseCtor.cid] | |
if (!ChildVue) { | |
var optionName = BaseCtor.options.name | |
var className = optionName | |
? _.classify(optionName) | |
: 'VueComponent' | |
ChildVue = new Function( | |
'return function ' + className + ' (options) {' + | |
'this.constructor = ' + className + ';' + | |
'this._init(options) }' | |
)() | |
ChildVue.options = BaseCtor.options | |
ChildVue.prototype = this | |
ctors[BaseCtor.cid] = ChildVue | |
} | |
} else { | |
ChildVue = BaseCtor | |
} | |
opts._parent = parent | |
opts._root = parent.$root | |
var child = new ChildVue(opts) | |
return child | |
} | |
/***/ }, | |
/* 10 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var compile = __webpack_require__(16) | |
/** | |
* 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 | |
*/ | |
exports.$mount = function (el) { | |
if (this._isCompiled) { | |
_.warn('$mount() should be called only once.') | |
return | |
} | |
if (!el) { | |
el = document.createElement('div') | |
} else if (typeof el === 'string') { | |
var selector = el | |
el = document.querySelector(el) | |
if (!el) { | |
_.warn('Cannot find element: ' + selector) | |
return | |
} | |
} | |
this._compile(el) | |
this._isCompiled = true | |
this._callHook('compiled') | |
if (_.inDoc(this.$el)) { | |
this._callHook('attached') | |
this._initDOMHooks() | |
ready.call(this) | |
} else { | |
this._initDOMHooks() | |
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. | |
*/ | |
exports.$destroy = function (remove, deferCleanup) { | |
this._destroy(remove, deferCleanup) | |
} | |
/** | |
* Partially compile a piece of DOM and return a | |
* decompile function. | |
* | |
* @param {Element|DocumentFragment} el | |
* @return {Function} | |
*/ | |
exports.$compile = function (el) { | |
return compile(el, this.$options, true)(this, el) | |
} | |
/***/ }, | |
/* 11 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var lang = __webpack_require__(26) | |
var extend = lang.extend | |
extend(exports, lang) | |
extend(exports, __webpack_require__(27)) | |
extend(exports, __webpack_require__(28)) | |
extend(exports, __webpack_require__(29)) | |
extend(exports, __webpack_require__(30)) | |
/***/ }, | |
/* 12 */ | |
/***/ function(module, exports, __webpack_require__) { | |
// manipulation directives | |
exports.text = __webpack_require__(31) | |
exports.html = __webpack_require__(32) | |
exports.attr = __webpack_require__(33) | |
exports.show = __webpack_require__(34) | |
exports['class'] = __webpack_require__(35) | |
exports.el = __webpack_require__(36) | |
exports.ref = __webpack_require__(37) | |
exports.cloak = __webpack_require__(38) | |
exports.style = __webpack_require__(39) | |
exports.partial = __webpack_require__(40) | |
exports.transition = __webpack_require__(41) | |
// event listener directives | |
exports.on = __webpack_require__(42) | |
exports.model = __webpack_require__(51) | |
// child vm directives | |
exports.component = __webpack_require__(43) | |
exports.repeat = __webpack_require__(44) | |
exports['if'] = __webpack_require__(45) | |
// child vm communication directives | |
exports['with'] = __webpack_require__(46) | |
exports.events = __webpack_require__(47) | |
/***/ }, | |
/* 13 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
/** | |
* Stringify value. | |
* | |
* @param {Number} indent | |
*/ | |
exports.json = { | |
read: function (value, indent) { | |
return typeof value === 'string' | |
? value | |
: JSON.stringify(value, null, Number(indent) || 2) | |
}, | |
write: function (value) { | |
try { | |
return JSON.parse(value) | |
} catch (e) { | |
return value | |
} | |
} | |
} | |
/** | |
* 'abc' => 'Abc' | |
*/ | |
exports.capitalize = function (value) { | |
if (!value && value !== 0) return '' | |
value = value.toString() | |
return value.charAt(0).toUpperCase() + value.slice(1) | |
} | |
/** | |
* 'abc' => 'ABC' | |
*/ | |
exports.uppercase = function (value) { | |
return (value || value === 0) | |
? value.toString().toUpperCase() | |
: '' | |
} | |
/** | |
* 'AbC' => 'abc' | |
*/ | |
exports.lowercase = function (value) { | |
return (value || value === 0) | |
? value.toString().toLowerCase() | |
: '' | |
} | |
/** | |
* 12345 => $12,345.00 | |
* | |
* @param {String} sign | |
*/ | |
var digitsRE = /(\d{3})(?=\d)/g | |
exports.currency = function (value, sign) { | |
value = parseFloat(value) | |
if (!isFinite(value) || (!value && value !== 0)) return '' | |
sign = sign || '$' | |
var s = Math.floor(Math.abs(value)).toString(), | |
i = s.length % 3, | |
h = i > 0 | |
? (s.slice(0, i) + (s.length > 3 ? ',' : '')) | |
: '', | |
v = Math.abs(parseInt((value * 100) % 100, 10)), | |
f = '.' + (v < 10 ? ('0' + v) : v) | |
return (value < 0 ? '-' : '') + | |
sign + h + s.slice(i).replace(digitsRE, '$1,') + f | |
} | |
/** | |
* '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'] | |
*/ | |
exports.pluralize = function (value) { | |
var args = _.toArray(arguments, 1) | |
return args.length > 1 | |
? (args[value % 10 - 1] || args[args.length - 1]) | |
: (args[0] + (value === 1 ? '' : 's')) | |
} | |
/** | |
* A special filter that takes a handler function, | |
* wraps it so it only gets triggered on specific | |
* keypresses. v-on only. | |
* | |
* @param {String} key | |
*/ | |
var keyCodes = { | |
enter : 13, | |
tab : 9, | |
'delete' : 46, | |
up : 38, | |
left : 37, | |
right : 39, | |
down : 40, | |
esc : 27 | |
} | |
exports.key = function (handler, key) { | |
if (!handler) return | |
var code = keyCodes[key] | |
if (!code) { | |
code = parseInt(key, 10) | |
} | |
return function (e) { | |
if (e.keyCode === code) { | |
return handler.call(this, e) | |
} | |
} | |
} | |
// expose keycode hash | |
exports.key.keyCodes = keyCodes | |
/** | |
* Install special array filters | |
*/ | |
_.extend(exports, __webpack_require__(48)) | |
/***/ }, | |
/* 14 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var extend = _.extend | |
/** | |
* 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 = 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 (!to.hasOwnProperty(key)) { | |
to.$add(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') { | |
_.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 { | |
// instance merge, return raw object | |
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') { | |
_.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.created = | |
strats.ready = | |
strats.attached = | |
strats.detached = | |
strats.beforeCompile = | |
strats.compiled = | |
strats.beforeDestroy = | |
strats.destroyed = | |
strats.paramAttributes = function (parentVal, childVal) { | |
return childVal | |
? parentVal | |
? parentVal.concat(childVal) | |
: _.isArray(childVal) | |
? childVal | |
: [childVal] | |
: parentVal | |
} | |
/** | |
* Assets | |
* | |
* When a vm is present (instance creation), we need to do | |
* a three-way merge between constructor options, instance | |
* options and parent options. | |
*/ | |
strats.directives = | |
strats.filters = | |
strats.partials = | |
strats.transitions = | |
strats.components = function (parentVal, childVal, vm, key) { | |
var ret = Object.create( | |
vm && vm.$parent | |
? vm.$parent.$options[key] | |
: _.Vue.options[key] | |
) | |
if (parentVal) { | |
var keys = Object.keys(parentVal) | |
var i = keys.length | |
var field | |
while (i--) { | |
field = keys[i] | |
ret[field] = parentVal[field] | |
} | |
} | |
if (childVal) extend(ret, childVal) | |
return ret | |
} | |
/** | |
* 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.methods = | |
strats.computed = function (parentVal, childVal) { | |
if (!childVal) return parentVal | |
if (!parentVal) return childVal | |
var ret = Object.create(parentVal) | |
extend(ret, childVal) | |
return ret | |
} | |
/** | |
* Default strategy. | |
*/ | |
var defaultStrat = function (parentVal, childVal) { | |
return childVal === undefined | |
? parentVal | |
: childVal | |
} | |
/** | |
* Make sure component options get converted to actual | |
* constructors. | |
* | |
* @param {Object} components | |
*/ | |
function guardComponents (components) { | |
if (components) { | |
var def | |
for (var key in components) { | |
def = components[key] | |
if (_.isPlainObject(def)) { | |
def.name = key | |
components[key] = _.Vue.extend(def) | |
} | |
} | |
} | |
} | |
/** | |
* 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. | |
*/ | |
module.exports = function mergeOptions (parent, child, vm) { | |
guardComponents(child.components) | |
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) { | |
merge(key) | |
} | |
for (key in child) { | |
if (!(parent.hasOwnProperty(key))) { | |
merge(key) | |
} | |
} | |
function merge (key) { | |
var strat = strats[key] || defaultStrat | |
options[key] = strat(parent[key], child[key], vm, key) | |
} | |
return options | |
} | |
/***/ }, | |
/* 15 */ | |
/***/ function(module, exports, __webpack_require__) { | |
module.exports = { | |
/** | |
* The prefix to look for when parsing directives. | |
* | |
* @type {String} | |
*/ | |
prefix: 'v-', | |
/** | |
* Whether to print debug messages. | |
* Also enables stack trace for warnings. | |
* | |
* @type {Boolean} | |
*/ | |
debug: false, | |
/** | |
* Whether to suppress warnings. | |
* | |
* @type {Boolean} | |
*/ | |
silent: false, | |
/** | |
* Whether allow observer to alter data objects' | |
* __proto__. | |
* | |
* @type {Boolean} | |
*/ | |
proto: true, | |
/** | |
* Whether to parse mustache tags in templates. | |
* | |
* @type {Boolean} | |
*/ | |
interpolate: true, | |
/** | |
* Whether to use async rendering. | |
*/ | |
async: true, | |
/** | |
* Whether to warn against errors caught when evaluating | |
* expressions. | |
*/ | |
warnExpressionErrors: true, | |
/** | |
* Internal flag to indicate the delimiters have been | |
* changed. | |
* | |
* @type {Boolean} | |
*/ | |
_delimitersChanged: true | |
} | |
/** | |
* Interpolation delimiters. | |
* We need to mark the changed flag so that the text parser | |
* knows it needs to recompile the regex. | |
* | |
* @type {Array<String>} | |
*/ | |
var delimiters = ['{{', '}}'] | |
Object.defineProperty(module.exports, 'delimiters', { | |
get: function () { | |
return delimiters | |
}, | |
set: function (val) { | |
delimiters = val | |
this._delimitersChanged = true | |
} | |
}) | |
/***/ }, | |
/* 16 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var config = __webpack_require__(15) | |
var textParser = __webpack_require__(19) | |
var dirParser = __webpack_require__(21) | |
var templateParser = __webpack_require__(20) | |
module.exports = compile | |
/** | |
* Compile a template and return a reusable composite link | |
* function, which recursively contains more link functions | |
* inside. This top level compile function should only be | |
* called on instance root nodes. | |
* | |
* @param {Element|DocumentFragment} el | |
* @param {Object} options | |
* @param {Boolean} partial | |
* @param {Boolean} transcluded | |
* @return {Function} | |
*/ | |
function compile (el, options, partial, transcluded) { | |
var isBlock = el.nodeType === 11 | |
// link function for param attributes. | |
var params = options.paramAttributes | |
var paramsLinkFn = params && !partial && !transcluded && !isBlock | |
? compileParamAttributes(el, params, options) | |
: null | |
// link function for the node itself. | |
// if this is a block instance, we return a link function | |
// for the attributes found on the container, if any. | |
// options._containerAttrs are collected during transclusion. | |
var nodeLinkFn = isBlock | |
? compileBlockContainer(options._containerAttrs, params, options) | |
: compileNode(el, options) | |
// 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 | |
* @return {Function|undefined} | |
*/ | |
function compositeLinkFn (vm, el) { | |
var originalDirCount = vm._directives.length | |
var parentOriginalDirCount = | |
vm.$parent && vm.$parent._directives.length | |
if (paramsLinkFn) { | |
paramsLinkFn(vm, el) | |
} | |
// cache childNodes before linking parent, fix #657 | |
var childNodes = _.toArray(el.childNodes) | |
// if this is a transcluded compile, linkers need to be | |
// called in source scope, and the host needs to be | |
// passed down. | |
var source = transcluded ? vm.$parent : vm | |
var host = transcluded ? vm : undefined | |
// link | |
if (nodeLinkFn) nodeLinkFn(source, el, host) | |
if (childLinkFn) childLinkFn(source, childNodes, host) | |
/** | |
* If this is a partial compile, the linker function | |
* returns an unlink function that tearsdown all | |
* directives instances generated during the partial | |
* linking. | |
*/ | |
if (partial && !transcluded) { | |
var selfDirs = vm._directives.slice(originalDirCount) | |
var parentDirs = vm.$parent && | |
vm.$parent._directives.slice(parentOriginalDirCount) | |
var teardownDirs = function (vm, dirs) { | |
var i = dirs.length | |
while (i--) { | |
dirs[i]._teardown() | |
} | |
i = vm._directives.indexOf(dirs[0]) | |
vm._directives.splice(i, dirs.length) | |
} | |
return function unlink () { | |
teardownDirs(vm, selfDirs) | |
if (parentDirs) { | |
teardownDirs(vm.$parent, parentDirs) | |
} | |
} | |
} | |
} | |
// transcluded linkFns are terminal, because it takes | |
// over the entire sub-tree. | |
if (transcluded) { | |
compositeLinkFn.terminal = true | |
} | |
return compositeLinkFn | |
} | |
/** | |
* Compile the attributes found on a "block container" - | |
* i.e. the container node in the parent tempate of a block | |
* instance. We are only concerned with v-with and | |
* paramAttributes here. | |
* | |
* @param {Object} attrs - a map of attr name/value pairs | |
* @param {Array} params - param attributes list | |
* @param {Object} options | |
* @return {Function} | |
*/ | |
function compileBlockContainer (attrs, params, options) { | |
if (!attrs) return null | |
var paramsLinkFn = params | |
? compileParamAttributes(attrs, params, options) | |
: null | |
var withVal = attrs[config.prefix + 'with'] | |
var withLinkFn = null | |
if (withVal) { | |
var descriptor = dirParser.parse(withVal)[0] | |
var def = options.directives['with'] | |
withLinkFn = function (vm, el) { | |
vm._bindDir('with', el, descriptor, def) | |
} | |
} | |
return function blockContainerLinkFn (vm) { | |
// explicitly passing null to the linkers | |
// since v-with doesn't need a real element | |
if (paramsLinkFn) paramsLinkFn(vm, null) | |
if (withLinkFn) withLinkFn(vm, null) | |
} | |
} | |
/** | |
* 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 && config.interpolate && 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) { | |
if (checkTransclusion(el)) { | |
// unwrap textNode | |
if (el.hasAttribute('__vue__wrap')) { | |
el = el.firstChild | |
} | |
return compile(el, options._parent.$options, true, true) | |
} | |
var linkFn, tag, component | |
// check custom element component, but only on non-root | |
if (!el.__vue__) { | |
tag = el.tagName.toLowerCase() | |
component = | |
tag.indexOf('-') > 0 && | |
options.components[tag] | |
if (component) { | |
el.setAttribute(config.prefix + 'component', tag) | |
} | |
} | |
if (component || el.hasAttributes()) { | |
// check terminal direcitves | |
linkFn = checkTerminalDirectives(el, options) | |
// if not terminal, build normal link function | |
if (!linkFn) { | |
var dirs = collectDirectives(el, options) | |
linkFn = dirs.length | |
? makeNodeLinkFn(dirs) | |
: null | |
} | |
} | |
// if the element is a textarea, we need to interpolate | |
// its content on initial render. | |
if (el.tagName === 'TEXTAREA') { | |
var realLinkFn = linkFn | |
linkFn = function (vm, el) { | |
el.value = vm.$interpolate(el.value) | |
if (realLinkFn) realLinkFn(vm, el) | |
} | |
linkFn.terminal = true | |
} | |
return linkFn | |
} | |
/** | |
* 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) { | |
// reverse apply because it's sorted low to high | |
var i = directives.length | |
var dir, j, k, target | |
while (i--) { | |
dir = directives[i] | |
// a directive can be transcluded if it's written | |
// on a component's container in its parent tempalte. | |
target = dir.transcluded | |
? vm.$parent | |
: vm | |
if (dir._link) { | |
// custom link fn | |
dir._link(target, el) | |
} else { | |
k = dir.descriptors.length | |
for (j = 0; j < k; j++) { | |
target._bindDir(dir.name, el, | |
dir.descriptors[j], dir.def, host) | |
} | |
} | |
} | |
} | |
} | |
/** | |
* Compile a textNode and return a nodeLinkFn. | |
* | |
* @param {TextNode} node | |
* @param {Object} options | |
* @return {Function|null} textNodeLinkFn | |
*/ | |
function compileTextNode (node, options) { | |
var tokens = textParser.parse(node.data) | |
if (!tokens) { | |
return null | |
} | |
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) | |
} | |
/** | |
* 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 if (token.partial) { | |
el = document.createComment('v-partial') | |
setTokenType('partial') | |
} 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) { | |
token.type = type | |
token.def = options.directives[type] | |
token.descriptor = dirParser.parse(token.value)[0] | |
} | |
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) { | |
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 = vm.$eval(value) | |
if (token.html) { | |
_.replace(node, templateParser.parse(value, true)) | |
} else { | |
node.data = value | |
} | |
} else { | |
vm._bindDir(token.type, node, | |
token.descriptor, token.def) | |
} | |
} | |
} | |
_.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) { | |
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) | |
} | |
if (childrenLinkFn) { | |
childrenLinkFn(vm, childNodes, host) | |
} | |
} | |
} | |
} | |
/** | |
* Compile param attributes on a root element and return | |
* a paramAttributes link function. | |
* | |
* @param {Element|Object} el | |
* @param {Array} attrs | |
* @param {Object} options | |
* @return {Function} paramsLinkFn | |
*/ | |
function compileParamAttributes (el, attrs, options) { | |
var params = [] | |
var isEl = el.nodeType | |
var i = attrs.length | |
var name, value, param | |
while (i--) { | |
name = attrs[i] | |
if (/[A-Z]/.test(name)) { | |
_.warn( | |
'You seem to be using camelCase for a paramAttribute, ' + | |
'but HTML doesn\'t differentiate between upper and ' + | |
'lower case. You should use hyphen-delimited ' + | |
'attribute names. For more info see ' + | |
'http://vuejs.org/api/options.html#paramAttributes' | |
) | |
} | |
value = isEl ? el.getAttribute(name) : el[name] | |
if (value !== null) { | |
param = { | |
name: name, | |
value: value | |
} | |
var tokens = textParser.parse(value) | |
if (tokens) { | |
if (isEl) el.removeAttribute(name) | |
if (tokens.length > 1) { | |
_.warn( | |
'Invalid param attribute binding: "' + | |
name + '="' + value + '"' + | |
'\nDon\'t mix binding tags with plain text ' + | |
'in param attribute bindings.' | |
) | |
continue | |
} else { | |
param.dynamic = true | |
param.value = tokens[0].value | |
} | |
} | |
params.push(param) | |
} | |
} | |
return makeParamsLinkFn(params, options) | |
} | |
/** | |
* Build a function that applies param attributes to a vm. | |
* | |
* @param {Array} params | |
* @param {Object} options | |
* @return {Function} paramsLinkFn | |
*/ | |
var dataAttrRE = /^data-/ | |
function makeParamsLinkFn (params, options) { | |
var def = options.directives['with'] | |
return function paramsLinkFn (vm, el) { | |
var i = params.length | |
var param, path | |
while (i--) { | |
param = params[i] | |
// params could contain dashes, which will be | |
// interpreted as minus calculations by the parser | |
// so we need to wrap the path here | |
path = _.camelize(param.name.replace(dataAttrRE, '')) | |
if (param.dynamic) { | |
// dynamic param attribtues are bound as v-with. | |
// we can directly duck the descriptor here beacuse | |
// param attributes cannot use expressions or | |
// filters. | |
vm._bindDir('with', el, { | |
arg: path, | |
expression: param.value | |
}, def) | |
} else { | |
// just set once | |
vm.$set(path, param.value) | |
} | |
} | |
} | |
} | |
/** | |
* 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 | |
*/ | |
var terminalDirectives = [ | |
'repeat', | |
'if', | |
'component' | |
] | |
function skip () {} | |
skip.terminal = true | |
function checkTerminalDirectives (el, options) { | |
if (_.attr(el, 'pre') !== null) { | |
return skip | |
} | |
var value, dirName | |
/* jshint boss: true */ | |
for (var i = 0; i < 3; i++) { | |
dirName = terminalDirectives[i] | |
if (value = _.attr(el, dirName)) { | |
return makeTerminalNodeLinkFn(el, dirName, value, options) | |
} | |
} | |
} | |
/** | |
* 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 | |
* @return {Function} terminalLinkFn | |
*/ | |
function makeTerminalNodeLinkFn (el, dirName, value, options) { | |
var descriptor = dirParser.parse(value)[0] | |
var def = options.directives[dirName] | |
var fn = function terminalNodeLinkFn (vm, el, host) { | |
vm._bindDir(dirName, el, descriptor, def, host) | |
} | |
fn.terminal = true | |
return fn | |
} | |
/** | |
* Collect the directives on an element. | |
* | |
* @param {Element} el | |
* @param {Object} options | |
* @return {Array} | |
*/ | |
function collectDirectives (el, options) { | |
var attrs = _.toArray(el.attributes) | |
var i = attrs.length | |
var dirs = [] | |
var attr, attrName, dir, dirName, dirDef, transcluded | |
while (i--) { | |
attr = attrs[i] | |
attrName = attr.name | |
transcluded = | |
options._transcludedAttrs && | |
options._transcludedAttrs[attrName] | |
if (attrName.indexOf(config.prefix) === 0) { | |
dirName = attrName.slice(config.prefix.length) | |
dirDef = options.directives[dirName] | |
_.assertAsset(dirDef, 'directive', dirName) | |
if (dirDef) { | |
dirs.push({ | |
name: dirName, | |
descriptors: dirParser.parse(attr.value), | |
def: dirDef, | |
transcluded: transcluded | |
}) | |
} | |
} else if (config.interpolate) { | |
dir = collectAttrDirective(el, attrName, attr.value, | |
options) | |
if (dir) { | |
dir.transcluded = transcluded | |
dirs.push(dir) | |
} | |
} | |
} | |
// sort by priority, LOW to HIGH | |
dirs.sort(directiveComparator) | |
return dirs | |
} | |
/** | |
* Check an attribute for potential dynamic bindings, | |
* and return a directive object. | |
* | |
* @param {Element} el | |
* @param {String} name | |
* @param {String} value | |
* @param {Object} options | |
* @return {Object} | |
*/ | |
function collectAttrDirective (el, name, value, options) { | |
var tokens = textParser.parse(value) | |
if (tokens) { | |
var def = options.directives.attr | |
var i = tokens.length | |
var allOneTime = true | |
while (i--) { | |
var token = tokens[i] | |
if (token.tag && !token.oneTime) { | |
allOneTime = false | |
} | |
} | |
return { | |
def: def, | |
_link: allOneTime | |
? function (vm, el) { | |
el.setAttribute(name, vm.$interpolate(value)) | |
} | |
: function (vm, el) { | |
var value = textParser.tokensToExp(tokens, vm) | |
var desc = dirParser.parse(name + ':' + value)[0] | |
vm._bindDir('attr', el, desc, def) | |
} | |
} | |
} | |
} | |
/** | |
* Directive priority sort comparator | |
* | |
* @param {Object} a | |
* @param {Object} b | |
*/ | |
function directiveComparator (a, b) { | |
a = a.def.priority || 0 | |
b = b.def.priority || 0 | |
return a > b ? 1 : -1 | |
} | |
/** | |
* Check whether an element is transcluded | |
* | |
* @param {Element} el | |
* @return {Boolean} | |
*/ | |
var transcludedFlagAttr = '__vue__transcluded' | |
function checkTransclusion (el) { | |
if (el.nodeType === 1 && el.hasAttribute(transcludedFlagAttr)) { | |
el.removeAttribute(transcludedFlagAttr) | |
return true | |
} | |
} | |
/***/ }, | |
/* 17 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var config = __webpack_require__(15) | |
var templateParser = __webpack_require__(20) | |
var transcludedFlagAttr = '__vue__transcluded' | |
/** | |
* 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-repeat. | |
* | |
* @param {Element} el | |
* @param {Object} options | |
* @return {Element|DocumentFragment} | |
*/ | |
module.exports = function transclude (el, options) { | |
if (options && options._asComponent) { | |
// mutating the options object here assuming the same | |
// object will be used for compile right after this | |
options._transcludedAttrs = extractAttrs(el.attributes) | |
// Mark content nodes and attrs so that the compiler | |
// knows they should be compiled in parent scope. | |
var i = el.childNodes.length | |
while (i--) { | |
var node = el.childNodes[i] | |
if (node.nodeType === 1) { | |
node.setAttribute(transcludedFlagAttr, '') | |
} else if (node.nodeType === 3 && node.data.trim()) { | |
// wrap transcluded textNodes in spans, because | |
// raw textNodes can't be persisted through clones | |
// by attaching attributes. | |
var wrapper = document.createElement('span') | |
wrapper.textContent = node.data | |
wrapper.setAttribute('__vue__wrap', '') | |
wrapper.setAttribute(transcludedFlagAttr, '') | |
el.replaceChild(wrapper, node) | |
} | |
} | |
} | |
// for template tags, what we want is its content as | |
// a documentFragment (for block instances) | |
if (el.tagName === 'TEMPLATE') { | |
el = templateParser.parse(el) | |
} | |
if (options && options.template) { | |
el = transcludeTemplate(el, options) | |
} | |
if (el instanceof DocumentFragment) { | |
_.prepend(document.createComment('v-start'), el) | |
el.appendChild(document.createComment('v-end')) | |
} | |
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 = templateParser.parse(template, true) | |
if (!frag) { | |
_.warn('Invalid template option: ' + template) | |
} else { | |
var rawContent = options._content || _.extractContent(el) | |
if (options.replace) { | |
if (frag.childNodes.length > 1) { | |
// this is a block instance which has no root node. | |
// however, the container in the parent template | |
// (which is replaced here) may contain v-with and | |
// paramAttributes that still need to be compiled | |
// for the child. we store all the container | |
// attributes on the options object and pass it down | |
// to the compiler. | |
var containerAttrs = options._containerAttrs = {} | |
var i = el.attributes.length | |
while (i--) { | |
var attr = el.attributes[i] | |
containerAttrs[attr.name] = attr.value | |
} | |
transcludeContent(frag, rawContent) | |
return frag | |
} else { | |
var replacer = frag.firstChild | |
_.copyAttributes(el, replacer) | |
transcludeContent(replacer, rawContent) | |
return replacer | |
} | |
} else { | |
el.appendChild(frag) | |
transcludeContent(el, rawContent) | |
return el | |
} | |
} | |
} | |
/** | |
* Resolve <content> insertion points mimicking the behavior | |
* of the Shadow DOM spec: | |
* | |
* http://w3c.github.io/webcomponents/spec/shadow/#insertion-points | |
* | |
* @param {Element|DocumentFragment} el | |
* @param {Element} raw | |
*/ | |
function transcludeContent (el, raw) { | |
var outlets = getOutlets(el) | |
var i = outlets.length | |
if (!i) return | |
var outlet, select, selected, j, main | |
function isDirectChild (node) { | |
return node.parentNode === raw | |
} | |
// first pass, collect corresponding content | |
// for each outlet. | |
while (i--) { | |
outlet = outlets[i] | |
if (raw) { | |
select = outlet.getAttribute('select') | |
if (select) { // select content | |
selected = raw.querySelectorAll(select) | |
if (selected.length) { | |
// according to Shadow DOM spec, `select` can | |
// only select direct children of the host node. | |
// enforcing this also fixes #786. | |
selected = [].filter.call(selected, isDirectChild) | |
} | |
outlet.content = selected.length | |
? selected | |
: _.toArray(outlet.childNodes) | |
} else { // default content | |
main = outlet | |
} | |
} else { // fallback content | |
outlet.content = _.toArray(outlet.childNodes) | |
} | |
} | |
// second pass, actually insert the contents | |
for (i = 0, j = outlets.length; i < j; i++) { | |
outlet = outlets[i] | |
if (outlet !== main) { | |
insertContentAt(outlet, outlet.content) | |
} | |
} | |
// finally insert the main content | |
if (main) { | |
insertContentAt(main, _.toArray(raw.childNodes)) | |
} | |
} | |
/** | |
* Get <content> outlets from the element/list | |
* | |
* @param {Element|Array} el | |
* @return {Array} | |
*/ | |
var concat = [].concat | |
function getOutlets (el) { | |
return _.isArray(el) | |
? concat.apply([], el.map(getOutlets)) | |
: el.querySelectorAll | |
? _.toArray(el.querySelectorAll('content')) | |
: [] | |
} | |
/** | |
* Insert an array of nodes at outlet, | |
* then remove the outlet. | |
* | |
* @param {Element} outlet | |
* @param {Array} contents | |
*/ | |
function insertContentAt (outlet, contents) { | |
// not using util DOM methods here because | |
// parentNode can be cached | |
var parent = outlet.parentNode | |
for (var i = 0, j = contents.length; i < j; i++) { | |
parent.insertBefore(contents[i], outlet) | |
} | |
parent.removeChild(outlet) | |
} | |
/** | |
* Helper to extract a component container's attribute names | |
* into a map, and filtering out `v-with` in the process. | |
* The resulting map will be used in compiler/compile to | |
* determine whether an attribute is transcluded. | |
* | |
* @param {NameNodeMap} attrs | |
*/ | |
function extractAttrs (attrs) { | |
if (!attrs) return null | |
var res = {} | |
var vwith = config.prefix + 'with' | |
var i = attrs.length | |
while (i--) { | |
var name = attrs[i].name | |
if (name !== vwith) res[name] = true | |
} | |
return res | |
} | |
/***/ }, | |
/* 18 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var Cache = __webpack_require__(52) | |
var pathCache = new Cache(1000) | |
var identRE = /^[$_a-zA-Z]+[\w$]*$/ | |
/** | |
* Path-parsing algorithm scooped from Polymer/observe-js | |
*/ | |
var pathStateMachine = { | |
'beforePath': { | |
'ws': ['beforePath'], | |
'ident': ['inIdent', 'append'], | |
'[': ['beforeElement'], | |
'eof': ['afterPath'] | |
}, | |
'inPath': { | |
'ws': ['inPath'], | |
'.': ['beforeIdent'], | |
'[': ['beforeElement'], | |
'eof': ['afterPath'] | |
}, | |
'beforeIdent': { | |
'ws': ['beforeIdent'], | |
'ident': ['inIdent', 'append'] | |
}, | |
'inIdent': { | |
'ident': ['inIdent', 'append'], | |
'0': ['inIdent', 'append'], | |
'number': ['inIdent', 'append'], | |
'ws': ['inPath', 'push'], | |
'.': ['beforeIdent', 'push'], | |
'[': ['beforeElement', 'push'], | |
'eof': ['afterPath', 'push'] | |
}, | |
'beforeElement': { | |
'ws': ['beforeElement'], | |
'0': ['afterZero', 'append'], | |
'number': ['inIndex', 'append'], | |
"'": ['inSingleQuote', 'append', ''], | |
'"': ['inDoubleQuote', 'append', ''] | |
}, | |
'afterZero': { | |
'ws': ['afterElement', 'push'], | |
']': ['inPath', 'push'] | |
}, | |
'inIndex': { | |
'0': ['inIndex', 'append'], | |
'number': ['inIndex', 'append'], | |
'ws': ['afterElement'], | |
']': ['inPath', 'push'] | |
}, | |
'inSingleQuote': { | |
"'": ['afterElement'], | |
'eof': 'error', | |
'else': ['inSingleQuote', 'append'] | |
}, | |
'inDoubleQuote': { | |
'"': ['afterElement'], | |
'eof': 'error', | |
'else': ['inDoubleQuote', 'append'] | |
}, | |
'afterElement': { | |
'ws': ['afterElement'], | |
']': ['inPath', 'push'] | |
} | |
} | |
function noop () {} | |
/** | |
* Determine the type of a character in a keypath. | |
* | |
* @param {Char} char | |
* @return {String} type | |
*/ | |
function getPathCharType (char) { | |
if (char === undefined) { | |
return 'eof' | |
} | |
var code = char.charCodeAt(0) | |
switch(code) { | |
case 0x5B: // [ | |
case 0x5D: // ] | |
case 0x2E: // . | |
case 0x22: // " | |
case 0x27: // ' | |
case 0x30: // 0 | |
return char | |
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 ((0x61 <= code && code <= 0x7A) || | |
(0x41 <= code && code <= 0x5A)) { | |
return 'ident' | |
} | |
// 1-9 | |
if (0x31 <= code && code <= 0x39) { | |
return 'number' | |
} | |
return 'else' | |
} | |
/** | |
* Parse a string path into an array of segments | |
* Todo implement cache | |
* | |
* @param {String} path | |
* @return {Array|undefined} | |
*/ | |
function parsePath (path) { | |
var keys = [] | |
var index = -1 | |
var mode = 'beforePath' | |
var c, newChar, key, type, transition, action, typeMap | |
var actions = { | |
push: function() { | |
if (key === undefined) { | |
return | |
} | |
keys.push(key) | |
key = undefined | |
}, | |
append: function() { | |
if (key === undefined) { | |
key = newChar | |
} else { | |
key += newChar | |
} | |
} | |
} | |
function maybeUnescapeQuote () { | |
var nextChar = path[index + 1] | |
if ((mode === 'inSingleQuote' && nextChar === "'") || | |
(mode === 'inDoubleQuote' && nextChar === '"')) { | |
index++ | |
newChar = nextChar | |
actions.append() | |
return true | |
} | |
} | |
while (mode) { | |
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]] || noop | |
newChar = transition[2] === undefined | |
? c | |
: transition[2] | |
action() | |
if (mode === 'afterPath') { | |
return keys | |
} | |
} | |
} | |
/** | |
* Format a accessor segment based on its type. | |
* | |
* @param {String} key | |
* @return {Boolean} | |
*/ | |
function formatAccessor(key) { | |
if (identRE.test(key)) { // identifier | |
return '.' + key | |
} else if (+key === key >>> 0) { // bracket index | |
return '[' + key + ']' | |
} else { // bracket string | |
return '["' + key.replace(/"/g, '\\"') + '"]' | |
} | |
} | |
/** | |
* Compiles a getter function with a fixed path. | |
* | |
* @param {Array} path | |
* @return {Function} | |
*/ | |
exports.compileGetter = function (path) { | |
var body = 'return o' + path.map(formatAccessor).join('') | |
return new Function('o', body) | |
} | |
/** | |
* External parse that check for a cache hit first | |
* | |
* @param {String} path | |
* @return {Array|undefined} | |
*/ | |
exports.parse = function (path) { | |
var hit = pathCache.get(path) | |
if (!hit) { | |
hit = parsePath(path) | |
if (hit) { | |
hit.get = exports.compileGetter(hit) | |
pathCache.put(path, hit) | |
} | |
} | |
return hit | |
} | |
/** | |
* Get from an object from a path string | |
* | |
* @param {Object} obj | |
* @param {String} path | |
*/ | |
exports.get = function (obj, path) { | |
path = exports.parse(path) | |
if (path) { | |
return path.get(obj) | |
} | |
} | |
/** | |
* Set on an object from a path | |
* | |
* @param {Object} obj | |
* @param {String | Array} path | |
* @param {*} val | |
*/ | |
exports.set = function (obj, path, val) { | |
if (typeof path === 'string') { | |
path = exports.parse(path) | |
} | |
if (!path || !_.isObject(obj)) { | |
return false | |
} | |
var last, key | |
for (var i = 0, l = path.length - 1; i < l; i++) { | |
last = obj | |
key = path[i] | |
obj = obj[key] | |
if (!_.isObject(obj)) { | |
obj = {} | |
last.$add(key, obj) | |
} | |
} | |
key = path[i] | |
if (key in obj) { | |
obj[key] = val | |
} else { | |
obj.$add(key, val) | |
} | |
return true | |
} | |
/***/ }, | |
/* 19 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var Cache = __webpack_require__(52) | |
var config = __webpack_require__(15) | |
var dirParser = __webpack_require__(21) | |
var regexEscapeRE = /[-.*+?^${}()|[\]\/\\]/g | |
var cache, tagRE, htmlRE, firstChar, lastChar | |
/** | |
* Escape a string so it can be used in a RegExp | |
* constructor. | |
* | |
* @param {String} str | |
*/ | |
function escapeRegex (str) { | |
return str.replace(regexEscapeRE, '\\$&') | |
} | |
/** | |
* Compile the interpolation tag regex. | |
* | |
* @return {RegExp} | |
*/ | |
function compileRegex () { | |
config._delimitersChanged = false | |
var open = config.delimiters[0] | |
var close = config.delimiters[1] | |
firstChar = open.charAt(0) | |
lastChar = close.charAt(close.length - 1) | |
var firstCharRE = escapeRegex(firstChar) | |
var lastCharRE = escapeRegex(lastChar) | |
var openRE = escapeRegex(open) | |
var closeRE = escapeRegex(close) | |
tagRE = new RegExp( | |
firstCharRE + '?' + openRE + | |
'(.+?)' + | |
closeRE + lastCharRE + '?', | |
'g' | |
) | |
htmlRE = new RegExp( | |
'^' + firstCharRE + openRE + | |
'.*' + | |
closeRE + lastCharRE + '$' | |
) | |
// 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] | |
*/ | |
exports.parse = function (text) { | |
if (config._delimitersChanged) { | |
compileRegex() | |
} | |
var hit = cache.get(text) | |
if (hit) { | |
return hit | |
} | |
if (!tagRE.test(text)) { | |
return null | |
} | |
var tokens = [] | |
var lastIndex = tagRE.lastIndex = 0 | |
var match, index, value, first, oneTime, partial | |
/* jshint boss:true */ | |
while (match = tagRE.exec(text)) { | |
index = match.index | |
// push text token | |
if (index > lastIndex) { | |
tokens.push({ | |
value: text.slice(lastIndex, index) | |
}) | |
} | |
// tag token | |
first = match[1].charCodeAt(0) | |
oneTime = first === 0x2A // * | |
partial = first === 0x3E // > | |
value = (oneTime || partial) | |
? match[1].slice(1) | |
: match[1] | |
tokens.push({ | |
tag: true, | |
value: value.trim(), | |
html: htmlRE.test(match[0]), | |
oneTime: oneTime, | |
partial: partial | |
}) | |
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} | |
*/ | |
exports.tokensToExp = function (tokens, vm) { | |
return tokens.length > 1 | |
? tokens.map(function (token) { | |
return formatToken(token, vm) | |
}).join('+') | |
: 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 | |
? vm && token.oneTime | |
? '"' + vm.$eval(token.value) + '"' | |
: single | |
? token.value | |
: inlineFilters(token.value) | |
: '"' + 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 | |
* @return {String} | |
*/ | |
var filterRE = /[^|]\|[^|]/ | |
function inlineFilters (exp) { | |
if (!filterRE.test(exp)) { | |
return '(' + exp + ')' | |
} else { | |
var dir = dirParser.parse(exp)[0] | |
if (!dir.filters) { | |
return '(' + exp + ')' | |
} else { | |
exp = dir.expression | |
for (var i = 0, l = dir.filters.length; i < l; i++) { | |
var filter = dir.filters[i] | |
var args = filter.args | |
? ',"' + filter.args.join('","') + '"' | |
: '' | |
filter = 'this.$options.filters["' + filter.name + '"]' | |
exp = '(' + filter + '.read||' + filter + ')' + | |
'.apply(this,[' + exp + args + '])' | |
} | |
return exp | |
} | |
} | |
} | |
/***/ }, | |
/* 20 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var Cache = __webpack_require__(52) | |
var templateCache = new Cache(1000) | |
var idSelectorCache = new Cache(1000) | |
var map = { | |
_default : [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>' | |
] | |
var tagRE = /<([\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 | |
* @return {DocumentFragment} | |
*/ | |
function stringToFragment (templateString) { | |
// try a cache hit first | |
var hit = templateCache.get(templateString) | |
if (hit) { | |
return hit | |
} | |
var frag = document.createDocumentFragment() | |
var tagMatch = templateString.match(tagRE) | |
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._default | |
var depth = wrap[0] | |
var prefix = wrap[1] | |
var suffix = wrap[2] | |
var node = document.createElement('div') | |
node.innerHTML = prefix + templateString.trim() + suffix | |
while (depth--) { | |
node = node.lastChild | |
} | |
var child | |
/* jshint boss:true */ | |
while (child = node.firstChild) { | |
frag.appendChild(child) | |
} | |
} | |
templateCache.put(templateString, frag) | |
return frag | |
} | |
/** | |
* Convert a template node to a DocumentFragment. | |
* | |
* @param {Node} node | |
* @return {DocumentFragment} | |
*/ | |
function nodeToFragment (node) { | |
var tag = node.tagName | |
// if its a template tag and the browser supports it, | |
// its content is already a document fragment. | |
if ( | |
tag === 'TEMPLATE' && | |
node.content instanceof DocumentFragment | |
) { | |
return node.content | |
} | |
// script template | |
if (tag === 'SCRIPT') { | |
return stringToFragment(node.textContent) | |
} | |
// normal node, clone it to avoid mutating the original | |
var clone = exports.clone(node) | |
var frag = document.createDocumentFragment() | |
var child | |
/* jshint boss:true */ | |
while (child = clone.firstChild) { | |
frag.appendChild(child) | |
} | |
return frag | |
} | |
// Test for the presence of the Safari template cloning bug | |
// https://bugs.webkit.org/show_bug.cgi?id=137755 | |
var hasBrokenTemplate = _.inBrowser | |
? (function () { | |
var a = document.createElement('div') | |
a.innerHTML = '<template>1</template>' | |
return !a.cloneNode(true).firstChild.innerHTML | |
})() | |
: false | |
// Test for IE10/11 textarea placeholder clone bug | |
var hasTextareaCloneBug = _.inBrowser | |
? (function () { | |
var t = document.createElement('textarea') | |
t.placeholder = 't' | |
return t.cloneNode(true).value === 't' | |
})() | |
: 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} | |
*/ | |
exports.clone = function (node) { | |
var res = node.cloneNode(true) | |
var i, original, cloned | |
/* istanbul ignore if */ | |
if (hasBrokenTemplate) { | |
original = node.querySelectorAll('template') | |
if (original.length) { | |
cloned = res.querySelectorAll('template') | |
i = cloned.length | |
while (i--) { | |
cloned[i].parentNode.replaceChild( | |
original[i].cloneNode(true), | |
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} clone | |
* @param {Boolean} noSelector | |
* @return {DocumentFragment|undefined} | |
*/ | |
exports.parse = function (template, clone, noSelector) { | |
var node, frag | |
// if the template is already a document fragment, | |
// do nothing | |
if (template instanceof DocumentFragment) { | |
return clone | |
? template.cloneNode(true) | |
: template | |
} | |
if (typeof template === 'string') { | |
// id selector | |
if (!noSelector && 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) | |
} | |
} else if (template.nodeType) { | |
// a direct node | |
frag = nodeToFragment(template) | |
} | |
return frag && clone | |
? exports.clone(frag) | |
: frag | |
} | |
/***/ }, | |
/* 21 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var Cache = __webpack_require__(52) | |
var cache = new Cache(1000) | |
var argRE = /^[^\{\?]+$|^'[^']*'$|^"[^"]*"$/ | |
var filterTokenRE = /[^\s'"]+|'[^']+'|"[^"]+"/g | |
/** | |
* Parser state | |
*/ | |
var str | |
var c, i, l | |
var inSingle | |
var inDouble | |
var curly | |
var square | |
var paren | |
var begin | |
var argIndex | |
var dirs | |
var dir | |
var lastFilterIndex | |
var arg | |
/** | |
* Push a directive object into the result Array | |
*/ | |
function pushDir () { | |
dir.raw = str.slice(begin, i).trim() | |
if (dir.expression === undefined) { | |
dir.expression = str.slice(argIndex, i).trim() | |
} else if (lastFilterIndex !== begin) { | |
pushFilter() | |
} | |
if (i === 0 || dir.expression) { | |
dirs.push(dir) | |
} | |
} | |
/** | |
* 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] | |
filter.args = tokens.length > 1 ? tokens.slice(1) : null | |
} | |
if (filter) { | |
(dir.filters = dir.filters || []).push(filter) | |
} | |
lastFilterIndex = i + 1 | |
} | |
/** | |
* Parse a directive string into an Array of AST-like | |
* objects representing directives. | |
* | |
* Example: | |
* | |
* "click: a = a + 1 | uppercase" will yield: | |
* { | |
* arg: 'click', | |
* expression: 'a = a + 1', | |
* filters: [ | |
* { name: 'uppercase', args: null } | |
* ] | |
* } | |
* | |
* @param {String} str | |
* @return {Array<Object>} | |
*/ | |
exports.parse = function (s) { | |
var hit = cache.get(s) | |
if (hit) { | |
return hit | |
} | |
// reset parser state | |
str = s | |
inSingle = inDouble = false | |
curly = square = paren = begin = argIndex = 0 | |
lastFilterIndex = 0 | |
dirs = [] | |
dir = {} | |
arg = null | |
for (i = 0, l = str.length; i < l; i++) { | |
c = str.charCodeAt(i) | |
if (inSingle) { | |
// check single quote | |
if (c === 0x27) inSingle = !inSingle | |
} else if (inDouble) { | |
// check double quote | |
if (c === 0x22) inDouble = !inDouble | |
} else if ( | |
c === 0x2C && // comma | |
!paren && !curly && !square | |
) { | |
// reached the end of a directive | |
pushDir() | |
// reset & skip the comma | |
dir = {} | |
begin = argIndex = lastFilterIndex = i + 1 | |
} else if ( | |
c === 0x3A && // colon | |
!dir.expression && | |
!dir.arg | |
) { | |
// argument | |
arg = str.slice(begin, i).trim() | |
// test for valid argument here | |
// since we may have caught stuff like first half of | |
// an object literal or a ternary expression. | |
if (argRE.test(arg)) { | |
argIndex = i + 1 | |
dir.arg = _.stripQuotes(arg) || arg | |
} | |
} else if ( | |
c === 0x7C && // pipe | |
str.charCodeAt(i + 1) !== 0x7C && | |
str.charCodeAt(i - 1) !== 0x7C | |
) { | |
if (dir.expression === undefined) { | |
// first filter, end of expression | |
lastFilterIndex = i + 1 | |
dir.expression = str.slice(argIndex, 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 (i === 0 || begin !== i) { | |
pushDir() | |
} | |
cache.put(s, dirs) | |
return dirs | |
} | |
/***/ }, | |
/* 22 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var Path = __webpack_require__(18) | |
var Cache = __webpack_require__(52) | |
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+\])*$/ | |
var pathReplaceRE = /[^\w$\.]([A-Za-z_$][\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 | |
* @param {Boolean} needSet | |
* @return {Function} | |
*/ | |
function compileExpFns (exp, needSet) { | |
if (improperKeywordsRE.test(exp)) { | |
_.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(pathReplaceRE, rewrite) | |
.replace(restoreRE, restore) | |
var getter = makeGetter(body) | |
if (getter) { | |
return { | |
get: getter, | |
body: body, | |
set: needSet | |
? makeSetter(body) | |
: null | |
} | |
} | |
} | |
/** | |
* Compile getter setters for a simple path. | |
* | |
* @param {String} exp | |
* @return {Function} | |
*/ | |
function compilePathFns (exp) { | |
var getter, path | |
if (exp.indexOf('[') < 0) { | |
// really simple path | |
path = exp.split('.') | |
getter = Path.compileGetter(path) | |
} else { | |
// do the real parsing | |
path = Path.parse(exp) | |
getter = path.get | |
} | |
return { | |
get: getter, | |
// always generate setter for simple paths | |
set: function (obj, val) { | |
Path.set(obj, path, val) | |
} | |
} | |
} | |
/** | |
* 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 makeGetter (body) { | |
try { | |
return new Function('scope', 'return ' + body + ';') | |
} catch (e) { | |
_.warn( | |
'Invalid expression. ' + | |
'Generated function body: ' + body | |
) | |
} | |
} | |
/** | |
* Build a setter function. | |
* | |
* This is only needed in rare situations like "a[b]" where | |
* a settable path requires dynamic evaluation. | |
* | |
* This setter function may throw error when called if the | |
* expression body is not a valid left-hand expression in | |
* assignment. | |
* | |
* @param {String} body | |
* @return {Function|undefined} | |
*/ | |
function makeSetter (body) { | |
try { | |
return new Function('scope', 'value', body + '=value;') | |
} catch (e) { | |
_.warn('Invalid setter function body: ' + body) | |
} | |
} | |
/** | |
* Check for setter existence on a cache hit. | |
* | |
* @param {Function} hit | |
*/ | |
function checkSetter (hit) { | |
if (!hit.set) { | |
hit.set = makeSetter(hit.body) | |
} | |
} | |
/** | |
* Parse an expression into re-written getter/setters. | |
* | |
* @param {String} exp | |
* @param {Boolean} needSet | |
* @return {Function} | |
*/ | |
exports.parse = function (exp, needSet) { | |
exp = exp.trim() | |
// try cache | |
var hit = expressionCache.get(exp) | |
if (hit) { | |
if (needSet) { | |
checkSetter(hit) | |
} | |
return hit | |
} | |
// we do a simple path check to optimize for them. | |
// the check fails valid paths with unusal whitespaces, | |
// but that's too rare and we don't care. | |
// also skip boolean literals and paths that start with | |
// global "Math" | |
var res = | |
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.' | |
? compilePathFns(exp) | |
: compileExpFns(exp, needSet) | |
expressionCache.put(exp, res) | |
return res | |
} | |
// Export the pathRegex for external use | |
exports.pathTestRE = pathTestRE | |
/***/ }, | |
/* 23 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var uid = 0 | |
var _ = __webpack_require__(11) | |
/** | |
* A dep is an observable that can have multiple | |
* directives subscribing to it. | |
* | |
* @constructor | |
*/ | |
function Dep () { | |
this.id = ++uid | |
this.subs = [] | |
} | |
var p = Dep.prototype | |
/** | |
* Add a directive subscriber. | |
* | |
* @param {Directive} sub | |
*/ | |
p.addSub = function (sub) { | |
this.subs.push(sub) | |
} | |
/** | |
* Remove a directive subscriber. | |
* | |
* @param {Directive} sub | |
*/ | |
p.removeSub = function (sub) { | |
if (this.subs.length) { | |
var i = this.subs.indexOf(sub) | |
if (i > -1) this.subs.splice(i, 1) | |
} | |
} | |
/** | |
* Notify all subscribers of a new value. | |
*/ | |
p.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() | |
} | |
} | |
module.exports = Dep | |
/***/ }, | |
/* 24 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var config = __webpack_require__(15) | |
var Watcher = __webpack_require__(25) | |
var textParser = __webpack_require__(19) | |
var expParser = __webpack_require__(22) | |
/** | |
* 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} expression | |
* - {String} [arg] | |
* - {Array<Object>} [filters] | |
* @param {Object} def - directive definition object | |
* @param {Vue|undefined} host - transclusion host target | |
* @constructor | |
*/ | |
function Directive (name, el, vm, descriptor, def, host) { | |
// public | |
this.name = name | |
this.el = el | |
this.vm = vm | |
// copy descriptor props | |
this.raw = descriptor.raw | |
this.expression = descriptor.expression | |
this.arg = descriptor.arg | |
this.filters = _.resolveFilters(vm, descriptor.filters) | |
// private | |
this._host = host | |
this._locked = false | |
this._bound = false | |
// init | |
this._bind(def) | |
} | |
var p = Directive.prototype | |
/** | |
* Initialize the directive, mixin definition properties, | |
* setup the watcher, call definition bind() and update() | |
* if present. | |
* | |
* @param {Object} def | |
*/ | |
p._bind = function (def) { | |
if (this.name !== 'cloak' && this.el && this.el.removeAttribute) { | |
this.el.removeAttribute(config.prefix + this.name) | |
} | |
if (typeof def === 'function') { | |
this.update = def | |
} else { | |
_.extend(this, def) | |
} | |
this._watcherExp = this.expression | |
this._checkDynamicLiteral() | |
if (this.bind) { | |
this.bind() | |
} | |
if (this._watcherExp && | |
(this.update || this.twoWay) && | |
(!this.isLiteral || this._isDynamicLiteral) && | |
!this._checkStatement()) { | |
// wrapped updater for context | |
var dir = this | |
var update = this._update = this.update | |
? function (val, oldVal) { | |
if (!dir._locked) { | |
dir.update(val, oldVal) | |
} | |
} | |
: function () {} // noop if no update is provided | |
// use raw expression as identifier because filters | |
// make them different watchers | |
var watcher = this.vm._watchers[this.raw] | |
// v-repeat always creates a new watcher because it has | |
// a special filter that's bound to its directive | |
// instance. | |
if (!watcher || this.name === 'repeat') { | |
watcher = this.vm._watchers[this.raw] = new Watcher( | |
this.vm, | |
this._watcherExp, | |
update, // callback | |
{ | |
filters: this.filters, | |
twoWay: this.twoWay, | |
deep: this.deep | |
} | |
) | |
} else { | |
watcher.addCb(update) | |
} | |
this._watcher = watcher | |
if (this._initValue != null) { | |
watcher.set(this._initValue) | |
} else if (this.update) { | |
this.update(watcher.value) | |
} | |
} | |
this._bound = true | |
} | |
/** | |
* check if this is a dynamic literal binding. | |
* | |
* e.g. v-component="{{currentView}}" | |
*/ | |
p._checkDynamicLiteral = function () { | |
var expression = this.expression | |
if (expression && this.isLiteral) { | |
var tokens = textParser.parse(expression) | |
if (tokens) { | |
var exp = textParser.tokensToExp(tokens) | |
this.expression = this.vm.$get(exp) | |
this._watcherExp = exp | |
this._isDynamicLiteral = true | |
} | |
} | |
} | |
/** | |
* 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. v-on="click: a++" | |
* | |
* @return {Boolean} | |
*/ | |
p._checkStatement = function () { | |
var expression = this.expression | |
if ( | |
expression && this.acceptStatement && | |
!expParser.pathTestRE.test(expression) | |
) { | |
var fn = expParser.parse(expression).get | |
var vm = this.vm | |
var handler = function () { | |
fn.call(vm, vm) | |
} | |
if (this.filters) { | |
handler = _.applyFilters( | |
handler, | |
this.filters.read, | |
vm | |
) | |
} | |
this.update(handler) | |
return true | |
} | |
} | |
/** | |
* Check for an attribute directive param, e.g. lazy | |
* | |
* @param {String} name | |
* @return {String} | |
*/ | |
p._checkParam = function (name) { | |
var param = this.el.getAttribute(name) | |
if (param !== null) { | |
this.el.removeAttribute(name) | |
} | |
return param | |
} | |
/** | |
* Teardown the watcher and call unbind. | |
*/ | |
p._teardown = function () { | |
if (this._bound) { | |
if (this.unbind) { | |
this.unbind() | |
} | |
var watcher = this._watcher | |
if (watcher && watcher.active) { | |
watcher.removeCb(this._update) | |
if (!watcher.active) { | |
this.vm._watchers[this.raw] = null | |
} | |
} | |
this._bound = false | |
this.vm = this.el = this._watcher = null | |
} | |
} | |
/** | |
* Set the corresponding value with the setter. | |
* This should only be used in two-way directives | |
* e.g. v-model. | |
* | |
* @param {*} value | |
* @param {Boolean} lock - prevent wrtie triggering update. | |
* @public | |
*/ | |
p.set = function (value, lock) { | |
if (this.twoWay) { | |
if (lock) { | |
this._locked = true | |
} | |
this._watcher.set(value) | |
if (lock) { | |
var self = this | |
_.nextTick(function () { | |
self._locked = false | |
}) | |
} | |
} | |
} | |
module.exports = Directive | |
/***/ }, | |
/* 25 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var config = __webpack_require__(15) | |
var Observer = __webpack_require__(49) | |
var expParser = __webpack_require__(22) | |
var batcher = __webpack_require__(53) | |
var uid = 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 | |
* @constructor | |
*/ | |
function Watcher (vm, expression, cb, options) { | |
this.vm = vm | |
vm._watcherList.push(this) | |
this.expression = expression | |
this.cbs = [cb] | |
this.id = ++uid // uid for batching | |
this.active = true | |
options = options || {} | |
this.deep = !!options.deep | |
this.user = !!options.user | |
this.deps = Object.create(null) | |
// setup filters if any. | |
// We delegate directive filters here to the watcher | |
// because they need to be included in the dependency | |
// collection process. | |
if (options.filters) { | |
this.readFilters = options.filters.read | |
this.writeFilters = options.filters.write | |
} | |
// parse expression for getter/setter | |
var res = expParser.parse(expression, options.twoWay) | |
this.getter = res.get | |
this.setter = res.set | |
this.value = this.get() | |
} | |
var p = Watcher.prototype | |
/** | |
* Add a dependency to this directive. | |
* | |
* @param {Dep} dep | |
*/ | |
p.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. | |
*/ | |
p.get = function () { | |
this.beforeGet() | |
var vm = this.vm | |
var value | |
try { | |
value = this.getter.call(vm, vm) | |
} catch (e) { | |
if (config.warnExpressionErrors) { | |
_.warn( | |
'Error when evaluating expression "' + | |
this.expression + '":\n ' + e | |
) | |
} | |
} | |
// "touch" every property so they are all tracked as | |
// dependencies for deep watching | |
if (this.deep) { | |
traverse(value) | |
} | |
value = _.applyFilters(value, this.readFilters, vm) | |
this.afterGet() | |
return value | |
} | |
/** | |
* Set the corresponding value with the setter. | |
* | |
* @param {*} value | |
*/ | |
p.set = function (value) { | |
var vm = this.vm | |
value = _.applyFilters( | |
value, this.writeFilters, vm, this.value | |
) | |
try { | |
this.setter.call(vm, vm, value) | |
} catch (e) { | |
if (config.warnExpressionErrors) { | |
_.warn( | |
'Error when evaluating setter "' + | |
this.expression + '":\n ' + e | |
) | |
} | |
} | |
} | |
/** | |
* Prepare for dependency collection. | |
*/ | |
p.beforeGet = function () { | |
Observer.target = this | |
this.newDeps = {} | |
} | |
/** | |
* Clean up for dependency collection. | |
*/ | |
p.afterGet = function () { | |
Observer.target = null | |
for (var id in this.deps) { | |
if (!this.newDeps[id]) { | |
this.deps[id].removeSub(this) | |
} | |
} | |
this.deps = this.newDeps | |
} | |
/** | |
* Subscriber interface. | |
* Will be called when a dependency changes. | |
*/ | |
p.update = function () { | |
if (!config.async || config.debug) { | |
this.run() | |
} else { | |
batcher.push(this) | |
} | |
} | |
/** | |
* Batcher job interface. | |
* Will be called by the batcher. | |
*/ | |
p.run = function () { | |
if (this.active) { | |
var value = this.get() | |
if ( | |
value !== this.value || | |
Array.isArray(value) || | |
this.deep | |
) { | |
var oldValue = this.value | |
this.value = value | |
var cbs = this.cbs | |
for (var i = 0, l = cbs.length; i < l; i++) { | |
cbs[i](value, oldValue) | |
// if a callback also removed other callbacks, | |
// we need to adjust the loop accordingly. | |
var removed = l - cbs.length | |
if (removed) { | |
i -= removed | |
l -= removed | |
} | |
} | |
} | |
} | |
} | |
/** | |
* Add a callback. | |
* | |
* @param {Function} cb | |
*/ | |
p.addCb = function (cb) { | |
this.cbs.push(cb) | |
} | |
/** | |
* Remove a callback. | |
* | |
* @param {Function} cb | |
*/ | |
p.removeCb = function (cb) { | |
var cbs = this.cbs | |
if (cbs.length > 1) { | |
var i = cbs.indexOf(cb) | |
if (i > -1) { | |
cbs.splice(i, 1) | |
} | |
} else if (cb === cbs[0]) { | |
this.teardown() | |
} | |
} | |
/** | |
* Remove self from all dependencies' subcriber list. | |
*/ | |
p.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) { | |
var list = this.vm._watcherList | |
var i = list.indexOf(this) | |
if (i > -1) { | |
list.splice(i, 1) | |
} | |
} | |
for (var id in this.deps) { | |
this.deps[id].removeSub(this) | |
} | |
this.active = false | |
this.vm = this.cbs = 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 {Object} obj | |
*/ | |
function traverse (obj) { | |
var key, val, i | |
for (key in obj) { | |
val = obj[key] | |
if (_.isArray(val)) { | |
i = val.length | |
while (i--) traverse(val[i]) | |
} else if (_.isObject(val)) { | |
traverse(val) | |
} | |
} | |
} | |
module.exports = Watcher | |
/***/ }, | |
/* 26 */ | |
/***/ function(module, exports, __webpack_require__) { | |
/** | |
* Check is a string starts with $ or _ | |
* | |
* @param {String} str | |
* @return {Boolean} | |
*/ | |
exports.isReserved = function (str) { | |
var c = (str + '').charCodeAt(0) | |
return c === 0x24 || c === 0x5F | |
} | |
/** | |
* Guard text output, make sure undefined outputs | |
* empty string | |
* | |
* @param {*} value | |
* @return {String} | |
*/ | |
exports.toString = function (value) { | |
return value == null | |
? '' | |
: value.toString() | |
} | |
/** | |
* Check and convert possible numeric numbers before | |
* setting back to data | |
* | |
* @param {*} value | |
* @return {*|Number} | |
*/ | |
exports.toNumber = function (value) { | |
return ( | |
isNaN(value) || | |
value === null || | |
typeof value === 'boolean' | |
) ? value | |
: Number(value) | |
} | |
/** | |
* Strip quotes from a string | |
* | |
* @param {String} str | |
* @return {String | false} | |
*/ | |
exports.stripQuotes = function (str) { | |
var a = str.charCodeAt(0) | |
var b = str.charCodeAt(str.length - 1) | |
return a === b && (a === 0x22 || a === 0x27) | |
? str.slice(1, -1) | |
: false | |
} | |
/** | |
* Replace helper | |
* | |
* @param {String} _ - matched delimiter | |
* @param {String} c - matched char | |
* @return {String} | |
*/ | |
function toUpper (_, c) { | |
return c ? c.toUpperCase () : '' | |
} | |
/** | |
* Camelize a hyphen-delmited string. | |
* | |
* @param {String} str | |
* @return {String} | |
*/ | |
var camelRE = /-(\w)/g | |
exports.camelize = function (str) { | |
return str.replace(camelRE, toUpper) | |
} | |
/** | |
* 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 | |
exports.classify = function (str) { | |
return str.replace(classifyRE, toUpper) | |
} | |
/** | |
* Simple bind, faster than native | |
* | |
* @param {Function} fn | |
* @param {Object} ctx | |
* @return {Function} | |
*/ | |
exports.bind = function (fn, ctx) { | |
return function () { | |
return fn.apply(ctx, arguments) | |
} | |
} | |
/** | |
* Convert an Array-like object to a real Array. | |
* | |
* @param {Array-like} list | |
* @param {Number} [start] - start index | |
* @return {Array} | |
*/ | |
exports.toArray = function (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 | |
*/ | |
exports.extend = function (to, from) { | |
for (var key in from) { | |
to[key] = from[key] | |
} | |
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} | |
*/ | |
exports.isObject = function (obj) { | |
return obj && typeof obj === 'object' | |
} | |
/** | |
* Strict object type check. Only returns true | |
* for plain JavaScript objects. | |
* | |
* @param {*} obj | |
* @return {Boolean} | |
*/ | |
var toString = Object.prototype.toString | |
exports.isPlainObject = function (obj) { | |
return toString.call(obj) === '[object Object]' | |
} | |
/** | |
* Array type check. | |
* | |
* @param {*} obj | |
* @return {Boolean} | |
*/ | |
exports.isArray = function (obj) { | |
return Array.isArray(obj) | |
} | |
/** | |
* Define a non-enumerable property | |
* | |
* @param {Object} obj | |
* @param {String} key | |
* @param {*} val | |
* @param {Boolean} [enumerable] | |
*/ | |
exports.define = function (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 | |
*/ | |
exports.debounce = function(func, wait) { | |
var timeout, args, context, timestamp, result | |
var later = function() { | |
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 | |
} | |
} | |
/***/ }, | |
/* 27 */ | |
/***/ function(module, exports, __webpack_require__) { | |
/** | |
* Can we use __proto__? | |
* | |
* @type {Boolean} | |
*/ | |
exports.hasProto = '__proto__' in {} | |
/** | |
* Indicates we have a window | |
* | |
* @type {Boolean} | |
*/ | |
var toString = Object.prototype.toString | |
var inBrowser = exports.inBrowser = | |
typeof window !== 'undefined' && | |
toString.call(window) !== '[object Object]' | |
/** | |
* 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 | |
*/ | |
exports.nextTick = (function () { | |
var callbacks = [] | |
var pending = false | |
var timerFunc | |
function handle () { | |
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(handle) | |
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(handle, 0) | |
} | |
})() | |
/** | |
* Detect if we are in IE9... | |
* | |
* @type {Boolean} | |
*/ | |
exports.isIE9 = | |
inBrowser && | |
navigator.userAgent.indexOf('MSIE 9.0') > 0 | |
/** | |
* Sniff transition/animation events | |
*/ | |
if (inBrowser && !exports.isIE9) { | |
var isWebkitTrans = | |
window.ontransitionend === undefined && | |
window.onwebkittransitionend !== undefined | |
var isWebkitAnim = | |
window.onanimationend === undefined && | |
window.onwebkitanimationend !== undefined | |
exports.transitionProp = isWebkitTrans | |
? 'WebkitTransition' | |
: 'transition' | |
exports.transitionEndEvent = isWebkitTrans | |
? 'webkitTransitionEnd' | |
: 'transitionend' | |
exports.animationProp = isWebkitAnim | |
? 'WebkitAnimation' | |
: 'animation' | |
exports.animationEndEvent = isWebkitAnim | |
? 'webkitAnimationEnd' | |
: 'animationend' | |
} | |
/***/ }, | |
/* 28 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var config = __webpack_require__(15) | |
/** | |
* 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 byy doing the | |
* contains() check on the node's parentNode instead of | |
* the node itself. | |
* | |
* @param {Node} node | |
* @return {Boolean} | |
*/ | |
var doc = | |
typeof document !== 'undefined' && | |
document.documentElement | |
exports.inDoc = function (node) { | |
var parent = node && node.parentNode | |
return doc === node || | |
doc === parent || | |
!!(parent && parent.nodeType === 1 && (doc.contains(parent))) | |
} | |
/** | |
* Extract an attribute from a node. | |
* | |
* @param {Node} node | |
* @param {String} attr | |
*/ | |
exports.attr = function (node, attr) { | |
attr = config.prefix + attr | |
var val = node.getAttribute(attr) | |
if (val !== null) { | |
node.removeAttribute(attr) | |
} | |
return val | |
} | |
/** | |
* Insert el before target | |
* | |
* @param {Element} el | |
* @param {Element} target | |
*/ | |
exports.before = function (el, target) { | |
target.parentNode.insertBefore(el, target) | |
} | |
/** | |
* Insert el after target | |
* | |
* @param {Element} el | |
* @param {Element} target | |
*/ | |
exports.after = function (el, target) { | |
if (target.nextSibling) { | |
exports.before(el, target.nextSibling) | |
} else { | |
target.parentNode.appendChild(el) | |
} | |
} | |
/** | |
* Remove el from DOM | |
* | |
* @param {Element} el | |
*/ | |
exports.remove = function (el) { | |
el.parentNode.removeChild(el) | |
} | |
/** | |
* Prepend el to target | |
* | |
* @param {Element} el | |
* @param {Element} target | |
*/ | |
exports.prepend = function (el, target) { | |
if (target.firstChild) { | |
exports.before(el, target.firstChild) | |
} else { | |
target.appendChild(el) | |
} | |
} | |
/** | |
* Replace target with el | |
* | |
* @param {Element} target | |
* @param {Element} el | |
*/ | |
exports.replace = function (target, el) { | |
var parent = target.parentNode | |
if (parent) { | |
parent.replaceChild(el, target) | |
} | |
} | |
/** | |
* Copy attributes from one element to another. | |
* | |
* @param {Element} from | |
* @param {Element} to | |
*/ | |
exports.copyAttributes = function (from, to) { | |
if (from.hasAttributes()) { | |
var attrs = from.attributes | |
for (var i = 0, l = attrs.length; i < l; i++) { | |
var attr = attrs[i] | |
to.setAttribute(attr.name, attr.value) | |
} | |
} | |
} | |
/** | |
* Add event listener shorthand. | |
* | |
* @param {Element} el | |
* @param {String} event | |
* @param {Function} cb | |
*/ | |
exports.on = function (el, event, cb) { | |
el.addEventListener(event, cb) | |
} | |
/** | |
* Remove event listener shorthand. | |
* | |
* @param {Element} el | |
* @param {String} event | |
* @param {Function} cb | |
*/ | |
exports.off = function (el, event, cb) { | |
el.removeEventListener(event, cb) | |
} | |
/** | |
* Add class with compatibility for IE & SVG | |
* | |
* @param {Element} el | |
* @param {Strong} cls | |
*/ | |
exports.addClass = function (el, cls) { | |
if (el.classList) { | |
el.classList.add(cls) | |
} else { | |
var cur = ' ' + (el.getAttribute('class') || '') + ' ' | |
if (cur.indexOf(' ' + cls + ' ') < 0) { | |
el.setAttribute('class', (cur + cls).trim()) | |
} | |
} | |
} | |
/** | |
* Remove class with compatibility for IE & SVG | |
* | |
* @param {Element} el | |
* @param {Strong} cls | |
*/ | |
exports.removeClass = function (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, ' ') | |
} | |
el.setAttribute('class', cur.trim()) | |
} | |
} | |
/** | |
* Extract raw content inside an element into a temporary | |
* container div | |
* | |
* @param {Element} el | |
* @param {Boolean} asFragment | |
* @return {Element} | |
*/ | |
exports.extractContent = function (el, asFragment) { | |
var child | |
var rawContent | |
if (el.hasChildNodes()) { | |
rawContent = asFragment | |
? document.createDocumentFragment() | |
: document.createElement('div') | |
/* jshint boss:true */ | |
while (child = el.firstChild) { | |
rawContent.appendChild(child) | |
} | |
} | |
return rawContent | |
} | |
/***/ }, | |
/* 29 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(30) | |
/** | |
* Resolve read & write filters for a vm instance. The | |
* filters descriptor Array comes from the directive parser. | |
* | |
* This is extracted into its own utility so it can | |
* be used in multiple scenarios. | |
* | |
* @param {Vue} vm | |
* @param {Array<Object>} filters | |
* @param {Object} [target] | |
* @return {Object} | |
*/ | |
exports.resolveFilters = function (vm, filters, target) { | |
if (!filters) { | |
return | |
} | |
var res = target || {} | |
// var registry = vm.$options.filters | |
filters.forEach(function (f) { | |
var def = vm.$options.filters[f.name] | |
_.assertAsset(def, 'filter', f.name) | |
if (!def) return | |
var args = f.args | |
var reader, writer | |
if (typeof def === 'function') { | |
reader = def | |
} else { | |
reader = def.read | |
writer = def.write | |
} | |
if (reader) { | |
if (!res.read) res.read = [] | |
res.read.push(function (value) { | |
return args | |
? reader.apply(vm, [value].concat(args)) | |
: reader.call(vm, value) | |
}) | |
} | |
if (writer) { | |
if (!res.write) res.write = [] | |
res.write.push(function (value, oldVal) { | |
return args | |
? writer.apply(vm, [value, oldVal].concat(args)) | |
: writer.call(vm, value, oldVal) | |
}) | |
} | |
}) | |
return res | |
} | |
/** | |
* Apply filters to a value | |
* | |
* @param {*} value | |
* @param {Array} filters | |
* @param {Vue} vm | |
* @param {*} oldVal | |
* @return {*} | |
*/ | |
exports.applyFilters = function (value, filters, vm, oldVal) { | |
if (!filters) { | |
return value | |
} | |
for (var i = 0, l = filters.length; i < l; i++) { | |
value = filters[i].call(vm, value, oldVal) | |
} | |
return value | |
} | |
/***/ }, | |
/* 30 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var config = __webpack_require__(15) | |
/** | |
* Enable debug utilities. The enableDebug() function and | |
* all _.log() & _.warn() calls will be dropped in the | |
* minified production build. | |
*/ | |
enableDebug() | |
function enableDebug () { | |
var hasConsole = typeof console !== 'undefined' | |
/** | |
* Log a message. | |
* | |
* @param {String} msg | |
*/ | |
exports.log = function (msg) { | |
if (hasConsole && config.debug) { | |
console.log('[Vue info]: ' + msg) | |
} | |
} | |
/** | |
* We've got a problem here. | |
* | |
* @param {String} msg | |
*/ | |
exports.warn = function (msg) { | |
if (hasConsole && (!config.silent || config.debug)) { | |
console.warn('[Vue warn]: ' + msg) | |
/* istanbul ignore if */ | |
if (config.debug) { | |
/* jshint debug: true */ | |
debugger | |
} | |
} | |
} | |
/** | |
* Assert asset exists | |
*/ | |
exports.assertAsset = function (val, type, id) { | |
if (!val) { | |
exports.warn('Failed to resolve ' + type + ': ' + id) | |
} | |
} | |
} | |
/***/ }, | |
/* 31 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
module.exports = { | |
bind: function () { | |
this.attr = this.el.nodeType === 3 | |
? 'nodeValue' | |
: 'textContent' | |
}, | |
update: function (value) { | |
this.el[this.attr] = _.toString(value) | |
} | |
} | |
/***/ }, | |
/* 32 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var templateParser = __webpack_require__(20) | |
module.exports = { | |
bind: function () { | |
// a comment node means this is a binding for | |
// {{{ inline unescaped html }}} | |
if (this.el.nodeType === 8) { | |
// hold nodes | |
this.nodes = [] | |
} | |
}, | |
update: function (value) { | |
value = _.toString(value) | |
if (this.nodes) { | |
this.swap(value) | |
} else { | |
this.el.innerHTML = value | |
} | |
}, | |
swap: function (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 = templateParser.parse(value, true, true) | |
// save a reference to these nodes so we can remove later | |
this.nodes = _.toArray(frag.childNodes) | |
_.before(frag, this.el) | |
} | |
} | |
/***/ }, | |
/* 33 */ | |
/***/ function(module, exports, __webpack_require__) { | |
// xlink | |
var xlinkNS = 'http://www.w3.org/1999/xlink' | |
var xlinkRE = /^xlink:/ | |
module.exports = { | |
priority: 850, | |
bind: function () { | |
var name = this.arg | |
this.update = xlinkRE.test(name) | |
? xlinkHandler | |
: defaultHandler | |
} | |
} | |
function defaultHandler (value) { | |
if (value || value === 0) { | |
this.el.setAttribute(this.arg, value) | |
} else { | |
this.el.removeAttribute(this.arg) | |
} | |
} | |
function xlinkHandler (value) { | |
if (value != null) { | |
this.el.setAttributeNS(xlinkNS, this.arg, value) | |
} else { | |
this.el.removeAttributeNS(xlinkNS, 'href') | |
} | |
} | |
/***/ }, | |
/* 34 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var transition = __webpack_require__(50) | |
module.exports = function (value) { | |
var el = this.el | |
transition.apply(el, value ? 1 : -1, function () { | |
el.style.display = value ? '' : 'none' | |
}, this.vm) | |
} | |
/***/ }, | |
/* 35 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var addClass = _.addClass | |
var removeClass = _.removeClass | |
module.exports = function (value) { | |
if (this.arg) { | |
var method = value ? addClass : removeClass | |
method(this.el, this.arg) | |
} else { | |
if (this.lastVal) { | |
removeClass(this.el, this.lastVal) | |
} | |
if (value) { | |
addClass(this.el, value) | |
this.lastVal = value | |
} | |
} | |
} | |
/***/ }, | |
/* 36 */ | |
/***/ function(module, exports, __webpack_require__) { | |
module.exports = { | |
isLiteral: true, | |
bind: function () { | |
this.vm.$$[this.expression] = this.el | |
}, | |
unbind: function () { | |
delete this.vm.$$[this.expression] | |
} | |
} | |
/***/ }, | |
/* 37 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
module.exports = { | |
isLiteral: true, | |
bind: function () { | |
var vm = this.el.__vue__ | |
if (!vm) { | |
_.warn( | |
'v-ref should only be used on a component root element.' | |
) | |
return | |
} | |
// If we get here, it means this is a `v-ref` on a | |
// child, because parent scope `v-ref` is stripped in | |
// `v-component` already. So we just record our own ref | |
// here - it will overwrite parent ref in `v-component`, | |
// if any. | |
vm._refID = this.expression | |
} | |
} | |
/***/ }, | |
/* 38 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var config = __webpack_require__(15) | |
module.exports = { | |
bind: function () { | |
var el = this.el | |
this.vm.$once('hook:compiled', function () { | |
el.removeAttribute(config.prefix + 'cloak') | |
}) | |
} | |
} | |
/***/ }, | |
/* 39 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var prefixes = ['-webkit-', '-moz-', '-ms-'] | |
var camelPrefixes = ['Webkit', 'Moz', 'ms'] | |
var importantRE = /!important;?$/ | |
var camelRE = /([a-z])([A-Z])/g | |
var testEl = null | |
var propCache = {} | |
module.exports = { | |
deep: true, | |
update: function (value) { | |
if (this.arg) { | |
this.setProp(this.arg, value) | |
} else { | |
if (typeof value === 'object') { | |
// cache object styles so that only changed props | |
// are actually updated. | |
if (!this.cache) this.cache = {} | |
for (var prop in value) { | |
this.setProp(prop, value[prop]) | |
/* jshint eqeqeq: false */ | |
if (value[prop] != this.cache[prop]) { | |
this.cache[prop] = value[prop] | |
this.setProp(prop, value[prop]) | |
} | |
} | |
} else { | |
this.el.style.cssText = value | |
} | |
} | |
}, | |
setProp: function (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 = prop.replace(camelRE, '$1-$2').toLowerCase() | |
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 | |
} | |
} | |
} | |
/***/ }, | |
/* 40 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var templateParser = __webpack_require__(20) | |
var vIf = __webpack_require__(45) | |
module.exports = { | |
isLiteral: true, | |
// same logic reuse from v-if | |
compile: vIf.compile, | |
teardown: vIf.teardown, | |
getContainedComponents: vIf.getContainedComponents, | |
unbind: vIf.unbind, | |
bind: function () { | |
var el = this.el | |
this.start = document.createComment('v-partial-start') | |
this.end = document.createComment('v-partial-end') | |
if (el.nodeType !== 8) { | |
el.innerHTML = '' | |
} | |
if (el.tagName === 'TEMPLATE' || el.nodeType === 8) { | |
_.replace(el, this.end) | |
} else { | |
el.appendChild(this.end) | |
} | |
_.before(this.start, this.end) | |
if (!this._isDynamicLiteral) { | |
this.insert(this.expression) | |
} | |
}, | |
update: function (id) { | |
this.teardown() | |
this.insert(id) | |
}, | |
insert: function (id) { | |
var partial = this.vm.$options.partials[id] | |
_.assertAsset(partial, 'partial', id) | |
if (partial) { | |
var filters = this.filters && this.filters.read | |
if (filters) { | |
partial = _.applyFilters(partial, filters, this.vm) | |
} | |
this.compile(templateParser.parse(partial, true)) | |
} | |
} | |
} | |
/***/ }, | |
/* 41 */ | |
/***/ function(module, exports, __webpack_require__) { | |
module.exports = { | |
priority: 1000, | |
isLiteral: true, | |
bind: function () { | |
if (!this._isDynamicLiteral) { | |
this.update(this.expression) | |
} | |
}, | |
update: function (id) { | |
var vm = this.el.__vue__ || this.vm | |
this.el.__v_trans = { | |
id: id, | |
// resolve the custom transition functions now | |
// so the transition module knows this is a | |
// javascript transition without having to check | |
// computed CSS. | |
fns: vm.$options.transitions[id] | |
} | |
} | |
} | |
/***/ }, | |
/* 42 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
module.exports = { | |
acceptStatement: true, | |
priority: 700, | |
bind: function () { | |
// deal with iframes | |
if ( | |
this.el.tagName === 'IFRAME' && | |
this.arg !== 'load' | |
) { | |
var self = this | |
this.iframeBind = function () { | |
_.on(self.el.contentWindow, self.arg, self.handler) | |
} | |
_.on(this.el, 'load', this.iframeBind) | |
} | |
}, | |
update: function (handler) { | |
if (typeof handler !== 'function') { | |
_.warn( | |
'Directive "v-on:' + this.expression + '" ' + | |
'expects a function value.' | |
) | |
return | |
} | |
this.reset() | |
var vm = this.vm | |
this.handler = function (e) { | |
e.targetVM = vm | |
vm.$event = e | |
var res = handler(e) | |
vm.$event = null | |
return res | |
} | |
if (this.iframeBind) { | |
this.iframeBind() | |
} else { | |
_.on(this.el, this.arg, this.handler) | |
} | |
}, | |
reset: function () { | |
var el = this.iframeBind | |
? this.el.contentWindow | |
: this.el | |
if (this.handler) { | |
_.off(el, this.arg, this.handler) | |
} | |
}, | |
unbind: function () { | |
this.reset() | |
_.off(this.el, 'load', this.iframeBind) | |
} | |
} | |
/***/ }, | |
/* 43 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var templateParser = __webpack_require__(20) | |
module.exports = { | |
isLiteral: true, | |
/** | |
* Setup. Two possible usages: | |
* | |
* - static: | |
* v-component="comp" | |
* | |
* - dynamic: | |
* v-component="{{currentView}}" | |
*/ | |
bind: function () { | |
if (!this.el.__vue__) { | |
// create a ref anchor | |
this.ref = document.createComment('v-component') | |
_.replace(this.el, this.ref) | |
// check keep-alive options. | |
// If yes, instead of destroying the active vm when | |
// hiding (v-if) or switching (dynamic literal) it, | |
// we simply remove it from the DOM and save it in a | |
// cache object, with its constructor id as the key. | |
this.keepAlive = this._checkParam('keep-alive') != null | |
// check ref | |
this.refID = _.attr(this.el, 'ref') | |
if (this.keepAlive) { | |
this.cache = {} | |
} | |
// check inline-template | |
if (this._checkParam('inline-template') !== null) { | |
// extract inline template as a DocumentFragment | |
this.template = _.extractContent(this.el, true) | |
} | |
// if static, build right now. | |
if (!this._isDynamicLiteral) { | |
this.resolveCtor(this.expression) | |
var child = this.build() | |
child.$before(this.ref) | |
this.setCurrent(child) | |
} else { | |
// check dynamic component params | |
this.readyEvent = this._checkParam('wait-for') | |
this.transMode = this._checkParam('transition-mode') | |
} | |
} else { | |
_.warn( | |
'v-component="' + this.expression + '" cannot be ' + | |
'used on an already mounted instance.' | |
) | |
} | |
}, | |
/** | |
* Resolve the component constructor to use when creating | |
* the child vm. | |
*/ | |
resolveCtor: function (id) { | |
this.ctorId = id | |
this.Ctor = this.vm.$options.components[id] | |
_.assertAsset(this.Ctor, 'component', id) | |
}, | |
/** | |
* Instantiate/insert a new child vm. | |
* If keep alive and has cached instance, insert that | |
* instance; otherwise build a new one and cache it. | |
* | |
* @return {Vue} - the created instance | |
*/ | |
build: function () { | |
if (this.keepAlive) { | |
var cached = this.cache[this.ctorId] | |
if (cached) { | |
return cached | |
} | |
} | |
var vm = this.vm | |
var el = templateParser.clone(this.el) | |
if (this.Ctor) { | |
var child = vm.$addChild({ | |
el: el, | |
template: this.template, | |
_asComponent: true, | |
_host: this._host | |
}, this.Ctor) | |
if (this.keepAlive) { | |
this.cache[this.ctorId] = child | |
} | |
return child | |
} | |
}, | |
/** | |
* Teardown the current child, but defers cleanup so | |
* that we can separate the destroy and removal steps. | |
*/ | |
unbuild: function () { | |
var child = this.childVM | |
if (!child || this.keepAlive) { | |
return | |
} | |
// the sole purpose of `deferCleanup` is so that we can | |
// "deactivate" the vm right now and perform DOM removal | |
// later. | |
child.$destroy(false, true) | |
}, | |
/** | |
* Remove current destroyed child and manually do | |
* the cleanup after removal. | |
* | |
* @param {Function} cb | |
*/ | |
remove: function (child, cb) { | |
var keepAlive = this.keepAlive | |
if (child) { | |
child.$remove(function () { | |
if (!keepAlive) child._cleanup() | |
if (cb) cb() | |
}) | |
} else if (cb) { | |
cb() | |
} | |
}, | |
/** | |
* Update callback for the dynamic literal scenario, | |
* e.g. v-component="{{view}}" | |
*/ | |
update: function (value) { | |
if (!value) { | |
// just destroy and remove current | |
this.unbuild() | |
this.remove(this.childVM) | |
this.unsetCurrent() | |
} else { | |
this.resolveCtor(value) | |
this.unbuild() | |
var newComponent = this.build() | |
var self = this | |
if (this.readyEvent) { | |
newComponent.$once(this.readyEvent, function () { | |
self.swapTo(newComponent) | |
}) | |
} else { | |
this.swapTo(newComponent) | |
} | |
} | |
}, | |
/** | |
* Actually swap the components, depending on the | |
* transition mode. Defaults to simultaneous. | |
* | |
* @param {Vue} target | |
*/ | |
swapTo: function (target) { | |
var self = this | |
var current = this.childVM | |
this.unsetCurrent() | |
this.setCurrent(target) | |
switch (self.transMode) { | |
case 'in-out': | |
target.$before(self.ref, function () { | |
self.remove(current) | |
}) | |
break | |
case 'out-in': | |
self.remove(current, function () { | |
target.$before(self.ref) | |
}) | |
break | |
default: | |
self.remove(current) | |
target.$before(self.ref) | |
} | |
}, | |
/** | |
* Set childVM and parent ref | |
*/ | |
setCurrent: function (child) { | |
this.childVM = child | |
var refID = child._refID || this.refID | |
if (refID) { | |
this.vm.$[refID] = child | |
} | |
}, | |
/** | |
* Unset childVM and parent ref | |
*/ | |
unsetCurrent: function () { | |
var child = this.childVM | |
this.childVM = null | |
var refID = (child && child._refID) || this.refID | |
if (refID) { | |
this.vm.$[refID] = null | |
} | |
}, | |
/** | |
* Unbind. | |
*/ | |
unbind: function () { | |
this.unbuild() | |
// destroy all keep-alive cached instances | |
if (this.cache) { | |
for (var key in this.cache) { | |
this.cache[key].$destroy() | |
} | |
this.cache = null | |
} | |
} | |
} | |
/***/ }, | |
/* 44 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var isObject = _.isObject | |
var isPlainObject = _.isPlainObject | |
var textParser = __webpack_require__(19) | |
var expParser = __webpack_require__(22) | |
var templateParser = __webpack_require__(20) | |
var compile = __webpack_require__(16) | |
var transclude = __webpack_require__(17) | |
var mergeOptions = __webpack_require__(14) | |
var uid = 0 | |
module.exports = { | |
/** | |
* Setup. | |
*/ | |
bind: function () { | |
// uid as a cache identifier | |
this.id = '__v_repeat_' + (++uid) | |
// we need to insert the objToArray converter | |
// as the first read filter, because it has to be invoked | |
// before any user filters. (can't do it in `update`) | |
if (!this.filters) { | |
this.filters = {} | |
} | |
// add the object -> array convert filter | |
var objectConverter = _.bind(objToArray, this) | |
if (!this.filters.read) { | |
this.filters.read = [objectConverter] | |
} else { | |
this.filters.read.unshift(objectConverter) | |
} | |
// setup ref node | |
this.ref = document.createComment('v-repeat') | |
_.replace(this.el, this.ref) | |
// check if this is a block repeat | |
this.template = this.el.tagName === 'TEMPLATE' | |
? templateParser.parse(this.el, true) | |
: this.el | |
// check other directives that need to be handled | |
// at v-repeat level | |
this.checkIf() | |
this.checkRef() | |
this.checkComponent() | |
// check for trackby param | |
this.idKey = | |
this._checkParam('track-by') || | |
this._checkParam('trackby') // 0.11.0 compat | |
this.cache = Object.create(null) | |
}, | |
/** | |
* Warn against v-if usage. | |
*/ | |
checkIf: function () { | |
if (_.attr(this.el, 'if') !== null) { | |
_.warn( | |
'Don\'t use v-if with v-repeat. ' + | |
'Use v-show or the "filterBy" filter instead.' | |
) | |
} | |
}, | |
/** | |
* Check if v-ref/ v-el is also present. | |
*/ | |
checkRef: function () { | |
var refID = _.attr(this.el, 'ref') | |
this.refID = refID | |
? this.vm.$interpolate(refID) | |
: null | |
var elId = _.attr(this.el, 'el') | |
this.elId = elId | |
? this.vm.$interpolate(elId) | |
: null | |
}, | |
/** | |
* Check the component constructor to use for repeated | |
* instances. If static we resolve it now, otherwise it | |
* needs to be resolved at build time with actual data. | |
*/ | |
checkComponent: function () { | |
var id = _.attr(this.el, 'component') | |
var options = this.vm.$options | |
if (!id) { | |
// default constructor | |
this.Ctor = _.Vue | |
// inline repeats should inherit | |
this.inherit = true | |
// important: transclude with no options, just | |
// to ensure block start and block end | |
this.template = transclude(this.template) | |
this._linkFn = compile(this.template, options) | |
} else { | |
this.asComponent = true | |
// check inline-template | |
if (this._checkParam('inline-template') !== null) { | |
// extract inline template as a DocumentFragment | |
this.inlineTempalte = _.extractContent(this.el, true) | |
} | |
var tokens = textParser.parse(id) | |
if (!tokens) { // static component | |
var Ctor = this.Ctor = options.components[id] | |
_.assertAsset(Ctor, 'component', id) | |
var merged = mergeOptions(Ctor.options, {}, { | |
$parent: this.vm | |
}) | |
merged.template = this.inlineTempalte || merged.template | |
merged._asComponent = true | |
merged._parent = this.vm | |
this.template = transclude(this.template, merged) | |
this._linkFn = compile(this.template, merged) | |
} else { | |
// to be resolved later | |
var ctorExp = textParser.tokensToExp(tokens) | |
this.ctorGetter = expParser.parse(ctorExp).get | |
} | |
} | |
}, | |
/** | |
* Update. | |
* This is called whenever the Array mutates. | |
* | |
* @param {Array|Number|String} data | |
*/ | |
update: function (data) { | |
data = data || [] | |
var type = typeof data | |
if (type === 'number') { | |
data = range(data) | |
} else if (type === 'string') { | |
data = _.toArray(data) | |
} | |
this.vms = this.diff(data, this.vms) | |
// update v-ref | |
if (this.refID) { | |
this.vm.$[this.refID] = this.vms | |
} | |
if (this.elId) { | |
this.vm.$$[this.elId] = this.vms.map(function (vm) { | |
return vm.$el | |
}) | |
} | |
}, | |
/** | |
* 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 | |
* @param {Array} oldVms | |
* @return {Array} | |
*/ | |
diff: function (data, oldVms) { | |
var idKey = this.idKey | |
var converted = this.converted | |
var ref = this.ref | |
var alias = this.arg | |
var init = !oldVms | |
var vms = new Array(data.length) | |
var obj, raw, vm, i, l | |
// First pass, go through the new Array and fill up | |
// the new vms 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++) { | |
obj = data[i] | |
raw = converted ? obj.$value : obj | |
vm = !init && this.getVm(raw) | |
if (vm) { // reusable instance | |
vm._reused = true | |
vm.$index = i // update $index | |
if (converted) { | |
vm.$key = obj.$key // update $key | |
} | |
if (idKey) { // swap track by id data | |
if (alias) { | |
vm[alias] = raw | |
} else { | |
vm._setData(raw) | |
} | |
} | |
} else { // new instance | |
vm = this.build(obj, i, true) | |
vm._new = true | |
vm._reused = false | |
} | |
vms[i] = vm | |
// insert if this is first run | |
if (init) { | |
vm.$before(ref) | |
} | |
} | |
// if this is the first run, we're done. | |
if (init) { | |
return vms | |
} | |
// Second pass, go through the old vm instances and | |
// destroy those who are not reused (and remove them | |
// from cache) | |
for (i = 0, l = oldVms.length; i < l; i++) { | |
vm = oldVms[i] | |
if (!vm._reused) { | |
this.uncacheVm(vm) | |
vm.$destroy(true) | |
} | |
} | |
// final pass, move/insert new instances into the | |
// right place. We're going in reverse here because | |
// insertBefore relies on the next sibling to be | |
// resolved. | |
var targetNext, currentNext | |
i = vms.length | |
while (i--) { | |
vm = vms[i] | |
// this is the vm that we should be in front of | |
targetNext = vms[i + 1] | |
if (!targetNext) { | |
// This is the last item. If it's reused then | |
// everything else will eventually be in the right | |
// place, so no need to touch it. Otherwise, insert | |
// it. | |
if (!vm._reused) { | |
vm.$before(ref) | |
} | |
} else { | |
var nextEl = targetNext.$el | |
if (vm._reused) { | |
// this is the vm we are actually in front of | |
currentNext = findNextVm(vm, ref) | |
// we only need to move if we are not in the right | |
// place already. | |
if (currentNext !== targetNext) { | |
vm.$before(nextEl, null, false) | |
} | |
} else { | |
// new instance, insert to existing next | |
vm.$before(nextEl) | |
} | |
} | |
vm._new = false | |
vm._reused = false | |
} | |
return vms | |
}, | |
/** | |
* Build a new instance and cache it. | |
* | |
* @param {Object} data | |
* @param {Number} index | |
* @param {Boolean} needCache | |
*/ | |
build: function (data, index, needCache) { | |
var meta = { $index: index } | |
if (this.converted) { | |
meta.$key = data.$key | |
} | |
var raw = this.converted ? data.$value : data | |
var alias = this.arg | |
if (alias) { | |
data = {} | |
data[alias] = raw | |
} else if (!isPlainObject(raw)) { | |
// non-object values | |
data = {} | |
meta.$value = raw | |
} else { | |
// default | |
data = raw | |
} | |
// resolve constructor | |
var Ctor = this.Ctor || this.resolveCtor(data, meta) | |
var vm = this.vm.$addChild({ | |
el: templateParser.clone(this.template), | |
_asComponent: this.asComponent, | |
_host: this._host, | |
_linkFn: this._linkFn, | |
_meta: meta, | |
data: data, | |
inherit: this.inherit, | |
template: this.inlineTempalte | |
}, Ctor) | |
// flag this instance as a repeat instance | |
// so that we can skip it in vm._digest | |
vm._repeat = true | |
// cache instance | |
if (needCache) { | |
this.cacheVm(raw, vm) | |
} | |
// sync back changes for $value, particularly for | |
// two-way bindings of primitive values | |
var self = this | |
vm.$watch('$value', function (val) { | |
if (self.converted) { | |
self.rawValue[vm.$key] = val | |
} else { | |
self.rawValue.$set(vm.$index, val) | |
} | |
}) | |
return vm | |
}, | |
/** | |
* Resolve a contructor to use for an instance. | |
* The tricky part here is that there could be dynamic | |
* components depending on instance data. | |
* | |
* @param {Object} data | |
* @param {Object} meta | |
* @return {Function} | |
*/ | |
resolveCtor: function (data, meta) { | |
// create a temporary context object and copy data | |
// and meta properties onto it. | |
// use _.define to avoid accidentally overwriting scope | |
// properties. | |
var context = Object.create(this.vm) | |
var key | |
for (key in data) { | |
_.define(context, key, data[key]) | |
} | |
for (key in meta) { | |
_.define(context, key, meta[key]) | |
} | |
var id = this.ctorGetter.call(context, context) | |
var Ctor = this.vm.$options.components[id] | |
_.assertAsset(Ctor, 'component', id) | |
return Ctor | |
}, | |
/** | |
* Unbind, teardown everything | |
*/ | |
unbind: function () { | |
if (this.refID) { | |
this.vm.$[this.refID] = null | |
} | |
if (this.vms) { | |
var i = this.vms.length | |
var vm | |
while (i--) { | |
vm = this.vms[i] | |
this.uncacheVm(vm) | |
vm.$destroy() | |
} | |
} | |
}, | |
/** | |
* Cache a vm instance based on its data. | |
* | |
* If the data is an object, we save the vm's reference on | |
* the data object as a hidden property. Otherwise we | |
* cache them in an object and for each primitive value | |
* there is an array in case there are duplicates. | |
* | |
* @param {Object} data | |
* @param {Vue} vm | |
*/ | |
cacheVm: function (data, vm) { | |
var idKey = this.idKey | |
var cache = this.cache | |
var id | |
if (idKey) { | |
id = data[idKey] | |
if (!cache[id]) { | |
cache[id] = vm | |
} else { | |
_.warn('Duplicate track-by key in v-repeat: ' + id) | |
} | |
} else if (isObject(data)) { | |
id = this.id | |
if (data.hasOwnProperty(id)) { | |
if (data[id] === null) { | |
data[id] = vm | |
} else { | |
_.warn( | |
'Duplicate objects are not supported in v-repeat ' + | |
'when using components or transitions.' | |
) | |
} | |
} else { | |
_.define(data, this.id, vm) | |
} | |
} else { | |
if (!cache[data]) { | |
cache[data] = [vm] | |
} else { | |
cache[data].push(vm) | |
} | |
} | |
vm._raw = data | |
}, | |
/** | |
* Try to get a cached instance from a piece of data. | |
* | |
* @param {Object} data | |
* @return {Vue|undefined} | |
*/ | |
getVm: function (data) { | |
if (this.idKey) { | |
return this.cache[data[this.idKey]] | |
} else if (isObject(data)) { | |
return data[this.id] | |
} else { | |
var cached = this.cache[data] | |
if (cached) { | |
var i = 0 | |
var vm = cached[i] | |
// since duplicated vm instances might be a reused | |
// one OR a newly created one, we need to return the | |
// first instance that is neither of these. | |
while (vm && (vm._reused || vm._new)) { | |
vm = cached[++i] | |
} | |
return vm | |
} | |
} | |
}, | |
/** | |
* Delete a cached vm instance. | |
* | |
* @param {Vue} vm | |
*/ | |
uncacheVm: function (vm) { | |
var data = vm._raw | |
if (this.idKey) { | |
this.cache[data[this.idKey]] = null | |
} else if (isObject(data)) { | |
data[this.id] = null | |
vm._raw = null | |
} else { | |
this.cache[data].pop() | |
} | |
} | |
} | |
/** | |
* Helper to find the next element that is an instance | |
* root node. This is necessary because a destroyed vm's | |
* element could still be lingering in the DOM before its | |
* leaving transition finishes, but its __vue__ reference | |
* should have been removed so we can skip them. | |
* | |
* @param {Vue} vm | |
* @param {CommentNode} ref | |
* @return {Vue} | |
*/ | |
function findNextVm (vm, ref) { | |
var el = (vm._blockEnd || vm.$el).nextSibling | |
while (!el.__vue__ && el !== ref) { | |
el = el.nextSibling | |
} | |
return el.__vue__ | |
} | |
/** | |
* Attempt to convert non-Array objects to array. | |
* This is the default filter installed to every v-repeat | |
* directive. | |
* | |
* It will be called with **the directive** as `this` | |
* context so that we can mark the repeat array as converted | |
* from an object. | |
* | |
* @param {*} obj | |
* @return {Array} | |
* @private | |
*/ | |
function objToArray (obj) { | |
// regardless of type, store the un-filtered raw value. | |
this.rawValue = obj | |
if (!isPlainObject(obj)) { | |
return obj | |
} | |
var keys = Object.keys(obj) | |
var i = keys.length | |
var res = new Array(i) | |
var key | |
while (i--) { | |
key = keys[i] | |
res[i] = { | |
$key: key, | |
$value: obj[key] | |
} | |
} | |
// `this` points to the repeat directive instance | |
this.converted = true | |
return res | |
} | |
/** | |
* 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 | |
} | |
/***/ }, | |
/* 45 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var compile = __webpack_require__(16) | |
var templateParser = __webpack_require__(20) | |
var transition = __webpack_require__(50) | |
module.exports = { | |
bind: function () { | |
var el = this.el | |
if (!el.__vue__) { | |
this.start = document.createComment('v-if-start') | |
this.end = document.createComment('v-if-end') | |
_.replace(el, this.end) | |
_.before(this.start, this.end) | |
if (el.tagName === 'TEMPLATE') { | |
this.template = templateParser.parse(el, true) | |
} else { | |
this.template = document.createDocumentFragment() | |
this.template.appendChild(templateParser.clone(el)) | |
} | |
// compile the nested partial | |
this.linker = compile( | |
this.template, | |
this.vm.$options, | |
true | |
) | |
} else { | |
this.invalid = true | |
_.warn( | |
'v-if="' + this.expression + '" cannot be ' + | |
'used on an already mounted instance.' | |
) | |
} | |
}, | |
update: function (value) { | |
if (this.invalid) return | |
if (value) { | |
// avoid duplicate compiles, since update() can be | |
// called with different truthy values | |
if (!this.unlink) { | |
var frag = templateParser.clone(this.template) | |
this.compile(frag) | |
} | |
} else { | |
this.teardown() | |
} | |
}, | |
// NOTE: this function is shared in v-partial | |
compile: function (frag) { | |
var vm = this.vm | |
// the linker is not guaranteed to be present because | |
// this function might get called by v-partial | |
this.unlink = this.linker | |
? this.linker(vm, frag) | |
: vm.$compile(frag) | |
transition.blockAppend(frag, this.end, vm) | |
// call attached for all the child components created | |
// during the compilation | |
if (_.inDoc(vm.$el)) { | |
var children = this.getContainedComponents() | |
if (children) children.forEach(callAttach) | |
} | |
}, | |
// NOTE: this function is shared in v-partial | |
teardown: function () { | |
if (!this.unlink) return | |
// collect children beforehand | |
var children | |
if (_.inDoc(this.vm.$el)) { | |
children = this.getContainedComponents() | |
} | |
transition.blockRemove(this.start, this.end, this.vm) | |
if (children) children.forEach(callDetach) | |
this.unlink() | |
this.unlink = null | |
}, | |
// NOTE: this function is shared in v-partial | |
getContainedComponents: function () { | |
var vm = this.vm | |
var start = this.start.nextSibling | |
var end = this.end | |
var selfCompoents = | |
vm._children.length && | |
vm._children.filter(contains) | |
var transComponents = | |
vm._transCpnts && | |
vm._transCpnts.filter(contains) | |
function contains (c) { | |
var cur = start | |
var next | |
while (next !== end) { | |
next = cur.nextSibling | |
if (cur.contains(c.$el)) { | |
return true | |
} | |
cur = next | |
} | |
return false | |
} | |
return selfCompoents | |
? transComponents | |
? selfCompoents.concat(transComponents) | |
: selfCompoents | |
: transComponents | |
}, | |
// NOTE: this function is shared in v-partial | |
unbind: function () { | |
if (this.unlink) this.unlink() | |
} | |
} | |
function callAttach (child) { | |
if (!child._isAttached) { | |
child._callHook('attached') | |
} | |
} | |
function callDetach (child) { | |
if (child._isAttached) { | |
child._callHook('detached') | |
} | |
} | |
/***/ }, | |
/* 46 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var Watcher = __webpack_require__(25) | |
var expParser = __webpack_require__(22) | |
var literalRE = /^(true|false|\s?('[^']*'|"[^"]")\s?)$/ | |
module.exports = { | |
priority: 900, | |
bind: function () { | |
var child = this.vm | |
var parent = child.$parent | |
var childKey = this.arg || '$data' | |
var parentKey = this.expression | |
if (this.el && this.el !== child.$el) { | |
_.warn( | |
'v-with can only be used on instance root elements.' | |
) | |
} else if (!parent) { | |
_.warn( | |
'v-with must be used on an instance with a parent.' | |
) | |
} else if (literalRE.test(parentKey)) { | |
// no need to setup watchers for literal bindings | |
if (!this.arg) { | |
_.warn( | |
'v-with cannot bind literal value as $data: ' + | |
parentKey | |
) | |
} else { | |
var value = expParser.parse(parentKey).get() | |
child.$set(childKey, value) | |
} | |
} else { | |
// simple lock to avoid circular updates. | |
// without this it would stabilize too, but this makes | |
// sure it doesn't cause other watchers to re-evaluate. | |
var locked = false | |
var lock = function () { | |
locked = true | |
_.nextTick(unlock) | |
} | |
var unlock = function () { | |
locked = false | |
} | |
this.parentWatcher = new Watcher( | |
parent, | |
parentKey, | |
function (val) { | |
if (!locked) { | |
lock() | |
child.$set(childKey, val) | |
} | |
} | |
) | |
// set the child initial value first, before setting | |
// up the child watcher to avoid triggering it | |
// immediately. | |
child.$set(childKey, this.parentWatcher.value) | |
this.childWatcher = new Watcher( | |
child, | |
childKey, | |
function (val) { | |
if (!locked) { | |
lock() | |
parent.$set(parentKey, val) | |
} | |
} | |
) | |
} | |
}, | |
unbind: function () { | |
if (this.parentWatcher) { | |
this.parentWatcher.teardown() | |
this.childWatcher.teardown() | |
} | |
} | |
} | |
/***/ }, | |
/* 47 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
module.exports = { | |
acceptStatement: true, | |
bind: function () { | |
var child = this.el.__vue__ | |
if (!child || this.vm !== child.$parent) { | |
_.warn( | |
'`v-events` should only be used on a child component ' + | |
'from the parent template.' | |
) | |
return | |
} | |
}, | |
update: function (handler, oldHandler) { | |
if (typeof handler !== 'function') { | |
_.warn( | |
'Directive "v-events:' + this.expression + '" ' + | |
'expects a function value.' | |
) | |
return | |
} | |
var child = this.el.__vue__ | |
if (oldHandler) { | |
child.$off(this.arg, oldHandler) | |
} | |
child.$on(this.arg, handler) | |
} | |
// when child is destroyed, all events are turned off, | |
// so no need for unbind here. | |
} | |
/***/ }, | |
/* 48 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var Path = __webpack_require__(18) | |
/** | |
* Filter filter for v-repeat | |
* | |
* @param {String} searchKey | |
* @param {String} [delimiter] | |
* @param {String} dataKey | |
*/ | |
exports.filterBy = function (arr, searchKey, delimiter, dataKey) { | |
// allow optional `in` delimiter | |
// because why not | |
if (delimiter && delimiter !== 'in') { | |
dataKey = delimiter | |
} | |
// get the search string | |
var search = | |
_.stripQuotes(searchKey) || | |
this.$get(searchKey) | |
if (!search) { | |
return arr | |
} | |
search = ('' + search).toLowerCase() | |
// get the optional dataKey | |
dataKey = | |
dataKey && | |
(_.stripQuotes(dataKey) || this.$get(dataKey)) | |
return arr.filter(function (item) { | |
return dataKey | |
? contains(Path.get(item, dataKey), search) | |
: contains(item, search) | |
}) | |
} | |
/** | |
* Filter filter for v-repeat | |
* | |
* @param {String} sortKey | |
* @param {String} reverseKey | |
*/ | |
exports.orderBy = function (arr, sortKey, reverseKey) { | |
var key = | |
_.stripQuotes(sortKey) || | |
this.$get(sortKey) | |
if (!key) { | |
return arr | |
} | |
var order = 1 | |
if (reverseKey) { | |
if (reverseKey === '-1') { | |
order = -1 | |
} else if (reverseKey.charCodeAt(0) === 0x21) { // ! | |
reverseKey = reverseKey.slice(1) | |
order = this.$get(reverseKey) ? 1 : -1 | |
} else { | |
order = this.$get(reverseKey) ? -1 : 1 | |
} | |
} | |
// sort on a copy to avoid mutating original array | |
return arr.slice().sort(function (a, b) { | |
a = _.isObject(a) ? Path.get(a, key) : a | |
b = _.isObject(b) ? Path.get(b, key) : b | |
return a === b ? 0 : a > b ? order : -order | |
}) | |
} | |
/** | |
* String contain helper | |
* | |
* @param {*} val | |
* @param {String} search | |
*/ | |
function contains (val, search) { | |
if (_.isObject(val)) { | |
for (var key in val) { | |
if (contains(val[key], search)) { | |
return true | |
} | |
} | |
} else if (val != null) { | |
return val.toString().toLowerCase().indexOf(search) > -1 | |
} | |
} | |
/***/ }, | |
/* 49 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var config = __webpack_require__(15) | |
var Dep = __webpack_require__(23) | |
var arrayMethods = __webpack_require__(54) | |
var arrayKeys = Object.getOwnPropertyNames(arrayMethods) | |
__webpack_require__(55) | |
var uid = 0 | |
/** | |
* Type enums | |
*/ | |
var ARRAY = 0 | |
var OBJECT = 1 | |
/** | |
* 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) { | |
var i = keys.length | |
var key | |
while (i--) { | |
key = keys[i] | |
_.define(target, key, src[key]) | |
} | |
} | |
/** | |
* 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 | |
* @param {Number} type | |
* @constructor | |
*/ | |
function Observer (value, type) { | |
this.id = ++uid | |
this.value = value | |
this.active = true | |
this.deps = [] | |
_.define(value, '__ob__', this) | |
if (type === ARRAY) { | |
var augment = config.proto && _.hasProto | |
? protoAugment | |
: copyAugment | |
augment(value, arrayMethods, arrayKeys) | |
this.observeArray(value) | |
} else if (type === OBJECT) { | |
this.walk(value) | |
} | |
} | |
Observer.target = null | |
var p = Observer.prototype | |
/** | |
* 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 | |
* @return {Observer|undefined} | |
* @static | |
*/ | |
Observer.create = function (value) { | |
if ( | |
value && | |
value.hasOwnProperty('__ob__') && | |
value.__ob__ instanceof Observer | |
) { | |
return value.__ob__ | |
} else if (_.isArray(value)) { | |
return new Observer(value, ARRAY) | |
} else if ( | |
_.isPlainObject(value) && | |
!value._isVue // avoid Vue instance | |
) { | |
return new Observer(value, OBJECT) | |
} | |
} | |
/** | |
* Walk through each property and convert them into | |
* getter/setters. This method should only be called when | |
* value type is Object. Properties prefixed with `$` or `_` | |
* and accessor properties are ignored. | |
* | |
* @param {Object} obj | |
*/ | |
p.walk = function (obj) { | |
var keys = Object.keys(obj) | |
var i = keys.length | |
var key, prefix | |
while (i--) { | |
key = keys[i] | |
prefix = key.charCodeAt(0) | |
if (prefix !== 0x24 && prefix !== 0x5F) { // skip $ or _ | |
this.convert(key, obj[key]) | |
} | |
} | |
} | |
/** | |
* Try to carete an observer for a child value, | |
* and if value is array, link dep to the array. | |
* | |
* @param {*} val | |
* @return {Dep|undefined} | |
*/ | |
p.observe = function (val) { | |
return Observer.create(val) | |
} | |
/** | |
* Observe a list of Array items. | |
* | |
* @param {Array} items | |
*/ | |
p.observeArray = function (items) { | |
var i = items.length | |
while (i--) { | |
this.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 | |
*/ | |
p.convert = function (key, val) { | |
var ob = this | |
var childOb = ob.observe(val) | |
var dep = new Dep() | |
if (childOb) { | |
childOb.deps.push(dep) | |
} | |
Object.defineProperty(ob.value, key, { | |
enumerable: true, | |
configurable: true, | |
get: function () { | |
// Observer.target is a watcher whose getter is | |
// currently being evaluated. | |
if (ob.active && Observer.target) { | |
Observer.target.addDep(dep) | |
} | |
return val | |
}, | |
set: function (newVal) { | |
if (newVal === val) return | |
// remove dep from old value | |
var oldChildOb = val && val.__ob__ | |
if (oldChildOb) { | |
var oldDeps = oldChildOb.deps | |
oldDeps.splice(oldDeps.indexOf(dep), 1) | |
} | |
val = newVal | |
// add dep to new value | |
var newChildOb = ob.observe(newVal) | |
if (newChildOb) { | |
newChildOb.deps.push(dep) | |
} | |
dep.notify() | |
} | |
}) | |
} | |
/** | |
* Notify change on all self deps on an observer. | |
* This is called when a mutable value mutates. e.g. | |
* when an Array's mutating methods are called, or an | |
* Object's $add/$delete are called. | |
*/ | |
p.notify = function () { | |
var deps = this.deps | |
for (var i = 0, l = deps.length; i < l; i++) { | |
deps[i].notify() | |
} | |
} | |
/** | |
* Add an owner vm, so that when $add/$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 | |
*/ | |
p.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 | |
*/ | |
p.removeVm = function (vm) { | |
this.vms.splice(this.vms.indexOf(vm), 1) | |
} | |
module.exports = Observer | |
/***/ }, | |
/* 50 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var applyCSSTransition = __webpack_require__(56) | |
var applyJSTransition = __webpack_require__(57) | |
var doc = typeof document === 'undefined' ? null : document | |
/** | |
* Append with transition. | |
* | |
* @oaram {Element} el | |
* @param {Element} target | |
* @param {Vue} vm | |
* @param {Function} [cb] | |
*/ | |
exports.append = function (el, target, vm, cb) { | |
apply(el, 1, function () { | |
target.appendChild(el) | |
}, vm, cb) | |
} | |
/** | |
* InsertBefore with transition. | |
* | |
* @oaram {Element} el | |
* @param {Element} target | |
* @param {Vue} vm | |
* @param {Function} [cb] | |
*/ | |
exports.before = function (el, target, vm, cb) { | |
apply(el, 1, function () { | |
_.before(el, target) | |
}, vm, cb) | |
} | |
/** | |
* Remove with transition. | |
* | |
* @oaram {Element} el | |
* @param {Vue} vm | |
* @param {Function} [cb] | |
*/ | |
exports.remove = function (el, vm, cb) { | |
apply(el, -1, function () { | |
_.remove(el) | |
}, vm, cb) | |
} | |
/** | |
* Remove by appending to another parent with transition. | |
* This is only used in block operations. | |
* | |
* @oaram {Element} el | |
* @param {Element} target | |
* @param {Vue} vm | |
* @param {Function} [cb] | |
*/ | |
exports.removeThenAppend = function (el, target, vm, cb) { | |
apply(el, -1, function () { | |
target.appendChild(el) | |
}, vm, cb) | |
} | |
/** | |
* Append the childNodes of a fragment to target. | |
* | |
* @param {DocumentFragment} block | |
* @param {Node} target | |
* @param {Vue} vm | |
*/ | |
exports.blockAppend = function (block, target, vm) { | |
var nodes = _.toArray(block.childNodes) | |
for (var i = 0, l = nodes.length; i < l; i++) { | |
exports.before(nodes[i], target, vm) | |
} | |
} | |
/** | |
* Remove a block of nodes between two edge nodes. | |
* | |
* @param {Node} start | |
* @param {Node} end | |
* @param {Vue} vm | |
*/ | |
exports.blockRemove = function (start, end, vm) { | |
var node = start.nextSibling | |
var next | |
while (node !== end) { | |
next = node.nextSibling | |
exports.remove(node, vm) | |
node = next | |
} | |
} | |
/** | |
* Apply transitions with an operation callback. | |
* | |
* @oaram {Element} el | |
* @param {Number} direction | |
* 1: enter | |
* -1: leave | |
* @param {Function} op - the actual DOM operation | |
* @param {Vue} vm | |
* @param {Function} [cb] | |
*/ | |
var apply = exports.apply = function (el, direction, op, vm, cb) { | |
var transData = el.__v_trans | |
if ( | |
!transData || | |
!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 | |
} | |
// determine the transition type on the element | |
var jsTransition = transData.fns | |
if (jsTransition) { | |
// js | |
applyJSTransition( | |
el, | |
direction, | |
op, | |
transData, | |
jsTransition, | |
vm, | |
cb | |
) | |
} else 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. | |
!(doc && doc.hidden) | |
) { | |
// css | |
applyCSSTransition( | |
el, | |
direction, | |
op, | |
transData, | |
cb | |
) | |
} else { | |
// not applicable | |
op() | |
if (cb) cb() | |
} | |
} | |
/***/ }, | |
/* 51 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var handlers = { | |
_default: __webpack_require__(58), | |
radio: __webpack_require__(59), | |
select: __webpack_require__(60), | |
checkbox: __webpack_require__(61) | |
} | |
module.exports = { | |
priority: 800, | |
twoWay: true, | |
handlers: handlers, | |
/** | |
* Possible elements: | |
* <select> | |
* <textarea> | |
* <input type="*"> | |
* - text | |
* - checkbox | |
* - radio | |
* - number | |
* - TODO: more types may be supplied as a plugin | |
*/ | |
bind: function () { | |
// friendly warning... | |
var filters = this.filters | |
if (filters && filters.read && !filters.write) { | |
_.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._default | |
} else if (tag === 'SELECT') { | |
handler = handlers.select | |
} else if (tag === 'TEXTAREA') { | |
handler = handlers._default | |
} else { | |
_.warn("v-model doesn't support element type: " + tag) | |
return | |
} | |
handler.bind.call(this) | |
this.update = handler.update | |
this.unbind = handler.unbind | |
} | |
} | |
/***/ }, | |
/* 52 */ | |
/***/ function(module, exports, __webpack_require__) { | |
/** | |
* A doubly linked list-based Least Recently Used (LRU) | |
* cache. Will keep most recently used items while | |
* discarding least recently used items when its limit is | |
* reached. This is a bare-bone version of | |
* Rasmus Andersson's js-lru: | |
* | |
* https://github.com/rsms/js-lru | |
* | |
* @param {Number} limit | |
* @constructor | |
*/ | |
function Cache (limit) { | |
this.size = 0 | |
this.limit = limit | |
this.head = this.tail = undefined | |
this._keymap = {} | |
} | |
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 entry = { | |
key:key, | |
value:value | |
} | |
this._keymap[key] = entry | |
if (this.tail) { | |
this.tail.newer = entry | |
entry.older = this.tail | |
} else { | |
this.head = entry | |
} | |
this.tail = entry | |
if (this.size === this.limit) { | |
return this.shift() | |
} else { | |
this.size++ | |
} | |
} | |
/** | |
* 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 | |
} | |
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 | |
} | |
module.exports = Cache | |
/***/ }, | |
/* 53 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var MAX_UPDATE_COUNT = 10 | |
// 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 waiting = false | |
var flushing = false | |
/** | |
* Reset the batcher's state. | |
*/ | |
function reset () { | |
queue = [] | |
userQueue = [] | |
has = {} | |
waiting = false | |
flushing = false | |
} | |
/** | |
* Flush both queues and run the jobs. | |
*/ | |
function flush () { | |
flushing = true | |
run(queue) | |
run(userQueue) | |
reset() | |
} | |
/** | |
* Run the jobs in a single queue. | |
* | |
* @param {Array} queue | |
*/ | |
function run (queue) { | |
// do not cache length because more jobs might be pushed | |
// as we run existing jobs | |
for (var i = 0; i < queue.length; i++) { | |
queue[i].run() | |
} | |
} | |
/** | |
* Push a job into the job queue. | |
* Jobs with duplicate IDs will be skipped unless it's | |
* pushed when the queue is being flushed. | |
* | |
* @param {Object} job | |
* properties: | |
* - {String|Number} id | |
* - {Function} run | |
*/ | |
exports.push = function (job) { | |
var id = job.id | |
if (!id || !has[id] || flushing) { | |
if (!has[id]) { | |
has[id] = 1 | |
} else { | |
has[id]++ | |
// detect possible infinite update loops | |
if (has[id] > MAX_UPDATE_COUNT) { | |
_.warn( | |
'You may have an infinite update loop for the ' + | |
'watcher with expression: "' + job.expression + '".' | |
) | |
return | |
} | |
} | |
// A user watcher callback could trigger another | |
// directive update during the flushing; at that time | |
// the directive queue would already have been run, so | |
// we call that update immediately as it is pushed. | |
if (flushing && !job.user) { | |
job.run() | |
return | |
} | |
;(job.user ? userQueue : queue).push(job) | |
if (!waiting) { | |
waiting = true | |
_.nextTick(flush) | |
} | |
} | |
} | |
/***/ }, | |
/* 54 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
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] | |
_.define(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.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 | |
*/ | |
_.define( | |
arrayProto, | |
'$set', | |
function $set (index, val) { | |
if (index >= this.length) { | |
this.length = index + 1 | |
} | |
return this.splice(index, 1, val)[0] | |
} | |
) | |
/** | |
* Convenience method to remove the element at given index. | |
* | |
* @param {Number} index | |
* @param {*} val | |
*/ | |
_.define( | |
arrayProto, | |
'$remove', | |
function $remove (index) { | |
if (typeof index !== 'number') { | |
index = this.indexOf(index) | |
} | |
if (index > -1) { | |
return this.splice(index, 1)[0] | |
} | |
} | |
) | |
module.exports = arrayMethods | |
/***/ }, | |
/* 55 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var objProto = Object.prototype | |
/** | |
* Add a new property to an observed object | |
* and emits corresponding event | |
* | |
* @param {String} key | |
* @param {*} val | |
* @public | |
*/ | |
_.define( | |
objProto, | |
'$add', | |
function $add (key, val) { | |
if (this.hasOwnProperty(key)) return | |
var ob = this.__ob__ | |
if (!ob || _.isReserved(key)) { | |
this[key] = val | |
return | |
} | |
ob.convert(key, val) | |
if (ob.vms) { | |
var i = ob.vms.length | |
while (i--) { | |
var vm = ob.vms[i] | |
vm._proxy(key) | |
vm._digest() | |
} | |
} else { | |
ob.notify() | |
} | |
} | |
) | |
/** | |
* Set a property on an observed object, calling add to | |
* ensure the property is observed. | |
* | |
* @param {String} key | |
* @param {*} val | |
* @public | |
*/ | |
_.define( | |
objProto, | |
'$set', | |
function $set (key, val) { | |
this.$add(key, val) | |
this[key] = val | |
} | |
) | |
/** | |
* Deletes a property from an observed object | |
* and emits corresponding event | |
* | |
* @param {String} key | |
* @public | |
*/ | |
_.define( | |
objProto, | |
'$delete', | |
function $delete (key) { | |
if (!this.hasOwnProperty(key)) return | |
delete this[key] | |
var ob = this.__ob__ | |
if (!ob || _.isReserved(key)) { | |
return | |
} | |
if (ob.vms) { | |
var i = ob.vms.length | |
while (i--) { | |
var vm = ob.vms[i] | |
vm._unproxy(key) | |
vm._digest() | |
} | |
} else { | |
ob.notify() | |
} | |
} | |
) | |
/***/ }, | |
/* 56 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var addClass = _.addClass | |
var removeClass = _.removeClass | |
var transDurationProp = _.transitionProp + 'Duration' | |
var animDurationProp = _.animationProp + 'Duration' | |
var queue = [] | |
var queued = false | |
/** | |
* Push a job into the transition queue, which is to be | |
* executed on next frame. | |
* | |
* @param {Element} el - target element | |
* @param {Number} dir - 1: enter, -1: leave | |
* @param {Function} op - the actual dom operation | |
* @param {String} cls - the className to remove when the | |
* transition is done. | |
* @param {Function} [cb] - user supplied callback. | |
*/ | |
function push (el, dir, op, cls, cb) { | |
queue.push({ | |
el : el, | |
dir : dir, | |
cb : cb, | |
cls : cls, | |
op : op | |
}) | |
if (!queued) { | |
queued = true | |
_.nextTick(flush) | |
} | |
} | |
/** | |
* Flush the queue, and do one forced reflow before | |
* triggering transitions. | |
*/ | |
function flush () { | |
/* jshint unused: false */ | |
var f = document.documentElement.offsetHeight | |
queue.forEach(run) | |
queue = [] | |
queued = false | |
} | |
/** | |
* Run a transition job. | |
* | |
* @param {Object} job | |
*/ | |
function run (job) { | |
var el = job.el | |
var data = el.__v_trans | |
var cls = job.cls | |
var cb = job.cb | |
var op = job.op | |
var transitionType = getTransitionType(el, data, cls) | |
if (job.dir > 0) { // ENTER | |
if (transitionType === 1) { | |
// trigger transition by removing enter class | |
removeClass(el, cls) | |
// only need to listen for transitionend if there's | |
// a user callback | |
if (cb) setupTransitionCb(_.transitionEndEvent) | |
} else if (transitionType === 2) { | |
// animations are triggered when class is added | |
// so we just listen for animationend to remove it. | |
setupTransitionCb(_.animationEndEvent, function () { | |
removeClass(el, cls) | |
}) | |
} else { | |
// no transition applicable | |
removeClass(el, cls) | |
if (cb) cb() | |
} | |
} else { // LEAVE | |
if (transitionType) { | |
// leave transitions/animations are both triggered | |
// by adding the class, just remove it on end event. | |
var event = transitionType === 1 | |
? _.transitionEndEvent | |
: _.animationEndEvent | |
setupTransitionCb(event, function () { | |
op() | |
removeClass(el, cls) | |
}) | |
} else { | |
op() | |
removeClass(el, cls) | |
if (cb) cb() | |
} | |
} | |
/** | |
* Set up a transition end callback, store the callback | |
* on the element's __v_trans data object, so we can | |
* clean it up if another transition is triggered before | |
* the callback is fired. | |
* | |
* @param {String} event | |
* @param {Function} [cleanupFn] | |
*/ | |
function setupTransitionCb (event, cleanupFn) { | |
data.event = event | |
var onEnd = data.callback = function transitionCb (e) { | |
if (e.target === el) { | |
_.off(el, event, onEnd) | |
data.event = data.callback = null | |
if (cleanupFn) cleanupFn() | |
if (cb) cb() | |
} | |
} | |
_.on(el, event, onEnd) | |
} | |
} | |
/** | |
* Get an element's transition type based on the | |
* calculated styles | |
* | |
* @param {Element} el | |
* @param {Object} data | |
* @param {String} className | |
* @return {Number} | |
* 1 - transition | |
* 2 - animation | |
*/ | |
function getTransitionType (el, data, className) { | |
var type = data.cache && data.cache[className] | |
if (type) return type | |
var inlineStyles = el.style | |
var computedStyles = window.getComputedStyle(el) | |
var transDuration = | |
inlineStyles[transDurationProp] || | |
computedStyles[transDurationProp] | |
if (transDuration && transDuration !== '0s') { | |
type = 1 | |
} else { | |
var animDuration = | |
inlineStyles[animDurationProp] || | |
computedStyles[animDurationProp] | |
if (animDuration && animDuration !== '0s') { | |
type = 2 | |
} | |
} | |
if (type) { | |
if (!data.cache) data.cache = {} | |
data.cache[className] = type | |
} | |
return type | |
} | |
/** | |
* Apply CSS transition to an element. | |
* | |
* @param {Element} el | |
* @param {Number} direction - 1: enter, -1: leave | |
* @param {Function} op - the actual DOM operation | |
* @param {Object} data - target element's transition data | |
*/ | |
module.exports = function (el, direction, op, data, cb) { | |
var prefix = data.id || 'v' | |
var enterClass = prefix + '-enter' | |
var leaveClass = prefix + '-leave' | |
// clean up potential previous unfinished transition | |
if (data.callback) { | |
_.off(el, data.event, data.callback) | |
removeClass(el, enterClass) | |
removeClass(el, leaveClass) | |
data.event = data.callback = null | |
} | |
if (direction > 0) { // enter | |
addClass(el, enterClass) | |
op() | |
push(el, direction, null, enterClass, cb) | |
} else { // leave | |
addClass(el, leaveClass) | |
push(el, direction, op, leaveClass, cb) | |
} | |
} | |
/***/ }, | |
/* 57 */ | |
/***/ function(module, exports, __webpack_require__) { | |
/** | |
* Apply JavaScript enter/leave functions. | |
* | |
* @param {Element} el | |
* @param {Number} direction - 1: enter, -1: leave | |
* @param {Function} op - the actual DOM operation | |
* @param {Object} data - target element's transition data | |
* @param {Object} def - transition definition object | |
* @param {Vue} vm - the owner vm of the element | |
* @param {Function} [cb] | |
*/ | |
module.exports = function (el, direction, op, data, def, vm, cb) { | |
// if the element is the root of an instance, | |
// use that instance as the transition function context | |
vm = el.__vue__ || vm | |
if (data.cancel) { | |
data.cancel() | |
data.cancel = null | |
} | |
if (direction > 0) { // enter | |
if (def.beforeEnter) { | |
def.beforeEnter.call(vm, el) | |
} | |
op() | |
if (def.enter) { | |
data.cancel = def.enter.call(vm, el, function () { | |
data.cancel = null | |
if (cb) cb() | |
}) | |
} else if (cb) { | |
cb() | |
} | |
} else { // leave | |
if (def.leave) { | |
data.cancel = def.leave.call(vm, el, function () { | |
data.cancel = null | |
op() | |
if (cb) cb() | |
}) | |
} else { | |
op() | |
if (cb) cb() | |
} | |
} | |
} | |
/***/ }, | |
/* 58 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
module.exports = { | |
bind: function () { | |
var self = this | |
var el = this.el | |
// check params | |
// - lazy: update model on "change" instead of "input" | |
var lazy = this._checkParam('lazy') != null | |
// - number: cast value into number when updating model. | |
var number = this._checkParam('number') != null | |
// - debounce: debounce the input listener | |
var debounce = parseInt(this._checkParam('debounce'), 10) | |
// handle composition events. | |
// http://blog.evanyou.me/2014/01/03/composition-event/ | |
var cpLocked = false | |
this.cpLock = function () { | |
cpLocked = true | |
} | |
this.cpUnlock = function () { | |
cpLocked = 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. | |
set() | |
} | |
_.on(el,'compositionstart', this.cpLock) | |
_.on(el,'compositionend', this.cpUnlock) | |
// shared setter | |
function set () { | |
self.set( | |
number ? _.toNumber(el.value) : el.value, | |
true | |
) | |
} | |
// if the directive has filters, we need to | |
// record cursor position and restore it after updating | |
// the input with the filtered value. | |
// also force update for type="range" inputs to enable | |
// "lock in range" (see #506) | |
var hasReadFilter = this.filters && this.filters.read | |
this.listener = hasReadFilter || el.type === 'range' | |
? function textInputListener () { | |
if (cpLocked) return | |
var charsOffset | |
// some HTML5 input types throw error here | |
try { | |
// record how many chars from the end of input | |
// the cursor was at | |
charsOffset = el.value.length - el.selectionStart | |
} catch (e) {} | |
// Fix IE10/11 infinite update cycle | |
// https://github.com/yyx990803/vue/issues/592 | |
/* istanbul ignore if */ | |
if (charsOffset < 0) { | |
return | |
} | |
set() | |
_.nextTick(function () { | |
// force a value update, because in | |
// certain cases the write filters output the | |
// same result for different input values, and | |
// the Observer set events won't be triggered. | |
var newVal = self._watcher.value | |
self.update(newVal) | |
if (charsOffset != null) { | |
var cursorPos = | |
_.toString(newVal).length - charsOffset | |
el.setSelectionRange(cursorPos, cursorPos) | |
} | |
}) | |
} | |
: function textInputListener () { | |
if (cpLocked) return | |
set() | |
} | |
if (debounce) { | |
this.listener = _.debounce(this.listener, debounce) | |
} | |
this.event = lazy ? 'change' : 'input' | |
// 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(this.event, this.listener) | |
} else { | |
_.on(el, this.event, this.listener) | |
} | |
// IE9 doesn't fire input event on backspace/del/cut | |
if (!lazy && _.isIE9) { | |
this.onCut = function () { | |
_.nextTick(self.listener) | |
} | |
this.onDel = function (e) { | |
if (e.keyCode === 46 || e.keyCode === 8) { | |
self.listener() | |
} | |
} | |
_.on(el, 'cut', this.onCut) | |
_.on(el, 'keyup', this.onDel) | |
} | |
// set initial value if present | |
if ( | |
el.hasAttribute('value') || | |
(el.tagName === 'TEXTAREA' && el.value.trim()) | |
) { | |
this._initValue = number | |
? _.toNumber(el.value) | |
: el.value | |
} | |
}, | |
update: function (value) { | |
this.el.value = _.toString(value) | |
}, | |
unbind: function () { | |
var el = this.el | |
if (this.hasjQuery) { | |
jQuery(el).off(this.event, this.listener) | |
} else { | |
_.off(el, this.event, this.listener) | |
} | |
_.off(el,'compositionstart', this.cpLock) | |
_.off(el,'compositionend', this.cpUnlock) | |
if (this.onCut) { | |
_.off(el,'cut', this.onCut) | |
_.off(el,'keyup', this.onDel) | |
} | |
} | |
} | |
/***/ }, | |
/* 59 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
module.exports = { | |
bind: function () { | |
var self = this | |
var el = this.el | |
this.listener = function () { | |
self.set(el.value, true) | |
} | |
_.on(el, 'change', this.listener) | |
if (el.checked) { | |
this._initValue = el.value | |
} | |
}, | |
update: function (value) { | |
/* jshint eqeqeq: false */ | |
this.el.checked = value == this.el.value | |
}, | |
unbind: function () { | |
_.off(this.el, 'change', this.listener) | |
} | |
} | |
/***/ }, | |
/* 60 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
var Watcher = __webpack_require__(25) | |
var dirParser = __webpack_require__(21) | |
module.exports = { | |
bind: function () { | |
var self = this | |
var el = this.el | |
// check options param | |
var optionsParam = this._checkParam('options') | |
if (optionsParam) { | |
initOptions.call(this, optionsParam) | |
} | |
this.number = this._checkParam('number') != null | |
this.multiple = el.hasAttribute('multiple') | |
this.listener = function () { | |
var value = self.multiple | |
? getMultiValue(el) | |
: el.value | |
value = self.number | |
? _.isArray(value) | |
? value.map(_.toNumber) | |
: _.toNumber(value) | |
: value | |
self.set(value, true) | |
} | |
_.on(el, 'change', this.listener) | |
checkInitialValue.call(this) | |
}, | |
update: function (value) { | |
/* jshint eqeqeq: false */ | |
var el = this.el | |
el.selectedIndex = -1 | |
var multi = this.multiple && _.isArray(value) | |
var options = el.options | |
var i = options.length | |
var option | |
while (i--) { | |
option = options[i] | |
option.selected = multi | |
? indexOf(value, option.value) > -1 | |
: value == option.value | |
} | |
}, | |
unbind: function () { | |
_.off(this.el, 'change', this.listener) | |
if (this.optionWatcher) { | |
this.optionWatcher.teardown() | |
} | |
} | |
} | |
/** | |
* Initialize the option list from the param. | |
* | |
* @param {String} expression | |
*/ | |
function initOptions (expression) { | |
var self = this | |
var descriptor = dirParser.parse(expression)[0] | |
function optionUpdateWatcher (value) { | |
if (_.isArray(value)) { | |
self.el.innerHTML = '' | |
buildOptions(self.el, value) | |
if (self._watcher) { | |
self.update(self._watcher.value) | |
} | |
} else { | |
_.warn('Invalid options value for v-model: ' + value) | |
} | |
} | |
this.optionWatcher = new Watcher( | |
this.vm, | |
descriptor.expression, | |
optionUpdateWatcher, | |
{ | |
deep: true, | |
filters: _.resolveFilters(this.vm, descriptor.filters) | |
} | |
) | |
// update with initial value | |
optionUpdateWatcher(this.optionWatcher.value) | |
} | |
/** | |
* Build up option elements. IE9 doesn't create options | |
* when setting innerHTML on <select> elements, so we have | |
* to use DOM API here. | |
* | |
* @param {Element} parent - a <select> or an <optgroup> | |
* @param {Array} options | |
*/ | |
function buildOptions (parent, options) { | |
var op, el | |
for (var i = 0, l = options.length; i < l; i++) { | |
op = options[i] | |
if (!op.options) { | |
el = document.createElement('option') | |
if (typeof op === 'string') { | |
el.text = el.value = op | |
} else { | |
el.text = op.text | |
el.value = op.value | |
} | |
} else { | |
el = document.createElement('optgroup') | |
el.label = op.label | |
buildOptions(el, op.options) | |
} | |
parent.appendChild(el) | |
} | |
} | |
/** | |
* Check the initial value for selected options. | |
*/ | |
function checkInitialValue () { | |
var initValue | |
var options = this.el.options | |
for (var i = 0, l = options.length; i < l; i++) { | |
if (options[i].hasAttribute('selected')) { | |
if (this.multiple) { | |
(initValue || (initValue = [])) | |
.push(options[i].value) | |
} else { | |
initValue = options[i].value | |
} | |
} | |
} | |
if (typeof initValue !== 'undefined') { | |
this._initValue = this.number | |
? _.toNumber(initValue) | |
: initValue | |
} | |
} | |
/** | |
* Helper to extract a value array for select[multiple] | |
* | |
* @param {SelectElement} el | |
* @return {Array} | |
*/ | |
function getMultiValue (el) { | |
return Array.prototype.filter | |
.call(el.options, filterSelected) | |
.map(getOptionValue) | |
} | |
function filterSelected (op) { | |
return op.selected | |
} | |
function getOptionValue (op) { | |
return op.value || op.text | |
} | |
/** | |
* Native Array.indexOf uses strict equal, but in this | |
* case we need to match string/numbers with soft equal. | |
* | |
* @param {Array} arr | |
* @param {*} val | |
*/ | |
function indexOf (arr, val) { | |
/* jshint eqeqeq: false */ | |
var i = arr.length | |
while (i--) { | |
if (arr[i] == val) return i | |
} | |
return -1 | |
} | |
/***/ }, | |
/* 61 */ | |
/***/ function(module, exports, __webpack_require__) { | |
var _ = __webpack_require__(11) | |
module.exports = { | |
bind: function () { | |
var self = this | |
var el = this.el | |
this.listener = function () { | |
self.set(el.checked, true) | |
} | |
_.on(el, 'change', this.listener) | |
if (el.checked) { | |
this._initValue = el.checked | |
} | |
}, | |
update: function (value) { | |
this.el.checked = !!value | |
}, | |
unbind: function () { | |
_.off(this.el, 'change', this.listener) | |
} | |
} | |
/***/ } | |
/******/ ]) | |
}); | |
; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment