datatable-base.js revision 550773f24e3b2d71b334b9863dc3950498fd40de
DATATABLE = "datatable",
COLUMN = "column",
FOCUS = "focus",
KEYDOWN = "keydown",
MOUSEENTER = "mouseenter",
MOUSELEAVE = "mouseleave",
MOUSEUP = "mouseup",
MOUSEDOWN = "mousedown",
CLICK = "click",
DOUBLECLICK = "doubleclick",
TEMPLATE_TABLE = '<table></table>',
TEMPLATE_COL = '<col></col>',
TEMPLATE_TH = '<th id="{id}" rowspan="{rowspan}" colspan="{colspan}" class="{classnames}"><div class="'+CLASS_LINER+'">{value}</div></th>',
TEMPLATE_TR = '<tr id="{id}"></tr>',
TEMPLATE_TD = '<td headers="{headers}" class="{classnames}"><div class="'+CLASS_LINER+'">{value}</div></td>',
TEMPLATE_VALUE = '{value}',
/**
* The Column class defines and manages attributes of Columns for DataTable.
*
* @class Column
* @extends Widget
* @constructor
*/
}
/////////////////////////////////////////////////////////////////////////////
//
// STATIC PROPERTIES
//
/////////////////////////////////////////////////////////////////////////////
/**
* Class name.
*
* @property NAME
* @type String
* @static
* @final
* @value "column"
*/
NAME: "column",
/////////////////////////////////////////////////////////////////////////////
//
// ATTRIBUTES
//
/////////////////////////////////////////////////////////////////////////////
ATTRS: {
id: {
valueFn: "_defaultId",
writeOnce: true
},
key: {
valueFn: "_defaultKey"
},
field: {
valueFn: "_defaultField"
},
label: {
valueFn: "_defaultLabel"
},
keyIndex: {
readOnly: true
},
parent: {
readOnly: true
},
children: {
},
colSpan: {
readOnly: true
},
rowSpan: {
readOnly: true
},
thNode: {
readOnly: true
},
thLinerNode: {
readOnly: true
},
thLabelNode: {
readOnly: true
},
abbr: {
value: null
},
headers: {}, // set by Columnset code
classnames: {
readOnly: true,
getter: "_getClassnames"
},
editor: {},
formatter: {},
// requires datatable-colresize
resizeable: {},
//requires datatable-sort
sortable: {},
hidden: {},
width: {},
minWidth: {},
maxAutoWidth: {}
}
});
/////////////////////////////////////////////////////////////////////////////
//
// PROTOTYPE
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// ATTRIBUTE HELPERS
//
/////////////////////////////////////////////////////////////////////////////
/**
* @method _defaultId
* @description Return ID for instance.
* @returns String
* @private
*/
_defaultId: function() {
return Y.guid();
},
/**
* @method _defaultKey
* @description Return key for instance. Defaults to ID if one was not
* provided.
* @returns String
* @private
*/
_defaultKey: function(key) {
},
/**
* @method _defaultField
* @description Return field for instance. Defaults to key if one was not
* provided.
* @returns String
* @private
*/
_defaultField: function(field) {
},
/**
* @method _defaultLabel
* @description Return label for instance. Defaults to key if one was not
* provided.
* @returns String
* @private
*/
_defaultLabel: function(label) {
},
/**
* Updates the UI if changes are made to abbr.
*
* @method _afterAbbrChange
* @param e {Event} Custom event for the attribute change.
* @private
*/
_afterAbbrChange: function (e) {
this._uiSetAbbr(e.newVal);
},
/////////////////////////////////////////////////////////////////////////////
//
// METHODS
//
/////////////////////////////////////////////////////////////////////////////
/**
* Initializer.
*
* @method initializer
* @param config {Object} Config object.
* @private
*/
initializer: function(config) {
},
/**
* Destructor.
*
* @method destructor
* @private
*/
destructor: function() {
},
/**
* Returns classnames for Column.
*
* @method _getClassnames
* @private
*/
_getClassnames: function () {
/*var allClasses;
// Add CSS classes
if(lang.isString(oColumn.className)) {
// Single custom class
allClasses = [oColumn.className];
}
else if(lang.isArray(oColumn.className)) {
// Array of custom classes
allClasses = oColumn.className;
}
else {
// no custom classes
allClasses = [];
}
// Hook for setting width with via dynamic style uses key since ID is too disposable
allClasses[allClasses.length] = this.getId() + "-col-" +oColumn.getSanitizedKey();
// Column key - minus any chars other than "A-Z", "a-z", "0-9", "_", "-", ".", or ":"
allClasses[allClasses.length] = "yui-dt-col-" +oColumn.getSanitizedKey();
var isSortedBy = this.get("sortedBy") || {};
// Sorted
if(oColumn.key === isSortedBy.key) {
allClasses[allClasses.length] = isSortedBy.dir || '';
}
// Hidden
if(oColumn.hidden) {
allClasses[allClasses.length] = DT.CLASS_HIDDEN;
}
// Selected
if(oColumn.selected) {
allClasses[allClasses.length] = DT.CLASS_SELECTED;
}
// Sortable
if(oColumn.sortable) {
allClasses[allClasses.length] = DT.CLASS_SORTABLE;
}
// Resizeable
if(oColumn.resizeable) {
allClasses[allClasses.length] = DT.CLASS_RESIZEABLE;
}
// Editable
if(oColumn.editor) {
allClasses[allClasses.length] = DT.CLASS_EDITABLE;
}
if(aAddClasses) {
allClasses = allClasses.concat(aAddClasses);
}
return allClasses.join(' ');*/
},
////////////////////////////////////////////////////////////////////////////
//
// SYNC
//
////////////////////////////////////////////////////////////////////////////
/**
* Syncs UI to intial state.
*
* @method syncUI
* @private
*/
syncUI: function() {
},
/**
* Updates abbr.
*
* @method _uiSetAbbr
* @param val {String} New abbr.
* @protected
*/
_uiSetAbbr: function(val) {
}
});
/**
* The Columnset class defines and manages a collection of Columns.
*
* @class Columnset
* @extends Base
* @constructor
*/
}
/////////////////////////////////////////////////////////////////////////////
//
// STATIC PROPERTIES
//
/////////////////////////////////////////////////////////////////////////////
/**
* Class name.
*
* @property NAME
* @type String
* @static
* @final
* @value "columnset"
*/
NAME: "columnset",
/////////////////////////////////////////////////////////////////////////////
//
// ATTRIBUTES
//
/////////////////////////////////////////////////////////////////////////////
ATTRS: {
definitions: {
setter: "_setDefinitions"
},
// DOM tree representation of all Columns
tree: {
readOnly: true,
value: []
},
//TODO: is this necessary?
// Flat representation of all Columns
flat: {
readOnly: true,
value: []
},
// Hash of all Columns by ID
hash: {
readOnly: true,
value: {}
},
// Flat representation of only Columns that are meant to display data
keys: {
readOnly: true,
value: []
}
}
});
/////////////////////////////////////////////////////////////////////////////
//
// PROTOTYPE
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// ATTRIBUTE HELPERS
//
/////////////////////////////////////////////////////////////////////////////
/**
* @method _setDefinitions
* @description Clones definitions before setting.
* @param definitions {Array} Array of column definitions.
* @returns Array
* @private
*/
_setDefinitions: function(definitions) {
return Y.clone(definitions);
},
/////////////////////////////////////////////////////////////////////////////
//
// METHODS
//
/////////////////////////////////////////////////////////////////////////////
/**
* Initializer. Generates all internal representations of the collection of
* Columns.
*
* @method initializer
* @param config {Object} Config object.
* @private
*/
initializer: function() {
// DOM tree representation of all Columns
var tree = [],
// Flat representation of all Columns
flat = [],
// Hash of all Columns by ID
hash = {},
// Flat representation of only Columns that are meant to display data
keys = [],
// Original definitions
self = this;
// Internal recursive function to define Column instances
var i=0,
// One level down
depth++;
// Create corresponding dom node if not already there for this depth
}
// Parse each node at this depth for attributes and any children
for(; i<len; ++i) {
currentDefinition = YLang.isString(currentDefinition) ? {key:currentDefinition} : currentDefinition;
// Instantiate a new Column for each node
// Cross-reference Column ID back to the original object literal definition
// Add the new Column to the flat list
// Add the new Column to the hash
// Assign its parent as an attribute, if applicable
if(parent) {
}
// The Column has descendants
// The children themselves must also be parsed for Column instances
}
}
// This Column does not have any children
else {
}
// Add the Column to the top-down dom tree
}
depth--;
}
// Parse out Column instances from the array of object literals
// Save to the Columnset instance
this._setRowSpans();
this._setHeaders();
},
/**
* Destructor.
*
* @method destructor
* @private
*/
destructor: function() {
},
/////////////////////////////////////////////////////////////////////////////
//
// COLUMN HELPERS
//
/////////////////////////////////////////////////////////////////////////////
/**
* Cascade certain properties to children if not defined on their own.
*
* @method _cascadePropertiesToChildren
* @private
*/
//TODO: this is all a giant todo
var i = 0,
// Cascade certain properties to children if not defined on their own
for(; i<len; ++i) {
child = currentChildren[i];
}
}
}
}
}
}
}
}
}
}
},
/**
* @method _setColSpans
* @description Calculates and sets colSpan attribute on given Column.
* @param column {Array} Column instance.
* @param definition {Object} Column definition.
* @private
*/
// Determine COLSPAN value for this Column
var terminalChildNodes = 0;
function countTerminalChildNodes(ancestor) {
i = 0,
// Drill down each branch and count terminal nodes
for(; i<len; ++i) {
// Keep drilling down
}
// Reached branch terminus
else {
}
}
}
},
/**
* @method _setRowSpans
* @description Calculates and sets rowSpan attribute on all Columns.
* @private
*/
_setRowSpans: function() {
// Determine ROWSPAN value for each Column in the DOM tree
function parseDomTreeForRowSpan(tree) {
var maxRowDepth = 1,
m,p;
// Calculate the max depth of descendants for this row
var i = 0,
col;
for(; i<len; ++i) {
// Column has children, so keep counting
tmpRowDepth++;
tmpRowDepth--;
}
// Column has children, so keep counting
tmpRowDepth++;
tmpRowDepth--;
}
// No children, is it the max depth?
else {
if(tmpRowDepth > maxRowDepth) {
}
}
}
}
// Count max row depth for each row
currentRow = tree[m];
// Assign the right ROWSPAN values to each Column in the row
currentColumn = currentRow[p];
}
else {
}
}
// Reset counter for next row
maxRowDepth = 1;
}
}
},
/**
* @method _setHeaders
* @description Calculates and sets headers attribute on all Columns.
* @private
*/
_setHeaders: function() {
//headers[i].push(column.getSanitizedKey());
}
}
for(; i<len; ++i) {
headers = [];
}
},
getColumn: function() {
}
});
/**
* The DataTable widget provides a progressively enhanced DHTML control for
* displaying tabular data across A-grade browsers.
*
* @module datatable
*/
/**
* Provides the base DataTable implementation, which can be extended to add
* additional functionality, such as sorting or scrolling.
*
* @module datatable
* @submodule datatable-base
*/
/**
* Base class for the DataTable widget.
* @class DataSource.Base
* @extends Widget
* @constructor
*/
}
/////////////////////////////////////////////////////////////////////////////
//
// STATIC PROPERTIES
//
/////////////////////////////////////////////////////////////////////////////
/**
* Class name.
*
* @property NAME
* @type String
* @static
* @final
* @value "dataTable"
*/
NAME: "dataTable",
/////////////////////////////////////////////////////////////////////////////
//
// ATTRIBUTES
//
/////////////////////////////////////////////////////////////////////////////
ATTRS: {
/**
* @attribute columnset
* @description Pointer to Columnset instance.
* @type Array | Y.Columnset
*/
columnset: {
setter: "_setColumnset"
},
/**
* @attribute recordset
* @description Pointer to Recordset instance.
* @type Array | Y.Recordset
*/
recordset: {
setter: "_setRecordset"
},
/*TODO
* @attribute state
* @description Internal state.
* @readonly
* @type
*/
/*state: {
value: new Y.State(),
readOnly: true
},*/
/**
* @attribute strings
* @description The collection of localizable strings used to label
* elements of the UI.
* @type Object
*/
strings: {
valueFn: function() {
}
},
/**
* @attribute thValueTemplate
* @description Tokenized markup template for TH value.
* @type String
* @default '{value}'
*/
},
/**
* @attribute tdValueTemplate
* @description Tokenized markup template for TD value.
* @type String
* @default '{value}'
*/
},
/**
* @attribute trTemplate
* @description Tokenized markup template for TR node creation.
* @type String
* @default '<tr id="{id}"></tr>'
*/
trTemplate: {
}
},
/////////////////////////////////////////////////////////////////////////////
//
// TODO: HTML_PARSER
//
/////////////////////////////////////////////////////////////////////////////
HTML_PARSER: {
/*caption: function (srcNode) {
}*/
}
});
/////////////////////////////////////////////////////////////////////////////
//
// PROTOTYPE
//
/////////////////////////////////////////////////////////////////////////////
/**
* @property thTemplate
* @description Tokenized markup template for TH node creation.
* @type String
* @default '<th id="{id}" rowspan="{rowspan}" colspan="{colspan}"><div class="'+CLASS_LINER+'">{value}</div></th>'
*/
/**
* @property tdTemplate
* @description Tokenized markup template for TD node creation.
* @type String
* @default '<td headers="{headers}"><div class="'+CLASS_LINER+'">{value}</div></td>'
*/
/**
* @property _theadNode
* @description Pointer to THEAD node.
* @type Y.Node
* @private
*/
_theadNode: null,
/**
* @property _tbodyNode
* @description Pointer to TBODY node.
* @type Y.Node
* @private
*/
_tbodyNode: null,
/**
* @property _msgNode
* @description Pointer to message display node.
* @type Y.Node
* @private
*/
_msgNode: null,
/////////////////////////////////////////////////////////////////////////////
//
// ATTRIBUTE HELPERS
//
/////////////////////////////////////////////////////////////////////////////
/**
* Updates the UI if changes are made to any of the strings in the strings
* attribute.
*
* @method _afterStringsChange
* @param e {Event} Custom event for the attribute change.
* @protected
*/
_afterStringsChange: function (e) {
this._uiSetStrings(e.newVal);
},
/**
* @method _setColumnset
* @description Converts Array to Y.Columnset.
* @param columns {Array | Y.Columnset}
* @returns Y.Columnset
* @private
*/
_setColumnset: function(columns) {
},
/**
* Updates the UI if changes are made to Columnset.
*
* @method _afterColumnsetChange
* @param e {Event} Custom event for the attribute change.
* @private
*/
_afterColumnsetChange: function (e) {
this._uiSetColumnset(e.newVal);
},
/**
* @method _setRecordset
* @description Converts Array to Y.Recordset.
* @param records {Array | Y.Recordset}
* @returns Y.Recordset
* @private
*/
_setRecordset: function(rs) {
}
return rs;
},
/**
* @method _afterRecordsetChange
* @description Adds bubble target.
* @param records {Array | Y.Recordset}
* @returns Y.Recordset
* @private
*/
_afterRecordsetChange: function (e) {
this._uiSetRecordset(e.newVal);
},
/////////////////////////////////////////////////////////////////////////////
//
// METHODS
//
/////////////////////////////////////////////////////////////////////////////
/**
* Initializer.
*
* @method initializer
* @param config {Object} Config object.
* @private
*/
initializer: function(config) {
},
/**
* Destructor.
*
* @method destructor
* @private
*/
destructor: function() {
},
////////////////////////////////////////////////////////////////////////////
//
// RENDER
//
////////////////////////////////////////////////////////////////////////////
/**
* Renders UI.
*
* @method renderUI
* @private
*/
renderUI: function() {
// TABLE
// COLGROUP
this._addColgroupNode(this._tableNode) &&
// THEAD
this._addTheadNode(this._tableNode) &&
// Primary TBODY
this._addTbodyNode(this._tableNode) &&
// Message TBODY
this._addMessageNode(this._tableNode) &&
// CAPTION
this._addCaptionNode(this._tableNode));
},
/**
* Creates and attaches TABLE element to given container.
*
* @method _addTableNode
* @param containerNode {Y.Node} Parent node.
* @protected
* @returns Y.Node
*/
_addTableNode: function(containerNode) {
if (!this._tableNode) {
}
return this._tableNode;
},
/**
* Creates and attaches COLGROUP element to given TABLE.
*
* @method _addColgroupNode
* @param tableNode {Y.Node} Parent node.
* @protected
* @returns Y.Node
*/
_addColgroupNode: function(tableNode) {
// Add COLs to DOCUMENT FRAGMENT
i = 0,
allCols = ["<colgroup>"];
for(; i<len; ++i) {
}
// Create COLGROUP
this._colgroupNode = tableNode.insertBefore(Ycreate(allCols.join("")), tableNode.get("firstChild"));
return this._colgroupNode;
},
/**
* Creates and attaches THEAD element to given container.
*
* @method _addTheadNode
* @param tableNode {Y.Node} Parent node.
* @protected
* @returns Y.Node
*/
_addTheadNode: function(tableNode) {
if(tableNode) {
return this._theadNode;
}
},
/**
* Creates and attaches TBODY element to given container.
*
* @method _addTbodyNode
* @param tableNode {Y.Node} Parent node.
* @protected
* @returns Y.Node
*/
_addTbodyNode: function(tableNode) {
return this._tbodyNode;
},
/**
* Creates and attaches message display element to given container.
*
* @method _addMessageNode
* @param tableNode {Y.Node} Parent node.
* @protected
* @returns Y.Node
*/
_addMessageNode: function(tableNode) {
return this._msgNode;
},
/**
* Creates and attaches CAPTION element to given container.
*
* @method _addCaptionNode
* @param tableNode {Y.Node} Parent node.
* @protected
* @returns Y.Node
*/
_addCaptionNode: function(tableNode) {
//TODO: node.createCaption
return this._captionNode;
},
////////////////////////////////////////////////////////////////////////////
//
// BIND
//
////////////////////////////////////////////////////////////////////////////
/**
* Binds events.
*
* @method bindUI
* @private
*/
bindUI: function() {
var tableNode = this._tableNode,
// Define custom events that wrap DOM events. Simply pass through DOM
// event facades.
//TODO: do we need queuable=true?
//TODO: All the other events.
/**
* Fired when a TH element has a click.
*
* @event theadCellClick
*/
this.publish("theadCellClick", {defaultFn: this._defTheadCellClickFn, emitFacade:false, queuable:true});
/**
* Fired when a THEAD>TR element has a click.
*
* @event theadRowClick
*/
this.publish("theadRowClick", {defaultFn: this._defTheadRowClickFn, emitFacade:false, queuable:true});
/**
* Fired when the THEAD element has a click.
*
* @event theadClick
*/
/**
* Fired when a TH element has a mouseenter.
*
* @event theadCellMouseenter
*/
this.publish("theadCellMouseenter", {defaultFn: this._defTheadCellMouseenterFn, emitFacade:false, queuable:true});
/**
* Fired when a THEAD>TR element has a mouseenter.
*
* @event theadRowMouseenter
*/
this.publish("theadRowMouseenter", {defaultFn: this._defTheadRowMouseenterFn, emitFacade:false, queuable:true});
/**
* Fired when the THEAD element has a mouseenter.
*
* @event theadMouseenter
*/
this.publish("theadMouseenter", {defaultFn: this._defTheadMouseenterFn, emitFacade:false, queuable:true});
/**
* Fired when a TD element has a click.
*
* @event tbodyCellClick
*/
this.publish("tbodyCellClick", {defaultFn: this._defTbodyCellClickFn, emitFacade:false, queuable:true});
/**
* Fired when a TBODY>TR element has a click.
*
* @event tbodyRowClick
*/
this.publish("tbodyRowClick", {defaultFn: this._defTbodyRowClickFn, emitFacade:false, queuable:true});
/**
* Fired when the TBODY element has a click.
*
* @event tbodyClick
*/
// Bind to THEAD DOM events
// Since we can't listen for click and dblclick on the same element...
// Bind to TBODY DOM events
// Since we can't listen for click and dblclick on the same element...
// Bind to message TBODY DOM events
// Since we can't listen for click and dblclick on the same element...
},
/**
* On DOM event, fires corresponding custom event.
*
* @method _onDomEvent
* @param e {DOMEvent} The original DOM event facade.
* @param type {String} Corresponding custom event to fire.
* @private
*/
_onDomEvent: function(e, type) {
},
//TODO: abstract this out
_defTheadCellClickFn: function(e) {
this.fire("theadRowClick", e);
},
_defTheadRowClickFn: function(e) {
this.fire("theadClick", e);
},
_defTheadClickFn: function(e) {
},
////////////////////////////////////////////////////////////////////////////
//
// SYNC
//
////////////////////////////////////////////////////////////////////////////
/**
* Syncs UI to intial state.
*
* @method syncUI
* @private
*/
syncUI: function() {
// THEAD ROWS
// DATA ROWS
// STRINGS
},
/**
* Updates all strings.
*
* @method _uiSetStrings
* @param strings {Object} Collection of new strings.
* @protected
*/
_uiSetStrings: function (strings) {
},
/**
* Updates summary.
*
* @method _uiSetSummary
* @param val {String} New summary.
* @protected
*/
_uiSetSummary: function(val) {
},
/**
* Updates caption.
*
* @method _uiSetCaption
* @param val {String} New caption.
* @protected
*/
_uiSetCaption: function(val) {
},
////////////////////////////////////////////////////////////////////////////
//
//
////////////////////////////////////////////////////////////////////////////
/**
* Updates THEAD.
*
* @method _uiSetColumnset
* @param cs {Y.Columnset} New Columnset.
* @protected
*/
_uiSetColumnset: function(cs) {
thead = this._theadNode,
i = 0,
// Move THEAD off DOM
// Iterate tree of columns to add THEAD rows
for(; i<len; ++i) {
}
// Column helpers needs _theadNode to exist
//this._createColumnHelpers();
// Re-attach THEAD to DOM
},
/**
* Creates and attaches header row element.
*
* @method _addTheadTrNode
* @param o {Object} {thead, columns}.
* @param isFirst {Boolean} Is first row.
* @param isFirst {Boolean} Is last row.
* @protected
*/
this._attachTheadTrNode(o);
},
/**
* Creates header row element.
*
* @method _createTheadTrNode
* @param o {Object} {thead, columns}.
* @param isFirst {Boolean} Is first row.
* @param isLast {Boolean} Is last row.
* @protected
* @returns Y.Node
*/
//TODO: custom classnames
i = 0,
if(isFirst) {
}
if(isLast) {
}
for(; i<len; ++i) {
}
return tr;
},
/**
* Attaches header row element.
*
* @method _attachTheadTrNode
* @param o {Object} {thead, columns, tr}.
* @protected
*/
_attachTheadTrNode: function(o) {
},
/**
* Creates and attaches header cell element.
*
* @method _addTheadThNode
* @param o {Object} {value, column, tr}.
* @protected
*/
_addTheadThNode: function(o) {
o.th = this._createTheadThNode(o);
this._attachTheadThNode(o);
},
/**
* Creates header cell element.
*
* @method _createTheadThNode
* @param o {Object} {value, column, tr}.
* @protected
* @returns Y.Node
*/
_createTheadThNode: function(o) {
// Populate template object
//TODO o.abbr = column.get("abbr");
/*TODO
// Clear minWidth on hidden Columns
if(column.get("hidden")) {
//this._clearMinWidth(column);
}
*/
//column._set("thNode", o.th);
},
/**
* Attaches header cell element.
*
* @method _attachTheadTrNode
* @param o {Object} {value, column, tr}.
* @protected
*/
_attachTheadThNode: function(o) {
},
////////////////////////////////////////////////////////////////////////////
//
//
////////////////////////////////////////////////////////////////////////////
/**
* Updates TBODY.
*
* @method _uiSetRecordset
* @param rs {Y.Recordset} New Recordset.
* @protected
*/
_uiSetRecordset: function(rs) {
var i = 0,//TODOthis.get("state.offsetIndex")
tbody = this._tbodyNode,
// Move TBODY off DOM
// Iterate Recordset to use existing TR when possible or add new TR
for(; i<len; ++i) {
o.rowindex = i;
this._addTbodyTrNode(o); //TODO: sometimes rowindex != recordindex
}
// Re-attach TBODY to DOM
},
/**
* Creates and attaches data row element.
*
* @method _addTbodyTrNode
* @param o {Object} {tbody, record}
* @protected
*/
_addTbodyTrNode: function(o) {
this._attachTbodyTrNode(o);
},
/**
* Creates data row element.
*
* @method _createTbodyTrNode
* @param o {Object} {tbody, record}
* @protected
* @returns Y.Node
*/
_createTbodyTrNode: function(o) {
i = 0,
for(; i<len; ++i) {
this._addTbodyTdNode(o);
}
return tr;
},
/**
* Attaches data row element.
*
* @method _attachTbodyTrNode
* @param o {Object} {tbody, record, tr}.
* @protected
*/
_attachTbodyTrNode: function(o) {
if(isEven) {
}
else {
}
},
/**
* Creates and attaches data cell element.
*
* @method _addTbodyTdNode
* @param o {Object} {record, column, tr}.
* @protected
*/
_addTbodyTdNode: function(o) {
o.td = this._createTbodyTdNode(o);
this._attachTbodyTdNode(o);
},
/**
* Creates data cell element.
*
* @method _createTbodyTdNode
* @param o {Object} {record, column, tr}.
* @protected
* @returns Y.Node
*/
_createTbodyTdNode: function(o) {
//TODO: attributes? or methods?
o.value = this.formatDataCell(o);
},
/**
* Attaches data cell element.
*
* @method _attachTbodyTdNode
* @param o {Object} {record, column, tr, headers, classnames, value}.
* @protected
*/
_attachTbodyTdNode: function(o) {
},
/**
* Returns markup to insert into data cell element.
*
* @method formatDataCell
* @param @param o {Object} {record, column, tr, headers, classnames}.
*/
formatDataCell: function(o) {
}
});