source: Dev/branches/rest-dojo-ui/client/dojox/layout/TableContainer.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

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