summaryrefslogtreecommitdiff
path: root/frontend/beta/js/YUI-extensions/grid/Grid.js
Unidiff
Diffstat (limited to 'frontend/beta/js/YUI-extensions/grid/Grid.js') (more/less context) (show 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 @@
1/**
2 * @class YAHOO.ext.grid.Grid
3 * @extends YAHOO.ext.util.Observable
4 * This class represents the primary interface of a component based grid control.
5 * <br><br>Usage:<pre><code>
6 var grid = new YAHOO.ext.grid.Grid('my-container-id', dataModel, columnModel);
7 // set any options
8 grid.render();
9 // or using a config
10 var grid = new YAHOO.ext.grid.Grid('my-container-id', {
11 dataModel: myDataModel,
12 colModel: myColModel,
13 selModel: mySelectionModel,
14 autoSizeColumns: true,
15 monitorWindowResize: false,
16 trackMouseOver: true
17 }).render();
18 * </code></pre>
19 * <b>Common Problems:</b><br/>
20 * - Grid does not resize properly when going smaller: Setting overflow hidden on the container
21 * element will correct this<br/>
22 * - If you get el.style[camel]= NaNpx or -2px or something related, be certain you have given your container element
23 * dimensions. The grid adapts to your container's size, if your container has no size defined then the results
24 * are unpredictable.<br/>
25 * - Do not render the grid into an element with display:none. Try using visibility:hidden. Otherwise there is no way for the
26 * grid to calculate dimensions/offsets.<br/>
27 * @requires YAHOO.util.Dom
28 * @requires YAHOO.util.Event
29 * @requires YAHOO.util.CustomEvent
30 * @requires YAHOO.ext.Element
31 * @requires YAHOO.ext.util.Browser
32 * @requires YAHOO.ext.util.CSS
33 * @requires YAHOO.ext.SplitBar
34 * @requires YAHOO.ext.EventObject
35 * @constructor
36 * @param {String/HTMLElement/YAHOO.ext.Element} container The element into which this grid will be rendered -
37 * The container MUST have some type of size defined for the grid to fill. The container will be
38 * automatically set to position relative if it isn't already.
39 * @param {Object} config A config object that sets properties on this grid OR the data model to bind to
40 * @param {Object} colModel (optional) The column model with info about this grid's columns
41 * @param {Object} selectionModel (optional) The selection model for this grid (defaults to DefaultSelectionModel)
42 */
43YAHOO.ext.grid.Grid = function(container, config, colModel, selectionModel){
44 /** @private */
45 this.container = YAHOO.ext.Element.get(container);
46 this.container.update('');
47 this.container.setStyle('overflow', 'hidden');
48 this.id = this.container.id;
49 this.rows = [];
50 this.rowCount = 0;
51 this.fieldId = null;
52 var dataModel = config; // for legacy pre config support
53 this.dataModel = dataModel;
54 this.colModel = colModel;
55 this.selModel = selectionModel;
56 this.activeEditor = null;
57 this.editingCell = null;
58
59
60 if(typeof config == 'object' && !config.getRowCount){// must be config object
61 YAHOO.ext.util.Config.apply(this, config);
62 }
63
64 /** @private */
65 this.setValueDelegate = this.setCellValue.createDelegate(this);
66
67 /** @private */
68 this.events = {
69 // raw events
70 /**
71 * @event click
72 * The raw click event for the entire grid.
73 * @param {YAHOO.ext.EventObject} e
74 */
75 'click' : true,
76 /**
77 * @event dblclick
78 * The raw dblclick event for the entire grid.
79 * @param {YAHOO.ext.EventObject} e
80 */
81 'dblclick' : true,
82 /**
83 * @event mousedown
84 * The raw mousedown event for the entire grid.
85 * @param {YAHOO.ext.EventObject} e
86 */
87 'mousedown' : true,
88 /**
89 * @event mouseup
90 * The raw mouseup event for the entire grid.
91 * @param {YAHOO.ext.EventObject} e
92 */
93 'mouseup' : true,
94 /**
95 * @event mouseover
96 * The raw mouseover event for the entire grid.
97 * @param {YAHOO.ext.EventObject} e
98 */
99 'mouseover' : true,
100 /**
101 * @event mouseout
102 * The raw mouseout event for the entire grid.
103 * @param {YAHOO.ext.EventObject} e
104 */
105 'mouseout' : true,
106 /**
107 * @event keypress
108 * The raw keypress event for the entire grid.
109 * @param {YAHOO.ext.EventObject} e
110 */
111 'keypress' : true,
112 /**
113 * @event keydown
114 * The raw keydown event for the entire grid.
115 * @param {YAHOO.ext.EventObject} e
116 */
117 'keydown' : true,
118
119 // custom events
120
121 /**
122 * @event cellclick
123 * Fires when a cell is clicked
124 * @param {Grid} this
125 * @param {Number} rowIndex
126 * @param {Number} columnIndex
127 * @param {YAHOO.ext.EventObject} e
128 */
129 'cellclick' : true,
130 /**
131 * @event celldblclick
132 * Fires when a cell is double clicked
133 * @param {Grid} this
134 * @param {Number} rowIndex
135 * @param {Number} columnIndex
136 * @param {YAHOO.ext.EventObject} e
137 */
138 'celldblclick' : true,
139 /**
140 * @event rowclick
141 * Fires when a row is clicked
142 * @param {Grid} this
143 * @param {Number} rowIndex
144 * @param {YAHOO.ext.EventObject} e
145 */
146 'rowclick' : true,
147 /**
148 * @event rowdblclick
149 * Fires when a row is double clicked
150 * @param {Grid} this
151 * @param {Number} rowIndex
152 * @param {YAHOO.ext.EventObject} e
153 */
154 'rowdblclick' : true,
155 /**
156 * @event headerclick
157 * Fires when a header is clicked
158 * @param {Grid} this
159 * @param {Number} columnIndex
160 * @param {YAHOO.ext.EventObject} e
161 */
162 'headerclick' : true,
163 /**
164 * @event rowcontextmenu
165 * Fires when a row is right clicked
166 * @param {Grid} this
167 * @param {Number} rowIndex
168 * @param {YAHOO.ext.EventObject} e
169 */
170 'rowcontextmenu' : true,
171 /**
172 * @event cellcontextmenu
173 * Fires when a cell is right clicked
174 * @param {Grid} this
175 * @param {Number} rowIndex
176 * @param {Number} cellIndex
177 * @param {YAHOO.ext.EventObject} e
178 */
179 'cellcontextmenu' : true,
180 /**
181 * @event headercontextmenu
182 * Fires when a header is right clicked
183 * @param {Grid} this
184 * @param {Number} columnIndex
185 * @param {YAHOO.ext.EventObject} e
186 */
187 'headercontextmenu' : true,
188 /**
189 * @event beforeedit
190 * Fires before a cell is edited
191 * @param {Grid} this
192 * @param {Number} rowIndex
193 * @param {Number} columnIndex
194 */
195 'beforeedit' : true,
196 /**
197 * @event afteredit
198 * Fires after a cell is edited
199 * @param {Grid} this
200 * @param {Number} rowIndex
201 * @param {Number} columnIndex
202 */
203 'afteredit' : true,
204 /**
205 * @event bodyscroll
206 * Fires when the body element is scrolled
207 * @param {Number} scrollLeft
208 * @param {Number} scrollTop
209 */
210 'bodyscroll' : true,
211 /**
212 * @event columnresize
213 * Fires when the user resizes a column
214 * @param {Number} columnIndex
215 * @param {Number} newSize
216 */
217 'columnresize' : true,
218 /**
219 * @event startdrag
220 * Fires when row(s) start being dragged
221 * @param {Grid} this
222 * @param {YAHOO.ext.GridDD} dd The drag drop object
223 * @param {event} e The raw browser event
224 */
225 'startdrag' : true,
226 /**
227 * @event enddrag
228 * Fires when a drag operation is complete
229 * @param {Grid} this
230 * @param {YAHOO.ext.GridDD} dd The drag drop object
231 * @param {event} e The raw browser event
232 */
233 'enddrag' : true,
234 /**
235 * @event dragdrop
236 * Fires when dragged row(s) are dropped on a valid DD target
237 * @param {Grid} this
238 * @param {YAHOO.ext.GridDD} dd The drag drop object
239 * @param {String} targetId The target drag drop object
240 * @param {event} e The raw browser event
241 */
242 'dragdrop' : true,
243 /**
244 * @event dragover
245 * Fires while row(s) are being dragged. "targetId" is the id of the Yahoo.util.DD object the selected rows are being dragged over.
246 * @param {Grid} this
247 * @param {YAHOO.ext.GridDD} dd The drag drop object
248 * @param {String} targetId The target drag drop object
249 * @param {event} e The raw browser event
250 */
251 'dragover' : true,
252 /**
253 * @event dragenter
254 * Fires when the dragged row(s) first cross another DD target while being dragged
255 * @param {Grid} this
256 * @param {YAHOO.ext.GridDD} dd The drag drop object
257 * @param {String} targetId The target drag drop object
258 * @param {event} e The raw browser event
259 */
260 'dragenter' : true,
261 /**
262 * @event dragout
263 * Fires when the dragged row(s) leave another DD target while being dragged
264 * @param {Grid} this
265 * @param {YAHOO.ext.GridDD} dd The drag drop object
266 * @param {String} targetId The target drag drop object
267 * @param {event} e The raw browser event
268 */
269 'dragout' : true
270 };
271};
272
273YAHOO.ext.grid.Grid.prototype = {
274 /** The minimum width a column can be resized to. (Defaults to 25)
275 * @type Number */
276 minColumnWidth : 25,
277
278 /** True to automatically resize the columns to fit their content <b>on initial render</b>
279 * @type Boolean */
280 autoSizeColumns : false,
281
282 /** True to measure headers with column data when auto sizing columns
283 * @type Boolean */
284 autoSizeHeaders : false,
285
286 /**
287 * True to autoSize the grid when the window resizes - defaults to true
288 */
289 monitorWindowResize : true,
290
291 /** If autoSizeColumns is on, maxRowsToMeasure can be used to limit the number of
292 * rows measured to get a columns size - defaults to 0 (all rows).
293 * @type Number */
294 maxRowsToMeasure : 0,
295
296 /** True to highlight rows when the mouse is over (default is false)
297 * @type Boolean */
298 trackMouseOver : false,
299
300 /** True to enable drag and drop of rows
301 * @type Boolean */
302 enableDragDrop : false,
303
304 /** True to stripe the rows (default is true)
305 * @type Boolean */
306 stripeRows : true,
307 /** True to fit the height of the grid container to the height of the data (defaults to false)
308 * @type Boolean */
309 autoHeight : false,
310
311 /** True to fit the width of the grid container to the width of the columns (defaults to false)
312 * @type Boolean */
313 autoWidth : false,
314
315 /**
316 * The view used by the grid. This can be set before a call to render().
317 * Defaults to a YAHOO.ext.grid.GridView or PagedGridView depending on the data model.
318 * @type Object
319 */
320 view : null,
321
322 /** A regular expression defining tagNames
323 * allowed to have text selection (Defaults to <code>/INPUT|TEXTAREA|SELECT/i</code>) */
324 allowTextSelectionPattern : /INPUT|TEXTAREA|SELECT/i,
325
326 /**
327 * Called once after all setup has been completed and the grid is ready to be rendered.
328 * @return {YAHOO.ext.grid.Grid} this
329 */
330 render : function(){
331 if((!this.container.dom.offsetHeight || this.container.dom.offsetHeight < 20)
332 || this.container.getStyle('height') == 'auto'){
333 this.autoHeight = true;
334 }
335 if((!this.container.dom.offsetWidth || this.container.dom.offsetWidth < 20)){
336 this.autoWidth = true;
337 }
338 if(!this.view){
339 if(this.dataModel.isPaged()){
340 this.view = new YAHOO.ext.grid.PagedGridView();
341 }else{
342 this.view = new YAHOO.ext.grid.GridView();
343 }
344 }
345 this.view.init(this);
346 this.el = getEl(this.view.render(), true);
347 var c = this.container;
348 c.mon("click", this.onClick, this, true);
349 c.mon("dblclick", this.onDblClick, this, true);
350 c.mon("contextmenu", this.onContextMenu, this, true);
351 c.mon("selectstart", this.cancelTextSelection, this, true);
352 c.mon("mousedown", this.cancelTextSelection, this, true);
353 c.mon("mousedown", this.onMouseDown, this, true);
354 c.mon("mouseup", this.onMouseUp, this, true);
355 if(this.trackMouseOver){
356 this.el.mon("mouseover", this.onMouseOver, this, true);
357 this.el.mon("mouseout", this.onMouseOut, this, true);
358 }
359 c.mon("keypress", this.onKeyPress, this, true);
360 c.mon("keydown", this.onKeyDown, this, true);
361 this.init();
362 return this;
363 },
364
365 init : function(){
366 this.rows = this.el.dom.rows;
367 if(!this.disableSelection){
368 if(!this.selModel){
369 this.selModel = new YAHOO.ext.grid.DefaultSelectionModel(this);
370 }
371 this.selModel.init(this);
372 this.selModel.onSelectionChange.subscribe(this.updateField, this, true);
373 }else{
374 this.selModel = new YAHOO.ext.grid.DisableSelectionModel(this);
375 this.selModel.init(this);
376 }
377
378 if(this.enableDragDrop){
379 this.dd = new YAHOO.ext.grid.GridDD(this, this.container.dom);
380 }
381 },
382
383 /**
384 * Resets the grid for use with a new configuration and/or data and column models. After calling this function
385 * you will need to call render() again. Any listeners for this grid will be retained.
386 * Warning: any listeners manually attached (not through the grid) to the grid's container
387 * element will be removed.
388 * @param {Object} config Standard config object with properties to set on this grid
389 * @return {YAHOO.ext.grid.Grid} this
390 */
391 reset : function(config){
392 this.destroy(false, true);
393 YAHOO.ext.util.Config.apply(this, config);
394 return this;
395 },
396
397 /**
398 * Destroy this grid.
399 * @param {Boolean} removeEl True to remove the element
400 */
401 destroy : function(removeEl, keepListeners){
402 var c = this.container;
403 c.removeAllListeners();
404 this.view.destroy();
405 YAHOO.ext.EventManager.removeResizeListener(this.view.onWindowResize, this.view);
406 this.view = null;
407 this.colModel.purgeListeners();
408 if(!keepListeners){
409 this.purgeListeners();
410 }
411 c.update('');
412 if(removeEl === true){
413 c.remove();
414 }
415 },
416
417 /**
418 * Replace the current data model with a new one (experimental)
419 * @param {DataModel} dm The new data model
420 * @pram {Boolean} rerender true to render the grid rows from scratch
421 */
422 setDataModel : function(dm, rerender){
423 this.view.unplugDataModel(this.dataModel);
424 this.dataModel = dm;
425 this.view.plugDataModel(dm);
426 if(rerender){
427 dm.fireEvent('datachanged');
428 }
429 },
430
431 onMouseDown : function(e){
432 this.fireEvent('mousedown', e);
433 },
434
435 onMouseUp : function(e){
436 this.fireEvent('mouseup', e);
437 },
438
439 onMouseOver : function(e){
440 this.fireEvent('mouseover', e);
441 },
442
443 onMouseOut : function(e){
444 this.fireEvent('mouseout', e);
445 },
446
447 onKeyPress : function(e){
448 this.fireEvent('keypress', e);
449 },
450
451 onKeyDown : function(e){
452 this.fireEvent('keydown', e);
453 },
454
455 fireEvent : YAHOO.ext.util.Observable.prototype.fireEvent,
456 on : YAHOO.ext.util.Observable.prototype.on,
457 addListener : YAHOO.ext.util.Observable.prototype.addListener,
458 delayedListener : YAHOO.ext.util.Observable.prototype.delayedListener,
459 removeListener : YAHOO.ext.util.Observable.prototype.removeListener,
460 purgeListeners : YAHOO.ext.util.Observable.prototype.purgeListeners,
461 bufferedListener : YAHOO.ext.util.Observable.prototype.bufferedListener,
462
463 onClick : function(e){
464 this.fireEvent('click', e);
465 var target = e.getTarget();
466 var row = this.getRowFromChild(target);
467 var cell = this.getCellFromChild(target);
468 var header = this.getHeaderFromChild(target);
469 if(cell){
470 this.fireEvent('cellclick', this, row.rowIndex, cell.columnIndex, e);
471 }
472 if(row){
473 this.fireEvent('rowclick', this, row.rowIndex, e);
474 }
475 if(header){
476 this.fireEvent('headerclick', this, header.columnIndex, e);
477 }
478 },
479
480 onContextMenu : function(e){
481 var target = e.getTarget();
482 var row = this.getRowFromChild(target);
483 var cell = this.getCellFromChild(target);
484 var header = this.getHeaderFromChild(target);
485 if(cell){
486 this.fireEvent('cellcontextmenu', this, row.rowIndex, cell.columnIndex, e);
487 }
488 if(row){
489 this.fireEvent('rowcontextmenu', this, row.rowIndex, e);
490 }
491 if(header){
492 this.fireEvent('headercontextmenu', this, header.columnIndex, e);
493 }
494 e.preventDefault();
495 },
496
497 onDblClick : function(e){
498 this.fireEvent('dblclick', e);
499 var target = e.getTarget();
500 var row = this.getRowFromChild(target);
501 var cell = this.getCellFromChild(target);
502 if(row){
503 this.fireEvent('rowdblclick', this, row.rowIndex, e);
504 }
505 if(cell){
506 this.fireEvent('celldblclick', this, row.rowIndex, cell.columnIndex, e);
507 }
508 },
509
510 /**
511 * Starts editing the specified for the specified row/column
512 * @param {Number} rowIndex
513 * @param {Number} colIndex
514 */
515 startEditing : function(rowIndex, colIndex){
516 var row = this.rows[rowIndex];
517 var cell = row.childNodes[colIndex];
518 this.stopEditing();
519 setTimeout(this.doEdit.createDelegate(this, [row, cell]), 10);
520 },
521
522 /**
523 * Stops any active editing
524 */
525 stopEditing : function(){
526 if(this.activeEditor){
527 this.activeEditor.stopEditing();
528 }
529 },
530
531 /** @ignore */
532 doEdit : function(row, cell){
533 if(!row || !cell) return;
534 var cm = this.colModel;
535 var dm = this.dataModel;
536 var colIndex = cell.columnIndex;
537 var rowIndex = row.rowIndex;
538 if(cm.isCellEditable(colIndex, rowIndex)){
539 var ed = cm.getCellEditor(colIndex, rowIndex);
540 if(ed){
541 if(this.activeEditor){
542 this.activeEditor.stopEditing();
543 }
544 this.fireEvent('beforeedit', this, rowIndex, colIndex);
545 this.activeEditor = ed;
546 this.editingCell = cell;
547 this.view.ensureVisible(row, true);
548 try{
549 cell.focus();
550 }catch(e){}
551 ed.init(this, this.el.dom.parentNode, this.setValueDelegate);
552 var value = dm.getValueAt(rowIndex, cm.getDataIndex(colIndex));
553 // set timeout so firefox stops editing before starting a new edit
554 setTimeout(ed.startEditing.createDelegate(ed, [value, row, cell]), 1);
555 }
556 }
557 },
558
559 setCellValue : function(value, rowIndex, colIndex){
560 this.dataModel.setValueAt(value, rowIndex, this.colModel.getDataIndex(colIndex));
561 this.fireEvent('afteredit', this, rowIndex, colIndex);
562 },
563
564 /** @ignore Called when text selection starts or mousedown to prevent default */
565 cancelTextSelection : function(e){
566 var target = e.getTarget();
567 if(target && target != this.el.dom.parentNode && !this.allowTextSelectionPattern.test(target.tagName)){
568 e.preventDefault();
569 }
570 },
571
572 /**
573 * Causes the grid to manually recalculate it's dimensions. Generally this is done automatically,
574 * but if manual update is required this method will initiate it.
575 */
576 autoSize : function(){
577 this.view.updateWrapHeight();
578 this.view.adjustForScroll();
579 },
580
581 /**
582 * Scrolls the grid to the specified row
583 * @param {Number/HTMLElement} row The row object or index of the row
584 */
585 scrollTo : function(row){
586 if(typeof row == 'number'){
587 row = this.rows[row];
588 }
589 this.view.ensureVisible(row, true);
590 },
591
592 /** @private */
593 getEditingCell : function(){
594 return this.editingCell;
595 },
596
597 /**
598 * Binds this grid to the field with the specified id. Initially reads and parses the comma
599 * delimited ids in the field and selects those items. All selections made in the grid
600 * will be persisted to the field by their ids comma delimited.
601 * @param {String} The id of the field to bind to
602 */
603 bindToField : function(fieldId){
604 this.fieldId = fieldId;
605 this.readField();
606 },
607
608 /** @private */
609 updateField : function(){
610 if(this.fieldId){
611 var field = YAHOO.util.Dom.get(this.fieldId);
612 field.value = this.getSelectedRowIds().join(',');
613 }
614 },
615
616 /**
617 * Causes the grid to read and select the ids from the bound field - See {@link #bindToField}.
618 */
619 readField : function(){
620 if(this.fieldId){
621 var field = YAHOO.util.Dom.get(this.fieldId);
622 var values = field.value.split(',');
623 var rows = this.getRowsById(values);
624 this.selModel.selectRows(rows, false);
625 }
626 },
627
628 /**
629 * Returns the table row at the specified index
630 * @param {Number} index
631 * @return {HTMLElement}
632 */
633 getRow : function(index){
634 return this.rows[index];
635 },
636
637 /**
638 * Returns the rows that have the specified id(s). The id value for a row is provided
639 * by the DataModel. See {@link YAHOO.ext.grid.DefaultDataModel#getRowId}.
640 * @param {String/Array} An id to find or an array of ids
641 * @return {HtmlElement/Array} If one id was passed in, it returns one result.
642 * If an array of ids was specified, it returns an Array of HTMLElements
643 */
644 getRowsById : function(id){
645 var dm = this.dataModel;
646 if(!(id instanceof Array)){
647 for(var i = 0; i < this.rows.length; i++){
648 if(dm.getRowId(i) == id){
649 return this.rows[i];
650 }
651 }
652 return null;
653 }
654 var found = [];
655 var re = "^(?:";
656 for(var i = 0; i < id.length; i++){
657 re += id[i];
658 if(i != id.length-1) re += "|";
659 }
660 var regex = new RegExp(re + ")$");
661 for(var i = 0; i < this.rows.length; i++){
662 if(regex.test(dm.getRowId(i))){
663 found.push(this.rows[i]);
664 }
665 }
666 return found;
667 },
668
669 /**
670 * Returns the row that comes after the specified row - text nodes are skipped.
671 * @param {HTMLElement} row
672 * @return {HTMLElement}
673 */
674 getRowAfter : function(row){
675 return this.getSibling('next', row);
676 },
677
678 /**
679 * Returns the row that comes before the specified row - text nodes are skipped.
680 * @param {HTMLElement} row
681 * @return {HTMLElement}
682 */
683 getRowBefore : function(row){
684 return this.getSibling('previous', row);
685 },
686
687 /**
688 * Returns the cell that comes after the specified cell - text nodes are skipped.
689 * @param {HTMLElement} cell
690 * @param {Boolean} includeHidden
691 * @return {HTMLElement}
692 */
693 getCellAfter : function(cell, includeHidden){
694 var next = this.getSibling('next', cell);
695 if(next && !includeHidden && this.colModel.isHidden(next.columnIndex)){
696 return this.getCellAfter(next);
697 }
698 return next;
699 },
700
701 /**
702 * Returns the cell that comes before the specified cell - text nodes are skipped.
703 * @param {HTMLElement} cell
704 * @param {Boolean} includeHidden
705 * @return {HTMLElement}
706 */
707 getCellBefore : function(cell, includeHidden){
708 var prev = this.getSibling('previous', cell);
709 if(prev && !includeHidden && this.colModel.isHidden(prev.columnIndex)){
710 return this.getCellBefore(prev);
711 }
712 return prev;
713 },
714
715 /**
716 * Returns the last cell for the row - text nodes and hidden columns are skipped.
717 * @param {HTMLElement} row
718 * @param {Boolean} includeHidden
719 * @return {HTMLElement}
720 */
721 getLastCell : function(row, includeHidden){
722 var cell = this.getElement('previous', row.lastChild);
723 if(cell && !includeHidden && this.colModel.isHidden(cell.columnIndex)){
724 return this.getCellBefore(cell);
725 }
726 return cell;
727 },
728
729 /**
730 * Returns the first cell for the row - text nodes and hidden columns are skipped.
731 * @param {HTMLElement} row
732 * @param {Boolean} includeHidden
733 * @return {HTMLElement}
734 */
735 getFirstCell : function(row, includeHidden){
736 var cell = this.getElement('next', row.firstChild);
737 if(cell && !includeHidden && this.colModel.isHidden(cell.columnIndex)){
738 return this.getCellAfter(cell);
739 }
740 return cell;
741 },
742
743 /**
744 * @private
745 * Gets siblings, skipping text nodes
746 * @param {String} type The direction to walk: 'next' or 'previous'
747 * @param {HTMLElement} node
748 */
749 getSibling : function(type, node){
750 if(!node) return null;
751 type += 'Sibling';
752 var n = node[type];
753 while(n && n.nodeType != 1){
754 n = n[type];
755 }
756 return n;
757 },
758
759 /**
760 * Returns node if node is an HTMLElement else walks the siblings in direction looking for
761 * a node that is an element
762 * @param {String} direction The direction to walk: 'next' or 'previous'
763 * @private
764 */
765 getElement : function(direction, node){
766 if(!node || node.nodeType == 1) return node;
767 else return this.getSibling(direction, node);
768 },
769
770 /**
771 * @private
772 */
773 getElementFromChild : function(childEl, parentClass){
774 if(!childEl || (YAHOO.util.Dom.hasClass(childEl, parentClass))){
775 return childEl;
776 }
777 var p = childEl.parentNode;
778 var b = document.body;
779 while(p && p != b){
780 if(YAHOO.util.Dom.hasClass(p, parentClass)){
781 return p;
782 }
783 p = p.parentNode;
784 }
785 return null;
786 },
787
788 /**
789 * Returns the row that contains the specified child element.
790 * @param {HTMLElement} childEl
791 * @return {HTMLElement}
792 */
793 getRowFromChild : function(childEl){
794 return this.getElementFromChild(childEl, 'ygrid-row');
795 },
796
797 /**
798 * Returns the cell that contains the specified child element.
799 * @param {HTMLElement} childEl
800 * @return {HTMLElement}
801 */
802 getCellFromChild : function(childEl){
803 return this.getElementFromChild(childEl, 'ygrid-col');
804 },
805
806
807 /**
808 * Returns the header element that contains the specified child element.
809 * @param {HTMLElement} childEl
810 * @return {HTMLElement}
811 */
812 getHeaderFromChild : function(childEl){
813 return this.getElementFromChild(childEl, 'ygrid-hd');
814 },
815
816 /**
817 * Convenience method for getSelectionModel().getSelectedRows() -
818 * See <small>{@link YAHOO.ext.grid.DefaultSelectionModel#getSelectedRows}</small> for more details.
819 * @return {Array}
820 */
821 getSelectedRows : function(){
822 return this.selModel.getSelectedRows();
823 },
824
825 /**
826 * Convenience method for getSelectionModel().getSelectedRows()[0] -
827 * See <small>{@link YAHOO.ext.grid.DefaultSelectionModel#getSelectedRows}</small> for more details.
828 * @return {HTMLElement}
829 */
830 getSelectedRow : function(){
831 if(this.selModel.hasSelection()){
832 return this.selModel.getSelectedRows()[0];
833 }
834 return null;
835 },
836
837 /**
838 * Get the selected row indexes
839 * @return {Array} Array of indexes
840 */
841 getSelectedRowIndexes : function(){
842 var a = [];
843 var rows = this.selModel.getSelectedRows();
844 for(var i = 0; i < rows.length; i++) {
845 a[i] = rows[i].rowIndex;
846 }
847 return a;
848 },
849
850 /**
851 * Gets the first selected row or -1 if none are selected
852 * @return {Number}
853 */
854 getSelectedRowIndex : function(){
855 if(this.selModel.hasSelection()){
856 return this.selModel.getSelectedRows()[0].rowIndex;
857 }
858 return -1;
859 },
860
861 /**
862 * Convenience method for getSelectionModel().getSelectedRowIds()[0] -
863 * See <small>{@link YAHOO.ext.grid.DefaultSelectionModel#getSelectedRowIds}</small> for more details.
864 * @return {String}
865 */
866 getSelectedRowId : function(){
867 if(this.selModel.hasSelection()){
868 return this.selModel.getSelectedRowIds()[0];
869 }
870 return null;
871 },
872
873 /**
874 * Convenience method for getSelectionModel().getSelectedRowIds() -
875 * See <small>{@link YAHOO.ext.grid.DefaultSelectionModel#getSelectedRowIds}</small> for more details.
876 * @return {Array}
877 */
878 getSelectedRowIds : function(){
879 return this.selModel.getSelectedRowIds();
880 },
881
882 /**
883 * Convenience method for getSelectionModel().clearSelections() -
884 * See <small>{@link YAHOO.ext.grid.DefaultSelectionModel#clearSelections}</small> for more details.
885 */
886 clearSelections : function(){
887 this.selModel.clearSelections();
888 },
889
890
891 /**
892 * Convenience method for getSelectionModel().selectAll() -
893 * See <small>{@link YAHOO.ext.grid.DefaultSelectionModel#selectAll}</small> for more details.
894 */
895 selectAll : function(){
896 this.selModel.selectAll();
897 },
898
899
900 /**
901 * Convenience method for getSelectionModel().getCount() -
902 * See <small>{@link YAHOO.ext.grid.DefaultSelectionModel#getCount}</small> for more details.
903 * @return {Number}
904 */
905 getSelectionCount : function(){
906 return this.selModel.getCount();
907 },
908
909 /**
910 * Convenience method for getSelectionModel().hasSelection() -
911 * See <small>{@link YAHOO.ext.grid.DefaultSelectionModel#hasSelection}</small> for more details.
912 * @return {Boolean}
913 */
914 hasSelection : function(){
915 return this.selModel.hasSelection();
916 },
917
918 /**
919 * Returns the grid's SelectionModel.
920 * @return {SelectionModel}
921 */
922 getSelectionModel : function(){
923 if(!this.selModel){
924 this.selModel = new DefaultSelectionModel();
925 }
926 return this.selModel;
927 },
928
929 /**
930 * Returns the grid's DataModel.
931 * @return {DataModel}
932 */
933 getDataModel : function(){
934 return this.dataModel;
935 },
936
937 /**
938 * Returns the grid's ColumnModel.
939 * @return {ColumnModel}
940 */
941 getColumnModel : function(){
942 return this.colModel;
943 },
944
945 /**
946 * Returns the grid's GridView object.
947 * @return {GridView}
948 */
949 getView : function(){
950 return this.view;
951 },
952 /**
953 * Called to get grid's drag proxy text, by default returns this.ddText.
954 * @return {String}
955 */
956 getDragDropText : function(){
957 return this.ddText.replace('%0', this.selModel.getCount());
958 }
959};
960/**
961 * Configures the text is the drag proxy (defaults to "%0 selected row(s)").
962 * %0 is replaced with the number of selected rows.
963 * @type String
964 */
965YAHOO.ext.grid.Grid.prototype.ddText = "%0 selected row(s)";