Commit bf18ccb5 authored by Cheng Lou's avatar Cheng Lou

[React] New react-backbone todomvc with fixes and React version bump

Like #855, bumped React version (along with all the other deps) and made
some fixes.
parent 904aa5a8
......@@ -2,11 +2,11 @@
"name": "todomvc-react-backbone",
"version": "0.0.0",
"dependencies": {
"react": "~0.8.0",
"todomvc-common": "~0.1.9",
"backbone": "~1.1.0",
"react": "~0.9.0",
"backbone": "~1.1.2",
"backbone.localstorage": "~1.1.7",
"jquery": "~2.0.3",
"underscore": "~1.5.2"
"jquery": "~2.1.0",
"todomvc-common": "~0.1.9",
"underscore": "~1.6.0"
}
}
// Backbone.js 1.1.1
// Backbone.js 1.1.2
// (c) 2010-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Backbone may be freely distributed under the MIT license.
......@@ -17,9 +17,8 @@
// Next for Node.js or CommonJS. jQuery may not be needed as a module.
} else if (typeof exports !== 'undefined') {
var _ = require('underscore'), $;
try { $ = require('jquery'); } catch(e) {}
factory(root, exports, _, $);
var _ = require('underscore');
factory(root, exports, _);
// Finally, as a browser global.
} else {
......@@ -42,7 +41,7 @@
var splice = array.splice;
// Current version of the library. Keep in sync with `package.json`.
Backbone.VERSION = '1.1.1';
Backbone.VERSION = '1.1.2';
// For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
// the `$` variable.
......@@ -1293,7 +1292,7 @@
return optional ? match : '([^/?]+)';
})
.replace(splatParam, '([^?]*?)');
return new RegExp('^' + route + '(?:\\?(.*))?$');
return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$');
},
// Given a route, and a URL fragment that it matches, return the array of
......@@ -1450,7 +1449,7 @@
// but possibly useful for unit testing Routers.
stop: function() {
Backbone.$(window).off('popstate', this.checkUrl).off('hashchange', this.checkUrl);
clearInterval(this._checkUrlInterval);
if (this._checkUrlInterval) clearInterval(this._checkUrlInterval);
History.started = false;
},
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
// Underscore.js 1.5.2
// Underscore.js 1.6.0
// http://underscorejs.org
// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Underscore may be freely distributed under the MIT license.
(function() {
......@@ -65,7 +65,7 @@
}
// Current version.
_.VERSION = '1.5.2';
_.VERSION = '1.6.0';
// Collection Functions
// --------------------
......@@ -74,7 +74,7 @@
// Handles objects with the built-in `forEach`, arrays, and raw objects.
// Delegates to **ECMAScript 5**'s native `forEach` if available.
var each = _.each = _.forEach = function(obj, iterator, context) {
if (obj == null) return;
if (obj == null) return obj;
if (nativeForEach && obj.forEach === nativeForEach) {
obj.forEach(iterator, context);
} else if (obj.length === +obj.length) {
......@@ -87,6 +87,7 @@
if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
}
}
return obj;
};
// Return the results of applying the iterator to each element.
......@@ -152,10 +153,10 @@
};
// Return the first value which passes a truth test. Aliased as `detect`.
_.find = _.detect = function(obj, iterator, context) {
_.find = _.detect = function(obj, predicate, context) {
var result;
any(obj, function(value, index, list) {
if (iterator.call(context, value, index, list)) {
if (predicate.call(context, value, index, list)) {
result = value;
return true;
}
......@@ -166,33 +167,33 @@
// Return all the elements that pass a truth test.
// Delegates to **ECMAScript 5**'s native `filter` if available.
// Aliased as `select`.
_.filter = _.select = function(obj, iterator, context) {
_.filter = _.select = function(obj, predicate, context) {
var results = [];
if (obj == null) return results;
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context);
each(obj, function(value, index, list) {
if (iterator.call(context, value, index, list)) results.push(value);
if (predicate.call(context, value, index, list)) results.push(value);
});
return results;
};
// Return all the elements for which a truth test fails.
_.reject = function(obj, iterator, context) {
_.reject = function(obj, predicate, context) {
return _.filter(obj, function(value, index, list) {
return !iterator.call(context, value, index, list);
return !predicate.call(context, value, index, list);
}, context);
};
// Determine whether all of the elements match a truth test.
// Delegates to **ECMAScript 5**'s native `every` if available.
// Aliased as `all`.
_.every = _.all = function(obj, iterator, context) {
iterator || (iterator = _.identity);
_.every = _.all = function(obj, predicate, context) {
predicate || (predicate = _.identity);
var result = true;
if (obj == null) return result;
if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context);
each(obj, function(value, index, list) {
if (!(result = result && iterator.call(context, value, index, list))) return breaker;
if (!(result = result && predicate.call(context, value, index, list))) return breaker;
});
return !!result;
};
......@@ -200,13 +201,13 @@
// Determine if at least one element in the object matches a truth test.
// Delegates to **ECMAScript 5**'s native `some` if available.
// Aliased as `any`.
var any = _.some = _.any = function(obj, iterator, context) {
iterator || (iterator = _.identity);
var any = _.some = _.any = function(obj, predicate, context) {
predicate || (predicate = _.identity);
var result = false;
if (obj == null) return result;
if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context);
each(obj, function(value, index, list) {
if (result || (result = iterator.call(context, value, index, list))) return breaker;
if (result || (result = predicate.call(context, value, index, list))) return breaker;
});
return !!result;
};
......@@ -232,25 +233,19 @@
// Convenience version of a common use case of `map`: fetching a property.
_.pluck = function(obj, key) {
return _.map(obj, function(value){ return value[key]; });
return _.map(obj, _.property(key));
};
// Convenience version of a common use case of `filter`: selecting only objects
// containing specific `key:value` pairs.
_.where = function(obj, attrs, first) {
if (_.isEmpty(attrs)) return first ? void 0 : [];
return _[first ? 'find' : 'filter'](obj, function(value) {
for (var key in attrs) {
if (attrs[key] !== value[key]) return false;
}
return true;
});
_.where = function(obj, attrs) {
return _.filter(obj, _.matches(attrs));
};
// Convenience version of a common use case of `find`: getting the first object
// containing specific `key:value` pairs.
_.findWhere = function(obj, attrs) {
return _.where(obj, attrs, true);
return _.find(obj, _.matches(attrs));
};
// Return the maximum element or (element-based computation).
......@@ -260,13 +255,15 @@
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
return Math.max.apply(Math, obj);
}
if (!iterator && _.isEmpty(obj)) return -Infinity;
var result = {computed : -Infinity, value: -Infinity};
var result = -Infinity, lastComputed = -Infinity;
each(obj, function(value, index, list) {
var computed = iterator ? iterator.call(context, value, index, list) : value;
computed > result.computed && (result = {value : value, computed : computed});
if (computed > lastComputed) {
result = value;
lastComputed = computed;
}
});
return result.value;
return result;
};
// Return the minimum element (or element-based computation).
......@@ -274,16 +271,18 @@
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
return Math.min.apply(Math, obj);
}
if (!iterator && _.isEmpty(obj)) return Infinity;
var result = {computed : Infinity, value: Infinity};
var result = Infinity, lastComputed = Infinity;
each(obj, function(value, index, list) {
var computed = iterator ? iterator.call(context, value, index, list) : value;
computed < result.computed && (result = {value : value, computed : computed});
if (computed < lastComputed) {
result = value;
lastComputed = computed;
}
});
return result.value;
return result;
};
// Shuffle an array, using the modern version of the
// Shuffle an array, using the modern version of the
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
_.shuffle = function(obj) {
var rand;
......@@ -297,11 +296,12 @@
return shuffled;
};
// Sample **n** random values from an array.
// If **n** is not specified, returns a single random element from the array.
// Sample **n** random values from a collection.
// If **n** is not specified, returns a single random element.
// The internal `guard` argument allows it to work with `map`.
_.sample = function(obj, n, guard) {
if (arguments.length < 2 || guard) {
if (n == null || guard) {
if (obj.length !== +obj.length) obj = _.values(obj);
return obj[_.random(obj.length - 1)];
}
return _.shuffle(obj).slice(0, Math.max(0, n));
......@@ -309,12 +309,14 @@
// An internal function to generate lookup iterators.
var lookupIterator = function(value) {
return _.isFunction(value) ? value : function(obj){ return obj[value]; };
if (value == null) return _.identity;
if (_.isFunction(value)) return value;
return _.property(value);
};
// Sort the object's values by a criterion produced by an iterator.
_.sortBy = function(obj, value, context) {
var iterator = lookupIterator(value);
_.sortBy = function(obj, iterator, context) {
iterator = lookupIterator(iterator);
return _.pluck(_.map(obj, function(value, index, list) {
return {
value: value,
......@@ -334,9 +336,9 @@
// An internal function used for aggregate "group by" operations.
var group = function(behavior) {
return function(obj, value, context) {
return function(obj, iterator, context) {
var result = {};
var iterator = value == null ? _.identity : lookupIterator(value);
iterator = lookupIterator(iterator);
each(obj, function(value, index) {
var key = iterator.call(context, value, index, obj);
behavior(result, key, value);
......@@ -348,7 +350,7 @@
// Groups the object's values by a criterion. Pass either a string attribute
// to group by, or a function that returns the criterion.
_.groupBy = group(function(result, key, value) {
(_.has(result, key) ? result[key] : (result[key] = [])).push(value);
_.has(result, key) ? result[key].push(value) : result[key] = [value];
});
// Indexes the object's values by a criterion, similar to `groupBy`, but for
......@@ -367,7 +369,7 @@
// Use a comparator function to figure out the smallest index at which
// an object should be inserted so as to maintain order. Uses binary search.
_.sortedIndex = function(array, obj, iterator, context) {
iterator = iterator == null ? _.identity : lookupIterator(iterator);
iterator = lookupIterator(iterator);
var value = iterator.call(context, obj);
var low = 0, high = array.length;
while (low < high) {
......@@ -399,7 +401,9 @@
// allows it to work with `_.map`.
_.first = _.head = _.take = function(array, n, guard) {
if (array == null) return void 0;
return (n == null) || guard ? array[0] : slice.call(array, 0, n);
if ((n == null) || guard) return array[0];
if (n < 0) return [];
return slice.call(array, 0, n);
};
// Returns everything but the last entry of the array. Especially useful on
......@@ -414,11 +418,8 @@
// values in the array. The **guard** check allows it to work with `_.map`.
_.last = function(array, n, guard) {
if (array == null) return void 0;
if ((n == null) || guard) {
return array[array.length - 1];
} else {
return slice.call(array, Math.max(array.length - n, 0));
}
if ((n == null) || guard) return array[array.length - 1];
return slice.call(array, Math.max(array.length - n, 0));
};
// Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
......@@ -459,6 +460,16 @@
return _.difference(array, slice.call(arguments, 1));
};
// Split an array into two arrays: one whose elements all satisfy the given
// predicate, and one whose elements all do not satisfy the predicate.
_.partition = function(array, predicate) {
var pass = [], fail = [];
each(array, function(elem) {
(predicate(elem) ? pass : fail).push(elem);
});
return [pass, fail];
};
// Produce a duplicate-free version of the array. If the array has already
// been sorted, you have the option of using a faster algorithm.
// Aliased as `unique`.
......@@ -492,7 +503,7 @@
var rest = slice.call(arguments, 1);
return _.filter(_.uniq(array), function(item) {
return _.every(rest, function(other) {
return _.indexOf(other, item) >= 0;
return _.contains(other, item);
});
});
};
......@@ -507,7 +518,7 @@
// Zip together multiple lists into a single array -- elements that share
// an index go together.
_.zip = function() {
var length = _.max(_.pluck(arguments, "length").concat(0));
var length = _.max(_.pluck(arguments, 'length').concat(0));
var results = new Array(length);
for (var i = 0; i < length; i++) {
results[i] = _.pluck(arguments, '' + i);
......@@ -613,19 +624,27 @@
};
// Partially apply a function by creating a version that has had some of its
// arguments pre-filled, without changing its dynamic `this` context.
// arguments pre-filled, without changing its dynamic `this` context. _ acts
// as a placeholder, allowing any combination of arguments to be pre-filled.
_.partial = function(func) {
var args = slice.call(arguments, 1);
var boundArgs = slice.call(arguments, 1);
return function() {
return func.apply(this, args.concat(slice.call(arguments)));
var position = 0;
var args = boundArgs.slice();
for (var i = 0, length = args.length; i < length; i++) {
if (args[i] === _) args[i] = arguments[position++];
}
while (position < arguments.length) args.push(arguments[position++]);
return func.apply(this, args);
};
};
// Bind all of an object's methods to that object. Useful for ensuring that
// all callbacks defined on an object belong to it.
// Bind a number of an object's methods to that object. Remaining arguments
// are the method names to be bound. Useful for ensuring that all callbacks
// defined on an object belong to it.
_.bindAll = function(obj) {
var funcs = slice.call(arguments, 1);
if (funcs.length === 0) throw new Error("bindAll must be passed function names");
if (funcs.length === 0) throw new Error('bindAll must be passed function names');
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
return obj;
};
......@@ -664,12 +683,13 @@
var previous = 0;
options || (options = {});
var later = function() {
previous = options.leading === false ? 0 : new Date;
previous = options.leading === false ? 0 : _.now();
timeout = null;
result = func.apply(context, args);
context = args = null;
};
return function() {
var now = new Date;
var now = _.now();
if (!previous && options.leading === false) previous = now;
var remaining = wait - (now - previous);
context = this;
......@@ -679,6 +699,7 @@
timeout = null;
previous = now;
result = func.apply(context, args);
context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
......@@ -692,24 +713,33 @@
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
var timeout, args, context, timestamp, result;
var later = function() {
var last = _.now() - timestamp;
if (last < wait) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
if (!immediate) {
result = func.apply(context, args);
context = args = null;
}
}
};
return function() {
context = this;
args = arguments;
timestamp = new Date();
var later = function() {
var last = (new Date()) - timestamp;
if (last < wait) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
if (!immediate) result = func.apply(context, args);
}
};
timestamp = _.now();
var callNow = immediate && !timeout;
if (!timeout) {
timeout = setTimeout(later, wait);
}
if (callNow) result = func.apply(context, args);
if (callNow) {
result = func.apply(context, args);
context = args = null;
}
return result;
};
};
......@@ -731,11 +761,7 @@
// allowing you to adjust arguments, run code before and after, and
// conditionally execute the original function.
_.wrap = function(func, wrapper) {
return function() {
var args = [func];
push.apply(args, arguments);
return wrapper.apply(this, args);
};
return _.partial(wrapper, func);
};
// Returns a function that is the composition of a list of functions, each
......@@ -765,8 +791,9 @@
// Retrieve the names of an object's properties.
// Delegates to **ECMAScript 5**'s native `Object.keys`
_.keys = nativeKeys || function(obj) {
if (obj !== Object(obj)) throw new TypeError('Invalid object');
_.keys = function(obj) {
if (!_.isObject(obj)) return [];
if (nativeKeys) return nativeKeys(obj);
var keys = [];
for (var key in obj) if (_.has(obj, key)) keys.push(key);
return keys;
......@@ -921,7 +948,8 @@
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
_.isFunction(bCtor) && (bCtor instanceof bCtor))) {
_.isFunction(bCtor) && (bCtor instanceof bCtor))
&& ('constructor' in a && 'constructor' in b)) {
return false;
}
// Add the first object to the stack of traversed objects.
......@@ -1061,6 +1089,30 @@
return value;
};
_.constant = function(value) {
return function () {
return value;
};
};
_.property = function(key) {
return function(obj) {
return obj[key];
};
};
// Returns a predicate for checking whether an object has a given set of `key:value` pairs.
_.matches = function(attrs) {
return function(obj) {
if (obj === attrs) return true; //avoid comparing an object to itself.
for (var key in attrs) {
if (attrs[key] !== obj[key])
return false;
}
return true;
}
};
// Run a function **n** times.
_.times = function(n, iterator, context) {
var accum = Array(Math.max(0, n));
......@@ -1077,6 +1129,9 @@
return min + Math.floor(Math.random() * (max - min + 1));
};
// A (possibly faster) way to get the current timestamp as an integer.
_.now = Date.now || function() { return new Date().getTime(); };
// List of HTML entities for escaping.
var entityMap = {
escape: {
......@@ -1273,4 +1328,16 @@
});
// AMD registration happens at the end for compatibility with AMD loaders
// that may not enforce next-turn semantics on modules. Even though general
// practice for AMD registration is to be anonymous, underscore registers
// as a named module because, like jQuery, it is a base library that is
// popular enough to be bundled in a third party lib, but not be part of
// an AMD load request. Those cases could generate an error when an
// anonymous define() is called outside of a loader request.
if (typeof define === 'function' && define.amd) {
define('underscore', [], function() {
return _;
});
}
}).call(this);
......@@ -17,7 +17,7 @@
<script src="bower_components/todomvc-common/base.js"></script>
<script src="bower_components/react/react-with-addons.js"></script>
<script src="bower_components/react/JSXTransformer.js"></script>
<script src="bower_components/jquery/jquery.js"></script>
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/underscore/underscore.js"></script>
<script src="bower_components/backbone/backbone.js"></script>
<script src="bower_components/backbone.localStorage/backbone.localStorage.js"></script>
......
......@@ -74,7 +74,6 @@ var app = app || {};
Backbone.history.start();
this.props.todos.fetch();
this.refs.newField.getDOMNode().focus();
},
componentDidUpdate: function () {
......@@ -203,6 +202,7 @@ var app = app || {};
id="new-todo"
placeholder="What needs to be done?"
onKeyDown={this.handleNewTodoKeyDown}
autoFocus={true}
/>
</header>
{main}
......
......@@ -21,7 +21,7 @@ var app = app || {};
<button
id="clear-completed"
onClick={this.props.onClearCompleted}>
{''}Clear completed ({this.props.completedCount}){''}
Clear completed ({this.props.completedCount})
</button>
);
}
......@@ -32,8 +32,7 @@ var app = app || {};
return (
<footer id="footer">
<span id="todo-count">
<strong>{this.props.count}</strong>
{' '}{activeTodoWord}{' '}left{''}
<strong>{this.props.count}</strong> {activeTodoWord} left
</span>
<ul id="filters">
<li>
......
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