Link to home
Start Free TrialLog in
Avatar of dshrenik
dshrenikFlag for United States of America

asked on

Error with table navigation

In the attached code, it is possible to navigate the table cells with the arrow keys.
I need an enhancement:
 - When the user presses the left arrow key when the focus is on the first textbox of a row, the focus must shift to the last textbox of the previous row.
 - When the user presses the right arrow key when the focus is on the last textbox of a row, the focus must shift to the first textbox of the next row.  

Also, table navigation is not happening in the last row - probably because it is not being renamed according to the convention.

If possible, please give me the code that fixes these things.

Thanks!
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>OOP Table Manipulation</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
body, p, td, div { font-family: Calibri, Arial, Tahoma; }

table {
	margin:10px 0;
	border-collapse: collapse;
}

tr { margin-top:2px; }

td {
	margin-left:2px;
	padding: 2px;
}
div.newcol a {
	text-decoration: none;
}
.xmark {
	font-size:14px;
}
.xmark, .pmark, .pRowMark {
	color:#888;
	text-decoration:none;
}
.pmark {
	font-size: 22px;
	margin-left: -8px;
}

.xRowMark, .pRowMark {
	padding-right: 10px;
	margin-left: 65px;
}

.pRowMark {
	font-size: 22px;
	margin-right: -1px;
}

.xTableMark {
	font-size:18px;
	color:#888;
	text-decoration:none;
}

.xmark:hover,
.xTableMark:hover { color:#F00; }

.tableContainer {
	display: inline-block;
	position: relative;
	padding: 0 20px 20px 0;
	overflow: visible;
}

.tableContainer img.button {
	position: absolute;
	z-index: 1000;
}

.tableContainer img.button:hover { cursor: pointer; }

.tableContainer img.newCol {
	top: 60px;
	right: 0px;
	width: 20px;
	height: 20px;
}

.tableContainer img.newRow {
	bottom: 5px;
	right: 100px;
	width: 16px;
	height: 16px;
}

</style>
<script type="text/javascript">
//<![CDATA[
var tableInstancePool = new Array();
var counter = 0;
var numTables = 0;

var dropDown = "<select name='' id='' style='width: 100%'><option value='1'>1</option><option value='2'>2</option><option value='3'>3</option></select>";
//var textBox = "<input type='text'></input>";
var textBox = "<input type='text' onfocus=\"this.style.border='2px solid gray';\" onblur=\"this.style.border='';\"></input>";
var b = "1px solid red";

function move(e, el) {
      var did = el.id;
      var parts = did.split('*');
      var grow = parts[1].split('_');
      var gcol = parts[2].split('_');
      var currow = parseInt(grow[1]);
      var curcol = parseInt(gcol[1]);

var key = (window.event) ? event.keyCode : e.keyCode;

window.status = key;
var newcol = curcol;
var newrow = currow;

var oRows = document.getElementById(parts[0]).getElementsByTagName('tr').length - 1;
var oCols = document.getElementById(parts[0]).getElementsByTagName('tr')[0].getElementsByTagName('td').length - 1;

if (key == 37) { // left arrow
if (curcol > 0) {var newcol = curcol - 1;} else if (currow > 0) {newrow = currow - 1; newcol = oCols - 1;}
} else if (key == 38) { // up arrow
if (currow > 0 ) {var newrow = currow - 1;}
} else if (key == 39) { // right arrow
if (curcol < oCols - 1) {newcol = curcol + 1;} else {newrow = currow + 1; newcol = 0;}
} else if (key == 40) { // down arrow
newrow = currow + 1;
}

var newid = parts[0] + '*tr_' + newrow + '*td_' + newcol;      
var element = document.getElementById(newid);
var inp = element.getElementsByTagName('input');
inp[0].focus();
return false;

}

function highlightRow(cellElem) {

	// Cell that contains the delete link
	var cellElem = cellElem.parentNode;

	// Table that contains the cell
	var tbody = cellElem.parentNode.parentNode;

	// Get row index of current cell
	var rowIndex = -1;
	var rows = tbody.getElementsByTagName("tr");

	outerLoop:
	for(i=0; i<rows.length; i++) {

		var cells = rows[i].getElementsByTagName("td");
		for(j=0; j<cells.length; j++) {

			if(cells[j] == cellElem) {
				rowIndex = i;
				break outerLoop;
			}
		}
	}

	// Highlight all cells in same row
	if(rowIndex > 0) {
		var cells = rows[rowIndex].getElementsByTagName("td");

		cells[1].style.borderLeft = b;
		for(j=1; j<cells.length; j++) {

			cells[j].style.borderTop = b;
			cells[j].style.borderBottom = b;
		}
		cells[cells.length-1].style.borderRight = b;
	}
}

function highlightCol(cellElem) {

	// Cell that contains the delete link
	var cellElem = cellElem.parentNode;

	// Table that contains the cell
	var tbody = cellElem.parentNode.parentNode;

	// Get row index of current cell
	var colIndex = -1;
	var rows = tbody.getElementsByTagName("tr");

	outerLoop:
	for(i=0; i<rows.length; i++) {

		var cells = rows[i].getElementsByTagName("td");
		for(j=0; j<cells.length; j++) {

			if(cells[j] == cellElem) {
				colIndex = j;
				break outerLoop;
			}
		}
	}

	// Highlight all cells in same row
	if(colIndex > 0) {

		rows[1].getElementsByTagName("td")[colIndex].style.borderTop = b;
		for(i=1; i<rows.length - 1; i++) {

			var cell = rows[i].getElementsByTagName("td")[colIndex];

			cell.style.borderLeft = b;
			cell.style.borderRight = b;
		}
		rows[rows.length-2].getElementsByTagName("td")[colIndex].style.borderBottom = b;
	}
}

function highlightTable(tableElem) {

	var tbody = tableElem.parentNode.parentNode.parentNode;

	var rows = tbody.getElementsByTagName("tr");
	for(i=1; i<rows.length - 1; i++) {

		var cells = rows[i].getElementsByTagName("td");
		for(j=1; j<cells.length; j++) {

			if(i==1) cells[j].style.borderTop = b;
			if(j==1) cells[j].style.borderLeft = b;
			if(i==rows.length-2) cells[j].style.borderBottom = b;
			if(j==cells.length-1) cells[j].style.borderRight = b;
		}
	}
}

function clearHighlights(cellElem) {

	// Table that contains the cell
	var tbody = cellElem.parentNode.parentNode.parentNode;
	var cells = tbody.getElementsByTagName("td");
	for(i=0; i<cells.length; i++) {

		cells[i].style.borderLeft = '';
		cells[i].style.borderRight = '';
		cells[i].style.borderTop = '';
		cells[i].style.borderBottom = '';
	}
}

function table(numRows, numCols, parentId) {
	numTables++;
	name = ++counter;
	this.name = name;
	this.numRows = numRows;
	this.numCols = numCols;
	this.parentId = parentId;
	this.rowCounter = numRows;
	this.colCounter = numCols;

	var tableHTML = '<div class="tableContainer"><table id="id_' + name + '">';

	// first row with the table delete button
	tableHTML += '<td align="center" style="color:#F00;"><a href="javascript:void(0);" onmouseover="highlightTable(this);" onmouseout="clearHighlights(this);" class="xTableMark" title="Delete Table" onclick="tableInstancePool[\'' + this.name + '\'].deleteThisTable(this);">X</a><br /><input id="id_' + this.name + '_checkbox_checkboxno" type="checkbox" style="margin-left: 30px; margin-bottom: 5px" checked="checked" /></td>';

	// first row with the col delete buttons
	for (var colCounter = 0; colCounter < numCols; colCounter++) {
		tableHTML += '<td align="center" valign="bottom" style="color:#F00"><div style="float: left"><a class="pmark" href="#" style="text-decoration: none" onclick="tableInstancePool[\'' + this.name + '\'].addCol(this)">+</a></div><a href="#" class="xmark" onmouseover="highlightCol(this);" onmouseout="clearHighlights(this);" onclick="tableInstancePool[\'' + this.name + '\'].delCol(this.parentNode);">X</a></td>';
	}
	
	// add the last col delete button
	tableHTML += '<td align="center" valign="bottom" style="color:#F00"><div style="float: left"><a class="pmark" href="#" style="text-decoration: none" onclick="tableInstancePool[\'' + this.name + '\'].addCol(this)">+</a></div>';
	
	
	tableHTML += '</tr>';

	// second row with select boxes
	tableHTML += '<tr><td>&nbsp;</td>'; // no delete button on this row
	for (var colCounter = 0; colCounter < numCols; colCounter++) {
		tableHTML += '<td>' + dropDown + '</td>';
	}
	tableHTML += '</tr>';

	// remaining rows with input fields
	for (var rowCounter = 0; rowCounter < numRows; rowCounter++) {
		tableHTML += '<tr id="">';
		tableHTML += '<td align="right" style="color:#F00"><a href="#" class="xmark xRowMark" onmouseover="highlightRow(this);" onmouseout="clearHighlights(this);" onclick="tableInstancePool[\'' + this.name + '\'].delRow(this.parentNode);">X</a></td>';
		for (var colCounter = 0; colCounter < numCols; colCounter++) {
			tableHTML += '<td id="" onkeyup="move(event,this);">' + textBox + '</td>';
		}
		tableHTML += '</tr>';
	}
	
	var container = document.createElement("div");
	container.innerHTML = tableHTML;
	document.getElementById(parentId).appendChild(container);
	this.renameID();
	
	addLastRow(this);
	
	var firstTextbox = document.getElementById("id_"+ name + "*tr_0*td_0");
	var inp = firstTextbox.getElementsByTagName('input');
	inp[0].focus();
}

table.prototype.addRow = addRow;
table.prototype.deleteRow = deleteRow;
table.prototype.deleteThisTable = deleteThisTable;
table.prototype.addCol = addCol;
table.prototype.delCol = delCol;
table.prototype.delRow = delRow;
table.prototype.renameID = renameID;

function addRow() {
	tableHTML = '<td align="right" style="color:#736F6E;"><a href="#" class="xmark xRowMark" onmouseover="highlightRow(this);" onmouseout="clearHighlights(this);" onclick="tableInstancePool[\'' + this.name + '\'].delRow(this.parentNode);">X</a></td>';
	for (var colCounter = 0; colCounter < this.numCols; colCounter++) {
		tableHTML += "<td onkeyup='move(event,this);'>" + textBox + "</td>";
	}

	this.rowCounter++;
	this.numRows++;
	var table = document.getElementById("id_" + this.name);
	table = table.getElementsByTagName("TBODY")[0];
	// add a new row to the table, and insert the cells we've just written
	rowElement = document.createElement('tr');
	
	// remove the last row so it can be readded later
	var last = document.getElementById("lastRow_" + this.name);
	if (last != null) table.removeChild(last);
	newRow = table.appendChild(rowElement);
	newRow.innerHTML = tableHTML;
	addLastRow(this);
	this.renameID(this);
}

function addLastRow(currentTable) {
	var lastRow = '<td align="right" style="margin-top: -2px"><a class="pRowMark" href="#" style="text-decoration: none" onclick="tableInstancePool[\'' + currentTable.name + '\'].addRow(this)">+</a></td><td colspan="20" />';
	var table = document.getElementById("id_" + currentTable.name);
	table = table.getElementsByTagName("TBODY")[0];
	rowElement = document.createElement('tr');
	rowElement.id = "lastRow_" + currentTable.name;
	newRow = table.appendChild(rowElement);
	newRow.innerHTML = lastRow;
}

function addCol(row_link) {
	index = row_link.parentNode.parentNode.cellIndex-1;
	if (index == null) { index=this.numCols; }
	var table = document.getElementById("id_" + this.name);
	var rows = table.rows;
	var delCrossAdded = false;
	
	for (var rowCounter = 0; rowCounter < this.numRows + 2; rowCounter++) {
		var row = rows[rowCounter];
		var cell = row.insertCell(index + 1);
		if (delCrossAdded) {
			cell.id = "";
			cell.innerHTML = textBox;
			cell.setAttribute("onkeyup","move(event,this);");
		} else {
			delCrossAdded = true;
			cell.setAttribute("align", "center");
			cell.setAttribute("valign", "bottom");
			cell.setAttribute("style", "color:#F00");
			cell.innerHTML = '<div style="float: left"><a class="pmark" href="#" style="text-decoration: none" onclick="tableInstancePool[\'' + this.name + '\'].addCol(this)">+</a></div><a href="#" class="xmark" onmouseover="highlightCol(this);" onmouseout="clearHighlights(this);"  onclick="tableInstancePool[\'' + this.name + '\'].delCol(this.parentNode);">X</a>';

			// now add the second row with the select box
			rowCounter++;
			var row = rows[rowCounter];
			var cell = row.insertCell(index + 1);
			cell.innerHTML = dropDown;

		}
	}
	
	this.numCols++;
	this.colCounter++;
	this.renameID();
}

function delRow(rowObject) {
	//if(this.numRows <= 1) deleteTable(this.name);
	//else {
		rowObject.parentNode.parentNode.removeChild(rowObject.parentNode);
		this.numRows--;
		this.renameID();
	//}
}

function delCol(colObject) {
	if(this.numCols <= 1) deleteTable(this.name);
	else {
		var cells = colObject.parentNode.getElementsByTagName("td");
		var c = 0;
		for (c; c < cells.length; c++) if (cells[c] == colObject) break;
		var rows = colObject.parentNode.parentNode.getElementsByTagName("tr");
		for (var r = rows.length - 2; r >= 0; r--) colObject.parentNode.parentNode.rows[r].deleteCell(c);
		this.numCols--;
		this.renameID();
	}
}

function deleteRow(rowNumber) {
	this.numRows--;
	var row = document.getElementById("id_" + this.name + "*tr_" + this.rowCounter);
	row.parentNode.remove(row);
}

function deleteThisTable() {
	numTables--;
	var table = document.getElementById("id_" + this.name);
	var div = table.parentNode.parentNode;
	div.parentNode.removeChild(div);
}

function createTable() {
	var rows = parseInt(document.getElementById("rows").value);
	var cols = parseInt(document.getElementById("cols").value);
	if (isNaN(rows)) rows = 2;
	if (isNaN(cols)) cols = 4;
	var newTable = new table(rows, cols, "tables");
	tableInstancePool[name] = newTable;
}

function deleteTable(tableName) {
	var tableInstance = tableInstancePool[tableName];
	tableInstance.deleteThisTable();
}

function addRowToTable(tableName) {
	var tableInstance = tableInstancePool[tableName];
	tableInstance.addRow();
}

function addColToTable(tableName, index) {
	var tableInstance = tableInstancePool[tableName];
	tableInstance.addCol(index);
}

function renameID(renameLast) {
	var rows = document.getElementById("id_" + this.name).getElementsByTagName("tr");
	
	for (var i = 1; i < rows.length - 1; i++) {
		rows[i].id = "id_" + this.name + "*tr_" + (i - 1);

		cells = rows[i].getElementsByTagName("td");
		for (var j = 1; j < cells.length; j++) {
			cells[j].id = "id_" + this.name + "*tr_" + (i - 2) + "*td_" + (j - 1);
			selectBoxes = cells[j].getElementsByTagName("select");
			if (selectBoxes.length) {
				selectBoxes[0].id = "id_" + this.name + "dropdown_" + (j - 1);
				selectBoxes[0].name = "id_" + this.name + "dropdown_" + (j - 1);
			}
		}
	}
}
//]]>
</script>
</head>
    <body>
        Rows:
        <input id="rows" type="text" value="2" />
        <br />
        Cols:  
        <input id="cols" type="text" value="4" />
        <br />
        <a href="#" onclick="createTable(); return false;">Create Table</a>
        <div id="tables"></div>

    </body>
</html>

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of DarkoLord
DarkoLord
Flag of Slovenia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of dshrenik

ASKER

Not really. When I create a new table, the last row has problems...
If possible, please try to correct this as well:
A row must me deleted only when I click an X, and not anywhere in the cell that holds the X.

Thanks!
I think the attached code takes care of navigation in the last row.

If possible, please address post 34459306.

Thanks!
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>OOP Table Manipulation</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
body, p, td, div { font-family: Calibri, Arial, Tahoma; }

table {
	margin:10px 0;
	border-collapse: collapse;
}

tr { margin-top:2px; }

td {
	margin-left:2px;
	padding: 2px;
}
div.newcol a {
	text-decoration: none;
}
.xmark {
	font-size:14px;
}
.xmark, .pmark, .pRowMark {
	color:#888;
	text-decoration:none;
}
.pmark {
	font-size: 22px;
	margin-left: -8px;
}

.xRowMark, .pRowMark {
	padding-right: 10px;
	margin-left: 65px;
}

.pRowMark {
	font-size: 22px;
	margin-right: -1px;
}

.xTableMark {
	font-size:18px;
	color:#888;
	text-decoration:none;
}

.xmark:hover,
.xTableMark:hover { color:#F00; }

.tableContainer {
	display: inline-block;
	position: relative;
	padding: 0 20px 20px 0;
	overflow: visible;
}

.tableContainer img.button {
	position: absolute;
	z-index: 1000;
}

.tableContainer img.button:hover { cursor: pointer; }

.tableContainer img.newCol {
	top: 60px;
	right: 0px;
	width: 20px;
	height: 20px;
}

.tableContainer img.newRow {
	bottom: 5px;
	right: 100px;
	width: 16px;
	height: 16px;
}

</style>
<script type="text/javascript">
//<![CDATA[
var tableInstancePool = new Array();
var counter = 0;
var numTables = 0;

var dropDown = "<select name='' id='' style='width: 100%'><option value='1'>1</option><option value='2'>2</option><option value='3'>3</option></select>";
//var textBox = "<input type='text'></input>";
var textBox = "<input type='text' onfocus=\"this.style.border='2px solid gray';\" onblur=\"this.style.border='';\"></input>";
var b = "1px solid red";

function move(e, el) {
      var did = el.id;
      var parts = did.split('*');
      var grow = parts[1].split('_');
      var gcol = parts[2].split('_');
      var currow = parseInt(grow[1]);
      var curcol = parseInt(gcol[1]);

var key = (window.event) ? event.keyCode : e.keyCode;

window.status = key;
var newcol = curcol;
var newrow = currow;

var oRows = document.getElementById(parts[0]).getElementsByTagName('tr').length - 1;
var oCols = document.getElementById(parts[0]).getElementsByTagName('tr')[0].getElementsByTagName('td').length - 1;

if (key == 37) { // left arrow
if (curcol > 0) {var newcol = curcol - 1;} else if (currow > 0) {newrow = currow - 1; newcol = oCols - 2;}
} else if (key == 38) { // up arrow
if (currow > 0 ) {var newrow = currow - 1;}
} else if (key == 39) { // right arrow
if (curcol < oCols - 2) {newcol = curcol + 1;} else {newrow = currow + 1; newcol = 0;}
} else if (key == 40) { // down arrow
newrow = currow + 1;
}

var newid = parts[0] + '*tr_' + newrow + '*td_' + newcol;      
var element = document.getElementById(newid);
var inp = element.getElementsByTagName('input');
inp[0].focus();
return false;

}

function highlightRow(cellElem) {

	// Cell that contains the delete link
	var cellElem = cellElem.parentNode;

	// Table that contains the cell
	var tbody = cellElem.parentNode.parentNode;

	// Get row index of current cell
	var rowIndex = -1;
	var rows = tbody.getElementsByTagName("tr");

	outerLoop:
	for(i=0; i<rows.length; i++) {

		var cells = rows[i].getElementsByTagName("td");
		for(j=0; j<cells.length; j++) {

			if(cells[j] == cellElem) {
				rowIndex = i;
				break outerLoop;
			}
		}
	}

	// Highlight all cells in same row
	if(rowIndex > 0) {
		var cells = rows[rowIndex].getElementsByTagName("td");

		cells[1].style.borderLeft = b;
		for(j=1; j<cells.length; j++) {

			cells[j].style.borderTop = b;
			cells[j].style.borderBottom = b;
		}
		cells[cells.length-1].style.borderRight = b;
	}
}

function highlightCol(cellElem) {

	// Cell that contains the delete link
	var cellElem = cellElem.parentNode;

	// Table that contains the cell
	var tbody = cellElem.parentNode.parentNode;

	// Get row index of current cell
	var colIndex = -1;
	var rows = tbody.getElementsByTagName("tr");

	outerLoop:
	for(i=0; i<rows.length; i++) {

		var cells = rows[i].getElementsByTagName("td");
		for(j=0; j<cells.length; j++) {

			if(cells[j] == cellElem) {
				colIndex = j;
				break outerLoop;
			}
		}
	}

	// Highlight all cells in same row
	if(colIndex > 0) {

		rows[1].getElementsByTagName("td")[colIndex].style.borderTop = b;
		for(i=1; i<rows.length - 1; i++) {

			var cell = rows[i].getElementsByTagName("td")[colIndex];

			cell.style.borderLeft = b;
			cell.style.borderRight = b;
		}
		rows[rows.length-2].getElementsByTagName("td")[colIndex].style.borderBottom = b;
	}
}

function highlightTable(tableElem) {

	var tbody = tableElem.parentNode.parentNode.parentNode;

	var rows = tbody.getElementsByTagName("tr");
	for(i=1; i<rows.length - 1; i++) {

		var cells = rows[i].getElementsByTagName("td");
		for(j=1; j<cells.length; j++) {

			if(i==1) cells[j].style.borderTop = b;
			if(j==1) cells[j].style.borderLeft = b;
			if(i==rows.length-2) cells[j].style.borderBottom = b;
			if(j==cells.length-1) cells[j].style.borderRight = b;
		}
	}
}

function clearHighlights(cellElem) {

	// Table that contains the cell
	var tbody = cellElem.parentNode.parentNode.parentNode;
	var cells = tbody.getElementsByTagName("td");
	for(i=0; i<cells.length; i++) {

		cells[i].style.borderLeft = '';
		cells[i].style.borderRight = '';
		cells[i].style.borderTop = '';
		cells[i].style.borderBottom = '';
	}
}

function table(numRows, numCols, parentId) {
	numTables++;
	name = ++counter;
	this.name = name;
	this.numRows = numRows;
	this.numCols = numCols;
	this.parentId = parentId;
	this.rowCounter = numRows;
	this.colCounter = numCols;

	var tableHTML = '<div class="tableContainer"><table id="id_' + name + '">';

	// first row with the table delete button
	tableHTML += '<td align="center" style="color:#F00;"><a href="javascript:void(0);" onmouseover="highlightTable(this);" onmouseout="clearHighlights(this);" class="xTableMark" title="Delete Table" onclick="tableInstancePool[\'' + this.name + '\'].deleteThisTable(this);">X</a><br /><input id="id_' + this.name + '_checkbox_checkboxno" type="checkbox" style="margin-left: 30px; margin-bottom: 5px" checked="checked" /></td>';

	// first row with the col delete buttons
	for (var colCounter = 0; colCounter < numCols; colCounter++) {
		tableHTML += '<td align="center" valign="bottom" style="color:#F00"><div style="float: left"><a class="pmark" href="#" style="text-decoration: none" onclick="tableInstancePool[\'' + this.name + '\'].addCol(this)">+</a></div><a href="#" class="xmark" onmouseover="highlightCol(this);" onmouseout="clearHighlights(this);" onclick="tableInstancePool[\'' + this.name + '\'].delCol(this.parentNode);">X</a></td>';
	}
	
	// add the last col delete button
	tableHTML += '<td align="center" valign="bottom" style="color:#F00"><div style="float: left"><a class="pmark" href="#" style="text-decoration: none" onclick="tableInstancePool[\'' + this.name + '\'].addCol(this)">+</a></div>';
	
	
	tableHTML += '</tr>';

	// second row with select boxes
	tableHTML += '<tr><td>&nbsp;</td>'; // no delete button on this row
	for (var colCounter = 0; colCounter < numCols; colCounter++) {
		tableHTML += '<td>' + dropDown + '</td>';
	}
	tableHTML += '</tr>';

	// remaining rows with input fields
	for (var rowCounter = 0; rowCounter < numRows; rowCounter++) {
		tableHTML += '<tr id="">';
		tableHTML += '<td align="right" style="color:#F00"><a href="#" class="xmark xRowMark" onmouseover="highlightRow(this);" onmouseout="clearHighlights(this);" onclick="tableInstancePool[\'' + this.name + '\'].delRow(this.parentNode);">X</a></td>';
		for (var colCounter = 0; colCounter < numCols; colCounter++) {
			tableHTML += '<td id="" onkeyup="move(event,this);">' + textBox + '</td>';
		}
		tableHTML += '</tr>';
	}
	
	var container = document.createElement("div");
	container.innerHTML = tableHTML;
	document.getElementById(parentId).appendChild(container);	
	
	addLastRow(this);
	this.renameID();
	
	var firstTextbox = document.getElementById("id_"+ name + "*tr_0*td_0");
	var inp = firstTextbox.getElementsByTagName('input');
	inp[0].focus();
}

table.prototype.addRow = addRow;
table.prototype.deleteRow = deleteRow;
table.prototype.deleteThisTable = deleteThisTable;
table.prototype.addCol = addCol;
table.prototype.delCol = delCol;
table.prototype.delRow = delRow;
table.prototype.renameID = renameID;

function addRow() {
	tableHTML = '<td align="right" style="color:#736F6E;"><a href="#" class="xmark xRowMark" onmouseover="highlightRow(this);" onmouseout="clearHighlights(this);" onclick="tableInstancePool[\'' + this.name + '\'].delRow(this.parentNode);">X</a></td>';
	for (var colCounter = 0; colCounter < this.numCols; colCounter++) {
		tableHTML += "<td onkeyup='move(event,this);'>" + textBox + "</td>";
	}

	this.rowCounter++;
	this.numRows++;
	var table = document.getElementById("id_" + this.name);
	table = table.getElementsByTagName("TBODY")[0];
	// add a new row to the table, and insert the cells we've just written
	rowElement = document.createElement('tr');
	
	// remove the last row so it can be readded later
	var last = document.getElementById("lastRow_" + this.name);
	if (last != null) table.removeChild(last);
	newRow = table.appendChild(rowElement);
	newRow.innerHTML = tableHTML;
	addLastRow(this);
	this.renameID(this);
}

function addLastRow(currentTable) {
	var lastRow = '<td align="right" style="margin-top: -2px"><a class="pRowMark" href="#" style="text-decoration: none" onclick="tableInstancePool[\'' + currentTable.name + '\'].addRow(this)">+</a></td><td colspan="20" />';
	var table = document.getElementById("id_" + currentTable.name);
	table = table.getElementsByTagName("TBODY")[0];
	rowElement = document.createElement('tr');
	rowElement.id = "lastRow_" + currentTable.name;
	newRow = table.appendChild(rowElement);
	newRow.innerHTML = lastRow;
}

function addCol(row_link) {
	index = row_link.parentNode.parentNode.cellIndex-1;
	if (index == null) { index=this.numCols; }
	var table = document.getElementById("id_" + this.name);
	var rows = table.rows;
	var delCrossAdded = false;
	
	for (var rowCounter = 0; rowCounter < this.numRows + 2; rowCounter++) {
		var row = rows[rowCounter];
		var cell = row.insertCell(index + 1);
		if (delCrossAdded) {
			cell.id = "";
			cell.innerHTML = textBox;
			cell.setAttribute("onkeyup","move(event,this);");
		} else {
			delCrossAdded = true;
			cell.setAttribute("align", "center");
			cell.setAttribute("valign", "bottom");
			cell.setAttribute("style", "color:#F00");
			cell.innerHTML = '<div style="float: left"><a class="pmark" href="#" style="text-decoration: none" onclick="tableInstancePool[\'' + this.name + '\'].addCol(this)">+</a></div><a href="#" class="xmark" onmouseover="highlightCol(this);" onmouseout="clearHighlights(this);"  onclick="tableInstancePool[\'' + this.name + '\'].delCol(this.parentNode);">X</a>';

			// now add the second row with the select box
			rowCounter++;
			var row = rows[rowCounter];
			var cell = row.insertCell(index + 1);
			cell.innerHTML = dropDown;

		}
	}
	
	this.numCols++;
	this.colCounter++;
	this.renameID();
}

function delRow(rowObject) {
	//if(this.numRows <= 1) deleteTable(this.name);
	//else {
		rowObject.parentNode.parentNode.removeChild(rowObject.parentNode);
		this.numRows--;
		this.renameID();
	//}
}

function delCol(colObject) {
	if(this.numCols <= 1) deleteTable(this.name);
	else {
		var cells = colObject.parentNode.getElementsByTagName("td");
		var c = 0;
		for (c; c < cells.length; c++) if (cells[c] == colObject) break;
		var rows = colObject.parentNode.parentNode.getElementsByTagName("tr");
		for (var r = rows.length - 2; r >= 0; r--) colObject.parentNode.parentNode.rows[r].deleteCell(c);
		this.numCols--;
		this.renameID();
	}
}

function deleteRow(rowNumber) {
	this.numRows--;
	var row = document.getElementById("id_" + this.name + "*tr_" + this.rowCounter);
	row.parentNode.remove(row);
}

function deleteThisTable() {
	numTables--;
	var table = document.getElementById("id_" + this.name);
	var div = table.parentNode.parentNode;
	div.parentNode.removeChild(div);
}

function createTable() {
	var rows = parseInt(document.getElementById("rows").value);
	var cols = parseInt(document.getElementById("cols").value);
	if (isNaN(rows)) rows = 2;
	if (isNaN(cols)) cols = 4;
	var newTable = new table(rows, cols, "tables");
	tableInstancePool[name] = newTable;
}

function deleteTable(tableName) {
	var tableInstance = tableInstancePool[tableName];
	tableInstance.deleteThisTable();
}

function addRowToTable(tableName) {
	var tableInstance = tableInstancePool[tableName];
	tableInstance.addRow();
}

function addColToTable(tableName, index) {
	var tableInstance = tableInstancePool[tableName];
	tableInstance.addCol(index);
}

function renameID(renameLast) {
	var rows = document.getElementById("id_" + this.name).getElementsByTagName("tr");
	
	for (var i = 1; i < rows.length - 1; i++) {
		rows[i].id = "id_" + this.name + "*tr_" + (i - 1);

		cells = rows[i].getElementsByTagName("td");
		for (var j = 1; j < cells.length; j++) {
			cells[j].id = "id_" + this.name + "*tr_" + (i - 2) + "*td_" + (j - 1);
			selectBoxes = cells[j].getElementsByTagName("select");
			if (selectBoxes.length) {
				selectBoxes[0].id = "id_" + this.name + "dropdown_" + (j - 1);
				selectBoxes[0].name = "id_" + this.name + "dropdown_" + (j - 1);
			}
		}
	}
}
//]]>
</script>
</head>
    <body>
        Rows:
        <input id="rows" type="text" value="2" />
        <br />
        Cols:  
        <input id="cols" type="text" value="4" />
        <br />
        <a href="#" onclick="createTable(); return false;">Create Table</a>
        <div id="tables"></div>

    </body>
</html>

Open in new window

Also, if possible, please add a bit of documentation to your code. Thanks!
Not sure what do you mean... Can you explain it a bit more (possibly with a screenshot)?
Well, what I mean is when U click in the gap between an X mark to delete row and the first text box of the row, the row is getting deleted

Instead, I want the row to get deleted only when I click exactly on the X mark
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thank you so much!

If possible, please add some documentation to the code (every function of code that you are sur of, and also the user defined names in the CSS.

Please answer it here:
https://www.experts-exchange.com/questions/26711099/Documentation-to-code.html

Thanks! :)
*every function  that you are sure of