Mega Code Archive

 
Categories / JavaScript DHTML / GUI Components
 

Editable table cell

<HTML> <HEAD>   <META http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />   <META http-equiv="Author" content="Charles Dickens" />   <TITLE> HTML Grid Demo Ver 0.1.1</title>   <STYLE type="text/css">     input { border-style: solid; border-width: 1px; font-family: verdana, arial, sans-serif; font-size: 9px; padding: 0px; color:black; backgroundcolor: #FFFFEE}     td { border-style: solid; border-width: 1px; font-family: verdana, arial, sans-serif; font-size: 10px; padding: 0px;}      </STYLE>   <SCRIPT type="text/javascript"> /*\ |*| Version : 0.92 |*| Author  : Chaitanya Yinti |*| Contact : yinti@users.sourceforge.net |*| WebSite : http://dhtmlgrid.sourceforge.net/ |*| |*| Feel free to use this script under the terms of the GNU General Public |*| License, as long as you do not remove or alter this notice. \*/   /*************************************\   |       Start of Config Param         |   \*************************************/   // Color used for hilighting a selected row   var clrHilight = 'blue';   // Set this to false if you want 'click to select' and   // 'doubleclick to Edit' mode   var blnPointToSelect = true;   // Full path of the blank image used to hide the sort images    var strBlankImage = "blank.gif";   // Full path of the up image used on sort asc   var strUpImage = "up.gif";     // Full path of the up image used on sort des   var strDownImage = "down.gif";   // The width of the images used to indicate the asc/des sort   var intImgWidth = 12;   // The height of the images used to indicate the asc/des sort   var intImgHeight = 13;     /*************************************\   |           End of Config Param       |   \*************************************/   /*************************************\   |           Globals start             |   \*************************************/   // Stores the last used object during sort   var objLastClick = -1;   // Stores the text being edited   var txtOld = "";   // Stores the total table width   var intTotalWidth = 0;   // Stores the flag used by capturemouse   var blnMouseOver = false;     // Stores the div being moved   var objDivToMove = null;   // Stores the number of coloumns; initialized in init ()   var intColCount = 0;   // Stores the row element currently selected   var objRowSelected = null;   //THE element which holds the table...    var element = null;   /*************************************\   |           Globals end               |   \*************************************/   /*********************TODO*****************************\    prototype setCapture/releaseCapture PROPERLY    Get rid of isIE, isNS4 completely ...    Extend keycapture to navigate the table on up/down arrow    Fix escape/unescape on text change   \******************************************************/        /*\   |*| The entry point. This will    |*|    Attache all the appropriate functions to the table   |*|    Call function to create the IMG elems used during the sorting   |*|    call function to init the DIV elems that are used for moving   |*|    call function to init the DIV elems used for about box   \*/   function init (tableName)   {     //Handle all javascript errors      window.onerror = handleError;     isIE = (navigator.appVersion.indexOf ("MSIE") != -1);     isNS4 = (document.layers) ? true : false;     isNS6 = (!document.layers) && (navigator.userAgent.indexOf ('Netscape')!=-1);     if ((isNS4) && (!isNS6)) alert ("Currently only supports NN 6 and above");     if (document.getElementById)       element = document.getElementById (tableName);     else  //TODO: Need to test this piece of code still. Happens only in NN4 so far        eval (element = "document." + tableName);     if (element == null)       return alert ("Error: Not able to get table element ");     if (element.tagName != 'TABLE')       return alert ("Error: Not able to control element " + element.tagName);     initNNFunctions ();     if (blnPointToSelect)     {       element.attachEvent ('onmouseover', selectRow);       element.attachEvent ('onclick', onClickCell);     }     else     {       element.attachEvent ('onclick', selectRow);       element.attachEvent ('ondblclick', onClickCell);     }     document.attachEvent ('onkeydown' , captureDelKey);     //Need this fix for IE only .. so element.focus is stubbed in NN     element.focus ();        initSortImages ();     initDiv ();     initAbout ();   }   /*\   |*| This function removes the textnodes from the table rows.   |*| This cleanup work is needed to get rid of the EXTRA textnodes that NN gives   \*/   function removeTextNodes (t)   {     for (var i = 0; t.childNodes[i] ; i++)     {       if (!t.childNodes[i].tagName)       {          t.childNodes[i].parentNode.removeChild (t.childNodes[i]);       }       else       {         for (var j = 0; t.childNodes[i].childNodes[j] ; j++)         {           if (!t.childNodes[i].childNodes[j].tagName)              t.childNodes[i].childNodes[j].parentNode.removeChild (t.childNodes[i].childNodes[j]);         }       }     }   }   /*\   |*| This function adds the blank images to the head row of the table   \*/   function initSortImages ()   {     if (!element.tHead) return;     removeTextNodes (element.tHead);     var theadrow = element.tHead.childNodes[0]; //Assume just one Head row     if (isIE) theadrow.style.cursor = "hand";     else theadrow.style.cursor = "pointer";     removeTextNodes (theadrow.parentNode);     intColCount = theadrow.childNodes.length;     for (var i = 0; i < intColCount; i++)      {       objImg = document.createElement ("IMG");       objImg.setAttribute ("src", strBlankImage);       objImg.setAttribute ("id", "srtImg" + i);       objImg.setAttribute ("width", intImgWidth);       objImg.setAttribute ("height", intImgHeight);       objImg.setAttribute ("align", "right");       objImg.setAttribute ("valign", "middle");       objImg.setAttribute ("border", 0);       clickCell = theadrow.childNodes[i];       clickCell.selectIndex = i;       clickCell.insertAdjacentElement ("afterBegin", objImg);       clickCell.style.width = clickCell.width;     }   }   /*\   |*| This will only be called once during initIALIZATION   |*| This will create the DIV elems at the end of each col and   |*| attach all the functions needed to resize the coloumns   \*/   function initDiv ()   {     var objLast = element, objDiv;     removeTextNodes (element.tBodies[0]);     for (var i = 1; i <= intColCount; i++)     {         objDiv = document.createElement ("DIV");       objDiv.setAttribute ('id', "DragMark" + (i - 1));       objDiv.setAttribute ('name',  i);    //Used to track the TDs that have to be moved       objDiv.style.position = "absolute";       objDiv.style.top = 0;        var objTD = element.tHead.childNodes[0].childNodes[i - 1];       if (!objTD || objTD.tagName != "TD") return;       var intColWidth = (getRealPos (objTD) - 0) + (objTD.width - 0);       objDiv.style.left = intColWidth - 3 ;       objDiv.style.width = 6 + parseInt(element.border);       objDiv.style.height = (element.tBodies[0].childNodes.length + 1) * objTD.offsetHeight;       // for debugging only       //objDiv.style.backgroundColor = clrHilight;              //To make it more beautiful in IE 6         if (navigator.appVersion.indexOf ("MSIE 6.0") != -1)         objDiv.style.cursor = "col-resize";       else         objDiv.style.cursor = "crosshair";       objDiv.attachEvent ('onmouseover', flagTrue);       objDiv.attachEvent ('onmousedown', captureMouse);       objDiv.attachEvent ('onmousemove', resizeColoumn);       objDiv.attachEvent ('onmouseup', releaseMouse);       objDiv.attachEvent ('onmouseout', flagFalse);       objLast.insertAdjacentElement ("afterEnd", objDiv);       objLast = objDiv;     }   }   /*\   |*| This function will be fired onmouseover of the DIVs   |*| Set the flag to true indicating that the mouse is over the DIV   \*/   function flagTrue ()   {     blnMouseOver = true;   }   /*\   |*| This function will be fired onmousedown on the DIVs   |*| Capture all the mosue events if mousedown is fired inside the DIV   \*/   function captureMouse ()   {     if (blnMouseOver)     {       objDivToMove = window.event.srcElement;       objDivToMove.setCapture ();     }   }   /*\   |*| This function will be fired onmousemove of the DIVs   |*| This will be used as a ondrag function... thanks to IE 5   \*/   function resizeColoumn ()   {     //If mouse button is down, objDivToMove will be valid... we can move/resize     if (!objDivToMove) return;     var intTDNum = objDivToMove.name - 1;     var thead = element.tHead;     if (!thead) return;     var objTD = thead.childNodes[0].childNodes[intTDNum];     if (!objTD || objTD.tagName != "TD") return;     var intCurWidth = objTD.offsetWidth;     var newX = window.event.clientX;     //var newX = window.event.x;     var intNewWidth = newX - objTD.offsetLeft;     //TODO: who decided that the minimum col widhth is 50px?     if (intNewWidth < 50) return;     //Check to see if the table widht is more than the width of the window     //Need that 20px buffer in IE to prevent scroll bars from appearing     if (element.document.body.offsetWidth - 20 < element.offsetWidth - intCurWidth + intNewWidth) return;     objTD.style.width = intNewWidth;     var objDiv = objDivToMove;     //Will be Â± 1 depending on which side the mouse moved     //will be used to move all the DIVs remaining on the right     var intDivMove = newX - objDiv.offsetLeft;     objDiv.style.left = newX;     //Move all the remaining DIVs on the right     for (var i = 1; i < intColCount - intTDNum; i++)     {               objDiv = objDiv.nextSibling;       objDiv.style.left = objDiv.offsetLeft + intDivMove ;     }   }   /*\   |*| This function will be fired onmouseup   |*| Release all the mouse events of the DIV   \*/   function releaseMouse ()   {     objDivToMove.releaseCapture ();     objDivToMove = null;   }   /*\   |*| This function will be fired onmouseout of the DIV   |*| Set the flag indicating that the mouse is NOT over the DIV   \*/   function flagFalse ()   {     blnMouseOver = false;   }   /*\   |*| This function will be called once during initIALIZATION   |*| This will create DIV elm after the table to display the ABOUT informationA   \*/   function initAbout ()   {     objDiv = window.document.createElement ("DIV");     objDiv.id = "About";     objDiv.style.position = "absolute";     objDiv.style.top = 0;      objDiv.style.left = 0 ;     objDiv.align = "center";     //element.document.body.offsetWidth ==> width of the IFRAME in IE     objDiv.style.width = element.document.body.offsetWidth;     objDiv.style.height = element.document.body.offsetHeight;     objDiv.style.backgroundColor = "#0000FF";     objDiv.style.color = "#FFFF00";     objDiv.style.visibility = "hidden";     objDiv.insertAdjacentText ("afterBegin", "DHTML Grid ver 0.92\n\n" + "");     var objInput = document.createElement ("INPUT");     objInput.id = "cmdAbout";     objInput.title = "Ok";     objInput.value = "Ok";     objInput.align = "center";     objInput.valign = "middle";     objInput.style.height = "20px";     objInput.style.width = "102px";     objInput.type = "button";     objInput.attachEvent ("onclick", about);     objDiv.insertAdjacentElement ("beforeEnd", objInput);     element.insertAdjacentElement ("afterEnd", objDiv);   }   /*\   |*| Hilights the row on mouseover. This also sets the "previous row selected" to normal   \*/   function selectRow ()   {     var srcElem = getEventRow ();     if (srcElem.tagName != "TR") return;     if (objRowSelected)     {       objRowSelected.style.backgroundColor = '';       objRowSelected = null;     }     if (srcElem.rowIndex > 0)     {       srcElem.style.backgroundColor = clrHilight;       objRowSelected = srcElem;     }     element.focus ();   }   /*\   |*| Entry point for all the click events on the table   \*/   function onClickCell ()   {     var srcElem = getEventRow ();     if (srcElem.tagName != "TR") return;     if (srcElem.rowIndex == 0) sort ();     else onEdit ();   }   /*\   |*| Capture the key press event, on del key see if a row is selected and delete   \*/   function captureDelKey ()   {     var keyPressed = event.keyCode;          var srcElem = window.event.srcElement;     if ((keyPressed == 46) && (srcElem.tagName != "INPUT") && (objRowSelected))     {       deleteRow (objRowSelected.rowIndex - 1);       objRowSelected = null;     }   }   /*\   |*| detach all the events attached to the element and call other cleanup functions   \*/   function cleanup ()   {     element.detachEvent ('onmouseover', selectRow);     element.detachEvent ('onclick', onClickCell);     cleanupDiv ();     cleanupAbout ();   }   /*\   |*| Used by cleanup to clean the DIVs created for moving the Cols   |*| detach all the events and delete the elements here   \*/   function cleanupDiv ()   {     var objDiv;     for (var i = 1; i <= intColCount; i++)     {         objDiv = element.document.getElementById ("DragMark" + (i - 1));       objDiv.detachEvent ('onmouseover', flagTrue);       objDiv.detachEvent ('onmousedown', captureMouse);       objDiv.detachEvent ('onmousemove', resizeColoumn);       objDiv.detachEvent ('onmouseup', releaseMouse);       objDiv.detachEvent ('onmouseout', flagFalse);       objDiv.removeNode (true);     }   }   /*\   |*| Detach all the events and Delete the elms related to the about box here   \*/   function cleanupAbout ()   {     element.document.getElementById ("About").removeNode (true);   }   /*\   |*| This is THE function which does all the real sorting of the rows   |*| First get rid of all the text-node elements that NN returns for spaces in the tables   |*| then sort the contents based on which coloumn is clicked   \*/   function insertionSort (t, iRowEnd, fReverse, iColumn)   {     var textRowInsert, textRowCurrent, eRowInsert, eRowWalk;     removeTextNodes (t);     for (var iRowInsert = 1 ; iRowInsert <= iRowEnd ; iRowInsert++)     {       if (iColumn)       {         if (typeof (t.childNodes[iRowInsert].childNodes[iColumn]) != "undefined")            textRowInsert = t.childNodes[iRowInsert].childNodes[iColumn].innerText;         else           textRowInsert = "";       }       else       {         textRowInsert = t.childNodes[iRowInsert].innerText;       }       for (var iRowWalk = 0 ; iRowWalk < iRowInsert ; iRowWalk++)       {         if (iColumn)         {           if (typeof (t.childNodes[iRowWalk].childNodes[iColumn]) != "undefined")             textRowCurrent = t.childNodes[iRowWalk].childNodes[iColumn].innerText;           else             textRowCurrent = "";         }         else         {           textRowCurrent = t.childNodes[iRowWalk].innerText;         }         if ((!fReverse && textRowInsert < textRowCurrent) || (fReverse && textRowInsert > textRowCurrent))         {           eRowInsert = t.childNodes[iRowInsert];           eRowWalk = t.childNodes[iRowWalk];           t.insertBefore (eRowInsert, eRowWalk);           iRowWalk = iRowInsert; // done         }       }     }   }   /*\   |*|  This function is called when there is a click event on the top   |*|  row   \*/   function sort ()   {     var srcElem = getEventCell ();     if (srcElem.tagName != "TD") return;     var thead = element.tHead;       // clear the sort images in the head     var imgcol = thead.getElementsByTagName ("IMG");     for (var x = 0; x < imgcol.length; x++)      {       imgcol[x].setAttribute('src', strBlankImage);     }     if (objLastClick == srcElem.selectIndex)     {       if (reverse == false)       {         srcElem.childNodes[0].setAttribute ('src', strDownImage);         reverse = true;       }       else        {         srcElem.childNodes[0].setAttribute ('src', strUpImage);         reverse = false;       }     }     else     {       reverse = false;       objLastClick = srcElem.selectIndex;       srcElem.childNodes[0].setAttribute ('arc', strUpImage);     }     tbody = element.tBodies [0];     insertionSort (tbody, tbody.rows.length-1, reverse, srcElem.selectIndex);   }   /*\   |*| This function is called when focus is lost on the text box   |*| that is used to read user input. Validate the contents of the   |*| input box and write them back to the table cell   \*/   function focusLost ()   {     var objSrcElm = window.event.srcElement;      objSrcElm.parentNode.innerHTML = unescape (objSrcElm.value);   }   /*\   |*| This function is called when user clicks on a cell other than   |*| the top row.   |*| Show the content of the cell in an input box   \*/   function onEdit ()   {     var srcElem = getEventCell ();          if (srcElem.tagName != "TD") return;     if (srcElem.firstChild && srcElem.firstChild.tagName == "INPUT") return;          txtOld = srcElem.innerHTML;     srcElem.innerHTML = "";      var objInput = document.createElement ("INPUT");     objInput.style.width = "100%";//srcElem.clientWidth;     objInput.type = "text";     objInput.value = "" + escape (txtOld);     //objInput.attachEvent ("onfocusout", focusLost);     //the above onfocusout works fine in IE 6 but not in IE 5 so...     objInput.attachEvent ("onblur", focusLost);     objInput.attachEvent ("onkeypress", checkForEnter);     srcElem.insertAdjacentElement ("beforeEnd", objInput);     objInput.select ();   }   /*\   |*| This function is used to add a row at the end of the tabl   |*| Once the rows are added it calls the function to change the height   |*|  of the DIVs that are used for resizing the table.   \*/   function addRow ()   {     var objTR = document.createElement ("TR");     var objTD = document.createElement ("TD");     for (var i = 0; i < addRow.arguments.length; i++)      {       objTD = document.createElement ("TD");       objTD.appendChild (document.createTextNode ((arguments[i]=="")?"null":arguments[i]));       objTR.insertAdjacentElement ("beforeEnd", objTD);     }     objTBody = element.tBodies [0];     objTBody.insertAdjacentElement ("beforeEnd", objTR);     resizeDivs ();   }      /*\   |*| The function deletes the last row by calling the deleteRow function    |*|  with the table row count   \*/   function deleteLastRow ()   {     removeTextNodes (element.tBodies[0]);     this.deleteRow (element.tBodies[0].childNodes.length - 1);   }   /*\   |*| The function checks if the rownum passed is a valid row    |*|  and deletes it    |*| This also calls the resizeDivs function to reduce the height   |*|  of the DIVs that are used in resizing the table   \*/   function deleteRow (rowNum)   {     var tbody = element.tBodies [0];     if (!tbody || rowNum < 0) return;     removeTextNodes (tbody);     tbody.childNodes[rowNum].removeNode (true);     resizeDivs ();   }   /*\   |*| This will be called on everkeypress event of the input box   |*| This raises the focuslost event if the user hits enter   \*/   function checkForEnter ()   {     if (event.keyCode == 13) focusLost ();   }   /*\   |*| Toggle the About div section   \*/   function about ()   {     if (element.document.getElementById ("About").style.visibility == "hidden")       element.document.getElementById ("About").style.visibility = "visible";     else       element.document.getElementById ("About").style.visibility = "hidden";   }   /*\   |*| Need this as IE 5 doesnt give the offsetLeft property properly   \*/   function getRealPos (elm)   {     intPos = 0;     elm = elm.previousSibling;     while ((elm!= null) && (elm.tagName!="BODY"))     {        intPos += elm.width - 0;       elm = elm.previousSibling;     }     return intPos;   }   /*\   |*| Return the TR elem on which an event has fireed   \*/   function getEventRow ()   {     var srcElem = window.event.srcElement;     //crawl up to find the row     while (srcElem.tagName != "TR" && srcElem.tagName != "TABLE")     {       srcElem = srcElem.parentNode;     }     return srcElem;   }   /*\   |*| Return the TD elem on which an event has fireed   \*/   function getEventCell ()   {     var srcElem = window.event.srcElement;     //crawl up the tree to find the table col     while (srcElem.tagName != "TD" && srcElem.tagName != "TABLE")     {       srcElem = srcElem.parentNode;     }     return srcElem;   }   /*\   |*| This funtion is used to change the height of the DIVs that are used to drag the cols   |*| Used when a row is added or deleted.   \*/   function resizeDivs ()   {     for (var i = 0; i < intColCount; i++)     {         var objDiv = element.document.getElementById ("DragMark" + (i));       var objTD = element.tHead.childNodes[0].childNodes[i];       if ((!objDiv) || (!objTD) || (objTD.tagName != "TD")) return;       objDiv.style.height = (element.tBodies[0].childNodes.length + 1) * (objTD.offsetHeight - 1);     }   }   /*\   |*| Function to handle erros. Displayes a request to contact along with the error messagei, filename and line   \*/   function handleError (err, url, line)   {     alert ('Oops, something went wrong.\n' +        'Please contact yinti AT users DOT sourceforge DOT net with the following text\n' +         'Error text: ' + err + '\n' +         'Location  : ' + url + '\n' +        'Line no   : ' + line + '\n');      return true; // let the browser handle the error */   }   /*\   |*| Function to prototype all the functions needed by NN to emulate the functionality of IE   \*/   function initNNFunctions ()   {     if ((self.Node) && (self.Node.prototype))     {       Node.prototype.removeNode = NNRemoveNode;       Element.prototype.insertAdjacentText = NNInsertAdjacentText;       Element.prototype.insertAdjacentElement = NNInsertAdjacentElement;       Element.prototype.insert__Adj = NNInsertAdj;       Element.prototype.attachEvent = NNAttachEvent;       Element.prototype.detachEvent = NNDetachEvent;       Element.prototype.setCapture = NNSetCapture;       Element.prototype.releaseCapture = NNReleaseCapture;       Element.prototype.__defineGetter__('document', NNDocumentGetter);       HTMLElement.prototype.focus = NNNullFunction;       HTMLElement.prototype.attachEvent = NNAttachEvent;       HTMLElement.prototype.detachEvent = NNDetachEvent;       HTMLElement.prototype.__defineGetter__('innerText', NNInnerTextGetter);       HTMLElement.prototype.__defineSetter__('innerText', NNInnerTextSetter);       HTMLDocument.prototype.attachEvent = NNAttachEvent;       HTMLDocument.prototype.detachEvent = NNDetachEvent;       Event.prototype.__defineGetter__('keyCode', NNKeyCodeGetter);     }   }   /*\   |*|   \*/   function NNRemoveNode (a1)   {     var p = this.parentNode;     if (p&&!a1)     {       var df = document.createDocumentFragment ();       for (var a = 0; a < this.childNodes.length; a++)       {         df.appendChild (this.childNodes[a])       }       p.insertBefore (df , this)     }     return p?p.removeChild (this):this;   }   /*\   |*|   \*/   function NNInsertAdjacentText (a1 , a2)   {     var t = document.createTextNode (a2||"")     this.insert__Adj (a1 , t);   }   /*\   |*|   \*/   function NNInsertAdjacentElement (a1 , a2)   {     this.insert__Adj (a1 , a2);     return a2;   }   /*\   |*|   \*/   function NNInsertAdj (a1 , a2)   {     var p = this.parentNode;     var s = a1.toLowerCase ();     if (s == "beforebegin"){p.insertBefore (a2 , this)}     if (s == "afterend"){p.insertBefore (a2 , this.nextSibling)}     if (s == "afterbegin"){this.insertBefore (a2 , this.childNodes[0])}     if (s == "beforeend"){this.appendChild (a2)}   }   /*\   |*| Fuction to simulate attachEvent   \*/   function NNAttachEvent (strEvent, funcHandle)   {     var shortTypeName = strEvent.replace (/on/, "");     funcHandle._ieEmuEventHandler = function (e)     {       window.event = e;       window.event.srcElement = e.target;       return funcHandle ();     };     this.addEventListener (shortTypeName, funcHandle._ieEmuEventHandler, false);   }   /*\   |*| Fuction to simulate detachEvent   \*/   function NNDetachEvent (strEvent, funcHandle)   {     var shortTypeName = strEvent.replace (/on/, "");     if (typeof funcHandle._ieEmuEventHandler == "function")       this.removeEventListener (shortTypeName, funcHandle._ieEmuEventHandler, false);     else        this.removeEventListener (shortTypeName, funcHandle, true);   }   /*\   |*| A HUGE HACK to getaway with the lack of setcapture in NN   \*/   function NNSetCapture ()   {     //TODO: FIX THIS FIRST BEFORE ANYTHING ELSE!! MAJOR HACK FOR NOW     document.attachEvent ('onmousemove', resizeColoumn);     document.attachEvent ('onmouseup', releaseMouse);   }   /*\   |*| A HUGE HACK to getaway with the lack of releasecapture in NN   \*/   function NNReleaseCapture ()   {     //TODO: FIX THIS SECOND THEN GO TO EVERYTHING ELSE!      document.detachEvent ('onmousemove', resizeColoumn);     document.detachEvent ('onmouseup', releaseMouse);   }   /*\   |*| Empty function used to remove any functions not needed in NN   \*/   function NNNullFunction () { /*Nothing here*/ }   /*\   |*| return the innerhtml by replacing all the <TAGNAME> from the string   \*/   function NNInnerTextGetter ()   {     return this.innerHTML.replace (/<[^>]+>/g,"");   }   /*\   |*| Add the text as a textnode to the element   \*/   function NNInnerTextSetter (txtStr)   {     var parsedText = document.createTextNode (txtStr);     this.innerHTML = "";     this.appendChild (parsedText);   }   /*\   |*| Function to simulate event.keyCode   \*/   function NNKeyCodeGetter ()   {     return this.which;   }   /*\   |*| Function to simulate element.document   \*/   function NNDocumentGetter ()   {     return this.ownerDocument;   }      </SCRIPT> </HEAD> <BODY leftmargin="0" topmargin="0" onload="init('tblGrid')">   <TABLE bordercolor="#ababab" border="1px" cellpadding="0" cellspacing="0"       id="tblGrid" name="tblGrid" style="position:relative">       <!-- style="behavior:url(TableCtrl.htc);" -->     <THEAD>     <TR bgcolor="#999999">       <TD width="170">Col 1</TD>       <TD width="60">Col 2</TD>       <TD width="170">Col 3</TD>       <TD width="60">Col 4</TD>     </TR>     </THEAD>     <TBODY>     <TR>       <TD>200</TD>       <TD>dcdcdc</TD>       <TD>400</TD>       <TD>aaaaaa</TD>     </TR>     <TR>       <TD>300</TD>       <TD>c9e6ff</TD>       <TD>600</TD>       <TD>cccccc</TD>     </TR>     <TR>       <TD>301</TD>       <TD>e6e6ff</TD>       <TD>601</TD>       <TD>eeeeee</TD>     </TR>     </TBODY>   </TABLE> </BODY> </HTML>