/* Vue.js v0.10.6 (c) 2014 Evan You License: MIT */ ;(function(){ 'use strict'; /** * Require the given path. * * @param {String} path * @return {Object} exports * @api public */ function require(path, parent, orig) { var resolved = require.resolve(path); // lookup failed if (null == resolved) { throwError() return } var module = require.modules[resolved]; // perform real require() // by invoking the module's // registered function if (!module._resolving && !module.exports) { var mod = {}; mod.exports = {}; mod.client = mod.component = true; module._resolving = true; module.call(this, mod.exports, require.relative(resolved), mod); delete module._resolving; module.exports = mod.exports; } function throwError () { orig = orig || path; parent = parent || 'root'; var err = new Error('Failed to require "' + orig + '" from "' + parent + '"'); err.path = orig; err.parent = parent; err.require = true; throw err; } return module.exports; } /** * Registered modules. */ require.modules = {}; /** * Registered aliases. */ require.aliases = {}; /** * Resolve `path`. * * Lookup: * * - PATH/index.js * - PATH.js * - PATH * * @param {String} path * @return {String} path or null * @api private */ require.exts = [ '', '.js', '.json', '/index.js', '/index.json' ]; require.resolve = function(path) { if (path.charAt(0) === '/') path = path.slice(1); for (var i = 0; i < 5; i++) { var fullPath = path + require.exts[i]; if (require.modules.hasOwnProperty(fullPath)) return fullPath; if (require.aliases.hasOwnProperty(fullPath)) return require.aliases[fullPath]; } }; /** * Normalize `path` relative to the current path. * * @param {String} curr * @param {String} path * @return {String} * @api private */ require.normalize = function(curr, path) { var segs = []; if ('.' != path.charAt(0)) return path; curr = curr.split('/'); path = path.split('/'); for (var i = 0; i < path.length; ++i) { if ('..' === path[i]) { curr.pop(); } else if ('.' != path[i] && '' != path[i]) { segs.push(path[i]); } } return curr.concat(segs).join('/'); }; /** * Register module at `path` with callback `definition`. * * @param {String} path * @param {Function} definition * @api private */ require.register = function(path, definition) { require.modules[path] = definition; }; /** * Alias a module definition. * * @param {String} from * @param {String} to * @api private */ require.alias = function(from, to) { if (!require.modules.hasOwnProperty(from)) { throwError() return } require.aliases[to] = from; function throwError () { throw new Error('Failed to alias "' + from + '", it does not exist'); } }; /** * Return a require function relative to the `parent` path. * * @param {String} parent * @return {Function} * @api private */ require.relative = function(parent) { var p = require.normalize(parent, '..'); /** * The relative require() itself. */ function localRequire(path) { var resolved = localRequire.resolve(path); return require(resolved, parent, path); } /** * Resolve relative to the parent. */ localRequire.resolve = function(path) { var c = path.charAt(0); if ('/' === c) return path.slice(1); if ('.' === c) return require.normalize(p, path); // resolve deps by returning // the dep in the nearest "deps" // directory var segs = parent.split('/'); var i = segs.length; while (i--) { if (segs[i] === 'deps') { break; } } path = segs.slice(0, i + 2).join('/') + '/deps/' + path; return path; }; /** * Check if module is defined at `path`. */ localRequire.exists = function(path) { return require.modules.hasOwnProperty(localRequire.resolve(path)); }; return localRequire; }; require.register("vue/src/main.js", function(exports, require, module){ var config = require('./config'), ViewModel = require('./viewmodel'), utils = require('./utils'), makeHash = utils.hash, assetTypes = ['directive', 'filter', 'partial', 'effect', 'component'], // Internal modules that are exposed for plugins pluginAPI = { utils: utils, config: config, transition: require('./transition'), observer: require('./observer') } ViewModel.options = config.globalAssets = { directives : require('./directives'), filters : require('./filters'), partials : makeHash(), effects : makeHash(), components : makeHash() } /** * Expose asset registration methods */ assetTypes.forEach(function (type) { ViewModel[type] = function (id, value) { var hash = this.options[type + 's'] if (!hash) { hash = this.options[type + 's'] = makeHash() } if (!value) return hash[id] if (type === 'partial') { value = utils.parseTemplateOption(value) } else if (type === 'component') { value = utils.toConstructor(value) } else if (type === 'filter') { utils.checkFilter(value) } hash[id] = value return this } }) /** * Set config options */ ViewModel.config = function (opts, val) { if (typeof opts === 'string') { if (val === undefined) { return config[opts] } else { config[opts] = val } } else { utils.extend(config, opts) } return this } /** * Expose an interface for plugins */ ViewModel.use = function (plugin) { if (typeof plugin === 'string') { try { plugin = require(plugin) } catch (e) { utils.warn('Cannot find plugin: ' + plugin) return } } // additional parameters var args = [].slice.call(arguments, 1) args.unshift(this) if (typeof plugin.install === 'function') { plugin.install.apply(plugin, args) } else { plugin.apply(null, args) } return this } /** * Expose internal modules for plugins */ ViewModel.require = function (module) { return pluginAPI[module] } ViewModel.extend = extend ViewModel.nextTick = utils.nextTick /** * Expose the main ViewModel class * and add extend method */ function extend (options) { var ParentVM = this // extend data options need to be copied // on instantiation if (options.data) { options.defaultData = options.data delete options.data } // inherit options // but only when the super class is not the native Vue. if (ParentVM !== ViewModel) { options = inheritOptions(options, ParentVM.options, true) } utils.processOptions(options) var ExtendedVM = function (opts, asParent) { if (!asParent) { opts = inheritOptions(opts, options, true) } ParentVM.call(this, opts, true) } // inherit prototype props var proto = ExtendedVM.prototype = Object.create(ParentVM.prototype) utils.defProtected(proto, 'constructor', ExtendedVM) // allow extended VM to be further extended ExtendedVM.extend = extend ExtendedVM.super = ParentVM ExtendedVM.options = options // allow extended VM to add its own assets assetTypes.forEach(function (type) { ExtendedVM[type] = ViewModel[type] }) // allow extended VM to use plugins ExtendedVM.use = ViewModel.use ExtendedVM.require = ViewModel.require return ExtendedVM } /** * Inherit options * * For options such as `data`, `vms`, `directives`, 'partials', * they should be further extended. However extending should only * be done at top level. * * `proto` is an exception because it's handled directly on the * prototype. * * `el` is an exception because it's not allowed as an * extension option, but only as an instance option. */ function inheritOptions (child, parent, topLevel) { child = child || {} if (!parent) return child for (var key in parent) { if (key === 'el') continue var val = child[key], parentVal = parent[key] if (topLevel && typeof val === 'function' && parentVal) { // merge hook functions into an array child[key] = [val] if (Array.isArray(parentVal)) { child[key] = child[key].concat(parentVal) } else { child[key].push(parentVal) } } else if ( topLevel && (utils.isTrueObject(val) || utils.isTrueObject(parentVal)) && !(parentVal instanceof ViewModel) ) { // merge toplevel object options child[key] = inheritOptions(val, parentVal) } else if (val === undefined) { // inherit if child doesn't override child[key] = parentVal } } return child } module.exports = ViewModel }); require.register("vue/src/emitter.js", function(exports, require, module){ var slice = [].slice function Emitter (ctx) { this._ctx = ctx || this } var EmitterProto = Emitter.prototype EmitterProto.on = function (event, fn) { this._cbs = this._cbs || {} ;(this._cbs[event] = this._cbs[event] || []) .push(fn) return this } EmitterProto.once = function (event, fn) { var self = this this._cbs = this._cbs || {} function on () { self.off(event, on) fn.apply(this, arguments) } on.fn = fn this.on(event, on) return this } EmitterProto.off = function (event, fn) { this._cbs = this._cbs || {} // all if (!arguments.length) { this._cbs = {} return this } // specific event var callbacks = this._cbs[event] if (!callbacks) return this // remove all handlers if (arguments.length === 1) { delete this._cbs[event] return this } // remove specific handler var cb for (var i = 0; i < callbacks.length; i++) { cb = callbacks[i] if (cb === fn || cb.fn === fn) { callbacks.splice(i, 1) break } } return this } /** * The internal, faster emit with fixed amount of arguments * using Function.call */ EmitterProto.emit = function (event, a, b, c) { this._cbs = this._cbs || {} var callbacks = this._cbs[event] if (callbacks) { callbacks = callbacks.slice(0) for (var i = 0, len = callbacks.length; i < len; i++) { callbacks[i].call(this._ctx, a, b, c) } } return this } /** * The external emit using Function.apply */ EmitterProto.applyEmit = function (event) { this._cbs = this._cbs || {} var callbacks = this._cbs[event], args if (callbacks) { callbacks = callbacks.slice(0) args = slice.call(arguments, 1) for (var i = 0, len = callbacks.length; i < len; i++) { callbacks[i].apply(this._ctx, args) } } return this } module.exports = Emitter }); require.register("vue/src/config.js", function(exports, require, module){ var TextParser = require('./text-parser') module.exports = { prefix : 'v', debug : false, silent : false, enterClass : 'v-enter', leaveClass : 'v-leave', interpolate : true } Object.defineProperty(module.exports, 'delimiters', { get: function () { return TextParser.delimiters }, set: function (delimiters) { TextParser.setDelimiters(delimiters) } }) }); require.register("vue/src/utils.js", function(exports, require, module){ var config = require('./config'), toString = ({}).toString, win = window, console = win.console, def = Object.defineProperty, OBJECT = 'object', THIS_RE = /[^\w]this[^\w]/, BRACKET_RE_S = /\['([^']+)'\]/g, BRACKET_RE_D = /\["([^"]+)"\]/g, hasClassList = 'classList' in document.documentElement, ViewModel // late def var defer = win.requestAnimationFrame || win.webkitRequestAnimationFrame || win.setTimeout /** * Normalize keypath with possible brackets into dot notations */ function normalizeKeypath (key) { return key.indexOf('[') < 0 ? key : key.replace(BRACKET_RE_S, '.$1') .replace(BRACKET_RE_D, '.$1') } var utils = module.exports = { /** * Convert a string template to a dom fragment */ toFragment: require('./fragment'), /** * Parse the various types of template options */ parseTemplateOption: require('./template-parser.js'), /** * get a value from an object keypath */ get: function (obj, key) { /* jshint eqeqeq: false */ key = normalizeKeypath(key) if (key.indexOf('.') < 0) { return obj[key] } var path = key.split('.'), d = -1, l = path.length while (++d < l && obj != null) { obj = obj[path[d]] } return obj }, /** * set a value to an object keypath */ set: function (obj, key, val) { /* jshint eqeqeq: false */ key = normalizeKeypath(key) if (key.indexOf('.') < 0) { obj[key] = val return } var path = key.split('.'), d = -1, l = path.length - 1 while (++d < l) { if (obj[path[d]] == null) { obj[path[d]] = {} } obj = obj[path[d]] } obj[path[d]] = val }, /** * return the base segment of a keypath */ baseKey: function (key) { return key.indexOf('.') > 0 ? key.split('.')[0] : key }, /** * Create a prototype-less object * which is a better hash/map */ hash: function () { return Object.create(null) }, /** * get an attribute and remove it. */ attr: function (el, type) { var attr = config.prefix + '-' + type, val = el.getAttribute(attr) if (val !== null) { el.removeAttribute(attr) } return val }, /** * Define an ienumerable property * This avoids it being included in JSON.stringify * or for...in loops. */ defProtected: function (obj, key, val, enumerable, writable) { def(obj, key, { value : val, enumerable : enumerable, writable : writable, configurable : true }) }, /** * A less bullet-proof but more efficient type check * than Object.prototype.toString */ isObject: function (obj) { return typeof obj === OBJECT && obj && !Array.isArray(obj) }, /** * A more accurate but less efficient type check */ isTrueObject: function (obj) { return toString.call(obj) === '[object Object]' }, /** * Most simple bind * enough for the usecase and fast than native bind() */ bind: function (fn, ctx) { return function (arg) { return fn.call(ctx, arg) } }, /** * Make sure null and undefined output empty string */ guard: function (value) { /* jshint eqeqeq: false, eqnull: true */ return value == null ? '' : (typeof value == 'object') ? JSON.stringify(value) : value }, /** * When setting value on the VM, parse possible numbers */ checkNumber: function (value) { return (isNaN(value) || value === null || typeof value === 'boolean') ? value : Number(value) }, /** * simple extend */ extend: function (obj, ext) { for (var key in ext) { if (obj[key] !== ext[key]) { obj[key] = ext[key] } } return obj }, /** * filter an array with duplicates into uniques */ unique: function (arr) { var hash = utils.hash(), i = arr.length, key, res = [] while (i--) { key = arr[i] if (hash[key]) continue hash[key] = 1 res.push(key) } return res }, /** * Convert the object to a ViewModel constructor * if it is not already one */ toConstructor: function (obj) { ViewModel = ViewModel || require('./viewmodel') return utils.isObject(obj) ? ViewModel.extend(obj) : typeof obj === 'function' ? obj : null }, /** * Check if a filter function contains references to `this` * If yes, mark it as a computed filter. */ checkFilter: function (filter) { if (THIS_RE.test(filter.toString())) { filter.computed = true } }, /** * convert certain option values to the desired format. */ processOptions: function (options) { var components = options.components, partials = options.partials, template = options.template, filters = options.filters, key if (components) { for (key in components) { components[key] = utils.toConstructor(components[key]) } } if (partials) { for (key in partials) { partials[key] = utils.parseTemplateOption(partials[key]) } } if (filters) { for (key in filters) { utils.checkFilter(filters[key]) } } if (template) { options.template = utils.parseTemplateOption(template) } }, /** * used to defer batch updates */ nextTick: function (cb) { defer(cb, 0) }, /** * add class for IE9 * uses classList if available */ addClass: function (el, cls) { if (hasClassList) { el.classList.add(cls) } else { var cur = ' ' + el.className + ' ' if (cur.indexOf(' ' + cls + ' ') < 0) { el.className = (cur + cls).trim() } } }, /** * remove class for IE9 */ removeClass: function (el, cls) { if (hasClassList) { el.classList.remove(cls) } else { var cur = ' ' + el.className + ' ', tar = ' ' + cls + ' ' while (cur.indexOf(tar) >= 0) { cur = cur.replace(tar, ' ') } el.className = cur.trim() } }, /** * Convert an object to Array * used in v-repeat and array filters */ objectToArray: function (obj) { var res = [], val, data for (var key in obj) { val = obj[key] data = utils.isObject(val) ? val : { $value: val } data.$key = key res.push(data) } return res } } enableDebug() function enableDebug () { /** * log for debugging */ utils.log = function (msg) { if (config.debug && console) { console.log(msg) } } /** * warnings, traces by default * can be suppressed by `silent` option. */ utils.warn = function (msg) { if (!config.silent && console) { console.warn(msg) if (config.debug && console.trace) { console.trace() } } } } }); require.register("vue/src/fragment.js", function(exports, require, module){ // string -> DOM conversion // wrappers originally from jQuery, scooped from component/domify var map = { legend : [1, '
', '
'], tr : [2, '', '
'], col : [2, '', '
'], _default : [0, '', ''] } map.td = map.th = [3, '', '
'] map.option = map.optgroup = [1, ''] map.thead = map.tbody = map.colgroup = map.caption = map.tfoot = [1, '', '
'] map.text = map.circle = map.ellipse = map.line = map.path = map.polygon = map.polyline = map.rect = [1, '',''] var TAG_RE = /<([\w:]+)/ module.exports = function (templateString) { var frag = document.createDocumentFragment(), m = TAG_RE.exec(templateString) // text only if (!m) { frag.appendChild(document.createTextNode(templateString)) return frag } var tag = m[1], wrap = map[tag] || map._default, depth = wrap[0], prefix = wrap[1], suffix = wrap[2], node = document.createElement('div') node.innerHTML = prefix + templateString.trim() + suffix while (depth--) node = node.lastChild // one element if (node.firstChild === node.lastChild) { frag.appendChild(node.firstChild) return frag } // multiple nodes, return a fragment var child /* jshint boss: true */ while (child = node.firstChild) { if (node.nodeType === 1) { frag.appendChild(child) } } return frag } }); require.register("vue/src/compiler.js", function(exports, require, module){ var Emitter = require('./emitter'), Observer = require('./observer'), config = require('./config'), utils = require('./utils'), Binding = require('./binding'), Directive = require('./directive'), TextParser = require('./text-parser'), DepsParser = require('./deps-parser'), ExpParser = require('./exp-parser'), ViewModel, // cache methods slice = [].slice, extend = utils.extend, hasOwn = ({}).hasOwnProperty, def = Object.defineProperty, // hooks to register hooks = [ 'created', 'ready', 'beforeDestroy', 'afterDestroy', 'attached', 'detached' ], // list of priority directives // that needs to be checked in specific order priorityDirectives = [ 'if', 'repeat', 'view', 'component' ] /** * The DOM compiler * scans a DOM node and compile bindings for a ViewModel */ function Compiler (vm, options) { var compiler = this, key, i // default state compiler.init = true compiler.destroyed = false // process and extend options options = compiler.options = options || {} utils.processOptions(options) // copy compiler options extend(compiler, options.compilerOptions) // repeat indicates this is a v-repeat instance compiler.repeat = compiler.repeat || false // expCache will be shared between v-repeat instances compiler.expCache = compiler.expCache || {} // initialize element var el = compiler.el = compiler.setupElement(options) utils.log('\nnew VM instance: ' + el.tagName + '\n') // set other compiler properties compiler.vm = el.vue_vm = vm compiler.bindings = utils.hash() compiler.dirs = [] compiler.deferred = [] compiler.computed = [] compiler.children = [] compiler.emitter = new Emitter(vm) // VM --------------------------------------------------------------------- // set VM properties vm.$ = {} vm.$el = el vm.$options = options vm.$compiler = compiler vm.$event = null // set parent & root var parentVM = options.parent if (parentVM) { compiler.parent = parentVM.$compiler parentVM.$compiler.children.push(compiler) vm.$parent = parentVM // inherit lazy option if (!('lazy' in options)) { options.lazy = compiler.parent.options.lazy } } vm.$root = getRoot(compiler).vm // DATA ------------------------------------------------------------------- // setup observer // this is necesarry for all hooks and data observation events compiler.setupObserver() // create bindings for computed properties if (options.methods) { for (key in options.methods) { compiler.createBinding(key) } } // create bindings for methods if (options.computed) { for (key in options.computed) { compiler.createBinding(key) } } // initialize data var data = compiler.data = options.data || {}, defaultData = options.defaultData if (defaultData) { for (key in defaultData) { if (!hasOwn.call(data, key)) { data[key] = defaultData[key] } } } // copy paramAttributes var params = options.paramAttributes if (params) { i = params.length while (i--) { data[params[i]] = utils.checkNumber( compiler.eval( el.getAttribute(params[i]) ) ) } } // copy data properties to vm // so user can access them in the created hook extend(vm, data) vm.$data = data // beforeCompile hook compiler.execHook('created') // the user might have swapped the data ... data = compiler.data = vm.$data // user might also set some properties on the vm // in which case we should copy back to $data var vmProp for (key in vm) { vmProp = vm[key] if ( key.charAt(0) !== '$' && data[key] !== vmProp && typeof vmProp !== 'function' ) { data[key] = vmProp } } // now we can observe the data. // this will convert data properties to getter/setters // and emit the first batch of set events, which will // in turn create the corresponding bindings. compiler.observeData(data) // COMPILE ---------------------------------------------------------------- // before compiling, resolve content insertion points if (options.template) { this.resolveContent() } // now parse the DOM and bind directives. // During this stage, we will also create bindings for // encountered keypaths that don't have a binding yet. compiler.compile(el, true) // Any directive that creates child VMs are deferred // so that when they are compiled, all bindings on the // parent VM have been created. i = compiler.deferred.length while (i--) { compiler.bindDirective(compiler.deferred[i]) } compiler.deferred = null // extract dependencies for computed properties. // this will evaluated all collected computed bindings // and collect get events that are emitted. if (this.computed.length) { DepsParser.parse(this.computed) } // done! compiler.init = false // post compile / ready hook compiler.execHook('ready') } var CompilerProto = Compiler.prototype /** * Initialize the VM/Compiler's element. * Fill it in with the template if necessary. */ CompilerProto.setupElement = function (options) { // create the node first var el = typeof options.el === 'string' ? document.querySelector(options.el) : options.el || document.createElement(options.tagName || 'div') var template = options.template, child, replacer, i, attr, attrs if (template) { // collect anything already in there if (el.hasChildNodes()) { this.rawContent = document.createElement('div') /* jshint boss: true */ while (child = el.firstChild) { this.rawContent.appendChild(child) } } // replace option: use the first node in // the template directly if (options.replace && template.firstChild === template.lastChild) { replacer = template.firstChild.cloneNode(true) if (el.parentNode) { el.parentNode.insertBefore(replacer, el) el.parentNode.removeChild(el) } // copy over attributes if (el.hasAttributes()) { i = el.attributes.length while (i--) { attr = el.attributes[i] replacer.setAttribute(attr.name, attr.value) } } // replace el = replacer } else { el.appendChild(template.cloneNode(true)) } } // apply element options if (options.id) el.id = options.id if (options.className) el.className = options.className attrs = options.attributes if (attrs) { for (attr in attrs) { el.setAttribute(attr, attrs[attr]) } } return el } /** * Deal with insertion points * per the Web Components spec */ CompilerProto.resolveContent = function () { var outlets = slice.call(this.el.getElementsByTagName('content')), raw = this.rawContent, outlet, select, i, j, main i = outlets.length if (i) { // first pass, collect corresponding content // for each outlet. while (i--) { outlet = outlets[i] if (raw) { select = outlet.getAttribute('select') if (select) { // select content outlet.content = slice.call(raw.querySelectorAll(select)) } else { // default content main = outlet } } else { // fallback content outlet.content = slice.call(outlet.childNodes) } } // second pass, actually insert the contents for (i = 0, j = outlets.length; i < j; i++) { outlet = outlets[i] if (outlet === main) continue insert(outlet, outlet.content) } // finally insert the main content if (raw && main) { insert(main, slice.call(raw.childNodes)) } } function insert (outlet, contents) { var parent = outlet.parentNode, i = 0, j = contents.length for (; i < j; i++) { parent.insertBefore(contents[i], outlet) } parent.removeChild(outlet) } this.rawContent = null } /** * Setup observer. * The observer listens for get/set/mutate events on all VM * values/objects and trigger corresponding binding updates. * It also listens for lifecycle hooks. */ CompilerProto.setupObserver = function () { var compiler = this, bindings = compiler.bindings, options = compiler.options, observer = compiler.observer = new Emitter(compiler.vm) // a hash to hold event proxies for each root level key // so they can be referenced and removed later observer.proxies = {} // add own listeners which trigger binding updates observer .on('get', onGet) .on('set', onSet) .on('mutate', onSet) // register hooks var i = hooks.length, j, hook, fns while (i--) { hook = hooks[i] fns = options[hook] if (Array.isArray(fns)) { j = fns.length // since hooks were merged with child at head, // we loop reversely. while (j--) { registerHook(hook, fns[j]) } } else if (fns) { registerHook(hook, fns) } } // broadcast attached/detached hooks observer .on('hook:attached', function () { broadcast(1) }) .on('hook:detached', function () { broadcast(0) }) function onGet (key) { check(key) DepsParser.catcher.emit('get', bindings[key]) } function onSet (key, val, mutation) { observer.emit('change:' + key, val, mutation) check(key) bindings[key].update(val) } function registerHook (hook, fn) { observer.on('hook:' + hook, function () { fn.call(compiler.vm) }) } function broadcast (event) { var children = compiler.children if (children) { var child, i = children.length while (i--) { child = children[i] if (child.el.parentNode) { event = 'hook:' + (event ? 'attached' : 'detached') child.observer.emit(event) child.emitter.emit(event) } } } } function check (key) { if (!bindings[key]) { compiler.createBinding(key) } } } CompilerProto.observeData = function (data) { var compiler = this, observer = compiler.observer // recursively observe nested properties Observer.observe(data, '', observer) // also create binding for top level $data // so it can be used in templates too var $dataBinding = compiler.bindings['$data'] = new Binding(compiler, '$data') $dataBinding.update(data) // allow $data to be swapped def(compiler.vm, '$data', { get: function () { compiler.observer.emit('get', '$data') return compiler.data }, set: function (newData) { var oldData = compiler.data Observer.unobserve(oldData, '', observer) compiler.data = newData Observer.copyPaths(newData, oldData) Observer.observe(newData, '', observer) update() } }) // emit $data change on all changes observer .on('set', onSet) .on('mutate', onSet) function onSet (key) { if (key !== '$data') update() } function update () { $dataBinding.update(compiler.data) observer.emit('change:$data', compiler.data) } } /** * Compile a DOM node (recursive) */ CompilerProto.compile = function (node, root) { var nodeType = node.nodeType if (nodeType === 1 && node.tagName !== 'SCRIPT') { // a normal node this.compileElement(node, root) } else if (nodeType === 3 && config.interpolate) { this.compileTextNode(node) } } /** * Check for a priority directive * If it is present and valid, return true to skip the rest */ CompilerProto.checkPriorityDir = function (dirname, node, root) { var expression, directive, Ctor if ( dirname === 'component' && root !== true && (Ctor = this.resolveComponent(node, undefined, true)) ) { directive = this.parseDirective(dirname, '', node) directive.Ctor = Ctor } else { expression = utils.attr(node, dirname) directive = expression && this.parseDirective(dirname, expression, node) } if (directive) { if (root === true) { utils.warn( 'Directive v-' + dirname + ' cannot be used on an already instantiated ' + 'VM\'s root node. Use it from the parent\'s template instead.' ) return } this.deferred.push(directive) return true } } /** * Compile normal directives on a node */ CompilerProto.compileElement = function (node, root) { // textarea is pretty annoying // because its value creates childNodes which // we don't want to compile. if (node.tagName === 'TEXTAREA' && node.value) { node.value = this.eval(node.value) } // only compile if this element has attributes // or its tagName contains a hyphen (which means it could // potentially be a custom element) if (node.hasAttributes() || node.tagName.indexOf('-') > -1) { // skip anything with v-pre if (utils.attr(node, 'pre') !== null) { return } var i, l, j, k // check priority directives. // if any of them are present, it will take over the node with a childVM // so we can skip the rest for (i = 0, l = priorityDirectives.length; i < l; i++) { if (this.checkPriorityDir(priorityDirectives[i], node, root)) { return } } // check transition & animation properties node.vue_trans = utils.attr(node, 'transition') node.vue_anim = utils.attr(node, 'animation') node.vue_effect = this.eval(utils.attr(node, 'effect')) var prefix = config.prefix + '-', params = this.options.paramAttributes, attr, attrname, isDirective, exp, directives, directive, dirname // v-with has special priority among the rest // it needs to pull in the value from the parent before // computed properties are evaluated, because at this stage // the computed properties have not set up their dependencies yet. if (root) { var withExp = utils.attr(node, 'with') if (withExp) { directives = this.parseDirective('with', withExp, node, true) for (j = 0, k = directives.length; j < k; j++) { this.bindDirective(directives[j], this.parent) } } } var attrs = slice.call(node.attributes) for (i = 0, l = attrs.length; i < l; i++) { attr = attrs[i] attrname = attr.name isDirective = false if (attrname.indexOf(prefix) === 0) { // a directive - split, parse and bind it. isDirective = true dirname = attrname.slice(prefix.length) // build with multiple: true directives = this.parseDirective(dirname, attr.value, node, true) // loop through clauses (separated by ",") // inside each attribute for (j = 0, k = directives.length; j < k; j++) { this.bindDirective(directives[j]) } } else if (config.interpolate) { // non directive attribute, check interpolation tags exp = TextParser.parseAttr(attr.value) if (exp) { directive = this.parseDirective('attr', exp, node) directive.arg = attrname if (params && params.indexOf(attrname) > -1) { // a param attribute... we should use the parent binding // to avoid circular updates like size={{size}} this.bindDirective(directive, this.parent) } else { this.bindDirective(directive) } } } if (isDirective && dirname !== 'cloak') { node.removeAttribute(attrname) } } } // recursively compile childNodes if (node.hasChildNodes()) { slice.call(node.childNodes).forEach(this.compile, this) } } /** * Compile a text node */ CompilerProto.compileTextNode = function (node) { var tokens = TextParser.parse(node.nodeValue) if (!tokens) return var el, token, directive for (var i = 0, l = tokens.length; i < l; i++) { token = tokens[i] directive = null if (token.key) { // a binding if (token.key.charAt(0) === '>') { // a partial el = document.createComment('ref') directive = this.parseDirective('partial', token.key.slice(1), el) } else { if (!token.html) { // text binding el = document.createTextNode('') directive = this.parseDirective('text', token.key, el) } else { // html binding el = document.createComment(config.prefix + '-html') directive = this.parseDirective('html', token.key, el) } } } else { // a plain string el = document.createTextNode(token) } // insert node node.parentNode.insertBefore(el, node) // bind directive this.bindDirective(directive) } node.parentNode.removeChild(node) } /** * Parse a directive name/value pair into one or more * directive instances */ CompilerProto.parseDirective = function (name, value, el, multiple) { var compiler = this, definition = compiler.getOption('directives', name) if (definition) { // parse into AST-like objects var asts = Directive.parse(value) return multiple ? asts.map(build) : build(asts[0]) } function build (ast) { return new Directive(name, ast, definition, compiler, el) } } /** * Add a directive instance to the correct binding & viewmodel */ CompilerProto.bindDirective = function (directive, bindingOwner) { if (!directive) return // keep track of it so we can unbind() later this.dirs.push(directive) // for empty or literal directives, simply call its bind() // and we're done. if (directive.isEmpty || directive.isLiteral) { if (directive.bind) directive.bind() return } // otherwise, we got more work to do... var binding, compiler = bindingOwner || this, key = directive.key if (directive.isExp) { // expression bindings are always created on current compiler binding = compiler.createBinding(key, directive) } else { // recursively locate which compiler owns the binding while (compiler) { if (compiler.hasKey(key)) { break } else { compiler = compiler.parent } } compiler = compiler || this binding = compiler.bindings[key] || compiler.createBinding(key) } binding.dirs.push(directive) directive.binding = binding var value = binding.val() // invoke bind hook if exists if (directive.bind) { directive.bind(value) } // set initial value directive.$update(value, true) } /** * Create binding and attach getter/setter for a key to the viewmodel object */ CompilerProto.createBinding = function (key, directive) { utils.log(' created binding: ' + key) var compiler = this, methods = compiler.options.methods, isExp = directive && directive.isExp, isFn = (directive && directive.isFn) || (methods && methods[key]), bindings = compiler.bindings, computed = compiler.options.computed, binding = new Binding(compiler, key, isExp, isFn) if (isExp) { // expression bindings are anonymous compiler.defineExp(key, binding, directive) } else if (isFn) { bindings[key] = binding compiler.defineVmProp(key, binding, methods[key]) } else { bindings[key] = binding if (binding.root) { // this is a root level binding. we need to define getter/setters for it. if (computed && computed[key]) { // computed property compiler.defineComputed(key, binding, computed[key]) } else if (key.charAt(0) !== '$') { // normal property compiler.defineDataProp(key, binding) } else { // properties that start with $ are meta properties // they should be kept on the vm but not in the data object. compiler.defineVmProp(key, binding, compiler.data[key]) delete compiler.data[key] } } else if (computed && computed[utils.baseKey(key)]) { // nested path on computed property compiler.defineExp(key, binding) } else { // ensure path in data so that computed properties that // access the path don't throw an error and can collect // dependencies Observer.ensurePath(compiler.data, key) var parentKey = key.slice(0, key.lastIndexOf('.')) if (!bindings[parentKey]) { // this is a nested value binding, but the binding for its parent // has not been created yet. We better create that one too. compiler.createBinding(parentKey) } } } return binding } /** * Define the getter/setter to proxy a root-level * data property on the VM */ CompilerProto.defineDataProp = function (key, binding) { var compiler = this, data = compiler.data, ob = data.__emitter__ // make sure the key is present in data // so it can be observed if (!(hasOwn.call(data, key))) { data[key] = undefined } // if the data object is already observed, but the key // is not observed, we need to add it to the observed keys. if (ob && !(hasOwn.call(ob.values, key))) { Observer.convertKey(data, key) } binding.value = data[key] def(compiler.vm, key, { get: function () { return compiler.data[key] }, set: function (val) { compiler.data[key] = val } }) } /** * Define a vm property, e.g. $index, $key, or mixin methods * which are bindable but only accessible on the VM, * not in the data. */ CompilerProto.defineVmProp = function (key, binding, value) { var ob = this.observer binding.value = value def(this.vm, key, { get: function () { if (Observer.shouldGet) ob.emit('get', key) return binding.value }, set: function (val) { ob.emit('set', key, val) } }) } /** * Define an expression binding, which is essentially * an anonymous computed property */ CompilerProto.defineExp = function (key, binding, directive) { var computedKey = directive && directive.computedKey, exp = computedKey ? directive.expression : key, getter = this.expCache[exp] if (!getter) { getter = this.expCache[exp] = ExpParser.parse(computedKey || key, this) } if (getter) { this.markComputed(binding, getter) } } /** * Define a computed property on the VM */ CompilerProto.defineComputed = function (key, binding, value) { this.markComputed(binding, value) def(this.vm, key, { get: binding.value.$get, set: binding.value.$set }) } /** * Process a computed property binding * so its getter/setter are bound to proper context */ CompilerProto.markComputed = function (binding, value) { binding.isComputed = true // bind the accessors to the vm if (binding.isFn) { binding.value = value } else { if (typeof value === 'function') { value = { $get: value } } binding.value = { $get: utils.bind(value.$get, this.vm), $set: value.$set ? utils.bind(value.$set, this.vm) : undefined } } // keep track for dep parsing later this.computed.push(binding) } /** * Retrive an option from the compiler */ CompilerProto.getOption = function (type, id, silent) { var opts = this.options, parent = this.parent, globalAssets = config.globalAssets, res = (opts[type] && opts[type][id]) || ( parent ? parent.getOption(type, id, silent) : globalAssets[type] && globalAssets[type][id] ) if (!res && !silent && typeof id === 'string') { utils.warn('Unknown ' + type.slice(0, -1) + ': ' + id) } return res } /** * Emit lifecycle events to trigger hooks */ CompilerProto.execHook = function (event) { event = 'hook:' + event this.observer.emit(event) this.emitter.emit(event) } /** * Check if a compiler's data contains a keypath */ CompilerProto.hasKey = function (key) { var baseKey = utils.baseKey(key) return hasOwn.call(this.data, baseKey) || hasOwn.call(this.vm, baseKey) } /** * Do a one-time eval of a string that potentially * includes bindings. It accepts additional raw data * because we need to dynamically resolve v-component * before a childVM is even compiled... */ CompilerProto.eval = function (exp, data) { var parsed = TextParser.parseAttr(exp) return parsed ? ExpParser.eval(parsed, this, data) : exp } /** * Resolve a Component constructor for an element * with the data to be used */ CompilerProto.resolveComponent = function (node, data, test) { // late require to avoid circular deps ViewModel = ViewModel || require('./viewmodel') var exp = utils.attr(node, 'component'), tagName = node.tagName, id = this.eval(exp, data), tagId = (tagName.indexOf('-') > 0 && tagName.toLowerCase()), Ctor = this.getOption('components', id || tagId, true) if (id && !Ctor) { utils.warn('Unknown component: ' + id) } return test ? exp === '' ? ViewModel : Ctor : Ctor || ViewModel } /** * Unbind and remove element */ CompilerProto.destroy = function (noRemove) { // avoid being called more than once // this is irreversible! if (this.destroyed) return var compiler = this, i, j, key, dir, dirs, binding, vm = compiler.vm, el = compiler.el, directives = compiler.dirs, computed = compiler.computed, bindings = compiler.bindings, children = compiler.children, parent = compiler.parent compiler.execHook('beforeDestroy') // unobserve data Observer.unobserve(compiler.data, '', compiler.observer) // destroy all children // do not remove their elements since the parent // may have transitions and the children may not i = children.length while (i--) { children[i].destroy(true) } // unbind all direcitves i = directives.length while (i--) { dir = directives[i] // if this directive is an instance of an external binding // e.g. a directive that refers to a variable on the parent VM // we need to remove it from that binding's directives // * empty and literal bindings do not have binding. if (dir.binding && dir.binding.compiler !== compiler) { dirs = dir.binding.dirs if (dirs) { j = dirs.indexOf(dir) if (j > -1) dirs.splice(j, 1) } } dir.$unbind() } // unbind all computed, anonymous bindings i = computed.length while (i--) { computed[i].unbind() } // unbind all keypath bindings for (key in bindings) { binding = bindings[key] if (binding) { binding.unbind() } } // remove self from parent if (parent) { j = parent.children.indexOf(compiler) if (j > -1) parent.children.splice(j, 1) } // finally remove dom element if (!noRemove) { if (el === document.body) { el.innerHTML = '' } else { vm.$remove() } } el.vue_vm = null compiler.destroyed = true // emit destroy hook compiler.execHook('afterDestroy') // finally, unregister all listeners compiler.observer.off() compiler.emitter.off() } // Helpers -------------------------------------------------------------------- /** * shorthand for getting root compiler */ function getRoot (compiler) { while (compiler.parent) { compiler = compiler.parent } return compiler } module.exports = Compiler }); require.register("vue/src/viewmodel.js", function(exports, require, module){ var Compiler = require('./compiler'), utils = require('./utils'), transition = require('./transition'), Batcher = require('./batcher'), slice = [].slice, def = utils.defProtected, nextTick = utils.nextTick, // batch $watch callbacks watcherBatcher = new Batcher(), watcherId = 1 /** * ViewModel exposed to the user that holds data, * computed properties, event handlers * and a few reserved methods */ function ViewModel (options) { // compile if options passed, if false return. options are passed directly to compiler if (options === false) return new Compiler(this, options) } // All VM prototype methods are inenumerable // so it can be stringified/looped through as raw data var VMProto = ViewModel.prototype /** * init allows config compilation after instantiation: * var a = new Vue(false) * a.init(config) */ def(VMProto, '$init', function (options) { new Compiler(this, options) }) /** * Convenience function to get a value from * a keypath */ def(VMProto, '$get', function (key) { var val = utils.get(this, key) return val === undefined && this.$parent ? this.$parent.$get(key) : val }) /** * Convenience function to set an actual nested value * from a flat key string. Used in directives. */ def(VMProto, '$set', function (key, value) { utils.set(this, key, value) }) /** * watch a key on the viewmodel for changes * fire callback with new value */ def(VMProto, '$watch', function (key, callback) { // save a unique id for each watcher var id = watcherId++, self = this function on () { var args = slice.call(arguments) watcherBatcher.push({ id: id, override: true, execute: function () { callback.apply(self, args) } }) } callback._fn = on self.$compiler.observer.on('change:' + key, on) }) /** * unwatch a key */ def(VMProto, '$unwatch', function (key, callback) { // workaround here // since the emitter module checks callback existence // by checking the length of arguments var args = ['change:' + key], ob = this.$compiler.observer if (callback) args.push(callback._fn) ob.off.apply(ob, args) }) /** * unbind everything, remove everything */ def(VMProto, '$destroy', function (noRemove) { this.$compiler.destroy(noRemove) }) /** * broadcast an event to all child VMs recursively. */ def(VMProto, '$broadcast', function () { var children = this.$compiler.children, i = children.length, child while (i--) { child = children[i] child.emitter.applyEmit.apply(child.emitter, arguments) child.vm.$broadcast.apply(child.vm, arguments) } }) /** * emit an event that propagates all the way up to parent VMs. */ def(VMProto, '$dispatch', function () { var compiler = this.$compiler, emitter = compiler.emitter, parent = compiler.parent emitter.applyEmit.apply(emitter, arguments) if (parent) { parent.vm.$dispatch.apply(parent.vm, arguments) } }) /** * delegate on/off/once to the compiler's emitter */ ;['emit', 'on', 'off', 'once'].forEach(function (method) { // internal emit has fixed number of arguments. // exposed emit uses the external version // with fn.apply. var realMethod = method === 'emit' ? 'applyEmit' : method def(VMProto, '$' + method, function () { var emitter = this.$compiler.emitter emitter[realMethod].apply(emitter, arguments) }) }) // DOM convenience methods def(VMProto, '$appendTo', function (target, cb) { target = query(target) var el = this.$el transition(el, 1, function () { target.appendChild(el) if (cb) nextTick(cb) }, this.$compiler) }) def(VMProto, '$remove', function (cb) { var el = this.$el transition(el, -1, function () { if (el.parentNode) { el.parentNode.removeChild(el) } if (cb) nextTick(cb) }, this.$compiler) }) def(VMProto, '$before', function (target, cb) { target = query(target) var el = this.$el transition(el, 1, function () { target.parentNode.insertBefore(el, target) if (cb) nextTick(cb) }, this.$compiler) }) def(VMProto, '$after', function (target, cb) { target = query(target) var el = this.$el transition(el, 1, function () { if (target.nextSibling) { target.parentNode.insertBefore(el, target.nextSibling) } else { target.parentNode.appendChild(el) } if (cb) nextTick(cb) }, this.$compiler) }) function query (el) { return typeof el === 'string' ? document.querySelector(el) : el } module.exports = ViewModel }); require.register("vue/src/binding.js", function(exports, require, module){ var Batcher = require('./batcher'), bindingBatcher = new Batcher(), bindingId = 1 /** * Binding class. * * each property on the viewmodel has one corresponding Binding object * which has multiple directive instances on the DOM * and multiple computed property dependents */ function Binding (compiler, key, isExp, isFn) { this.id = bindingId++ this.value = undefined this.isExp = !!isExp this.isFn = isFn this.root = !this.isExp && key.indexOf('.') === -1 this.compiler = compiler this.key = key this.dirs = [] this.subs = [] this.deps = [] this.unbound = false } var BindingProto = Binding.prototype /** * Update value and queue instance updates. */ BindingProto.update = function (value) { if (!this.isComputed || this.isFn) { this.value = value } if (this.dirs.length || this.subs.length) { var self = this bindingBatcher.push({ id: this.id, execute: function () { if (!self.unbound) { self._update() } } }) } } /** * Actually update the directives. */ BindingProto._update = function () { var i = this.dirs.length, value = this.val() while (i--) { this.dirs[i].$update(value) } this.pub() } /** * Return the valuated value regardless * of whether it is computed or not */ BindingProto.val = function () { return this.isComputed && !this.isFn ? this.value.$get() : this.value } /** * Notify computed properties that depend on this binding * to update themselves */ BindingProto.pub = function () { var i = this.subs.length while (i--) { this.subs[i].update() } } /** * Unbind the binding, remove itself from all of its dependencies */ BindingProto.unbind = function () { // Indicate this has been unbound. // It's possible this binding will be in // the batcher's flush queue when its owner // compiler has already been destroyed. this.unbound = true var i = this.dirs.length while (i--) { this.dirs[i].$unbind() } i = this.deps.length var subs while (i--) { subs = this.deps[i].subs var j = subs.indexOf(this) if (j > -1) subs.splice(j, 1) } } module.exports = Binding }); require.register("vue/src/observer.js", function(exports, require, module){ /* jshint proto:true */ var Emitter = require('./emitter'), utils = require('./utils'), // cache methods def = utils.defProtected, isObject = utils.isObject, isArray = Array.isArray, hasOwn = ({}).hasOwnProperty, oDef = Object.defineProperty, slice = [].slice, // fix for IE + __proto__ problem // define methods as inenumerable if __proto__ is present, // otherwise enumerable so we can loop through and manually // attach to array instances hasProto = ({}).__proto__ // Array Mutation Handlers & Augmentations ------------------------------------ // The proxy prototype to replace the __proto__ of // an observed array var ArrayProxy = Object.create(Array.prototype) // intercept mutation methods ;[ 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse' ].forEach(watchMutation) // Augment the ArrayProxy with convenience methods def(ArrayProxy, '$set', function (index, data) { return this.splice(index, 1, data)[0] }, !hasProto) def(ArrayProxy, '$remove', function (index) { if (typeof index !== 'number') { index = this.indexOf(index) } if (index > -1) { return this.splice(index, 1)[0] } }, !hasProto) /** * Intercep a mutation event so we can emit the mutation info. * we also analyze what elements are added/removed and link/unlink * them with the parent Array. */ function watchMutation (method) { def(ArrayProxy, method, function () { var args = slice.call(arguments), result = Array.prototype[method].apply(this, args), inserted, removed // determine new / removed elements if (method === 'push' || method === 'unshift') { inserted = args } else if (method === 'pop' || method === 'shift') { removed = [result] } else if (method === 'splice') { inserted = args.slice(2) removed = result } // link & unlink linkArrayElements(this, inserted) unlinkArrayElements(this, removed) // emit the mutation event this.__emitter__.emit('mutate', '', this, { method : method, args : args, result : result, inserted : inserted, removed : removed }) return result }, !hasProto) } /** * Link new elements to an Array, so when they change * and emit events, the owner Array can be notified. */ function linkArrayElements (arr, items) { if (items) { var i = items.length, item, owners while (i--) { item = items[i] if (isWatchable(item)) { // if object is not converted for observing // convert it... if (!item.__emitter__) { convert(item) watch(item) } owners = item.__emitter__.owners if (owners.indexOf(arr) < 0) { owners.push(arr) } } } } } /** * Unlink removed elements from the ex-owner Array. */ function unlinkArrayElements (arr, items) { if (items) { var i = items.length, item while (i--) { item = items[i] if (item && item.__emitter__) { var owners = item.__emitter__.owners if (owners) owners.splice(owners.indexOf(arr)) } } } } // Object add/delete key augmentation ----------------------------------------- var ObjProxy = Object.create(Object.prototype) def(ObjProxy, '$add', function (key, val) { if (hasOwn.call(this, key)) return this[key] = val convertKey(this, key, true) }, !hasProto) def(ObjProxy, '$delete', function (key) { if (!(hasOwn.call(this, key))) return // trigger set events this[key] = undefined delete this[key] this.__emitter__.emit('delete', key) }, !hasProto) // Watch Helpers -------------------------------------------------------------- /** * Check if a value is watchable */ function isWatchable (obj) { return typeof obj === 'object' && obj && !obj.$compiler } /** * Convert an Object/Array to give it a change emitter. */ function convert (obj) { if (obj.__emitter__) return true var emitter = new Emitter() def(obj, '__emitter__', emitter) emitter .on('set', function (key, val, propagate) { if (propagate) propagateChange(obj) }) .on('mutate', function () { propagateChange(obj) }) emitter.values = utils.hash() emitter.owners = [] return false } /** * Propagate an array element's change to its owner arrays */ function propagateChange (obj) { var owners = obj.__emitter__.owners, i = owners.length while (i--) { owners[i].__emitter__.emit('set', '', '', true) } } /** * Watch target based on its type */ function watch (obj) { if (isArray(obj)) { watchArray(obj) } else { watchObject(obj) } } /** * Augment target objects with modified * methods */ function augment (target, src) { if (hasProto) { target.__proto__ = src } else { for (var key in src) { def(target, key, src[key]) } } } /** * Watch an Object, recursive. */ function watchObject (obj) { augment(obj, ObjProxy) for (var key in obj) { convertKey(obj, key) } } /** * Watch an Array, overload mutation methods * and add augmentations by intercepting the prototype chain */ function watchArray (arr) { augment(arr, ArrayProxy) linkArrayElements(arr, arr) } /** * Define accessors for a property on an Object * so it emits get/set events. * Then watch the value itself. */ function convertKey (obj, key, propagate) { var keyPrefix = key.charAt(0) if (keyPrefix === '$' || keyPrefix === '_') { return } // emit set on bind // this means when an object is observed it will emit // a first batch of set events. var emitter = obj.__emitter__, values = emitter.values init(obj[key], propagate) oDef(obj, key, { enumerable: true, configurable: true, get: function () { var value = values[key] // only emit get on tip values if (pub.shouldGet) { emitter.emit('get', key) } return value }, set: function (newVal) { var oldVal = values[key] unobserve(oldVal, key, emitter) copyPaths(newVal, oldVal) // an immediate property should notify its parent // to emit set for itself too init(newVal, true) } }) function init (val, propagate) { values[key] = val emitter.emit('set', key, val, propagate) if (isArray(val)) { emitter.emit('set', key + '.length', val.length, propagate) } observe(val, key, emitter) } } /** * When a value that is already converted is * observed again by another observer, we can skip * the watch conversion and simply emit set event for * all of its properties. */ function emitSet (obj) { var emitter = obj && obj.__emitter__ if (!emitter) return if (isArray(obj)) { emitter.emit('set', 'length', obj.length) } else { var key, val for (key in obj) { val = obj[key] emitter.emit('set', key, val) emitSet(val) } } } /** * Make sure all the paths in an old object exists * in a new object. * So when an object changes, all missing keys will * emit a set event with undefined value. */ function copyPaths (newObj, oldObj) { if (!isObject(newObj) || !isObject(oldObj)) { return } var path, oldVal, newVal for (path in oldObj) { if (!(hasOwn.call(newObj, path))) { oldVal = oldObj[path] if (isArray(oldVal)) { newObj[path] = [] } else if (isObject(oldVal)) { newVal = newObj[path] = {} copyPaths(newVal, oldVal) } else { newObj[path] = undefined } } } } /** * walk along a path and make sure it can be accessed * and enumerated in that object */ function ensurePath (obj, key) { var path = key.split('.'), sec for (var i = 0, d = path.length - 1; i < d; i++) { sec = path[i] if (!obj[sec]) { obj[sec] = {} if (obj.__emitter__) convertKey(obj, sec) } obj = obj[sec] } if (isObject(obj)) { sec = path[i] if (!(hasOwn.call(obj, sec))) { obj[sec] = undefined if (obj.__emitter__) convertKey(obj, sec) } } } // Main API Methods ----------------------------------------------------------- /** * Observe an object with a given path, * and proxy get/set/mutate events to the provided observer. */ function observe (obj, rawPath, observer) { if (!isWatchable(obj)) return var path = rawPath ? rawPath + '.' : '', alreadyConverted = convert(obj), emitter = obj.__emitter__ // setup proxy listeners on the parent observer. // we need to keep reference to them so that they // can be removed when the object is un-observed. observer.proxies = observer.proxies || {} var proxies = observer.proxies[path] = { get: function (key) { observer.emit('get', path + key) }, set: function (key, val, propagate) { if (key) observer.emit('set', path + key, val) // also notify observer that the object itself changed // but only do so when it's a immediate property. this // avoids duplicate event firing. if (rawPath && propagate) { observer.emit('set', rawPath, obj, true) } }, mutate: function (key, val, mutation) { // if the Array is a root value // the key will be null var fixedPath = key ? path + key : rawPath observer.emit('mutate', fixedPath, val, mutation) // also emit set for Array's length when it mutates var m = mutation.method if (m !== 'sort' && m !== 'reverse') { observer.emit('set', fixedPath + '.length', val.length) } } } // attach the listeners to the child observer. // now all the events will propagate upwards. emitter .on('get', proxies.get) .on('set', proxies.set) .on('mutate', proxies.mutate) if (alreadyConverted) { // for objects that have already been converted, // emit set events for everything inside emitSet(obj) } else { watch(obj) } } /** * Cancel observation, turn off the listeners. */ function unobserve (obj, path, observer) { if (!obj || !obj.__emitter__) return path = path ? path + '.' : '' var proxies = observer.proxies[path] if (!proxies) return // turn off listeners obj.__emitter__ .off('get', proxies.get) .off('set', proxies.set) .off('mutate', proxies.mutate) // remove reference observer.proxies[path] = null } // Expose API ----------------------------------------------------------------- var pub = module.exports = { // whether to emit get events // only enabled during dependency parsing shouldGet : false, observe : observe, unobserve : unobserve, ensurePath : ensurePath, copyPaths : copyPaths, watch : watch, convert : convert, convertKey : convertKey } }); require.register("vue/src/directive.js", function(exports, require, module){ var dirId = 1, ARG_RE = /^[\w\$-]+$/, FILTER_TOKEN_RE = /[^\s'"]+|'[^']+'|"[^"]+"/g, NESTING_RE = /^\$(parent|root)\./, SINGLE_VAR_RE = /^[\w\.$]+$/, QUOTE_RE = /"/g, TextParser = require('./text-parser') /** * Directive class * represents a single directive instance in the DOM */ function Directive (name, ast, definition, compiler, el) { this.id = dirId++ this.name = name this.compiler = compiler this.vm = compiler.vm this.el = el this.computeFilters = false this.key = ast.key this.arg = ast.arg this.expression = ast.expression var isEmpty = this.expression === '' // mix in properties from the directive definition if (typeof definition === 'function') { this[isEmpty ? 'bind' : 'update'] = definition } else { for (var prop in definition) { this[prop] = definition[prop] } } // empty expression, we're done. if (isEmpty || this.isEmpty) { this.isEmpty = true return } if (TextParser.Regex.test(this.key)) { this.key = compiler.eval(this.key) if (this.isLiteral) { this.expression = this.key } } var filters = ast.filters, filter, fn, i, l, computed if (filters) { this.filters = [] for (i = 0, l = filters.length; i < l; i++) { filter = filters[i] fn = this.compiler.getOption('filters', filter.name) if (fn) { filter.apply = fn this.filters.push(filter) if (fn.computed) { computed = true } } } } if (!this.filters || !this.filters.length) { this.filters = null } if (computed) { this.computedKey = Directive.inlineFilters(this.key, this.filters) this.filters = null } this.isExp = computed || !SINGLE_VAR_RE.test(this.key) || NESTING_RE.test(this.key) } var DirProto = Directive.prototype /** * called when a new value is set * for computed properties, this will only be called once * during initialization. */ DirProto.$update = function (value, init) { if (this.$lock) return if (init || value !== this.value || (value && typeof value === 'object')) { this.value = value if (this.update) { this.update( this.filters && !this.computeFilters ? this.$applyFilters(value) : value, init ) } } } /** * pipe the value through filters */ DirProto.$applyFilters = function (value) { var filtered = value, filter for (var i = 0, l = this.filters.length; i < l; i++) { filter = this.filters[i] filtered = filter.apply.apply(this.vm, [filtered].concat(filter.args)) } return filtered } /** * Unbind diretive */ DirProto.$unbind = function () { // this can be called before the el is even assigned... if (!this.el || !this.vm) return if (this.unbind) this.unbind() this.vm = this.el = this.binding = this.compiler = null } // Exposed static methods ----------------------------------------------------- /** * Parse a directive string into an Array of * AST-like objects representing directives */ Directive.parse = function (str) { var inSingle = false, inDouble = false, curly = 0, square = 0, paren = 0, begin = 0, argIndex = 0, dirs = [], dir = {}, lastFilterIndex = 0, arg for (var c, i = 0, l = str.length; i < l; i++) { c = str.charAt(i) if (inSingle) { // check single quote if (c === "'") inSingle = !inSingle } else if (inDouble) { // check double quote if (c === '"') inDouble = !inDouble } else if (c === ',' && !paren && !curly && !square) { // reached the end of a directive pushDir() // reset & skip the comma dir = {} begin = argIndex = lastFilterIndex = i + 1 } else if (c === ':' && !dir.key && !dir.arg) { // argument arg = str.slice(begin, i).trim() if (ARG_RE.test(arg)) { argIndex = i + 1 dir.arg = arg } } else if (c === '|' && str.charAt(i + 1) !== '|' && str.charAt(i - 1) !== '|') { if (dir.key === undefined) { // first filter, end of key lastFilterIndex = i + 1 dir.key = str.slice(argIndex, i).trim() } else { // already has filter pushFilter() } } else if (c === '"') { inDouble = true } else if (c === "'") { inSingle = true } else if (c === '(') { paren++ } else if (c === ')') { paren-- } else if (c === '[') { square++ } else if (c === ']') { square-- } else if (c === '{') { curly++ } else if (c === '}') { curly-- } } if (i === 0 || begin !== i) { pushDir() } function pushDir () { dir.expression = str.slice(begin, i).trim() if (dir.key === undefined) { dir.key = str.slice(argIndex, i).trim() } else if (lastFilterIndex !== begin) { pushFilter() } if (i === 0 || dir.key) { dirs.push(dir) } } function pushFilter () { var exp = str.slice(lastFilterIndex, i).trim(), filter if (exp) { filter = {} var tokens = exp.match(FILTER_TOKEN_RE) filter.name = tokens[0] filter.args = tokens.length > 1 ? tokens.slice(1) : null } if (filter) { (dir.filters = dir.filters || []).push(filter) } lastFilterIndex = i + 1 } return dirs } /** * Inline computed filters so they become part * of the expression */ Directive.inlineFilters = function (key, filters) { var args, filter for (var i = 0, l = filters.length; i < l; i++) { filter = filters[i] args = filter.args ? ',"' + filter.args.map(escapeQuote).join('","') + '"' : '' key = 'this.$compiler.getOption("filters", "' + filter.name + '").call(this,' + key + args + ')' } return key } /** * Convert double quotes to single quotes * so they don't mess up the generated function body */ function escapeQuote (v) { return v.indexOf('"') > -1 ? v.replace(QUOTE_RE, '\'') : v } module.exports = Directive }); require.register("vue/src/exp-parser.js", function(exports, require, module){ var utils = require('./utils'), STR_SAVE_RE = /"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/g, STR_RESTORE_RE = /"(\d+)"/g, NEWLINE_RE = /\n/g, CTOR_RE = new RegExp('constructor'.split('').join('[\'"+, ]*')), UNICODE_RE = /\\u\d\d\d\d/ // Variable extraction scooped from https://github.com/RubyLouvre/avalon var KEYWORDS = // keywords 'break,case,catch,continue,debugger,default,delete,do,else,false' + ',finally,for,function,if,in,instanceof,new,null,return,switch,this' + ',throw,true,try,typeof,var,void,while,with,undefined' + // reserved ',abstract,boolean,byte,char,class,const,double,enum,export,extends' + ',final,float,goto,implements,import,int,interface,long,native' + ',package,private,protected,public,short,static,super,synchronized' + ',throws,transient,volatile' + // ECMA 5 - use strict ',arguments,let,yield' + // allow using Math in expressions ',Math', KEYWORDS_RE = new RegExp(["\\b" + KEYWORDS.replace(/,/g, '\\b|\\b') + "\\b"].join('|'), 'g'), REMOVE_RE = /\/\*(?:.|\n)*?\*\/|\/\/[^\n]*\n|\/\/[^\n]*$|'[^']*'|"[^"]*"|[\s\t\n]*\.[\s\t\n]*[$\w\.]+|[\{,]\s*[\w\$_]+\s*:/g, SPLIT_RE = /[^\w$]+/g, NUMBER_RE = /\b\d[^,]*/g, BOUNDARY_RE = /^,+|,+$/g /** * Strip top level variable names from a snippet of JS expression */ function getVariables (code) { code = code .replace(REMOVE_RE, '') .replace(SPLIT_RE, ',') .replace(KEYWORDS_RE, '') .replace(NUMBER_RE, '') .replace(BOUNDARY_RE, '') return code ? code.split(/,+/) : [] } /** * A given path could potentially exist not on the * current compiler, but up in the parent chain somewhere. * This function generates an access relationship string * that can be used in the getter function by walking up * the parent chain to check for key existence. * * It stops at top parent if no vm in the chain has the * key. It then creates any missing bindings on the * final resolved vm. */ function traceScope (path, compiler, data) { var rel = '', dist = 0, self = compiler if (data && utils.get(data, path) !== undefined) { // hack: temporarily attached data return '$temp.' } while (compiler) { if (compiler.hasKey(path)) { break } else { compiler = compiler.parent dist++ } } if (compiler) { while (dist--) { rel += '$parent.' } if (!compiler.bindings[path] && path.charAt(0) !== '$') { compiler.createBinding(path) } } else { self.createBinding(path) } return rel } /** * Create a function from a string... * this looks like evil magic but since all variables are limited * to the VM's data it's actually properly sandboxed */ function makeGetter (exp, raw) { var fn try { fn = new Function(exp) } catch (e) { utils.warn('Error parsing expression: ' + raw) } return fn } /** * Escape a leading dollar sign for regex construction */ function escapeDollar (v) { return v.charAt(0) === '$' ? '\\' + v : v } /** * Parse and return an anonymous computed property getter function * from an arbitrary expression, together with a list of paths to be * created as bindings. */ exports.parse = function (exp, compiler, data) { // unicode and 'constructor' are not allowed for XSS security. if (UNICODE_RE.test(exp) || CTOR_RE.test(exp)) { utils.warn('Unsafe expression: ' + exp) return } // extract variable names var vars = getVariables(exp) if (!vars.length) { return makeGetter('return ' + exp, exp) } vars = utils.unique(vars) var accessors = '', has = utils.hash(), strings = [], // construct a regex to extract all valid variable paths // ones that begin with "$" are particularly tricky // because we can't use \b for them pathRE = new RegExp( "[^$\\w\\.](" + vars.map(escapeDollar).join('|') + ")[$\\w\\.]*\\b", 'g' ), body = (' ' + exp) .replace(STR_SAVE_RE, saveStrings) .replace(pathRE, replacePath) .replace(STR_RESTORE_RE, restoreStrings) body = accessors + 'return ' + body function saveStrings (str) { var i = strings.length // escape newlines in strings so the expression // can be correctly evaluated strings[i] = str.replace(NEWLINE_RE, '\\n') return '"' + i + '"' } function replacePath (path) { // keep track of the first char var c = path.charAt(0) path = path.slice(1) var val = 'this.' + traceScope(path, compiler, data) + path if (!has[path]) { accessors += val + ';' has[path] = 1 } // don't forget to put that first char back return c + val } function restoreStrings (str, i) { return strings[i] } return makeGetter(body, exp) } /** * Evaluate an expression in the context of a compiler. * Accepts additional data. */ exports.eval = function (exp, compiler, data) { var getter = exports.parse(exp, compiler, data), res if (getter) { // hack: temporarily attach the additional data so // it can be accessed in the getter compiler.vm.$temp = data res = getter.call(compiler.vm) delete compiler.vm.$temp } return res } }); require.register("vue/src/template-parser.js", function(exports, require, module){ var toFragment = require('./fragment'); /** * Parses a template string or node and normalizes it into a * a node that can be used as a partial of a template option * * Possible values include * id selector: '#some-template-id' * template string: '
my template
' * DocumentFragment object * Node object of type Template */ module.exports = function(template) { var templateNode; if (template instanceof window.DocumentFragment) { // if the template is already a document fragment -- do nothing return template } if (typeof template === 'string') { // template by ID if (template.charAt(0) === '#') { templateNode = document.getElementById(template.slice(1)) if (!templateNode) return } else { return toFragment(template) } } else if (template.nodeType) { templateNode = template } else { return } // if its a template tag and the browser supports it, // its content is already a document fragment! if (templateNode.tagName === 'TEMPLATE' && templateNode.content) { return templateNode.content } if (templateNode.tagName === 'SCRIPT') { return toFragment(templateNode.innerHTML) } return toFragment(templateNode.outerHTML); } }); require.register("vue/src/text-parser.js", function(exports, require, module){ var openChar = '{', endChar = '}', ESCAPE_RE = /[-.*+?^${}()|[\]\/\\]/g, // lazy require Directive exports.Regex = buildInterpolationRegex() function buildInterpolationRegex () { var open = escapeRegex(openChar), end = escapeRegex(endChar) return new RegExp(open + open + open + '?(.+?)' + end + '?' + end + end) } function escapeRegex (str) { return str.replace(ESCAPE_RE, '\\$&') } function setDelimiters (delimiters) { openChar = delimiters[0] endChar = delimiters[1] exports.delimiters = delimiters exports.Regex = buildInterpolationRegex() } /** * Parse a piece of text, return an array of tokens * token types: * 1. plain string * 2. object with key = binding key * 3. object with key & html = true */ function parse (text) { if (!exports.Regex.test(text)) return null var m, i, token, match, tokens = [] /* jshint boss: true */ while (m = text.match(exports.Regex)) { i = m.index if (i > 0) tokens.push(text.slice(0, i)) token = { key: m[1].trim() } match = m[0] token.html = match.charAt(2) === openChar && match.charAt(match.length - 3) === endChar tokens.push(token) text = text.slice(i + m[0].length) } if (text.length) tokens.push(text) return tokens } /** * Parse an attribute value with possible interpolation tags * return a Directive-friendly expression * * e.g. a {{b}} c => "a " + b + " c" */ function parseAttr (attr) { Directive = Directive || require('./directive') var tokens = parse(attr) if (!tokens) return null if (tokens.length === 1) return tokens[0].key var res = [], token for (var i = 0, l = tokens.length; i < l; i++) { token = tokens[i] res.push( token.key ? inlineFilters(token.key) : ('"' + token + '"') ) } return res.join('+') } /** * Inlines any possible filters in a binding * so that we can combine everything into a huge expression */ function inlineFilters (key) { if (key.indexOf('|') > -1) { var dirs = Directive.parse(key), dir = dirs && dirs[0] if (dir && dir.filters) { key = Directive.inlineFilters( dir.key, dir.filters ) } } return '(' + key + ')' } exports.parse = parse exports.parseAttr = parseAttr exports.setDelimiters = setDelimiters exports.delimiters = [openChar, endChar] }); require.register("vue/src/deps-parser.js", function(exports, require, module){ var Emitter = require('./emitter'), utils = require('./utils'), Observer = require('./observer'), catcher = new Emitter() /** * Auto-extract the dependencies of a computed property * by recording the getters triggered when evaluating it. */ function catchDeps (binding) { if (binding.isFn) return utils.log('\n- ' + binding.key) var got = utils.hash() binding.deps = [] catcher.on('get', function (dep) { var has = got[dep.key] if ( // avoid duplicate bindings (has && has.compiler === dep.compiler) || // avoid repeated items as dependency // only when the binding is from self or the parent chain (dep.compiler.repeat && !isParentOf(dep.compiler, binding.compiler)) ) { return } got[dep.key] = dep utils.log(' - ' + dep.key) binding.deps.push(dep) dep.subs.push(binding) }) binding.value.$get() catcher.off('get') } /** * Test if A is a parent of or equals B */ function isParentOf (a, b) { while (b) { if (a === b) { return true } b = b.parent } } module.exports = { /** * the observer that catches events triggered by getters */ catcher: catcher, /** * parse a list of computed property bindings */ parse: function (bindings) { utils.log('\nparsing dependencies...') Observer.shouldGet = true bindings.forEach(catchDeps) Observer.shouldGet = false utils.log('\ndone.') } } }); require.register("vue/src/filters.js", function(exports, require, module){ var utils = require('./utils'), get = utils.get, slice = [].slice, QUOTE_RE = /^'.*'$/, filters = module.exports = utils.hash() /** * 'abc' => 'Abc' */ filters.capitalize = function (value) { if (!value && value !== 0) return '' value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) } /** * 'abc' => 'ABC' */ filters.uppercase = function (value) { return (value || value === 0) ? value.toString().toUpperCase() : '' } /** * 'AbC' => 'abc' */ filters.lowercase = function (value) { return (value || value === 0) ? value.toString().toLowerCase() : '' } /** * 12345 => $12,345.00 */ filters.currency = function (value, sign) { value = parseFloat(value) if (!value && value !== 0) return '' sign = sign || '$' var s = Math.floor(value).toString(), i = s.length % 3, h = i > 0 ? (s.slice(0, i) + (s.length > 3 ? ',' : '')) : '', f = '.' + value.toFixed(2).slice(-2) return sign + h + s.slice(i).replace(/(\d{3})(?=\d)/g, '$1,') + f } /** * args: 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'] */ filters.pluralize = function (value) { var args = slice.call(arguments, 1) return args.length > 1 ? (args[value - 1] || args[args.length - 1]) : (args[value - 1] || args[0] + 's') } /** * A special filter that takes a handler function, * wraps it so it only gets triggered on specific keypresses. * * v-on only */ var keyCodes = { enter : 13, tab : 9, 'delete' : 46, up : 38, left : 37, right : 39, down : 40, esc : 27 } filters.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) } } } /** * Filter filter for v-repeat */ filters.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)) // convert object to array if (!Array.isArray(arr)) { arr = utils.objectToArray(arr) } return arr.filter(function (item) { return dataKey ? contains(get(item, dataKey), search) : contains(item, search) }) } filters.filterBy.computed = true /** * Sort fitler for v-repeat */ filters.orderBy = function (arr, sortKey, reverseKey) { var key = stripQuotes(sortKey) || this.$get(sortKey) if (!key) return arr // convert object to array if (!Array.isArray(arr)) { arr = utils.objectToArray(arr) } var order = 1 if (reverseKey) { if (reverseKey === '-1') { order = -1 } else if (reverseKey.charAt(0) === '!') { 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 = get(a, key) b = get(b, key) return a === b ? 0 : a > b ? order : -order }) } filters.orderBy.computed = true // Array filter helpers ------------------------------------------------------- /** * String contain helper */ function contains (val, search) { /* jshint eqeqeq: false */ if (utils.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 } } /** * Test whether a string is in quotes, * if yes return stripped string */ function stripQuotes (str) { if (QUOTE_RE.test(str)) { return str.slice(1, -1) } } }); require.register("vue/src/transition.js", function(exports, require, module){ var endEvents = sniffEndEvents(), config = require('./config'), // batch enter animations so we only force the layout once Batcher = require('./batcher'), batcher = new Batcher(), // cache timer functions setTO = window.setTimeout, clearTO = window.clearTimeout, // exit codes for testing codes = { CSS_E : 1, CSS_L : 2, JS_E : 3, JS_L : 4, CSS_SKIP : -1, JS_SKIP : -2, JS_SKIP_E : -3, JS_SKIP_L : -4, INIT : -5, SKIP : -6 } // force layout before triggering transitions/animations batcher._preFlush = function () { /* jshint unused: false */ var f = document.body.offsetHeight } /** * stage: * 1 = enter * 2 = leave */ var transition = module.exports = function (el, stage, cb, compiler) { var changeState = function () { cb() compiler.execHook(stage > 0 ? 'attached' : 'detached') } if (compiler.init) { changeState() return codes.INIT } var hasTransition = el.vue_trans === '', hasAnimation = el.vue_anim === '', effectId = el.vue_effect if (effectId) { return applyTransitionFunctions( el, stage, changeState, effectId, compiler ) } else if (hasTransition || hasAnimation) { return applyTransitionClass( el, stage, changeState, hasAnimation ) } else { changeState() return codes.SKIP } } /** * Togggle a CSS class to trigger transition */ function applyTransitionClass (el, stage, changeState, hasAnimation) { if (!endEvents.trans) { changeState() return codes.CSS_SKIP } // if the browser supports transition, // it must have classList... var onEnd, classList = el.classList, existingCallback = el.vue_trans_cb, enterClass = config.enterClass, leaveClass = config.leaveClass, endEvent = hasAnimation ? endEvents.anim : endEvents.trans // cancel unfinished callbacks and jobs if (existingCallback) { el.removeEventListener(endEvent, existingCallback) classList.remove(enterClass) classList.remove(leaveClass) el.vue_trans_cb = null } if (stage > 0) { // enter // set to enter state before appending classList.add(enterClass) // append changeState() // trigger transition if (!hasAnimation) { batcher.push({ execute: function () { classList.remove(enterClass) } }) } else { onEnd = function (e) { if (e.target === el) { el.removeEventListener(endEvent, onEnd) el.vue_trans_cb = null classList.remove(enterClass) } } el.addEventListener(endEvent, onEnd) el.vue_trans_cb = onEnd } return codes.CSS_E } else { // leave if (el.offsetWidth || el.offsetHeight) { // trigger hide transition classList.add(leaveClass) onEnd = function (e) { if (e.target === el) { el.removeEventListener(endEvent, onEnd) el.vue_trans_cb = null // actually remove node here changeState() classList.remove(leaveClass) } } // attach transition end listener el.addEventListener(endEvent, onEnd) el.vue_trans_cb = onEnd } else { // directly remove invisible elements changeState() } return codes.CSS_L } } function applyTransitionFunctions (el, stage, changeState, effectId, compiler) { var funcs = compiler.getOption('effects', effectId) if (!funcs) { changeState() return codes.JS_SKIP } var enter = funcs.enter, leave = funcs.leave, timeouts = el.vue_timeouts // clear previous timeouts if (timeouts) { var i = timeouts.length while (i--) { clearTO(timeouts[i]) } } timeouts = el.vue_timeouts = [] function timeout (cb, delay) { var id = setTO(function () { cb() timeouts.splice(timeouts.indexOf(id), 1) if (!timeouts.length) { el.vue_timeouts = null } }, delay) timeouts.push(id) } if (stage > 0) { // enter if (typeof enter !== 'function') { changeState() return codes.JS_SKIP_E } enter(el, changeState, timeout) return codes.JS_E } else { // leave if (typeof leave !== 'function') { changeState() return codes.JS_SKIP_L } leave(el, changeState, timeout) return codes.JS_L } } /** * Sniff proper transition end event name */ function sniffEndEvents () { var el = document.createElement('vue'), defaultEvent = 'transitionend', events = { 'webkitTransition' : 'webkitTransitionEnd', 'transition' : defaultEvent, 'mozTransition' : defaultEvent }, ret = {} for (var name in events) { if (el.style[name] !== undefined) { ret.trans = events[name] break } } ret.anim = el.style.animation === '' ? 'animationend' : 'webkitAnimationEnd' return ret } // Expose some stuff for testing purposes transition.codes = codes transition.sniff = sniffEndEvents }); require.register("vue/src/batcher.js", function(exports, require, module){ var utils = require('./utils') function Batcher () { this.reset() } var BatcherProto = Batcher.prototype BatcherProto.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 utils.nextTick(utils.bind(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 } } BatcherProto.flush = function () { // before flush hook if (this._preFlush) this._preFlush() // do not cache length because more jobs might be pushed // as we execute existing jobs for (var i = 0; i < this.queue.length; i++) { var job = this.queue[i] if (!job.cancelled) { job.execute() } } this.reset() } BatcherProto.reset = function () { this.has = utils.hash() this.queue = [] this.waiting = false } module.exports = Batcher }); require.register("vue/src/directives/index.js", function(exports, require, module){ var utils = require('../utils'), config = require('../config'), transition = require('../transition'), directives = module.exports = utils.hash() /** * Nest and manage a Child VM */ directives.component = { isLiteral: true, bind: function () { if (!this.el.vue_vm) { this.childVM = new this.Ctor({ el: this.el, parent: this.vm }) } }, unbind: function () { if (this.childVM) { this.childVM.$destroy() } } } /** * Binding HTML attributes */ directives.attr = { bind: function () { var params = this.vm.$options.paramAttributes this.isParam = params && params.indexOf(this.arg) > -1 }, update: function (value) { if (value || value === 0) { this.el.setAttribute(this.arg, value) } else { this.el.removeAttribute(this.arg) } if (this.isParam) { this.vm[this.arg] = utils.checkNumber(value) } } } /** * Binding textContent */ directives.text = { bind: function () { this.attr = this.el.nodeType === 3 ? 'nodeValue' : 'textContent' }, update: function (value) { this.el[this.attr] = utils.guard(value) } } /** * Binding CSS display property */ directives.show = function (value) { var el = this.el, target = value ? '' : 'none', change = function () { el.style.display = target } transition(el, value ? 1 : -1, change, this.compiler) } /** * Binding CSS classes */ directives['class'] = function (value) { if (this.arg) { utils[value ? 'addClass' : 'removeClass'](this.el, this.arg) } else { if (this.lastVal) { utils.removeClass(this.el, this.lastVal) } if (value) { utils.addClass(this.el, value) this.lastVal = value } } } /** * Only removed after the owner VM is ready */ directives.cloak = { isEmpty: true, bind: function () { var el = this.el this.compiler.observer.once('hook:ready', function () { el.removeAttribute(config.prefix + '-cloak') }) } } /** * Store a reference to self in parent VM's $ */ directives.ref = { isLiteral: true, bind: function () { var id = this.expression if (id) { this.vm.$parent.$[id] = this.vm } }, unbind: function () { var id = this.expression if (id) { delete this.vm.$parent.$[id] } } } directives.on = require('./on') directives.repeat = require('./repeat') directives.model = require('./model') directives['if'] = require('./if') directives['with'] = require('./with') directives.html = require('./html') directives.style = require('./style') directives.partial = require('./partial') directives.view = require('./view') }); require.register("vue/src/directives/if.js", function(exports, require, module){ var utils = require('../utils') /** * Manages a conditional child VM */ module.exports = { bind: function () { this.parent = this.el.parentNode this.ref = document.createComment('vue-if') this.Ctor = this.compiler.resolveComponent(this.el) // insert ref this.parent.insertBefore(this.ref, this.el) this.parent.removeChild(this.el) if (utils.attr(this.el, 'view')) { utils.warn( 'Conflict: v-if cannot be used together with v-view. ' + 'Just set v-view\'s binding value to empty string to empty it.' ) } if (utils.attr(this.el, 'repeat')) { utils.warn( 'Conflict: v-if cannot be used together with v-repeat. ' + 'Use `v-show` or the `filterBy` filter instead.' ) } }, update: function (value) { if (!value) { this.unbind() } else if (!this.childVM) { this.childVM = new this.Ctor({ el: this.el.cloneNode(true), parent: this.vm }) if (this.compiler.init) { this.parent.insertBefore(this.childVM.$el, this.ref) } else { this.childVM.$before(this.ref) } } }, unbind: function () { if (this.childVM) { this.childVM.$destroy() this.childVM = null } } } }); require.register("vue/src/directives/repeat.js", function(exports, require, module){ var utils = require('../utils'), config = require('../config') /** * Binding that manages VMs based on an Array */ module.exports = { bind: function () { this.identifier = '$r' + this.id // a hash to cache the same expressions on repeated instances // so they don't have to be compiled for every single instance this.expCache = utils.hash() var el = this.el, ctn = this.container = el.parentNode // extract child Id, if any this.childId = this.compiler.eval(utils.attr(el, 'ref')) // create a comment node as a reference node for DOM insertions this.ref = document.createComment(config.prefix + '-repeat-' + this.key) ctn.insertBefore(this.ref, el) ctn.removeChild(el) this.collection = null this.vms = null }, update: function (collection) { if (!Array.isArray(collection)) { if (utils.isObject(collection)) { collection = utils.objectToArray(collection) } else { utils.warn('v-repeat only accepts Array or Object values.') } } // keep reference of old data and VMs // so we can reuse them if possible this.oldVMs = this.vms this.oldCollection = this.collection collection = this.collection = collection || [] var isObject = collection[0] && utils.isObject(collection[0]) this.vms = this.oldCollection ? this.diff(collection, isObject) : this.init(collection, isObject) if (this.childId) { this.vm.$[this.childId] = this.vms } }, init: function (collection, isObject) { var vm, vms = [] for (var i = 0, l = collection.length; i < l; i++) { vm = this.build(collection[i], i, isObject) vms.push(vm) if (this.compiler.init) { this.container.insertBefore(vm.$el, this.ref) } else { vm.$before(this.ref) } } return vms }, /** * Diff the new array with the old * and determine the minimum amount of DOM manipulations. */ diff: function (newCollection, isObject) { var i, l, item, vm, oldIndex, targetNext, currentNext, nextEl, ctn = this.container, oldVMs = this.oldVMs, vms = [] vms.length = newCollection.length // first pass, collect new reused and new created for (i = 0, l = newCollection.length; i < l; i++) { item = newCollection[i] if (isObject) { item.$index = i if (item.__emitter__ && item.__emitter__[this.identifier]) { // this piece of data is being reused. // record its final position in reused vms item.$reused = true } else { vms[i] = this.build(item, i, isObject) } } else { // we can't attach an identifier to primitive values // so have to do an indexOf... oldIndex = indexOf(oldVMs, item) if (oldIndex > -1) { // record the position on the existing vm oldVMs[oldIndex].$reused = true oldVMs[oldIndex].$data.$index = i } else { vms[i] = this.build(item, i, isObject) } } } // second pass, collect old reused and destroy unused for (i = 0, l = oldVMs.length; i < l; i++) { vm = oldVMs[i] item = this.arg ? vm.$data[this.arg] : vm.$data if (item.$reused) { vm.$reused = true delete item.$reused } if (vm.$reused) { // update the index to latest vm.$index = item.$index // the item could have had a new key if (item.$key && item.$key !== vm.$key) { vm.$key = item.$key } vms[vm.$index] = vm } else { // this one can be destroyed. if (item.__emitter__) { delete item.__emitter__[this.identifier] } vm.$destroy() } } // final pass, move/insert DOM elements i = vms.length while (i--) { vm = vms[i] item = vm.$data targetNext = vms[i + 1] if (vm.$reused) { nextEl = vm.$el.nextSibling // destroyed VMs' element might still be in the DOM // due to transitions while (!nextEl.vue_vm && nextEl !== this.ref) { nextEl = nextEl.nextSibling } currentNext = nextEl.vue_vm if (currentNext !== targetNext) { if (!targetNext) { ctn.insertBefore(vm.$el, this.ref) } else { nextEl = targetNext.$el // new VMs' element might not be in the DOM yet // due to transitions while (!nextEl.parentNode) { targetNext = vms[nextEl.vue_vm.$index + 1] nextEl = targetNext ? targetNext.$el : this.ref } ctn.insertBefore(vm.$el, nextEl) } } delete vm.$reused delete item.$index delete item.$key } else { // a new vm vm.$before(targetNext ? targetNext.$el : this.ref) } } return vms }, build: function (data, index, isObject) { // wrap non-object values var raw, alias, wrap = !isObject || this.arg if (wrap) { raw = data alias = this.arg || '$value' data = {} data[alias] = raw } data.$index = index var el = this.el.cloneNode(true), Ctor = this.compiler.resolveComponent(el, data), vm = new Ctor({ el: el, data: data, parent: this.vm, compilerOptions: { repeat: true, expCache: this.expCache } }) if (isObject) { // attach an ienumerable identifier to the raw data (raw || data).__emitter__[this.identifier] = true } return vm }, unbind: function () { if (this.childId) { delete this.vm.$[this.childId] } if (this.vms) { var i = this.vms.length while (i--) { this.vms[i].$destroy() } } } } // Helpers -------------------------------------------------------------------- /** * Find an object or a wrapped data object * from an Array */ function indexOf (vms, obj) { for (var vm, i = 0, l = vms.length; i < l; i++) { vm = vms[i] if (!vm.$reused && vm.$value === obj) { return i } } return -1 } }); require.register("vue/src/directives/on.js", function(exports, require, module){ var utils = require('../utils') /** * Binding for event listeners */ module.exports = { isFn: true, bind: function () { this.context = this.binding.isExp ? this.vm : this.binding.compiler.vm if (this.el.tagName === 'IFRAME' && this.arg !== 'load') { var self = this this.iframeBind = function () { self.el.contentWindow.addEventListener(self.arg, self.handler) } this.el.addEventListener('load', this.iframeBind) } }, update: function (handler) { if (typeof handler !== 'function') { utils.warn('Directive "v-on:' + this.expression + '" expects a method.') return } this.reset() var vm = this.vm, context = this.context this.handler = function (e) { e.targetVM = vm context.$event = e var res = handler.call(context, e) context.$event = null return res } if (this.iframeBind) { this.iframeBind() } else { this.el.addEventListener(this.arg, this.handler) } }, reset: function () { var el = this.iframeBind ? this.el.contentWindow : this.el if (this.handler) { el.removeEventListener(this.arg, this.handler) } }, unbind: function () { this.reset() this.el.removeEventListener('load', this.iframeBind) } } }); require.register("vue/src/directives/model.js", function(exports, require, module){ var utils = require('../utils'), isIE9 = navigator.userAgent.indexOf('MSIE 9.0') > 0, filter = [].filter /** * Returns an array of values from a multiple select */ function getMultipleSelectOptions (select) { return filter .call(select.options, function (option) { return option.selected }) .map(function (option) { return option.value || option.text }) } /** * Two-way binding for form input elements */ module.exports = { bind: function () { var self = this, el = self.el, type = el.type, tag = el.tagName self.lock = false self.ownerVM = self.binding.compiler.vm // determine what event to listen to self.event = (self.compiler.options.lazy || tag === 'SELECT' || type === 'checkbox' || type === 'radio') ? 'change' : 'input' // determine the attribute to change when updating self.attr = type === 'checkbox' ? 'checked' : (tag === 'INPUT' || tag === 'SELECT' || tag === 'TEXTAREA') ? 'value' : 'innerHTML' // select[multiple] support if(tag === 'SELECT' && el.hasAttribute('multiple')) { this.multi = true } var compositionLock = false self.cLock = function () { compositionLock = true } self.cUnlock = function () { compositionLock = false } el.addEventListener('compositionstart', this.cLock) el.addEventListener('compositionend', this.cUnlock) // attach listener self.set = self.filters ? function () { if (compositionLock) return // if this directive has filters // we need to let the vm.$set trigger // update() so filters are applied. // therefore we have to record cursor position // so that after vm.$set changes the input // value we can put the cursor back at where it is var cursorPos try { cursorPos = el.selectionStart } catch (e) {} self._set() // since updates are async // we need to reset cursor position async too utils.nextTick(function () { if (cursorPos !== undefined) { el.setSelectionRange(cursorPos, cursorPos) } }) } : function () { if (compositionLock) return // no filters, don't let it trigger update() self.lock = true self._set() utils.nextTick(function () { self.lock = false }) } el.addEventListener(self.event, self.set) // fix shit for IE9 // since it doesn't fire input on backspace / del / cut if (isIE9) { self.onCut = function () { // cut event fires before the value actually changes utils.nextTick(function () { self.set() }) } self.onDel = function (e) { if (e.keyCode === 46 || e.keyCode === 8) { self.set() } } el.addEventListener('cut', self.onCut) el.addEventListener('keyup', self.onDel) } }, _set: function () { this.ownerVM.$set( this.key, this.multi ? getMultipleSelectOptions(this.el) : this.el[this.attr] ) }, update: function (value, init) { /* jshint eqeqeq: false */ // sync back inline value if initial data is undefined if (init && value === undefined) { return this._set() } if (this.lock) return var el = this.el if (el.tagName === 'SELECT') { // select dropdown el.selectedIndex = -1 if(this.multi && Array.isArray(value)) { value.forEach(this.updateSelect, this) } else { this.updateSelect(value) } } else if (el.type === 'radio') { // radio button el.checked = value == el.value } else if (el.type === 'checkbox') { // checkbox el.checked = !!value } else { el[this.attr] = utils.guard(value) } }, updateSelect: function (value) { /* jshint eqeqeq: false */ // setting