summaryrefslogtreecommitdiff
path: root/frontend/beta/js/YUI-extensions/grid/GridView.js
Unidiff
Diffstat (limited to 'frontend/beta/js/YUI-extensions/grid/GridView.js') (more/less context) (show whitespace changes)
-rw-r--r--frontend/beta/js/YUI-extensions/grid/GridView.js790
1 files changed, 790 insertions, 0 deletions
diff --git a/frontend/beta/js/YUI-extensions/grid/GridView.js b/frontend/beta/js/YUI-extensions/grid/GridView.js
new file mode 100644
index 0000000..dbd47e3
--- a/dev/null
+++ b/frontend/beta/js/YUI-extensions/grid/GridView.js
@@ -0,0 +1,790 @@
1/**
2 * @class YAHOO.ext.grid.GridView
3 * Default UI code used internally by the Grid. This is the object returned by {@link YAHOO.ext.grid.Grid#getView}.
4 * @constructor
5 */
6YAHOO.ext.grid.GridView = function(){
7 this.grid = null;
8 this.lastFocusedRow = null;
9 this.onScroll = new YAHOO.util.CustomEvent('onscroll');
10 this.adjustScrollTask = new YAHOO.ext.util.DelayedTask(this._adjustForScroll, this);
11 this.ensureVisibleTask = new YAHOO.ext.util.DelayedTask();
12};
13
14YAHOO.ext.grid.GridView.prototype = {
15 init: function(grid){
16 this.grid = grid;
17 },
18
19 fireScroll: function(scrollLeft, scrollTop){
20 this.onScroll.fireDirect(this.grid, scrollLeft, scrollTop);
21 },
22
23 /**
24 * @private
25 * Utility method that gets an array of the cell renderers
26 */
27 getColumnRenderers : function(){
28 var renderers = [];
29 var cm = this.grid.colModel;
30 var colCount = cm.getColumnCount();
31 for(var i = 0; i < colCount; i++){
32 renderers.push(cm.getRenderer(i));
33 }
34 return renderers;
35 },
36
37 buildIndexMap : function(){
38 var colToData = {};
39 var dataToCol = {};
40 var cm = this.grid.colModel;
41 for(var i = 0, len = cm.getColumnCount(); i < len; i++){
42 var di = cm.getDataIndex(i);
43 colToData[i] = di;
44 dataToCol[di] = i;
45 }
46 return {'colToData': colToData, 'dataToCol': dataToCol};
47 },
48
49 getDataIndexes : function(){
50 if(!this.indexMap){
51 this.indexMap = this.buildIndexMap();
52 }
53 return this.indexMap.colToData;
54 },
55
56 getColumnIndexByDataIndex : function(dataIndex){
57 if(!this.indexMap){
58 this.indexMap = this.buildIndexMap();
59 }
60 return this.indexMap.dataToCol[dataIndex];
61 },
62
63 updateHeaders : function(){
64 var colModel = this.grid.colModel;
65 var hcells = this.headers;
66 var colCount = colModel.getColumnCount();
67 for(var i = 0; i < colCount; i++){
68 hcells[i].textNode.innerHTML = colModel.getColumnHeader(i);
69 }
70 },
71
72 adjustForScroll : function(disableDelay){
73 if(!disableDelay){
74 this.adjustScrollTask.delay(50);
75 }else{
76 this._adjustForScroll();
77 }
78 },
79
80 /**
81 * Returns the rowIndex/columnIndex of the cell found at the passed page coordinates
82 * @param {Number} x
83 * @param {Number} y
84 * @return {Array} [rowIndex, columnIndex]
85 */
86 getCellAtPoint : function(x, y){
87 var colIndex = null;
88 var rowIndex = null;
89
90 // translate page coordinates to local coordinates
91 var xy = YAHOO.util.Dom.getXY(this.wrap);
92 x = (x - xy[0]) + this.wrap.scrollLeft;
93 y = (y - xy[1]) + this.wrap.scrollTop;
94
95 var colModel = this.grid.colModel;
96 var pos = 0;
97 var colCount = colModel.getColumnCount();
98 for(var i = 0; i < colCount; i++){
99 if(colModel.isHidden(i)) continue;
100 var width = colModel.getColumnWidth(i);
101 if(x >= pos && x < pos+width){
102 colIndex = i;
103 break;
104 }
105 pos += width;
106 }
107 if(colIndex != null){
108 rowIndex = (y == 0 ? 0 : Math.floor(y / this.getRowHeight()));
109 if(rowIndex >= this.grid.dataModel.getRowCount()){
110 return null;
111 }
112 return [colIndex, rowIndex];
113 }
114 return null;
115 },
116
117 /** @private */
118 _adjustForScroll : function(){
119 this.forceScrollUpdate();
120 if(this.scrollbarMode == YAHOO.ext.grid.GridView.SCROLLBARS_OVERLAP){
121 var adjustment = 0;
122 if(this.wrap.clientWidth && this.wrap.clientWidth !== 0){
123 adjustment = this.wrap.offsetWidth - this.wrap.clientWidth;
124 }
125 this.hwrap.setWidth(this.wrap.offsetWidth-adjustment);
126 }else{
127 this.hwrap.setWidth(this.wrap.offsetWidth);
128 }
129 this.bwrap.setWidth(Math.max(this.grid.colModel.getTotalWidth(), this.wrap.clientWidth));
130 },
131
132 /**
133 * Focuses the specified row. The preferred way to scroll to a row is {@link #ensureVisible}.
134 * @param {Number/HTMLElement} row The index of a row or the row itself
135 */
136 focusRow : function(row){
137 if(typeof row == 'number'){
138 row = this.getBodyTable().childNodes[row];
139 }
140 if(!row) return;
141 var left = this.wrap.scrollLeft;
142 try{ // try catch for IE occasional focus bug
143 row.childNodes.item(0).hideFocus = true;
144 row.childNodes.item(0).focus();
145 }catch(e){}
146 this.ensureVisible(row);
147 this.wrap.scrollLeft = left;
148 this.handleScroll();
149 this.lastFocusedRow = row;
150 },
151
152 /**
153 * Scrolls the specified row into view. This call is automatically buffered (delayed), to disable
154 * the delay, pass true for disableDelay.
155 * @param {Number/HTMLElement} row The index of a row or the row itself
156 * @param {Boolean} disableDelay
157 */
158 ensureVisible : function(row, disableDelay){
159 if(!disableDelay){
160 this.ensureVisibleTask.delay(50, this._ensureVisible, this, [row]);
161 }else{
162 this._ensureVisible(row);
163 }
164 },
165
166 /** @ignore */
167 _ensureVisible : function(row){
168 if(typeof row == 'number'){
169 row = this.getBodyTable().childNodes[row];
170 }
171 if(!row) return;
172 var left = this.wrap.scrollLeft;
173 var rowTop = parseInt(row.offsetTop, 10); // parseInt for safari bug
174 var rowBottom = rowTop + row.offsetHeight;
175 var clientTop = parseInt(this.wrap.scrollTop, 10); // parseInt for safari bug
176 var clientBottom = clientTop + this.wrap.clientHeight;
177 if(rowTop < clientTop){
178 this.wrap.scrollTop = rowTop;
179 }else if(rowBottom > clientBottom){
180 this.wrap.scrollTop = rowBottom-this.wrap.clientHeight;
181 }
182 this.wrap.scrollLeft = left;
183 this.handleScroll();
184 },
185
186 updateColumns : function(){
187 this.grid.stopEditing();
188 var colModel = this.grid.colModel;
189 var hcols = this.headers;
190 var colCount = colModel.getColumnCount();
191 var pos = 0;
192 var totalWidth = colModel.getTotalWidth();
193 for(var i = 0; i < colCount; i++){
194 if(colModel.isHidden(i)) continue;
195 var width = colModel.getColumnWidth(i);
196 hcols[i].style.width = width + 'px';
197 hcols[i].style.left = pos + 'px';
198 hcols[i].split.style.left = (pos+width-3) + 'px';
199 this.setCSSWidth(i, width, pos);
200 pos += width;
201 }
202 this.lastWidth = totalWidth;
203 if(this.grid.autoWidth){
204 this.grid.container.setWidth(totalWidth+this.grid.container.getBorderWidth('lr'));
205 this.grid.autoSize();
206 }
207 this.bwrap.setWidth(Math.max(totalWidth, this.wrap.clientWidth));
208 if(!YAHOO.ext.util.Browser.isIE){ // fix scrolling prob in gecko and opera
209 this.wrap.scrollLeft = this.hwrap.dom.scrollLeft;
210 }
211 this.syncScroll();
212 this.forceScrollUpdate();
213 if(this.grid.autoHeight){
214 this.autoHeight();
215 this.updateWrapHeight();
216 }
217 },
218
219 setCSSWidth : function(colIndex, width, pos){
220 var selector = ["#" + this.grid.id + " .ygrid-col-" + colIndex, ".ygrid-col-" + colIndex];
221 YAHOO.ext.util.CSS.updateRule(selector, 'width', width + 'px');
222 if(typeof pos == 'number'){
223 YAHOO.ext.util.CSS.updateRule(selector, 'left', pos + 'px');
224 }
225 },
226
227 /**
228 * Set a css style for a column dynamically.
229 * @param {Number} colIndex The index of the column
230 * @param {String} name The css property name
231 * @param {String} value The css value
232 */
233 setCSSStyle : function(colIndex, name, value){
234 var selector = ["#" + this.grid.id + " .ygrid-col-" + colIndex, ".ygrid-col-" + colIndex];
235 YAHOO.ext.util.CSS.updateRule(selector, name, value);
236 },
237
238 handleHiddenChange : function(colModel, colIndex, hidden){
239 if(hidden){
240 this.hideColumn(colIndex);
241 }else{
242 this.unhideColumn(colIndex);
243 }
244 this.updateColumns();
245 },
246
247 hideColumn : function(colIndex){
248 var selector = ["#" + this.grid.id + " .ygrid-col-" + colIndex, ".ygrid-col-" + colIndex];
249 YAHOO.ext.util.CSS.updateRule(selector, 'position', 'absolute');
250 YAHOO.ext.util.CSS.updateRule(selector, 'visibility', 'hidden');
251
252 this.headers[colIndex].style.display = 'none';
253 this.headers[colIndex].split.style.display = 'none';
254 },
255
256 unhideColumn : function(colIndex){
257 var selector = ["#" + this.grid.id + " .ygrid-col-" + colIndex, ".ygrid-col-" + colIndex];
258 YAHOO.ext.util.CSS.updateRule(selector, 'position', '');
259 YAHOO.ext.util.CSS.updateRule(selector, 'visibility', 'visible');
260
261 this.headers[colIndex].style.display = '';
262 this.headers[colIndex].split.style.display = '';
263 },
264
265 getBodyTable : function(){
266 return this.bwrap.dom;
267 },
268
269 updateRowIndexes : function(firstRow, lastRow){
270 var stripeRows = this.grid.stripeRows;
271 var bt = this.getBodyTable();
272 var nodes = bt.childNodes;
273 firstRow = firstRow || 0;
274 lastRow = lastRow || nodes.length-1;
275 var re = /^(?:ygrid-row ygrid-row-alt|ygrid-row)/;
276 for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
277 var node = nodes[rowIndex];
278 if(stripeRows && (rowIndex+1) % 2 == 0){
279 node.className = node.className.replace(re, 'ygrid-row ygrid-row-alt');
280 }else{
281 node.className = node.className.replace(re, 'ygrid-row');
282 }
283 node.rowIndex = rowIndex;
284 nodes[rowIndex].style.top = (rowIndex * this.rowHeight) + 'px';
285 }
286 },
287
288 insertRows : function(dataModel, firstRow, lastRow){
289 this.updateBodyHeight();
290 this.adjustForScroll(true);
291 var renderers = this.getColumnRenderers();
292 var dindexes = this.getDataIndexes();
293 var colCount = this.grid.colModel.getColumnCount();
294 var beforeRow = null;
295 var bt = this.getBodyTable();
296 if(firstRow < bt.childNodes.length){
297 beforeRow = bt.childNodes[firstRow];
298 }
299 for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
300 var row = document.createElement('span');
301 row.className = 'ygrid-row';
302 row.style.top = (rowIndex * this.rowHeight) + 'px';
303 this.renderRow(dataModel, row, rowIndex, colCount, renderers, dindexes);
304 if(beforeRow){
305 bt.insertBefore(row, beforeRow);
306 }else{
307 bt.appendChild(row);
308 }
309 }
310 this.updateRowIndexes(firstRow);
311 this.adjustForScroll(true);
312 },
313
314 renderRow : function(dataModel, row, rowIndex, colCount, renderers, dindexes){
315 for(var colIndex = 0; colIndex < colCount; colIndex++){
316 var td = document.createElement('span');
317 td.className = 'ygrid-col ygrid-col-' + colIndex + (colIndex == colCount-1 ? ' ygrid-col-last' : '');
318 td.columnIndex = colIndex;
319 td.tabIndex = 0;
320 var span = document.createElement('span');
321 span.className = 'ygrid-cell-text';
322 td.appendChild(span);
323 var val = renderers[colIndex](dataModel.getValueAt(rowIndex, dindexes[colIndex]), rowIndex, colIndex, td, dataModel);
324 if(typeof val == 'undefined' || val === '') val = '&#160;';
325 span.innerHTML = val;
326 row.appendChild(td);
327 }
328 },
329
330 deleteRows : function(dataModel, firstRow, lastRow){
331 this.updateBodyHeight();
332 // first make sure they are deselected
333 this.grid.selModel.deselectRange(firstRow, lastRow);
334 var bt = this.getBodyTable();
335 var rows = []; // get references because the rowIndex will change
336 for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
337 rows.push(bt.childNodes[rowIndex]);
338 }
339 for(var i = 0; i < rows.length; i++){
340 bt.removeChild(rows[i]);
341 rows[i] = null;
342 }
343 rows = null;
344 this.updateRowIndexes(firstRow);
345 this.adjustForScroll();
346 },
347
348 updateRows : function(dataModel, firstRow, lastRow){
349 var bt = this.getBodyTable();
350 var dindexes = this.getDataIndexes();
351 var renderers = this.getColumnRenderers();
352 var colCount = this.grid.colModel.getColumnCount();
353 for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
354 var row = bt.rows[rowIndex];
355 var cells = row.childNodes;
356 for(var colIndex = 0; colIndex < colCount; colIndex++){
357 var td = cells[colIndex];
358 var val = renderers[colIndex](dataModel.getValueAt(rowIndex, dindexes[colIndex]), rowIndex, colIndex, td, dataModel);
359 if(typeof val == 'undefined' || val === '') val = '&#160;';
360 td.firstChild.innerHTML = val;
361 }
362 }
363 },
364
365 handleSort : function(dataModel, sortColumnIndex, sortDir, noRefresh){
366 varselectedRows;
367 this.grid.selModel.syncSelectionsToIds();
368 if(!noRefresh){
369 this.updateRows(dataModel, 0, dataModel.getRowCount()-1);
370 }
371 this.updateHeaderSortState();
372 selectedRows = this.grid.selModel.getSelectedRows();
373 if (selectedRows.length > 0) {
374 this.focusRow(selectedRows[0]);
375 }
376 },
377
378 syncScroll : function(){
379 this.hwrap.dom.scrollLeft = this.wrap.scrollLeft;
380 },
381
382 handleScroll : function(){
383 this.syncScroll();
384 this.fireScroll(this.wrap.scrollLeft, this.wrap.scrollTop);
385 this.grid.fireEvent('bodyscroll', this.wrap.scrollLeft, this.wrap.scrollTop);
386 },
387
388 getRowHeight : function(){
389 if(!this.rowHeight){
390 var rule = YAHOO.ext.util.CSS.getRule(["#" + this.grid.id + " .ygrid-row", ".ygrid-row"]);
391 if(rule && rule.style.height){
392 this.rowHeight = parseInt(rule.style.height, 10);
393 }else{
394 this.rowHeight = 21;
395 }
396 }
397 return this.rowHeight;
398 },
399
400 renderRows : function(dataModel){
401 this.grid.stopEditing();
402 if(this.grid.selModel){
403 this.grid.selModel.clearSelections();
404 }
405 var bt = this.getBodyTable();
406 bt.innerHTML = '';
407 this.rowHeight = this.getRowHeight();
408 this.insertRows(dataModel, 0, dataModel.getRowCount()-1);
409 },
410
411 updateCell : function(dataModel, rowIndex, dataIndex){
412 var colIndex = this.getColumnIndexByDataIndex(dataIndex);
413 if(typeof colIndex == 'undefined'){ // not present in grid
414 return;
415 }
416 var bt = this.getBodyTable();
417 var row = bt.childNodes[rowIndex];
418 var cell = row.childNodes[colIndex];
419 var renderer = this.grid.colModel.getRenderer(colIndex);
420 var val = renderer(dataModel.getValueAt(rowIndex, dataIndex), rowIndex, colIndex, cell, dataModel);
421 if(typeof val == 'undefined' || val === '') val = '&#160;';
422 cell.firstChild.innerHTML = val;
423 },
424
425 calcColumnWidth : function(colIndex, maxRowsToMeasure){
426 var maxWidth = 0;
427 var bt = this.getBodyTable();
428 var rows = bt.childNodes;
429 var stopIndex = Math.min(maxRowsToMeasure || rows.length, rows.length);
430 if(this.grid.autoSizeHeaders){
431 var h = this.headers[colIndex];
432 var curWidth = h.style.width;
433 h.style.width = this.grid.minColumnWidth+'px';
434 maxWidth = Math.max(maxWidth, h.scrollWidth);
435 h.style.width = curWidth;
436 }
437 for(var i = 0; i < stopIndex; i++){
438 var cell = rows[i].childNodes[colIndex].firstChild;
439 maxWidth = Math.max(maxWidth, cell.scrollWidth);
440 }
441 return maxWidth + /*margin for error in IE*/ 5;
442 },
443
444 /**
445 * Autofit a column to it's content.
446 * @param {Number} colIndex
447 * @param {Boolean} forceMinSize true to force the column to go smaller if possible
448 */
449 autoSizeColumn : function(colIndex, forceMinSize){
450 if(forceMinSize){
451 this.setCSSWidth(colIndex, this.grid.minColumnWidth);
452 }
453 var newWidth = this.calcColumnWidth(colIndex);
454 this.grid.colModel.setColumnWidth(colIndex,
455 Math.max(this.grid.minColumnWidth, newWidth));
456 this.grid.fireEvent('columnresize', colIndex, newWidth);
457 },
458
459 /**
460 * Autofits all columns to their content and then expands to fit any extra space in the grid
461 */
462 autoSizeColumns : function(){
463 var colModel = this.grid.colModel;
464 var colCount = colModel.getColumnCount();
465 var wrap = this.wrap;
466 for(var i = 0; i < colCount; i++){
467 this.setCSSWidth(i, this.grid.minColumnWidth);
468 colModel.setColumnWidth(i, this.calcColumnWidth(i, this.grid.maxRowsToMeasure), true);
469 }
470 if(colModel.getTotalWidth() < wrap.clientWidth){
471 var diff = Math.floor((wrap.clientWidth - colModel.getTotalWidth()) / colCount);
472 for(var i = 0; i < colCount; i++){
473 colModel.setColumnWidth(i, colModel.getColumnWidth(i) + diff, true);
474 }
475 }
476 this.updateColumns();
477 },
478
479 /**
480 * Autofits all columns to the grid's width proportionate with their current size
481 */
482 fitColumns : function(){
483 var cm = this.grid.colModel;
484 var colCount = cm.getColumnCount();
485 var cols = [];
486 var width = 0;
487 var i, w;
488 for (i = 0; i < colCount; i++){
489 if(!cm.isHidden(i) && !cm.isFixed(i)){
490 w = cm.getColumnWidth(i);
491 cols.push(i);
492 cols.push(w);
493 width += w;
494 }
495 }
496 var frac = (this.wrap.clientWidth - cm.getTotalWidth())/width;
497 while (cols.length){
498 w = cols.pop();
499 i = cols.pop();
500 cm.setColumnWidth(i, Math.floor(w + w*frac), true);
501 }
502 this.updateColumns();
503 },
504
505 onWindowResize : function(){
506 if(this.grid.monitorWindowResize){
507 this.adjustForScroll();
508 this.updateWrapHeight();
509 this.adjustForScroll();
510 }
511 },
512
513 updateWrapHeight : function(){
514 this.grid.container.beginMeasure();
515 this.autoHeight();
516 var box = this.grid.container.getSize(true);
517 this.wrapEl.setHeight(box.height-this.footerHeight-parseInt(this.wrap.offsetTop, 10));
518 this.pwrap.setSize(box.width, box.height);
519 this.grid.container.endMeasure();
520 },
521
522 forceScrollUpdate : function(){
523 var wrap = this.wrapEl;
524 wrap.setWidth(wrap.getWidth(true));
525 setTimeout(function(){ // set timeout so FireFox works
526 wrap.setWidth('');
527 }, 1);
528 },
529
530 updateHeaderSortState : function(){
531 var state = this.grid.dataModel.getSortState();
532 if(!state || typeof state.column == 'undefined') return;
533 var sortColumn = this.getColumnIndexByDataIndex(state.column);
534 var sortDir = state.direction;
535 for(var i = 0, len = this.headers.length; i < len; i++){
536 var h = this.headers[i];
537 if(i != sortColumn){
538 h.sortDesc.style.display = 'none';
539 h.sortAsc.style.display = 'none';
540 YAHOO.util.Dom.removeClass(h, 'ygrid-sort-col');
541 }else{
542 h.sortDesc.style.display = sortDir == 'DESC' ? 'block' : 'none';
543 h.sortAsc.style.display = sortDir == 'ASC' ? 'block' : 'none';
544 YAHOO.util.Dom.addClass(h, 'ygrid-sort-col');
545 }
546 }
547 },
548
549 unplugDataModel : function(dm){
550 dm.removeListener('cellupdated', this.updateCell, this);
551 dm.removeListener('datachanged', this.renderRows, this);
552 dm.removeListener('rowsdeleted', this.deleteRows, this);
553 dm.removeListener('rowsinserted', this.insertRows, this);
554 dm.removeListener('rowsupdated', this.updateRows, this);
555 dm.removeListener('rowssorted', this.handleSort, this);
556 },
557
558 plugDataModel : function(dm){
559 dm.on('cellupdated', this.updateCell, this, true);
560 dm.on('datachanged', this.renderRows, this, true);
561 dm.on('rowsdeleted', this.deleteRows, this, true);
562 dm.on('rowsinserted', this.insertRows, this, true);
563 dm.on('rowsupdated', this.updateRows, this, true);
564 dm.on('rowssorted', this.handleSort, this, true);
565 },
566
567 destroy : function(){
568 this.unplugDataModel(this.grid.dataModel);
569 var sp = this.splitters;
570 if(sp){
571 for(var i in sp){
572 if(sp[i] && typeof sp[i] != 'function'){
573 sp[i].destroy(true);
574 }
575 }
576 }
577 },
578
579 render : function(){
580 var grid = this.grid;
581 var container = grid.container.dom;
582 var dataModel = grid.dataModel;
583 this.plugDataModel(dataModel);
584
585 var colModel = grid.colModel;
586 colModel.onWidthChange.subscribe(this.updateColumns, this, true);
587 colModel.onHeaderChange.subscribe(this.updateHeaders, this, true);
588 colModel.onHiddenChange.subscribe(this.handleHiddenChange, this, true);
589
590 if(grid.monitorWindowResize === true){
591 YAHOO.ext.EventManager.onWindowResize(this.onWindowResize, this, true);
592 }
593 var autoSizeDelegate = this.autoSizeColumn.createDelegate(this);
594
595 var colCount = colModel.getColumnCount();
596
597 var dh = YAHOO.ext.DomHelper;
598 this.pwrap = dh.append(container,
599 {tag: 'div', cls: 'ygrid-positioner',
600 style: 'position:relative;width:100%;height:100%;left:0;top:0;overflow:hidden;'}, true);
601 var pos = this.pwrap.dom;
602
603 //create wrapper elements that handle offsets and scrolling
604 var wrap = dh.append(pos, {tag: 'div', cls: 'ygrid-wrap'});
605 this.wrap = wrap;
606 this.wrapEl = getEl(wrap, true);
607 YAHOO.ext.EventManager.on(wrap, 'scroll', this.handleScroll, this, true);
608
609 var hwrap = dh.append(pos, {tag: 'div', cls: 'ygrid-wrap-headers'});
610 this.hwrap = getEl(hwrap, true);
611
612 var bwrap = dh.append(wrap, {tag: 'div', cls: 'ygrid-wrap-body', id: container.id + '-body'});
613 this.bwrap = getEl(bwrap, true);
614 this.bwrap.setWidth(colModel.getTotalWidth());
615 bwrap.rows = bwrap.childNodes;
616
617 this.footerHeight = 0;
618 var foot = this.appendFooter(this.pwrap.dom);
619 if(foot){
620 this.footer = getEl(foot, true);
621 this.footerHeight = this.footer.getHeight();
622 }
623 this.updateWrapHeight();
624
625 var hrow = dh.append(hwrap, {tag: 'span', cls: 'ygrid-hrow'});
626 this.hrow = hrow;
627
628 if(!YAHOO.ext.util.Browser.isGecko){
629 // IE doesn't like iframes, we will leave this alone
630 var iframe = document.createElement('iframe');
631 iframe.className = 'ygrid-hrow-frame';
632 iframe.frameBorder = 0;
633 iframe.src = YAHOO.ext.SSL_SECURE_URL;
634 hwrap.appendChild(iframe);
635 }
636 this.headerCtrl = new YAHOO.ext.grid.HeaderController(this.grid);
637 this.headers = [];
638 this.cols = [];
639 this.splitters = [];
640
641 var htemplate = dh.createTemplate({
642 tag: 'span', cls: 'ygrid-hd ygrid-header-{0}', children: [{
643 tag: 'span',
644 cls: 'ygrid-hd-body',
645 html: '<table border="0" cellpadding="0" cellspacing="0" title="{2}">' +
646 '<tbody><tr><td><span>{1}</span></td>' +
647 '<td><span class="sort-desc"></span><span class="sort-asc"></span></td>' +
648 '</tr></tbody></table>'
649 }]
650 });
651 htemplate.compile();
652
653 var ruleBuf = [];
654
655 for(var i = 0; i < colCount; i++){
656 var hd = htemplate.append(hrow, [i, colModel.getColumnHeader(i), colModel.getColumnTooltip(i) || '']);
657 var spans = hd.getElementsByTagName('span');
658 hd.textNode = spans[1];
659 hd.sortDesc = spans[2];
660 hd.sortAsc = spans[3];
661 hd.columnIndex = i;
662 this.headers.push(hd);
663 if(colModel.isSortable(i)){
664 this.headerCtrl.register(hd);
665 }
666 var split = dh.append(hrow, {tag: 'span', cls: 'ygrid-hd-split'});
667 hd.split = split;
668
669 if(colModel.isResizable(i) && !colModel.isFixed(i)){
670 YAHOO.util.Event.on(split, 'dblclick', autoSizeDelegate.createCallback(i+0, true));
671 var sb = new YAHOO.ext.SplitBar(split, hd, null, YAHOO.ext.SplitBar.LEFT);
672 sb.columnIndex = i;
673 sb.minSize = grid.minColumnWidth;
674 sb.onMoved.subscribe(this.onColumnSplitterMoved, this, true);
675 YAHOO.util.Dom.addClass(sb.proxy, 'ygrid-column-sizer');
676 YAHOO.util.Dom.setStyle(sb.proxy, 'background-color', '');
677 sb.dd._resizeProxy = function(){
678 var el = this.getDragEl();
679 YAHOO.util.Dom.setStyle(el, 'height', (hwrap.clientHeight+wrap.clientHeight-2) +'px');
680 };
681 this.splitters[i] = sb;
682 }else{
683 split.style.cursor = 'default';
684 }
685 ruleBuf.push('#', container.id, ' .ygrid-col-', i, ' {\n}\n');
686 }
687
688 YAHOO.ext.util.CSS.createStyleSheet(ruleBuf.join(''));
689
690 if(grid.autoSizeColumns){
691 this.renderRows(dataModel);
692 this.autoSizeColumns();
693 }else{
694 this.updateColumns();
695 this.renderRows(dataModel);
696 }
697
698 for(var i = 0; i < colCount; i++){
699 if(colModel.isHidden(i)){
700 this.hideColumn(i);
701 }
702 }
703 this.updateHeaderSortState();
704 return this.bwrap;
705 },
706
707 onColumnSplitterMoved : function(splitter, newSize){
708 this.grid.colModel.setColumnWidth(splitter.columnIndex, newSize);
709 this.grid.fireEvent('columnresize', splitter.columnIndex, newSize);
710 },
711
712 appendFooter : function(parentEl){
713 return null;
714 },
715
716 autoHeight : function(){
717 if(this.grid.autoHeight){
718 var h = this.getBodyHeight();
719 var c = this.grid.container;
720 var total = h + (parseInt(this.wrap.offsetTop, 10)||0) +
721 this.footerHeight + c.getBorderWidth('tb') + c.getPadding('tb')
722 + (this.wrap.offsetHeight - this.wrap.clientHeight);
723 c.setHeight(total);
724
725 }
726 },
727
728 getBodyHeight : function(){
729 return this.grid.dataModel.getRowCount() * this.getRowHeight();;
730 },
731
732 updateBodyHeight : function(){
733 this.getBodyTable().style.height = this.getBodyHeight() + 'px';
734 if(this.grid.autoHeight){
735 this.autoHeight();
736 this.updateWrapHeight();
737 }
738 }
739};
740YAHOO.ext.grid.GridView.SCROLLBARS_UNDER = 0;
741YAHOO.ext.grid.GridView.SCROLLBARS_OVERLAP = 1;
742YAHOO.ext.grid.GridView.prototype.scrollbarMode = YAHOO.ext.grid.GridView.SCROLLBARS_UNDER;
743
744YAHOO.ext.grid.GridView.prototype.fitColumnsToContainer = YAHOO.ext.grid.GridView.prototype.fitColumns;
745
746YAHOO.ext.grid.HeaderController = function(grid){
747 this.grid = grid;
748 this.headers = [];
749};
750
751YAHOO.ext.grid.HeaderController.prototype = {
752 register : function(header){
753 this.headers.push(header);
754 YAHOO.ext.EventManager.on(header, 'selectstart', this.cancelTextSelection, this, true);
755 YAHOO.ext.EventManager.on(header, 'mousedown', this.cancelTextSelection, this, true);
756 YAHOO.ext.EventManager.on(header, 'mouseover', this.headerOver, this, true);
757 YAHOO.ext.EventManager.on(header, 'mouseout', this.headerOut, this, true);
758 YAHOO.ext.EventManager.on(header, 'click', this.headerClick, this, true);
759 },
760
761 headerClick : function(e){
762 var grid = this.grid, cm = grid.colModel, dm = grid.dataModel;
763 grid.stopEditing();
764 var header = grid.getHeaderFromChild(e.getTarget());
765 var state = dm.getSortState();
766 var direction = header.sortDir || 'ASC';
767 if(typeof state.column != 'undefined' &&
768 grid.getView().getColumnIndexByDataIndex(state.column) == header.columnIndex){
769 direction = (state.direction == 'ASC' ? 'DESC' : 'ASC');
770 }
771 header.sortDir = direction;
772 dm.sort(cm, cm.getDataIndex(header.columnIndex), direction);
773 },
774
775 headerOver : function(e){
776 var header = this.grid.getHeaderFromChild(e.getTarget());
777 YAHOO.util.Dom.addClass(header, 'ygrid-hd-over');
778 //YAHOO.ext.util.CSS.applyFirst(header, this.grid.id, '.ygrid-hd-over');
779 },
780
781 headerOut : function(e){
782 var header = this.grid.getHeaderFromChild(e.getTarget());
783 YAHOO.util.Dom.removeClass(header, 'ygrid-hd-over');
784 //YAHOO.ext.util.CSS.revertFirst(header, this.grid.id, '.ygrid-hd-over');
785 },
786
787 cancelTextSelection : function(e){
788 e.preventDefault();
789 }
790}; \ No newline at end of file