Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why don't cloneNode <script> tags execute?

Tags:

javascript

dom

Cloned <script> tags do not execute. Why?

Example:

<script id="hello">
  console.log("hello execution count ", window.helloCount++);
</script>

<script id="action">
  document.body.appendChild(
    document.getElementById('hello').cloneNode(true));
  console.log('cloned the script');
</script>

After execution, there are two hello scripts in the document, but only one has executed.

http://jsbin.com/zuxoro/1/edit?html,console,output

This is part of a larger problem I am working on, so I know it is a dumb thing to do.

like image 857
Aleksandar Totic Avatar asked Feb 27 '15 18:02

Aleksandar Totic


2 Answers

This behavior is required by the W3C HTML5 specification.

Each <script> element has a property flag called "already started". The specification says:

Initially, script elements must have this flag unset (script blocks, when created, are not "already started"). The cloning steps for script elements must set the "already started" flag on the copy if it is set on the element being cloned.

And then, later:

If the script element is marked as having "already started", then the user agent must abort these steps at this point. The script is not executed.

The solution is simply not to clone script elements, but to create completely new elements that are populated with the same content.

like image 65
apsillers Avatar answered Oct 04 '22 02:10

apsillers


I don't know why it doesn't work with cloneNode, but you can achieve the same result by copying the innerHTML to a new script node.

var clone = document.createElement('script');
clone.innerHTML = document.getElementById('hello').innerHTML;
document.body.appendChild(clone);
console.log('copied the script');
<script>
  window.helloCount = 1;
</script>
<script id="hello">
  console.log("hello execution count ", window.helloCount++);
</script>
<div>Copied scripts do execute</div>
like image 32
Barmar Avatar answered Oct 04 '22 02:10

Barmar