/*
Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
Available via Academic Free License >= 2.1 OR the modified BSD license.
see: http://dojotoolkit.org/license for details
*/
if(!dojo._hasResource["dojox.layout.TableContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.layout.TableContainer"] = true;
dojo.experimental("dojox.layout.TableContainer");
dojo.provide("dojox.layout.TableContainer");
dojo.require("dijit.layout._LayoutWidget");
dojo.declare("dojox.layout.TableContainer",
dijit.layout._LayoutWidget,
{
// summary:
// A container that lays out its child widgets in a table layout.
//
// description:
// The TableContainer lays out child widgets in a Table layout.
// Each widget can specify a "label" or a "title" parameter.
// This label is displayed either above or to the left of
// a widget depending on whether the "orientation" attribute
// is "horiz" or "vert", for horizontal and vertical respectively.
// The number of columns is configured using the "cols" attribute.
// The width of labels can be configured using the "labelWidth" parameter.
//
// example:
// | <div dojoType="dojox.layout.TableContainer" orientation="vert" cols="3>
// | <div dojoType="dijit.form.TextInput" value="John" label="First Name:"></div>
// | <div dojoType="dijit.form.CheckBox" label="Is Student?:"></div>
// | <div dojoType="dojox.form.DateTextBox" label="Date Of Birth:"></div>
// | </div>
//
cols: 1,
// labelWidth: Number|String
// Defines the width of a label. If the value is a number, it is
// treated as a pixel value. The other valid value is a percentage,
// e.g. "50%"
labelWidth: "100",
// showLabels: Boolean
// True if labels should be displayed, false otherwise.
showLabels: true,
// orientation: String
// Either "horiz" or "vert" for label orientation.
orientation: "horiz",
// spacing: Number
// The cell spacing to apply to the table.
spacing: 1,
// customClass: String
// A CSS class that will be applied to child elements. For example, if
// the class is "myClass", the table will have "myClass-table" applied to it,
// each label TD will have "myClass-labelCell" applied, and each
// widget TD will have "myClass-valueCell" applied.
customClass: "",
postCreate: function(){
this.inherited(arguments);
this._children = [];
// If the orientation, customClass or cols attributes are changed,
// layout the widgets again.
this.connect(this, "set", function(name, value){
if(value && (name == "orientation" || name == "customClass" || name == "cols")) {
this.layout();
}
})
},
startup: function() {
if(this._started) {
return;
}
this.inherited(arguments);
if(this._initialized) {
return;
}
var children = this.getChildren();
if(children.length < 1) {
return;
}
this._initialized = true;
dojo.addClass(this.domNode, "dijitTableLayout");
// Call startup on all child widgets
dojo.forEach(children, function(child){
if(!child.started && !child._started) {
child.startup();
}
});
this.resize();
this.layout();
},
resize: function(){
// summary:
// Resizes all children. This widget itself
// does not resize, as it takes up 100% of the
// available width.
dojo.forEach(this.getChildren(), function(child){
if(typeof child.resize == "function") {
child.resize();
}
});
},
layout: function(){
// summary:
// Lays out the child widgets.
if(!this._initialized){
return;
}
var children = this.getChildren();
var childIds = {};
var _this = this;
function addCustomClass(node, type, count) {
if(_this.customClass != "") {
var clazz = _this.customClass+ "-" + (type || node.tagName.toLowerCase());
dojo.addClass(node, clazz);
if(arguments.length > 2) {
dojo.addClass(node, clazz + "-" + count);
}
}
}
// Find any new children that have been added since the last layout() call
dojo.forEach(this._children, dojo.hitch(this, function(child){
childIds[child.id] = child;
}));
dojo.forEach(children, dojo.hitch(this, function(child, index){
if(!childIds[child.id]) {
// Add pre-existing children to the start of the array
this._children.push(child);
}
}));
// Create the table. It fills the width of it's container.
var table = dojo.create("table", {
"width": "100%",
"class": "tableContainer-table tableContainer-table-" + this.orientation,
"cellspacing" : this.spacing
},
this.domNode);
var tbody = dojo.create("tbody");
table.appendChild(tbody);
addCustomClass(table, "table", this.orientation);
var width = Math.floor(100 / this.cols) + "%";
var labelRow = dojo.create("tr", {}, tbody);
var childRow = (!this.showLabels || this.orientation == "horiz")
? labelRow : dojo.create("tr", {}, tbody);
var maxCols = this.cols * (this.showLabels ? 2 : 1);
var numCols = 0;
// Iterate over the children, adding them to the table.
dojo.forEach(this._children, dojo.hitch(this, function(child, index){
var colspan = child.colspan || 1;
if(colspan > 1) {
colspan = this.showLabels ?
Math.min(maxCols - 1, colspan * 2 -1): Math.min(maxCols, colspan);
}
// Create a new row if we need one
if(numCols + colspan - 1 + (this.showLabels ? 1 : 0)>= maxCols) {
numCols = 0;
labelRow = dojo.create("tr", {}, tbody);
childRow = this.orientation == "horiz" ? labelRow : dojo.create("tr", {}, tbody);
}
var labelCell;
// If labels should be visible, add them
if(this.showLabels) {
labelCell = dojo.create("td", {"class": "tableContainer-labelCell"}, labelRow);
// If the widget should take up both the label and value,
// then just set the class on it.
if(child.spanLabel) {
dojo.attr(labelCell, this.orientation == "vert" ? "rowspan" : "colspan", 2);
}
else {
// Add the custom label class to the label cell
addCustomClass(labelCell, "labelCell");
var labelProps = {"for": child.get("id")};
var label = dojo.create("label", labelProps, labelCell);
if(Number(this.labelWidth) > -1 ||
String(this.labelWidth).indexOf("%") > -1) {
// Set the width of the label cell with either a pixel or percentage value
dojo.style(labelCell, "width",
String(this.labelWidth).indexOf("%") < 0
? this.labelWidth + "px" : this.labelWidth);
}
label.innerHTML = child.get("label") || child.get("title");
}
}
var childCell;
if(child.spanLabel && labelCell) {
childCell = labelCell;
} else {
childCell = dojo.create("td", {
"class" : "tableContainer-valueCell"
}, childRow);
}
if(colspan > 1) {
dojo.attr(childCell, "colspan", colspan);
}
// Add the widget cell's custom class, if one exists.
addCustomClass(childCell, "valueCell", index);
childCell.appendChild(child.domNode);
numCols += colspan + (this.showLabels ? 1 : 0);
}));
if(this.table) {
this.table.parentNode.removeChild(this.table);
}
// Refresh the layout of any child widgets, allowing them to resize
// to their new parent.
dojo.forEach(children, function(child){
if(typeof child.layout == "function") {
child.layout();
}
});
this.table = table;
this.resize();
},
destroyDescendants: function(/*Boolean*/ preserveDom){
// summary:
// Destroys all the widgets inside this.containerNode,
// but not this widget itself
dojo.forEach(this._children, function(child){ child.destroyRecursive(preserveDom); });
},
_setSpacingAttr: function(value) {
// summary:
// Sets the spacing attribute.
this.spacing = value;
if(this.table) {
this.table.cellspacing = Number(value);
}
}
});
// Extend the default widget with both label and title elements, as
// well as a "spanLabel" attribute. If a widget
dojo.extend(dijit._Widget, {
// label: String
// The label to display for a given widget
label: "",
// title: String
// The label to display for a given widget. This is interchangeable
// with the 'label' parameter, as some widgets already have a use
// for the 'label', and this can be used instead to avoid conflicts.
title: "",
// spanLabel: Boolean
// Setting spanLabel to true makes the widget take up both the
// label and value cells. Defaults to false.
spanLabel: false,
// colspan: Number
// The number of columns this widget should span.
colspan: 1
});
}