Debugging scripts added via jQuery getScript function

Solution 1:

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>

Solution 2:

With JQuery 1.6(maybe 1.5) you could switch to not using getScript, but using jQuery.ajax(). Then set crossDomain:true and you'll get the same effect.

The error callback will not work. So you might as well not set it up like below.

However, I do setup a timer and clear it with the success. So say after 10 seconds if I don't hear anything I assume the file was bad.

        jQuery.ajax({
            crossDomain: true,
            dataType: "script",
            url: url,
            success: function(){
                _success(_slot)
            },
            error: function(){
                _fail(_slot);
            }
        })

Solution 3:

For those who would like to debug scripts and use them with $.when (James Messinger's answer doesn't work well with $.when) I suggest to use this code:

var loadScript = function (path) {
  var result = $.Deferred(),
  script = document.createElement("script");
  script.async = "async";
  script.type = "text/javascript";
  script.src = path;
  script.onload = script.onreadystatechange = function (_, isAbort) {
      if (!script.readyState || /loaded|complete/.test(script.readyState)) {
         if (isAbort)
             result.reject();
         else
            result.resolve();
    }
  };
  script.onerror = function () { result.reject(); };
  $("head")[0].appendChild(script);
  return result.promise();
};

All credits and glory go to Benjamin Dumke-von der Ehe and his article: jQuery script insertion and its consequences for debugging

This works well with $.when and the script is totally visible and debuggable. Thanks.

Solution 4:

Try this,

jQuery.extend({
getScript: function(url, callback) {
    var head = document.getElementsByTagName("head")[0];

    var ext = url.replace(/.*\.(\w+)$/, "$1");

    if(ext == 'js'){
        var script = document.createElement("script");
        script.src = url;
        script.type = 'text/javascript';
    } else if(ext == 'css'){
        var script = document.createElement("link");
        script.href = url;
        script.type = 'text/css';
        script.rel = 'stylesheet';
    } else {
        console.log("Неизветсное расширение подгружаемого скрипта");
        return false;
    }



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

} 
   });