jQuery, YUI-style
/*
* Assuming requireJS or another AMD loader
* The idea is to have each jQuery.require() call have its own copy of jQuery
* and all loaded modules copied into it, that way each call has its own "sandbox"
*/
(function (require, define) {
/*
* Optionally define a global config
* Configuration is basically tiered into three levels that overwrite each other in this order:
* 1. An internal configuration object
* 2. The configuration defined in jQuery.GlobalConfig
* 3. The configuration provided in the jQuery.require() call
*/
if (!jQuery.GlobalConfig) {
jQuery.GlobalConfig = {};
}
/**
* Creates a new jQuery.sub() and loads modules on it
*/
jQuery.require = function () {
var $ = this.sub(),
/*
* Accessing directly "window" or "document" is a bad idea because
* the code can be wanted to reference the document inside an iframe
* Avoid them and use $.config.win or $.config.doc
*/
opts = {
win: window,
doc: document
};
/**
* Each sub() has a require function that can be called at any time
* and it will enhance that particular sub with extra modules
* jQuery.require() is then only a wrapper for creating a new sub and calling that sub's require function
*/
$.require = function (config, modules, callback) {
var self = this;
// Mimic requireJS optional arguments
if (arguments.length === 2) {
if (jQuery.isFunction(modules)) {
callback = modules;
if (jQuery.isArray(config)) {
modules = config;
config = {};
} else {
modules = [];
}
}
} else if (arguments.length === 1) {
if (jQuery.isFunction(config)) {
callback = config;
modules = [];
config = {};
} else if (jQuery.isArray(config)) {
modules = config;
config = {};
}
}
// overwrite configuration options
this.config = this.extend(opts, jQuery.GlobalConfig, config);
require(opts, modules, function () {
for (var i = 0, length = arguments.length; i < length; i++) {
arguments[i](self);
}
if (callback) {
callback(self);
}
});
return this;
};
return $.require.apply($, arguments);
};
/**
* Modules must always be functions that will be later called on each jQuery sub
*/
jQuery.define = function () {
var args = Array.prototype.slice.call(arguments),
fn = args.pop();
args.push(function () {
return fn;
});
define.apply(this, args);
};
}(curl, curl.define)); // for example, curl could be used as a AMD loader
jQuery.define('hello', function ($) {
$.sayHi = function () { console.log('hi'); };
});
jQuery.require(['hello'], function ($) {
console.log($ === jQuery); // false
console.log($.require === jQuery.require); // false
$.sayHi();
var previousSayHi = $.sayHi;
jQuery.require(['hello'], function ($) {
console.log(previousSayHi === $.sayHi); // false
});
});