Anand wrote:
Thanks for your replies.
I tried the method you suggested in the last reply. It was interesting
to note that, instead of the new node [var A = '<h2> New text </h2>';]
replacing the existing node, the existing node totally diappears from
the list.
It worked for me in Safari, Firefox (Mac & Windows) and IE (Windows).
You may want to set the display of the clone to '' as it may have
inherited the property from the original parent:
// Clone the node that was created
var xNode = tNode.firstChild.cloneNode(true);
xNode.style.display = '';
I have attached part of Dom tree I am dealing with. I need to replace
one of the TR under 'questionmenu' and my variable has
'<tr><td><a href='http://www.kkk.com'>Question 2</a></td>'
Do not use innerHTML to replace any table elements - though it can be
used to replace an entire table or the content of a cell.
<URL:http://msdn.microsoft.com/workshop/browser/mshtml/reference/ifaces/ihtmlelement/innerhtml.asp>
Your string is also missing a closing '</tr>' - closing TR tags are
optional in HTML, but I think it's better to keep it complete.
I applied your method for this DOM str. The existing node disappears.
The other thing is, I seem to be having problem with 'tr' and 'td'. I
haven't tried your method but with other tags like 'h2',
var newnode = createElement();
newnode.innerHTML = A;
parent.replaceChild(newnode,existing_node);
That will not work in all browsers that support innerHTML, though it
seems OK some.
works fine. With trs and tds, a small gap seems to have been placed
instead of the newone. When I check the innerHTML of newnode, it still
hold the actual value that I need to replace with. However, doesn't
work......
I am still to try outerHTML.
outerHTML is IE pretty much IE only, so only use it if this is for an
intranet and everyone uses IE. You can do a reasonable emulation with
Mozilla using createContextualFragment, which is part of the Geko
extensions to the range interface, but it's Mozilla only AFAIK.
<URL:http://www.mozilla.org/docs/dom/domref/dom_range_ref26.html#1003785>
See below for one I baked earlier as an exercise.
In regard to the extra space when adding nodes in Firefox, that seems to
be a function of the layout. For the new elements, set the margin &
padding to 0 (or some fixed value you like) and things settle down again.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/str ict.dtd">
<html>
<head>
<title>outerHTML play</title>
<meta http-equiv="Content-Type"
content="text/html; charset=ISO-8859-1">
<style type="text/css">
body, div, h2 { margin: 0; padding: 0}
#zz {
border: 1px solid red;
background-color: #ddddff;
}
</style>
<script type="text/javascript">
function timeNow() {
var t = new Date();
var s = preZ(t.getHours())
+ ':' + preZ(t.getMinutes())
+ ':' + preZ(t.getSeconds())
t = t*1 + '';
s += '.' + t.substring(t.length-3);
return s;
}
function preZ( x ) {
return ( 10 > x )? '0' + x : x;
}
/*
Add a temporary div with display none,
insert HTML using innerHTML,
clone the node created
replace the old node with the clone
delete the temporary div and its content.
Only works if innerHTML only created one child node of the
temporary DIV. But that child may have many children
and decedents.
*/
function divMethod(){
var A = '<h2 id="zz"> Now is ' + timeNow() + ' </h2>';
var oldnode = document.getElementById('yy');
var existing_node = document.getElementById('zz');
// Create a temp div
var tNode = document.createElement('div');
// Set its display to none (should stop any undesirable UI effects)
tNode.style.display = 'none';
// Add it to the document
document.body.appendChild(tNode);
// Use innerHTML to generate elements from the HTML
tNode.innerHTML = A;
// Clone the node that was created
var xNode = tNode.firstChild.cloneNode(true);
xNode.style.display = '';
// Replace 'existing_node' with the new cloned node
existing_node.parentNode.replaceChild(xNode, existing_node);
// Delete the temp div and its content
tNode.parentNode.removeChild(tNode);
}
/*
Use outerHTML if it's available,
if not, create a document range (if supported)
then use createContextualFragment (if supported)
and replace the old node
*/
function pseudoOuterHTML () {
var A = '<h2 id="zz"> Now is ' + timeNow() + ' </h2>';
var oldnode = document.getElementById('yy');
var existing_node = document.getElementById('zz');
// if ( existing_node.ownerDocument.createRange ) {
if ( document.createRange ) {
// Where createRange supported
var r = document.createRange();
r.selectNode(existing_node);
// And createContextualFragment supported
// It's a Mozilla extension...
if ( r.createContextualFragment ) {
var frag = r.createContextualFragment(A);
existing_node.parentNode.replaceChild(frag, existing_node);
}
}
// Where outerHTML supported
else if ( existing_node.outerHTML ) {
existing_node.outerHTML = A;
}
}
/*
Pure DOM - createElement and add the text,
then replace the old node
*/
function newElement( oid, tag, nid, txt ) {
var oNode = document.getElementById( oid );
var nNode = document.createElement( tag );
nNode.id = nid;
nNode.appendChild(document.createTextNode( txt ));
oNode.parentNode.replaceChild(nNode, oNode);
}
</script>
</head>
<body>
<div id="yy">
<h2>here is one</h2>
<h2 id="zz">Now is
<script type="text/javascript">
document.write( timeNow() );
</script></h2>
</div>
<div style="background-color: #ddffdd; border: 1px solid green;">
<input type="button" value="add/remove div" onclick="
divMethod();
">
<input type="button" value="createContextualFragment/outerHTML" onclick="
pseudoOuterHTML();
">
<input type="button" value="createElement" onclick="
newElement( 'zz', 'h2', 'zz', 'Now is ' + timeNow() );
">
</div>
</body>
</html>
--
Rob