summaryrefslogtreecommitdiff
path: root/frontend/beta/js/YUI-extensions/grid/Grid.js
Side-by-side diff
Diffstat (limited to 'frontend/beta/js/YUI-extensions/grid/Grid.js') (more/less context) (ignore whitespace changes)
-rw-r--r--frontend/beta/js/YUI-extensions/grid/Grid.js965
1 files changed, 965 insertions, 0 deletions
diff --git a/frontend/beta/js/YUI-extensions/grid/Grid.js b/frontend/beta/js/YUI-extensions/grid/Grid.js
new file mode 100644
index 0000000..46d5de4
--- a/dev/null
+++ b/frontend/beta/js/YUI-extensions/grid/Grid.js
@@ -0,0 +1,965 @@
+/**
+ * @class YAHOO.ext.grid.Grid
+ * @extends YAHOO.ext.util.Observable
+ * This class represents the primary interface of a component based grid control.
+ * <br><br>Usage:<pre><code>
+ var grid = new YAHOO.ext.grid.Grid('my-container-id', dataModel, columnModel);
+ // set any options
+ grid.render();
+ // or using a config
+ var grid = new YAHOO.ext.grid.Grid('my-container-id', {
+ dataModel: myDataModel,
+ colModel: myColModel,
+ selModel: mySelectionModel,
+ autoSizeColumns: true,
+ monitorWindowResize: false,
+ trackMouseOver: true
+ }).render();
+ * </code></pre>
+ * <b>Common Problems:</b><br/>
+ * - Grid does not resize properly when going smaller: Setting overflow hidden on the container
+ * element will correct this<br/>
+ * - If you get el.style[camel]= NaNpx or -2px or something related, be certain you have given your container element
+ * dimensions. The grid adapts to your container's size, if your container has no size defined then the results
+ * are unpredictable.<br/>
+ * - Do not render the grid into an element with display:none. Try using visibility:hidden. Otherwise there is no way for the
+ * grid to calculate dimensions/offsets.<br/>
+ * @requires YAHOO.util.Dom
+ * @requires YAHOO.util.Event
+ * @requires YAHOO.util.CustomEvent
+ * @requires YAHOO.ext.Element
+ * @requires YAHOO.ext.util.Browser
+ * @requires YAHOO.ext.util.CSS
+ * @requires YAHOO.ext.SplitBar
+ * @requires YAHOO.ext.EventObject
+ * @constructor
+ * @param {String/HTMLElement/YAHOO.ext.Element} container The element into which this grid will be rendered -
+ * The container MUST have some type of size defined for the grid to fill. The container will be
+ * automatically set to position relative if it isn't already.
+ * @param {Object} config A config object that sets properties on this grid OR the data model to bind to
+ * @param {Object} colModel (optional) The column model with info about this grid's columns
+ * @param {Object} selectionModel (optional) The selection model for this grid (defaults to DefaultSelectionModel)
+ */
+YAHOO.ext.grid.Grid = function(container, config, colModel, selectionModel){
+ /** @private */
+ this.container = YAHOO.ext.Element.get(container);
+ this.container.update('');
+ this.container.setStyle('overflow', 'hidden');
+ this.id = this.container.id;
+ this.rows = [];
+ this.rowCount = 0;
+ this.fieldId = null;
+ var dataModel = config; // for legacy pre config support
+ this.dataModel = dataModel;
+ this.colModel = colModel;
+ this.selModel = selectionModel;
+ this.activeEditor = null;
+ this.editingCell = null;
+
+
+ if(typeof config == 'object' && !config.getRowCount){// must be config object
+ YAHOO.ext.util.Config.apply(this, config);
+ }
+
+ /** @private */
+ this.setValueDelegate = this.setCellValue.createDelegate(this);
+
+ /** @private */
+ this.events = {
+ // raw events
+ /**
+ * @event click
+ * The raw click event for the entire grid.
+ * @param {YAHOO.ext.EventObject} e
+ */
+ 'click' : true,
+ /**
+ * @event dblclick
+ * The raw dblclick event for the entire grid.
+ * @param {YAHOO.ext.EventObject} e
+ */
+ 'dblclick' : true,
+ /**
+ * @event mousedown
+ * The raw mousedown event for the entire grid.
+ * @param {YAHOO.ext.EventObject} e
+ */
+ 'mousedown' : true,
+ /**
+ * @event mouseup
+ * The raw mouseup event for the entire grid.
+ * @param {YAHOO.ext.EventObject} e
+ */
+ 'mouseup' : true,
+ /**
+ * @event mouseover
+ * The raw mouseover event for the entire grid.
+ * @param {YAHOO.ext.EventObject} e
+ */
+ 'mouseover' : true,
+ /**
+ * @event mouseout
+ * The raw mouseout event for the entire grid.
+ * @param {YAHOO.ext.EventObject} e
+ */
+ 'mouseout' : true,
+ /**
+ * @event keypress
+ * The raw keypress event for the entire grid.
+ * @param {YAHOO.ext.EventObject} e
+ */
+ 'keypress' : true,
+ /**
+ * @event keydown
+ * The raw keydown event for the entire grid.
+ * @param {YAHOO.ext.EventObject} e
+ */
+ 'keydown' : true,
+
+ // custom events
+
+ /**
+ * @event cellclick
+ * Fires when a cell is clicked
+ * @param {Grid} this
+ * @param {Number} rowIndex
+ * @param {Number} columnIndex
+ * @param {YAHOO.ext.EventObject} e
+ */
+ 'cellclick' : true,
+ /**
+ * @event celldblclick
+ * Fires when a cell is double clicked
+ * @param {Grid} this
+ * @param {Number} rowIndex
+ * @param {Number} columnIndex
+ * @param {YAHOO.ext.EventObject} e
+ */
+ 'celldblclick' : true,
+ /**
+ * @event rowclick
+ * Fires when a row is clicked
+ * @param {Grid} this
+ * @param {Number} rowIndex
+ * @param {YAHOO.ext.EventObject} e
+ */
+ 'rowclick' : true,
+ /**
+ * @event rowdblclick
+ * Fires when a row is double clicked
+ * @param {Grid} this
+ * @param {Number} rowIndex
+ * @param {YAHOO.ext.EventObject} e
+ */
+ 'rowdblclick' : true,
+ /**
+ * @event headerclick
+ * Fires when a header is clicked
+ * @param {Grid} this
+ * @param {Number} columnIndex
+ * @param {YAHOO.ext.EventObject} e
+ */
+ 'headerclick' : true,
+ /**
+ * @event rowcontextmenu
+ * Fires when a row is right clicked
+ * @param {Grid} this
+ * @param {Number} rowIndex
+ * @param {YAHOO.ext.EventObject} e
+ */
+ 'rowcontextmenu' : true,
+ /**
+ * @event cellcontextmenu
+ * Fires when a cell is right clicked
+ * @param {Grid} this
+ * @param {Number} rowIndex
+ * @param {Number} cellIndex
+ * @param {YAHOO.ext.EventObject} e
+ */
+ 'cellcontextmenu' : true,
+ /**
+ * @event headercontextmenu
+ * Fires when a header is right clicked
+ * @param {Grid} this
+ * @param {Number} columnIndex
+ * @param {YAHOO.ext.EventObject} e
+ */
+ 'headercontextmenu' : true,
+ /**
+ * @event beforeedit
+ * Fires before a cell is edited
+ * @param {Grid} this
+ * @param {Number} rowIndex
+ * @param {Number} columnIndex
+ */
+ 'beforeedit' : true,
+ /**
+ * @event afteredit
+ * Fires after a cell is edited
+ * @param {Grid} this
+ * @param {Number} rowIndex
+ * @param {Number} columnIndex
+ */
+ 'afteredit' : true,
+ /**
+ * @event bodyscroll
+ * Fires when the body element is scrolled
+ * @param {Number} scrollLeft
+ * @param {Number} scrollTop
+ */
+ 'bodyscroll' : true,
+ /**
+ * @event columnresize
+ * Fires when the user resizes a column
+ * @param {Number} columnIndex
+ * @param {Number} newSize
+ */
+ 'columnresize' : true,
+ /**
+ * @event startdrag
+ * Fires when row(s) start being dragged
+ * @param {Grid} this
+ * @param {YAHOO.ext.GridDD} dd The drag drop object
+ * @param {event} e The raw browser event
+ */
+ 'startdrag' : true,
+ /**
+ * @event enddrag
+ * Fires when a drag operation is complete
+ * @param {Grid} this
+ * @param {YAHOO.ext.GridDD} dd The drag drop object
+ * @param {event} e The raw browser event
+ */
+ 'enddrag' : true,
+ /**
+ * @event dragdrop
+ * Fires when dragged row(s) are dropped on a valid DD target
+ * @param {Grid} this
+ * @param {YAHOO.ext.GridDD} dd The drag drop object
+ * @param {String} targetId The target drag drop object
+ * @param {event} e The raw browser event
+ */
+ 'dragdrop' : true,
+ /**
+ * @event dragover
+ * Fires while row(s) are being dragged. "targetId" is the id of the Yahoo.util.DD object the selected rows are being dragged over.
+ * @param {Grid} this
+ * @param {YAHOO.ext.GridDD} dd The drag drop object
+ * @param {String} targetId The target drag drop object
+ * @param {event} e The raw browser event
+ */
+ 'dragover' : true,
+ /**
+ * @event dragenter
+ * Fires when the dragged row(s) first cross another DD target while being dragged
+ * @param {Grid} this
+ * @param {YAHOO.ext.GridDD} dd The drag drop object
+ * @param {String} targetId The target drag drop object
+ * @param {event} e The raw browser event
+ */
+ 'dragenter' : true,
+ /**
+ * @event dragout
+ * Fires when the dragged row(s) leave another DD target while being dragged
+ * @param {Grid} this
+ * @param {YAHOO.ext.GridDD} dd The drag drop object
+ * @param {String} targetId The target drag drop object
+ * @param {event} e The raw browser event
+ */
+ 'dragout' : true
+ };
+};
+
+YAHOO.ext.grid.Grid.prototype = {
+ /** The minimum width a column can be resized to. (Defaults to 25)
+ * @type Number */
+ minColumnWidth : 25,
+
+ /** True to automatically resize the columns to fit their content <b>on initial render</b>
+ * @type Boolean */
+ autoSizeColumns : false,
+
+ /** True to measure headers with column data when auto sizing columns
+ * @type Boolean */
+ autoSizeHeaders : false,
+
+ /**
+ * True to autoSize the grid when the window resizes - defaults to true
+ */
+ monitorWindowResize : true,
+
+ /** If autoSizeColumns is on, maxRowsToMeasure can be used to limit the number of
+ * rows measured to get a columns size - defaults to 0 (all rows).
+ * @type Number */
+ maxRowsToMeasure : 0,
+
+ /** True to highlight rows when the mouse is over (default is false)
+ * @type Boolean */
+ trackMouseOver : false,
+
+ /** True to enable drag and drop of rows
+ * @type Boolean */
+ enableDragDrop : false,
+
+ /** True to stripe the rows (default is true)
+ * @type Boolean */
+ stripeRows : true,
+ /** True to fit the height of the grid container to the height of the data (defaults to false)
+ * @type Boolean */
+ autoHeight : false,
+
+ /** True to fit the width of the grid container to the width of the columns (defaults to false)
+ * @type Boolean */
+ autoWidth : false,
+
+ /**
+ * The view used by the grid. This can be set before a call to render().
+ * Defaults to a YAHOO.ext.grid.GridView or PagedGridView depending on the data model.
+ * @type Object
+ */
+ view : null,
+
+ /** A regular expression defining tagNames
+ * allowed to have text selection (Defaults to <code>/INPUT|TEXTAREA|SELECT/i</code>) */
+ allowTextSelectionPattern : /INPUT|TEXTAREA|SELECT/i,
+
+ /**
+ * Called once after all setup has been completed and the grid is ready to be rendered.
+ * @return {YAHOO.ext.grid.Grid} this
+ */
+ render : function(){
+ if((!this.container.dom.offsetHeight || this.container.dom.offsetHeight < 20)
+ || this.container.getStyle('height') == 'auto'){
+ this.autoHeight = true;
+ }
+ if((!this.container.dom.offsetWidth || this.container.dom.offsetWidth < 20)){
+ this.autoWidth = true;
+ }
+ if(!this.view){
+ if(this.dataModel.isPaged()){
+ this.view = new YAHOO.ext.grid.PagedGridView();
+ }else{
+ this.view = new YAHOO.ext.grid.GridView();
+ }
+ }
+ this.view.init(this);
+ this.el = getEl(this.view.render(), true);
+ var c = this.container;
+ c.mon("click", this.onClick, this, true);
+ c.mon("dblclick", this.onDblClick, this, true);
+ c.mon("contextmenu", this.onContextMenu, this, true);
+ c.mon("selectstart", this.cancelTextSelection, this, true);
+ c.mon("mousedown", this.cancelTextSelection, this, true);
+ c.mon("mousedown", this.onMouseDown, this, true);
+ c.mon("mouseup", this.onMouseUp, this, true);
+ if(this.trackMouseOver){
+ this.el.mon("mouseover", this.onMouseOver, this, true);
+ this.el.mon("mouseout", this.onMouseOut, this, true);
+ }
+ c.mon("keypress", this.onKeyPress, this, true);
+ c.mon("keydown", this.onKeyDown, this, true);
+ this.init();
+ return this;
+ },
+
+ init : function(){
+ this.rows = this.el.dom.rows;
+ if(!this.disableSelection){
+ if(!this.selModel){
+ this.selModel = new YAHOO.ext.grid.DefaultSelectionModel(this);
+ }
+ this.selModel.init(this);
+ this.selModel.onSelectionChange.subscribe(this.updateField, this, true);
+ }else{
+ this.selModel = new YAHOO.ext.grid.DisableSelectionModel(this);
+ this.selModel.init(this);
+ }
+
+ if(this.enableDragDrop){
+ this.dd = new YAHOO.ext.grid.GridDD(this, this.container.dom);
+ }
+ },
+
+ /**
+ * Resets the grid for use with a new configuration and/or data and column models. After calling this function
+ * you will need to call render() again. Any listeners for this grid will be retained.
+ * Warning: any listeners manually attached (not through the grid) to the grid's container
+ * element will be removed.
+ * @param {Object} config Standard config object with properties to set on this grid
+ * @return {YAHOO.ext.grid.Grid} this
+ */
+ reset : function(config){
+ this.destroy(false, true);
+ YAHOO.ext.util.Config.apply(this, config);
+ return this;
+ },
+
+ /**
+ * Destroy this grid.
+ * @param {Boolean} removeEl True to remove the element
+ */
+ destroy : function(removeEl, keepListeners){
+ var c = this.container;
+ c.removeAllListeners();
+ this.view.destroy();
+ YAHOO.ext.EventManager.removeResizeListener(this.view.onWindowResize, this.view);
+ this.view = null;
+ this.colModel.purgeListeners();
+ if(!keepListeners){
+ this.purgeListeners();
+ }
+ c.update('');
+ if(removeEl === true){
+ c.remove();
+ }
+ },
+
+ /**
+ * Replace the current data model with a new one (experimental)
+ * @param {DataModel} dm The new data model
+ * @pram {Boolean} rerender true to render the grid rows from scratch
+ */
+ setDataModel : function(dm, rerender){
+ this.view.unplugDataModel(this.dataModel);
+ this.dataModel = dm;
+ this.view.plugDataModel(dm);
+ if(rerender){
+ dm.fireEvent('datachanged');
+ }
+ },
+
+ onMouseDown : function(e){
+ this.fireEvent('mousedown', e);
+ },
+
+ onMouseUp : function(e){
+ this.fireEvent('mouseup', e);
+ },
+
+ onMouseOver : function(e){
+ this.fireEvent('mouseover', e);
+ },
+
+ onMouseOut : function(e){
+ this.fireEvent('mouseout', e);
+ },
+
+ onKeyPress : function(e){
+ this.fireEvent('keypress', e);
+ },
+
+ onKeyDown : function(e){
+ this.fireEvent('keydown', e);
+ },
+
+ fireEvent : YAHOO.ext.util.Observable.prototype.fireEvent,
+ on : YAHOO.ext.util.Observable.prototype.on,
+ addListener : YAHOO.ext.util.Observable.prototype.addListener,
+ delayedListener : YAHOO.ext.util.Observable.prototype.delayedListener,
+ removeListener : YAHOO.ext.util.Observable.prototype.removeListener,
+ purgeListeners : YAHOO.ext.util.Observable.prototype.purgeListeners,
+ bufferedListener : YAHOO.ext.util.Observable.prototype.bufferedListener,
+
+ onClick : function(e){
+ this.fireEvent('click', e);
+ var target = e.getTarget();
+ var row = this.getRowFromChild(target);
+ var cell = this.getCellFromChild(target);
+ var header = this.getHeaderFromChild(target);
+ if(cell){
+ this.fireEvent('cellclick', this, row.rowIndex, cell.columnIndex, e);
+ }
+ if(row){
+ this.fireEvent('rowclick', this, row.rowIndex, e);
+ }
+ if(header){
+ this.fireEvent('headerclick', this, header.columnIndex, e);
+ }
+ },
+
+ onContextMenu : function(e){
+ var target = e.getTarget();
+ var row = this.getRowFromChild(target);
+ var cell = this.getCellFromChild(target);
+ var header = this.getHeaderFromChild(target);
+ if(cell){
+ this.fireEvent('cellcontextmenu', this, row.rowIndex, cell.columnIndex, e);
+ }
+ if(row){
+ this.fireEvent('rowcontextmenu', this, row.rowIndex, e);
+ }
+ if(header){
+ this.fireEvent('headercontextmenu', this, header.columnIndex, e);
+ }
+ e.preventDefault();
+ },
+
+ onDblClick : function(e){
+ this.fireEvent('dblclick', e);
+ var target = e.getTarget();
+ var row = this.getRowFromChild(target);
+ var cell = this.getCellFromChild(target);
+ if(row){
+ this.fireEvent('rowdblclick', this, row.rowIndex, e);
+ }
+ if(cell){
+ this.fireEvent('celldblclick', this, row.rowIndex, cell.columnIndex, e);
+ }
+ },
+
+ /**
+ * Starts editing the specified for the specified row/column
+ * @param {Number} rowIndex
+ * @param {Number} colIndex
+ */
+ startEditing : function(rowIndex, colIndex){
+ var row = this.rows[rowIndex];
+ var cell = row.childNodes[colIndex];
+ this.stopEditing();
+ setTimeout(this.doEdit.createDelegate(this, [row, cell]), 10);
+ },
+
+ /**
+ * Stops any active editing
+ */
+ stopEditing : function(){
+ if(this.activeEditor){
+ this.activeEditor.stopEditing();
+ }
+ },
+
+ /** @ignore */
+ doEdit : function(row, cell){
+ if(!row || !cell) return;
+ var cm = this.colModel;
+ var dm = this.dataModel;
+ var colIndex = cell.columnIndex;
+ var rowIndex = row.rowIndex;
+ if(cm.isCellEditable(colIndex, rowIndex)){
+ var ed = cm.getCellEditor(colIndex, rowIndex);
+ if(ed){
+ if(this.activeEditor){
+ this.activeEditor.stopEditing();
+ }
+ this.fireEvent('beforeedit', this, rowIndex, colIndex);
+ this.activeEditor = ed;
+ this.editingCell = cell;
+ this.view.ensureVisible(row, true);
+ try{
+ cell.focus();
+ }catch(e){}
+ ed.init(this, this.el.dom.parentNode, this.setValueDelegate);
+ var value = dm.getValueAt(rowIndex, cm.getDataIndex(colIndex));
+ // set timeout so firefox stops editing before starting a new edit
+ setTimeout(ed.startEditing.createDelegate(ed, [value, row, cell]), 1);
+ }
+ }
+ },
+
+ setCellValue : function(value, rowIndex, colIndex){
+ this.dataModel.setValueAt(value, rowIndex, this.colModel.getDataIndex(colIndex));
+ this.fireEvent('afteredit', this, rowIndex, colIndex);
+ },
+
+ /** @ignore Called when text selection starts or mousedown to prevent default */
+ cancelTextSelection : function(e){
+ var target = e.getTarget();
+ if(target && target != this.el.dom.parentNode && !this.allowTextSelectionPattern.test(target.tagName)){
+ e.preventDefault();
+ }
+ },
+
+ /**
+ * Causes the grid to manually recalculate it's dimensions. Generally this is done automatically,
+ * but if manual update is required this method will initiate it.
+ */
+ autoSize : function(){
+ this.view.updateWrapHeight();
+ this.view.adjustForScroll();
+ },
+
+ /**
+ * Scrolls the grid to the specified row
+ * @param {Number/HTMLElement} row The row object or index of the row
+ */
+ scrollTo : function(row){
+ if(typeof row == 'number'){
+ row = this.rows[row];
+ }
+ this.view.ensureVisible(row, true);
+ },
+
+ /** @private */
+ getEditingCell : function(){
+ return this.editingCell;
+ },
+
+ /**
+ * Binds this grid to the field with the specified id. Initially reads and parses the comma
+ * delimited ids in the field and selects those items. All selections made in the grid
+ * will be persisted to the field by their ids comma delimited.
+ * @param {String} The id of the field to bind to
+ */
+ bindToField : function(fieldId){
+ this.fieldId = fieldId;
+ this.readField();
+ },
+
+ /** @private */
+ updateField : function(){
+ if(this.fieldId){
+ var field = YAHOO.util.Dom.get(this.fieldId);
+ field.value = this.getSelectedRowIds().join(',');
+ }
+ },
+
+ /**
+ * Causes the grid to read and select the ids from the bound field - See {@link #bindToField}.
+ */
+ readField : function(){
+ if(this.fieldId){
+ var field = YAHOO.util.Dom.get(this.fieldId);
+ var values = field.value.split(',');
+ var rows = this.getRowsById(values);
+ this.selModel.selectRows(rows, false);
+ }
+ },
+
+ /**
+ * Returns the table row at the specified index
+ * @param {Number} index
+ * @return {HTMLElement}
+ */
+ getRow : function(index){
+ return this.rows[index];
+ },
+
+ /**
+ * Returns the rows that have the specified id(s). The id value for a row is provided
+ * by the DataModel. See {@link YAHOO.ext.grid.DefaultDataModel#getRowId}.
+ * @param {String/Array} An id to find or an array of ids
+ * @return {HtmlElement/Array} If one id was passed in, it returns one result.
+ * If an array of ids was specified, it returns an Array of HTMLElements
+ */
+ getRowsById : function(id){
+ var dm = this.dataModel;
+ if(!(id instanceof Array)){
+ for(var i = 0; i < this.rows.length; i++){
+ if(dm.getRowId(i) == id){
+ return this.rows[i];
+ }
+ }
+ return null;
+ }
+ var found = [];
+ var re = "^(?:";
+ for(var i = 0; i < id.length; i++){
+ re += id[i];
+ if(i != id.length-1) re += "|";
+ }
+ var regex = new RegExp(re + ")$");
+ for(var i = 0; i < this.rows.length; i++){
+ if(regex.test(dm.getRowId(i))){
+ found.push(this.rows[i]);
+ }
+ }
+ return found;
+ },
+
+ /**
+ * Returns the row that comes after the specified row - text nodes are skipped.
+ * @param {HTMLElement} row
+ * @return {HTMLElement}
+ */
+ getRowAfter : function(row){
+ return this.getSibling('next', row);
+ },
+
+ /**
+ * Returns the row that comes before the specified row - text nodes are skipped.
+ * @param {HTMLElement} row
+ * @return {HTMLElement}
+ */
+ getRowBefore : function(row){
+ return this.getSibling('previous', row);
+ },
+
+ /**
+ * Returns the cell that comes after the specified cell - text nodes are skipped.
+ * @param {HTMLElement} cell
+ * @param {Boolean} includeHidden
+ * @return {HTMLElement}
+ */
+ getCellAfter : function(cell, includeHidden){
+ var next = this.getSibling('next', cell);
+ if(next && !includeHidden && this.colModel.isHidden(next.columnIndex)){
+ return this.getCellAfter(next);
+ }
+ return next;
+ },
+
+ /**
+ * Returns the cell that comes before the specified cell - text nodes are skipped.
+ * @param {HTMLElement} cell
+ * @param {Boolean} includeHidden
+ * @return {HTMLElement}
+ */
+ getCellBefore : function(cell, includeHidden){
+ var prev = this.getSibling('previous', cell);
+ if(prev && !includeHidden && this.colModel.isHidden(prev.columnIndex)){
+ return this.getCellBefore(prev);
+ }
+ return prev;
+ },
+
+ /**
+ * Returns the last cell for the row - text nodes and hidden columns are skipped.
+ * @param {HTMLElement} row
+ * @param {Boolean} includeHidden
+ * @return {HTMLElement}
+ */
+ getLastCell : function(row, includeHidden){
+ var cell = this.getElement('previous', row.lastChild);
+ if(cell && !includeHidden && this.colModel.isHidden(cell.columnIndex)){
+ return this.getCellBefore(cell);
+ }
+ return cell;
+ },
+
+ /**
+ * Returns the first cell for the row - text nodes and hidden columns are skipped.
+ * @param {HTMLElement} row
+ * @param {Boolean} includeHidden
+ * @return {HTMLElement}
+ */
+ getFirstCell : function(row, includeHidden){
+ var cell = this.getElement('next', row.firstChild);
+ if(cell && !includeHidden && this.colModel.isHidden(cell.columnIndex)){
+ return this.getCellAfter(cell);
+ }
+ return cell;
+ },
+
+ /**
+ * @private
+ * Gets siblings, skipping text nodes
+ * @param {String} type The direction to walk: 'next' or 'previous'
+ * @param {HTMLElement} node
+ */
+ getSibling : function(type, node){
+ if(!node) return null;
+ type += 'Sibling';
+ var n = node[type];
+ while(n && n.nodeType != 1){
+ n = n[type];
+ }
+ return n;
+ },
+
+ /**
+ * Returns node if node is an HTMLElement else walks the siblings in direction looking for
+ * a node that is an element
+ * @param {String} direction The direction to walk: 'next' or 'previous'
+ * @private
+ */
+ getElement : function(direction, node){
+ if(!node || node.nodeType == 1) return node;
+ else return this.getSibling(direction, node);
+ },
+
+ /**
+ * @private
+ */
+ getElementFromChild : function(childEl, parentClass){
+ if(!childEl || (YAHOO.util.Dom.hasClass(childEl, parentClass))){
+ return childEl;
+ }
+ var p = childEl.parentNode;
+ var b = document.body;
+ while(p && p != b){
+ if(YAHOO.util.Dom.hasClass(p, parentClass)){
+ return p;
+ }
+ p = p.parentNode;
+ }
+ return null;
+ },
+
+ /**
+ * Returns the row that contains the specified child element.
+ * @param {HTMLElement} childEl
+ * @return {HTMLElement}
+ */
+ getRowFromChild : function(childEl){
+ return this.getElementFromChild(childEl, 'ygrid-row');
+ },
+
+ /**
+ * Returns the cell that contains the specified child element.
+ * @param {HTMLElement} childEl
+ * @return {HTMLElement}
+ */
+ getCellFromChild : function(childEl){
+ return this.getElementFromChild(childEl, 'ygrid-col');
+ },
+
+
+ /**
+ * Returns the header element that contains the specified child element.
+ * @param {HTMLElement} childEl
+ * @return {HTMLElement}
+ */
+ getHeaderFromChild : function(childEl){
+ return this.getElementFromChild(childEl, 'ygrid-hd');
+ },
+
+ /**
+ * Convenience method for getSelectionModel().getSelectedRows() -
+ * See <small>{@link YAHOO.ext.grid.DefaultSelectionModel#getSelectedRows}</small> for more details.
+ * @return {Array}
+ */
+ getSelectedRows : function(){
+ return this.selModel.getSelectedRows();
+ },
+
+ /**
+ * Convenience method for getSelectionModel().getSelectedRows()[0] -
+ * See <small>{@link YAHOO.ext.grid.DefaultSelectionModel#getSelectedRows}</small> for more details.
+ * @return {HTMLElement}
+ */
+ getSelectedRow : function(){
+ if(this.selModel.hasSelection()){
+ return this.selModel.getSelectedRows()[0];
+ }
+ return null;
+ },
+
+ /**
+ * Get the selected row indexes
+ * @return {Array} Array of indexes
+ */
+ getSelectedRowIndexes : function(){
+ var a = [];
+ var rows = this.selModel.getSelectedRows();
+ for(var i = 0; i < rows.length; i++) {
+ a[i] = rows[i].rowIndex;
+ }
+ return a;
+ },
+
+ /**
+ * Gets the first selected row or -1 if none are selected
+ * @return {Number}
+ */
+ getSelectedRowIndex : function(){
+ if(this.selModel.hasSelection()){
+ return this.selModel.getSelectedRows()[0].rowIndex;
+ }
+ return -1;
+ },
+
+ /**
+ * Convenience method for getSelectionModel().getSelectedRowIds()[0] -
+ * See <small>{@link YAHOO.ext.grid.DefaultSelectionModel#getSelectedRowIds}</small> for more details.
+ * @return {String}
+ */
+ getSelectedRowId : function(){
+ if(this.selModel.hasSelection()){
+ return this.selModel.getSelectedRowIds()[0];
+ }
+ return null;
+ },
+
+ /**
+ * Convenience method for getSelectionModel().getSelectedRowIds() -
+ * See <small>{@link YAHOO.ext.grid.DefaultSelectionModel#getSelectedRowIds}</small> for more details.
+ * @return {Array}
+ */
+ getSelectedRowIds : function(){
+ return this.selModel.getSelectedRowIds();
+ },
+
+ /**
+ * Convenience method for getSelectionModel().clearSelections() -
+ * See <small>{@link YAHOO.ext.grid.DefaultSelectionModel#clearSelections}</small> for more details.
+ */
+ clearSelections : function(){
+ this.selModel.clearSelections();
+ },
+
+
+ /**
+ * Convenience method for getSelectionModel().selectAll() -
+ * See <small>{@link YAHOO.ext.grid.DefaultSelectionModel#selectAll}</small> for more details.
+ */
+ selectAll : function(){
+ this.selModel.selectAll();
+ },
+
+
+ /**
+ * Convenience method for getSelectionModel().getCount() -
+ * See <small>{@link YAHOO.ext.grid.DefaultSelectionModel#getCount}</small> for more details.
+ * @return {Number}
+ */
+ getSelectionCount : function(){
+ return this.selModel.getCount();
+ },
+
+ /**
+ * Convenience method for getSelectionModel().hasSelection() -
+ * See <small>{@link YAHOO.ext.grid.DefaultSelectionModel#hasSelection}</small> for more details.
+ * @return {Boolean}
+ */
+ hasSelection : function(){
+ return this.selModel.hasSelection();
+ },
+
+ /**
+ * Returns the grid's SelectionModel.
+ * @return {SelectionModel}
+ */
+ getSelectionModel : function(){
+ if(!this.selModel){
+ this.selModel = new DefaultSelectionModel();
+ }
+ return this.selModel;
+ },
+
+ /**
+ * Returns the grid's DataModel.
+ * @return {DataModel}
+ */
+ getDataModel : function(){
+ return this.dataModel;
+ },
+
+ /**
+ * Returns the grid's ColumnModel.
+ * @return {ColumnModel}
+ */
+ getColumnModel : function(){
+ return this.colModel;
+ },
+
+ /**
+ * Returns the grid's GridView object.
+ * @return {GridView}
+ */
+ getView : function(){
+ return this.view;
+ },
+ /**
+ * Called to get grid's drag proxy text, by default returns this.ddText.
+ * @return {String}
+ */
+ getDragDropText : function(){
+ return this.ddText.replace('%0', this.selModel.getCount());
+ }
+};
+/**
+ * Configures the text is the drag proxy (defaults to "%0 selected row(s)").
+ * %0 is replaced with the number of selected rows.
+ * @type String
+ */
+YAHOO.ext.grid.Grid.prototype.ddText = "%0 selected row(s)";