OSDN Git Service

git-svn-id: https://svn.sourceforge.jp/svnroot/nucleus-jp/plugin@1020 1ca29b6e-896d...
[nucleus-jp/nucleus-plugins.git] / NP_TrackBack / trunk / trackback / js / rico / ricoGridCommon.js
1 /**
2   *  (c) 2005-2007 Richard Cowin (http://openrico.org)
3   *  (c) 2005-2007 Matt Brown (http://dowdybrown.com)
4   *
5   *  Rico is licensed under the Apache License, Version 2.0 (the "License"); you may not use this
6   *  file except in compliance with the License. You may obtain a copy of the License at
7   *   http://www.apache.org/licenses/LICENSE-2.0
8   **/
9
10
11 if(typeof Rico=='undefined') throw("GridCommon requires the Rico JavaScript framework");
12 if(typeof RicoUtil=='undefined') throw("GridCommon requires the RicoUtil Library");
13
14
15 /**
16  * Define methods that are common to both SimpleGrid and LiveGrid
17  */
18 Rico.GridCommon = function() {};
19
20 Rico.GridCommon.prototype = {
21
22   baseInit: function() {
23     this.options = {
24       resizeBackground : 'resize.gif',
25       saveColumnInfo   : {width:true, filter:false, sort:false},  // save info in cookies?
26       allowColResize   : true,      // allow user to resize columns
27       windowResize     : true,      // Resize grid on window.resize event? Set to false when embedded in an accordian.
28       click            : null,
29       dblclick         : null,
30       contextmenu      : null,
31       useUnformattedColWidth : true,
32       menuEvent        : 'dblclick',  // event that triggers menus - click, dblclick, contextmenu, or none (no menus)
33       defaultWidth     : 100,   // in the absence of any other width info, columns will be this many pixels wide
34       scrollBarWidth   : 19,    // this is the value used in positioning calculations, it does not actually change the width of the scrollbar
35       minScrollWidth   : 100,   // min scroll area width when width of frozen columns exceeds window width
36       columnSpecs      : []
37     }
38     this.colWidths = new Array();
39     this.hdrCells=new Array();
40     this.headerColCnt=0;
41     this.headerRowIdx=0;
42     this.tabs=new Array(2);
43     this.thead=new Array(2);
44     this.tbody=new Array(2);
45   },
46
47   attachMenuEvents: function() {
48     if (!this.options.menuEvent || this.options.menuEvent=='none') return;
49     this.hideScroll=navigator.userAgent.match(/Macintosh\b.*\b(Firefox|Camino)\b/i) || Prototype.Browser.Opera;
50     this.options[this.options.menuEvent]=this.handleMenuClick.bindAsEventListener(this);
51     if (this.highlightDiv) {
52       switch (this.options.highlightElem) {
53         case 'cursorRow':
54           this.attachMenu(this.highlightDiv);
55           break;
56         case 'cursorCell':
57           for (var i=0; i<2; i++)
58             this.attachMenu(this.highlightDiv[i]);
59           break;
60       }
61     }
62     for (var i=0; i<2; i++)
63       this.attachMenu(this.tbody[i]);
64   },
65
66   attachMenu: function(elem) {
67     if (this.options.click)
68       Event.observe(elem, 'click', this.options.click, false);
69     if (this.options.dblclick) {
70       if (Prototype.Browser.WebKit || Prototype.Browser.Opera)
71         Event.observe(elem, 'click', this.handleDblClick.bindAsEventListener(this), false);
72       else
73         Event.observe(elem, 'dblclick', this.options.dblclick, false);
74     }
75     if (this.options.contextmenu) {
76       if (Prototype.Browser.Opera)
77         Event.observe(elem, 'click', this.handleContextMenu.bindAsEventListener(this), false);
78       else
79         Event.observe(elem, 'contextmenu', this.options.contextmenu, false);
80     }
81   },
82
83   // implement double-click for browsers that don't support a double-click event (e.g. Safari)
84   handleDblClick: function(e) {
85     var elem=Event.element(e);
86     if (this.dblClickElem == elem) {
87       this.options.dblclick(e);
88     } else {
89       this.dblClickElem = elem;
90       this.safariTimer=setTimeout(this.clearDblClick.bind(this),300);
91     }
92   },
93
94   clearDblClick: function() {
95     this.dblClickElem=null;
96   },
97
98   // implement right-click for browsers that don't support contextmenu event (e.g. Opera)
99   // use control-click instead
100   handleContextMenu: function(e) {
101     if( typeof( e.which ) == 'number' )
102       var b = e.which; //Netscape compatible
103     else if( typeof( e.button ) == 'number' )
104       var b = e.button; //DOM
105     else
106       return;
107     if (b==1 && e.ctrlKey)
108       this.options.contextmenu(e);
109   },
110
111   cancelMenu: function() {
112     if (this.menu && this.menu.isVisible()) this.menu.cancelmenu();
113   },
114
115   // gather info from original headings
116   getColumnInfo: function(hdrSrc) {
117     Rico.writeDebugMsg("getColumnInfo start");
118     //alert(hdrSrc.tagName+' '+hdrSrc.id+' len='+hdrSrc.length);
119     if (hdrSrc.length == 0) return;
120     this.headerRowCnt=hdrSrc.length;
121     var colcnt;
122     for (r=0; r<this.headerRowCnt; r++) {
123       var headerRow = hdrSrc[r];
124       var headerCells=headerRow.cells;
125       if (r >= this.hdrCells.length) this.hdrCells[r]=new Array();
126       for (c=0; c<headerCells.length; c++) {
127         var obj={};
128         obj.cell=headerCells[c];
129         obj.colSpan=headerCells[c].colSpan || 1;  // Safari & Konqueror return default colspan of 0
130         if (this.options.useUnformattedColWidth) obj.initWidth=headerCells[c].offsetWidth
131         this.hdrCells[r].push(obj);
132       }
133       if (headerRow.id.slice(-5)=='_main') {
134         colcnt=this.hdrCells[r].length;
135         this.headerRowIdx=r;
136       }
137     }
138     Rico.writeDebugMsg("getColumnInfo end");
139     if (!colcnt) {
140       this.headerRowIdx=this.headerRowCnt-1;
141       colcnt=this.hdrCells[this.headerRowIdx].length
142     }
143     return colcnt;
144   },
145
146   // create column array
147   createColumnArray: function() {
148     this.direction=Element.getStyle(this.outerDiv,'direction').toLowerCase();  // ltr or rtl
149     this.align=this.direction=='rtl' ? ['right','left'] : ['left','right'];
150     //alert(this.direction+' : '+this.align[0]);
151     this.columns = new Array();
152     for (var c=0 ; c < this.headerColCnt; c++) {
153       Rico.writeDebugMsg("createColumnArray: c="+c);
154       var tabidx=c<this.options.frozenColumns ? 0 : 1;
155       this.columns.push(new Rico.TableColumn(this, c, this.hdrCells[this.headerRowIdx][c], tabidx));
156     }
157     this.getCookie();
158   },
159
160   // create div structure
161   createDivs: function() {
162     Rico.writeDebugMsg("createDivs start");
163     this.outerDiv   = this.createDiv("outer");
164     this.scrollDiv  = this.createDiv("scroll",this.outerDiv);
165     this.frozenTabs = this.createDiv("frozenTabs",this.outerDiv);
166     this.innerDiv   = this.createDiv("inner",this.outerDiv);
167     this.resizeDiv  = this.createDiv("resize",this.outerDiv);
168     this.resizeDiv.style.display="none";
169     this.exportDiv  = this.createDiv("export",this.outerDiv);
170     this.exportDiv.style.display="none";
171     //this.frozenTabs.style[this.align[0]]='0px';
172     //this.innerDiv.style[this.align[0]]='0px';
173     Rico.writeDebugMsg("createDivs end");
174   },
175
176   createDiv: function(elemName,elemParent) {
177     var id=this.tableId+"_"+elemName+"Div";
178     newdiv=$(id);
179     if (!newdiv) {
180       var newdiv = document.createElement("div");
181       newdiv.id = id;
182       if (elemParent) elemParent.appendChild(newdiv);
183     }
184     newdiv.className = "ricoLG_"+elemName+"Div";
185     return newdiv;
186   },
187
188   baseSizeDivs: function() {
189     this.setOtherHdrCellWidths();
190     this.tabs[0].style.display=this.options.frozenColumns ? '' : 'none';
191     this.hdrHt=Math.max(RicoUtil.nan2zero(this.thead[0].offsetHeight),this.thead[1].offsetHeight);
192     this.dataHt=Math.max(RicoUtil.nan2zero(this.tbody[0].offsetHeight),this.tbody[1].offsetHeight);
193     this.frzWi=this.borderWidth(this.tabs[0]);
194     var borderWi=this.borderWidth(this.columns[0].dataCell);
195     Rico.writeDebugMsg('baseSizeDivs '+this.tableId+': hdrHt='+this.hdrHt+' dataHt='+this.dataHt);
196     //alert(this.tableId+' frzWi='+this.frzWi+' borderWi='+borderWi);
197     for (var i=0; i<this.options.frozenColumns; i++)
198       if (this.columns[i].visible) this.frzWi+=parseInt(this.columns[i].colWidth)+borderWi;
199     this.scrTabWi=this.borderWidth(this.tabs[1]);
200     for (var i=this.options.frozenColumns; i<this.columns.length; i++)
201       if (this.columns[i].visible) this.scrTabWi+=parseInt(this.columns[i].colWidth)+borderWi;
202     this.scrWi=this.scrTabWi+this.options.scrollBarWidth;
203     var wiLimit=RicoUtil.windowWidth()-this.options.scrollBarWidth-8;
204     if (this.outerDiv.parentNode.clientWidth > 0)
205       wiLimit=Math.min(this.outerDiv.parentNode.clientWidth, wiLimit);
206     var overage=this.frzWi+this.scrWi-wiLimit;
207     Rico.writeDebugMsg('baseSizeDivs '+this.tableId+': scrWi='+this.scrWi+' wiLimit='+wiLimit+' overage='+overage+' clientWidth='+this.outerDiv.parentNode.clientWidth);
208     if (overage > 0 && this.options.frozenColumns < this.columns.length)
209       this.scrWi=Math.max(this.scrWi-overage, this.options.minScrollWidth);
210     this.scrollDiv.style.width=this.scrWi+'px';
211     this.scrollDiv.style.top=this.hdrHt+'px';
212     this.frozenTabs.style.width=this.scrollDiv.style[this.align[0]]=this.innerDiv.style[this.align[0]]=this.frzWi+'px';
213     this.outerDiv.style.width=(this.frzWi+this.scrWi)+'px';
214   },
215
216   borderWidth: function(elem) {
217     return RicoUtil.nan2zero(Element.getStyle(elem,'border-left-width')) + RicoUtil.nan2zero(Element.getStyle(elem,'border-right-width'));
218   },
219
220   setOtherHdrCellWidths: function() {
221     for (var r=0; r<this.hdrCells.length; r++) {
222       if (r==this.headerRowIdx) continue;
223       Rico.writeDebugMsg('setOtherHdrCellWidths: r='+r);
224       var c=i=0;
225       while (i<this.headerColCnt && c<this.hdrCells[r].length) {
226         var hdrcell=this.hdrCells[r][c];
227         var cell=hdrcell.cell;
228         var origSpan=newSpan=hdrcell.colSpan;
229         for (var w=j=0; j<origSpan; j++, i++) {
230           if (this.columns[i].hdrCell.style.display=='none')
231             newSpan--;
232           else if (this.columns[i].hdrColDiv.style.display!='none')
233             w+=parseInt(this.columns[i].colWidth);
234         }
235         if (!hdrcell.hdrColDiv || !hdrcell.hdrCellDiv) {
236           var divs=cell.getElementsByTagName('div');
237           hdrcell.hdrColDiv=(divs.length<1) ? RicoUtil.wrapChildren(cell,'ricoLG_col') : divs[0];
238           hdrcell.hdrCellDiv=(divs.length<2) ? RicoUtil.wrapChildren(hdrcell.hdrColDiv,'ricoLG_cell') : divs[1];
239         }
240         if (newSpan==0) {
241           cell.style.display='none';
242         } else if (w==0) {
243           hdrcell.hdrColDiv.style.display='none';
244           cell.colSpan=newSpan;
245         } else {
246           cell.style.display='';
247           hdrcell.hdrColDiv.style.display='';
248           cell.colSpan=newSpan;
249           hdrcell.hdrColDiv.style.width=w+'px';
250         }
251         c++;
252       }
253     }
254   },
255   
256   cell: function(r,c) {
257     return (0<=c && c<this.columns.length && r>=0) ? this.columns[c].cell(r) : null;
258   },
259
260   availHt: function() {
261     var divPos=Position.page(this.outerDiv);
262     return RicoUtil.windowHeight()-divPos[1]-2*this.options.scrollBarWidth-15;  // allow for scrollbar and some margin
263   },
264
265   handleScroll: function(e) {
266     var newTop=(this.hdrHt-this.scrollDiv.scrollTop)+'px';
267     this.tabs[0].style.top=newTop;
268     this.setHorizontalScroll();
269   },
270
271   setHorizontalScroll: function() {
272     var newLeft=(-this.scrollDiv.scrollLeft)+'px';
273     this.hdrTabs[1].style.left=newLeft;
274   },
275
276   pluginScroll: function() {
277      if (this.scrollPluggedIn) return;
278      Event.observe(this.scrollDiv,"scroll",this.scrollEventFunc, false);
279      this.scrollPluggedIn=true;
280   },
281
282   unplugScroll: function() {
283      Event.stopObserving(this.scrollDiv,"scroll", this.scrollEventFunc , false);
284      this.scrollPluggedIn=false;
285   },
286
287   printVisible: function(exportType) {
288     this.exportStart();
289     var limit=this.pageSize;
290     if (this.buffer && this.buffer.totalRows < limit) limit=this.buffer.totalRows;
291     for(var r=0; r < limit; r++) {
292       this.exportText+="<tr>";
293       for (var c=0; c<this.columns.length; c++) {
294         if (this.columns[c].visible)
295           this.exportText+="<td style='"+this.exportStyle(this.columns[c].cell(r))+"'>"+this.columns[c].getFormattedValue(r)+"</td>";
296       }
297       this.exportText+="</tr>";
298     }
299     this.exportFinish(exportType);
300   },
301
302   exportStart: function() {
303     this.exportText="<table border='1' cellspacing='0'><thead style='display: table-header-group;'>";
304
305     for (var r=0; r<this.hdrCells.length; r++) {
306       if (this.hdrCells[r].length==0 || Element.getStyle(this.hdrCells[r][0].cell.parentNode,'display')=='none') continue;
307       this.exportText+="<tr>";
308       for (var c=0,i=0; c<this.hdrCells[r].length; c++) {
309         var hdrcell=this.hdrCells[r][c];
310         var newSpan=hdrcell.colSpan;
311         for (var j=0; j<hdrcell.colSpan; j++, i++)
312           if (!this.columns[i].visible) newSpan--;
313         if (newSpan > 0) {
314           var divs=Element.getElementsByClassName(hdrcell.cell,'ricoLG_cell');
315           var cell=divs && divs.length>0 ? divs[0] : hdrcell.cell;
316           this.exportText+="<td style='"+this.exportStyle(cell)+"'";
317           if (hdrcell.colSpan > 1) this.exportText+=" colspan='"+newSpan+"'";
318           this.exportText+=">"+RicoUtil.getInnerText(cell)+"</td>";
319         }
320       }
321       this.exportText+="</tr>";
322     }
323
324     for (var c=0; c<this.columns.length; c++)
325     this.exportText+="</thead><tbody>";
326   },
327
328   exportFinish: function(exportType) {
329     if (this.hideMsg) this.hideMsg();
330     this.exportText+="</tbody></table>";
331     this.exportDiv.innerHTML=this.exportText;
332     this.exportText=undefined;
333     if (this.cancelMenu) this.cancelMenu();
334     window.open(Rico.htmDir+'export-'+(exportType || 'plain')+'.html?'+this.exportDiv.id,'',this.options.exportWindow);
335   },
336   
337   exportStyle: function(elem) {
338     var styleList=['background-color','color','text-align','font-weight']
339     for (var i=0,s=''; i < styleList.length; i++) {
340       var curstyle=Element.getStyle(elem,styleList[i]);
341       if (curstyle) s+=styleList[i]+':'+curstyle+';';
342     }
343     return s;
344   },
345
346   // Gets the value of the specified cookie
347   getCookie: function() {
348     var c=RicoUtil.getCookie(this.tableId);
349     if (!c) return;
350         var cookieVals=c.split(',');
351         for (var i=0; i<cookieVals.length; i++) {
352           var v=cookieVals[i].split(':');
353           if (v.length!=2) continue;
354           var colnum=parseInt(v[0].slice(1));
355           if (colnum < 0 || colnum >= this.columns.length) continue;
356           var col=this.columns[colnum];
357           switch (v[0].charAt(0)) {
358             case 'w':
359               col.setColWidth(v[1]);
360           col.customWidth=true;
361               break;
362             case 'h':
363               if (v[1].toLowerCase()=='true')
364                 col.showColumn(true);
365               else
366                 col.hideColumn(true);
367               break;
368             case 's':
369               col.setSorted(v[1]);
370               break;
371             case 'f':
372               var filterTemp=v[1].split('~');
373               col.filterOp=filterTemp.shift();
374           col.filterValues = [];
375           col.filterType = Rico.TableColumn.USERFILTER;
376           for (var j=0; j<filterTemp.length; j++)
377             col.filterValues.push(unescape(filterTemp[j]));
378               break;
379           }
380         }
381   },
382   
383   // Write information to cookie
384   setCookie: function() {
385         var cookieVals=[];
386         for (var i=0; i<this.columns.length; i++) {
387           var col=this.columns[i];
388           if (this.options.saveColumnInfo.width) {
389           if (col.customWidth) cookieVals.push('w'+i+':'+col.colWidth);
390           if (col.customVisible) cookieVals.push('h'+i+':'+col.visible);
391           }
392       if (this.options.saveColumnInfo.sort) {
393         if (col.currentSort != Rico.TableColumn.UNSORTED)
394           cookieVals.push('s'+i+':'+col.currentSort);
395       }
396       if (this.options.saveColumnInfo.filter && col.filterType == Rico.TableColumn.USERFILTER) {
397         var filterTemp=[col.filterOp];
398         for (var j=0; j<col.filterValues.length; j++)
399           filterTemp.push(escape(col.filterValues[j]));
400         cookieVals.push('f'+i+':'+filterTemp.join('~'));
401       }
402         }
403         if (cookieVals.length > 0)
404           RicoUtil.setCookie(this.tableId, cookieVals.join(','), this.options.cookieDays, this.options.cookiePath, this.options.cookieDomain);
405   }
406
407 }
408
409 Rico.TableColumn = Class.create();
410
411 Rico.TableColumn.UNFILTERED   = 0;
412 Rico.TableColumn.SYSTEMFILTER = 1;  /* system-generated filter, not shown to user */
413 Rico.TableColumn.USERFILTER   = 2;
414
415 Rico.TableColumn.UNSORTED   = 0;
416 Rico.TableColumn.SORT_ASC   = "ASC";
417 Rico.TableColumn.SORT_DESC  = "DESC";
418 Rico.TableColumn.MINWIDTH   = 10; // min column width when user is resizing
419
420 Rico.TableColumn.DOLLAR  = {type:'number', prefix:'$', decPlaces:2, ClassName:'alignright'};
421 Rico.TableColumn.EURO    = {type:'number', prefix:'&euro;', decPlaces:2, ClassName:'alignright'};
422 Rico.TableColumn.PERCENT = {type:'number', suffix:'%', decPlaces:2, multiplier:100, ClassName:'alignright'};
423 Rico.TableColumn.QTY     = {type:'number', decPlaces:0, ClassName:'alignright'};
424 Rico.TableColumn.DEFAULT = {type:"raw"};
425
426 Rico.TableColumn.prototype = {
427
428   baseInit: function(liveGrid,colIdx,hdrInfo,tabIdx) {
429     Rico.writeDebugMsg("TableColumn.init index="+colIdx+" tabIdx="+tabIdx);
430     this.liveGrid  = liveGrid;
431     this.index     = colIdx;
432     this.hideWidth = Rico.isKonqueror || Prototype.Browser.WebKit || liveGrid.headerRowCnt>1 ? 5 : 2;  // column width used for "hidden" columns. Anything less than 5 causes problems with Konqueror. Best to keep this greater than padding used inside cell.
433     this.options   = liveGrid.options;
434     this.tabIdx    = tabIdx;
435     this.hdrCell   = hdrInfo.cell;
436     this.body = document.getElementsByTagName("body")[0];  // work around FireFox bug (document.body doesn't exist after XSLT)
437     this.displayName  = this.getDisplayName(this.hdrCell);
438     var divs=this.hdrCell.getElementsByTagName('div');
439     this.hdrColDiv=(divs.length<1) ? RicoUtil.wrapChildren(this.hdrCell,'ricoLG_col') : divs[0];
440     this.hdrCellDiv=(divs.length<2) ? RicoUtil.wrapChildren(this.hdrColDiv,'ricoLG_cell') : divs[1];
441     var sectionIndex= tabIdx==0 ? colIdx : colIdx-liveGrid.options.frozenColumns;
442     this.dataCell = liveGrid.tbody[tabIdx].rows[0].cells[sectionIndex];
443     var divs=this.dataCell.getElementsByTagName('div');
444     this.dataColDiv=(divs.length<1) ? RicoUtil.wrapChildren(this.dataCell,'ricoLG_col') : divs[0];
445
446     this.mouseDownHandler= this.handleMouseDown.bindAsEventListener(this);
447     this.mouseMoveHandler= this.handleMouseMove.bindAsEventListener(this);
448     this.mouseUpHandler  = this.handleMouseUp.bindAsEventListener(this);
449     this.mouseOutHandler = this.handleMouseOut.bindAsEventListener(this);
450
451     this.fieldName = 'col'+this.index;
452     var spec = liveGrid.options.columnSpecs[colIdx];
453     this.format=Object.extend( {}, Rico.TableColumn.DEFAULT);
454     switch (typeof spec) {
455       case 'object':
456         if (typeof spec.format=='string') Object.extend(this.format, Rico.TableColumn[spec.format.toUpperCase()]);
457         Object.extend(this.format, spec);
458         break;
459       case 'string':
460         if (spec.slice(0,4)=='spec') spec=spec.slice(4).toUpperCase();  // for backwards compatibility
461         this.format=typeof Rico.TableColumn[spec]=='object' ? Rico.TableColumn[spec] : Rico.TableColumn.DEFAULT;
462         break;
463     }
464     this.dataColDiv.className += (this.format.ClassName) ? ' '+this.format.ClassName : ' '+liveGrid.tableId+'_col'+colIdx;
465     this.visible=true;
466     if (typeof this.format.visible=='boolean') this.visible=this.format.visible;
467     if (typeof this.format.type!='string') this.format.type='raw';
468     Rico.writeDebugMsg("TableColumn.init index="+colIdx+" fieldName="+this.fieldName+' type='+this.format.type);
469     this.sortable     = typeof this.format.canSort=='boolean' ? this.format.canSort : liveGrid.options.canSortDefault;
470     this.currentSort  = Rico.TableColumn.UNSORTED;
471     this.filterable   = typeof this.format.canFilter=='boolean' ? this.format.canFilter : liveGrid.options.canFilterDefault;
472     this.filterType   = Rico.TableColumn.UNFILTERED;
473     this.hideable     = typeof this.format.canHide=='boolean' ? this.format.canHide : liveGrid.options.canHideDefault;
474     if (typeof this.isNullable!='boolean') this.isNullable = /number|date/.test(this.format.type);
475     this.isText       = /raw|text/.test(this.format.type);
476
477     var wi=(typeof(this.format.width)=='number') ? this.format.width : hdrInfo.initWidth;
478     wi=(typeof(wi)=='number') ? Math.max(wi,Rico.TableColumn.MINWIDTH) : liveGrid.options.defaultWidth;
479     this.setColWidth(wi);
480     if (!this.visible) this.setDisplayNone();
481     if (this.options.allowColResize && !this.format.noResize) this.insertResizer();
482   },
483
484   insertResizer: function() {
485     this.hdrCell.style.width='';
486     var resizer=this.hdrCellDiv.appendChild(document.createElement('div'));
487     resizer.className='ricoLG_Resize';
488     resizer.style[this.liveGrid.align[1]]='0px';
489     if (this.options.resizeBackground) {
490       var resizePath=Rico.imgDir+this.options.resizeBackground;
491       if (Prototype.Browser.IE) resizePath=location.protocol+resizePath;
492       resizer.style.backgroundImage='url('+resizePath+')';
493     }
494     Event.observe(resizer,"mousedown", this.mouseDownHandler, false);
495   },
496
497   // get the display name of a column
498   getDisplayName: function(el) {
499     var anchors=el.getElementsByTagName("A");
500     //Check the existance of A tags
501     if (anchors.length > 0)
502       return anchors[0].innerHTML;
503     else
504       return el.innerHTML.stripTags();
505   },
506   
507   _clear: function(gridCell) {
508     gridCell.innerHTML='&nbsp;';
509   },
510
511   clearCell: function(rowIndex) {
512     var gridCell=this.cell(rowIndex);
513     this._clear(gridCell,rowIndex);
514     if (!this.liveGrid.buffer) return;
515     var acceptAttr=this.liveGrid.buffer.options.acceptAttr;
516     for (var k=0; k<acceptAttr.length; k++) {
517       switch (acceptAttr[k]) {
518         case 'style': gridCell.style.cssText=''; break;
519         case 'class': gridCell.className=''; break;
520         default:      gridCell['_'+acceptAttr[k]]=''; break;
521       }
522     }
523   },
524
525   dataTable: function() {
526     return this.liveGrid.tabs[this.tabIdx];
527   },
528   
529   numRows: function() {
530     return this.dataColDiv.childNodes.length;
531   },
532
533   clearColumn: function() {
534     var childCnt=this.numRows();
535     for (var r=0; r<childCnt; r++)
536       this.clearCell(r);
537   },
538
539   cell: function(r) {
540     return this.dataColDiv.childNodes[r];
541   },
542   
543   getFormattedValue: function(r) {
544     return RicoUtil.getInnerText(this.cell(r));
545   },
546
547   setColWidth: function(wi) {
548     if (typeof wi=='number') {
549       wi=parseInt(wi);
550       if (wi < Rico.TableColumn.MINWIDTH) return;
551       wi=wi+'px';
552     }
553     Rico.writeDebugMsg('setColWidth '+this.index+': '+wi);
554     this.colWidth=wi;
555     this.hdrColDiv.style.width=wi;
556     this.dataColDiv.style.width=wi;
557   },
558
559   pluginMouseEvents: function() {
560     if (this.mousePluggedIn==true) return;
561     Event.observe(this.body,"mousemove", this.mouseMoveHandler, false);
562     Event.observe(this.body,"mouseup",   this.mouseUpHandler  , false);
563     Event.observe(this.body,"mouseout",  this.mouseOutHandler , false);
564     this.mousePluggedIn=true;
565   },
566
567   unplugMouseEvents: function() {
568     Event.stopObserving(this.body,"mousemove", this.mouseMoveHandler, false);
569     Event.stopObserving(this.body,"mouseup",   this.mouseUpHandler  , false);
570     Event.stopObserving(this.body,"mouseout",  this.mouseOutHandler , false);
571     this.mousePluggedIn=false;
572   },
573
574   handleMouseDown: function(e) {
575     this.resizeStart=e.clientX;
576     this.origWidth=parseInt(this.colWidth);
577     var p=Position.positionedOffset(this.hdrCell);
578     if (this.liveGrid.direction=='rtl') {
579       this.edge=p[0]+this.liveGrid.options.scrollBarWidth;
580       switch (this.tabIdx) {
581         case 0: this.edge+=this.liveGrid.innerDiv.offsetWidth; break;
582         case 1: this.edge-=this.liveGrid.scrollDiv.scrollLeft; break;
583       }
584     } else {
585       this.edge=p[0]+this.hdrCell.offsetWidth;
586       if (this.tabIdx>0) this.edge+=RicoUtil.nan2zero(this.liveGrid.tabs[0].offsetWidth)-this.liveGrid.scrollDiv.scrollLeft;
587     }
588     this.liveGrid.resizeDiv.style.left=this.edge+"px";
589     this.liveGrid.resizeDiv.style.display="";
590     this.liveGrid.outerDiv.style.cursor='e-resize';
591     this.tmpHighlight=this.liveGrid.highlightEnabled;
592     this.liveGrid.highlightEnabled=false;
593     this.pluginMouseEvents();
594     Event.stop(e);
595   },
596
597   handleMouseMove: function(e) {
598     var delta=e.clientX-this.resizeStart;
599     var newWidth=(this.liveGrid.direction=='rtl') ? this.origWidth-delta : this.origWidth+delta;
600     if (newWidth < Rico.TableColumn.MINWIDTH) return;
601     this.liveGrid.resizeDiv.style.left=(this.edge+delta)+"px";
602     this.colWidth=newWidth;
603     Event.stop(e);
604   },
605
606   handleMouseUp: function(e) {
607     this.unplugMouseEvents();
608     Rico.writeDebugMsg('handleMouseUp '+this.liveGrid.tableId);
609     this.liveGrid.outerDiv.style.cursor='';
610     this.liveGrid.resizeDiv.style.display="none";
611     this.setColWidth(this.colWidth);
612     this.customWidth=true;
613     this.liveGrid.setCookie();
614     this.liveGrid.highlightEnabled=this.tmpHighlight;
615     this.liveGrid.sizeDivs();
616     Event.stop(e);
617   },
618
619   handleMouseOut: function(e) {
620     var reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement;
621     while (reltg != null && reltg.nodeName.toLowerCase() != 'body')
622       reltg=reltg.parentNode;
623     if (reltg!=null && reltg.nodeName.toLowerCase() == 'body') return true;
624     this.handleMouseUp(e);
625     return true;
626   },
627
628   setDisplayNone: function() {
629     this.hdrCell.style.display='none';
630     this.hdrColDiv.style.display='none';
631     this.dataCell.style.display='none';
632     this.dataColDiv.style.display='none';
633   },
634
635   // recalcTableWidth defaults to true
636   hideColumn: function(noresize) {
637     Rico.writeDebugMsg('hideColumn '+this.liveGrid.tableId);
638     this.setDisplayNone();
639     this.liveGrid.cancelMenu();
640     this.visible=false;
641     this.customVisible=true;
642     if (noresize) return;
643     this.liveGrid.setCookie();
644     this.liveGrid.sizeDivs();
645   },
646
647   showColumn: function(noresize) {
648     Rico.writeDebugMsg('showColumn '+this.liveGrid.tableId);
649     this.hdrCell.style.display='';
650     this.hdrColDiv.style.display='';
651     this.dataCell.style.display='';
652     this.dataColDiv.style.display='';
653     this.liveGrid.cancelMenu();
654     this.visible=true;
655     this.customVisible=true;
656     if (noresize) return;
657     this.liveGrid.setCookie();
658     this.liveGrid.sizeDivs();
659   },
660
661   setImage: function() {
662     if ( this.currentSort == Rico.TableColumn.SORT_ASC ) {
663        this.imgSort.style.display='';
664        this.imgSort.src=Rico.imgDir+this.options.sortAscendImg;
665     } else if ( this.currentSort == Rico.TableColumn.SORT_DESC ) {
666        this.imgSort.style.display='';
667        this.imgSort.src=Rico.imgDir+this.options.sortDescendImg;
668     } else {
669        this.imgSort.style.display='none';
670     }
671     if (this.filterType == Rico.TableColumn.USERFILTER) {
672        this.imgFilter.style.display='';
673        this.imgFilter.title=this.getFilterText();
674     } else {
675        this.imgFilter.style.display='none';
676     }
677   },
678
679   canHideShow: function() {
680     return this.hideable;
681   }
682
683 };
684
685 Rico.includeLoaded('ricoGridCommon.js');