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.
- 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; } - Table elements have an
insertRow()method, which takes one argument: the position at which to insert the row. Thethead,tbody, andtfootelements also have this method, so ouraddRowfunction above can take theidof any of the element types as the first argument. The method inserts an empty row which we then can fill with cells. - Table rows have an
insertCell()method. It also takes one argument: the position at which to insert the cell. The inserted cell is empty. OuraddRowfunction above populates the cells from the elements in the passed-in cells array. - We have also created a helper function for deleting rows:
It uses thefunction 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 } }deleteRow()method oftable,thead,tbody, andtfootelements to remove the row. If the passed-inrowNumberdoesn't exist, the function fails silently by returning false. - The following shows an example of this code in use:
This code renders the following:<!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>
Note that you must have the associated files to run with this code for it to display correctly.
