I was asked an interesting Ender question on IRC (#enderjs on Freenode) and as I was answering it, it occurred to me that the subject would be an ideal way to explain how Ender's multi-library bundling works. So here is that explanation!

The original question went something like this:

When a browser first visits my page, they only get served Bonzo (a DOM manipulation library) as a stand-alone library, but on returning visits they are also served Qwery (a selector engine), Bean (an event manager) and a few other modules in an Ender build. Can I integrate Bonzo into the Ender build on the browser for repeat visitors?

What's Ender?

Let's step back a bit and start with some basics. The way I generally explain Ender to people is that it's two different things:

It's a build tool, for bundling JavaScript libraries together into a single file. The resulting file constitutes a new "framework" based around the jQuery-style DOM element collection pattern: $('selector').method(). The constituent libraries provide the functionality for the methods and may also provide the selector engine functionality.

It's an ecosystem of JavaScript libraries. Ender promotes a small collection of libraries as a base, called The Jeesh, which together provide a large portion of the functionality normally required of a JavaScript framework, but there are many more libraries compatible with Ender that add extra functionality. Many of the libraries available for Ender are also usable outside of Ender as stand-alone libraries.

The Jeesh is made up of the following libraries, each of these also works as a stand-alone library:

domReady: detects when the DOM is ready for manipulation. Provides $.domReady(callback) and $.ready(callback) methods.

Qwery: a small and fast CSS3-compatible selector engine. Does the work of looking up DOM elements when you call $('selector') and also provides $(elements).find('selector'), $(elements).and(elements) and $(elements).is('selector').

Bonzo: a DOM manipulation library, providing some of the most commonly used methods, such as $(elements).css('property', 'value'), $(elements).empty(), $(elements).after(elements||html), and many more.

The Jeesh gives you the features of these four libraries bundled into a neat package for only 11.7 kB minified and gzipped.

The Basics: Bonzo

Bonzo is a great way to start getting your head around Ender because it's so useful by itself. Let's include it in a page and do some really simple DOM manipulation with it.

<!DOCTYPE HTML>
<html lang="en-us">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Example 1</title>
</head>
<body>
<script src="bonzo.js"></script>
<script id="scr">
// the contents of *this* script,
var scr = document.getElementById('scr').innerHTML
// create a
{gfm-js-extract-pre-1}
var pre = bonzo.create('
{gfm-js-extract-pre-2}
{gfm-js-extract-pre-3}')` and we'd end up with two blocks, both responding to the click event.
###Removing Bonzo
It's possible to pull Bonzo out of the Ender build and manually stitch it back together again. Just like we used to do with our toys when we were children! (Or was that just me?)
First, our Ender build is now created with: `ender build qwery bean` (or we could run `ender remove bonzo` to remove Bonzo from the previous example's `ender.js` file). The new `ender.js` file will contain the selector engine goodness from Qwery, and event management from Bean, but not much else.
Bonzo can be loaded separately, but we'll need some special glue to do this. In Ender parlance, this glue is called an Ender **Bridge**.
###The Ender Bridge
Ender follows the basic CommonJS Module pattern -- it sets up a simple module registry and gives each module a `module.exports` object and a `require()` method that can be used to fetch any other modules in the build. It also uses a `provide('name', module.exports)` method to insert exports into the registry with the name of your module. The exact details here aren't important and I'll cover how you can build your own Ender module in a later article, for now we just need a basic understanding of the module registry system.
Using our Qwery, Bean and Bonzo build, the file looks something like this:

Moment.js

Moment.js was mentioned last year on DailyJS but it now has a simple Ender bridge allowing you to pack it neatly into Ender builds for use via $.ender(). Plus, it's an absolutely fantastic library for anything date/time related so it's worth mentioning again. Be sure to scan the docs to see just how much this library can do.

SelectNav.js

SelectNav.js (GitHub: lukaszfiszer/selectnav.js, npm / Ender: selectnav.js) by Lukasz Fiszer is a small library that will convert your website's navigation into a <select> menu. Used together with media queries it helps you to create a space saving, responsive navigation for small screen devices. SelectNav.js is inspired by TinyNav.js for jQuery.

Andrew also has a tiny extension to Bonzo, the DOM utility included in Ender's starter pack (The Jeesh), named ender-remove that simply triggers a 'remove' event when nodes are removed from the DOM. Which can be helpful for performing clean-up actions.

Categorizr.js

Categorizr gives you $.isDesktop()$.isTablet()$.isTV()$.isMobile() methods to determine the current device.

Arbiter

Arbiter (GitHub: iamdustan/arbiter, Licence: MIT, npm / Ender: arbiter) also by Dustan Kasten is a tiny library for managing the HTML5 history interface via pushState(), using AJAX requests to load new content upon request.

Declarative

Declarative (License: MIT, npm: declarative) by Alex Lawrence allows HTML to be mapped to behavioural JavaScript using mappings. The author's first example is a search form with a character counter that uses the following HTML:

Once a mapping has been declared, it can be mapped to the whole DOM using apply:

declarative.apply('counter').to(document);

None of this depends on jQuery, but the author has provided examples that demonstrate jQueryUI integration. Jasmine tests and examples are included in the project's source.

jQR

jQR (GitHub: Gottox / jQR, License: GPL3) by Enno Boland is a QR Code generator for jQuery. It's similar to jquery.qrcode.js by Jerome Etienne, featured previously on DailyJS -- both use the same method name:

$('#qrcode').qrcode('Hello World');

Jerome's plugin includes qrcode.js by Kazuhiko Arase, whereas Enno's plugin is a rewrite that's influenced by Kazuhiko's original code.

Stapes.js

Stapes.js (GitHub: hay / stapes, License: MIT) by Hay Kranen is a small JavaScript MVC framework. Like other recent takes on MVC, it's based around events and inheritance. It also works nicely with RequireJS, jQuery, and Zepto.

//create topic called changeTabEvent and subscribe myFunction
$.radio('changeTabEvent').subscribe(myfunction);
//publish to the topic changeTabEvent
$.radio('changeTabEvent').broadcast(data);
//unsubscribe myFunction from the topic changeTabEvent
$.radio('changeTabEvent').unsubscribe(myFunction);
//do all of the above in one line via chaining
$.radio('changeTabEvent').subscribe(myFunction).broadcast(data).unsubscribe(myFunction);

Event "channels" are created by the main radio() method.
You can then use the three main API calls to interact with the channels: subscribe(), broadcast() and unsubscribe(), each able to take different types and
numbers of arguments.

Radio.js will also work as a stand-alone browser library and in node.js.

one.color

one.color (GitHub:
One-com/one-color, Licence:
BSD, npm / Ender: onecolor) by Peter Müller and One.com is an
amazingly comprehensive color toolkit. It implicitly converts between
RGB, HSV, HSL and CMYK color spaces with or without alpha transparency.
Its API is chainable for composing, adjusting, and serializing color
values. A demo page gives you some
idea of the potential of one.color.

Hypher

Hypher adds soft hyphens to
text strings (Unicode: U+00AD, HTML: &#173; or &shy;) according
to language rules as defined in the patterns objects. Modern browsers
then use these soft hyphens to break words where wrapping is required,
otherwise they are invisible.

Hypher comes with a large number of language patterns
which are also available in the npm repository as hyphenation.lang (e.g. hyphenation.en-us or hyphenation.fr). Simply
include hypher and at least one language pattern in your
Ender build.

// generates 'Hy|phen|ation is use|ful when cen|ter jus|ti|fy|ing a text.'
// where `|` is a soft hyphen
$('<p>Hyphenation is useful when center justifying a text.</p>')
.appendTo('body')
.hyphenate('en-us');

Hypher is also available as a jQuery plugin and will work as a stand-alone
browser library and in node.js.

Tidbits and updates

Some minor notable items since the last Roundup:

Bonzo goes 1.0.0

Bonzo, the DOM manipulation library included in
The Jeesh, has received a lot of minor fixes this week and its test suite has been
significantly expanded, so much that a bump to 1.0.0 seemed appropriate.

Minor Qwery update

Qwery, the selector engine included in
The Jeesh had some minor performance improvements, particularly for IE8,
and can now be configured to turn off use of native querySelectorAll if required: $.configure({ useNativeQSA: false }).

Bean does better delegation

Bean, the event manager included in The
Jeesh, has received some delegation-love, fixing bugs related to clone() and erroneous event.currentTarget
values.

Bean is also likely to see a change in the implementation of on() that will make it (mostly) compatible with the
implementations in Prototype, jQuery and
Zepto.
Further details are available on GitHub.

Ender via CDN

After the flurry of recent activity on core Ender modules, Dustin Diaz has updated the The Jeesh and a
more bulky Ender build on S3 this week, so is these builds suit your
needs then point your script tag to one of these CloudFront URLs:

Twitter's Bootstrap for Ender

Along with the release of Bootstrap
v2, an Ender compatible version
is now available on npm. Unlike the v1.x port, this new version makes
each plugin available separately so you only need to include the ones
you intend to use in your Ender build.

With all plugins installed, a minimal Ender build for full Bootstrap
functionality comes in at a little under half the size of the equivalent
jQuery Bootstrap.

Traversty has no dependencies but will detect the presence of a selector engine if included in the Ender build (officially supports Qwery, SelSizzle and NWMatcher). Without a selector engine, Traversty will rely on native querySelectorAll() and the various vendor-prefixed native matchesSelector() implementations (available everywhere post-IE8).

Traversty can also be used as a stand-alone library:

traversty('li:nth-child(20)').previous('.interesting');

NWMatcher

NWMatcher (npm / Ender: nwmatcher), by Diego Perini is a battle-hardened selector engine with a strong focus on standards compatibility. It's consistently fast across browsers and has continuing support for some very old browsers. NWMatcher became a popular alternative selector engine for Prototype users when the selector engine code was modularised in version 1.7. It continues to have a strong following, particularly amongst purists who appreciate NWMatcher's close adherence to W3C standards.

NWMatcher now has Ender support and is in npm so can be easily included in your Ender builds: ender build nwmatcher undersore bonzo bean

Some of NWMatcher's advanced features are supported directly via Ender:

// adjust NWMatcher's internals
$.configure({ USE_QSAPI: false, VERBOSITY: false });
// a collection containing the first match only, works like
// querySelector() and halts processing upon first match
$.first('div');
// just like calling $('div', root) but will trigger a callback
// function on each match found
$.select('div', root, callback);
// does at least one element in the current collection match
// the given selector?
$('div').match('.someclass');
// alias for .match()
$('div').is('.someclass');
// a new collection of child elements matching the given selector
$('div').find('.someclass');
// a new collection that includes the original collection and
// additional elements matching the given selector
$('div').and('.someclass');

As with all Ender modules, the original library can be accessed via require('nwmatcher'), this gives you the same object as NW.Dom when running outside of Ender.

NWMatcher has no dependencies and can be used as a stand-alone library.

Tidbits

There were a couple of notable updates to Ender modules recently:

Bean

Bean, by Jacob Thornton, is Ender's default event handling library. It received a major internal overhaul and a version bump to 0.4.x. Bean has a new internal registry for storing event handler data and it no longer relies on storing an ID on your DOM elements or your JavaScript objects. There have been some small fixes and optimisations and the inclusion of a new event.stop() method that invokes both event.preventDefault() and event.stopPropagation(), but otherwise the external API remains largely untouched.

Reqwest gets jQuery compatibility

Reqwest, by Dustin Diaz, is Ender's native Ajax library, giving you a jQuery-like $.ajax() method. There are some differences in options between Reqwest and jQuery / Zepto which has caused some pain for jQuery users migrating to Ender and for libraries designed for jQuery integration, such as Backbone.js. In particular, jQuery uses type where Reqwest uses method, jQuery uses dataType where Reqwest uses type. Thankfully, Reqwest now has a compat mode. Calling $.ajax.compat() gives you access to the same option names as jQuery.

Sel gets CSS4

Sel, by Andrew McCollum, a selector engine for Ender, is one of the first selector engines to receive some CSS4 love. Working from the latest working draft, Andrew has enabled some excellent additions to Sel's query syntax: