From 512d265cbd656da5e19cf1d5f1a43f321b6488a5 Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 26 Sep 2014 21:23:47 -0400 Subject: [PATCH] build 0.11.0-rc --- bower.json | 2 +- component.json | 2 +- dist/vue.js | 7205 +++++++++++++++++++++++++++++++++++++++++++++++ dist/vue.min.js | 7 + package.json | 2 +- 5 files changed, 7215 insertions(+), 3 deletions(-) create mode 100644 dist/vue.js create mode 100644 dist/vue.min.js diff --git a/bower.json b/bower.json index 64d131170da..22436de53e9 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "vue", - "version": "0.11.0", + "version": "0.11.0-rc", "main": "dist/vue.js", "description": "Simple, Fast & Composable MVVM for building interative interfaces", "authors": ["Evan You "], diff --git a/component.json b/component.json index 184b0aefc8c..1427e3f6f78 100644 --- a/component.json +++ b/component.json @@ -1,6 +1,6 @@ { "name": "vue", - "version": "0.11.0", + "version": "0.11.0-rc", "main": "src/vue.js", "author": "Evan You ", "description": "Simple, Fast & Composable MVVM for building interative interfaces", diff --git a/dist/vue.js b/dist/vue.js new file mode 100644 index 00000000000..85e4a045fb7 --- /dev/null +++ b/dist/vue.js @@ -0,0 +1,7205 @@ +/** + * Vue.js v0.11.0-rc + * (c) 2014 Evan You + * Released under the MIT License. + */ + +;(function(){ + +"use strict" + +/** + * Require the module at `name`. + * + * @param {String} name + * @return {Object} exports + * @api public + */ + +function require(name) { + var module = require.modules[name]; + if (!module) throw new Error('failed to require "' + name + '"'); + + if (!('exports' in module) && typeof module.definition === 'function') { + module.client = module.component = true; + module.definition.call(this, module.exports = {}, module); + delete module.definition; + } + + return module.exports; +} + +/** + * Registered modules. + */ + +require.modules = {}; + +/** + * Register module at `name` with callback `definition`. + * + * @param {String} name + * @param {Function} definition + * @api private + */ + +require.register = function (name, definition) { + require.modules[name] = { + definition: definition + }; +}; + +/** + * Define a module's exports immediately with `exports`. + * + * @param {String} name + * @param {Generic} exports + * @api private + */ + +require.define = function (name, exports) { + require.modules[name] = { + exports: exports + }; +}; +require.register(1, function (exports, module) { +var _ = require(2) + +/** + * 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 + if (!ctors) { + ctors = parent._childCtors = {} + } + ChildVue = ctors[BaseCtor.cid] + if (!ChildVue) { + ChildVue = function (options) { + this.constructor = ChildVue + _.Vue.call(this, 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) + if (!this._children) { + this._children = [] + } + this._children.push(child) + return child +} +}); + +require.register(3, function (exports, module) { +var _ = require(2) +var Watcher = require(4) +var textParser = require(5) +var dirParser = require(6) +var expParser = require(7) +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) { + return res.get.call(this, this) + } +} + +/** + * 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, null, false, deep) + } 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} [key] + */ + +exports.$log = function (key) { + var data = this[key || '_data'] + console.log(JSON.parse(JSON.stringify(data))) +} +}); + +require.register(8, function (exports, module) { +var _ = require(2) +var transition = require(9) + +/** + * Append instance to target + * + * @param {Node} target + * @param {Function} [cb] + * @param {Boolean} [withTransition] - defaults to true + */ + +exports.$appendTo = function (target, cb, withTransition) { + var targetIsDetached = !_.inDoc(target) + var op = withTransition === false || targetIsDetached + ? append + : transition.append + insert(this, target, op, targetIsDetached, cb) +} + +/** + * 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) + } +} + +/** + * Insert instance before target + * + * @param {Node} target + * @param {Function} [cb] + * @param {Boolean} [withTransition] - defaults to true + */ + +exports.$before = function (target, cb, withTransition) { + var targetIsDetached = !_.inDoc(target) + var op = withTransition === false || targetIsDetached + ? before + : transition.before + insert(this, target, op, targetIsDetached, cb) +} + +/** + * 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) + } +} + +/** + * 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) + } +} + +/** + * Shared DOM insertion function. + * + * @param {Vue} vm + * @param {Element} target + * @param {Function} op + * @param {Boolean} targetIsDetached + * @param {Function} [cb] + */ + +function insert (vm, target, op, targetIsDetached, cb) { + target = query(target) + 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') + } +} + +/** + * 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() +} +}); + +require.register(10, function (exports, module) { +var _ = require(2) + +/** + * 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) +} + +/** + * 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) +} + +/** + * 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 + } + // specific event + cbs = this._events[event] + if (!cbs) return + if (arguments.length === 1) { + modifyListenerCount(this, event, -cbs.length) + this._events[event] = null + return + } + // 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 + } + } +} + +/** + * 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 + } + } + } +} + +/** + * 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 + if (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) + } + } + } +} + +/** + * 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 + } +} + +/** + * 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 + } +} +}); + +require.register(11, function (exports, module) { +var _ = require(2) +var mergeOptions = require(12) + +/** + * Expose useful internals + */ + +exports.util = _ +exports.nextTick = _.nextTick +exports.config = require(13) + +/** + * 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 || '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( + 'Vue', + 'return function ' + _.camelize(name) + + ' (options) { Vue.call(this, options) }' + )(_.Vue) +} + +/** + * 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) +}); + +require.register(14, function (exports, module) { +var _ = require(2) + +/** + * 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 (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) + } +} + +/** + * Mark an instance as ready. + */ + +function ready () { + this._isAttached = true + this._isReady = true + this._callHook('ready') +} + +/** + * 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. + * @public + */ + +exports.$destroy = function (remove) { + if (this._isDestroyed) { + return + } + this._callHook('beforeDestroy') + this._isBeingDestroyed = true + // remove DOM element + if (remove && this.$el) { + this.$remove() + } + 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) + } + // destroy all children. + if (this._children) { + i = this._children.length + while (i--) { + this._children[i].$destroy() + } + } + // teardown all directives. this also tearsdown all + // directive-owned watchers. + i = this._directives.length + while (i--) { + this._directives[i]._teardown() + } + // teardown all user watchers. + for (i in this._userWatchers) { + this._userWatchers[i].teardown() + } + // clean up + if (this.$el) { + this.$el.__vue__ = null + } + // 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._bindings = + this._directives = null + // call the last hook... + this._isDestroyed = true + this._callHook('destroyed') + // turn off all instance listeners. + this.$off() +} +}); + +require.register(15, function (exports, module) { +var _ = require(2) + +/** + * The Batcher maintains a job queue to be run + * async on the next event loop. + */ + +function Batcher () { + this._preFlush = null + this.reset() +} + +var p = Batcher.prototype + +/** + * Push a job into the job queue. + * Jobs with duplicate IDs will be skipped, however we can + * use the `override` option to override existing jobs. + * + * @param {Object} job + * properties: + * - {String|Number} id + * - {Boolean} override + * - {Function} run + */ + +p.push = function (job) { + if (!job.id || !this.has[job.id]) { + this.queue.push(job) + this.has[job.id] = job + if (!this.waiting) { + this.waiting = true + _.nextTick(this.flush, this) + } + } else if (job.override) { + var oldJob = this.has[job.id] + oldJob.cancelled = true + this.queue.push(job) + this.has[job.id] = job + } +} + +/** + * Flush the queue and run the jobs. + * Will call a preFlush hook if has one. + */ + +p.flush = function () { + // before flush hook + if (this._preFlush) { + this._preFlush() + } + // do not cache length because more jobs might be pushed + // as we run existing jobs + for (var i = 0; i < this.queue.length; i++) { + var job = this.queue[i] + if (!job.cancelled) { + job.run() + } + } + this.reset() +} + +/** + * Reset the batcher's state. + */ + +p.reset = function () { + this.has = {} + this.queue = [] + this.waiting = false +} + +module.exports = Batcher +}); + +require.register(16, function (exports, module) { +var uid = 0 + +/** + * A binding is an observable that can have multiple + * directives subscribing to it. + * + * @constructor + */ + +function Binding () { + this.id = ++uid + this.subs = [] +} + +var p = Binding.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 () { + var i = this.subs.length + while (i--) { + this.subs[i].update() + } +} + +module.exports = Binding +}); + +require.register(17, function (exports, module) { +/** + * 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 into the cache associated with . + * Returns the entry which was removed to make room for + * the new entry. Otherwise undefined is returned. + * (i.e. if there was enough room already). + * + * @param {String} key + * @param {*} value + * @return {Entry|undefined} + */ + +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 . Returns the value + * associated with 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 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 +}); + +require.register(18, function (exports, module) { +var _ = require(2) +var config = require(13) +var textParser = require(5) +var dirParser = require(6) +var templateParser = require(19) + +function noop () {} + +/** + * 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 + * @return {Function} + */ + +module.exports = function compile (el, options, partial) { + var params = !partial && options.paramAttributes + var paramsLinkFn = params + ? compileParamAttributes(el, params, options) + : null + var nodeLinkFn = el instanceof DocumentFragment + ? null + : compileNode(el, options) + var childLinkFn = + (!nodeLinkFn || !nodeLinkFn.terminal) && + el.hasChildNodes() + ? compileNodeList(el.childNodes, options) + : null + return function link (vm, el) { + if (paramsLinkFn) paramsLinkFn(vm, el) + if (nodeLinkFn) nodeLinkFn(vm, el) + if (childLinkFn) childLinkFn(vm, el.childNodes) + } +} + +/** + * Compile a node and return a nodeLinkFn based on the + * node type. + * + * @param {Node} node + * @param {Object} options + * @return {Function|undefined} + */ + +function compileNode (node, options) { + var type = node.nodeType + if (type === 1 && node.tagName !== 'SCRIPT') { + return compileElement(node, options) + } else if (type === 3 && config.interpolate) { + return compileTextNode(node, options) + } +} + +/** + * Compile an element and return a nodeLinkFn. + * + * @param {Element} el + * @param {Object} options + * @return {Function|null} + */ + +function compileElement (el, options) { + var hasAttributes = el.hasAttributes() + var tag = el.tagName.toLowerCase() + if (hasAttributes) { + // check terminal direcitves + var terminalLinkFn + for (var i = 0; i < 3; i++) { + terminalLinkFn = checkTerminalDirectives(el, options) + if (terminalLinkFn) { + terminalLinkFn.terminal = true + return terminalLinkFn + } + } + } + // check custom element component + var component = + tag.indexOf('-') > 0 && + options.components[tag] + if (component) { + return makeTeriminalLinkFn(el, 'component', tag, options) + } + // check other directives + var linkFn + if (hasAttributes) { + var directives = collectDirectives(el, options) + linkFn = directives.length + ? makeDirectivesLinkFn(directives) + : 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) + } + } + return linkFn +} + +/** + * Build a multi-directive link function. + * + * @param {Array} directives + * @return {Function} directivesLinkFn + */ + +function makeDirectivesLinkFn (directives) { + return function directivesLinkFn (vm, el) { + // reverse apply because it's sorted low to high + var i = directives.length + var dir, j + while (i--) { + dir = directives[i] + if (dir._link) { + // custom link fn + dir._link(vm, el) + } else { + j = dir.descriptors.length + while (j--) { + vm._bindDir(dir.name, el, + dir.descriptors[j], dir.def) + } + } + } + } +} + +/** + * 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.nodeValue) + if (!tokens) { + return null + } + var frag = document.createDocumentFragment() + var dirs = options.directives + var el, token, value + for (var i = 0, l = tokens.length; i < l; i++) { + token = tokens[i] + value = token.value + if (token.tag) { + if (token.oneTime) { + el = document.createTextNode(value) + } else { + if (token.html) { + el = document.createComment('v-html') + token.type = 'html' + token.def = dirs.html + token.descriptor = dirParser.parse(value)[0] + } else if (token.partial) { + el = document.createComment('v-partial') + token.type = 'partial' + token.def = dirs.partial + token.descriptor = dirParser.parse(value)[0] + } else { + // IE will clean up empty textNodes during + // frag.cloneNode(true), so we have to give it + // something here... + el = document.createTextNode(' ') + token.type = 'text' + token.def = dirs.text + token.descriptor = dirParser.parse(value)[0] + } + } + } else { + el = document.createTextNode(value) + } + frag.appendChild(el) + } + return makeTextNodeLinkFn(tokens, frag, options) +} + +/** + * Build a function that processes a textNode. + * + * @param {Array} 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.nodeValue = 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.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} linkFns + * @return {Function} childLinkFn + */ + +function makeChildLinkFn (linkFns) { + return function childLinkFn (vm, nodes) { + // stablize nodes + nodes = _.toArray(nodes) + 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++] + if (nodeLinkFn) { + nodeLinkFn(vm, node) + } + if (childrenLinkFn) { + childrenLinkFn(vm, node.childNodes) + } + } + } +} + +/** + * Compile param attributes on a root element and return + * a paramAttributes link function. + * + * @param {Element} el + * @param {Array} attrs + * @param {Object} options + * @return {Function} paramsLinkFn + */ + +function compileParamAttributes (el, attrs, options) { + var params = [] + var i = attrs.length + var name, value, param + while (i--) { + name = attrs[i] + value = el.getAttribute(name) + if (value !== null) { + param = { + name: name, + value: value + } + var tokens = textParser.parse(value) + if (tokens) { + 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 + */ + +function makeParamsLinkFn (params, options) { + var def = options.directives['with'] + return function paramsLinkFn (vm, el) { + var i = params.length + var param + while (i--) { + param = params[i] + 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: param.name, + expression: param.value + }, def) + } else { + // just set once + vm.$set(param.name, 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', + 'component', + 'if' +] + +function checkTerminalDirectives (el, options) { + if (_.attr(el, 'pre') !== null) { + return noop + } + var value, dirName + /* jshint boss: true */ + for (var i = 0; i < 3; i++) { + dirName = terminalDirectives[i] + if (value = _.attr(el, dirName)) { + return makeTeriminalLinkFn(el, dirName, value, options) + } + } +} + +/** + * Build a link function for a terminal directive. + * + * @param {Element} el + * @param {String} dirName + * @param {String} value + * @param {Object} options + * @return {Function} terminalLinkFn + */ + +function makeTeriminalLinkFn (el, dirName, value, options) { + var descriptor = dirParser.parse(value)[0] + var def = options.directives[dirName] + return function terminalLinkFn (vm, el) { + vm._bindDir(dirName, el, descriptor, def) + } +} + +/** + * 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 + while (i--) { + attr = attrs[i] + attrName = attr.name + if (attrName.indexOf(config.prefix) === 0) { + dirName = attrName.slice(config.prefix.length) + dirDef = options.directives[dirName] + _.assertAsset(dirDef, 'directive', dirName) + if (dirDef) { + if (dirName !== 'cloak') { + el.removeAttribute(attrName) + } + dirs.push({ + name: dirName, + descriptors: dirParser.parse(attr.value), + def: dirDef + }) + } + } else if (config.interpolate) { + dir = collectAttrDirective(el, attrName, attr.value, + options) + if (dir) { + 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 +} +}); + +require.register(20, function (exports, module) { +var _ = require(2) +var templateParser = require(19) + +/** + * 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) { + // 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.template) { + return transcludeTemplate(el, options) + } else { + 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 { + collectRawContent(el) + if (options.replace) { + if (frag.childNodes.length > 1) { + transcludeContent(_.toArray(frag.childNodes)) + return frag + } else { + var replacer = frag.firstChild + _.copyAttributes(el, replacer) + transcludeContent(replacer) + return replacer + } + } else { + el.appendChild(frag) + transcludeContent(el) + return el + } + } +} + +/** + * Collect raw content inside $el before they are + * replaced by template content. + */ + +var rawContent +function collectRawContent (el) { + var child + rawContent = null + if (el.hasChildNodes()) { + rawContent = document.createElement('div') + /* jshint boss:true */ + while (child = el.firstChild) { + rawContent.appendChild(child) + } + } +} + +/** + * Resolve insertion points mimicking the behavior + * of the Shadow DOM spec: + * + * http://w3c.github.io/webcomponents/spec/shadow/#insertion-points + * + * @param {Element|DocumentFragment} el + */ + +function transcludeContent (el) { + var outlets = getOutlets(el) + var i = outlets.length + if (!i) return + var outlet, select, j, main + // first pass, collect corresponding content + // for each outlet. + while (i--) { + outlet = outlets[i] + if (rawContent) { + select = outlet.getAttribute('select') + if (select) { // select content + outlet.content = _.toArray( + rawContent.querySelectorAll(select) + ) + } 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(rawContent.childNodes)) + } +} + +/** + * Get 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.nodeType === 1 + ? _.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) +} +}); + +require.register(13, function (exports, module) { +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, + + /** + * 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} + */ + +var delimiters = ['{{', '}}'] +Object.defineProperty(module.exports, 'delimiters', { + get: function () { + return delimiters + }, + set: function (val) { + delimiters = val + this._delimitersChanged = true + } +}) +}); + +require.register(21, function (exports, module) { +var _ = require(2) +var Watcher = require(4) +var textParser = require(5) +var expParser = require(7) + +/** + * 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} [filters] + * @param {Object} def - directive definition object + * @param {Function} [linker] - pre-compiled linker function + * @constructor + */ + +function Directive (name, el, vm, descriptor, def, linker) { + // 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._linker = linker + 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 (typeof def === 'function') { + this.update = def + } else { + _.extend(this, def) + } + this._watcherExp = this.expression + this._checkDynamicLiteral() + if (this.bind) { + this.bind() + } + if ( + this.expression && this.update && + (!this.isLiteral || this._isDynamicLiteral) && + !this._checkExpFn() + ) { + // use raw expression as identifier because filters + // make them different watchers + var watcher = this.vm._watchers[this.raw] + // wrapped updater for context + var dir = this + var update = this._update = function (val, oldVal) { + if (!dir._locked) { + dir.update(val, oldVal) + } + } + if (!watcher) { + watcher = this.vm._watchers[this.raw] = new Watcher( + this.vm, + this._watcherExp, + update, // callback + this.filters, + this.twoWay // need setter + ) + } else { + watcher.addCb(update) + } + this._watcher = watcher + 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._checkExpFn = function () { + var expression = this.expression + if ( + expression && this.isFn && + !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 + } +} + +/** + * 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.expression] = 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 +}); + +require.register(22, function (exports, module) { +// 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 != null) { + 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') + } +} +}); + +require.register(23, function (exports, module) { +var _ = require(2) +var hasClassList = + typeof document !== 'undefined' && + 'classList' in document.documentElement + +/** + * add class for IE9 + * + * @param {Element} el + * @param {Strong} cls + */ + +var addClass = hasClassList + ? function (el, cls) { + el.classList.add(cls) + } + : _.addClass + +/** + * remove class for IE9 + * + * @param {Element} el + * @param {Strong} cls + */ + +var removeClass = hasClassList + ? function (el, cls) { + el.classList.remove(cls) + } + : _.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 + } + } +} +}); + +require.register(24, function (exports, module) { +var config = require(13) + +module.exports = { + + bind: function () { + var el = this.el + this.vm.$once('hook:compiled', function () { + el.removeAttribute(config.prefix + 'cloak') + }) + } + +} +}); + +require.register(25, function (exports, module) { +var _ = require(2) +var Watcher = require(4) + +module.exports = { + + isLiteral: true, + + /** + * Setup. Need to check a few possible permutations: + * + * - literal: + * v-component="comp" + * + * - dynamic: + * v-component="{{currentView}}" + * + * - conditional: + * v-component="comp" v-if="abc" + * + * - dynamic + conditional: + * v-component="{{currentView}}" v-if="abc" + */ + + bind: function () { + if (!this.el.__vue__) { + // create a ref anchor + this.ref = document.createComment('v-component') + _.replace(this.el, this.ref) + // check v-if conditionals + this.checkIf() + // check keep-alive options + this.checkKeepAlive() + // if static, build right now. + if (!this._isDynamicLiteral) { + this.resolveCtor(this.expression) + this.build() + } + } else { + _.warn( + 'v-component="' + this.expression + '" cannot be ' + + 'used on an already mounted instance.' + ) + } + }, + + /** + * Check if v-component is being used together with v-if. + * If yes, we created a watcher for the v-if value and + * react to its value change in `this.ifCallback`. + */ + + checkIf: function () { + var condition = _.attr(this.el, 'if') + if (condition !== null) { + var self = this + this.ifWatcher = new Watcher( + this.vm, + condition, + function (value) { + self.toggleIf(value) + } + ) + this.active = this.ifWatcher.value + } else { + this.active = true + } + }, + + /** + * Callback when v-if value changes. + * Marks the active flag. + * + * @param {*} value + */ + + toggleIf: function (value) { + if (value) { + this.active = true + this.build() + } else { + this.active = false + this.unbuild(true) + } + }, + + /** + * Check if the "keep-alive" flag is present. + * 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. + */ + + checkKeepAlive: function () { + // check keep-alive flag + this.keepAlive = this.el.hasAttribute('keep-alive') + if (this.keepAlive) { + this.el.removeAttribute('keep-alive') + this.cache = {} + } + }, + + /** + * 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. + */ + + build: function () { + if (!this.active) { + return + } + if (this.keepAlive) { + var vm = this.cache[this.ctorId] + if (vm) { + this.childVM = vm + vm.$before(this.ref) + return + } + } + if (this.Ctor && !this.childVM) { + this.childVM = this.vm.$addChild({ + el: this.el.cloneNode(true) + }, this.Ctor) + if (this.keepAlive) { + this.cache[this.ctorId] = this.childVM + } + this.childVM.$before(this.ref) + } + }, + + /** + * Teardown the active vm. + * If keep alive, simply remove it; otherwise destroy it. + * + * @param {Boolean} remove + */ + + unbuild: function (remove) { + if (!this.childVM) { + return + } + if (this.keepAlive) { + if (remove) { + this.childVM.$remove() + } + } else { + this.childVM.$destroy(remove) + } + this.childVM = null + }, + + /** + * Update callback for the dynamic literal scenario, + * e.g. v-component="{{view}}" + */ + + update: function (value) { + this.unbuild(true) + if (value) { + this.resolveCtor(value) + this.build() + } + }, + + /** + * Unbind. + * Make sure keepAlive is set to false so that the + * instance is always destroyed. Teardown v-if watcher + * if present. + */ + + unbind: function () { + this.keepAlive = false + this.unbuild() + if (this.ifWatcher) { + this.ifWatcher.teardown() + } + } + +} +}); + +require.register(26, function (exports, module) { +module.exports = { + + isLiteral: true, + + bind: function () { + this.vm._owner.$$[this.expression] = this.el + }, + + unbind: function () { + this.vm._owner.$$[this.expression] = null + } + +} +}); + +require.register(27, function (exports, module) { +var _ = require(2) +var templateParser = require(19) + +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 + var frag = templateParser.parse(value, true) + // save a reference to these nodes so we can remove later + this.nodes = _.toArray(frag.childNodes) + _.before(frag, this.el) + } + +} +}); + +require.register(28, function (exports, module) { +var _ = require(2) +var templateParser = require(19) + +module.exports = { + + bind: function () { + var el = this.el + if (!el.__vue__) { + this.ref = document.createComment('v-if') + _.replace(el, this.ref) + this.inserted = false + if (el.tagName === 'TEMPLATE') { + this.el = templateParser.parse(el, 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) { + if (!this.inserted) { + if (!this.childVM) { + this.childVM = this.vm.$addChild({ + el: this.el, + inherit: true, + _anonymous: true + }) + } + this.childVM.$before(this.ref) + this.inserted = true + } + } else { + if (this.inserted) { + this.childVM.$remove() + this.inserted = false + } + } + }, + + unbind: function () { + if (this.childVM) { + this.childVM.$destroy() + } + } + +} +}); + +require.register(29, function (exports, module) { +// manipulation directives +exports.text = require(30) +exports.html = require(27) +exports.attr = require(22) +exports.show = require(31) +exports['class'] = require(23) +exports.el = require(26) +exports.ref = require(32) +exports.cloak = require(24) +exports.style = require(33) +exports.partial = require(34) +exports.transition = require(35) + +// event listener directives +exports.on = require(36) +exports.model = require(37) + +// child vm directives +exports.component = require(25) +exports.repeat = require(38) +exports['if'] = require(28) +exports['with'] = require(39) +}); + +require.register(40, function (exports, module) { +var _ = require(2) + +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) { + // watcher is not set up yet + this.vm.$set(this.expression, el.checked) + } + }, + + update: function (value) { + this.el.checked = !!value + }, + + unbind: function () { + _.off(this.el, 'change', this.listener) + } + +} +}); + +require.register(37, function (exports, module) { +var _ = require(2) + +var handlers = { + text: require(41), + radio: require(42), + select: require(43), + checkbox: require(40) +} + +module.exports = { + + priority: 800, + twoWay: true, + handlers: handlers, + + /** + * Possible elements: + *