Commit 81c8ad00 authored by Addy Osmani's avatar Addy Osmani

Merge pull request #1045 from pgilad/patch-2

Ampersand.js - extract methods to collection
parents b3400aee 48054b8c
...@@ -14,13 +14,12 @@ module.exports = State.extend({ ...@@ -14,13 +14,12 @@ module.exports = State.extend({
initialize: function () { initialize: function () {
// Listen to changes to the todos collection that will // Listen to changes to the todos collection that will
// affect lengths we want to calculate. // affect lengths we want to calculate.
this.listenTo(this.todos, 'change:completed change:title add remove', this.handleTodosUpdate); this.listenTo(this.todos, 'change:completed add remove', this.handleTodosUpdate);
// We also want to calculate these values once on init // We also want to calculate these values once on init
this.handleTodosUpdate(); this.handleTodosUpdate();
// Listen for changes to `mode` so we can update // Listen for changes to `mode` so we can update
// the collection mode. // the collection mode.
this.on('change:mode', this.handleModeChange, this); this.listenTo(this, 'change:mode', this.handleModeChange);
}, },
collections: { collections: {
todos: Todos todos: Todos
...@@ -71,18 +70,17 @@ module.exports = State.extend({ ...@@ -71,18 +70,17 @@ module.exports = State.extend({
// so they're easy to listen to and bind to DOM // so they're easy to listen to and bind to DOM
// where needed. // where needed.
handleTodosUpdate: function () { handleTodosUpdate: function () {
var completed = 0; var total = this.todos.length;
var todos = this.todos; // use a method we defined on the collection itself
todos.each(function (todo) { // to count how many todos are completed
if (todo.completed) { var completed = this.todos.getCompletedCount();
completed++; // We use `set` here in order to update multiple attributes at once
} // It's possible to set directely using `this.completedCount = completed` ...
});
this.set({ this.set({
completedCount: completed, completedCount: completed,
activeCount: todos.length - completed, activeCount: total - completed,
totalCount: todos.length, totalCount: total,
allCompleted: todos.length === completed allCompleted: total === completed
}); });
}, },
handleModeChange: function () { handleModeChange: function () {
......
...@@ -30,6 +30,11 @@ module.exports = Collection.extend({ ...@@ -30,6 +30,11 @@ module.exports = Collection.extend({
// and persist on change // and persist on change
this.on('all', this.writeToLocalStorage, this); this.on('all', this.writeToLocalStorage, this);
}, },
getCompletedCount: function() {
return this.reduce(function(total, todo){
return todo.completed ? ++total : total;
}, 0);
},
// Helper for removing all completed items // Helper for removing all completed items
clearCompleted: function () { clearCompleted: function () {
var toRemove = this.filter(function (todo) { var toRemove = this.filter(function (todo) {
......
...@@ -43,13 +43,12 @@ module.exports = State.extend({ ...@@ -43,13 +43,12 @@ module.exports = State.extend({
initialize: function () { initialize: function () {
// Listen to changes to the todos collection that will // Listen to changes to the todos collection that will
// affect lengths we want to calculate. // affect lengths we want to calculate.
this.listenTo(this.todos, 'change:completed change:title add remove', this.handleTodosUpdate); this.listenTo(this.todos, 'change:completed add remove', this.handleTodosUpdate);
// We also want to calculate these values once on init // We also want to calculate these values once on init
this.handleTodosUpdate(); this.handleTodosUpdate();
// Listen for changes to `mode` so we can update // Listen for changes to `mode` so we can update
// the collection mode. // the collection mode.
this.on('change:mode', this.handleModeChange, this); this.listenTo(this, 'change:mode', this.handleModeChange);
}, },
collections: { collections: {
todos: Todos todos: Todos
...@@ -100,18 +99,17 @@ module.exports = State.extend({ ...@@ -100,18 +99,17 @@ module.exports = State.extend({
// so they're easy to listen to and bind to DOM // so they're easy to listen to and bind to DOM
// where needed. // where needed.
handleTodosUpdate: function () { handleTodosUpdate: function () {
var completed = 0; var total = this.todos.length;
var todos = this.todos; // use a method we defined on the collection itself
todos.each(function (todo) { // to count how many todos are completed
if (todo.completed) { var completed = this.todos.getCompletedCount();
completed++; // We use `set` here in order to update multiple attributes at once
} // It's possible to set directely using `this.completedCount = completed` ...
});
this.set({ this.set({
completedCount: completed, completedCount: completed,
activeCount: todos.length - completed, activeCount: total - completed,
totalCount: todos.length, totalCount: total,
allCompleted: todos.length === completed allCompleted: total === completed
}); });
}, },
handleModeChange: function () { handleModeChange: function () {
...@@ -188,6 +186,11 @@ module.exports = Collection.extend({ ...@@ -188,6 +186,11 @@ module.exports = Collection.extend({
// and persist on change // and persist on change
this.on('all', this.writeToLocalStorage, this); this.on('all', this.writeToLocalStorage, this);
}, },
getCompletedCount: function() {
return this.reduce(function(total, todo){
return todo.completed ? ++total : total;
}, 0);
},
// Helper for removing all completed items // Helper for removing all completed items
clearCompleted: function () { clearCompleted: function () {
var toRemove = this.filter(function (todo) { var toRemove = this.filter(function (todo) {
...@@ -532,7 +535,7 @@ extend(Collection.prototype, BackboneEvents, { ...@@ -532,7 +535,7 @@ extend(Collection.prototype, BackboneEvents, {
} else if (targetProto.generateId) { } else if (targetProto.generateId) {
id = targetProto.generateId(attrs); id = targetProto.generateId(attrs);
} else { } else {
id = attrs[targetProto.idAttribute || 'id']; id = attrs[targetProto.idAttribute || this.mainIndex];
} }
// If a duplicate is found, prevent it from being added and // If a duplicate is found, prevent it from being added and
...@@ -1402,6 +1405,7 @@ _.extend(History.prototype, Events, { ...@@ -1402,6 +1405,7 @@ _.extend(History.prototype, Events, {
module.exports = new History(); module.exports = new History();
},{"backbone-events-standalone":20,"underscore":21}],16:[function(require,module,exports){ },{"backbone-events-standalone":20,"underscore":21}],16:[function(require,module,exports){
;window.ampersand = window.ampersand || {};window.ampersand["ampersand-router"] = window.ampersand["ampersand-router"] || [];window.ampersand["ampersand-router"].push("1.0.6");
var classExtend = require('ampersand-class-extend'); var classExtend = require('ampersand-class-extend');
var Events = require('backbone-events-standalone'); var Events = require('backbone-events-standalone');
var ampHistory = require('./ampersand-history'); var ampHistory = require('./ampersand-history');
...@@ -2870,6 +2874,7 @@ module.exports=require(12) ...@@ -2870,6 +2874,7 @@ module.exports=require(12)
}).call(this); }).call(this);
},{}],22:[function(require,module,exports){ },{}],22:[function(require,module,exports){
;window.ampersand = window.ampersand || {};window.ampersand["ampersand-state"] = window.ampersand["ampersand-state"] || [];window.ampersand["ampersand-state"].push("4.3.14");
var _ = require('underscore'); var _ = require('underscore');
var BBEvents = require('backbone-events-standalone'); var BBEvents = require('backbone-events-standalone');
var KeyTree = require('key-tree-store'); var KeyTree = require('key-tree-store');
...@@ -6243,6 +6248,9 @@ function getBindingFunc(binding) { ...@@ -6243,6 +6248,9 @@ function getBindingFunc(binding) {
return ''; return '';
} }
})(); })();
var yes = binding.yes;
var no = binding.no;
var hasYesNo = !!(yes || no);
// storage variable for previous if relevant // storage variable for previous if relevant
var previousValue; var previousValue;
...@@ -6289,10 +6297,10 @@ function getBindingFunc(binding) { ...@@ -6289,10 +6297,10 @@ function getBindingFunc(binding) {
}; };
} else if (type === 'booleanClass') { } else if (type === 'booleanClass') {
// if there's a `no` case this is actually a switch // if there's a `no` case this is actually a switch
if (binding.no) { if (hasYesNo) {
return function (el, value, keyName) { yes = makeArray(yes || '');
var yes = makeArray(binding.name || binding.yes || keyName); no = makeArray(no || '');
var no = makeArray(binding.no); return function (el, value) {
var prevClass = value ? no : yes; var prevClass = value ? no : yes;
var newClass = value ? yes : no; var newClass = value ? yes : no;
getMatches(el, selector).forEach(function (match) { getMatches(el, selector).forEach(function (match) {
...@@ -6325,17 +6333,17 @@ function getBindingFunc(binding) { ...@@ -6325,17 +6333,17 @@ function getBindingFunc(binding) {
}; };
} else if (type === 'toggle') { } else if (type === 'toggle') {
// this doesn't require a selector since we can pass yes/no selectors // this doesn't require a selector since we can pass yes/no selectors
if (binding.yes && binding.no) { if (hasYesNo) {
return function (el, value) { return function (el, value) {
getMatches(el, binding.yes).forEach(function (match) { getMatches(el, yes).forEach(function (match) {
dom[value ? 'show' : 'hide'](match); dom[value ? 'show' : 'hide'](match);
}); });
getMatches(el, binding.no).forEach(function (match) { getMatches(el, no).forEach(function (match) {
dom[value ? 'hide' : 'show'](match); dom[value ? 'hide' : 'show'](match);
}); });
}; };
} else { } else {
return function (el, value) { return function (el, value) {
getMatches(el, selector).forEach(function (match) { getMatches(el, selector).forEach(function (match) {
dom[value ? 'show' : 'hide'](match); dom[value ? 'show' : 'hide'](match);
}); });
...@@ -6374,6 +6382,7 @@ function getBindingFunc(binding) { ...@@ -6374,6 +6382,7 @@ function getBindingFunc(binding) {
} }
},{"ampersand-dom":42,"key-tree-store":43,"matches-selector":51}],42:[function(require,module,exports){ },{"ampersand-dom":42,"key-tree-store":43,"matches-selector":51}],42:[function(require,module,exports){
;window.ampersand = window.ampersand || {};window.ampersand["ampersand-dom"] = window.ampersand["ampersand-dom"] || [];window.ampersand["ampersand-dom"].push("1.2.6");
var dom = module.exports = { var dom = module.exports = {
text: function (el, val) { text: function (el, val) {
el.textContent = getString(val); el.textContent = getString(val);
...@@ -6396,7 +6405,8 @@ var dom = module.exports = { ...@@ -6396,7 +6405,8 @@ var dom = module.exports = {
}, },
removeClass: function (el, cls) { removeClass: function (el, cls) {
if (el.classList) { if (el.classList) {
el.classList.remove(getString(cls)); cls = getString(cls);
if (cls) el.classList.remove(cls);
} else { } else {
// may be faster to not edit unless we know we have it? // may be faster to not edit unless we know we have it?
el.className = el.className.replace(new RegExp('(^|\\b)' + cls.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); el.className = el.className.replace(new RegExp('(^|\\b)' + cls.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
......
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