I have the folowing code that makes me a datagrid but when i make the header freeze and to make scroll the grid doesn't work. Help <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>Grid</title> <style type="text/css"> td a:link, td a:visited { border: 0; text-decoration: none; } td a:hover { border-bottom: 1px solid rgb(204, 204, 204); } td a img { border: 0 !important; } th { text-align: left; vertical-align: bottom; } th.cellHeader { text-align: center; } th.rowHeader { text-align: right; vertical-align: middle; } tr.alt { } tr td { vertical-align: bottom; } tr.data td { vertical-align: center; } tr.data td { text-align: left; border-right: 1px solid #9eb6ce; border-bottom: 1px solid #9eb6ce; } td.readOnly { background-image: url(header.jpg); border-right: 1px solid #9eb6ce; background-repeat: repeat-x; text-align: center; } td.cell0{ background-image: url(cell.jpg); border-right: 1px solid #9eb6ce; background-repeat: repeat-x; text-align: center; } tr.data td.text { text-align: left; border-left: none; white-space: nowrap; } tr.data td.memo { white-space: normal; } tr th, tr td { font-size: 80%; font-family: arial } tr.data td.selected { background-color: #000066; color:#FFFFFF; } tr.data td.selected input { text-align: right; border: 1px 1px 1px 1px #000066; } </style> <script language="javascript"> function mask(str,textbox,loc,delim){ var locs = loc.split(','); for (var i = 0; i <= locs.length; i++){ for (var k = 0; k <= str.length; k++){ if (k == locs[i]){ if (str.substring(k, k+1) != delim){ str = str.substring(0,k) + delim + str.substring(k,str.length) } } } } textbox.value = str } </script> </head> <body> <div style="overflow:auto;width:150px;height:100px;"> <table id="jsGrid" cellpadding="0" cellspacing="0px" > <thead> <tr style="position:relative; top:expression(this.offsetParent.scrollTop);"> <td width="14" class='readOnly'> </td> <td width="22" class='readOnly'>A</td> <td width="61" class="readOnly">B</td> <td width="45" class="readOnly">C</td> <td width="72" class="readOnly">D</td> </tr> </thead> <tr class="data"> <td class="cell0"> 1</td> <td> </td><td> </td><td> </td><td> </td> </tr> <tr class="data alt"> <td class="cell0"> 2</td> <td> </td><td> </td><td> </td><td> </td> </tr> <tr class="data"> <td class="cell0"> 3</td> <td> </td><td> </td><td> </td><td> </td> </tr> <tr class="data alt"> <td class="cell0"> 4</td> <td> </td><td> </td><td> </td><td> </td> </tr> <tr class="data"> <td class="cell0"> 5</td> <td> </td><td> </td><td> </td><td> </td> </tr> <tr class="data alt"> <td class="cell0"> 6</td> <td> </td><td> </td><td> </td><td> </td> </tr> <tr class="data"> <td class="cell0"> 7</td> <td> </td><td> </td><td> </td><td> </td> </tr> <tr class="data alt"> <td class="cell0"> 8</td> <td> </td><td> </td><td> </td><td> </td> </tr> <tr class="data"> <td class="cell0"> 9</td> <td> </td><td> </td><td> </td><td> </td> </tr> </table> </div> <script type="text/javascript"> //<![CDATA[ document.onmousedown = OnDocumentMouseDown; document.onmouseup = OnDocumentMouseUp; document.onkeydown = OnDocumentKeyDown; document.onkeypress = OnDocumentKeyPress; $('jsGrid').onclick = OnTableClick; var VK_UP = 38; var VK_LEFT = 37; var VK_RIGHT = 39; var VK_DOWN = 40; var VK_TAB = 9; var VK_ENTER = 13; var VK_F2 = 113; var VK_ESCAPE = 27; var VK_DELETE = 46; var VK_BACK = 8; var _keyNavMap; // _lastTxt != null = o celula se editeaza var _lastTxt; // _lastCell != null = o celula este aprinsa var _lastCell; var _lastValue; function InitKeyNavMap() { _keyNavMap = new Object(); _keyNavMap[VK_UP] = { 'false': [0, -1], 'true': [0, 0] }; _keyNavMap[VK_DOWN] = { 'false': [0, 1], 'true': [0, 0] }; _keyNavMap[VK_LEFT] = { 'false': [-1, 0], 'true': [0, 0], NotOnEdit: true }; _keyNavMap[VK_RIGHT] = { 'false': [1, 0], 'true': [0, 0], NotOnEdit: true }; _keyNavMap[VK_TAB] = { 'false': [1, 0], 'true': [-1, 0] }; _keyNavMap[VK_ENTER] = { 'false': [1, 0], 'true': [-1, 0] }; } InitKeyNavMap(); function OnDocumentKeyDown(e) { e = e || window.event; var target = e.target || e.srcElement; if (e.ctrlKey || e.altKey || _lastCell == null) return; if (e.keyCode == VK_F2 && _lastCell != null) { EnterCell(_lastCell, false); return false; } else if (e.keyCode == VK_ESCAPE && _lastTxt != null) { var td = _lastCell; LeaveCell(td, false); EnterCell(td, true); return false; } else if (e.keyCode == VK_DELETE && _lastCell != null && _lastTxt == null) { SetCellValue(_lastCell, ''); return false; } else if (e.keyCode == VK_BACK && _lastCell != null && _lastTxt == null) { EnterCell(_lastCell, false); _lastTxt.value = ''; return false; } var keyNav = _keyNavMap[e.keyCode]; if (keyNav == null || _lastTxt != null && keyNav.NotOnEdit) return; var xy = keyNav[e.shiftKey]; NavigateCells(xy[0], xy[1]); if (_lastTxt != null) { var td = _lastCell; LeaveCell(td, true); EnterCell(td, true); } return false; } function NavigateCells(dx, dy) { if (dx != 0) { var td = _lastCell; for (; dx > 0 && td != null; dx = IsValidCell(td) ? dx - 1 : dx) td = nextSiblingByTagName(td, 'TD'); for (; dx < 0 && td != null; dx = IsValidCell(td) ? dx + 1 : dx) td = prevSiblingByTagName(td, 'TD'); if (IsValidCell(td)) EnterCell(td, true); } else if (dy != 0) { var tr = _lastCell.parentNode; for (; dy > 0 && tr != null; dy = IsValidRow(tr) ? dy - 1 : dy) tr = nextSiblingByTagName(tr, 'TR'); for (; dy < 0 && tr != null; dy = IsValidRow(tr) ? dy + 1 : dy) tr = prevSiblingByTagName(tr, 'TR'); if (!IsValidRow(tr)) return; var fromTds = _lastCell.parentNode.getElementsByTagName('td'); var toTds = tr.getElementsByTagName('td'); for (var i = 0; i < toTds.length; i++) { if (fromTds[i] == _lastCell) { EnterCell(toTds[i], true); break; } } } } function IsValidCell(td) { return td != null && !ContainsClass(td, 'text') && !ContainsClass(td, 'readOnly') && !ContainsClass(td, 'cell0'); } function IsValidRow(tr) { return tr != null && ContainsClass(tr, 'data'); } function SetCellValue(cell, value) { cell.innerHTML = value.length > 0 ? value : ' '; // NOTE: we can implement an OnChange event by comparing value against _lastValue; } function GetCellValue(cell) { return cell.innerHTML != ' ' ? cell.innerHTML : ''; } function LeaveCell(cell, saveEdit) { if (cell == null) return; RemoveClass(cell, 'selected'); if (_lastTxt != null) SetCellValue(cell, saveEdit ? _lastTxt.value : _lastValue) cell.style.padding = ''; cell.style.margin = ''; _lastCell = null; _lastTxt = null; } function EnterCell(cell, highlightOnly) { if (_lastCell != null && _lastCell != cell) LeaveCell(_lastCell, true); else if (_lastCell != null && _lastCell == cell && highlightOnly && _lastTxt != null) throw 'Cannot call EnterCell with highlightOnly == true if cell is the ' + 'currently selected cell and is in edit mode; call LeaveCell first.' AddClass(cell, 'selected'); _lastCell = cell; if (highlightOnly || _lastTxt != null) return; var txt = document.createElement('input'); txt.type = 'text'; txt.value = GetCellValue(cell); // CHANGE: we want to preserve the actual contents, which might be different // from what GetCellValue returns _lastValue = txt.value; // MAGIC: who knows why these numbers result the textbox fitting perfectly // in the cell in Firefox. The width is actually 2 pixels too large for // IE, but subtracting these two additional pixels below results in IE // obliterating the nice border to the left of the textbox; instead, we // keep the extra two pixels so that the textbox's border takes over the // right and left borders of the cell. txt.style.width = (cell.offsetWidth - 7) + 'px'; txt.style.height = (cell.offsetHeight - 6) + 'px'; // MAGIC: IE is retarded and forces a pixel of space above and below the // textbox; with the spacing used in the table above, this results in // a textbox which is too short, or a textbox which forces the entire // row to be two pixels higher. Therefore, we absolutely position the // textbox within the table cell, which keeps it from affecting the row's // height. Due to the above comment on IE screwing up borders, we also // shift the cell one pixel to the left. // NOTE: Firefox apparently does not respect absolutely positioned elements // in table cells when the table cell is given a position: relative // style; why this is so is unknown, if (document.all) { txt.style.position = 'absolute'; txt.style.left = '1px'; txt.style.top = '0'; cell.style.position = 'relative'; } cell.innerHTML = ''; cell.style.padding = '0'; cell.style.margin = '0'; cell.appendChild(txt); txt.select(); _lastTxt = txt; } function OnDocumentKeyPress(e) { if (_lastCell == null || _lastTxt != null) return; e = e || window.event; if (e.charCode == 0 || e.keyCode == VK_ESCAPE) return; var code = e.keyCode || e.charCode; if (code != 0) { EnterCell(_lastCell, false); _lastTxt.value = String.fromCharCode(code); return false; } } function OnDocumentMouseDown(e) { e = e || window.event; var target = e.target || e.srcElement; if (target.tagName == 'TD' && IsValidRow(target.parentNode) && IsValidCell(target)) { EnterCell(target, true); document.onselectstart = function() { return false; }; return false; } else if (_lastCell != null && (target.tagName != 'INPUT' || target.parentNode.tagName != 'TD')) LeaveCell(_lastCell, true); } function OnTableClick(e) { e = e || window.event; var target = e.target || e.srcElement; if (target.tagName == 'TD' && IsValidRow(target.parentNode) && IsValidCell(target)) EnterCell(target, false); } function OnDocumentMouseUp() { // activez text selection document.onselectstart = null; } /* functii ajutatoare */ function $(id) { return document.getElementById(id); } function AddClass(el, className) { if (el.className == null) el.className = className; else if (!ContainsClass(el, className)) el.className += (el.className.length > 0 ? ' ' : '') + className; } function RemoveClass(el, className) { if (el.className == null) return; var r = new RegExp('\\s*\\b' + className + '\\b\\s*'); el.className = el.className.replace(r, ' ').replace(/^\s*(.*?)\s*$/, '$1'); } function ContainsClass(el, className) { var r = new RegExp('\\b' + className + '\\b'); return r.test(el.className); } function nextSiblingByTagName(obj, tagName, searchPassedElement) { if (obj == null) return null; var element = searchPassedElement ? obj : obj.nextSibling; while (element != null) { if (element.tagName == tagName) return element; else element = element.nextSibling; } return null; } function prevSiblingByTagName(obj, tagName) { var element = obj.previousSibling; while (element != null) { if (element.tagName == tagName) return element; else element = element.previousSibling; } return null; } //]]> </script> </body> </html> Code (markup):