Commit b6e14c17 authored by asudoh's avatar asudoh

Separate data binding definitions from templates.

parent 31af9f78
......@@ -39,7 +39,8 @@
parseOnLoad: true,
locale: "en",
paths: {
"dijit": "../dijit-1.8"
"dijit": "../dijit-1.8",
"todo": "../../todo"
},
deps: ["dojo/parser", "dojo/domReady!"],
mvc: {debugBindings: true}
......
This source diff could not be displayed because it is too large. You can view the blob instead.
define([
"dojo/_base/declare",
"dojo/_base/lang",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dijit/_WidgetsInTemplateMixin",
"dojox/mvc/at"
], function(declare, lang, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, at){
return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], {
// summary:
// A templated widget, mostly the same as dijit/_Templated, but without deprecated features in it.
// bindings: Object
// The data binding declaration for child widgets.
bindings: null,
startup: function(){
// Code to support childBindings property in dojox/mvc/WidgetList, etc.
// This implementation makes sure childBindings is set before this widget starts up, as dijit/_WidgetsInTemplatedMixin starts up child widgets before it starts itself up.
for(var s in this.bindings){
var w = this[s], props = this.bindings[s];
if(w){
for(var prop in props){
w.set(prop, props[prop]);
}
}
}
this.inherited(arguments);
}
});
});
define(["dojo/_base/declare"], function(declare){
define([
"dojo/_base/declare",
"dojox/mvc/at",
"todo/_CssToggleMixin",
"todo/Templated"
], function(declare, at, _CssToggleMixin, Templated){
var ACTIVE = "/active",
COMPLETED = "/completed";
......@@ -13,15 +18,24 @@ define(["dojo/_base/declare"], function(declare){
false;
}
return declare(null, {
return declare([Templated, _CssToggleMixin], {
// summary:
// A mix-in class for widgets-in-template for todo item, that looks at URL hash and completed state of todo item, and updates the hidden state.
// The widgets-in-template for todo item.
// description:
// A todo item should be hidden if:
// Defines data bindings for uniqueId/completed, and the mapping between several widget attributes to CSS classes (using todo/_CssToggleMixin).
// Also, looks at URL hash and completed state of todo item, and updates the hidden state. A todo item should be hidden if:
//
// - URL hash is "/active" and the todo item is complete -OR-
// - URL hash is "/copleted" and the todo item is incomplete
// _setStrikeAttr: Object
// A object used by todo/_CssToggleMixin to reflect true/false state of "strike" attribute to existence of "completed" CSS class in this widget's root DOM.
_setStrikeAttr: {type: "classExists", className: "completed"},
// _setHiddenAttr: Object
// A object used by todo/_CssToggleMixin to reflect true/false state of "hidden" attribute to existence of "hidden" CSS class in this widget's root DOM.
_setHiddenAttr: {type: "classExists", className: "hidden"},
_setHashAttr: function(/*String*/ value){
// summary:
// Handler for calls to set("hash", val), to update hidden state given the new value and the completed state.
......@@ -35,7 +49,26 @@ define(["dojo/_base/declare"], function(declare){
// Handler for calls to set("completed", val), to update hidden state given the new value and the hash.
this.set("hidden", getHiddenState({hash: this.hash, completed: value})); // Update hidden state given the new value and the hash
this.set("strike", value); // Update completed strike-through
this._set("completed", value); // Assign the new value to the attribute
},
startup: function(){
// summary:
// A function called after the DOM fragment declaring this controller is added to the document, in a similar manner as dijit/_WidgetBase.startup().
// description:
// Defines data binding for uniqueId/completed.
this.set("uniqueId", at(this.target, "uniqueId")); // Bind its uniqueId attribute to the data model for the todo item, so that the action handler for removing a todo item can specify which todo item should be removed
this.set("completed", at(this.target, "completed")); // Bind its completed attribute to the data model for the todo item, so that todo/ctrl/_HashCompletedMixin code can determine the shown/hidden state with the URL hash
this.inherited(arguments);
},
removeItem: function(){
// summary:
// Implements an action to remove a todo item.
this.listCtrl.removeItem(this.uniqueId);
}
});
});
......@@ -5,42 +5,38 @@
data-dojo-id creates object reference of the widget. Though TodoMVC application does not have multiple instances of this widgets-in-template, "${id}_" prefix is added to data-dojo-id attribute to avoid ID duplication.
-->
<!--
This <script> tag assigns module references to variables that can be used in this template. The modules used here are:
This <script> tag assigns module references to variables that can be used in this template, as well as the parameter file for the data binding setting, etc. (app18bindings.json) for this template.
The modules used here are:
- dojo/_base/lang: A utility library containing a function to control what object "this" in a function points to
- dojox/mvc/at: Function to create a pointer to dojo/Stateful, for the purpose of data binding
- todo/model/SimpleTodoModel: The data model class for TodoMVC data
- todo/misc/HashSelectedConverter: dojox/mvc data converter for widgets of the <a> tags for All/Active/Completed, for the selected state of the <a> tags
- todo/misc/LessThanOrEqualToConverter: dojox/mvc data converter for the shown/hidden state of "s" in "items left", as well as for the check box to mark all todo items complete/incomplete
-->
<script type="dojo/require">
lang: "dojo/_base/lang",
at: "dojox/mvc/at",
SimpleTodoModel: "todo/model/SimpleTodoModel",
HashSelectedConverter: "todo/misc/HashSelectedConverter",
LessThanOrEqualToConverter: "todo/misc/LessThanOrEqualToConverter"
</script>
<!-- A controller that keeps its hash attribute in sync with the URL hash -->
<span data-dojo-id="${id}_routeCtl"
<span data-dojo-attach-point="routeCtrl"
data-dojo-type="todo/ctrl/RouteController"></span>
<!-- A Dojo Object Store for fetching/saving data from/to localStorage -->
<span data-dojo-id="${id}_localStorage"
data-dojo-type="todo/store/LocalStorage"></span>
<!--
Our custom controller, based on dojox/mvc/EditStoreRefController, that loads and saves data using a Dojo Object Store, and provides references to the data model (from the Dojo Object Store).
The complete attribute (count of completed todo items, coming as a reference in the data model) is bound to the parent widgets-in-template, so that it can update a CSS class in its root DOM node.
-->
<span data-dojo-id="${id}_ctrl"
<!-- Our custom controller, based on dojox/mvc/EditStoreRefController, that loads and saves data using a Dojo Object Store, and provides references to the data model (from the Dojo Object Store). -->
<span data-dojo-attach-point="ctrl"
data-dojo-type="todo/ctrl/TodoRefController"
data-dojo-props="defaultId: 'todos-dojo', store: ${id}_localStorage, modelClass: SimpleTodoModel,
complete: at('widget:${id}', 'complete')"></span>
<!--
Our custom controller, based on dojox/mvc/ModelRefController, that provides references to the todo list in data model, and handles actions like adding/removing/marking.
The model attribute (the todo list in data model) is bound to above todo/ctrl/TodoRefController instance, so that it's updated as soon as todo/ctrl/TodoRefController obtains the data from Dojo Object Store.
The length attribute (count of all todo items, coming as a reference in the todo list in the data model) is bound to the parent widgets-in-template, so that it can update a CSS class in its root DOM node.
-->
data-dojo-props="store: ${id}_localStorage,
modelClass: SimpleTodoModel,
defaultId: 'todos-dojo'"></span>
<!-- Our custom controller, based on dojox/mvc/ModelRefController, that provides references to the todo list in data model, and handles actions like adding/removing/marking. -->
<span data-dojo-id="${id}_listCtrl"
data-dojo-type="todo/ctrl/TodoListRefController"
data-dojo-props="model: at(${id}_ctrl, 'todos'),
length: at('widget:${id}', 'present').direction(at.to)"></span>
data-dojo-attach-point="listCtrl"
data-dojo-type="todo/ctrl/TodoListRefController"></span>
<header id="header">
<h1>todos</h1>
<!--
......@@ -52,41 +48,19 @@
<span class="ui-tooltip-top" style="display:none;">Press Enter to save this task</span>
</header>
<section id="main">
<!--
The check box to mark todo items complete/incomplete.
It's automatically checked when there is no incomplete items, by the data binding to the count of incomplete todo items (via the todo/ctrl/TodoRefController instance), which is converted to a boolean state representing whether there is no incomplete todo items.
-->
<input id="toggle-all" type="checkbox"
data-dojo-type="dijit/form/CheckBox"
data-dojo-props="checked: at(${id}_ctrl, 'incomplete').transform(LessThanOrEqualToConverter),
onClick: function(e){ ${id}_listCtrl.markAll(e.target.checked); }">
data-dojo-attach-point="toggleAll"
data-dojo-type="dijit/form/CheckBox">
<label for="toggle-all">Mark all as complete</label>
<!--
The todo list UI, composed by repeating <li> for each todo item with dojox/mvc/WidgetList.
The children attribute (the list of the todo items) is bound to the todo/ctrl/TodoListRefController instance, so that it's updated as soon as todo/ctrl/TodoRefController obtains the data from Dojo Object Store.
The todo UI, composed by repeating <li> for each todo item with dojox/mvc/WidgetList.
Each <li> is created along with a widgets-in-template associated with it.
Each widgets-in-template here does:
- Associate completed attribute to the existence of "completed" CSS class of its root DOM node (Such association is used by todo/_CssToggleMixin code)
- Associate hidden attribute to the existence of "hidden" CSS class of its root DOM node (Such association is used by todo/_CssToggleMixin code)
- Mix-in in todo/_CssToggleMixin as well as todo/ctrl/_HashCompletedMixin, so that the combination of URL hash and todo item's completed state will end up with the shown/hidden states being updated (by adding/removing "hidden" CSS class)
- Bind its uniqueId attribute to the data model for the todo item, so that the action handler for removing a todo item can specify which todo item should be removed
- Bind its completed attribute to the data model for the todo item, so that todo/ctrl/_HashCompletedMixin code can determine the shown/hidden state with the URL hash
- Bind its hash attribute to the todo/ctrl/RouteController instance, so that todo/ctrl/_HashCompletedMixin code can determine the shown/hidden state with the completed state
-->
<ul id="todo-list"
data-dojo-attach-point="todoList"
data-dojo-type="dojox/mvc/WidgetList"
data-dojo-mixins="dojox/mvc/_InlineTemplateMixin"
data-dojo-props="children: at(${id}_listCtrl, 'model'),
partialRebuild: true"
data-mvc-child-type="dijit/_WidgetBase"
data-mvc-child-mixins="dijit/_TemplatedMixin,dijit/_WidgetsInTemplateMixin,todo/_CssToggleMixin,todo/ctrl/_HashCompletedMixin"
data-mvc-child-props="_setCompletedAttr: {type: 'classExists', className: 'completed'},
_setHiddenAttr: {type: 'classExists', className: 'hidden'},
uniqueId: at(this.target, 'uniqueId'),
completed: at(this.target, 'completed'),
hash: at(${id}_routeCtl, 'hash'),
onRemoveClick: function(){ ${id}_listCtrl.removeItem(this.uniqueId); }">
data-mvc-child-type="todo/TodoListItem">
<!--
dojox/mvc/_InlineTemplateMixin picks up the contents in <script type="dojox/mvc/InlineTemplate"> as the template string.
dojox/mvc/WidgetList used its template string for each child widget.
......@@ -94,25 +68,15 @@
<script type="dojox/mvc/InlineTemplate">
<li>
<div class="view">
<!--
The title of the todo item, with in-line editing feature.
The value attribute is bound to the data model for the todo item, so that the title of the todo item is in sync with the data model.
The uniqueId attribute is bound to the data model for the todo item, so that the action handler for removing the todo item (when its title is empty) can specify which todo item should be removed.
-->
<!-- The title of the todo item, with in-line editing feature. -->
<label class="dijitInline inline_edit"
data-dojo-type="todo/form/InlineEditBox"
data-dojo-props="value: at('rel:', 'title'),
uniqueId: at('rel:', 'uniqueId'),
editor: 'dijit/form/TextBox',
autosave: true,
onChange: function(){ if(!this.value){ ${id}_listCtrl.removeItem(this.uniqueId); return false; } }"></label>
<!--
The check box indicating whether the todo item is completed or not.
The checked attribute is bound to the data model for the todo item, so that the checked state is in sync with the completed state in the data model.
-->
data-dojo-attach-point="editBox"
data-dojo-type="todo/form/InlineEditBox"></label>
<!-- The check box indicating whether the todo item is completed or not. -->
<input class="toggle" type="checkbox"
data-dojo-type="dijit/form/CheckBox" data-dojo-props="checked: at('rel:', 'completed')">
<button class="destroy" data-dojo-attach-event="onclick: onRemoveClick"></button>
data-dojo-attach-point="checkBox"
data-dojo-type="dijit/form/CheckBox">
<button class="destroy" data-dojo-attach-event="onclick: removeItem"></button>
</div>
</li>
</script>
......@@ -121,76 +85,43 @@
<footer id="footer">
<span id="todo-count">
<strong>
<!--
The count of incomplete todo items.
The value attribute is associated with the text in this widget, and bound to the todo/ctrl/TodoRefController instance, so that the count of incomplete todo items is updated as soon as todo/ctrl/TodoRefController obtains the data from Dojo Object Store.
-->
<span class="number"
data-dojo-type="dijit/_WidgetBase"
data-dojo-props="_setValueAttr: {type: 'innerText', node: 'domNode'}, value: at(${id}_ctrl, 'incomplete')"></span>
data-dojo-attach-point="countIncompleteItems"
data-dojo-type="dijit/_WidgetBase"></span>
</strong>
<span class="word">item<!--
The 's' in "items".
The single attribute is associated with the existence of "plural" CSS class of its root DOM node. (Such association is used by todo/_CssToggleMixin code)
The single attribute is bound to the todo/ctrl/TodoRefController instance, so that the state whether the count of incomplete todo item is less than or equal to 1 is updated as soon as todo/ctrl/TodoRefController obtains the data from Dojo Object Store.
--><span data-dojo-type="dijit/_WidgetBase"
data-dojo-mixins="todo/_CssToggleMixin"
data-dojo-props="_setSingleAttr: {type: 'classExists', className: 'plural'},
constraints: {lessThanOrEqualTo: 1},
single: at(${id}_ctrl, 'incomplete').transform(LessThanOrEqualToConverter)">s</span></span>
--><span data-dojo-attach-point="pluralIncompleteItems"
data-dojo-type="dijit/_WidgetBase"
data-dojo-mixins="todo/_CssToggleMixin">s</span></span>
left.
</span>
<!-- Remove this if you don't implement routing -->
<ul id="filters">
<li>
<!--
The link to show all todo items.
The selected attribute is associated with the existence of "selected" CSS class of its root DOM node. (Such association is used by todo/_CssToggleMixin code)
The selected attribute is bound to todo/ctrl/RouteController instance, so that change in URL hash will be reflected here.
The URL hash is converted to the state whether the hash matches to the href here, by HashSelectedConverter (a dojox/mvc data converter).
-->
<a href="#/"
data-dojo-attach-point="hashAll"
data-dojo-type="dijit/_WidgetBase"
data-dojo-mixins="todo/_CssToggleMixin"
data-dojo-props="_setSelectedAttr: {type: 'classExists', className: 'selected'},
selected: at(${id}_routeCtl, 'hash').transform(HashSelectedConverter)">All</a>
data-dojo-mixins="todo/_CssToggleMixin">All</a>
</li>
<li>
<!--
The link to show all todo items.
The selected attribute is associated with the existence of "selected" CSS class of its root DOM node. (Such association is used by todo/_CssToggleMixin code)
The selected attribute is bound to todo/ctrl/RouteController instance, so that change in URL hash will be reflected here.
The URL hash is converted to the state whether the hash matches to the href here, by HashSelectedConverter (a dojox/mvc data converter).
-->
<a href="#/active"
data-dojo-attach-point="hashActive"
data-dojo-type="dijit/_WidgetBase"
data-dojo-mixins="todo/_CssToggleMixin"
data-dojo-props="_setSelectedAttr: {type: 'classExists', className: 'selected'},
selected: at(${id}_routeCtl, 'hash').transform(HashSelectedConverter)">Active</a>
data-dojo-mixins="todo/_CssToggleMixin">Active</a>
</li>
<li>
<!--
The link to show all todo items.
The selected attribute is associated with the existence of "selected" CSS class of its root DOM node. (Such association is used by todo/_CssToggleMixin code)
The selected attribute is bound to todo/ctrl/RouteController instance, so that change in URL hash will be reflected here.
The URL hash is converted to the state whether the hash matches to the href here, by HashSelectedConverter (a dojox/mvc data converter).
-->
<a href="#/completed"
data-dojo-attach-point="hashCompleted"
data-dojo-type="dijit/_WidgetBase"
data-dojo-mixins="todo/_CssToggleMixin"
data-dojo-props="_setSelectedAttr: {type: 'classExists', className: 'selected'},
selected: at(${id}_routeCtl, 'hash').transform(HashSelectedConverter)">Completed</a>
data-dojo-props="">Completed</a>
</li>
</ul>
<button id="clear-completed" onclick="${id}_listCtrl.removeCompletedItems();">
Clear completed (
<!--
The count of completed todo items.
The value attribute is associated with the text in this widget, and bound to the todo/ctrl/TodoRefController instance, so that the count of completed todo items is updated as soon as todo/ctrl/TodoRefController obtains the data from Dojo Object Store.
-->
<span class="number-done"
data-dojo-type="dijit/_WidgetBase"
data-dojo-props="_setValueAttr: {type: 'innerText', node: 'domNode'}, value: at(${id}_ctrl, 'complete')"></span>
data-dojo-attach-point="countCompleted"
data-dojo-type="dijit/_WidgetBase"></span>
)
</button>
</footer>
......
define([
"dojo/_base/declare",
"dojo/_base/lang",
"dojo/_base/unload",
"dojo/keys",
"dojo/string",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dijit/_WidgetsInTemplateMixin",
"todo/Templated",
"todo/_CssToggleMixin",
"dojo/text!./app18.html",
"dojo/text!./app18bindings.json",
// Below modules are referred in template.
// dijit/_WidgetsInTemplateMixin requires all modules referred in template to have been loaded before it's instantiated.
"dijit/form/CheckBox",
......@@ -16,7 +14,7 @@ define([
"dojox/mvc/at",
"dojox/mvc/_InlineTemplateMixin",
"dojox/mvc/WidgetList",
"todo/ctrl/_HashCompletedMixin",
"todo/TodoListItem",
"todo/ctrl/RouteController",
"todo/ctrl/TodoListRefController",
"todo/ctrl/TodoRefController",
......@@ -25,8 +23,10 @@ define([
"todo/misc/LessThanOrEqualToConverter",
"todo/model/SimpleTodoModel",
"todo/store/LocalStorage"
], function(declare, lang, unload, keys, string, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, _CssToggleMixin, template){
return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, _CssToggleMixin], {
], function(declare, unload, keys, string, Templated, _CssToggleMixin, template, bindings){
function runEval(js){ return eval(js); } // To let eval script point to app18 instance as "this"
return declare([Templated, _CssToggleMixin], {
// summary:
// A widgets-in-template widget that composes the application UI of TodoMVC (Dojo 1.8 version).
// Also, this class inherits todo/_CssToggleMixin so that it can react to change in "present"/"complete" attributes and add/remove CSS class to the root DOM node of this widget.
......@@ -49,6 +49,7 @@ define([
// See documentation for dijit/_WidgetBase.startup() for more details.
var _self = this;
this.bindings = runEval.call(this, "(" + bindings + ")");
this.inherited(arguments);
unload.addOnUnload(function(){
_self.destroy(); // When this page is being unloaded, call destroy callbacks of inner-widgets to let them clean up
......@@ -65,7 +66,7 @@ define([
return; // If the key is not Enter, or the input field is empty, bail
}
lang.getObject(this.id + "_listCtrl").addItem(event.target.value); // Add a todo item with the given text
this.listCtrl.addItem(event.target.value); // Add a todo item with the given text
event.target.value = ""; // Clear the input field
event.preventDefault();
event.stopPropagation();
......
// This file defines data binding, etc. settings for child widgets in app18.html template.
// The 1st-level object key here (ctrl/listCtrl, etc.) is the data-dojo-attach-point set in app18.html.
{
// Our custom controller, based on dojox/mvc/EditStoreRefController, that loads and saves data using a Dojo Object Store, and provides references to the data model (from the Dojo Object Store).
ctrl: {
// The complete attribute (count of completed todo items, coming as a reference in the data model) is bound to the parent widgets-in-template, so that it can update a CSS class in its root DOM node.
complete: at(this, "complete")
},
// Our custom controller, based on dojox/mvc/ModelRefController, that provides references to the todo list in data model, and handles actions like adding/removing/marking.
listCtrl: {
// The model attribute (the todo list in data model) is bound to above todo/ctrl/TodoRefController instance, so that it's updated as soon as todo/ctrl/TodoRefController obtains the data from Dojo Object Store.
model: at(this.ctrl, "todos"),
// The length attribute (count of all todo items, coming as a reference in the todo list in the data model) is bound to the parent widgets-in-template, so that it can update a CSS class in its root DOM node.
length: at(this, "present").direction(at.to)
},
// The check box to mark todo items complete/incomplete.
toggleAll: {
// It's automatically checked when there is no incomplete items, by the data binding to the count of incomplete todo items (via the todo/ctrl/TodoRefController instance), which is converted to a boolean state representing whether there is no incomplete todo items.
checked: at(this.ctrl, "incomplete").transform(LessThanOrEqualToConverter),
onClick: lang.hitch(this, function(e){ this.listCtrl.markAll(e.target.checked); })
},
// The todo list UI.
todoList: {
// The children attribute (the list of the todo items) is bound to the todo/ctrl/TodoListRefController instance, so that it's updated as soon as todo/ctrl/TodoRefController obtains the data from Dojo Object Store.
children: at(this.listCtrl, "model"),
partialRebuild: true,
childParams: {
listCtrl: this.listCtrl,
// Bind hash attribute to the todo/ctrl/RouteController instance, so that todo/ctrl/_HashCompletedMixin code can determine the shown/hidden state with the completed state
hash: at(this.routeCtrl, "hash")
},
childBindings: {
editBox: {
// The value attribute is bound to the data model for the todo item, so that the title of the todo item is in sync with the data model.
value: at("rel:", "title"),
// The uniqueId attribute is bound to the data model for the todo item, so that the action handler for removing the todo item (when its title is empty) can specify which todo item should be removed.
uniqueId: at("rel:", "uniqueId"),
editor: "dijit/form/TextBox",
autosave: true,
listCtrl: this.listCtrl,
onChange: function(){ if(!this.value){ this.listCtrl.removeItem(this.uniqueId); return false; } }
},
checkBox: {
// The checked attribute is bound to the data model for the todo item, so that the checked state is in sync with the completed state in the data model.
checked: at("rel:", "completed")
}
}
},
// The count of incomplete todo items.
countIncompleteItems: {
// The value attribute is associated with the text in this widget, and bound to the todo/ctrl/TodoRefController instance, so that the count of incomplete todo items is updated as soon as todo/ctrl/TodoRefController obtains the data from Dojo Object Store.
_setValueAttr: {type: "innerText", node: "domNode"},
value: at(this.ctrl, "incomplete")
},
// The 's' in "items" showing the count of incomplete todo items.
pluralIncompleteItems: {
// The single attribute is associated with the existence of "plural" CSS class of its root DOM node. (Such association is used by todo/_CssToggleMixin code)
_setSingleAttr: {type: "classExists", className: "plural"},
// The single attribute is bound to the todo/ctrl/TodoRefController instance, so that the state whether the count of incomplete todo item is less than or equal to 1 is updated as soon as todo/ctrl/TodoRefController obtains the data from Dojo Object Store.
single: at(this.ctrl, "incomplete").transform(LessThanOrEqualToConverter),
constraints: {lessThanOrEqualTo: 1}
},
// The link to show all todo items.
hashAll: {
// The selected attribute is associated with the existence of "selected" CSS class of its root DOM node. (Such association is used by todo/_CssToggleMixin code)
_setSelectedAttr: {type: "classExists", className: "selected"},
// The selected attribute is bound to todo/ctrl/RouteController instance, so that change in URL hash will be reflected here.
// The URL hash is converted to the state whether the hash matches to the href here, by HashSelectedConverter (a dojox/mvc data converter).
selected: at(this.routeCtrl, "hash").transform(HashSelectedConverter)
},
// The link to show incomplete todo items.
hashActive: {
// The selected attribute is associated with the existence of "selected" CSS class of its root DOM node. (Such association is used by todo/_CssToggleMixin code)
_setSelectedAttr: {type: "classExists", className: "selected"},
// The selected attribute is bound to todo/ctrl/RouteController instance, so that change in URL hash will be reflected here.
// The URL hash is converted to the state whether the hash matches to the href here, by HashSelectedConverter (a dojox/mvc data converter).
selected: at(this.routeCtrl, "hash").transform(HashSelectedConverter)
},
// The link to show completed todo items.
hashCompleted: {
// The selected attribute is associated with the existence of "selected" CSS class of its root DOM node. (Such association is used by todo/_CssToggleMixin code)
_setSelectedAttr: {type: "classExists", className: "selected"},
// The selected attribute is bound to todo/ctrl/RouteController instance, so that change in URL hash will be reflected here.
// The URL hash is converted to the state whether the hash matches to the href here, by HashSelectedConverter (a dojox/mvc data converter).
selected: at(this.routeCtrl, "hash").transform(HashSelectedConverter)
},
// The count of completed todo items.
countCompleted: {
// The value attribute is associated with the text in this widget, and bound to the todo/ctrl/TodoRefController instance, so that the count of completed todo items is updated as soon as todo/ctrl/TodoRefController obtains the data from Dojo Object Store.
_setValueAttr: {type: "innerText", node: "domNode"},
value: at(this.ctrl, "complete")
}
}
......@@ -47,6 +47,7 @@ define([
}));
router.startup(); // Activate dojo/router
this.set("hash", router._currentPath); // Set the inital value of hash property
this._started = true;
},
_setHashAttr: function(value){
......
......@@ -16,6 +16,26 @@ define([
// Actions are implemented in the manner of manipulating array.
// The change will automatically be reflected to the UI via the notification system of dojox/mvc/StatefulArray.
postscript: function(/*Object?*/ params, /*DOMNode?*/ srcNodeRef){
// summary:
// Kicks off instantiation of this controller, in a similar manner as dijit/_WidgetBase.postscript().
// params: Object?
// The optional parameters for this controller.
// srcNodeRef: DOMNode?
// The DOM node declaring this controller. Set if this controller is created via Dojo parser.
this.inherited(arguments);
srcNodeRef && srcNodeRef.setAttribute("widgetId", this.id); // If this is created via Dojo parser, set widgetId attribute so that destroyDescendants() of parent widget works
},
startup: function(){
// summary:
// A function called after the DOM fragment declaring this controller is added to the document, in a similar manner as dijit/_WidgetBase.startup().
this.inherited(arguments);
this._started = true;
},
addItem: function(/*String*/ title){
// summary:
// Adds a todo item with the given title.
......@@ -59,6 +79,15 @@ define([
array.forEach(this[this._refModelProp], function(item){
item.set("completed", markComplete);
});
},
hasControllerProperty: function(/*String*/ name){
// summary:
// Returns true if this controller itself owns the given property.
// name: String
// The property name.
return this.inherited(arguments) || /^dojoAttach(Point|Event)$/i.test(name); // Let dojoAttachPoint/dojoAttachEvent be this controller's property
}
});
});
......@@ -74,6 +74,7 @@ define([
this.inherited(arguments);
this.getStore(this.defaultId); // Obtain data from Dojo Object Store as soon as this starts up
this._started = true;
},
set: function(/*String*/ name, /*Anything*/ value){
......@@ -86,6 +87,15 @@ define([
this.inherited(arguments);
},
hasControllerProperty: function(/*String*/ name){
// summary:
// Returns true if this controller itself owns the given property.
// name: String
// The property name.
return this.inherited(arguments) || /^dojoAttach(Point|Event)$/i.test(name); // Let dojoAttachPoint/dojoAttachEvent be this controller's property
},
destroy: function(){
// summary:
// A function called when this controller is being destroyed, in a similar manner as dijit/_WidgetBase.destroy().
......
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