Permalink
Browse files

DOH mobile demo test and required data binding engine change.

  • Loading branch information...
asudoh committed Feb 22, 2012
1 parent 29a1e99 commit 7c2e614048d93f5c8496652a0b4dfe702d7a92cb
Showing with 650 additions and 202 deletions.
  1. +2 −2 EditModelRefControllerMixin.js
  2. +91 −46 Generate.js
  3. +93 −50 ListControllerMixin.js
  4. +62 −21 ModelRefControllerMixin.js
  5. +2 −2 Repeat.js
  6. +12 −43 _atBindingMixin.js
  7. +344 −0 tests/doh_mvc_mobile-demo.html
  8. +1 −0 tests/module.js
  9. +43 −38 tests/moduleFullSet.js
@@ -12,7 +12,7 @@ define([
// The data serving as the data source.
this.set(this._refOriginalModelProp, this.holdModelUntilCommit ? value : this.cloneModel(value));
- this.set(this._refModelProp, this.holdModelUntilCommit ? this.cloneModel(value) : value);
+ this.set(this._refInModelProp, this.holdModelUntilCommit ? this.cloneModel(value) : value);
this._set(this._refSourceModelProp, value);
}
@@ -76,7 +76,7 @@ define([
// Send the change back to the data source.
this.set(this.holdModelUntilCommit ? this._refSourceModelProp : this._refOriginalModelProp,
- this.holdModelUntilCommit ? this.get(this._refModelProp) : this.cloneModel(this.get(this._refModelProp)));
+ this.holdModelUntilCommit ? this.get(this._refInModelProp) : this.cloneModel(this.get(this._refInModelProp)));
},
reset: function(){
View
@@ -1,10 +1,12 @@
define([
+ "dojo/_base/array",
"dojo/_base/lang",
"dojo/_base/declare",
"./_Container",
+ "./at",
"./Group",
"dijit/form/TextBox"
-], function(lang, declare, Container){
+], function(array, lang, declare, Container){
/*=====
Container = dojox.mvc._Container;
declare = dojo.declare;
@@ -39,115 +41,158 @@ define([
// The mapping of id and name to use. Set idNameMapping to override this. A count will be added to the id and name
//
_defaultIdNameMapping: {"String" : "textbox_t"},
-
+
+ // children: dojo.Stateful
+ // The array of data model that is used to render child nodes.
+ children: null,
+
+ // _relTargetProp: String
+ // The name of the property that is used by child widgets for relative data binding.
+ _relTargetProp : "children",
+
////////////////////// PRIVATE METHODS ////////////////////////
-
- _updateBinding: function(){
+
+ _setChildrenAttr: function(/*dojo.Stateful*/ value){
// summary:
- // Regenerate if the binding changes.
- this.inherited(arguments);
- this._buildContained();
+ // Handler for calls to set("children", val).
+ // description:
+ // Sets "ref" property so that child widgets can refer to, and then rebuilds the children.
+
+ var children = this.children;
+ this._set("children", value);
+ // this.binding is the resolved ref, so not matching with the new value means change in repeat target.
+ if(this.binding != value){
+ this.set("ref", value);
+ }
+ if(this._started && (!this._builtOnce || children != value)){
+ this._builtOnce = true;
+ this._buildContained(value);
+ }
},
- _buildContained: function(){
+ _buildContained: function(/*dojo.Stateful*/ children){
// summary:
// Destroy any existing generated view, recreate it from scratch
// parse the new contents.
+ // children: dojo.Stateful
+ // The array of child widgets.
// tags:
// private
+
+ if(!children){ return; }
+
this._destroyBody();
this._counter = 0;
- this.srcNodeRef.innerHTML = this._generateBody(this.get("binding"));
+ this.srcNodeRef.innerHTML = this._generateBody(children);
this._createBody();
},
- _generateBody: function(binding, hideHeading){
+ _generateBody: function(/*dojo.Stateful*/ children, /*Boolean*/ hideHeading){
// summary:
// Generate the markup for the view associated with this generate
// container.
- // binding:
- // The associated data binding to generate a view for.
- // hideHeading:
+ // children: dojo.Stateful
+ // The associated data to generate a view for.
+ // hideHeading: Boolean
// Whether the property name should be displayed as a heading.
// tags:
// private
- var body = "";
- for(var prop in binding){
- if(binding[prop] && lang.isFunction(binding[prop].toPlainObject)){
- if(binding[prop].get(0)){
- body += this._generateRepeat(binding[prop], prop);
- }else if(binding[prop].value){
+
+ if(children === void 0){ return ""; }
+
+ var body = [];
+ var isStatefulModel = lang.isFunction(children.toPlainObject);
+
+ function generateElement(value, prop){
+ if(isStatefulModel ? (value && lang.isFunction(value.toPlainObject)) : !lang.isFunction(value)){
+ if(lang.isArray(value)){
+ body.push(this._generateRepeat(value, prop));
+ }else if(isStatefulModel ? value.value : ({}.toString.call(value) != "[object Object]" && (!(value || {}).set || !(value || {}).watch))){
// TODO: Data types based widgets
- body += this._generateTextBox(prop);
+ body.push(this._generateTextBox(prop, isStatefulModel));
}else{
- body += this._generateGroup(binding[prop], prop, hideHeading);
+ body.push(this._generateGroup(value, prop, hideHeading));
+ }
+ }
+ }
+
+ if(lang.isArray(children)){
+ array.forEach(children, generateElement, this);
+ }else{
+ for(var s in children){
+ if(children.hasOwnProperty(s)){
+ generateElement.call(this, children[s], s);
}
}
}
- return body;
+
+ return body.join("");
},
- _generateRepeat: function(binding, repeatHeading){
+ _generateRepeat: function(/*dojox.mvc.StatefulArray*/ children, /*String*/ repeatHeading){
// summary:
// Generate a repeating model-bound view.
- // binding:
+ // children: dojox.mvc.StatefulArray
// The bound node (a collection/array node) to generate a
// repeating UI/view for.
- // repeatHeading:
+ // repeatHeading: String
// The heading to be used for this portion.
// tags:
// private
+
var headingClass = (this.classMapping && this.classMapping["Heading"]) ? this.classMapping["Heading"] : this._defaultClassMapping["Heading"];
- var repeat = '<div data-dojo-type="dojox.mvc.Group" data-dojo-props="ref: \'' + repeatHeading + '\'" + id="' + this.id + '_r' + this._counter++ + '">' +
- '<div class="' + headingClass + '\">' + repeatHeading + '</div>';
- repeat += this._generateBody(binding, true);
- repeat += '</div>';
- return repeat;
+ return '<div data-dojo-type="dojox.mvc.Group" data-dojo-props="target: dojox.mvc.at(\'rel:\', \'' + repeatHeading + '\')" + id="' + this.id + '_r' + this._counter++ + '">'
+ + '<div class="' + headingClass + '\">' + repeatHeading + '</div>'
+ + this._generateBody(children, true)
+ + '</div>';
},
- _generateGroup: function(binding, groupHeading, hideHeading){
+ _generateGroup: function(/*dojo.Stateful*/ model, /*String*/ groupHeading, /*Boolean*/ hideHeading){
// summary:
// Generate a hierarchical model-bound view.
- // binding:
- // The bound (intermediate) node to generate a hierarchical
- // view portion for.
- // groupHeading:
+ // model: dojo.Stateful
+ // The bound (intermediate) model to generate a hierarchical view portion for.
+ // groupHeading: String
// The heading to be used for this portion.
- // hideHeading:
+ // hideHeading: Boolean
// Whether the heading should be hidden for this portion.
// tags:
// private
- var group = '<div data-dojo-type="dojox.mvc.Group" data-dojo-props="ref: \'' + groupHeading + '\'" + id="' + this.id + '_g' + this._counter++ + '">';
+
+ var html = ['<div data-dojo-type="dojox.mvc.Group" data-dojo-props="target: dojox.mvc.at(\'rel:\', \'' + groupHeading + '\')" + id="' + this.id + '_g' + this._counter++ + '">'];
if(!hideHeading){
var headingClass = (this.classMapping && this.classMapping["Heading"]) ? this.classMapping["Heading"] : this._defaultClassMapping["Heading"];
- group += '<div class="' + headingClass + '\">' + groupHeading + '</div>';
+ html.push('<div class="' + headingClass + '\">' + groupHeading + '</div>');
}
- group += this._generateBody(binding);
- group += '</div>';
- return group;
+ html.push(this._generateBody(model) + '</div>');
+ return html.join("");
},
- _generateTextBox: function(prop){
+ _generateTextBox: function(/*String*/ prop, /*Boolean*/ referToValue){
// summary:
// Produce a widget for a simple value.
- // prop:
+ // prop: String
// The data model property name.
+ // referToValue: Boolean
+ // True if the property is dojox.mvc.StatefulModel with "value" attribute.
// tags:
// private
// TODO: Data type based widget generation / enhanced meta-data
+
var idname = this.idNameMapping ? this.idNameMapping["String"] : this._defaultIdNameMapping["String"];
idname = idname + this._counter++;
var widClass = this.widgetMapping ? this.widgetMapping["String"] : this._defaultWidgetMapping["String"];
var labelClass = (this.classMapping && this.classMapping["Label"]) ? this.classMapping["Label"] : this._defaultClassMapping["Label"];
var stringClass = (this.classMapping && this.classMapping["String"]) ? this.classMapping["String"] : this._defaultClassMapping["String"];
var rowClass = (this.classMapping && this.classMapping["Row"]) ? this.classMapping["Row"] : this._defaultClassMapping["Row"];
-
+ var bindingSyntax = 'value: dojox.mvc.at(\'rel:' + (referToValue && prop || '') + '\', \'' + (referToValue ? 'value' : prop) + '\')';
+
return '<div class="' + rowClass + '\">' +
'<label class="' + labelClass + '\">' + prop + ':</label>' +
- '<input class="' + stringClass + '\" data-dojo-type="' + widClass + '\" data-dojo-props="name: \'' + idname + "', ref: '" + prop + '\'" id="' +
- idname + '\"></input>' +
+ '<input class="' + stringClass + '\" data-dojo-type="' + widClass + '\"' +
+ ' data-dojo-props="name: \'' + idname + '\', ' + bindingSyntax + '" id="' + idname + '\"></input>' +
'</div>';
}
});
Oops, something went wrong.

0 comments on commit 7c2e614

Please sign in to comment.