TableContainer.js 8.4 KB

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