Commit 254fa67a authored by DimitarChristoff's avatar DimitarChristoff

refactor for code style, spaces creep in, fix issue with active filter, change...

refactor for code style, spaces creep in, fix issue with active filter, change completed to boolean, editing enter fires blur, see pull/235#issuecomment-7264416
parent 9447769a
...@@ -25,19 +25,19 @@ ...@@ -25,19 +25,19 @@
<footer id="info"> <footer id="info">
<p>Double-click to edit a todo</p> <p>Double-click to edit a todo</p>
<p>Created by <a href="https://github.com/DimitarChristoff/">Dimitar Christoff</a></p> <p>Created by <a href="https://github.com/DimitarChristoff/">Dimitar Christoff</a></p>
<p>Powered by <a href="https://github.com/DimitarChristoff/Epitome">Epitome for MooTools</a></p> <p>Powered by <a href="https://dimitarchristoff.github.com/Epitome">Epitome for MooTools</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p> <p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer> </footer>
<script type="text/template" id="item-template"> <script type="text/template" id="item-template">
<div class="view"> <div class="view">
<input class="toggle" type="checkbox" <%=completedCheckbox%>> <input class="toggle" type="checkbox" <%=completedCheckbox%>>
<label><%=title%></label> <label><%=title%></label>
<button class="destroy"></button> <button class="destroy"></button>
</div> </div>
<input class="edit" value="<%=title%>"> <input class="edit" value="<%=title%>">
</script> </script>
<script type="text/template" id="stats-template"> <script type="text/template" id="stats-template">
<span id="todo-count"><strong><%=remaining%></strong> item<% if (obj.remaining !== 1) { %>s<% } %> left</span> <span id="todo-count"><strong><%=remaining%></strong> item<% if (obj.remaining !== 1) { %>s<% } %> left</span>
<ul id="filters"> <ul id="filters">
<li> <li>
<a class="selected" href="#!/">All</a> <a class="selected" href="#!/">All</a>
...@@ -53,16 +53,17 @@ ...@@ -53,16 +53,17 @@
<button id="clear-completed">Clear completed (<%=completed%>)</button> <button id="clear-completed">Clear completed (<%=completed%>)</button>
<% } %> <% } %>
</script> </script>
<script src="../../../assets/base.js"></script> <script src="../../../assets/base.js"></script>
<!-- mootools --> <!-- mootools -->
<script src="js/lib/mootools-yui-compressed.js"></script> <script src="js/lib/mootools-yui-compressed.js"></script>
<!-- epitome pre-compiled --> <!-- epitome pre-compiled -->
<script src="js/lib/Epitome-min.js"></script> <script src="js/lib/Epitome-min.js"></script>
<!-- todo app --> <!-- todo app -->
<script src="js/models/todo-model.js"></script> <script src="js/models/todo-model.js"></script>
<script src="js/collections/todo-collection.js"></script> <script src="js/collections/todo-collection.js"></script>
<script src="js/views/todo-list.js"></script> <script src="js/views/todo-list.js"></script>
<script src="js/views/todo-main.js"></script> <script src="js/views/todo-main.js"></script>
<script src="js/controllers/todo-router.js"></script>
<script src="js/app.js"></script> <script src="js/app.js"></script>
</body> </body>
</html> </html>
\ No newline at end of file
/*global Epitome */ /*global Epitome */
/*jshint mootools:true */
(function( window ) { (function( window ) {
'use strict'; 'use strict';
var App = window.App; var App = window.App;
var todos = new App.TodoCollection( null, { var todos = new App.TodoCollection( null, {
// a consistent collection if is needed if you want to use storage for a collection // a consistent collection if is needed if you want to use storage for a collection
id: 'todos' id: 'todos'
}); });
// populate from storage if available // populate from storage if available
todos.setUp( todos.retrieve() ); todos.setUp( todos.retrieve() );
// instantiate the todo list view // instantiate the todo list view
App.todoView = new App.TodoView({ App.todoView = new App.TodoView({
...@@ -19,10 +20,10 @@ ...@@ -19,10 +20,10 @@
collection: todos, collection: todos,
// encapsulating element to bind to // encapsulating element to bind to
element: document.id('todo-list'), element: document.id( 'todo-list' ),
// template to use // template to use
template: document.id('item-template').get('text') template: document.id( 'item-template' ).get( 'text' )
}); });
...@@ -36,11 +37,23 @@ ...@@ -36,11 +37,23 @@
element: document.id('todoapp'), element: document.id('todoapp'),
// stats template from DOM // stats template from DOM
template: document.id('stats-template').get('text') template: document.id( 'stats-template' ).get( 'text' ),
onReady: function() {
// need to work with controller that sets the current state of filtering
var proxy = function() {
App.router.showActiveFilter();
};
this.addEvents({
'add:collection': proxy,
'change:collection': proxy
});
}
}); });
// the pseudo controller via Epitome.Router // the pseudo controller via Epitome.Router
App.router = new Epitome.Router({ App.router = new App.Router({
routes: { routes: {
'': 'init', '': 'init',
'#!/': 'applyFilter', '#!/': 'applyFilter',
...@@ -49,10 +62,10 @@ ...@@ -49,10 +62,10 @@
onInit: function() { onInit: function() {
// we want to always have a state // we want to always have a state
this.navigate('#!/'); this.navigate( '#!/' );
}, },
onApplyFilter: function( filter ) { onApplyFilter: function( filter ) {
// the filter is being used by the todo collection and view. // the filter is being used by the todo collection and view.
// when false, the whole collection is being passed. // when false, the whole collection is being passed.
todos.filterType = filter || false; todos.filterType = filter || false;
...@@ -60,11 +73,7 @@ ...@@ -60,11 +73,7 @@
// render as per current filter // render as per current filter
App.todoView.render(); App.todoView.render();
// fix up the links quickie. this.showActiveFilter();
var self = this;
document.getElements('#filters li a').each(function( link ) {
link.set( 'class', link.get('href') === self.req ? 'selected' : '' );
});
} }
}); });
}( window )); }( window ));
\ No newline at end of file
/*global Epitome, App, Class */ /*global Epitome, App */
/*jshint mootools:true */
(function(window) { (function(window) {
'use strict'; 'use strict';
...@@ -15,9 +16,14 @@ ...@@ -15,9 +16,14 @@
// base model class prototype // base model class prototype
model: App.Todo, model: App.Todo,
todoFilter: function( model ) { map: {
active: 0,
completed: 1
},
todoFilter: function( model ) {
// references the filterType which the controller sets // references the filterType which the controller sets
return this.filterType === false ? true : model.get('completed') === this.filterType; return this.filterType === false ? true : this.map[this.filterType] === +model.get( 'completed' );
} }
}); });
}( window )); }( window ));
\ No newline at end of file
/*global Epitome, App */
/*jshint mootools:true */
(function(window) {
'use strict';
window.App = window.App || {};
App.Router = new Class({
Extends: Epitome.Router,
showActiveFilter: function() {
// fix up the links for current filter
var self = this;
document.getElements( '#filters li a' ).each(function( link ) {
link.set( 'class', link.get( 'href' ) === self.req ? 'selected' : '' );
});
}
});
}( window ));
\ No newline at end of file
/*global Epitome, App, Class */ /*global Epitome, App */
/*jshint mootools:true */
(function(window) { (function(window) {
'use strict'; 'use strict';
...@@ -11,7 +12,7 @@ ...@@ -11,7 +12,7 @@
options: { options: {
defaults: { defaults: {
completed: 'active', completed: false,
title: '' title: ''
} }
} }
......
/*global Epitome, App, Class, Elements, Element */ /*global Epitome, App */
/*jshint mootools:true */
(function( window ) { (function( window ) {
'use strict'; 'use strict';
...@@ -34,94 +35,103 @@ ...@@ -34,94 +35,103 @@
}, },
// when collection changes, save the data to storage and re-render // when collection changes, save the data to storage and re-render
'onChange:collection': function( model ) { 'onChange:collection': function( model ) {
this.collection.store(); this.collection.store();
this.render(); this.render();
}, },
// when models get removed, re-render // when models get removed, re-render
'onRemove:collection': function( model ) { 'onRemove:collection': function( model ) {
this.collection.store(); this.collection.store();
this.render(); this.render();
}, },
// when sort is applied, re-render // when sort is applied, re-render
'onSort:collection': function() { 'onSort:collection': function() {
this.collection.store(); this.collection.store();
this.render(); this.render();
}, },
// when a new model is added, re-render // when a new model is added, re-render
'onAdd:collection': function( model ) { 'onAdd:collection': function( model ) {
this.collection.store(); this.collection.store();
this.render(); this.render();
}, },
// handler for the edit event // handler for the edit event
onEditing: function( e, el ) { onEditing: function( e, el ) {
if ( e && e.stop ) { if ( e && e.stop ) {
e.stop(); e.stop();
} }
el.addClass( this.options.editingClass );
el.getElement( this.options.input ).focus();
},
el.addClass( this.options.editingClass ); // when enter pressed while editing
el.getElement( this.options.input ).focus(); onHandleKeypress: function( e, el ) {
// on enter, blur() and let it bubble to onUpdate.
if ( e.key === 'enter' ) {
el.blur();
}
}, },
// fired when editing ends // fired when editing ends
onUpdate: function( e, el ) { onUpdate: function( e, el ) {
var p = el.getParent('li').removeClass( this.options.editingClass ); var p = el.getParent( 'li ').removeClass( this.options.editingClass );
var val = el.get('value').trim(); var val = el.get( 'value' ).trim();
if ( !val.length ) { if ( !val.length ) {
// the render method stores the model into the element, get it and remove // the render method stores the model into the element, get it and remove
this.collection.removeModel( p.retrieve('model') ); this.collection.removeModel( p.retrieve( 'model' ) );
return; return;
} }
p.retrieve('model').set( 'title', val ); p.retrieve( 'model' ).set( 'title', val );
}, },
// handler for clicks on the checkboxes // handler for clicks on the checkboxes
onStatusChange: function( e, el ) { onStatusChange: function( e, el ) {
var p = el.getParent('li'); var p = el.getParent( 'li' );
var done = !!el.get('checked') ? 'completed' : 'active'; var done = !!el.get( 'checked' );
p.retrieve('model').set( 'completed', done ); p.retrieve( 'model' ).set( 'completed', done );
}, },
// when the X is pressed, drop the model // when the X is pressed, drop the model
onRemoveItem: function( e, el ) { onRemoveItem: function( e, el ) {
if ( e && e.stop ) { if ( e && e.stop ) {
e.stop(); e.stop();
} }
// the render method stores the model into the element, get it and remove // the render method stores the model into the element, get it and remove
this.collection.removeModel( el.getParent('li').retrieve('model') ); this.collection.removeModel( el.getParent( 'li' ).retrieve( 'model' ) );
} }
}, },
render: function() { render: function() {
// main render method, will also fire onRender // main render method, will also fire onRender
var todos = new Elements(); var todos = new Elements();
var self = this; var self = this;
// empty the container. // empty the container.
this.empty(); this.empty();
// the route controller works with the todoFilter to help determine what we render. // the route controller works with the todoFilter to help determine what we render.
this.collection.filter( this.collection.todoFilter.bind( this.collection ) ).each(function( model ) { this.collection.filter( this.collection.todoFilter.bind( this.collection ) ).each(function( model ) {
var obj = model.toJSON(); var obj = model.toJSON();
var li = new Element( self.tagName ).toggleClass( 'completed', obj.completed === 'completed' ).store( 'model', model ); var li = new Element( self.tagName ).toggleClass( 'completed', obj.completed ).store( 'model', model );
// help the template to avoid slower logic in the template layer // help the template to avoid slower logic in the template layer
obj.completedCheckbox = obj.completed === 'completed' ? 'checked' : ''; obj.completedCheckbox = obj.completed ? 'checked' : '';
// compile template and store resulting element in our Elements collection // compile template and store resulting element in our Elements collection
todos.push( li.set( 'html', self.template( obj ) ) ); todos.push( li.set( 'html', self.template( obj ) ) );
}); });
// inject the elements collection into the container element // inject the elements collection into the container element
this.element.adopt( todos ); this.element.adopt( todos );
// propagate the render event. // propagate the render event.
this.parent(); this.parent();
......
/*global Epitome, App, Class */ /*global Epitome, App */
/*jshint mootools:true */
(function( window ) { (function( window ) {
'use strict'; 'use strict';
...@@ -28,29 +29,29 @@ ...@@ -28,29 +29,29 @@
toggleAll: 'toggle-all', toggleAll: 'toggle-all',
onToggleAll: function( e, el ) { onToggleAll: function( e, el ) {
// all todos will change their models to the new completed value // all todos will change their models to the new completed value
var state = el.get('checked') ? 'completed' : 'active'; var state = !!el.get( 'checked' );
this.collection.each(function( model ) { this.collection.each( function( model ) {
model.set( 'completed', state ); model.set( 'completed', state );
}); });
}, },
onHandleKeypress: function( e, el ) { onHandleKeypress: function( e, el ) {
// on enter, submit. // on enter, submit.
if ( e.key === 'enter' ) { if ( e.key === 'enter' ) {
this.addTodo(); this.addTodo();
} }
}, },
onClearCompleted: function() { onClearCompleted: function() {
// because removing a model re-indexes so we don't get a sparse array, cannot apply that in a normal loop. // because removing a model re-indexes so we don't get a sparse array, cannot apply that in a normal loop.
var toRemove = this.collection.filter(function( model ) { var toRemove = this.collection.filter(function( model ) {
return model.get('completed') === 'completed'; return model.get( 'completed' );
}); });
// removeModel actually supports a single model or an array of models as arguments. // removeModel actually supports a single model or an array of models as arguments.
this.collection.removeModel( toRemove ); this.collection.removeModel( toRemove );
this.render(); this.render();
}, },
...@@ -70,14 +71,14 @@ ...@@ -70,14 +71,14 @@
} }
}, },
initialize: function( options ) { initialize: function( options ) {
// call default view constructor. // call default view constructor.
this.parent( options ); this.parent( options );
// store some pointers to static elements // store some pointers to static elements
this.newTodo = document.id( this.options.newTodo ); this.newTodo = document.id( this.options.newTodo );
this.footer = document.id( this.options.footer ); this.footer = document.id( this.options.footer );
this.toggleAll = document.id( this.options.toggleAll ); this.toggleAll = document.id( this.options.toggleAll );
// draw it. // draw it.
this.render(); this.render();
...@@ -85,43 +86,43 @@ ...@@ -85,43 +86,43 @@
addTodo: function() { addTodo: function() {
// adding a new model when data exists // adding a new model when data exists
var val = this.newTodo.get('value').trim(); var val = this.newTodo.get( 'value' ).trim();
if ( val.length ) { if ( val.length ) {
this.collection.addModel({ this.collection.addModel({
title: val, title: val,
completed: 'active' completed: false
}); });
} }
// clear the input // clear the input
this.newTodo.set( 'value', '' ); this.newTodo.set( 'value', '' );
}, },
render: function() { render: function() {
// main method to output everything. well. the footer anyway. // main method to output everything. well. the footer anyway.
// work out what we have remaining and what is complete // work out what we have remaining and what is complete
var remaining = 0; var remaining = 0;
var completed = this.collection.filter(function( el ) { var completed = this.collection.filter(function( model ) {
var status = el.get('completed') === 'completed'; var status = model.get( 'completed' );
if ( !status ) { if ( status === false ) {
remaining++; remaining++;
} }
return status; return status;
}).length; }).length;
// output footer // output footer
this.footer.set( 'html', this.template({ this.footer.set( 'html', this.template({
completed: completed, completed: completed,
remaining: remaining remaining: remaining
})); }));
// auto-correct the toggle-all checkbox with the new stats. // auto-correct the toggle-all checkbox with the new stats.
this.toggleAll.set( 'checked', this.collection.length ? !remaining : false ); this.toggleAll.set( 'checked', this.collection.length ? !remaining : false );
} }
}); });
}( window )); }( window ));
\ No newline at end of file
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