Javascript script execution in innerHTML: another round

May 27th, 2007

More than one year ago I was play­ing with AJAX, and I was facing a prob­lem with scripts con­tained in doc­u­ments loaded through XML­HttpRe­quest. So, at that time, I wrote two blog posts talk­ing about this issue. The first was just a modify to the well known AHAH tech­nique, while the second post was a script I entirely wrote by myself: “Javascript script exe­cu­tion in inner­HTML: the revenge”.

Now more than a year has passed and tech­nolo­gies are evolved. Now the web is full of very pow­er­ful AJAX frame­works and much prob­a­bly, for medium/big projects you won’t need this kind of “hack” any­more. But there are few devel­op­ers across the world that still hand-​code their little ajax tricks and needs this. So, since I received a lot of com­ments about that, I’m writ­ing here again to update you about the mod­i­fies that have been done to that script.

That script suf­fered of a (rel­a­tively) big prob­lem: if you had a document.write() call in the exter­nal script you loaded, well, it won’t work. Jeremy Bell has mod­i­fied that script in order to have this func­tion­al­ity included. You can see it work­ing at http://​www.​black​outweb​de​sign.​com/​a​j​a​x​.​d​e​m​o.php.

For other dis­cus­sion about the topic, look at the com­ments in the post, they have been very help­ful to me to cor­rect var­i­ous com­pat­i­bil­ity issues.

Javascript script execution in innerHTML: the revenge

March 7th, 2006

The execJS() I posted some time ago have some prob­lems (and it, yes, was just a modify to the AHAH ver­sion). I didn’t really real­ized what exactly it is, but I found a simple (?) solu­tion. The prob­lem, as far as I can under­stand, is that eval() doesn’t always exe­cute the code. So here it is the workaround: look for <script> tags, take its con­tent and create a new ele­ment into the <head> with createElement/appendChild. In this way we should also be more standard-​compliant than before:

function execJS(node)
{
  var bSaf = (navigator.userAgent.indexOf('Safari') != -1);
  var bOpera = (navigator.userAgent.indexOf('Opera') != -1);
  var bMoz = (navigator.appName == 'Netscape');

  if (!node) return;

  /* IE wants it uppercase */
  var st = node.getElementsByTagName('SCRIPT');
  var strExec;

  for(var i=0;i<st.length; i++)
  {
    if (bSaf) {
      strExec = st[i].innerHTML;
      st[i].innerHTML = "";
    } else if (bOpera) {
      strExec = st[i].text;
      st[i].text = "";
    } else if (bMoz) {
      strExec = st[i].textContent;
      st[i].textContent = "";
    } else {
      strExec = st[i].text;
      st[i].text = "";
    }

    try {
      var x = document.createElement("script");
      x.type = "text/javascript";

      /* In IE we must use .text! */
      if ((bSaf) || (bOpera) || (bMoz))
        x.innerHTML = strExec;
      else x.text = strExec;

      document.getElementsByTagName("head")[0].appendChild(x);
    } catch(e) {
      alert(e);
    }
  }
};

I tested it only under fire­fox, but it should work on other browsers too. If it doesn’t, let me know.

Update (Octo­ber 1st, 2006): now it works under Inter­net Explorer too (if you want to inject some text in a script ele­ment in IE you can’t use .inner­HTML, but you have to use .text!)

30 Comments, tagged with Javascript

Javascript script execution in innerHTML

February 23rd, 2006

I am devel­op­ing a new web­site for a club I’m found­ing. I can’t tell you what this club will do (also because I don’t really know, yet) but the site is going to become a chal­lenge.
I wanted to use all the latest, inno­v­a­tive tech­nolo­gies around here. So, I just took PHP, Javascript, XHTML (strictly 1.0 strict!) and a MySQL data­base in my gun­ny­sack and gone around with them.

There’s an issue I’ve been facing against that just got me crazy: if I include a HTML page (not really, a php gen­er­ated one to be pre­cise) through inner­HTML the con­tent that was into the <script>...</script> tags was not exe­cuted. After some google-​ing, I found that this is a secu­rity imple­men­ta­tion: browsers doesn’t allow code to be exe­cuted into a inner­HTML block. If you break a moment and think about it, it makes per­fectly sense, but I need of such a fea­ture so I had to found a workaround.

The idea was this: let threat the html page as an xml file (although it is really one), so let use the DOM to browse it look­ing for <script></script>, then pass its con­tent to eval().
I was not using any AJAX library, so I had to wrote all the code by myself. Here is a snippet:

function execJS(node) {
       var bSaf = (navigator.userAgent.indexOf('Safari') != -1);
       var bOpera = (navigator.userAgent.indexOf('Opera') != -1);
       var bMoz = (navigator.appName == 'Netscape');

var st = node.getElementsByTagName('SCRIPT');
       var strExec;

for(var i=0;i<st.length; i++) {
               if (bSaf) {
                       strExec = st[i].innerHTML;
               } else if (bOpera) {
                       strExec = st[i].text;
               } else if (bMoz) {
                       strExec = st[i].textContent;
               } else {
                       strExec = st[i].text;
               }

try {
                       eval(strExec);
               } catch(e) {
                       alert(e);
               }
       }
}

function handlePageChanging()
{
       if (http.readyState == 4) {
               var cnt_big = document.getElementById('cnt_big');
               cnt_big.innerHTML = http.responseText;

execJS(cnt_big);
               hideLoading();
               doLinks();
       }
}

function changeContentPage(param)
{
       _current = param;

var url = param + '&aJ=y';
       showLoading();
       http.open("GET", url, true);
       http.onreadystatechange = handlePageChanging;
       http.send(null);
}

Of course you can’t copy and paste this code except the execJS func­tion (since it is this post’s pur­pose) but the impor­tant thing is that you notice how it works. Prat­i­cally, the page makes an AJAX request with changeContentPage(), then handle it through handlePageChanging(). So when we’re going to set up the con­tent with inner­HTML, we call execJS() so it will eval()-ize all the <script></script> contents.

Update: see this http://​krat​code.​blogspot.​com/​2​0​0​6​/​0​3​/​j​a​v​a​s​c​r​i​p​t​-​s​c​r​i​p​t​-​e​x​e​c​u​t​i​o​n​-​i​n​.html

2 Comments, tagged with Javascript

Microblogging

  1. January 28th

    1. Finally something to eat! http://t.co/FH3x3oGR [krat]

      1:10am via Twitter

  2. January 27th

    1. Finally some cleanup on my inbox. Feels cleaner now. [krat]

      5:13pm via Twitter

  3. January 26th

    1. panzerotti & peroni [krat]

      7:49pm via Twitter

  4. January 25th

    1. I lost count of how many times I wanted to expand the tweet stream and clicked "favorite" instead [krat]

      11:15am via Twitter

  5. January 23rd

    1. It's hateful when you have to chase people who owe you some money [krat]

      5:45pm via Twitter

    Powered by Lifestream.

Search