Safari quirk: Copying innerHTML
Here's a fun one. Given the following HTML, let's attempt to copy the contents of div1 to div2, then grab a reference to the SPAN element "foo."
<div id="div1"> <span id="foo">Foo span</span> </div> <div id="div2"></div>
The easy way out is to just copy innerHTML from one element to the other, then destroy the contents of the original element:
document.getElementById('div2').innerHTML = document.getElementById('div1').innerHTML; document.getElementById('div1').innerHTML = ''; alert(document.getElementById('foo'));
In most browsers, the alert dialog displays "Element SPAN" or something similar. But in Safari 1.3 and above, the dialog displays null. Why?
For a brief moment, when we copy the innerHTML, we create two SPANs with identical IDs of "foo." Even after we destroy the contents of div1 (leaving only the one SPAN), the DOM is screwed up enough to confuse Safari, which continues to return null even after the DOM is "fixed." By contrast, Firefox for OS X is far more forgiving.
The solution seems to be: duh, don't copy from element to element. Instead, hold the contents in a variable until it's safe to reinsert them into the page:
var tempHTML = document.getElementById('div1').innerHTML; document.getElementById('div1').innerHTML = ''; document.getElementById('div2').innerHTML = tempHTML; alert(document.getElementById('foo'));
The dialog should now display "Object SPAN" in Safari. Of course, astute JS developers would probably prefer to skip using innerHTML altogether
8 Comments:
I would argue the better way to do such a thing is to clone the DOM node since it is all good in the eyes of the DOM:
function moveFoo () {
var div1 = document.getElementById('div1');
var foo = document.getElementById('foo');
var clonefoo = foo.cloneNode(true);
var div2 = document.getElementById('div2');
div2.appendChild(clonefoo);
div1.removeChild(foo);
alert(document.getElementById('foo'));
}
window.onload = moveFoo;
Cheers;
Poncho
You'd probably want to remove the original foo first before appending the clone, or once again you'll have a DOM with two foos ;)
Also, in the example code we're swapping the entire node contents, not just SPAN foo, so innerHTML isn't a bad way to go unless you wanna mess with DocumentFragments.
Good point about the first foo. What can I say? It was a quick post.
I guess I'll stick to PHP ;)
innerHTML rulez!!
传世私服
传奇世界私服
传世私服
最新传世私服
新开传世私服
千年私服
最新传世私服
传世私服
新开千年私服
奇迹私服
最新奇迹私服
新开奇迹私服
变态奇迹私服
奇迹私服ip
pr查询
pr交换
var div1interval;
function div1init()
{
for(j=0; j<2;j++)
{
div1.innerHTML += 1+" ";
}
while((div1.scrollHeight/2) <= parseInt(div1.style.height))
{
div1.innerHTML += div1.innerHTML;
}
}
function div1start()
{
div1interval=setInterval("div1scent();div1.scrollTop+=5;",100);
}
function div1scent()
{
if(div1.scrollTop == (div1.scrollHeight-parseInt(div1.style.height)))
{
div1.scrollTop = (div1.scrollHeight/2)-parseInt(div1.style.height);
}
Greetings,
TiDy2
This tip saved my day ! Thank you so much !
You shouldn't even need to clone the node. Eg, to move "node" from container1 to container2:
container2.appendChild(node);
to move it back:
container1.appendChild(node);
It should be as simple as that!
Haig
Post a Comment
<< Home