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
License: MIT
*/
......@@ -509,8 +509,13 @@ function inheritOptions (child, parent, topLevel) {
parentVal = parent[key],
type = utils.typeOf(val)
if (topLevel && type === 'Function' && parentVal) {
// merge hook functions
child[key] = mergeHook(val, 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 && type === 'Object') {
// merge toplevel object options
inheritOptions(val, parentVal)
......@@ -522,17 +527,6 @@ function inheritOptions (child, parent, topLevel) {
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
});
require.register("vue/src/emitter.js", function(exports, require, module){
......@@ -846,7 +840,14 @@ var Emitter = require('./emitter'),
makeHash = utils.hash,
extend = utils.extend,
def = utils.defProtected,
hasOwn = Object.prototype.hasOwnProperty
hasOwn = Object.prototype.hasOwnProperty,
// hooks to register
hooks = [
'created', 'ready',
'beforeDestroy', 'afterDestroy',
'enteredView', 'leftView'
]
/**
* The DOM compiler
......@@ -914,7 +915,7 @@ function Compiler (vm, options) {
}
// beforeCompile hook
compiler.execHook('beforeCompile', 'created')
compiler.execHook('created')
// the user might have set some props on the vm
// so copy it back to the data...
......@@ -951,9 +952,7 @@ function Compiler (vm, options) {
compiler.compile(el, true)
// bind deferred directives (child components)
for (var i = 0, l = compiler.deferred.length; i < l; i++) {
compiler.bindDirective(compiler.deferred[i])
}
compiler.deferred.forEach(compiler.bindDirective, compiler)
// extract dependencies for computed properties
compiler.parseDeps()
......@@ -962,7 +961,7 @@ function Compiler (vm, options) {
compiler.init = false
// post compile / ready hook
compiler.execHook('afterCompile', 'ready')
compiler.execHook('ready')
}
var CompilerProto = Compiler.prototype
......@@ -1011,11 +1010,13 @@ CompilerProto.setupElement = function (options) {
* 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()
// a hash to hold event proxies for each root level key
......@@ -1038,6 +1039,27 @@ CompilerProto.setupObserver = function () {
check(key)
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) {
if (!bindings[key]) {
......@@ -1090,7 +1112,7 @@ CompilerProto.compile = function (node, root) {
}
// 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)
if (directive) {
......@@ -1130,7 +1152,7 @@ CompilerProto.compile = function (node, root) {
*/
CompilerProto.compileNode = function (node) {
var i, j,
attrs = node.attributes,
attrs = slice.call(node.attributes),
prefix = config.prefix + '-'
// parse if has attributes
if (attrs && attrs.length) {
......@@ -1171,10 +1193,7 @@ CompilerProto.compileNode = function (node) {
}
// recursively compile childNodes
if (node.childNodes.length) {
var nodes = slice.call(node.childNodes)
for (i = 0, j = nodes.length; i < j; i++) {
this.compile(nodes[i])
}
slice.call(node.childNodes).forEach(this.compile, this)
}
}
......@@ -1189,7 +1208,7 @@ CompilerProto.compileTextNode = function (node) {
for (var i = 0, l = tokens.length; i < l; i++) {
token = tokens[i]
directive = null
directive = partialNodes = null
if (token.key) { // a binding
if (token.key.charAt(0) === '>') { // a partial
partialId = token.key.slice(1).trim()
......@@ -1215,6 +1234,8 @@ CompilerProto.compileTextNode = function (node) {
// insert node
node.parentNode.insertBefore(el, node)
// bind directive
if (directive) {
this.bindDirective(directive)
}
......@@ -1223,10 +1244,7 @@ CompilerProto.compileTextNode = function (node) {
// will change from the fragment to the correct parentNode.
// This could affect directives that need access to its element's parentNode.
if (partialNodes) {
for (var j = 0, k = partialNodes.length; j < k; j++) {
this.compile(partialNodes[j])
}
partialNodes = null
partialNodes.forEach(this.compile, this)
}
}
......@@ -1241,9 +1259,9 @@ CompilerProto.bindDirective = function (directive) {
// keep track of it so we can unbind() later
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.
if (directive.isEmpty) {
if (directive.isEmpty || directive.isLiteral) {
if (directive.bind) directive.bind()
return
}
......@@ -1417,14 +1435,12 @@ CompilerProto.getOption = function (type, id) {
}
/**
* Execute a user hook
* Emit lifecycle events to trigger hooks
*/
CompilerProto.execHook = function (id, alt) {
var opts = this.options,
hook = opts[id] || opts[alt]
if (hook) {
hook.call(this.vm, opts)
}
CompilerProto.execHook = function (event) {
event = 'hook:' + event
this.observer.emit(event)
this.emitter.emit(event)
}
/**
......@@ -1449,6 +1465,10 @@ CompilerProto.parseDeps = function () {
*/
CompilerProto.destroy = function () {
// avoid being called more than once
// this is irreversible!
if (this.destroyed) return
var compiler = this,
i, key, dir, instances, binding,
vm = compiler.vm,
......@@ -1459,10 +1479,6 @@ CompilerProto.destroy = function () {
compiler.execHook('beforeDestroy')
// unwatch
compiler.observer.off()
compiler.emitter.off()
// unbind all direcitves
i = directives.length
while (i--) {
......@@ -1511,7 +1527,13 @@ CompilerProto.destroy = function () {
vm.$remove()
}
this.destroyed = true
// emit destroy hook
compiler.execHook('afterDestroy')
// finally, unregister all listeners
compiler.observer.off()
compiler.emitter.off()
}
// Helpers --------------------------------------------------------------------
......@@ -2131,11 +2153,11 @@ var utils = require('./utils'),
// match up to the first single pipe, ignore those within quotes.
KEY_RE = /^(?:['"](?:\\.|[^'"])*['"]|\\.|[^\|]|\|\|)+/,
ARG_RE = /^([\w- ]+):(.+)$/,
ARG_RE = /^([\w-$ ]+):(.+)$/,
FILTERS_RE = /\|[^\|]+/g,
FILTER_TOKEN_RE = /[^\s']+|'[^']+'/g,
NESTING_RE = /^\$(parent|root)\./,
SINGLE_VAR_RE = /^[\w\.\$]+$/
SINGLE_VAR_RE = /^[\w\.$]+$/
/**
* Directive class
......@@ -2168,6 +2190,13 @@ function Directive (definition, expression, rawKey, compiler, node) {
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.rawKey = rawKey
......@@ -2178,8 +2207,7 @@ function Directive (definition, expression, rawKey, compiler, node) {
var filterExps = this.expression.slice(rawKey.length).match(FILTERS_RE)
if (filterExps) {
this.filters = []
var i = 0, l = filterExps.length, filter
for (; i < l; i++) {
for (var i = 0, l = filterExps.length, filter; i < l; i++) {
filter = parseFilter(filterExps[i], this.compiler)
if (filter) this.filters.push(filter)
}
......@@ -2560,8 +2588,7 @@ module.exports = {
parse: function (bindings) {
utils.log('\nparsing dependencies...')
Observer.shouldGet = true
var i = bindings.length
while (i--) { catchDeps(bindings[i]) }
bindings.forEach(catchDeps)
Observer.shouldGet = false
utils.log('\ndone.')
}
......@@ -2862,6 +2889,7 @@ module.exports = {
'if' : require('./if'),
'with' : require('./with'),
html : require('./html'),
style : require('./style'),
attr: function (value) {
this.el.setAttribute(this.arg, value)
......@@ -2983,10 +3011,7 @@ var mutationHandlers = {
},
unshift: function (m) {
var i, l = m.args.length
for (i = 0; i < l; i++) {
this.buildItem(m.args[i], i)
}
m.args.forEach(this.buildItem, this)
},
shift: function () {
......@@ -3068,7 +3093,7 @@ module.exports = {
var method = mutation.method
mutationHandlers[method].call(self, mutation)
if (method !== 'push' && method !== 'pop') {
self.updateIndexes()
self.updateIndex()
}
if (method === 'push' || method === 'unshift' || method === 'splice') {
self.changed()
......@@ -3102,9 +3127,7 @@ module.exports = {
// create child-vms and append to DOM
if (collection.length) {
for (var i = 0, l = collection.length; i < l; i++) {
this.buildItem(collection[i], i)
}
collection.forEach(this.buildItem, this)
if (!init) this.changed()
}
},
......@@ -3132,32 +3155,33 @@ module.exports = {
*/
buildItem: function (data, index) {
var node = this.el.cloneNode(true),
ctn = this.container,
var el = this.el.cloneNode(true),
ctn = this.container,
vms = this.vms,
col = this.collection,
ref, item
// append node into DOM first
// so v-if can get access to parentNode
if (data) {
ref = this.vms.length > index
? this.vms[index].$el
ref = vms.length > index
? vms[index].$el
: this.ref
// make sure it works with v-if
if (!ref.parentNode) ref = ref.vue_ref
// process transition info before appending
node.vue_trans = utils.attr(node, 'transition', true)
transition(node, 1, function () {
ctn.insertBefore(node, ref)
el.vue_trans = utils.attr(el, 'transition', true)
transition(el, 1, function () {
ctn.insertBefore(el, ref)
}, this.compiler)
}
item = new this.Ctor({
el: node,
el: el,
data: data,
compilerOptions: {
repeat: true,
repeatIndex: index,
repeatCollection: this.collection,
parentCompiler: this.compiler,
delegator: ctn
}
......@@ -3168,14 +3192,19 @@ module.exports = {
// let's remove it...
item.$destroy()
} 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
*/
updateIndexes: function () {
updateIndex: function () {
var i = this.vms.length
while (i--) {
this.vms[i].$data.$index = i
......@@ -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", "emitter/index.js");
......
......@@ -16,7 +16,7 @@
<ul id="todo-list">
<li class="todo" v-repeat="todos" v-if="filterTodo(this)" v-class="completed: completed, editing: this == editedTodo">
<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>
<button class="destroy" v-on="click: removeTodo(this)"></button>
</div>
......
......@@ -59,7 +59,7 @@
// http://vuejs.org/guide/computed.html
computed: {
remaining: function () {
return this.todos.filter(this.filters.active).length
return this.todos.filter(this.filters.active).length;
},
allDone: {
$get: function () {
......@@ -98,7 +98,7 @@
todoStorage.save();
},
toggleTodo: function (todo) {
toggleTodo: function () {
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