Skip to content

Commit

Permalink
Add comments and cleanup inconsistencies.
Browse files Browse the repository at this point in the history
  • Loading branch information
GCheung55 committed Sep 4, 2012
1 parent 8d198bb commit d170cdf
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 79 deletions.
37 changes: 18 additions & 19 deletions labs/architecture-examples/neuro/js/collection/TodoList.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
}
},

/**
* Methods used for filtering in filterBy method
* @type {Object}
*/
filterTypes: {
active: function(model){
return !model.get('completed');
Expand All @@ -46,24 +50,10 @@
}
},

setAll: function(prop, value){
this.each(function(model){
model.set(prop, value);
});

return this;
},

removeTodo: function(id){
var model = this.filter(function(m){ return m.get('id') == id; });

if (model) {
this.remove(model);
}

return this;
},

/**
* Clear (remove) the completed items from the collection. Destroying the model itself automatically removes it from the collection
* @return {Object} The class instance.
*/
clearCompleted: function(){
/**
* Filter creates a new array of models that match
Expand All @@ -81,12 +71,21 @@
return this
},

/**
* Count the number of compeleted items in the collection
* @return {Number} The number of completed items in the collection
*/
countCompleted: function(){
return this.filter(function(model){return model.get('completed');}).length;
},

/**
* Filter the collection by a type.
* @param {String} type String refers to a function in filterTypes object that will be used for filtering
* @return {Array} An array of filtered items or the array of models.
*/
filterBy: function(type){
var filtered = type ? this.filter(this.filterTypes[type]) : this._models
var filtered = type ? this.filter(this.filterTypes[type]) : this._models;

return filtered;
}
Expand Down
4 changes: 2 additions & 2 deletions labs/architecture-examples/neuro/js/model/TodoListItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
* Connect the change:title event with Views/TodoListItem.updateTitle method
* change:title will pass the model, property, and value to the method
*/
'change:title': 'updateTitle',
'change:completed': 'onUpdateComplete',
'change:title': '_onUpdateTitle',
'change:completed': '_onUpdateComplete',
'destroy': 'destroy'
}
}
Expand Down
6 changes: 0 additions & 6 deletions labs/architecture-examples/neuro/js/view/TodoFooter.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,6 @@
return this;
},

clearCompleted: function(){
this.fireEvent('clearCompleted');

return this;
},

updateCount: function(count){
count = this.options.todoCountTemplate.substitute({
count: count,
Expand Down
116 changes: 64 additions & 52 deletions labs/architecture-examples/neuro/js/view/TodoListItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
* Method names refer to the method on this View class.
*/
events: {
'dblclick:relay(label)': 'onEdit',
'click:relay(input.toggle)': 'onToggleStatus',
'dblclick:relay(label)': '_onEdit',
'click:relay(input.toggle)': '_onToggleStatus',
'click:relay(button.destroy)': 'destroy'
},

Expand All @@ -35,83 +35,95 @@
}
},

updateTitle: function(model, prop, title){
if (title != undefined) {
this.label.set('html', title);
}

return this;
},

/**
* Mark the element as completed
* @param {Boolean} bool Boolean used to add/remove 'completed' class on the element. Also used to check/uncheck the completedInput element
* @return {Object} The class instance.
*/
updateComplete: function(bool){
this.element[bool ? 'addClass' : 'removeClass']('completed');
this.completedInput.set('checked', bool);
return this;
},

onEdit: function(e, element){
var value = this._previousTitle = element.get('html');

this.editInput.set('value', value);

this.element.addClass('editing');

this.editInput.fireEvent('focus').focus();

return this;
},

onUpdate: function(e, element){
var value = element.get('value').trim();

if (value) {
this.element.removeClass('editing');

this.fireEvent('update', ['title', value]);
}

return this;
},

onUpdateComplete: function(model, prop, complete){
this.updateComplete(complete);

this.elements.completed.set('checked', bool);
return this;
},

onToggleStatus: function(e, element){
var hasClass = this.element.hasClass('completed');
this.updateComplete(hasClass);

this.fireEvent('toggleStatus', ['completed', !hasClass]);
/**
* Cleanup the stored elements and trigger the parent method to continue cleanup.
* @return {[type]} [description]
*/
destroy: function(){
Object.each(this.elements, Element.destroy);

return this;
return this.parent.apply(this, arguments);
},

/**
* Render the view.
* @param {Object} model The model instance used to render the view.
* @return {Object} The class instance.
*/
render: function(model){
// Connect this view with the model one-way binding.
this.connect(model);

// Create a proxy element with the html from the template
var element = new Element('div', {
html: this.options.template.substitute(model.getData())
}).getElement('>');

// Set the element so that events get attached to it and the element gets stored in the class instance.
this.setElement(element);

this.elements = {
edit: this.element.getElement('input.edit'),
completed: this.element.getElement('input.toggle'),
label: this.element.getElement('label')
};

// Create an input view to handle keyup events for enter and reset behaviors.
var input = new View.Input({
element: element.getElement('input.edit'),
element: this.elements.edit,
connector: {
'keyup:enter': '_onEnter'
, 'keyup:reset': '_onReset'
}
}).connect(this);

this.editInput = this.element.getElement('input.edit');
// Execute the parent method, which will trigger the render event.
return this.parent(model);
},

_onEdit: function(e, element){
var value = this._previousTitle = element.get('html'),
editElement = this.elements.edit;

editElement.set('value', value);

this.element.addClass('editing');

editElement.fireEvent('focus').focus();

return this;
},

_onUpdateTitle: function(model, prop, title){
if (title != undefined) {
this.elements.label.set('html', title);
}

return this;
},

_onUpdateComplete: function(model, prop, complete){
this.updateComplete(complete);

this.completedInput = this.element.getElement('input.toggle');
return this;
},

this.label = this.element.getElement('label');
_onToggleStatus: function(e, element){
var hasClass = this.element.hasClass('completed');
this.updateComplete(hasClass);

this.parent(model);
this.fireEvent('toggleStatus', ['completed', !hasClass]);

return this;
},
Expand Down
54 changes: 54 additions & 0 deletions labs/architecture-examples/neuro/js/view/TodoMain.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,82 +20,136 @@
}
},

/**
* Setup the View and reference the toggleAll and List elements.
* @param {Object} options Options to setup the view.
* @return {Object} The class instance.
*/
setup: function(options){
this.parent(options);

this.elements = {
toggleAll: document.id(this.options.elements.toggleAll),
list: document.id(this.options.elements.list)
};

return this;
},

/**
* Show the element.
* @return {Object} The class instance.
*/
showMain: function(){
this.element.removeClass('hidden');

return this;
},

/**
* Hide the element
* @return {Object} The class instance.
*/
hideMain: function(){
this.element.addClass('hidden');

return this;
},

/**
* Toggle hide/show of the element
* @param {Boolean} bool Boolean used to determine whether to trigger hide or show methods
* @return {[type]} [description]
*/
toggleMain: function(bool){
this[(bool ? 'show' : 'hide') + 'Main']();

return this;
},

/**
* Process the model to create/render the ToDo Item View.
* @param {Object} model The model used to generate the ToDo List Item view.
* @return {Object} The class instance.
*/
addTodo: function(model){
var todoItem = new View.TodoListItem({
template: this.options.todoItemTemplate
});

// Connect the view with the model both ways.
todoItem.connect(model, true);

// Render the view with the model data.
todoItem.render(model);

// Silently set the view because we don't need to trigger change to the model.
model.silence(function(){
model.set('view', todoItem);
});

return this;
},

/**
* Uncheck the Completed checkbox
* @return {Object} The class instance.
*/
uncheckCompleted: function(){
this.elements.toggleAll.set('checked');

return this;
},

/**
* Check the Completed checkbox
* @return {Object} The class instance.
*/
checkCompleted: function(){
this.elements.toggleAll.set('checked', 'checked');

return this;
},

/**
* Toggle Completed checkbox
* @param {Boolean} bool Boolean value used trigger the check/uncheckCompleted method.
* @return {Object} This class instance.
*/
toggleCompleted: function(bool){
this[(bool ? '' : 'un') + 'checkCompleted']();

return this;
},

/**
* Render the view. Does not create new elements. Does not throw away elements.
* @param {Object} collection The collection object used for rendering.
* @param {String} filterType The string used to filter the collections models for display.
* @return {Object} The class instance.
*/
render: function(collection, filterType){
var elements,
// Count the number of completed items in the collection
completeCount = collection.countCompleted(),
count = collection.length;

// Check/uncheck the completed checkbox based on whether citems in the collection are compeleted or not
this.toggleCompleted(completeCount == count);

// Show/hide the element based on the count
this.toggleMain(count);

// Prepare the list element by emptying it first.
this.elements.list.empty();

// Retrieve the elements from the collection by filter
elements = collection.filterBy(filterType).invoke('get', 'view');

// Have the list element adopt all the elements that have been filtered from the collection
this.elements.list.adopt(elements);

// Execute the parent method, which will trigger the render event.
return this.parent.apply(this, arguments);
},

Expand Down

0 comments on commit d170cdf

Please sign in to comment.