Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 11 of 11
  1. #1
    Regular Coder
    Join Date
    Mar 2004
    Posts
    130
    Thanks
    0
    Thanked 0 Times in 0 Posts

    script.onload observer?

    Is there an observer for a "script loaded" event?
    Or maybe an observable property so I can tell if the script is loaded via polling?

    Thinking something like:
    Code:
    callback = function() {
     alert("script loaded");
    };
    
    var script = document.createElement("script");
    script.addEventListener(type, callback, false);
    script.src = "/js/bark.js";
    document.getElementsByTagName("head")[0].appendChild(script);

  • #2
    Senior Coder
    Join Date
    Jul 2005
    Location
    New York, NY
    Posts
    1,084
    Thanks
    4
    Thanked 19 Times in 19 Posts
    I don't believe so. What are you trying to accomplish?

  • #3
    Regular Coder
    Join Date
    Mar 2004
    Posts
    130
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Why for loading external scripts, of course!

    Dojo uses a require function to accomplish it, calling eval( responseText ); Problem is: If the responseText contains a js error, you can't debug it, or if it's 404 or 500 error page, then it will of course cause a js error. I'm not gonna say anything more about Dojo...

    t should be possible to listen for the script load event and get the http status code, too. The browser already has access to it, but read access isn't just provided in js.

    We need this functionality. It's more than useful: It's necessary.

  • #4
    jkd
    jkd is offline
    Senior Coder jkd's Avatar
    Join Date
    May 2002
    Location
    metro DC
    Posts
    3,163
    Thanks
    1
    Thanked 18 Times in 18 Posts
    You could implement it easily. For every JS file you load:

    Beginning of the JS file:
    Code:
    if (!("scripts" in window)) var scripts = new Object();
    scripts["jsfilename.js"] = false;
    Then you have the rest of the code. Then at the end:
    Code:
    scripts["jsfilename.js"] = true;
    And then you can just poll the scripts object for completion. If you wanted to be fancy, you could assign a callback .watch() for Gecko, and a callback via onpropertychange for IE (if you change the new Object() to say, document.createElement("script") so it's a DOM object).

  • #5
    Regular Coder
    Join Date
    Mar 2004
    Posts
    130
    Thanks
    0
    Thanked 0 Times in 0 Posts
    That's one approach.

    We can poll to wait for "true" to appear, and clearTimeout after a while, throw a custom error (e.g. ScriptNotLoaded).

  • #6
    Regular Coder
    Join Date
    Mar 2004
    Posts
    130
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Ok, I think i'm onto something...

    Code:
    <script>
    function loadScript(src, callback) {
        var script = document.createElement("script");
        
        if(script.addEventListener)
            script.addEventListener("load", callback, false);
        else if(script.attachEvent) 
            script.attachEvent("onreadystatechange", 
                function() { loadScript.callbackIE(callback); });
        
        script.src = src;
        document.getElementsByTagName("head")[0].appendChild(script);
    }
    loadScript.callbackIE = function(callback) {
        var target = window.event.srcElement;
        if(target.readyState == "loaded")
            callback.call(target);
    };
    
    // load  30k script.
    // Listener.cleanUp is defined at the bottom of drag.js
    callback = function() {
        var self = this;
        alert("Loaded: " + this.src + "\nListener.cleanUp (nested):" + Listener.cleanUp);
    };
    loadScript("http://dhtmlkitchen.com/editor/js/drag.js", callback);
    </script>

  • #7
    Master Coder
    Join Date
    Feb 2003
    Location
    UmeŚ, Sweden
    Posts
    5,575
    Thanks
    0
    Thanked 83 Times in 74 Posts
    DHTML Kitchen: How good control do you have over the script on the server, and what type of content can be found in it? If the contents is in the form of JSON, a JavaScript function literal or an object literal a solution to your problem might look like this:
    Code:
    function callback(o){
        /* Script is loaded, it's sent an object back to the callback.
        Do whatever you need to do with the object. */
    }
    And then you append the scripts using DOM, with a query string of '?fn=callback'. The server uses this query string to build
    Code:
    callback(
        /* JSON object, JavaScript function literal or object literal */
    );

    The same way of doing it, but appending the callback to the end of the file instead of wrapping it also works for libraries where you use function declarations, variable declarations, or globally executed code. If you do have those though, it's normally pretty quick work to make the former approach work perfectly too.

    It demands some control over the server side of it, though.
    Last edited by liorean; 05-01-2006 at 10:49 PM.
    liorean <[lio@wg]>
    Articles: RegEx evolt wsabstract , Named Arguments
    Useful Threads: JavaScript Docs & Refs, FAQ - HTML & CSS Docs, FAQ - XML Doc & Refs
    Moz: JavaScript DOM Interfaces MSDN: JScript DHTML KDE: KJS KHTML Opera: Standards

  • #8
    Regular Coder
    Join Date
    Mar 2004
    Posts
    130
    Thanks
    0
    Thanked 0 Times in 0 Posts
    I don't know what you mean. We can send back anything we want from the server. We have total control. The callback executes after the script is loaded.

    I'm trying to get some sort of "waitForCondition" to pause script execution until the script file is fully loaded.

    The load event is capturable. readyState == "loaded", and useCapture = false.

    I just need a waitForCondition. I want to waitForCondition before returning the script. Selenium has waitForCondition functionality. I'm going look into that.

    along the lines of
    waitForCondition("scripts['"+jsfilename.js+"'] == true;");
    Last edited by DHTML Kitchen; 05-01-2006 at 11:08 PM.

  • #9
    Senior Coder
    Join Date
    Jun 2002
    Location
    near Oswestry
    Posts
    4,508
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Another thing you might try is to preload the script using ajax. I've done this with stylesheets before and it works, so it might work for scripts as well.

    The idea is, make a GET request for the script, and inside that request's completed readystate function (200 or 304) create the script and append it to the page. At this point the script should be drawn from cache, and hence you can consider its loading to be instantaneous.

    That's the theory anyway!
    "Why bother with accessibility? ... Because deep down you know that the web is attractive to people who aren't exactly like you." - Joe Clark

  • #10
    Regular Coder
    Join Date
    Aug 2005
    Posts
    282
    Thanks
    0
    Thanked 0 Times in 0 Posts
    You can actually shorten the code you already made:
    Code:
    function loadScript(src, callback) {
      var node = document.createElement("script");
      if (node.addEventListener)
        node.addEventListener("load", callback, false);
      else
        node.onreadystatechange = function() {
          if (this.readyState == "complete") callback.call(this);
        }
      node.src = src;
      document.getElementsByTagName("head").item(0).appendChild(node);
      node = null;
    }
    Tested successfully in IE6 and Firefox 1.5, and no memory leaks.

  • #11
    New to the CF scene
    Join Date
    Sep 2009
    Posts
    1
    Thanks
    0
    Thanked 0 Times in 0 Posts
    thank you guys for the tip, but I had to work it around like this in order to work properly (readyState "complete" ain't gonna get recognized in IE, so I used "loaded"). Furtherly, I was using Prototype methods besides.

    Code:
    var isIE6 = myWork.BrowserCheck.IE6;	// custom method, use "navigator.userAgent.yaddayadda" instead
    		
    var newSliderScript = new Element("script", { 
    	type: "text/javascript", 
    	src:"/path/to/slider.js" 
    });
    documentBody.insert(newSliderScript);
    
    if(isIE6) {
    	newSliderScript.onreadystatechange = function() {
    		//alert(this.readyState);	// test IE loading state
    		if (this.readyState == "loaded") document.fire("myWork:sliderReady");
    	}
    } else {
    	// "good" browsers go here
    	newSliderScript.observe("load", function(){
    		document.fire("myWork:sliderReady");
    	});
    }
    
    document.observe("myWork:sliderReady", function() {
    
    	// ... your code that should run on "load" here ....
    	
    });
    This does the trick for me and "my" IE 6 and FF 3 :-)


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •