Update vendor/underscore and backbone.

Former-commit-id: 614926653b0b1669f8a5533666adb0aecbd46c03
This commit is contained in:
John-David Dalton
2012-07-19 01:32:47 -04:00
parent 9848ffb77f
commit d43ede3a11
3 changed files with 62 additions and 37 deletions

View File

@@ -295,7 +295,7 @@
// If the new and previous value differ, record the change. If not,
// then remove changes for this attribute.
if (!_.isEqual(prev[attr], val) || (_.has(now, attr) != _.has(prev, attr))) {
if (!_.isEqual(prev[attr], val) || (_.has(now, attr) !== _.has(prev, attr))) {
this.changed[attr] = val;
if (!options.silent) this._pending[attr] = true;
} else {
@@ -432,7 +432,7 @@
url: function() {
var base = getValue(this, 'urlRoot') || getValue(this.collection, 'url') || urlError();
if (this.isNew()) return base;
return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + encodeURIComponent(this.id);
return base + (base.charAt(base.length - 1) === '/' ? '' : '/') + encodeURIComponent(this.id);
},
// **parse** converts a response into the hash of attributes to be `set` on
@@ -555,7 +555,7 @@
var Collection = Backbone.Collection = function(models, options) {
options || (options = {});
if (options.model) this.model = options.model;
if (options.comparator !== undefined) this.comparator = options.comparator;
if (options.comparator !== void 0) this.comparator = options.comparator;
this._reset();
this.initialize.apply(this, arguments);
if (models) this.reset(models, {silent: true, parse: options.parse});
@@ -628,9 +628,7 @@
// Merge in duplicate models.
if (options.merge) {
for (i = 0, length = dups.length; i < length; i++) {
if (model = this._byId[dups[i].id]) {
model.set(dups[i], options);
}
if (model = this._byId[dups[i].id]) model.set(dups[i], options);
}
}
@@ -737,7 +735,7 @@
options || (options = {});
if (!this.comparator) throw new Error('Cannot sort a set without a comparator');
var boundComparator = _.bind(this.comparator, this);
if (this.comparator.length == 1) {
if (this.comparator.length === 1) {
this.models = this.sortBy(boundComparator);
} else {
this.models.sort(boundComparator);
@@ -771,7 +769,7 @@
// models to the collection instead of resetting.
fetch: function(options) {
options = options ? _.clone(options) : {};
if (options.parse === undefined) options.parse = true;
if (options.parse === void 0) options.parse = true;
var collection = this;
var success = options.success;
options.success = function(resp, status, xhr) {
@@ -842,9 +840,7 @@
// Internal method to remove a model's ties to a collection.
_removeReference: function(model) {
if (this == model.collection) {
delete model.collection;
}
if (this === model.collection) delete model.collection;
model.off('all', this._onModelEvent, this);
},
@@ -853,10 +849,8 @@
// events simply proxy through. "add" and "remove" events that originate
// in other collections are ignored.
_onModelEvent: function(event, model, collection, options) {
if ((event == 'add' || event == 'remove') && collection != this) return;
if (event == 'destroy') {
this.remove(model, options);
}
if ((event === 'add' || event === 'remove') && collection !== this) return;
if (event === 'destroy') this.remove(model, options);
if (model && event === 'change:' + model.idAttribute) {
delete this._byId[model.previous(model.idAttribute)];
if (model.id != null) this._byId[model.id] = model;
@@ -1048,7 +1042,7 @@
// opened by a non-pushState browser.
this.fragment = fragment;
var loc = this.location;
var atRoot = (loc.pathname == this.options.root) && !loc.search;
var atRoot = (loc.pathname === this.options.root) && !loc.search;
// If we've started off with a route from a `pushState`-enabled browser,
// but we're currently in a browser that doesn't support it...
@@ -1065,9 +1059,7 @@
this.history.replaceState({}, document.title, loc.protocol + '//' + loc.host + this.options.root + this.fragment);
}
if (!this.options.silent) {
return this.loadUrl();
}
if (!this.options.silent) return this.loadUrl();
},
// Disable Backbone.history, perhaps temporarily. Not useful in a real app,
@@ -1088,10 +1080,10 @@
// calls `loadUrl`, normalizing across the hidden iframe.
checkUrl: function(e) {
var current = this.getFragment();
if (current == this.fragment && this.iframe) {
if (current === this.fragment && this.iframe) {
current = this.getFragment(this.getHash(this.iframe));
}
if (current == this.fragment) return false;
if (current === this.fragment) return false;
if (this.iframe) this.navigate(current);
this.loadUrl() || this.loadUrl(this.getHash());
},
@@ -1121,9 +1113,9 @@
if (!History.started) return false;
if (!options || options === true) options = {trigger: options};
var frag = (fragment || '').replace(routeStripper, '');
if (this.fragment == frag) return;
if (this.fragment === frag) return;
this.fragment = frag;
var url = (frag.indexOf(this.options.root) != 0 ? this.options.root : '') + frag;
var url = (frag.indexOf(this.options.root) !== 0 ? this.options.root : '') + frag;
// If pushState is available, we use it to set the fragment as a real URL.
if (this._hasPushState) {
@@ -1133,7 +1125,7 @@
// fragment to store history.
} else if (this._wantsHashChange) {
this._updateHash(this.location, frag, options.replace);
if (this.iframe && (frag != this.getFragment(this.getHash(this.iframe)))) {
if (this.iframe && (frag !== this.getFragment(this.getHash(this.iframe)))) {
// Opening and closing the iframe tricks IE7 and earlier to push a
// history entry on hash-tag change. When replace is true, we don't
// want this.
@@ -1158,6 +1150,7 @@
location.hash = fragment;
}
}
});
// Backbone.View
@@ -1303,9 +1296,7 @@
// The self-propagating extend function that Backbone classes use.
var extend = function(protoProps, classProps) {
var child = inherits(this, protoProps, classProps);
child.extend = this.extend;
return child;
return inherits(this, protoProps, classProps);
};
// Set up inheritance for the model, collection, and view.
@@ -1352,7 +1343,7 @@
}
// Ensure that we have the appropriate request data.
if (!options.data && model && (method == 'create' || method == 'update')) {
if (!options.data && model && (method === 'create' || method === 'update')) {
params.contentType = 'application/json';
params.data = JSON.stringify(model);
}

View File

@@ -253,6 +253,18 @@ $(document).ready(function() {
equal(grouped['5'].join(' '), 'three seven eight');
});
test('collections: countBy', function() {
var parity = _.countBy([1, 2, 3, 4, 5], function(num){ return num % 2 == 0; });
equal(parity['true'], 2);
equal(parity['false'], 3);
var list = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"];
var grouped = _.countBy(list, 'length');
equal(grouped['3'], 4);
equal(grouped['4'], 3);
equal(grouped['5'], 3);
});
test('collections: sortedIndex', function() {
var numbers = [10, 20, 30, 40, 50], num = 35;
var indexForNum = _.sortedIndex(numbers, num);

View File

@@ -267,7 +267,7 @@
// Sort the object's values by a criterion produced by an iterator.
_.sortBy = function(obj, val, context) {
var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
var iterator = lookupIterator(obj, val);
return _.pluck(_.map(obj, function(value, index, list) {
return {
value : value,
@@ -281,16 +281,38 @@
}), 'value');
};
// An internal function to generate lookup iterators.
var lookupIterator = function(obj, val) {
return _.isFunction(val) ? val : function(obj) { return obj[val]; };
};
// An internal function used for aggregate "group by" operations.
var group = function(obj, val, behavior) {
var result = {};
var iterator = lookupIterator(obj, val);
each(obj, function(value, index) {
var key = iterator(value, index);
behavior(result, key, value);
});
return result;
};
// Groups the object's values by a criterion. Pass either a string attribute
// to group by, or a function that returns the criterion.
_.groupBy = function(obj, val) {
var result = {};
var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
each(obj, function(value, index) {
var key = iterator(value, index);
return group(obj, val, function(result, key, value) {
(result[key] || (result[key] = [])).push(value);
});
return result;
};
// Counts instances of an object that group by a certain criterion. Pass
// either a string attribute to count by, or a function that returns the
// criterion.
_.countBy = function(obj, val) {
return group(obj, val, function(result, key, value) {
result[key] || (result[key] = 0);
result[key]++;
});
};
// Use a comparator function to figure out the smallest index at which
@@ -709,7 +731,7 @@
};
// Internal recursive comparison function for `isEqual`.
function eq(a, b, stack) {
var eq = function(a, b, stack) {
// Identical objects are equal. `0 === -0`, but they aren't identical.
// See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
if (a === b) return a !== 0 || 1 / a == 1 / b;
@@ -794,7 +816,7 @@
// Remove the first object from the stack of traversed objects.
stack.pop();
return result;
}
};
// Perform a deep comparison to check if two objects are equal.
_.isEqual = function(a, b) {
@@ -832,7 +854,7 @@
return toString.call(obj) == '[object ' + name + ']';
};
});
// Define a fallback version of the method in browsers (ahem, IE), where
// there isn't any inspectable "Arguments" type.
if (!_.isArguments(arguments)) {