javascript datagrid problemm

Discussion in 'JavaScript' started by bebitzaa, Apr 3, 2007.

  1. #1
    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'>&nbsp;</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">&nbsp;1</td>
    			<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>
    		</tr>
    		<tr class="data alt">
    			<td class="cell0">&nbsp;2</td>
    			<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>
    		</tr>
    		<tr class="data">
    			<td class="cell0">&nbsp;3</td>
    			<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>
    		</tr>
    		<tr class="data alt">
    			<td class="cell0">&nbsp;4</td>
    			<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>
    		</tr>
    		<tr class="data">
    			<td class="cell0">&nbsp;5</td>
    			<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>
    		</tr>
    		<tr class="data alt">
    			<td class="cell0">&nbsp;6</td>
    			<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>
    		</tr>
    		<tr class="data">
    			<td class="cell0">&nbsp;7</td>
    			<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>
    		</tr>
    		<tr class="data alt">
    			<td class="cell0">&nbsp;8</td>
    			<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>
    		</tr>
    		<tr class="data">
    			<td class="cell0">&nbsp;9</td>
    			<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</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 : '&nbsp;';
    	
    	// NOTE: we can implement an OnChange event by comparing value against _lastValue;
    }
    
    function GetCellValue(cell)
    {
    	return cell.innerHTML != '&nbsp;' ? 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):

     
    bebitzaa, Apr 3, 2007 IP