Categories

Inserting SCRIPT tags at runtime

If you ever tried to create a script tag and add it to the DOM, you probably discover that it works fine in Mozilla browser, but not as well in IE.

?View Code JAVASCRIPT
var myScript = document.createElement("script");
     myScript.setAttribute("type","text/javascript");
     myScript.innerHTML += 'alert("Hello from SanRaul.com");';
     document.body.appendChild(myScript);



For the SCRIPT tag IE doesn’t allow modifying the innerHTML value of your new HTMLElement. In one of the Microsoft page they explain how to insert a script after the pages was constructed (innerHTML Property).



This is what you will see in Microsoft’s Example:

?View Code JAVASCRIPT
<SCRIPT>
function insertScript(){
    var sHTML="<input type=button onclick=" + "go2()" + " value='Click Me'><BR>";
    var sScript="<SCRIPT DEFER>";
    sScript = sScript + "function go2(){ alert('Hello from inserted script.') }";
    sScript = sScript + "</SCRIPT" + ">";
    ScriptDiv.innerHTML = sHTML + sScript;
}    
</SCRIPT>


Its’ a kind of tricky, but this approach does not work in Mozilla browsers. The DEFER value is need by IE and it doesn’t help Mozilla browsers. To make it compatible we have to avoid accessing elements directly. Getting a reference by the element ID will be a more compliant approach.

?View Code JAVASCRIPT
// instead of 
ScriptDiv.innerHTML = sHTML + sScript;
// we can use
var container = document.getElementById('ScriptDiv');
     container.innerHTML = sHTML + sScript;



In a real world you may not want to insert a button to trigger the new script and you just some new code to be executed, so we can remove the ‘Click’ button and add our own code.



Custom Example:

?View Code JAVASCRIPT
<SCRIPT>
function insertScript(){
    var sScript = "<SCRIPT DEFER>";
         sScript += "alert('Hello from inserted script.')";
         sScript += "</SCRIPT" + ">";
    var container = document.getElementById('ScriptDiv');
         container.innerHTML = sHTML + sScript;
}
</SCRIPT>
 
<input type="submit" value="insert" onclick="insertScript()"/>
    <DIV ID="ScriptDiv"></DIV>


The new SCRIPT tag can be inserted but the code does not execute in IE. Removing the button makes IE ignore the script. It seems like a visual element must be added for this to work. Instead of removing the button we can replace with an invisible element.



IE and Mozilla compatible:

?View Code JAVASCRIPT
<SCRIPT>
function insertScript(){
    var spanElement = "<span style='display:none;'>.</span>";
    var sScript = "<SCRIPT DEFER>";
         sScript += "alert('Hello from inserted script.')";
         sScript += "</SCRIPT" + ">";
    var container = document.getElementById('ScriptDiv');
         container.innerHTML = spanElement + sScript;
}
</SCRIPT>


This is a good example if we know ahead of time what the code that we want to execute. If we want to add dynamic values to our code we have to use a more generic approach:



Enhanced Version:

?View Code JAVASCRIPT
<SCRIPT>
/**
* @param tagAttributesObj keyvalue object with the attributes of the script tag
* @param codeAsTex a string that contains the javascript code
* @param divName The div ID where the script is going to be inserted (optional)
* @return {String} Id of the script tag
*/
function appendScript(tagAttributesObj, codeAsText, divName){
    var newScript = "<span style='display:none;'>.</span>";
    // Create openning tag
    var tagId = "scriptId" + Math.ceil(Math.random() * 10000);
    if(tagAttributesObj != null){
        newScript += "<SCRIPT id='"+ tagId +"' ";
        for(var a in tagAttributesObj){
            newScript += a +"='"+ tagAttributesObj[a] +"' ";
        }
        newScript += "DEFER>";
    }else{
        newScript += "<SCRIPT type='text/javascript' DEFER>";
    }
 
    // Add new script
    if(codeAsText != null) newScript += codeAsText;
 
    // Close script tag
    newScript += "</SCRIPT" + ">";
 
    // Append to DOM
    if(divName != null){
        var container = document.getElementById(divName);
             container.innerHTML = newScript;
    }else{
        var container = document.createElement("div");
             container.innerHTML = newScript;
        document.body.appendChild(container);
    }
    return tagId;
}
</SCRIPT>
    <input type='submit' value='import script' 
             onclick='appendScript({"src":"http://www.sanraul.com/blog/sanraul/hello.js"})'/>
    <input type="submit" value="append script" 
             onclick="appendScript(null, 'alert('Hello from SanRaul.com')')"/>
    <DIV ID="ScriptDiv"></DIV>


As you can see this approach will let us include a script that is in a different URL or create a string with any dynamic value.

If you ever wonder why the function returns the new script tag id, well, that why I wrote this post. I needed to dynamically add an script tag to listen to events in a windows media player object. To do that, I had to add a script tag that contains attributes such ‘FOR’ which points to the windows media player instance (object id) and ‘EVENT’ which refer to the player event you want to listen to. Well the script above works fine but the ‘EVENT’ attribute is ignored. A way to work around is adding the ‘EVENT’ attribute after the script tag was appended to the DOM. This is why convenient to have the script tag id.

Click HERE to test this functionality.

1 comment to Inserting SCRIPT tags at runtime

  • This script appears to work when the script is included in the call
    appendScript(null, “alert(‘Hello from SanRaul.com’)”);

    but not when the script is in an external script file.
    //appendScript({“src”:”http://affiliates.hotelscombined.com/scripts/AffiliateSearchBoxExtended.ashx?target=_blank&typeId=12&affiliateId=8567&label=whereisitsunny”},null,’overlaycontent’)

    Is this because the script is not on the same server? I am attempting to load a search widgit into a popup div.

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

IMPORTANT! To be able to proceed, you need to solve the following simple math (so I know that you are a human) :-)

What is 10 + 11 ?
Please leave these two fields as-is: