Skip to content
This repository was archived by the owner on Dec 9, 2021. It is now read-only.

Commit 5778690

Browse files
committed
Add todomvc example
1 parent 9ff8f64 commit 5778690

File tree

33 files changed

+25631
-0
lines changed

33 files changed

+25631
-0
lines changed

examples/TodoMVC/assets/media/fonts/.keep

Whitespace-only changes.

examples/TodoMVC/assets/media/images/.keep

Whitespace-only changes.

examples/TodoMVC/assets/media/uploads/.keep

Whitespace-only changes.
Lines changed: 370 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,370 @@
1+
define(function (require, exports, module) { // jshint ignore:line
2+
'use strict';
3+
4+
require('lodash');
5+
6+
// Imports
7+
var Extend = require('structurejs/util/Extend');
8+
var Stage = require('structurejs/display/Stage');
9+
var BaseEvent = require('structurejs/event/BaseEvent');
10+
var Router = require('structurejs/controller/Router');
11+
var StringUtil = require('structurejs/util/StringUtil');
12+
var ListItemCollection = require('model/ListItemCollection');
13+
var ListItemComponent = require('component/ListItemComponent');
14+
var ListItemVO = require('model/vo/ListItemVO');
15+
var Key = require('constant/Key');
16+
var FooterView = require('view/FooterView');
17+
18+
/**
19+
* YUIDoc_comment
20+
*
21+
* @class App
22+
* @extends Stage
23+
* @constructor
24+
**/
25+
var App = (function () {
26+
27+
var _super = Extend(App, Stage);
28+
29+
function App() {
30+
_super.call(this);
31+
32+
/**
33+
* @property _listItemCollection
34+
* @type {ListItemCollection}
35+
* @private
36+
*/
37+
this._listItemCollection = null;
38+
39+
/**
40+
* @property _$addTodoInput
41+
* @type {HTMLInputElement}
42+
* @private
43+
*/
44+
this._$addTodoInput = null;
45+
46+
/**
47+
* @property _$markAllCompleteCheckbox
48+
* @type {HTMLInputElement}
49+
* @private
50+
*/
51+
this._$markAllCompleteCheckbox = null;
52+
53+
/**
54+
* @property _todoListContainer
55+
* @type {DOMElement}
56+
* @private
57+
*/
58+
this._todoListContainer = null;
59+
60+
/**
61+
* @property _$mainView
62+
* @type {jQuery}
63+
* @private
64+
*/
65+
this._$mainView = null;
66+
67+
/**
68+
* @property _footerView
69+
* @type {FooterView}
70+
* @private
71+
*/
72+
this._footerView = null;
73+
}
74+
75+
/**
76+
* @overridden DOMElement.createChildren
77+
*/
78+
App.prototype.createChildren = function () {
79+
_super.prototype.createChildren.call(this);
80+
81+
this._listItemCollection = new ListItemCollection();
82+
83+
this._$addTodoInput = this.$element.find('.js-addInput');
84+
this._$markAllCompleteCheckbox = this.$element.find('.js-markAllComplete');
85+
this._$mainView = this.$element.find('.js-mainView');
86+
87+
// Take note the "getChild" is a method of the DOMElement class. It will return the first html element from the selector name
88+
// that is passed in and create a DOMElement view class with that markup so we can use functionality that comes with the DOMElement class.
89+
this._todoListContainer = this.getChild('.js-todoList');
90+
91+
this._footerView = new FooterView(this.$element.find('.js-footerView'));
92+
this.addChild(this._footerView);
93+
};
94+
95+
/**
96+
* @overridden DOMElement.layoutChildren
97+
*/
98+
App.prototype.layoutChildren = function () {
99+
100+
this._footerView.updateCounts(this._listItemCollection.getCompletedCount(), this._listItemCollection.getRemainingCount());
101+
102+
if (this._listItemCollection.length > 0) {
103+
// Take note we are working with the FooterView class jQuery view object "$element" directly.
104+
// All classes that extend the DOMElement class has a "$element" property which is the main view/markup the class controls.
105+
// If you wanted to encapsulate this more you could create a show/hide method in the FooterView class to handle it.
106+
this._footerView.$element.show();
107+
108+
this._$mainView.show();
109+
} else {
110+
this._$mainView.hide();
111+
this._footerView.$element.hide();
112+
}
113+
114+
return this;
115+
};
116+
117+
/**
118+
* @overridden DOMElement.enable
119+
*/
120+
App.prototype.enable = function () {
121+
if (this.isEnabled === true) { return this; }
122+
123+
// Class Events
124+
this._listItemCollection.addEventListener('loadComplete', this.onLoadedItems, this);//
125+
this._footerView.addEventListener(BaseEvent.CLEAR, this.onClearCompleted, this);
126+
this.addEventListener(BaseEvent.CHANGE, this.onItemChange, this);
127+
this.addEventListener(BaseEvent.REMOVED, this.onItemRemove, this);
128+
129+
// DOM Events
130+
this._$addTodoInput.addEventListener('keypress', this.onCreateTodo, this);
131+
this._$markAllCompleteCheckbox.addEventListener('change', this.onAllCompleteChange, this);
132+
133+
// Load and parse the data in the browsers local storage.
134+
this._listItemCollection.loadStoredItems();
135+
136+
return _super.prototype.enable.call(this);
137+
};
138+
139+
/**
140+
* @overridden DOMElement.disable
141+
*/
142+
App.prototype.disable = function () {
143+
if (this.isEnabled === false) { return this; }
144+
145+
// Class Events
146+
this._listItemCollection.removeEventListener('loadComplete', this.onLoadedItems, this);// Example of plan string event.
147+
this._footerView.removeEventListener(BaseEvent.CLEAR, this.onClearCompleted, this);
148+
this.removeEventListener(BaseEvent.CHANGE, this.onItemChange, this);
149+
this.removeEventListener(BaseEvent.REMOVED, this.onItemRemove, this);
150+
151+
// DOM Events
152+
this._$addTodoInput.removeEventListener('keypress', this.onCreateTodo, this);
153+
this._$markAllCompleteCheckbox.removeEventListener('change', this.onAllCompleteChange, this);
154+
155+
return _super.prototype.disable.call(this);
156+
};
157+
158+
/**
159+
* @overridden DOMElement.destroy
160+
*/
161+
App.prototype.destroy = function () {
162+
this._todoListContainer.destroy();
163+
this._listItemCollection.destroy();
164+
165+
_super.prototype.destroy.call(this);
166+
};
167+
168+
/**
169+
* YUIDoc_comment
170+
*
171+
* @method onCreateTodo
172+
* @private
173+
*/
174+
App.prototype.onCreateTodo = function(event) {
175+
var todoText = this._$addTodoInput.val().trim();
176+
177+
if (event.which === Key.ENTER && todoText != '') {
178+
var valueObject = new ListItemVO({text: todoText});
179+
valueObject.id = StringUtil.createUUID();
180+
var childItem = new ListItemComponent(valueObject);
181+
182+
this._listItemCollection.addItem(valueObject);
183+
this._todoListContainer.addChild(childItem);
184+
this._$addTodoInput.val('');
185+
}
186+
187+
this.layoutChildren();
188+
};
189+
190+
/**
191+
* YUIDoc_comment
192+
*
193+
* @method onAllCompleteChange
194+
* @private
195+
*/
196+
App.prototype.onAllCompleteChange = function(event) {
197+
var $target = $(event.target);
198+
199+
var listItemComponent;
200+
if ($target.prop("checked") == true) {
201+
for (var i = 0; i < this._todoListContainer.numChildren; i++) {
202+
listItemComponent = this._todoListContainer.getChildAt(i);
203+
listItemComponent.setCompleted();
204+
}
205+
} else {
206+
for (var i = 0; i < this._todoListContainer.numChildren; i++) {
207+
listItemComponent = this._todoListContainer.getChildAt(i);
208+
listItemComponent.setUnCompleted();
209+
}
210+
}
211+
};
212+
213+
/**
214+
* YUIDoc_comment
215+
*
216+
* @method onItemRemove
217+
* @param event {BaseEvent}
218+
* @private
219+
*/
220+
App.prototype.onItemRemove = function(event) {
221+
var listItemComponent = event.target;
222+
var listItemVO = listItemComponent.vo;
223+
224+
this._listItemCollection.removeItem(listItemVO);
225+
this._todoListContainer.removeChild(listItemComponent);
226+
227+
this.layoutChildren();
228+
};
229+
230+
/**
231+
* YUIDoc_comment
232+
*
233+
* @method onItemChange
234+
* @param event {BaseEvent}
235+
* @private
236+
*/
237+
App.prototype.onItemChange = function(event) {
238+
this._listItemCollection.save();
239+
240+
this.layoutChildren();
241+
};
242+
243+
/**
244+
* YUIDoc_comment
245+
*
246+
* @method onLoadedItems
247+
* @param event {BaseEvent}
248+
* @private
249+
*/
250+
App.prototype.onLoadedItems = function(event) {
251+
var items = this._listItemCollection.items;
252+
var length = items.length;
253+
254+
// Create ListItemComponent view items from the stored ListItemVO value objects.
255+
for (var i = 0; i < length; i++) {
256+
var childItem = new ListItemComponent(items[i]);
257+
this._todoListContainer.addChild(childItem);
258+
}
259+
260+
// When the app loads we need to check if all stored items are all completed or not.
261+
var isAllCompleted = this._listItemCollection.length == this._listItemCollection.getCompletedCount();
262+
this._$markAllCompleteCheckbox.prop('checked', isAllCompleted);
263+
264+
// Setup the router/deeplink handlers
265+
Router.add('/active/', this.onActiveHandler.bind(this));
266+
Router.add('/completed/', this.onCompletedHandler.bind(this));
267+
Router.add('', this.onDefaultHandler.bind(this));
268+
Router.start();
269+
270+
this.layoutChildren();
271+
};
272+
273+
/**
274+
* This method is called when the BaseEvent.CLEAR event is dispatched from the FooterView.
275+
*
276+
* @method onClearCompleted
277+
* @param event {BaseEvent}
278+
* @private
279+
*/
280+
App.prototype.onClearCompleted = function(event) {
281+
var listItemVO;
282+
var listItemComponent;
283+
284+
for (var i = this._todoListContainer.numChildren - 1; i >= 0; i--) {
285+
listItemComponent = this._todoListContainer.getChildAt(i);
286+
listItemVO = listItemComponent.vo;
287+
288+
if (listItemVO.isComplete == true) {
289+
this._todoListContainer.removeChild(listItemComponent);
290+
this._listItemCollection.removeItem(listItemVO);
291+
}
292+
}
293+
294+
this.layoutChildren();
295+
};
296+
297+
/**
298+
* When the deep link "#/active" tag is triggered this method will hide all items and show only items that are not completed.
299+
* Also updates the footer nav.
300+
*
301+
* @method onActiveHandler
302+
* @private
303+
*/
304+
App.prototype.onActiveHandler = function() {
305+
var listItemComponent;
306+
307+
for (var i = this._todoListContainer.numChildren - 1; i >= 0; i--) {
308+
listItemComponent = this._todoListContainer.getChildAt(i);
309+
listItemComponent.hide();
310+
311+
if (listItemComponent.vo.isComplete == false) {
312+
listItemComponent.show();
313+
}
314+
}
315+
316+
this._footerView.updateNav('active');
317+
318+
this.layoutChildren();
319+
};
320+
321+
/**
322+
* When the deep link "#/completed" tag is triggered this method will hide all items and show only items that are completed.
323+
* Also updates the footer nav.
324+
*
325+
* @method onCompletedHandler
326+
* @private
327+
*/
328+
App.prototype.onCompletedHandler = function() {
329+
var listItemComponent;
330+
331+
for (var i = this._todoListContainer.numChildren - 1; i >= 0; i--) {
332+
listItemComponent = this._todoListContainer.getChildAt(i);
333+
listItemComponent.hide();
334+
335+
if (listItemComponent.vo.isComplete == true) {
336+
listItemComponent.show();
337+
}
338+
}
339+
340+
this._footerView.updateNav('completed');
341+
342+
this.layoutChildren();
343+
};
344+
345+
/**
346+
* When the deep link "#/" tag is triggered this method will show all items.
347+
* Also updates the footer nav.
348+
*
349+
* @method onDefaultHandler
350+
* @private
351+
*/
352+
App.prototype.onDefaultHandler = function() {
353+
var listItemComponent;
354+
355+
for (var i = this._todoListContainer.numChildren - 1; i >= 0; i--) {
356+
listItemComponent = this._todoListContainer.getChildAt(i);
357+
listItemComponent.show();
358+
}
359+
360+
this._footerView.updateNav('');
361+
362+
this.layoutChildren();
363+
};
364+
365+
return App;
366+
})();
367+
368+
module.exports = App;
369+
370+
});

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy