Jul 28, 2010 -- posted by Ambasta
$.getScript() and Firebug: But then, who was code?
If you’ve ever tried to import javascript via jQuery.getScript(), you might be rendered unable to actually debug the fetched js in firebug or similar debuggers. The reason is simple and lies in how jQuery implements getscript :
getScript: function( url, callback ) {
return jQuery.get(url, null, callback, "script");
}
where get itself is implemented as :
get: function( url, data, callback, type ) {
// shift arguments if data argument was omited
if ( jQuery.isFunction( data ) ) {
type = type || callback;
callback = data;
data = null;
}
return jQuery.ajax({
type: "GET",
url: url,
data: data,
success: callback,
dataType: type
});
}
Debugging further you’ll find that ajax uses JSONP to allow linking scripts from non-origin domain by taking advantage of the behavior of src attribute in script tag. However local scripts are just imported inline as:
<script type="text/javascript">local code</script>
as seen in implementation of $.ajax() :
// Matches an absolute URL, and saves the domain
var parts = rurl.exec( s.url ), remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);
// If we're requesting a remote document
// and trying to load JSON or Script with a GET
if ( s.dataType === "script" && type === "GET" && remote ) {
var head = document.getElementsByTagName("head")[0] || document.documentElement;
var script = document.createElement("script");
script.src = s.url;
if ( s.scriptCharset ) {
script.charset = s.scriptCharset;
}
// Handle Script loading
if ( !jsonp ) {
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;
success();
complete();
// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
if ( head && script.parentNode ) {
head.removeChild( script );
}
}
};
}
// Use insertBefore instead of appendChild to circumvent an IE6 bug.
// This arises when a base node is used (#2709 and #4378).
head.insertBefore( script, head.firstChild );
// We handle everything using the script element injection
return undefined;
}
As you can see, splitting URL and domain causes local scripts to be treated as non-remote objects. So now, since your local scripts are loaded asynchronously and added inline, you only need to override jQuery.getScript() to make it work as how ajax handles remote requests, per say:
jQuery.extend({
getScript: function(url, callback) {
var head = document.getElementsByTagName("head")[0] || document.documentElement;
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;
//success();
//complete();
if ( callback)
callback();
// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
if ( head && script.parentNode ) {
head.removeChild( script );
}
}
};
}
head.insertBefore( script, head.firstChild );
return undefined;
}
});
We’ve implemented our own call to callback since in $.ajax uses success() to fire the callback instead. While a success can be written for this new getScript(), its beyond the scope of this article.
