Permalink
Browse files

Initial commit

need to tidy up directory structure to match the others
  • Loading branch information...
1 parent c183dc9 commit 526b9c4463ae08c474a582bf6bb100ff17840914 @chrisprice chrisprice committed Feb 17, 2012
Binary file not shown.
@@ -0,0 +1,25 @@
+{
+ "id" : "todomvc",
+ "inputs" : "src/main.js",
+ "paths" : "src/",
+ "output-wrapper" : "(function(){%output%})();",
+ "mode" : "ADVANCED",
+ "define" : {
+ "goog.LOCALE": "en_GB"
+ },
+ "checks": {
+ // Unfortunately, the Closure Library violates these in many places.
+ // "accessControls": "ERROR",
+ // "visibility": "ERROR"
+
+ "checkRegExp": "WARNING",
+ "checkTypes": "WARNING",
+ "checkVars": "WARNING",
+ "deprecated": "WARNING",
+ "fileoverviewTags": "WARNING",
+ "invalidCasts": "WARNING",
+ "missingProperties": "WARNING",
+ "nonStandardJsDocs": "WARNING",
+ "undefinedVars": "WARNING"
+ }
+}
@@ -0,0 +1,143 @@
+goog.require('goog.array');
+goog.require('goog.events.EventType');
+goog.require('goog.events.KeyCodes');
+goog.require('goog.ui.Component');
+goog.require('goog.ui.Control');
+
+goog.require('todomvc.model.ToDoItem');
+goog.require('todomvc.view');
+goog.require('todomvc.view.ClearCompletedControlRenderer');
+goog.require('todomvc.view.ItemCountControlRenderer');
+goog.require('todomvc.view.ToDoItemControl');
+goog.require('todomvc.view.ToDoListContainer');
+
+/**
+ * @fileoverview The controller/business logic for the application.
+ *
+ * This file creates the interface and marshalls changes from the interface to the model and back.
+ */
+
+
+/**
+ * @type {Array.<todomvc.model.ToDoItem>}
+ */
+var items = [];
+
+/**
+ * @type {Element}
+ */
+var todoStats = document.getElementById('todo-stats');
+
+/**
+ * @type {goog.ui.Control}
+ */
+var itemCountControl = new goog.ui.Control(null, todomvc.view.ItemCountControlRenderer.getInstance());
+itemCountControl.render(todoStats);
+
+/**
+ * @type {goog.ui.Control}
+ */
+var clearCompletedControl = new goog.ui.Control(null, todomvc.view.ClearCompletedControlRenderer.getInstance());
+clearCompletedControl.render(todoStats);
+
+goog.events.listen(clearCompletedControl, goog.ui.Component.EventType.ACTION, function(e) {
+ // go backwards to avoid collection modification problems
+ goog.array.forEachRight(items, function(model) {
+ if (model.isDone()) {
+ goog.array.remove(items, model);
+ // do optimised model view sync
+ container.forEachChild(function(control) {
+ if (control.getModel() === model) {
+ container.removeChild(control, true);
+ }
+ });
+ }
+ });
+ updateStats();
+});
+
+function updateStats() {
+ var doneCount = goog.array.reduce(items, function(count, model) {
+ return model.isDone() ? count + 1 : count;
+ }, 0);
+ var remainingCount = items.length - (/**@type {number}*/ doneCount);
+ itemCountControl.setContent((/**@type {string}*/ remainingCount));
+ itemCountControl.setVisible(remainingCount > 0);
+ clearCompletedControl.setContent((/**@type {string}*/ doneCount));
+ clearCompletedControl.setVisible((/**@type {number}*/ doneCount) > 0);
+}
+updateStats();
+
+/**
+ * @type {todomvc.view.ToDoListContainer}
+ */
+var container = new todomvc.view.ToDoListContainer();
+container.decorate(document.getElementById('todo-list'));
+
+goog.events.listen(container, todomvc.view.ToDoItemControl.EventType.EDIT, function(e) {
+ /**
+ * @type {todomvc.view.ToDoItemControl}
+ */
+ var control = e.target;
+
+ /**
+ * @type {todomvc.model.ToDoItem}
+ */
+ var model = (/**@type {todomvc.model.ToDoItem} */ control.getModel());
+
+ // do optimised model view sync
+ model.setNote((/**@type {!string} */ control.getContent()));
+ model.setDone((/**@type {!boolean} */ control.isChecked()));
+
+ updateStats();
+});
+
+goog.events.listen(container, todomvc.view.ToDoItemControl.EventType.DESTROY, function(e) {
+ /**
+ * @type {todomvc.view.ToDoItemControl}
+ */
+ var control = e.target;
+
+ /**
+ * @type {todomvc.model.ToDoItem}
+ */
+ var model = (/**@type {todomvc.model.ToDoItem} */ control.getModel());
+
+ // do optimised model view sync
+ goog.array.remove(items, model);
+ container.removeChild(control, true);
+
+ updateStats();
+});
+
+/**
+ * @type {Element}
+ */
+var newToDo = document.getElementById('new-todo');
+goog.events.listen(newToDo, goog.events.EventType.KEYUP, function(e) {
+ if (e.keyCode === goog.events.KeyCodes.ENTER) {
+ /**
+ * @type {todomvc.model.ToDoItem}
+ */
+ var model = new todomvc.model.ToDoItem(newToDo.value);
+
+ /**
+ * @type {todomvc.view.ToDoItemControl}
+ */
+ var control = new todomvc.view.ToDoItemControl();
+
+ // do optimised model view sync
+ items.push(model);
+
+ control.setContent(model.getNote());
+ control.setChecked(model.isDone());
+ control.setModel(model);
+
+ container.addChild(control, true);
+
+ // clear the input box
+ newToDo.value = '';
+
+ updateStats();
+ }
+});
@@ -0,0 +1,52 @@
+goog.provide('todomvc.model.ToDoItem');
+
+/**
+ * The model object representing a todo item.
+ *
+ * @param {!string} note the text associated with this item
+ * @param {!boolean=} opt_done is this item complete? defaults to false
+ * @constructor
+ */
+todomvc.model.ToDoItem = function(note, opt_done) {
+ /**
+ * note the text associated with this item
+ * @private
+ * @type {!string}
+ */
+ this.note_ = note;
+
+ /**
+ * is this item complete?
+ * @private
+ * @type {!boolean}
+ */
+ this.done_ = opt_done || false;
+};
+
+/**
+ * @return {!string} the text associated with this item
+ */
+todomvc.model.ToDoItem.prototype.getNote = function() {
+ return this.note_;
+};
+
+/**
+ * @return {!boolean} is this item complete?
+ */
+todomvc.model.ToDoItem.prototype.isDone = function() {
+ return this.done_;
+};
+
+/**
+ * @param {!string} note the text associated with this item
+ */
+todomvc.model.ToDoItem.prototype.setNote = function(note) {
+ this.note_ = note;
+};
+
+/**
+ * @param {!boolean} done is this item complete?
+ */
+todomvc.model.ToDoItem.prototype.setDone = function(done) {
+ this.done_ = done;
+};
@@ -0,0 +1,64 @@
+goog.provide('todomvc.view.ClearCompletedControlRenderer');
+
+goog.require('goog.dom');
+goog.require('goog.ui.Component.State');
+goog.require('goog.ui.ControlRenderer');
+
+/**
+ * A renderer for the clear completed control.
+ *
+ * @constructor
+ * @extends {goog.ui.ControlRenderer}
+ */
+todomvc.view.ClearCompletedControlRenderer = function() {
+ goog.ui.ControlRenderer.call(this);
+};
+goog.inherits(todomvc.view.ClearCompletedControlRenderer, goog.ui.ControlRenderer);
+
+// add getInstance method to todomvc.view.ClearCompletedControlRenderer
+goog.addSingletonGetter(todomvc.view.ClearCompletedControlRenderer);
+
+/**
+ * @param {goog.ui.Control} control Control to render.
+ * @return {Element} Root element for the control.
+ */
+todomvc.view.ClearCompletedControlRenderer.prototype.createDom = function(control) {
+ var html = todomvc.view.clearCompleted({
+ number : control.getContent()
+ });
+ var element = (/**@type {!Element}*/ goog.dom.htmlToDocumentFragment(html));
+ this.setAriaStates(control, element);
+ return element;
+};
+
+/**
+ * @param {Element} element Element to decorate.
+ * @return {boolean} Whether the renderer can decorate the element.
+ */
+todomvc.view.ClearCompletedControlRenderer.prototype.canDecorate = function(element) {
+ return false;
+};
+
+/**
+ * @param {Element} element Element to populate.
+ * @param {goog.ui.ControlContent} content Text caption or DOM
+ */
+todomvc.view.ClearCompletedControlRenderer.prototype.setContent = function(element, content) {
+ element.innerHTML = todomvc.view.clearCompletedInner({
+ number : content
+ });
+};
+
+/**
+ * Updates the appearance of the control in response to a state change.
+ *
+ * @param {goog.ui.Control} control Control instance to update.
+ * @param {goog.ui.Component.State} state State to enable or disable.
+ * @param {boolean} enable Whether the control is entering or exiting the state.
+ */
+todomvc.view.ClearCompletedControlRenderer.prototype.setState = function(control, state, enable) {
+ var element = control.getElement();
+ if (element) {
+ this.updateAriaState(element, state, enable);
+ }
+};
@@ -0,0 +1,64 @@
+goog.provide('todomvc.view.ItemCountControlRenderer');
+
+goog.require('goog.dom');
+goog.require('goog.ui.Component.State');
+goog.require('goog.ui.ControlRenderer');
+
+/**
+ * A renderer for the item count control.
+ *
+ * @constructor
+ * @extends {goog.ui.ControlRenderer}
+ */
+todomvc.view.ItemCountControlRenderer = function() {
+ goog.ui.ControlRenderer.call(this);
+};
+goog.inherits(todomvc.view.ItemCountControlRenderer, goog.ui.ControlRenderer);
+
+// add getInstance method to todomvc.view.ItemCountControlRenderer
+goog.addSingletonGetter(todomvc.view.ItemCountControlRenderer);
+
+/**
+ * @param {goog.ui.Control} control Control to render.
+ * @return {Element} Root element for the control.
+ */
+todomvc.view.ItemCountControlRenderer.prototype.createDom = function(control) {
+ var html = todomvc.view.itemCount({
+ number : control.getContent()
+ });
+ var element = (/**@type {!Element}*/ goog.dom.htmlToDocumentFragment(html));
+ this.setAriaStates(control, element);
+ return element;
+};
+
+/**
+ * @param {Element} element Element to decorate.
+ * @return {boolean} Whether the renderer can decorate the element.
+ */
+todomvc.view.ItemCountControlRenderer.prototype.canDecorate = function(element) {
+ return false;
+};
+
+/**
+ * @param {Element} element Element to populate.
+ * @param {goog.ui.ControlContent} content Text caption or DOM
+ */
+todomvc.view.ItemCountControlRenderer.prototype.setContent = function(element, content) {
+ element.innerHTML = todomvc.view.itemCountInner({
+ number : content
+ });
+};
+
+/**
+ * Updates the appearance of the control in response to a state change.
+ *
+ * @param {goog.ui.Control} control Control instance to update.
+ * @param {goog.ui.Component.State} state State to enable or disable.
+ * @param {boolean} enable Whether the control is entering or exiting the state.
+ */
+todomvc.view.ItemCountControlRenderer.prototype.setState = function(control, state, enable) {
+ var element = control.getElement();
+ if (element) {
+ this.updateAriaState(element, state, enable);
+ }
+};
Oops, something went wrong.

0 comments on commit 526b9c4

Please sign in to comment.