Friday, April 15, 2011

Debugging scripts added via jQuery getScript function

I have a page that dynamically adds script references via jQuery's $.getScript function. The scripts load and execute fine, so I know the references are correct. However, when I add a "debugger" statement to any of the scripts to allow me to step through the code in a debugger (such as VS.Net, Firebug, etc.), it doesn't work. It appears that something about the way jQuery loads the scripts is preventing debuggers from finding the files.

Does anybody have a work-around for this?

From stackoverflow
  • Ok, so it turns out that the default implementation of the $.getScript() function works differently depending on whether the referenced script file is on the same domain or not. External references such as:

    $.getScript("http://www.someothersite.com/script.js")
    

    will cause jQuery to create an external script reference, which can be debugged with no problems.

    <script type="text/javascript" src="http://www.someothersite.com/script.js"></script>
    

    However, if you reference a local script file such as any of the following:

    $.getScript("http://www.mysite.com/script.js")
    $.getScript("script.js")
    $.getScript("/Scripts/script.js");
    

    then jQuery will download the script content asynchronously and then add it as inline content:

    <script type="text/javascript">{your script here}</script>
    

    This latter approach does not work with any debugger that I tested (Visual Studio.net, Firebug, IE8 Debugger).

    The workaround is to override the $.getScript() function so that it always creates an external reference rather than inline content. Here is the script to do that. I have tested this in Firefox, Opera, Safari, and IE 8.

    <script type="text/javascript">
    // Replace the normal jQuery getScript function with one that supports
    // debugging and which references the script files as external resources
    // rather than inline.
    jQuery.extend({
       getScript: function(url, callback) {
          var head = document.getElementsByTagName("head")[0];
          var script = document.createElement("script");
          script.src = url;
    
          // Handle Script loading
          {
             var done = false;
    
             // Attach handlers for all browsers
             script.onload = script.onreadystatechange = function(){
                if ( !done && (!this.readyState ||
                      this.readyState == "loaded" || this.readyState == "complete") ) {
                   done = true;
                   if (callback)
                      callback();
    
                   // Handle memory leak in IE
                   script.onload = script.onreadystatechange = null;
                }
             };
          }
    
          head.appendChild(script);
    
          // We handle everything using the script element injection
          return undefined;
       },
    });
    </script>
    
    Andrew Matthews : nice. Have you experienced any issues that I should be aware of since you posted this answer? ;)
    Shrikant Sharat : I don't think this method makes use of the global ajax events.. not sure.
  • Is there a way around this without hacking JQuery? I'm hitting exactly the same problem but I can't see a workable solution, without overriding getScript. Thanks

    James Messinger : I don't recommend using my workaround in a production environment. This is just a workaround for your dev environment for debugging purposes. In our applications, we put this "hack" in a file that is only referenced in DEBUG builds. Our release builds use the normal jQuery getScript method, since we don't have any need to debug our production environments.
  • script somewhat works but does throw unexpected errors when using eval(). but thanks for posting, its pretty nifty workaround.

0 comments:

Post a Comment