Skip to content

Instantly share code, notes, and snippets.

@rafaelrinaldi
Created May 8, 2014 23:50
Show Gist options
  • Save rafaelrinaldi/47f109a7dd14134ab056 to your computer and use it in GitHub Desktop.
Save rafaelrinaldi/47f109a7dd14134ab056 to your computer and use it in GitHub Desktop.
Vue new dev release
/*
Vue.js v0.10.4
(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']
// require these so Browserify can catch them
// so they can be used in Vue.require
require('./observer')
require('./transition')
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.toFragment(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 (path) {
return require('./' + path)
}
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'),
/**
* 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.toFragment(partials[key])
}
}
if (filters) {
for (key in filters) {
utils.checkFilter(filters[key])
}
}
if (template) {
options.template = utils.toFragment(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, '<fieldset>', '</fieldset>'],
tr : [2, '<table><tbody>', '</tbody></table>'],
col : [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
_default : [0, '', '']
}
map.td =
map.th = [3, '<table><tbody><tr>', '</tr></tbody></table>']
map.option =
map.optgroup = [1, '<select multiple="multiple">', '</select>']
map.thead =
map.tbody =
map.colgroup =
map.caption =
map.tfoot = [1, '<table>', '</table>']
map.text =
map.circle =
map.ellipse =
map.line =
map.path =
map.polygon =
map.polyline =
map.rect = [1, '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">','</svg>']
var TAG_RE = /<([\w:]+)/
module.exports = function (template) {
if (typeof template !== 'string') {
return template
}
// template by ID
if (template.charAt(0) === '#') {
var templateNode = document.getElementById(template.slice(1))
if (!templateNode) 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
}
template = templateNode.innerHTML
}
var frag = document.createDocumentFragment(),
m = TAG_RE.exec(template)
// text only
if (!m) {
frag.appendChild(document.createTextNode(template))
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 + template.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)
// 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)
}
}
// 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
}
vm.$root = getRoot(compiler).vm
// DATA -------------------------------------------------------------------
// setup observer
// this is necesarry for all hooks and data observation events
compiler.setupObserver()
// 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 <content> 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 + '-',
attrs = slice.call(node.attributes),
params = this.options.paramAttributes,
attr, isDirective, exp, directives, directive, dirname
for (i = 0, l = attrs.length; i < l; i++) {
attr = attrs[i]
isDirective = false
if (attr.name.indexOf(prefix) === 0) {
// a directive - split, parse and bind it.
isDirective = true
dirname = attr.name.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++) {
directive = directives[j]
if (dirname === 'with') {
this.bindDirective(directive, this.parent)
} else {
this.bindDirective(directive)
}
}
} else if (config.interpolate) {
// non directive attribute, check interpolation tags
exp = TextParser.parseAttr(attr.value)
if (exp) {
directive = this.parseDirective('attr', attr.name + ':' + exp, node)
if (params && params.indexOf(attr.name) > -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(attr.name)
}
}
}
// 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
binding.value = compiler.vm[key] = 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.defineProp(key, binding)
} else {
compiler.defineMeta(key, binding)
}
} 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 for a root-level property on the VM
* and observe the initial value
*/
CompilerProto.defineProp = 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 meta property, e.g. $index or $key,
* which is bindable but only accessible on the VM,
* not in the data.
*/
CompilerProto.defineMeta = function (key, binding) {
var ob = this.observer
binding.value = this.data[key]
delete this.data[key]
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 () {
// 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)
// 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()
}
}
// destroy all children
i = children.length
while (i--) {
children[i].destroy()
}
// remove self from parent
if (parent) {
j = parent.children.indexOf(compiler)
if (j > -1) parent.children.splice(j, 1)
}
// finally remove dom element
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) {
// just compile. options are passed directly to compiler
new Compiler(this, options)
}
// All VM prototype methods are inenumerable
// so it can be stringified/looped through as raw data
var VMProto = ViewModel.prototype
/**
* 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 () {
this.$compiler.destroy()
})
/**
* 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 = str.slice(begin, i).trim()
}
} 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/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) {
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
},
update: function (handler) {
if (typeof handler !== 'function') {
utils.warn('Directive "v-on:' + this.expression + '" expects a method.')
return
}
this.unbind()
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
}
this.el.addEventListener(this.arg, this.handler)
},
unbind: function () {
this.el.removeEventListener(this.arg, this.handler)
}
}
});
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 <select>'s value in IE9 doesn't work
// we have to manually loop through the options
var options = this.el.options,
i = options.length
while (i--) {
if (options[i].value == value) {
options[i].selected = true
break
}
}
},
unbind: function () {
var el = this.el
el.removeEventListener(this.event, this.set)
el.removeEventListener('compositionstart', this.cLock)
el.removeEventListener('compositionend', this.cUnlock)
if (isIE9) {
el.removeEventListener('cut', this.onCut)
el.removeEventListener('keyup', this.onDel)
}
}
}
});
require.register("vue/src/directives/with.js", function(exports, require, module){
var utils = require('../utils')
/**
* Binding for inheriting data from parent VMs.
*/
module.exports = {
bind: function () {
var self = this,
childKey = self.arg,
parentKey = self.key,
compiler = self.compiler,
owner = self.binding.compiler
if (compiler === owner) {
this.alone = true
return
}
if (childKey) {
if (!compiler.bindings[childKey]) {
compiler.createBinding(childKey)
}
// sync changes on child back to parent
compiler.observer.on('change:' + childKey, function (val) {
if (compiler.init) return
if (!self.lock) {
self.lock = true
utils.nextTick(function () {
self.lock = false
})
}
owner.vm.$set(parentKey, val)
})
}
},
update: function (value) {
// sync from parent
if (!this.alone && !this.lock) {
if (this.arg) {
this.vm.$set(this.arg, value)
} else {
this.vm.$data = value
}
}
}
}
});
require.register("vue/src/directives/html.js", function(exports, require, module){
var utils = require('../utils'),
slice = [].slice
/**
* Binding for innerHTML
*/
module.exports = {
bind: function () {
// a comment node means this is a binding for
// {{{ inline unescaped html }}}
if (this.el.nodeType === 8) {
// hold nodes
this.nodes = []
}
},
update: function (value) {
value = utils.guard(value)
if (this.nodes) {
this.swap(value)
} else {
this.el.innerHTML = value
}
},
swap: function (value) {
var parent = this.el.parentNode,
nodes = this.nodes,
i = nodes.length
// remove old nodes
while (i--) {
parent.removeChild(nodes[i])
}
// convert new value to a fragment
var frag = utils.toFragment(value)
// save a reference to these nodes so we can remove later
this.nodes = slice.call(frag.childNodes)
parent.insertBefore(frag, this.el)
}
}
});
require.register("vue/src/directives/style.js", function(exports, require, module){
var camelRE = /-([a-z])/g,
prefixes = ['webkit', 'moz', 'ms']
function camelReplacer (m) {
return m[1].toUpperCase()
}
/**
* Binding for CSS styles
*/
module.exports = {
bind: function () {
var prop = this.arg
if (!prop) return
var first = prop.charAt(0)
if (first === '$') {
// properties that start with $ will be auto-prefixed
prop = prop.slice(1)
this.prefixed = true
} else if (first === '-') {
// normal starting hyphens should not be converted
prop = prop.slice(1)
}
this.prop = prop.replace(camelRE, camelReplacer)
},
update: function (value) {
var prop = this.prop
if (prop) {
this.el.style[prop] = value
if (this.prefixed) {
prop = prop.charAt(0).toUpperCase() + prop.slice(1)
var i = prefixes.length
while (i--) {
this.el.style[prefixes[i] + prop] = value
}
}
} else {
this.el.style.cssText = value
}
}
}
});
require.register("vue/src/directives/partial.js", function(exports, require, module){
var utils = require('../utils')
/**
* Binding for partials
*/
module.exports = {
isLiteral: true,
bind: function () {
var id = this.expression
if (!id) return
var el = this.el,
compiler = this.compiler,
partial = compiler.getOption('partials', id)
if (!partial) {
if (id === 'yield') {
utils.warn('{{>yield}} syntax has been deprecated. Use <content> tag instead.')
}
return
}
partial = partial.cloneNode(true)
// comment ref node means inline partial
if (el.nodeType === 8) {
// keep a ref for the partial's content nodes
var nodes = [].slice.call(partial.childNodes),
parent = el.parentNode
parent.insertBefore(partial, el)
parent.removeChild(el)
// compile partial after appending, because its children's parentNode
// will change from the fragment to the correct parentNode.
// This could affect directives that need access to its element's parentNode.
nodes.forEach(compiler.compile, compiler)
} else {
// just set innerHTML...
el.innerHTML = ''
el.appendChild(partial.cloneNode(true))
}
}
}
});
require.register("vue/src/directives/view.js", function(exports, require, module){
/**
* Manages a conditional child VM using the
* binding's value as the component ID.
*/
module.exports = {
bind: function () {
// track position in DOM with a ref node
var el = this.raw = this.el,
parent = el.parentNode,
ref = this.ref = document.createComment('v-view')
parent.insertBefore(ref, el)
parent.removeChild(el)
// cache original content
/* jshint boss: true */
var node,
frag = this.inner = document.createElement('div')
while (node = el.firstChild) {
frag.appendChild(node)
}
},
update: function(value) {
this.unbind()
var Ctor = this.compiler.getOption('components', value)
if (!Ctor) return
this.childVM = new Ctor({
el: this.raw.cloneNode(true),
parent: this.vm,
compilerOptions: {
rawContent: this.inner.cloneNode(true)
}
})
this.el = this.childVM.$el
if (this.compiler.init) {
this.ref.parentNode.insertBefore(this.el, this.ref)
} else {
this.childVM.$before(this.ref)
}
},
unbind: function() {
if (this.childVM) {
this.childVM.$destroy()
}
}
}
});
require.alias("vue/src/main.js", "vue/index.js");
if (typeof exports == 'object') {
module.exports = require('vue');
} else if (typeof define == 'function' && define.amd) {
define(function(){ return require('vue'); });
} else {
window['Vue'] = require('vue');
}})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment