:)Chapter 12 sorting tables examples doesn't handle nested <input> boxes. If you create editable tables using <input type="text"> you need to go deeper into the dom. Additionally, the current sort routine only sorts a column once, subsequent column selections only REVERSE the current display order. If you enable changes to a given column and click the column expecting a new sort you will find that sorting will occur according to the first sorted positions and not the new values.
Below are changes to the example code that allow changes to the displayed values via nested <input> tags and a new sort for every column selection , still preserving the ascending / descending toggle.
I added an additional function call to pull the value from any given column and row in the array. This allows for a quick test to determine if the column is currently in ascending or descending order
(most of the time, the exception being that an initial random ordering may produce an ascending or descending initial sort.).
The following code was tested only on IE6, but meets my needs for inclusion in autogenerated header/detail tables directly from a database using Cold Fusion or .Net2.0.
================ Modified Code =====================
<html>
<head>
<title>Table Sort Example</title>
<script type="text/javascript">
function convert(sValue, sDataType) {
switch(sDataType) {
case "int":
return parseInt(sValue);
case "float":
return parseFloat(sValue);
case "number":
return parseFloat(sValue);
case "num":
return parseFloat(sValue);
case "date":
return new Date(Date.parse(sValue));
default:
return sValue.toString();
}
}
function generateCompareTRs(iCol, sDataType) {
return function compareTRs(oTR1, oTR2) {
var vValue1, vValue2;
if (oTR1.cells[iCol].getAttribute("value")) {
vValue1 = convert(oTR1.cells[iCol].getAttribute("value"),
sDataType);
vValue2 = convert(oTR2.cells[iCol].getAttribute("value"),
sDataType);
}
else if(oTR1.cells[iCol].firstChild.nodeValue) {
vValue1 = convert(oTR1.cells[iCol].firstChild.nodeValue,
sDataType);
vValue2 = convert(oTR2.cells[iCol].firstChild.nodeValue,
sDataType);
}
else {
vValue1 = convert(oTR1.cells[iCol].firstChild.getAttribute("value"),
sDataType);
vValue2 = convert(oTR2.cells[iCol].firstChild.getAttribute("value"),
sDataType);
}
if (vValue1 < vValue2) {
return -1;
} else if (vValue1 > vValue2) {
return 1;
} else {
return 0;
}
};
}
function sortTable(sTableID, iCol, sDataType) {
var oTable = document.getElementById(sTableID);
var oTBody = oTable.tBodies[0];
var colDataRows = oTBody.rows;
var aTRs = new Array;
for (var i=0; i < colDataRows.length; i++) {
aTRs[i] = colDataRows[i];
}
//rVal = aTRs

.cells[2].firstChild.getAttribute("value");
//alert(rVal + " Datatype = " + sDataType);
if (oTable.sortCol == iCol) {
// We need to sort always and then set to the reverse order
// that the column is in. So get the first value then sort so that
// the new value does not equal the incoming first. this preserves the
// toggle action
curVal = getValByColumn(aTRs, 0, iCol);
// Perform the sort and test for ordering
aTRs.sort(generateCompareTRs(iCol, sDataType));
if (getValByColumn(aTRs, 0, iCol) == curVal){
aTRs.reverse();}
}
else {
aTRs.sort(generateCompareTRs(iCol, sDataType));
}
var oFragment = document.createDocumentFragment();
for (var i=0; i < aTRs.length; i++) {
oFragment.appendChild(aTRs[i]);
}
oTBody.appendChild(oFragment);
oTable.sortCol = iCol;
}
function getValByColumn(aR, iRow, iCol)
{
var colVal = "";
if (aR[iRow].cells[iCol].getAttribute("value")) {
colVal = aR[iRow].cells[iCol].getAttribute("value");
}
else if(aR[iRow].cells[iCol].firstChild.nodeValue) {
colVal = aR[iRow].cells[iCol].firstChild.nodeValue;
}
else {
colVal = aR[iRow].cells[iCol].firstChild.getAttribute("value");
}
return colVal;
}
</script>
</head>
<body>
<p>Click on the table header to sort.</p>
<table border="1" id="tblSort">
<thead>
<tr>
<th onClick="sortTable('tblSort', 0)" style="cursor:pointer">Type</th>
<th onClick="sortTable('tblSort', 1)" style="cursor:pointer">Filename</th> <th onClick="sortTable('tblSort', 2, 'int')" style="cursor:pointer">Seq Num</th>
</tr>
</thead>
<tbody>
<tr>
<td value="doc"><img src="images/wordicon.gif"/></td>
<td>My Resume.doc</td>
<td><input type="text" value="1"
onDblClick="javascript
:alert(this.value);"></input></td>
</tr>
<tr>
<td value="xls"><img src="images/excelicon.gif"/></td>
<td>Fall Budget.xls</td>
<td><input type="text" value="2"
onDblClick="javascript
:alert(this.value);"></input></td>
</tr>
<tr>
<td value="pdf"><img src="images/acrobaticon.gif"/></td>
<td>How to be a better programmer.pdf</td>
<td><input type="text" value="3"
onDblClick="javascript
:alert(this.value);"></input></td>
</tr>
<tr>
<td value="doc"><img src="images/wordicon.gif"/></td>
<td>My Old Resume.doc</td>
<td><input type="text" value="4"
onDblClick="javascript
:alert(this.value);"></input></td>
</tr>
<tr>
<td value="txt"><img src="images/notepadicon.gif"/></td>
<td>Notes from Meeting.txt</td>
<td><input type="text" value="5"
onDblClick="javascript
:alert(this.value);"></input></td>
</tr>
<tr>
<td value="zip"><img src="images/zippedfoldericon.gif"/></td>
<td>Backups.zip</td>
<td><input type="text" value="6"
onDblClick="javascript
:alert(this.value);"></input></td>
</tr>
<tr>
<td value="xls"><img src="images/excelicon.gif"/></td>
<td>Spring Budget.xls</td>
<td><input type="text" value="7"
onDblClick="javascript
:alert(this.value);"></input></td>
</tr>
<tr>
<td value="doc"><img src="images/wordicon.gif"/></td>
<td>Job Description - Web Designer.doc</td>
<td><input type="text" value="8"
onDblClick="javascript
:alert(this.value);"></input></td>
</tr>
<tr>
<td value="pdf"><img src="images/acrobaticon.gif"/></td>
<td>Saved Web Page.pdf</td>
<td><input type="text" value="16"
onDblClick="javascript
:alert(this.value);"></input></td>
</tr>
<tr>
<td value="doc"><img src="images/wordicon.gif"/></td>
<td>Chapter 1.doc</td>
<td><input type="text" value="9"
onDblClick="javascript
:alert(this.value);"></input></td>
</tr>
</tbody>
</table>
</body>
</html>