How to Create a Navigable Table with Ajax

See Ajax: Tips and Tricks for similar articles.

Google Maps (http://maps.google.com) was one of the applications that brought so much attention to Ajax. One of the cool things about it is that it allows the user to drag maps around the screen seamlessly loading new sections. It does this by preloading the sections around the map that the user is likely to drag on to the screen. This same concept can be applied to other applications, such as navigable tables. Learn how to create a navigable table with Ajax in the following steps.

For these examples to work, more files are required than are available in this how to. To see these examples in action, take the Ajax training course.

  1. There are table-specific methods for adding rows and cells. The helper functions shown below makes use of these:
    function addRow(tableId, cells){
    	var tableElem = document.getElementById(tableId);
    	var newRow = tableElem.insertRow(tableElem.rows.length);
    	var newCell;
    	for (var i = 0; i < cells.length; i++) {
    		newCell = newRow.insertCell(newRow.cells.length);
    		newCell.innerHTML = cells[i];
    	}
    	return newRow;
    }
  2. Table elements have an insertRow() method, which takes one argument: the position at which to insert the row. The thead, tbody, and tfoot elements also have this method, so our addRow function above can take the id of any of the element types as the first argument. The method inserts an empty row which we then can fill with cells.
  3. Table rows have an insertCell() method. It also takes one argument: the position at which to insert the cell. The inserted cell is empty. Our addRow function above populates the cells from the elements in the passed-in cells array.
  4. We have also created a helper function for deleting rows:
    function deleteRow(tableId, rowNumber){
    	var tableElem = document.getElementById(tableId);
    	if (rowNumber >= 0 && rowNumber < tableElem.rows.length) {
    		tableElem.deleteRow(rowNumber);
    		return true;
    	} else {
    	return false; //no row to delete
    	}
    }
    It uses the deleteRow() method of table, thead, tbody, and tfoot elements to remove the row. If the passed-in rowNumber doesn't exist, the function fails silently by returning false.
  5. The following shows an example of this code in use:
    <!DOCTYPE HTML>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Table Rows</title>
    <link href="TableRows.css" type="text/css" rel="stylesheet">
    <script type="text/javascript" src="lib.js"></script>
    <script type="text/javascript">
    	var tableConfig = {
    		rowsToShow: 2,
    		totalRows: 10 //this number would normally be retrieved from the server
    	}
    
    	function prevRows() {
    		var curRow = Number(document.getElementById("CurRowStart").innerHTML);
    		getRows(curRow - tableConfig.rowsToShow, "prev");
    	}
    
    	function nextRows() {
    		var curRow = Number(document.getElementById("CurRowStart").innerHTML);
    		getRows(curRow + tableConfig.rowsToShow, "next");
    	}
    
    	function getRows(curRow, rowSource) {
    		var slideImage = document.getElementById("CurSlideImage");
    		var curRowStart = document.getElementById("CurRowStart");
    		var curRowEnd = document.getElementById("CurRowEnd");
    		var btnPrev = document.getElementById("PrevButton");
    		var btnNext = document.getElementById("NextButton");
    		var prevTbody = document.getElementById("PrevRows");
    		var nextTbody = document.getElementById("NextRows");
    		var curTbody = document.getElementById("CurRows");
    		var rowsToShow = tableConfig.rowsToShow;
    		var totalRows = tableConfig.totalRows;
    		var xmlhttp;
    
    		btnPrev.disabled = true;
    		btnNext.disabled = true;
    
    		if (rowSource == "prev") {
    			for (var i = curTbody.rows.length - 1; i >= 0; i--) {
    				curTbody.replaceChild(prevTbody.rows[i], curTbody.rows[i]);
    				deleteRow("NextRows", i);
    			}
    			curRowStart.innerHTML = curRow;
    			curRowEnd.innerHTML = curRow + rowsToShow - 1;
    			message("Loading from Prev");
    		} else if (rowSource == "next") {
    			for (var i = curTbody.rows.length - 1; i >= 0; i--) {
    				curTbody.replaceChild(nextTbody.rows[i], curTbody.rows[i]);
    				deleteRow("PrevRows", i);
    			}
    			curRowStart.innerHTML = curRow;
    			curRowEnd.innerHTML = curRow + rowsToShow - 1;
    			message("Loading from Next");
    		}
    		
    		url = "TableRows?Row=" + curRow + "&RowsToShow=" + rowsToShow;
    		xmlhttp = new XMLHttpRequest();
    		xmlhttp.open("get", url, true);
    
    		xmlhttp.onreadystatechange = function() {
    			if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
    				changeRows(xmlhttp);
    			}
    		}
    		xmlhttp.send(null);
    
    		function changeRows(xmlhttp) {
    			var docElem = xmlhttp.responseXML.documentElement;
    			var lastSetStart = totalRows - rowsToShow + 1;
    			var prevRowPos = (curRow == 1) ? null : 0;
    			var curRowPos = (curRow == 1) ? 0 : rowsToShow;
    			var nextRowPos = (curRow == 1) ? rowsToShow :
    				(curRow >= lastSetStart) ? null : 2 * rowsToShow;
    
    			removeWhitespace(docElem, true);
    
    			if (prevRowPos !== null) {
    				loadRows("Prev", prevRowPos, docElem);
    				btnPrev.disabled = false;
    			}
    
    			if (nextRowPos !== null) {
    				loadRows("Next", nextRowPos, docElem);
    				btnNext.disabled = false;
    			}
    
    			if (rowSource == "ajax") {
    				loadRows("Cur", curRowPos, docElem);
    				message("Loading from Ajax");
    			}
    
    			curRowStart.innerHTML = curRow;
    			curRowEnd.innerHTML = curRow + rowsToShow - 1;
    
    		}
    	}
    
    	function loadRows(rowset, startRow, docElem) {
    		var endRow = startRow + tableConfig.rowsToShow - 1;
    		var tbodyId = rowset + "Rows";
    		var cells = [],
    			row, cellText;
    		var rowLength = docElem.firstChild.childNodes.length;
    		var htmlRow;
    		for (var i = startRow; i <= endRow; i++) {
    			row = docElem.childNodes[i];
    			for (var j = 0; j < rowLength; j++) {
    				if (row) {
    					cellNode = row.childNodes[j];
    					cellText = cellNode.firstChild.nodeValue;
    					if (cellNode.nodeName == "Image") {
    						cellText = "<img src='Images/" + cellText + "'>";
    					}
    				} else {
    					cellText = "";
    				}
    				cells.push(cellText);
    			}
    			htmlRow = addRow(tbodyId, cells);
    			if (!row) htmlRow.style.display = "none";
    			cells = [];
    		}
    	}
    
    	function message(msg) {
    		var output = document.getElementById("Message");
    		output.innerHTML = msg;
    	}
    
    	observeEvent(window, "load", function() {
    		var btnPrev = document.getElementById("PrevButton");
    		var btnNext = document.getElementById("NextButton");
    		var totalRows = tableConfig.totalRows;
    		observeEvent(btnPrev, "click", prevRows);
    		observeEvent(btnNext, "click", nextRows);
    		document.getElementById("TotalRowsNum").innerHTML = totalRows;
    		getRows(1, "ajax");
    	});
    </script>
    </head>
    
    <body>
    <h1>First 10 Presidents</h1>
    <table id="Table">
    	<thead>
    		<tr>
    			<th>President</th>
    			<th>Years</th>
    			<th>Image</th>
    		</tr>
    	</thead>
    	<tbody id="PrevRows"></tbody>
    	<tbody id="CurRows"></tbody>
    	<tbody id="NextRows"></tbody>
    	<tfoot>
    		<tr>
    			<td colspan="3">
    				<button id="PrevButton">Previous</button>
    				Rows <span id="CurRowStart">1</span> - <span id="CurRowEnd"></span> of <span id="TotalRowsNum"></span>
    				<button id="NextButton">Next</button>
    			</td>
    		</tr>
    		<tr>
    			<td colspan="3" id="Message"></td>
    		</tr>
    	</tfoot>
    </table>
    </body>
    </html>
    This code renders the following: Table Rows Note that you must have the associated files to run with this code for it to display correctly.

Related Articles

  1. How to Make a Cross-origin Ajax Request
  2. How to Create a Login Form with Ajax
  3. How to Set Up Automatic Session Timeout with Ajax
  4. How to Use the Callback Function in Ajax
  5. How to Develop a Web Application with Ajax
  6. How to Make GET, POST, and HEAD Requests Using Ajax
  7. How to Use the jQuery ajax() Method
  8. How to Create a Lookup Form with Ajax
  9. How to Create a Slideshow with Ajax
  10. How to Handle the Response from the Server in Ajax
  11. How to Set Up for Ajax Training on Windows
  12. Inline Editing Using Ajax
  13. How to Create a Navigable Table with Ajax (this article)