views:

168

answers:

5

I'm loading a few YUI scripts dynamically in my code in response to an Ajax request. The DOM and the page is fully loaded when the request is made - it's a response for an user event.

I add the tag to head, as children. But I stumbled in a few problems:

I add two YUI scripts hosted at the Yahoo! CDN and an inlined script of my own responsible for creating object, adding event listeners and rendering the YUI widgets. But I when my script run the YUI scripts are not loaded yet giving me errors and not running as I expect.

There's a way to only run my script (or define a function to be run) when YUI scripts are fully loaded?

+1  A: 

You could use a setTimeout() to run some function that just checks if it's loaded - check something like

if (typeof YUI_NAMESPACED_THING !== "undefined") runCode()

EDIT Thanks, CMS

Jamie Wong
The `typeof` operator *always* returns a string, the check should be `if (typeof YUI_NAMESPACED_THING != "undefined") //...`
CMS
This is the wrong way to go about it. Firstly, you're probably thinking of setInterval or a chained setTimeout, since a single setTimeout would either A) delay execution too long causing unnecessarily poor page setup time, or B) fail the race condition created by assuming the scripts would be loaded within a certain time.Something based on onload/onreadystatechange solution is better.
Luke
@Luke I was thinking of chained setTimeout. But yes, I agree that onload/onreadystatechange is a better solution. I knew that onload didn't work by itself and wasn't aware there was a cross browser solution down that alley. I upvoted digitalFresh's answer
Jamie Wong
+7  A: 

Have you tried an onload event?

Edited:(thanks Jamie)

var script = document.createElement("script");
script.type = "text/javascript";
script.src = src;
//IE:
if(window.attachEvent && document.all) {
    script.onreadystatechange = function () {
        if(this.readyState === "complete") {
            callback_function(); //execute
        }
    };
}
//other browsers:
else {
    script.onload = callback_function; //execute
}
document.getElementsByTagName("head")[0].appendChild(script);
digitalFresh
While this may actually work in some browsers, `script` elements are not required to have an onLoad event handler, so far as I know - http://www.w3schools.com/tags/tag_script.asp
Jamie Wong
All browsers except IE have an `onload` event(kinda predictable). In IE, you need a fallback `onreadystatechange` function.
digitalFresh
+1 - Hadn't heard of `onreadystatechange`. Good to know
Jamie Wong
+1  A: 

If you're using YUI 2.x I highly recommend using the YUI Get utility, as it's designed to handle just this sort of a problem.

Tivac
A: 

If you are loading multiple individual script files from the Yahoo! CDN, you'll need to makes sure both are loaded before executing your dependent code. You can avoid this using the combo handler. See the Configurator to get what the script url should be to load both/all needed YUI files from one url.

http://developer.yahoo.com/yui/articles/hosting/

With that in mind, assuming you must load the YUI files asynchronously, you should use an onload/onreadystatechange handler as noted by digitalFresh.

I would recommend the following pattern, however:

(function (d) {
    var s = d.createElement('script'),
        onEvent = ('onreadystatechange' in s) ? 'onreadystatechange' : 'onload';

    s[onEvent] = function () {
        if (("loaded,complete").indexOf(this.readyState || "loaded") > -1) {
            s[onEvent] = null;

            // Call your code here
            YAHOO.util.Dom.get('x').innerHTML = "Loaded";
        }
    };

    // Set the src to the combo script url, e.g.
    s.src = "http://yui.yahooapis.com/combo?2.8.1/...";

    d.getElementsByTagName('head')[0].appendChild(s);
})(document);
Luke
A: 

Hi Victor,

If I understand this correctly, your ajax response with this:

<script href="yui-combo?1"></script>
<script href="yui-combo?2"></script>
<p>some text here</a>
<script>
// using some of the components included in the previous combos
// YAHOO.whatever here...
</script>

If this is the case, this is a clear case in which you should use dispatcher plugin. Dispatcher will emulate the browser loading process for AJAX responses. Basically it will load and execute every script in the exact order.

Best Regards, Caridy

Caridy Patino