source: Dev/trunk/src/client/dojox/layout/TableContainer.js

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

Added Dojo 1.9.3 release.

File size: 8.5 KB
Line 
1define(["dojo/_base/kernel", "dojo/_base/lang", "dojo/_base/declare", "dojo/dom-class", "dojo/dom-construct",
2                "dojo/_base/array", "dojo/dom-prop", "dojo/dom-style", "dijit/_WidgetBase", "dijit/layout/_LayoutWidget"],
3function(kernel, lang, declare, domClass, domConstruct, arrayUtil, domProp, domStyle, _WidgetBase, _LayoutWidget){
4
5kernel.experimental("dojox.layout.TableContainer");
6
7var TableContainer = declare("dojox.layout.TableContainer", _LayoutWidget, {
8        // summary:
9        //              A container that lays out its child widgets in a table layout.
10        //
11        // description:
12        //              The TableContainer lays out child widgets in a Table layout.
13        //              Each widget can specify a "label" or a "title" parameter.
14        //              This label is displayed either above or to the left of
15        //              a widget depending on whether the "orientation" attribute
16        //              is "horiz" or "vert", for horizontal and vertical respectively.
17        //              The number of columns is configured using the "cols" attribute.
18        //              The width of labels can be configured using the "labelWidth" parameter.
19        //
20        // example:
21        // |    <div dojoType="dojox.layout.TableContainer" orientation="vert" cols="3>
22        // |            <div dojoType="dijit.form.TextInput" value="John" label="First Name:"></div>
23        // |            <div dojoType="dijit.form.CheckBox" label="Is Student?:"></div>
24        // |            <div dojoType="dojox.form.DateTextBox" label="Date Of Birth:"></div>
25        // |    </div>
26        //
27
28        cols: 1,
29       
30        // labelWidth: Number|String
31        //              Defines the width of a label.  If the value is a number, it is
32        //              treated as a pixel value.  The other valid value is a percentage,
33        //              e.g. "50%"
34        labelWidth: "100",
35
36        // showLabels: Boolean
37        //              True if labels should be displayed, false otherwise.
38        showLabels: true,
39
40        // orientation: String
41        //              Either "horiz" or "vert" for label orientation.
42        orientation: "horiz",
43       
44        // spacing: Number
45        //              The cell spacing to apply to the table.
46        spacing: 1,
47
48        // customClass: String
49        //              A CSS class that will be applied to child elements.  For example, if
50        //              the class is "myClass", the table will have "myClass-table" applied to it,
51        //              each label TD will have "myClass-labelCell" applied, and each
52        //              widget TD will have "myClass-valueCell" applied.
53        customClass: "",
54
55        postCreate: function(){
56                this.inherited(arguments);
57                this._children = [];
58               
59                // If the orientation, customClass or cols attributes are changed,
60                // layout the widgets again.
61                this.connect(this, "set", function(name, value){
62                        if(value && (name == "orientation" || name == "customClass" || name == "cols")) {
63                                this.layout();
64                        }
65                });
66        },
67
68        startup: function() {
69                if(this._started) {
70                        return;
71                }
72                this.inherited(arguments);
73                if(this._initialized) {
74                        return;
75                }
76                var children = this.getChildren();
77                if(children.length < 1) {
78                        return;
79                }
80                this._initialized = true;
81
82                domClass.add(this.domNode, "dijitTableLayout");
83
84                // Call startup on all child widgets
85                arrayUtil.forEach(children, function(child){
86                        if(!child.started && !child._started) {
87                                child.startup();
88                        }
89                });
90                this.layout();
91                this.resize();
92        },
93
94        resize: function(){
95                // summary:
96                //              Resizes all children.  This widget itself
97                //              does not resize, as it takes up 100% of the
98                //              available width.
99                arrayUtil.forEach(this.getChildren(), function(child){
100                        if(typeof child.resize == "function") {
101                                child.resize();
102                        }
103                });
104        },
105
106        layout: function(){
107                // summary:
108                //              Lays out the child widgets.
109                if(!this._initialized){
110                        return;
111                }
112
113                var children = this.getChildren();
114
115                var childIds = {};
116                var _this = this;
117
118                function addCustomClass(node, type, count) {
119                        if(_this.customClass != "") {
120                                var clazz = _this.customClass+ "-" + (type || node.tagName.toLowerCase());
121                                domClass.add(node, clazz);
122
123                                if(arguments.length > 2) {
124                                        domClass.add(node, clazz + "-" + count);
125                                }
126                        }
127                }
128
129                // Find any new children that have been added since the last layout() call
130                arrayUtil.forEach(this._children, lang.hitch(this, function(child){
131                        childIds[child.id] = child;
132                }));
133
134                arrayUtil.forEach(children, lang.hitch(this, function(child, index){
135                        if(!childIds[child.id]) {
136                                // Add pre-existing children to the start of the array
137                                this._children.push(child);
138                        }
139                }));
140
141                // Create the table.  It fills the width of it's container.
142                var table = domConstruct.create("table", {
143                        "width": "100%",
144                         "class": "tableContainer-table tableContainer-table-" + this.orientation,
145                         "cellspacing" : this.spacing
146                        },
147                        this.domNode);
148
149                var tbody = domConstruct.create("tbody");
150                table.appendChild(tbody);
151
152                addCustomClass(table, "table", this.orientation);
153
154                var width = Math.floor(100 / this.cols) + "%";
155
156                var labelRow = domConstruct.create("tr", {}, tbody);
157                var childRow = (!this.showLabels || this.orientation == "horiz")
158                                                ? labelRow : domConstruct.create("tr", {}, tbody);
159                var maxCols = this.cols * (this.showLabels ? 2 : 1);
160                var numCols = 0;
161
162                // Iterate over the children, adding them to the table.
163                arrayUtil.forEach(this._children, lang.hitch(this, function(child, index){
164                       
165                        var colspan = child.colspan || 1;
166                       
167                        if(colspan > 1) {
168                                colspan = this.showLabels ?
169                                        Math.min(maxCols - 1, colspan * 2 -1): Math.min(maxCols, colspan);
170                        }
171
172                        // Create a new row if we need one
173                        if(numCols + colspan - 1 + (this.showLabels ? 1 : 0)>= maxCols) {
174                                numCols = 0;
175                                labelRow = domConstruct.create("tr", {}, tbody);
176                                childRow = this.orientation == "horiz" ? labelRow : domConstruct.create("tr", {}, tbody);
177                        }
178                        var labelCell;
179                       
180                        // If labels should be visible, add them
181                        if(this.showLabels) {
182                                labelCell = domConstruct.create("td", {"class": "tableContainer-labelCell"}, labelRow);
183
184                                // If the widget should take up both the label and value,
185                                // then just set the class on it.
186                                if(child.spanLabel) {
187                                        domProp.set(labelCell, this.orientation == "vert" ? "rowspan" : "colspan", 2);
188                                }
189                                else {
190                                        // Add the custom label class to the label cell
191                                        addCustomClass(labelCell, "labelCell");
192                                        var labelProps = {"for": child.get("id")};
193                                        var label = domConstruct.create("label", labelProps, labelCell);
194
195                                        if(Number(this.labelWidth) > -1 ||
196                                                String(this.labelWidth).indexOf("%") > -1) {
197                                                       
198                                                // Set the width of the label cell with either a pixel or percentage value
199                                                domStyle.set(labelCell, "width",
200                                                        String(this.labelWidth).indexOf("%") < 0
201                                                                ? this.labelWidth + "px" : this.labelWidth);
202                                        }
203
204                                        label.innerHTML = child.get("label") || child.get("title");
205                                }
206                        }
207                        var childCell;
208
209                        if(child.spanLabel && labelCell) {
210                                childCell = labelCell;
211                        } else {
212                                 childCell = domConstruct.create("td", {
213                                        "class" : "tableContainer-valueCell"
214                                }, childRow);
215                        }
216                        if(colspan > 1) {
217                                domProp.set(childCell, "colspan", colspan);
218                        }
219                       
220                        // Add the widget cell's custom class, if one exists.
221                        addCustomClass(childCell, "valueCell", index);
222
223                        childCell.appendChild(child.domNode);
224                        numCols += colspan + (this.showLabels ? 1 : 0);
225                }));
226
227                if(this.table)   {
228                        this.table.parentNode.removeChild(this.table);
229                }
230                // Refresh the layout of any child widgets, allowing them to resize
231                // to their new parent.
232                arrayUtil.forEach(children, function(child){
233                        if(typeof child.layout == "function") {
234                                child.layout();
235                        }
236                });
237                this.table = table;
238                this.resize();
239        },
240       
241        destroyDescendants: function(/*Boolean*/ preserveDom){
242                // summary:
243                //              Destroys all the widgets inside this.containerNode,
244                //              but not this widget itself
245                arrayUtil.forEach(this._children, function(child){ child.destroyRecursive(preserveDom); });
246        },
247       
248        _setSpacingAttr: function(value) {
249                // summary:
250                //              Sets the spacing attribute.
251                this.spacing = value;
252                if(this.table) {
253                        this.table.cellspacing = Number(value);
254                }
255        }
256});
257
258TableContainer.ChildWidgetProperties = {
259        // summary:
260        //              Properties to be set on children of TableContainer
261
262        // label: String
263        //              The label to display for a given widget
264        label: "",
265       
266        // title: String
267        //              The label to display for a given widget.  This is interchangeable
268        //              with the 'label' parameter, as some widgets already have a use
269        //              for the 'label', and this can be used instead to avoid conflicts.
270        title: "",
271       
272        // spanLabel: Boolean
273        //              Setting spanLabel to true makes the widget take up both the
274        //              label and value cells. Defaults to false.
275        spanLabel: false,
276       
277        // colspan: Number
278        //              The number of columns this widget should span.
279        colspan: 1
280};
281
282// Add to widget base for benefit of parser.   Remove for 2.0.   Also, hide from doc viewer.
283lang.extend(_WidgetBase, /*===== {} || =====*/ TableContainer.ChildWidgetProperties);
284
285return TableContainer;
286});
Note: See TracBrowser for help on using the repository browser.