Link to home
Create AccountLog in
Avatar of dshrenik
dshrenikFlag for United States of America

asked on

Resize column size of a table

The attached code allows the user to create tables and navigate through them using arrow keys.

Can anybody give me the code to a function that will allow the user to resize columns by dragging on the column border, just like how its done in Excel?

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 {
	color:#888;
	text-decoration:none;
}
.pmark {
	font-size: 22px;
	margin-left: -8px;
}

.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: 149px'><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='3px solid gray';\" onblur=\"this.style.border='1px inset';\"></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();

}

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; i++) {

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

			cell.style.borderLeft = b;
			cell.style.borderRight = b;
		}
		rows[rows.length-1].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; 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-1) 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;" 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>';
	}
	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" 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>';
	}
	tableHTML += '</table><img src="http://www.ict7.com/images/RightArrow2HS.png" class="newCol button" title="New Column" onclick="addColToTable(\''+ this.name +'\');" /><img src="http://confluence.atlassian.com/download/attachments/18579599/arrow_down_blue.gif" class="newRow button" title="New Row" onclick="addRowToTable(\''+ this.name +'\');" /></div>';

	var container = document.createElement("div");
	container.innerHTML = tableHTML;
	document.getElementById(parentId).appendChild(container);
	this.renameID();
}

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" 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');
	newRow = table.appendChild(rowElement);
	newRow.innerHTML = tableHTML;
	this.renameID();
}

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 - 1; 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() {
	var rows = document.getElementById("id_" + this.name).getElementsByTagName("tr");
	for (var i = 1; i < rows.length; 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

Avatar of hpierson
hpierson

You realize that in Excel, the column borders are visible.

The cell borders are NOT visible in your tables. All that is visible is the border of the input text boxes, which are inside the cells.
Avatar of dshrenik

ASKER

Yes. But, is it possible to drag the border of a text box or a dropdown menu?
Or can we have an imaginary border around the cells that are draggable and cause the column width to change?
SOLUTION
Avatar of hpierson
hpierson

Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
You might consider small icons over each column with a plus and a minus, which will increase or decrease the width of the column each time they are clicked, lets say 10 pixels at a time

something like  <-->  and --><--

Well, we can the imaginary border right outside the drop down menu's border right?
This way, they will be under the impression that dragging the border of the dropdown menu is doing the job...
why don't you make that change (put in a border in the top row) and make sure it is what you want.

It's difficult enough to drag a cell/column when you can see the border. You can't possibly drag something you can't see
I don't want put in something visible, since that will spoil the look of the table.

If we can have a imaginary border, or a tiny imaginary object, and have the mouse pointer change to suggest that it can be dragged, that will be great!
Please use this code:
<style type="text/css">
body, p, td, div { font-family: Calibri, Arial, Tahoma; } /* Set the text in most tags to Calibri... */

table {
	margin:10px 0;
	border-collapse: collapse; /* http://www.w3schools.com/css/pr_tab_border-collapse.asp */
}

tr { margin-top:2px; }

td {
	margin-left:2px;
	padding: 2px;
}
div.newcol a {
	text-decoration: none; /* turn off underlines for links in divs with className=newcol */
}
.xmark {
	font-size:14px;
}
.xmark, .pmark, .pRowMark { /* turn off underlines for className=xmar, pmark or pRowMark and give the text the color 888888 */
	color:#888;
	text-decoration:none; 
}
.pmark {
	font-size: 22px;
	margin-left: -8px;
}

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

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

.xTableMark { /* turn off underlines for className=xmark, pmark or pRowMark and give the text the color 888888 and change the font-size. This could have been included above with xmark */
	font-size:18px;
	color:#888;
	text-decoration:none;
}

.xmark:hover,
.xTableMark:hover { color:#F00; } /* change color on hovering over elements with className xmark or xTableMark */

.tableContainer {
	display: inline-block; /* http://www.w3schools.com/css/pr_class_display.asp */
	position: relative;
	padding: 0 20px 20px 0;
	overflow: visible;
}

.tableContainer img.button { /* image with className butto in tableContainer should be posisition absolutely and on top of other stuff */
	position: absolute;
	z-index: 1000;
}

.tableContainer img.button:hover { cursor: pointer; } /* change the cursor to a hand on hover */

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

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

</style>

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Michel Plungjan
Michel Plungjan
Flag of Denmark image

Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
Please give the examples...
SOLUTION
Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account