Skip to content

Instantly share code, notes, and snippets.

@cyranix
Last active February 7, 2024 02:32
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cyranix/6180495 to your computer and use it in GitHub Desktop.
Save cyranix/6180495 to your computer and use it in GitHub Desktop.
Example for easy dependency loading in user-scripts, compatible with Firefox (Greasemonkey) and Chrome (native; haven't tried Tampermonkey). Because Chrome doesn't allow `@require`, this technique is useful if you're too lazy to sync up a homebrew Chrome extension with an equivalent Greasemonkey script.
// ==UserScript==
// @name <name>
// @match <URL patterns for activation>
// @description <description>
// ==/UserScript==
/**
* Outermost IIFE for bootstrapper.
* @param main Function encapsulating the real work of the script [required]
* @param dep_urls Array of URLs to dependencies [default: empty array]
* @param dep_refs Array of references to dependencies from window scope [default: empty array]
*/
(function bootstrap(main, dep_urls, dep_refs) {
dep_urls = dep_urls || [];
dep_refs = dep_refs || [];
// Inner IIFE for recursive dependency loading.
// This is an extension of Erik Vold's technique.
(function load() {
var script = document.createElement('script');
if (dep_urls.length > 0) {
// Load dependencies until the list is exhausted...
script.src = dep_urls.shift();
script.addEventListener('load', load);
} else {
// ... then inject the main script (as text) using arguments from the window scope.
script.textContent = '(' + main.toString() + ')(' + dep_refs.join(',') + ');';
}
document.body.appendChild(script);
})();
})(
__main__,
['//rawgit.com/mbostock/queue/master/queue.min.js'],
['jQuery', 'queue']
// In this example, I assume that jQuery is already present on the page,
// so my user-script can piggyback off the existing jQuery reference.
);
// This is where the actual functionality of the user-script is specified.
// Arguments correspond to the dependency references given above.
function __main__($, queue) {
// TODO
}
@sharpedavid
Copy link

Very neat metaprogramming hack. I understand what this achieves, but I'll have to ask you what the alternatives are when you have time.

Thanks for documenting the IIFE: I'd been confused by this convention for some time, but unable to Google it without a name.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment