TableContainer.js 8.3 KB

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