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