']
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