I looked at a lot of solutions for this and here's what I've come up with:
(function getjQuery(callback) {
if ('complete' === document.readyState) {
var script = document.createElement('script');
var target = document.documentElement;
script.src = '//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js';
script.async = false;
script.onload = function () {
target.removeChild(script);
callback(jQuery.noConflict(true));
};
target.appendChild(script);
} else {
window.addEventListener('load', function () {
getjQuery(callback);
});
}
})(function ($) {
// Your code here...
});
Many scripts try to detect if jQuery is already loaded, and some go further
and check if the loaded version is the version they want. I think this is bad:
though exceedingly unlikely, a site could inject malicious code somewhere into
the jQuery
object, or even for whatever reason have a global variable set to
something like jQuery = false
.
I say let's grab our own version. And the version I load is the latest 1.x release from Google's CDN. Since the 1.x branch is in a sort of maintenance-mode, I guess it's unlikely to get many breaking changes in the future. It will probably last on Google's CDN for a long time, though. Once you've finalized functionality it would be wise to pick a full version number and use that. Since we're loading from one of the most popular CDNs for jQuery, chances are, the browser already has the script cached, so it won't need to be downloaded anyway.
Since bookmarklets are almost always written expecting a fully usable document,
I've named the calling function and wrapped it in a check that the document's
readyState
is 'complete', and if it's not, add's a window.onload
event
to re-run the script.
I set the script async
to false, again because the site's scripts should
already be loaded, and it saves setting up an onreadystatechange
listener
for the script. The onload
event can be used instead. I've heard some places
that onload
might not be as backwards-compatible as using onreadystatechange
,
so if you need old versions of browsers to work, try refactoring it to use the
onreadystatechange
event. I've had no issues in the latest versions of the
usual candidates (Firefox and Chrome).
Once the script is loaded, I immediately remove the script tag from the DOM,
so as not to alter the generated source code much. I don't know that there's a
great reason to be doing this, but it doesn't hurt, and it leaves the DOM in
the same state it was before calling, so it's likely to prevent issues with
some few sites. Even though the script tag is removed, window.jQuery
remains.
The last thing to do is just call the callback function, sending jQuery as the
sole argument. I use jQuery.noConflict(true)
to restore the previous values
of window.jQuery
and window.$
, even if they were undefined
. This is
another thing I saw often overlooked in others' bookmarklets. My objective is
to make clicking it provide jQuery to the callback function and execute that
code, without causing any side effects, and I think this method achieves that
pretty well. I'm using it myself "in production" (read: on my personal
computers), and will certainly report any issues I come across with this method.
I don't feel that such simple code needs a license, so for anyone who wants to alter/redistribute it, consider it Unlicensed (see: http://unlicense.org) and in the public domain.