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 <scripts> 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

5 Answers 5

18

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);
Sign up to request clarification or add additional context in comments.

2 Comments

While this may actually work in some browsers, script elements are not required to have an onLoad event handler, so far as I know - w3schools.com/tags/tag_script.asp
All browsers except IE have an onload event(kinda predictable). In IE, you need a fallback onreadystatechange function.
2

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.

Comments

2

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);

Comments

1

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

3 Comments

The typeof operator always returns a string, the check should be if (typeof YUI_NAMESPACED_THING != "undefined") //...
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 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
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.