1 | define(["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"], |
---|
3 | function(kernel, lang, declare, domClass, domConstruct, arrayUtil, domProp, domStyle, _WidgetBase, _LayoutWidget){ |
---|
4 | |
---|
5 | kernel.experimental("dojox.layout.TableContainer"); |
---|
6 | |
---|
7 | var 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 | |
---|
258 | TableContainer.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. |
---|
283 | lang.extend(_WidgetBase, /*===== {} || =====*/ TableContainer.ChildWidgetProperties); |
---|
284 | |
---|
285 | return TableContainer; |
---|
286 | }); |
---|