Commit b7d77e8a authored by Pascal Hartig's avatar Pascal Hartig

CanJS: Updated to 1.1.5

parent 66100a72
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"jquery": "~1.9.1", "jquery": "~1.9.1",
"canjs": "~1.1.4", "canjs": "~1.1.5",
"canjs-localstorage": "~0.1.0", "canjs-localstorage": "~0.1.0",
"todomvc-common": "~0.1.4" "todomvc-common": "~0.1.6"
} }
} }
/*! /*!
* CanJS - 1.1.4 (2013-02-05) * CanJS - 1.1.5 (2013-03-27)
* http://canjs.us/ * http://canjs.us/
* Copyright (c) 2013 Bitovi * Copyright (c) 2013 Bitovi
* Licensed MIT * Licensed MIT
...@@ -496,7 +496,10 @@ ...@@ -496,7 +496,10 @@
}, },
bind = $method('addEvent'), bind = $method('addEvent'),
unbind = $method('removeEvent'), unbind = $method('removeEvent'),
attrParts = function (attr) { attrParts = function (attr, keepKey) {
if (keepKey) {
return [attr];
}
return can.isArray(attr) ? attr : ("" + attr).split("."); return can.isArray(attr) ? attr : ("" + attr).split(".");
}, },
// Which batch of events this is for -- might not want to send multiple // Which batch of events this is for -- might not want to send multiple
...@@ -544,7 +547,7 @@ ...@@ -544,7 +547,7 @@
can.trigger.apply(can, args); can.trigger.apply(can, args);
}); });
can.each(callbacks, function (cb) { can.each(callbacks, function (cb) {
cb; cb();
}); });
} }
}, },
...@@ -555,13 +558,12 @@ ...@@ -555,13 +558,12 @@
if (transactions == 0) { if (transactions == 0) {
return can.trigger(item, event, args); return can.trigger(item, event, args);
} else { } else {
event = typeof event === "string" ? {
type: event
} : event;
event.batchNum = batchNum;
batchEvents.push([ batchEvents.push([
item, item, event, args]);
{
type: event,
batchNum: batchNum
},
args]);
} }
} }
}, },
...@@ -622,18 +624,22 @@ ...@@ -622,18 +624,22 @@
}, },
removeAttr: function (attr) { removeAttr: function (attr) {
// Info if this is List or not
var isList = this instanceof can.Observe.List,
// Convert the `attr` into parts (if nested). // Convert the `attr` into parts (if nested).
var parts = attrParts(attr), parts = attrParts(attr),
// The actual property to remove. // The actual property to remove.
prop = parts.shift(), prop = parts.shift(),
// The current value. // The current value.
current = this._data[prop]; current = isList ? this[prop] : this._data[prop];
// If we have more parts, call `removeAttr` on that part. // If we have more parts, call `removeAttr` on that part.
if (parts.length) { if (parts.length) {
return current.removeAttr(parts) return current.removeAttr(parts)
} else { } else {
if (prop in this._data) { if (isList) {
this.splice(prop, 1)
} else if (prop in this._data) {
// Otherwise, `delete`. // Otherwise, `delete`.
delete this._data[prop]; delete this._data[prop];
// Create the event. // Create the event.
...@@ -650,6 +656,11 @@ ...@@ -650,6 +656,11 @@
}, },
// Reads a property from the `object`. // Reads a property from the `object`.
_get: function (attr) { _get: function (attr) {
var value = typeof attr === 'string' && !! ~attr.indexOf('.') && this.__get(attr);
if (value) {
return value;
}
// break up the attr (`"foo.bar"`) into `["foo","bar"]` // break up the attr (`"foo.bar"`) into `["foo","bar"]`
var parts = attrParts(attr), var parts = attrParts(attr),
// get the value of the first attr name (`"foo"`) // get the value of the first attr name (`"foo"`)
...@@ -673,9 +684,9 @@ ...@@ -673,9 +684,9 @@
// Sets `attr` prop as value on this object where. // Sets `attr` prop as value on this object where.
// `attr` - Is a string of properties or an array of property values. // `attr` - Is a string of properties or an array of property values.
// `value` - The raw value to set. // `value` - The raw value to set.
_set: function (attr, value) { _set: function (attr, value, keepKey) {
// Convert `attr` to attr parts (if it isn't already). // Convert `attr` to attr parts (if it isn't already).
var parts = attrParts(attr), var parts = attrParts(attr, keepKey),
// The immediate prop we are setting. // The immediate prop we are setting.
prop = parts.shift(), prop = parts.shift(),
// The current value. // The current value.
...@@ -789,7 +800,7 @@ ...@@ -789,7 +800,7 @@
// Add remaining props. // Add remaining props.
for (var prop in props) { for (var prop in props) {
newVal = props[prop]; newVal = props[prop];
this._set(prop, newVal) this._set(prop, newVal, true)
} }
Observe.stopBatch() Observe.stopBatch()
return this; return this;
...@@ -814,7 +825,11 @@ ...@@ -814,7 +825,11 @@
this.length = 0; this.length = 0;
can.cid(this, ".observe") can.cid(this, ".observe")
this._init = 1; this._init = 1;
if (can.isDeferred(instances)) {
this.replace(instances)
} else {
this.push.apply(this, can.makeArray(instances || [])); this.push.apply(this, can.makeArray(instances || []));
}
this.bind('change' + this._cid, can.proxy(this._changes, this)); this.bind('change' + this._cid, can.proxy(this._changes, this));
can.extend(this, options); can.extend(this, options);
delete this._init; delete this._init;
...@@ -859,14 +874,14 @@ ...@@ -859,14 +874,14 @@
for (i = 2; i < args.length; i++) { for (i = 2; i < args.length; i++) {
var val = args[i]; var val = args[i];
if (canMakeObserve(val)) { if (canMakeObserve(val)) {
args[i] = hookupBubble(val, "*", this) args[i] = hookupBubble(val, "*", this, this.constructor.Observe, this.constructor)
} }
} }
if (howMany === undefined) { if (howMany === undefined) {
howMany = args[1] = this.length - index; howMany = args[1] = this.length - index;
} }
var removed = splice.apply(this, args); var removed = splice.apply(this, args);
can.Observe.startBatch() can.Observe.startBatch();
if (howMany > 0) { if (howMany > 0) {
this._triggerChange("" + index, "remove", undefined, removed); this._triggerChange("" + index, "remove", undefined, removed);
unhookup(removed, this._cid); unhookup(removed, this._cid);
...@@ -950,7 +965,8 @@ ...@@ -950,7 +965,8 @@
// Call the original method. // Call the original method.
res = orig.apply(this, args); res = orig.apply(this, args);
if (!this.comparator || !args.length) { if (!this.comparator || args.length) {
this._triggerChange("" + len, "add", args, undefined); this._triggerChange("" + len, "add", args, undefined);
} }
...@@ -1001,6 +1017,9 @@ ...@@ -1001,6 +1017,9 @@
join: [].join, join: [].join,
reverse: [].reverse,
slice: function () { slice: function () {
var temp = Array.prototype.slice.apply(this, arguments); var temp = Array.prototype.slice.apply(this, arguments);
return new this.constructor(temp); return new this.constructor(temp);
...@@ -1081,7 +1100,7 @@ ...@@ -1081,7 +1100,7 @@
// If we get a string, handle it. // If we get a string, handle it.
if (typeof ajaxOb == "string") { if (typeof ajaxOb == "string") {
// If there's a space, it's probably the type. // If there's a space, it's probably the type.
var parts = ajaxOb.split(/\s/); var parts = ajaxOb.split(/\s+/);
params.url = parts.pop(); params.url = parts.pop();
if (parts.length) { if (parts.length) {
params.type = parts.pop(); params.type = parts.pop();
...@@ -1104,7 +1123,18 @@ ...@@ -1104,7 +1123,18 @@
}, params)); }, params));
}, },
makeRequest = function (self, type, success, error, method) { makeRequest = function (self, type, success, error, method) {
var deferred, args = [self.serialize()], var args;
// if we pass an array as `self` it it means we are coming from
// the queued request, and we're passing already serialized data
// self's signature will be: [self, serializedData]
if (can.isArray(self)) {
args = self[1];
self = self[0];
} else {
args = self.serialize();
}
args = [args];
var deferred,
// The model. // The model.
model = self.constructor, model = self.constructor,
jqXHR; jqXHR;
...@@ -1250,6 +1280,7 @@ ...@@ -1250,6 +1280,7 @@
this._url = this._shortName + "/{" + this.id + "}" this._url = this._shortName + "/{" + this.id + "}"
}, },
_ajax: ajaxMaker, _ajax: ajaxMaker,
_makeRequest: makeRequest,
_clean: function () { _clean: function () {
this._reqs--; this._reqs--;
if (!this._reqs) { if (!this._reqs) {
...@@ -1418,6 +1449,11 @@ ...@@ -1418,6 +1449,11 @@
// Call event on the instance // Call event on the instance
can.trigger(this, funcName); can.trigger(this, funcName);
// triggers change event that bubble's like
// handler( 'change','1.destroyed' ). This is used
// to remove items on destroyed from Model Lists.
// but there should be a better way.
can.trigger(this, "change", funcName) can.trigger(this, "change", funcName)
...@@ -1475,6 +1511,7 @@ ...@@ -1475,6 +1511,7 @@
value = prep(parts.join("=")), value = prep(parts.join("=")),
current = data; current = data;
if (key) {
parts = key.match(keyBreaker); parts = key.match(keyBreaker);
for (var j = 0, l = parts.length - 1; j < l; j++) { for (var j = 0, l = parts.length - 1; j < l; j++) {
...@@ -1490,6 +1527,7 @@ ...@@ -1490,6 +1527,7 @@
} else { } else {
current[lastPart] = value; current[lastPart] = value;
} }
}
}); });
} }
return data; return data;
...@@ -2131,8 +2169,10 @@ ...@@ -2131,8 +2169,10 @@
} }
if (can.isDeferred(result)) { if (can.isDeferred(result)) {
result.done(function (result, data) { result.then(function (result, data) {
deferred.resolve.call(deferred, pipe(result), data); deferred.resolve.call(deferred, pipe(result), data);
}, function () {
deferred.fail.apply(deferred, arguments);
}); });
return deferred; return deferred;
} }
...@@ -2277,6 +2317,8 @@ ...@@ -2277,6 +2317,8 @@
// If there's a `callback`, call it back with the result. // If there's a `callback`, call it back with the result.
callback && callback(result, dataCopy); callback && callback(result, dataCopy);
}, function () {
deferred.reject.apply(deferred, arguments)
}); });
// Return the deferred... // Return the deferred...
return deferred; return deferred;
...@@ -2537,7 +2579,7 @@ ...@@ -2537,7 +2579,7 @@
// Calls `callback(newVal, oldVal)` everytime an observed property // Calls `callback(newVal, oldVal)` everytime an observed property
// called within `getterSetter` is changed and creates a new result of `getterSetter`. // called within `getterSetter` is changed and creates a new result of `getterSetter`.
// Also returns an object that can teardown all event handlers. // Also returns an object that can teardown all event handlers.
computeBinder = function (getterSetter, context, callback) { computeBinder = function (getterSetter, context, callback, computeState) {
// track what we are observing // track what we are observing
var observing = {}, var observing = {},
// a flag indicating if this observe/attr pair is already bound // a flag indicating if this observe/attr pair is already bound
...@@ -2559,6 +2601,11 @@ ...@@ -2559,6 +2601,11 @@
// when a property value is changed // when a property value is changed
var onchanged = function (ev) { var onchanged = function (ev) {
// If the compute is no longer bound (because the same change event led to an unbind)
// then do not call getValueAndBind, or we will leak bindings.
if (computeState && !computeState.bound) {
return;
}
if (ev.batchNum === undefined || ev.batchNum !== batchNum) { if (ev.batchNum === undefined || ev.batchNum !== batchNum) {
// store the old value // store the old value
var oldValue = data.value, var oldValue = data.value,
...@@ -2673,14 +2720,18 @@ ...@@ -2673,14 +2720,18 @@
computed.isComputed = true; computed.isComputed = true;
can.cid(computed, "compute") can.cid(computed, "compute")
var computeState = {
bound: false
};
computed.bind = function (ev, handler) { computed.bind = function (ev, handler) {
can.addEvent.apply(computed, arguments); can.addEvent.apply(computed, arguments);
if (bindings === 0 && canbind) { if (bindings === 0 && canbind) {
computeState.bound = true;
// setup live-binding // setup live-binding
computedData = computeBinder(getterSetter, context || this, function (newValue, oldValue) { computedData = computeBinder(getterSetter, context || this, function (newValue, oldValue) {
can.Observe.triggerBatch(computed, "change", [newValue, oldValue]) can.Observe.triggerBatch(computed, "change", [newValue, oldValue])
}); }, computeState);
} }
bindings++; bindings++;
} }
...@@ -2690,6 +2741,7 @@ ...@@ -2690,6 +2741,7 @@
bindings--; bindings--;
if (bindings === 0 && canbind) { if (bindings === 0 && canbind) {
computedData.teardown(); computedData.teardown();
computeState.bound = false;
} }
}; };
...@@ -2728,6 +2780,7 @@ ...@@ -2728,6 +2780,7 @@
i++; i++;
} }
} }
return '';
}, },
bracketNum = function (content) { bracketNum = function (content) {
return (--content.split("{").length) - (--content.split("}").length); return (--content.split("{").length) - (--content.split("}").length);
...@@ -2878,6 +2931,8 @@ ...@@ -2878,6 +2931,8 @@
tagName = '', tagName = '',
// stack of tagNames // stack of tagNames
tagNames = [], tagNames = [],
// Pop from tagNames?
popTagName = false,
// Declared here. // Declared here.
bracketCount, i = 0, bracketCount, i = 0,
token, tmap = this.tokenMap; token, tmap = this.tokenMap;
...@@ -2935,13 +2990,13 @@ ...@@ -2935,13 +2990,13 @@
case '>': case '>':
htmlTag = 0; htmlTag = 0;
// content.substr(-1) doesn't work in IE7/8 // content.substr(-1) doesn't work in IE7/8
var emptyElement = content.substr(content.length - 1) == "/"; var emptyElement = content.substr(content.length - 1) == "/" || content.substr(content.length - 2) == "--";
// if there was a magic tag // if there was a magic tag
// or it's an element that has text content between its tags, // or it's an element that has text content between its tags,
// but content is not other tags add a hookup // but content is not other tags add a hookup
// TODO: we should only add `can.EJS.pending()` if there's a magic tag // TODO: we should only add `can.EJS.pending()` if there's a magic tag
// within the html tags. // within the html tags.
if (magicInTag || tagToContentPropMap[tagNames[tagNames.length - 1]]) { if (magicInTag || !popTagName && tagToContentPropMap[tagNames[tagNames.length - 1]]) {
// make sure / of /> is on the left of pending // make sure / of /> is on the left of pending
if (emptyElement) { if (emptyElement) {
put(content.substr(0, content.length - 1), ",can.view.pending(),\"/>\""); put(content.substr(0, content.length - 1), ",can.view.pending(),\"/>\"");
...@@ -2949,15 +3004,18 @@ ...@@ -2949,15 +3004,18 @@
put(content, ",can.view.pending(),\">\""); put(content, ",can.view.pending(),\">\"");
} }
content = ''; content = '';
magicInTag = 0;
} else { } else {
content += token; content += token;
} }
// if it's a tag like <input/> // if it's a tag like <input/>
if (emptyElement) { if (emptyElement || popTagName) {
// remove the current tag in the stack // remove the current tag in the stack
tagNames.pop(); tagNames.pop();
// set the current tag to the previous parent // set the current tag to the previous parent
tagName = tagNames[tagNames.length - 1]; tagName = tagNames[tagNames.length - 1];
// Don't pop next time
popTagName = false;
} }
break; break;
case "'": case "'":
...@@ -2979,10 +3037,11 @@ ...@@ -2979,10 +3037,11 @@
// Track the current tag // Track the current tag
if (lastToken === '<') { if (lastToken === '<') {
tagName = token.split(/\s/)[0]; tagName = token.split(/\s/)[0];
if (tagName.indexOf("/") === 0 && tagNames.pop() === tagName.substr(1)) { if (tagName.indexOf("/") === 0 && tagNames[tagNames.length - 1] === tagName.substr(1)) {
// set tagName to the last tagName // set tagName to the last tagName
// if there are no more tagNames, we'll rely on getTag. // if there are no more tagNames, we'll rely on getTag.
tagName = tagNames[tagNames.length - 1]; tagName = tagNames[tagNames.length - 1];
popTagName = true;
} else { } else {
tagNames.push(tagName); tagNames.push(tagName);
} }
...@@ -3180,7 +3239,7 @@ ...@@ -3180,7 +3239,7 @@
}, },
getAttr = function (el, attrName) { getAttr = function (el, attrName) {
// Default to a blank string for IE7/8 // Default to a blank string for IE7/8
return (attrMap[attrName] ? el[attrMap[attrName]] : el.getAttribute(attrName)) || ''; return (attrMap[attrName] && el[attrMap[attrName]] ? el[attrMap[attrName]] : el.getAttribute(attrName)) || '';
}, },
removeAttr = function (el, attrName) { removeAttr = function (el, attrName) {
if (can.inArray(attrName, bool) > -1) { if (can.inArray(attrName, bool) > -1) {
...@@ -3381,8 +3440,18 @@ ...@@ -3381,8 +3440,18 @@
var parent = getParentNode(el, parentNode), var parent = getParentNode(el, parentNode),
node = document.createTextNode(binding.value); node = document.createTextNode(binding.value);
// When iterating through an Observe.List with no DOM
// elements containing the individual items, the parent
// is sometimes incorrect not the true parent of the
// source element. (#153)
if (el.parentNode !== parent) {
parent = el.parentNode;
parent.insertBefore(node, el); parent.insertBefore(node, el);
parent.removeChild(el); parent.removeChild(el);
} else {
parent.insertBefore(node, el);
parent.removeChild(el);
}
setupTeardownOnDestroy(parent); setupTeardownOnDestroy(parent);
} : } :
// If we are not escaping, replace the parentNode with a // If we are not escaping, replace the parentNode with a
......
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