Commit ccc295a7 authored by Evan You's avatar Evan You

Update Vue.js to v0.8.4 and fix IE issue

- fixed some jshint errors overlooked from last commit
- fixed IE-only bug which causes some directives to be skipped
parent 64445b01
/* /*
Vue.js v0.8.3 Vue.js v0.8.4
(c) 2014 Evan You (c) 2014 Evan You
License: MIT License: MIT
*/ */
...@@ -509,8 +509,13 @@ function inheritOptions (child, parent, topLevel) { ...@@ -509,8 +509,13 @@ function inheritOptions (child, parent, topLevel) {
parentVal = parent[key], parentVal = parent[key],
type = utils.typeOf(val) type = utils.typeOf(val)
if (topLevel && type === 'Function' && parentVal) { if (topLevel && type === 'Function' && parentVal) {
// merge hook functions // merge hook functions into an array
child[key] = mergeHook(val, parentVal) child[key] = [val]
if (Array.isArray(parentVal)) {
child[key] = child[key].concat(parentVal)
} else {
child[key].push(parentVal)
}
} else if (topLevel && type === 'Object') { } else if (topLevel && type === 'Object') {
// merge toplevel object options // merge toplevel object options
inheritOptions(val, parentVal) inheritOptions(val, parentVal)
...@@ -522,17 +527,6 @@ function inheritOptions (child, parent, topLevel) { ...@@ -522,17 +527,6 @@ function inheritOptions (child, parent, topLevel) {
return child return child
} }
/**
* Merge hook functions
* so parent hooks also get called
*/
function mergeHook (fn, parentFn) {
return function (opts) {
parentFn.call(this, opts)
fn.call(this, opts)
}
}
module.exports = ViewModel module.exports = ViewModel
}); });
require.register("vue/src/emitter.js", function(exports, require, module){ require.register("vue/src/emitter.js", function(exports, require, module){
...@@ -846,7 +840,14 @@ var Emitter = require('./emitter'), ...@@ -846,7 +840,14 @@ var Emitter = require('./emitter'),
makeHash = utils.hash, makeHash = utils.hash,
extend = utils.extend, extend = utils.extend,
def = utils.defProtected, def = utils.defProtected,
hasOwn = Object.prototype.hasOwnProperty hasOwn = Object.prototype.hasOwnProperty,
// hooks to register
hooks = [
'created', 'ready',
'beforeDestroy', 'afterDestroy',
'enteredView', 'leftView'
]
/** /**
* The DOM compiler * The DOM compiler
...@@ -914,7 +915,7 @@ function Compiler (vm, options) { ...@@ -914,7 +915,7 @@ function Compiler (vm, options) {
} }
// beforeCompile hook // beforeCompile hook
compiler.execHook('beforeCompile', 'created') compiler.execHook('created')
// the user might have set some props on the vm // the user might have set some props on the vm
// so copy it back to the data... // so copy it back to the data...
...@@ -951,9 +952,7 @@ function Compiler (vm, options) { ...@@ -951,9 +952,7 @@ function Compiler (vm, options) {
compiler.compile(el, true) compiler.compile(el, true)
// bind deferred directives (child components) // bind deferred directives (child components)
for (var i = 0, l = compiler.deferred.length; i < l; i++) { compiler.deferred.forEach(compiler.bindDirective, compiler)
compiler.bindDirective(compiler.deferred[i])
}
// extract dependencies for computed properties // extract dependencies for computed properties
compiler.parseDeps() compiler.parseDeps()
...@@ -962,7 +961,7 @@ function Compiler (vm, options) { ...@@ -962,7 +961,7 @@ function Compiler (vm, options) {
compiler.init = false compiler.init = false
// post compile / ready hook // post compile / ready hook
compiler.execHook('afterCompile', 'ready') compiler.execHook('ready')
} }
var CompilerProto = Compiler.prototype var CompilerProto = Compiler.prototype
...@@ -1011,11 +1010,13 @@ CompilerProto.setupElement = function (options) { ...@@ -1011,11 +1010,13 @@ CompilerProto.setupElement = function (options) {
* Setup observer. * Setup observer.
* The observer listens for get/set/mutate events on all VM * The observer listens for get/set/mutate events on all VM
* values/objects and trigger corresponding binding updates. * values/objects and trigger corresponding binding updates.
* It also listens for lifecycle hooks.
*/ */
CompilerProto.setupObserver = function () { CompilerProto.setupObserver = function () {
var compiler = this, var compiler = this,
bindings = compiler.bindings, bindings = compiler.bindings,
options = compiler.options,
observer = compiler.observer = new Emitter() observer = compiler.observer = new Emitter()
// a hash to hold event proxies for each root level key // a hash to hold event proxies for each root level key
...@@ -1038,6 +1039,27 @@ CompilerProto.setupObserver = function () { ...@@ -1038,6 +1039,27 @@ CompilerProto.setupObserver = function () {
check(key) check(key)
bindings[key].pub() bindings[key].pub()
}) })
// register hooks
hooks.forEach(function (hook) {
var fns = options[hook]
if (Array.isArray(fns)) {
var i = fns.length
// since hooks were merged with child at head,
// we loop reversely.
while (i--) {
register(hook, fns[i])
}
} else if (fns) {
register(hook, fns)
}
})
function register (hook, fn) {
observer.on('hook:' + hook, function () {
fn.call(compiler.vm, options)
})
}
function check (key) { function check (key) {
if (!bindings[key]) { if (!bindings[key]) {
...@@ -1090,7 +1112,7 @@ CompilerProto.compile = function (node, root) { ...@@ -1090,7 +1112,7 @@ CompilerProto.compile = function (node, root) {
} }
// v-with has 2nd highest priority // v-with has 2nd highest priority
} else if (!root && ((withKey = utils.attr(node, 'with')) || componentCtor)) { } else if (root !== true && ((withKey = utils.attr(node, 'with')) || componentCtor)) {
directive = Directive.parse('with', withKey || '', compiler, node) directive = Directive.parse('with', withKey || '', compiler, node)
if (directive) { if (directive) {
...@@ -1130,7 +1152,7 @@ CompilerProto.compile = function (node, root) { ...@@ -1130,7 +1152,7 @@ CompilerProto.compile = function (node, root) {
*/ */
CompilerProto.compileNode = function (node) { CompilerProto.compileNode = function (node) {
var i, j, var i, j,
attrs = node.attributes, attrs = slice.call(node.attributes),
prefix = config.prefix + '-' prefix = config.prefix + '-'
// parse if has attributes // parse if has attributes
if (attrs && attrs.length) { if (attrs && attrs.length) {
...@@ -1171,10 +1193,7 @@ CompilerProto.compileNode = function (node) { ...@@ -1171,10 +1193,7 @@ CompilerProto.compileNode = function (node) {
} }
// recursively compile childNodes // recursively compile childNodes
if (node.childNodes.length) { if (node.childNodes.length) {
var nodes = slice.call(node.childNodes) slice.call(node.childNodes).forEach(this.compile, this)
for (i = 0, j = nodes.length; i < j; i++) {
this.compile(nodes[i])
}
} }
} }
...@@ -1189,7 +1208,7 @@ CompilerProto.compileTextNode = function (node) { ...@@ -1189,7 +1208,7 @@ CompilerProto.compileTextNode = function (node) {
for (var i = 0, l = tokens.length; i < l; i++) { for (var i = 0, l = tokens.length; i < l; i++) {
token = tokens[i] token = tokens[i]
directive = null directive = partialNodes = null
if (token.key) { // a binding if (token.key) { // a binding
if (token.key.charAt(0) === '>') { // a partial if (token.key.charAt(0) === '>') { // a partial
partialId = token.key.slice(1).trim() partialId = token.key.slice(1).trim()
...@@ -1215,6 +1234,8 @@ CompilerProto.compileTextNode = function (node) { ...@@ -1215,6 +1234,8 @@ CompilerProto.compileTextNode = function (node) {
// insert node // insert node
node.parentNode.insertBefore(el, node) node.parentNode.insertBefore(el, node)
// bind directive
if (directive) { if (directive) {
this.bindDirective(directive) this.bindDirective(directive)
} }
...@@ -1223,10 +1244,7 @@ CompilerProto.compileTextNode = function (node) { ...@@ -1223,10 +1244,7 @@ CompilerProto.compileTextNode = function (node) {
// will change from the fragment to the correct parentNode. // will change from the fragment to the correct parentNode.
// This could affect directives that need access to its element's parentNode. // This could affect directives that need access to its element's parentNode.
if (partialNodes) { if (partialNodes) {
for (var j = 0, k = partialNodes.length; j < k; j++) { partialNodes.forEach(this.compile, this)
this.compile(partialNodes[j])
}
partialNodes = null
} }
} }
...@@ -1241,9 +1259,9 @@ CompilerProto.bindDirective = function (directive) { ...@@ -1241,9 +1259,9 @@ CompilerProto.bindDirective = function (directive) {
// keep track of it so we can unbind() later // keep track of it so we can unbind() later
this.dirs.push(directive) this.dirs.push(directive)
// for a simple directive, simply call its bind() or _update() // for empty or literal directives, simply call its bind()
// and we're done. // and we're done.
if (directive.isEmpty) { if (directive.isEmpty || directive.isLiteral) {
if (directive.bind) directive.bind() if (directive.bind) directive.bind()
return return
} }
...@@ -1417,14 +1435,12 @@ CompilerProto.getOption = function (type, id) { ...@@ -1417,14 +1435,12 @@ CompilerProto.getOption = function (type, id) {
} }
/** /**
* Execute a user hook * Emit lifecycle events to trigger hooks
*/ */
CompilerProto.execHook = function (id, alt) { CompilerProto.execHook = function (event) {
var opts = this.options, event = 'hook:' + event
hook = opts[id] || opts[alt] this.observer.emit(event)
if (hook) { this.emitter.emit(event)
hook.call(this.vm, opts)
}
} }
/** /**
...@@ -1449,6 +1465,10 @@ CompilerProto.parseDeps = function () { ...@@ -1449,6 +1465,10 @@ CompilerProto.parseDeps = function () {
*/ */
CompilerProto.destroy = function () { CompilerProto.destroy = function () {
// avoid being called more than once
// this is irreversible!
if (this.destroyed) return
var compiler = this, var compiler = this,
i, key, dir, instances, binding, i, key, dir, instances, binding,
vm = compiler.vm, vm = compiler.vm,
...@@ -1459,10 +1479,6 @@ CompilerProto.destroy = function () { ...@@ -1459,10 +1479,6 @@ CompilerProto.destroy = function () {
compiler.execHook('beforeDestroy') compiler.execHook('beforeDestroy')
// unwatch
compiler.observer.off()
compiler.emitter.off()
// unbind all direcitves // unbind all direcitves
i = directives.length i = directives.length
while (i--) { while (i--) {
...@@ -1511,7 +1527,13 @@ CompilerProto.destroy = function () { ...@@ -1511,7 +1527,13 @@ CompilerProto.destroy = function () {
vm.$remove() vm.$remove()
} }
this.destroyed = true
// emit destroy hook
compiler.execHook('afterDestroy') compiler.execHook('afterDestroy')
// finally, unregister all listeners
compiler.observer.off()
compiler.emitter.off()
} }
// Helpers -------------------------------------------------------------------- // Helpers --------------------------------------------------------------------
...@@ -2131,11 +2153,11 @@ var utils = require('./utils'), ...@@ -2131,11 +2153,11 @@ var utils = require('./utils'),
// match up to the first single pipe, ignore those within quotes. // match up to the first single pipe, ignore those within quotes.
KEY_RE = /^(?:['"](?:\\.|[^'"])*['"]|\\.|[^\|]|\|\|)+/, KEY_RE = /^(?:['"](?:\\.|[^'"])*['"]|\\.|[^\|]|\|\|)+/,
ARG_RE = /^([\w- ]+):(.+)$/, ARG_RE = /^([\w-$ ]+):(.+)$/,
FILTERS_RE = /\|[^\|]+/g, FILTERS_RE = /\|[^\|]+/g,
FILTER_TOKEN_RE = /[^\s']+|'[^']+'/g, FILTER_TOKEN_RE = /[^\s']+|'[^']+'/g,
NESTING_RE = /^\$(parent|root)\./, NESTING_RE = /^\$(parent|root)\./,
SINGLE_VAR_RE = /^[\w\.\$]+$/ SINGLE_VAR_RE = /^[\w\.$]+$/
/** /**
* Directive class * Directive class
...@@ -2168,6 +2190,13 @@ function Directive (definition, expression, rawKey, compiler, node) { ...@@ -2168,6 +2190,13 @@ function Directive (definition, expression, rawKey, compiler, node) {
return return
} }
// for literal directives, all we need
// is the expression as the value.
if (this.isLiteral) {
this.value = expression.trim()
return
}
this.expression = expression.trim() this.expression = expression.trim()
this.rawKey = rawKey this.rawKey = rawKey
...@@ -2178,8 +2207,7 @@ function Directive (definition, expression, rawKey, compiler, node) { ...@@ -2178,8 +2207,7 @@ function Directive (definition, expression, rawKey, compiler, node) {
var filterExps = this.expression.slice(rawKey.length).match(FILTERS_RE) var filterExps = this.expression.slice(rawKey.length).match(FILTERS_RE)
if (filterExps) { if (filterExps) {
this.filters = [] this.filters = []
var i = 0, l = filterExps.length, filter for (var i = 0, l = filterExps.length, filter; i < l; i++) {
for (; i < l; i++) {
filter = parseFilter(filterExps[i], this.compiler) filter = parseFilter(filterExps[i], this.compiler)
if (filter) this.filters.push(filter) if (filter) this.filters.push(filter)
} }
...@@ -2560,8 +2588,7 @@ module.exports = { ...@@ -2560,8 +2588,7 @@ module.exports = {
parse: function (bindings) { parse: function (bindings) {
utils.log('\nparsing dependencies...') utils.log('\nparsing dependencies...')
Observer.shouldGet = true Observer.shouldGet = true
var i = bindings.length bindings.forEach(catchDeps)
while (i--) { catchDeps(bindings[i]) }
Observer.shouldGet = false Observer.shouldGet = false
utils.log('\ndone.') utils.log('\ndone.')
} }
...@@ -2862,6 +2889,7 @@ module.exports = { ...@@ -2862,6 +2889,7 @@ module.exports = {
'if' : require('./if'), 'if' : require('./if'),
'with' : require('./with'), 'with' : require('./with'),
html : require('./html'), html : require('./html'),
style : require('./style'),
attr: function (value) { attr: function (value) {
this.el.setAttribute(this.arg, value) this.el.setAttribute(this.arg, value)
...@@ -2983,10 +3011,7 @@ var mutationHandlers = { ...@@ -2983,10 +3011,7 @@ var mutationHandlers = {
}, },
unshift: function (m) { unshift: function (m) {
var i, l = m.args.length m.args.forEach(this.buildItem, this)
for (i = 0; i < l; i++) {
this.buildItem(m.args[i], i)
}
}, },
shift: function () { shift: function () {
...@@ -3068,7 +3093,7 @@ module.exports = { ...@@ -3068,7 +3093,7 @@ module.exports = {
var method = mutation.method var method = mutation.method
mutationHandlers[method].call(self, mutation) mutationHandlers[method].call(self, mutation)
if (method !== 'push' && method !== 'pop') { if (method !== 'push' && method !== 'pop') {
self.updateIndexes() self.updateIndex()
} }
if (method === 'push' || method === 'unshift' || method === 'splice') { if (method === 'push' || method === 'unshift' || method === 'splice') {
self.changed() self.changed()
...@@ -3102,9 +3127,7 @@ module.exports = { ...@@ -3102,9 +3127,7 @@ module.exports = {
// create child-vms and append to DOM // create child-vms and append to DOM
if (collection.length) { if (collection.length) {
for (var i = 0, l = collection.length; i < l; i++) { collection.forEach(this.buildItem, this)
this.buildItem(collection[i], i)
}
if (!init) this.changed() if (!init) this.changed()
} }
}, },
...@@ -3132,32 +3155,33 @@ module.exports = { ...@@ -3132,32 +3155,33 @@ module.exports = {
*/ */
buildItem: function (data, index) { buildItem: function (data, index) {
var node = this.el.cloneNode(true), var el = this.el.cloneNode(true),
ctn = this.container, ctn = this.container,
vms = this.vms,
col = this.collection,
ref, item ref, item
// append node into DOM first // append node into DOM first
// so v-if can get access to parentNode // so v-if can get access to parentNode
if (data) { if (data) {
ref = this.vms.length > index ref = vms.length > index
? this.vms[index].$el ? vms[index].$el
: this.ref : this.ref
// make sure it works with v-if // make sure it works with v-if
if (!ref.parentNode) ref = ref.vue_ref if (!ref.parentNode) ref = ref.vue_ref
// process transition info before appending // process transition info before appending
node.vue_trans = utils.attr(node, 'transition', true) el.vue_trans = utils.attr(el, 'transition', true)
transition(node, 1, function () { transition(el, 1, function () {
ctn.insertBefore(node, ref) ctn.insertBefore(el, ref)
}, this.compiler) }, this.compiler)
} }
item = new this.Ctor({ item = new this.Ctor({
el: node, el: el,
data: data, data: data,
compilerOptions: { compilerOptions: {
repeat: true, repeat: true,
repeatIndex: index, repeatIndex: index,
repeatCollection: this.collection,
parentCompiler: this.compiler, parentCompiler: this.compiler,
delegator: ctn delegator: ctn
} }
...@@ -3168,14 +3192,19 @@ module.exports = { ...@@ -3168,14 +3192,19 @@ module.exports = {
// let's remove it... // let's remove it...
item.$destroy() item.$destroy()
} else { } else {
this.vms.splice(index, 0, item) vms.splice(index, 0, item)
// in case `$destroy` is called directly on a repeated vm
// make sure the vm's data is properly removed
item.$compiler.observer.on('hook:afterDestroy', function () {
col.remove(data)
})
} }
}, },
/** /**
* Update index of each item after a mutation * Update index of each item after a mutation
*/ */
updateIndexes: function () { updateIndex: function () {
var i = this.vms.length var i = this.vms.length
while (i--) { while (i--) {
this.vms[i].$data.$index = i this.vms[i].$data.$index = i
...@@ -3493,6 +3522,44 @@ module.exports = { ...@@ -3493,6 +3522,44 @@ module.exports = {
} }
} }
}); });
require.register("vue/src/directives/style.js", function(exports, require, module){
var camelRE = /-([a-z])/g,
prefixes = ['webkit', 'moz', 'ms']
function camelReplacer (m) {
return m[1].toUpperCase()
}
module.exports = {
bind: function () {
var prop = this.arg,
first = prop.charAt(0)
if (first === '$') {
// properties that start with $ will be auto-prefixed
prop = prop.slice(1)
this.prefixed = true
} else if (first === '-') {
// normal starting hyphens should not be converted
prop = prop.slice(1)
}
this.prop = prop.replace(camelRE, camelReplacer)
},
update: function (value) {
var prop = this.prop
this.el.style[prop] = value
if (this.prefixed) {
prop = prop.charAt(0).toUpperCase() + prop.slice(1)
var i = prefixes.length
while (i--) {
this.el.style[prefixes[i] + prop] = value
}
}
}
}
});
require.alias("component-emitter/index.js", "vue/deps/emitter/index.js"); require.alias("component-emitter/index.js", "vue/deps/emitter/index.js");
require.alias("component-emitter/index.js", "emitter/index.js"); require.alias("component-emitter/index.js", "emitter/index.js");
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<ul id="todo-list"> <ul id="todo-list">
<li class="todo" v-repeat="todos" v-if="filterTodo(this)" v-class="completed: completed, editing: this == editedTodo"> <li class="todo" v-repeat="todos" v-if="filterTodo(this)" v-class="completed: completed, editing: this == editedTodo">
<div class="view"> <div class="view">
<input class="toggle" type="checkbox" v-model="completed" v-on="change: toggleTodo(this)"> <input class="toggle" type="checkbox" v-model="completed" v-on="change: toggleTodo">
<label v-text="title" v-on="dblclick: editTodo(this)"></label> <label v-text="title" v-on="dblclick: editTodo(this)"></label>
<button class="destroy" v-on="click: removeTodo(this)"></button> <button class="destroy" v-on="click: removeTodo(this)"></button>
</div> </div>
......
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
// http://vuejs.org/guide/computed.html // http://vuejs.org/guide/computed.html
computed: { computed: {
remaining: function () { remaining: function () {
return this.todos.filter(this.filters.active).length return this.todos.filter(this.filters.active).length;
}, },
allDone: { allDone: {
$get: function () { $get: function () {
...@@ -98,7 +98,7 @@ ...@@ -98,7 +98,7 @@
todoStorage.save(); todoStorage.save();
}, },
toggleTodo: function (todo) { toggleTodo: function () {
todoStorage.save(); todoStorage.save();
}, },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment