IE bug with removeChild 
November 8th, 2005, 01:05 AM
| | | IE bug with removeChild
I have the following code (modified) from RobG on this newsgroup...
function moveColumn(table_id,col_id, dir)
{
var table=document.getElementById(table_id);
var idx=GetCellIndex(col_id,table);
var numcols=table.rows[0].cells.length;
var fIdx;
fIdx = (dir=="left")? (idx-1) : (idx+1);
if (fIdx < 0) fIdx=numcols-1;
if (fIdx == numcols) fIdx=0;
var j=table.rows.length;
while (j--) {
var row = table.rows[j];
var x = row.removeChild(row.cells[idx]);
row.insertBefore(x, row.cells[fIdx]);
}
}
The intent, of course, is to swap 2 columns in a table.
Works like a charm in FF 1.x
But in IE when I pass in the second-to-last column in the table with a
direction of "right" to swap it with the last column, the removeChild
removes the bottom-right cell in the table and seems to return null
because I get that yellow error thingy in IE and the script aborts.
Is this a IE bug? Is there a workaround?
Thanks | 
November 8th, 2005, 02:45 AM
| | | Re: IE bug with removeChild
VA wrote:[color=blue]
> I have the following code (modified) from RobG on this newsgroup...[/color]
Unfortunately you combined the logic for swapping and moving - they are
different things. You have tried to bundle it all into one function,
which I suppose is OK but makes it less re-usable.
[color=blue]
>
> function moveColumn(table_id,col_id, dir)
> {
> var table=document.getElementById(table_id);
> var idx=GetCellIndex(col_id,table);[/color]
Presumably GetCellIndex() returns the index of the column to move:
function GetCellIndex(id, table)
{
var cells = table.rows[0].cells;
var i = cells.length;
while ( i-- ){
if ( cells[i].id && id == cells[i].id ){
return i;
}
}
return null;
}
The following line should be added to moveColumn just after the call to
GetCellIndex() (in case the id can't be found):
if (null == idx) return;
[color=blue]
>
> var numcols=table.rows[0].cells.length;
> var fIdx;
> fIdx = (dir=="left")? (idx-1) : (idx+1);
> if (fIdx < 0) fIdx=numcols-1;
> if (fIdx == numcols) fIdx=0;
> var j=table.rows.length;
> while (j--) {
> var row = table.rows[j];
> var x = row.removeChild(row.cells[idx]);
> row.insertBefore(x, row.cells[fIdx]);[/color]
What happens here is that you remove cell 3, then try to insert before
cell 3 which no longer exists in the table (it's in limbo).
The logic for moving left or right is different when you wrap around -
so remove the cell to move (cell[idx]), then look ahead to see if
there's a cell at the destination index (fIdx). If there is, insert the
removed cell immediately before it.
If there's no cell at the destination index, insert the removed cell
before the nextSibling of the one to the left (fIdx-1). There wont be a
nextSibling but that's OK, the cell will simply be appended to the end
of the row.
e.g. if there are 4 cells in the row and cell 0 is removed, there are
only 3 left (0 to 2 inclusive). So insert the removed cell before the
nextSibling of cell 2 (which just it as cell 3).
Replace the line above with:
if (row.cells[fIdx]) {
row.insertBefore(x, row.cells[fIdx])
} else {
row.insertBefore(x, row.cells[fIdx-1].nextSibling);
}
[...]
Here's a working example:
<script type="text/javascript">
function moveColumn(table_id, col_id, dir)
{
var table = document.getElementById(table_id);
var idx = GetCellIndex(col_id, table);
if (null == idx) return;
var numcols=table.rows[0].cells.length;
var fIdx;
fIdx = (dir=="left")? (idx-1) : (idx+1);
if (fIdx < 0) fIdx=numcols-1;
if (fIdx == numcols) fIdx=0;
var j=table.rows.length;
while (j--) {
var row = table.rows[j];
var x = row.removeChild(row.cells[idx]);
if (row.cells[fIdx] ){
row.insertBefore(x, row.cells[fIdx])
} else {
row.insertBefore(x,row.cells[fIdx-1].nextSibling);
}
}
}
function GetCellIndex(id, table)
{
var cells = table.rows[0].cells;
var i = cells.length;
while ( i-- ){
if ( cells[i].id && id == cells[i].id ){
return i;
}
}
return null;
}
</script>
<form action="">
<input type="button" value="Move C right" onClick="
moveColumn('tableA','ENAME','right');
"><br>
<input type="button" value="Move D left" onClick="
moveColumn('tableA','EMPNO','left');
"><br>
</form>
<table id="tableA" cellpadding="5" border="1" cellspacing="5"
summary="0">
<tr><th id="JOB">JOB A</th><th id="MGR">MGR B</th><th
id="ENAME">ENAME C</th><th id="EMPNO">EMPNO D</th></tr>
<tr><td>R0 CA</td><td>R0 CB</td><td>R0 CC</td><td>R0 CD</td></tr>
<tr><td>R1 CA</td><td>R1 CB</td><td>R1 CC</td><td>R1 CD</td></tr>
<tr><td>R2 CA</td><td>R2 CB</td><td>R2 CC</td><td>R2 CD</td></tr>
<tr><td>R3 CA</td><td>R3 CB</td><td>R3 CC</td><td>R3 CD</td></tr>
</table>
--
Rob | 
November 8th, 2005, 01:25 PM
| | | Re: IE bug with removeChild
Rob, thanks a lot. Appreciate your guidance.
Thanks | 
November 8th, 2005, 02:35 PM
| | | Re: IE bug with removeChild
Still curious...how come my code was working properly in Firefox? IE is
generally more "tolerant" of things like these! | 
November 8th, 2005, 11:05 PM
| | | Re: IE bug with removeChild
VA wrote:[color=blue]
> Still curious...how come my code was working properly in Firefox? IE is
> generally more "tolerant" of things like these!
>[/color]
IE probably does more error correction of source HTML than any other
browser - you can generally toss it any old tag soup and it will make
something of it. Whether that's good or bad has been discussed at great
length in other forums.
But when it comes to DOM, IE is pretty ordinary. Not only does it
occasionally strictly enforce the standard in unexpected ways[1], it is
also lacking in conformance. For example, where you have:
someElement.insertBefore(newChild, refChild)
and refChild doesn't exist, newChild should be appended as the last
child of someElement:
"insertBefore
"Inserts the node newChild before the existing child node refChild.
If refChild is null, insert newChild at the end of the list of
children.
"If newChild is a DocumentFragment object, all of its children are
inserted, in the same order, before refChild. If the newChild is
already in the tree, it is first removed."
<URL:http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-952280727>
IE simply doesn't follow the spec.
1. for example, only allowing table rows to be appended to a tbody
element when using appendChild, or only firing the onchange event
for a checkbox after it loses focus. Both can be said to be strictly
consistent with the specification but are counter intuitive.
--
Rob | | Thread Tools | Search this Thread | | | |
Posting Rules
| You may not post new threads You may not post replies You may not post attachments You may not edit your posts HTML code is Off | | | | | | What is Bytes?
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 220,662 network members.
|