source: Dev/trunk/src/client/dojox/mvc/Generate.js @ 536

Last change on this file since 536 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 7.4 KB
Line 
1define([
2        "dojo/_base/array",
3        "dojo/_base/lang",
4        "dojo/_base/declare",
5        "./_Container",
6        "./at",
7        "./Group",
8        "dijit/form/TextBox"
9], function(array, lang, declare, Container, at){
10
11        return declare("dojox.mvc.Generate", [Container], {
12                // summary:
13                //              A container that generates a view based on the data model its bound to.
14                //
15                // description:
16                //              A generate introspects its data binding and creates a view contained in
17                //              it that allows displaying the bound data. Child dijits or custom view
18                //              components inside it inherit their parent data binding context from it.
19       
20                // _counter: [private] Integer
21                //              A count maintained internally to always generate predictable widget
22                //              IDs in the view generated by this container.
23                _counter : 0,
24       
25                // defaultWidgetMapping: Object
26                //              The mapping of types to a widget class. Set widgetMapping to override this.
27                //     
28                _defaultWidgetMapping: {"String" : "dijit/form/TextBox"},
29       
30                // defaultClassMapping: Object
31                //              The mapping of class to use. Set classMapping to override this.
32                //     
33                _defaultClassMapping: {"Label" : "generate-label-cell", "String" : "generate-dijit-cell", "Heading" : "generate-heading", "Row" : "row"},
34       
35       
36                // defaultIdNameMapping: Object
37                //              The mapping of id and name to use. Set idNameMapping to override this. A count will be added to the id and name
38                //     
39                _defaultIdNameMapping: {"String" : "textbox_t"},
40
41                // children: dojo/Stateful
42                //              The array of data model that is used to render child nodes.
43                children: null,
44
45                // _relTargetProp: String
46                //              The name of the property that is used by child widgets for relative data binding.
47                _relTargetProp : "children",
48
49                startup: function(){
50                        this.inherited(arguments);
51                        this._setChildrenAttr(this.children);
52                },
53
54                ////////////////////// PRIVATE METHODS ////////////////////////
55
56                _setChildrenAttr: function(/*dojo/Stateful*/ value){
57                        // summary:
58                        //              Handler for calls to set("children", val).
59                        // description:
60                        //              Sets "ref" property so that child widgets can refer to, and then rebuilds the children.
61
62                        var children = this.children;
63                        this._set("children", value);
64                        // this.binding is the resolved ref, so not matching with the new value means change in repeat target.
65                        if(this.binding != value){
66                                this.set("ref", value);
67                        }
68                        if(this._started && (!this._builtOnce || children != value)){
69                                this._builtOnce = true;
70                                this._buildContained(value);
71                        }
72                },
73       
74                _buildContained: function(/*dojo/Stateful*/ children){
75                        // summary:
76                        //              Destroy any existing generated view, recreate it from scratch
77                        //              parse the new contents.
78                        // children: dojo/Stateful
79                        //              The array of child widgets.
80                        // tags:
81                        //              private
82
83                        if(!children){ return; }
84
85                        this._destroyBody();
86       
87                        this._counter = 0;
88                        this.srcNodeRef.innerHTML = this._generateBody(children);
89       
90                        this._createBody();
91                },
92       
93                _generateBody: function(/*dojo/Stateful*/ children, /*Boolean*/ hideHeading){
94                        // summary:
95                        //              Generate the markup for the view associated with this generate
96                        //              container.
97                        // children: dojo/Stateful
98                        //              The associated data to generate a view for.
99                        // hideHeading: Boolean
100                        //              Whether the property name should be displayed as a heading.
101                        // tags:
102                        //              private
103
104                        if(children === void 0){ return ""; }
105
106                        var body = [];
107                        var isStatefulModel = lang.isFunction(children.toPlainObject);
108
109                        function generateElement(value, prop){
110                                if(isStatefulModel ? (value && lang.isFunction(value.toPlainObject)) : !lang.isFunction(value)){
111                                        if(lang.isArray(value)){
112                                                body.push(this._generateRepeat(value, prop));
113                                        }else if(isStatefulModel ? value.value : ((value == null || {}.toString.call(value) != "[object Object]") && (!(value || {}).set || !(value || {}).watch))){
114                                                // TODO: Data types based widgets
115                                                body.push(this._generateTextBox(prop, isStatefulModel));
116                                        }else{
117                                                body.push(this._generateGroup(value, prop, hideHeading));
118                                        }
119                                }
120                        }
121
122                        if(lang.isArray(children)){
123                                array.forEach(children, generateElement, this);
124                        }else{
125                                for(var s in children){
126                                        if(children.hasOwnProperty(s)){
127                                                generateElement.call(this, children[s], s);
128                                        }
129                                }
130                        }
131
132                        return body.join("");
133                },
134       
135                _generateRepeat: function(/*dojox/mvc/StatefulArray*/ children, /*String*/ repeatHeading){
136                        // summary:
137                        //              Generate a repeating model-bound view.
138                        // children: dojox/mvc/StatefulArray
139                        //              The bound node (a collection/array node) to generate a
140                        //              repeating UI/view for.
141                        // repeatHeading: String
142                        //              The heading to be used for this portion.
143                        // tags:
144                        //              private
145
146                        var headingClass = (this.classMapping && this.classMapping["Heading"]) ? this.classMapping["Heading"] : this._defaultClassMapping["Heading"];
147                        return '<div data-dojo-type="dojox/mvc/Group" data-dojo-props="target: at(\'rel:\', \'' + repeatHeading + '\')" + id="' + this.id + '_r' + this._counter++ + '">'
148                         + '<div class="' + headingClass + '\">' + repeatHeading + '</div>'
149                         + this._generateBody(children, true)
150                         + '</div>';
151                },
152               
153                _generateGroup: function(/*dojo/Stateful*/ model, /*String*/ groupHeading, /*Boolean*/ hideHeading){
154                        // summary:
155                        //              Generate a hierarchical model-bound view.
156                        // model: dojo/Stateful
157                        //              The bound (intermediate) model to generate a hierarchical view portion for.
158                        // groupHeading: String
159                        //              The heading to be used for this portion.
160                        // hideHeading: Boolean
161                        //              Whether the heading should be hidden for this portion.
162                        // tags:
163                        //              private
164
165                        var html = ['<div data-dojo-type="dojox/mvc/Group" data-dojo-props="target: at(\'rel:\', \'' + groupHeading + '\')" + id="' + this.id + '_g' + this._counter++ + '">'];
166                        if(!hideHeading){
167                                var headingClass = (this.classMapping && this.classMapping["Heading"]) ? this.classMapping["Heading"] : this._defaultClassMapping["Heading"];
168                                html.push('<div class="' + headingClass + '\">' + groupHeading + '</div>');
169                        }
170                        html.push(this._generateBody(model) + '</div>');
171                        return html.join("");
172                },
173       
174                _generateTextBox: function(/*String*/ prop, /*Boolean*/ referToValue){
175                        // summary:
176                        //              Produce a widget for a simple value.
177                        // prop: String
178                        //              The data model property name.
179                        // referToValue: Boolean
180                        //              True if the property is dojox/mvc/StatefulModel with "value" attribute.
181                        // tags:
182                        //              private
183                        // TODO: Data type based widget generation / enhanced meta-data
184
185                        var idname = this.idNameMapping ? this.idNameMapping["String"] : this._defaultIdNameMapping["String"];
186                        idname = idname + this._counter++;
187                        var widClass = this.widgetMapping ? this.widgetMapping["String"] : this._defaultWidgetMapping["String"];
188                        var labelClass = (this.classMapping && this.classMapping["Label"]) ? this.classMapping["Label"] : this._defaultClassMapping["Label"];
189                        var stringClass = (this.classMapping && this.classMapping["String"]) ? this.classMapping["String"] : this._defaultClassMapping["String"];
190                        var rowClass = (this.classMapping && this.classMapping["Row"]) ? this.classMapping["Row"] : this._defaultClassMapping["Row"];
191                        var bindingSyntax = 'value: at(\'rel:' + (referToValue && prop || '') + '\', \'' + (referToValue ? 'value' : prop) + '\')';
192
193                        return '<div class="' + rowClass + '\">' +
194                                        '<label class="' + labelClass + '\">' + prop + ':</label>' +
195                                        '<input class="' + stringClass + '\" data-dojo-type="' + widClass + '\"' +
196                                        ' data-dojo-props="name: \'' + idname + '\', ' + bindingSyntax + '" id="' + idname + '\"></input>' +
197                                        '</div>';
198                }
199        });
200});
Note: See TracBrowser for help on using the repository browser.