I have a javascript function I’m writing which is being used to include an external JS file, but only once. The reason I need such a function is because it is being called when some content is loaded via AJAX and I need to run page-specific code to that content (no, just using .live won’t cover it).
Here’s my attempt, shortened for brevity:
$.include_once = function(filename) {
if ($("script[src='" + filename + "']").length === 0) {
var $node = $("<script></script>")
.attr({
src : filename,
type : "text/javascript"
})
;
$(document.body).append($node);
}
};
This works fine: the function is called, it loads the external file, and that file is being run when loaded. Perfect.
The problem is that it will always re-load that external file: the query I’m using to check for the presence of the script always finds nothing!
When debugging this, I added some lines:
alert($("script").length); // alerts: 4
$(document.body).append($node);
alert($("script").length); // alerts: 4
Looking in the dynamic source (the HTML tab of Firebug), I can’t find the script tag at all.
I know that I could maintain an array of files that I’ve previously included, but I was hoping to go with a method such as this, which (if it worked), seems a bit more robust, since not all the JS files are being included in this way.
Can anyone explain the behaviour seen in this second snippet?
jQuery is a bit of a dumb-dumb in this case; it doesn’t do at all what you’d expect. When you
append($node)jQuery does this:Woops! For local files (eg on the same domain) jQuery performs a standard
XMLHttpRequestfor the .js file body, and proceeds to “eval” it by a whole convoluted process of creating a<script>tag (again!) and settings it’s contents to your .js file body. This is to simulateevalbut in the global context.For cross-domain files, since it cannot perform the standard
XMLHttpRequestdue to the same-domain policy, jQuery once again creates a<script>element and inserts it into<head>.In both the local and cross-domain cases above jQuery finally gets around to doing this:
And booms your
.lengthcheck! Bummer.So on to your problem, don’t bother jQuery with this. Just do
Which will do what you’d expect, particularly wrt querying for it later.