Posted by: Andrei Neculau | 20060929

AJAX, onDemand JavaScript or Dynamic Script Tags

Now, with Web 2.0 being closer and closer (actually it is already alive!) you don’t just make asynchronious requests in order to get HTML or JSON… but ALSO JavaScript.

To be more exact… you make requests to get HTML with SCRIPT tags.

But the “beauty” is that the SCRIPT blocks don’t get loaded/evaluated/ran. This if you AJAX for a response like

<script type=”text/javascript” src=”my.js” id=”myjs”></script><div>some other HTML</div>

and put this in the innerHTML of a DIV element, then you will not get your my.js loaded. The same happens if you put actual scripting code inside the SCRIPT block.

The first thing you think of (or at least I thought of) is to assign the response to a DIV element, then parse it to find any SCRIPT tags.

For each SCRIPT element you do this

for (var i in scriptElements) {
var scriptElement = scriptElements[i];
var newScript = document.createElement(’SCRIPT’);
newScript.setAttribute(’src’, scriptElement.getAttribute(’src’));
newScript.setAttribute(’type’, scriptElement.getAttribute(’type’));
newScript.setAttribute(’id’, scriptElement.getAttribute(’id’));
newScript.data = scriptElement.data;
if (_isMSIE_)
{
newScript.onreadystatechange = function ()
{
if (newScript.readyState == ‘loaded’)
{
_do your thing_
newScript.onreadystatechange = null;
}
}
}
else
{
newScript.onload = function() {_do the same thing_}
}
scriptElement.parentNode.removeChild(scriptElement);
var head = document.getElementsByTagName(”head”)[0];
head.appendChild(newScript);
}

Be sure to retain the IDs of the SCRIPT elements, so that you can eliminate them later, if you need to do this.

This should fix it. BUT… there’s also Internet Explorer! It always is.

When you try to put the example AJAX response into an element’s innerHTML, the SCRIPT tags dissappear!!! Why?! I do not know. Maybe it is because it will not load the SCRIPT anyway, so it erases it.

The solution I came up with is: why should you need to use the SCRIPT tag when responding to the AJAX request? I respond with a normal “innocent” DIV tag like this:

<div src=”my.js” id=”myjs” type=”text/javascript”></div>

Then, when you search for “SCRIPT” elements, you can search for elements with type == “text/javascript”, etc.

Et voila! Enjoy!

Tags: , , , ,

Responses

Hey Andrei,

Another simple method that may work (from what I’ve found, anyway) is just to eval the innerText/text of any and all script nodes in your XHR response - effectively running them like they were JSON. Of course this only works on “inline” script blocks, not those referenced with src= as you showed. You’ll have to consider security, but then again this should be script only coming from the local domain anyhow.

Dynamically inserting script nodes can be frustrating as it seems to be inconistent with different browsers - with IE you seem to have to watch both onreadystatechange and onload as your code shows, and even then it seems you’ll get a failure once in a while. I believe Safari doesn’t like this method much either, but I haven’t done any experiments with it recently.

Thanks for your input. I haven’t tested this on Safari either. Not even Konqueror.

The thing about using eval is that it is very harsh with memory resources, and on low-average systems you get a big hang. Everywhere you search when you would have a solution with eval, people suggest another that doesn’t use eval, just so you behave nicely with the memory resources.

dasda

Hey Andrei, few weeks ago I was searching information about this… and my conclusion at this point is that maybe if we use a regular expression to parse the entering XHR response, then we can guaranteed that the inline SCRIPTS and the Remote SCRIPTS could be evaluated and loaded respectively. But what about the scope for inline SCRIPTS evaluation? because the response will be evaluated inside a function…

regards
Caridy

Caridy, my research took me to the following results.

If you have inline SCRIPTS, then that’s ok. They are parsed ok.
The problem comes up when you have remote SCRIPTS, the browser takes that away, leaving you with no SCRIPT.
You can test this in IE and Firefox. I remember I have tested this in Opera as well.

Please come back with your findings, or email me.

Andrei, finally I wrote a solution for this issue on the feet of YUI Library, I already tested it on firefox, IE and opera, and everything was great…

Here is an example of dynamic areas with script tags (inline and remote scripts):
http://bubbling.comarq.com/themes/bubbling/examples/plugin-dispatcher-dynamic-contents.html

And here is the full explanation:
http://bubbling.comarq.com/eng/node/dispatcher/

Regards.
Caridy

THANKS, CARIDY! Nice work! Cheers! ;)

Leave a response

Your response:

Categories