Tuesday, August 4, 2009

Beware of moving element with script node by jquery

My colleague hit a strange error when he implement the code in to move element with following code (with simplification):


<div id="moveMe">hihi
<a id="clickMeAlertOnce"> Click Me Alert Once </a>
<script type="text/javascript">
//Script Code inside moveMe
$('#clickMeAlertOnce').click(function(){alert(' Click Me Alert Once');});
</script>
</div>

<div id="'newLocation'" />

<script type="text/javascript">
//Code to move Node
$('#newLocation').append($('#moveMe'));
//omit some code as clean up old node<br />
</script>


The cause of the error is because the 'append' method in Jquery will invoke the below method
domManip: function( args, table, callback ) {
if ( this[0] ) {
var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
first = fragment.firstChild;

if ( first )
for ( var i = 0, l = this.length; i <>
callback.call( root(this[i], first), this.length > 1 || i > 0 ?
fragment.cloneNode(true) : fragment );
if ( scripts )
jQuery.each( scripts, evalScript );
}

return this;
function root( elem, cur ) {
return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
(elem.getElementsByTagName("tbody")[0] ||
elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
elem;
}
}

Its logic will eval each script node within a html Dom being manipulate.
As a result, "Script Code inside moveMe" was being eval twice time. First is the page render, and second is the appending node.

Possible solution is to remove the script node before the DOM append action.

//This is prevent the script block being event again during append.
$("#"+item.Id+" script").remove();
$('#newLocation').append($('#moveMe'));

No comments:

Post a Comment