Mike wrote:
My page populates a table with a list of names and other
information from a JavaScript object. I receive changes (adds,
change & delete) to that list, convert it into a JavaScript
object. I do understand how to add the new names to the list.
So you are after a tutorial on manipulation of tables?
I have 3 questions:
1) How can I search through the table rows to find the rows
to be changed or removed?
Presumably each record in your object has a key? Put the key as
the id of the table row that the record is displayed in. When
adding or removing elements in your object, do the same to the
table.
If you have a row with id="row06":
<tr id="row06"> ... </tr>
a reference to the row can be found by:
var rowRef = document.getElementById('row06');
Code below includes support for document.all for IE 5 (& 4?).
2) How can I resort the table, so the names continue to
appear in alphabetical order.
I would keep rows sorted by keeping the records in the object
sorted. Then whatever was done to the object, do to the table.
if the table is small, you could perhaps re-draw it each time.
But if it's more than say 1 screen, do it by rows. Presumably
you only change one row at a time, or the whole lot in one go?
To delete a table row, use:
rowRef.parentNode.removeChild(rowRef);
You can also add an onclick to the row to make it remove itself
(then replicate the removal in your object).
3) How can change or remove data in the cells, once I've
found ...
Changing data in the cells can be done very easily with
innerHTML or with marginally more effort DOM. The DOM method is
likely better since it is part of the W3C specification,
innerHTML isn't (and probably never will be).
With innerHTML, the text entered is interpreted, so if the user
enters HTML markup, it is parsed and displayed so:
<b>hi</b>
will display 'hi' in bold. The DOM method will show the
characters entered ('<b>hi</b>'). This likely makes it not
suitable for a web application unless you intend parsing the
text entered... I think DOM is better. e.g. suppose the user
enters:
<span onclick="alert('hi');">here is a lot of text</span>
Now when they click on the cell, an alert pops up with 'hi'.
Once you have a reference to the row, the cells can be accessed
as a collection:
var theCells = rowRef.cells
But that doesn't work in Safari 1.0.3 (it may be fixed in later
versions) so I've used:
var theCells = rowRef.cells;
if (!theCells[0]) theCells = rowRef.childNodes;
Safari creates the collection, but for some reason, you can't
access it. The childNodes method is equivalent in this case
(for Safari only, Firefox barfs on it).
The code below shows manipulation using both innerHTML and DOM.
It is heavily commented, hopefully it's understandable.
Have fun...
<html><head><title>table play</title>
<style type="text/css">
td {width: 150px; border: 1px solid blue;}
</style>
<script type="text/javascript">
// This method gets passed a reference to the cell to change.
function changeCellInner(x) {
var newText = prompt('Enter new text: ','');
x.innerHTML = (newText == '')?'<i>No entry</i>':newText;
}
// This method gets passed a reference to the cell to change.
function changeCellDOM(x) {
var newText = prompt('Enter new text: ','');
// Create a new text node
var textNode = document.createTextNode(newText);
// textNodes have no style attribute, so must wrap
// in something. Manipulating the TD style is OK, but creates
// logic issues so use a span to wrap the text node
var spanNode = document.createElement('span');
spanNode.appendChild(textNode);
// If no text entered at prompt, deal with it
if (newText == '') {
textNode.data = 'No entry';
spanNode.style.fontStyle = 'italic';
}
// Delete everything in the cell
while (x.childNodes.length > 0) {
x.removeChild(x.childNodes[0]);
}
// Add the span (& hence text node) to the cell
x.appendChild(spanNode);
}
// calls innerHTML method:
function changeCell0(r,c) {
if (document.getElementById) {
var rowRef = document.getElementById(r);
} else if (document.all) {
var rowRef = document.all[r];
}
var theCells = rowRef.cells;
if (!theCells[0]) theCells = rowRef.childNodes;
changeCellInner(theCells[c])
}
// calls DOM method:
function changeCell1(r,c) {
if (document.getElementById) {
var rowRef = document.getElementById(r);
} else if (document.all) {
var rowRef = document.all[r];
}
var theCells = rowRef.cells;
if (!theCells[0]) theCells = rowRef.childNodes;
changeCellDOM(theCells[c]);
}
</script>
</head>
<body>
<table>
<tr id="row0">
<td>row 0 cell 0</td>
<td>row 0 cell 1</td>
<td onclick="changeCellInner(this)">row 0 cell 2</td>
</tr>
<tr id="row1" onclick="
alert('About to delete ' + this.id);
this.parentNode.removeChild(this);">
<td>row 1 cell 0</td>
<td>row 1 cell 1</td>
<td onclick="changeCell(this)">row 1 cell 2</td>
</table>
<button onclick="
var rowRef = document.getElementById('row0');
alert('About to delete ' + rowRef.id);
rowRef.parentNode.removeChild(rowRef);
">Delete row 0</button>
<br>
<button onclick="changeCell0('row0','0');
">Change row 0 cell 0 (innerHTML)</button>
<button onclick="changeCell1('row0','1');
">Change row 0 cell 1 (DOM)</button>
</body>
</html>
--
Fred