Skip to content

Using curl.js with jQuery

briancavalier edited this page Jan 10, 2012 · 8 revisions

Using curl.js with jQuery

As of jQuery 1.7.1, curl.js and jQuery get along great!

However, if you're not experienced with modular programming, there are a few important things to know:

You must map the path to jquery.js when configuring curl.js.

jQuery registers itself as an absolutely named module. curl.js (as well as any other AMD loader) ensures that the correct module got loaded by comparing the id of the requested module with the module that was actually loaded. Since jQuery registers itself with the name, "jquery", all modules that list jQuery as a dependency must also refer to it by the exact same name. Trying to refer to jQuery as any of the following module ids will fail:

  • "js/vendor/jQuery/jquery" (BAD: path is included)
  • "jQuery" (BAD: capitalization is different)
  • "jquery.1.7.1.min" (BAD: extra filename bits)

The best way to ensure all code can correctly refer to jQuery as "jquery", you should add the following path mapping to curl.js's config:

paths: {
	"jquery": "js/vendor/jQuery/jquery.1.7.1.min"
}

Path mappings allow modules to find dependencies without knowing their exact locations or file names.

Here's a full example:

curl(
	{
		baseUrl: "myApp",
		paths: {
			"jquery": "../jQuery1.7.1/jquery.min"
		}
	},
	["jquery", "main"],
	function ($, main) {
		main.init();
		$('html').removeClass('loading');
	}
);

$ and jQuery are no longer available as global variables.

If your code -- or third-party code -- relies on the $ or jQuery global variables, they will fail. When loaded as an AMD module, jQuery will not create these globals. To fix this, your code and any third-party code you're using should be rewritten as modules.

There's a work-around for mixing modules and non-modules, but you're only complicating your code by using the work-around. You're also just delaying the inevitable anyways:

The javascript community is embracing modules. Your global hackfest must come to an end.

The easiest way to convert your global hackfest to be module-ish is to wrap each file in a define() call:

define(['jquery'], function ($) {
	// your not-very-modular code goes here
	// return something useful to code that depends on this code
});

If you were already using the "module pattern" (which is only somewhat modular) or were wrapping your code in closures in order to limit the leakage of variables into the global scope, then your code will end up looking more like this:

(function (global) {

	// you can put code here that could run before the dom is ready

	define(['jquery'], function ($) {
		// most of your code goes here
		// return something useful!
	});

	// don't put code down here unless it is totally unrelated to
	// whatever you returned from the define(). dependent modules could be
	// executed before this code runs!

}(this));

It's fairly easy to wrap most third-party plugins this way, too. However, most jQuery plugin creators are planning to wrap their modules already. Check with your plugin creators to find out when they plan to support AMD and/or UMD module formats.

If you're seriously desperate to get curl.js working with jQuery plugins, you can also do something like this:

curl(
	{
		baseUrl: "myApp",
		paths: {
			"jquery": "../jQuery1.7.1/jquery.min",
			"plugin": "../third-party"
		}
	},
	["jquery"],
	function ($, main) {
		// expose $ and jQuery globally (ewww!):
		window.$ = window.jQuery = $;
	}
).next(
	// load plugins
	["main", "js!plugin/foo.js", "js!plugin/bar.js"],
	function (main) {
		// code executed by main.init() can use plugins safely:
		main.init();
		// $ is global now:
		$('html').removeClass('loading');
	}
);

This method is slower than using pure modules, but should work for most jQuery plugins.

curl.js does not prevent conflicts with third-party scripts that may load other versions of jQuery as an AMD module.

There is no equivalent to $.noConflict() when jQuery is loaded as an AMD module. Whichever version is loaded first is the version that is used on the page. At the moment, this is not a problem. There are only two versions of jQuery that are AMD-aware: 1.7.0 and 1.7.1.

However, in the future, if your code relies on a third-party script that attempts to load jQuery 1.8.3 (for instance), but your code is using 1.7.4, then the third-party script may fail if it is relying on features in 1.8.3.

curl.js 0.6 will introduce a feature that allows you to configure separate configuration options per "package". (A package is a formal or informal grouping of modules.) One of these options is the specific jQuery version that the package requires. As of curl.js 0.6.3, you will be able to manage each package's version of jQuery separately and provide the one needed by each package.