novel, open, next level, modular JavaScript. no-library library
Clone or download
Pull request Compare This branch is 425 commits behind ender-js:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


Ender is not a JavaScript library in the traditional sense. So don't rush out and try to replace jQuery or MooTools with Ender... It just wouldn't work.... But! you can build a library from Ender which will. And you should. right now.

That's because: Ender is an open, powerful, micro-to-macro API for composing your own custom JavaScript library; it wraps up application agnostic, independent modules into a slick, intuitive, and familiar interface so you don't have to.


Because in the browser - small, loosely coupled modules are the future, and large, tightly-bound monolithic libraries are the past!

Ponder this... Ender is unique and important in two key ways:

  1. Ender provides front end developers with a true package management system and the powerful command line tools necessary to back it up... making your library maintenance tasks simple, painless, and fast.

  2. Ender offers a way to bring together the awesome work happening in small frameworks and libraries that otherwise do only one thing, and allows you to mix, match, and customize your own library suited to your individual needs without all the extra cruft that comes with larger libraries.

With Ender, if one part of your library goes bad or unmaintained, it can be replaced with another. Need a specific package version? no big deal. Want to load all your packages asynchronously to cut down on page load? Ender can do that for you too.


Before you do anything, you're going to need to install Ender. Ender is built with NodeJS and leverages NPM heavily for all that slick package management. What this means is that to use Ender you're going to first need to have both NodeJS and NPM installed (if you haven't already).

Once you have those, simply run:

$ npm install ender

or if you're a boss (you know you are) and you're using the latest npm 1.0 rc:

$ npm install ender -g

This will install Ender as a CLI (command line) tool. So let's get to it...


Ender provides a whole slew of methods for building, updating, and slimming down your libraries. Let's take a look...

Build (-b, build)

As the name suggests, build is responsible for building your libraries. To use it, navigate to the directory you would like to build into and run something like:

$ ender build scriptjs qwery underscore

When building you can include as many packages as you like. This will generate three things of interest to you:

  • an uncompressed ender.js file,
  • a compressed ender.min.js
  • a node_modules dir (if there wasn't already one present).

With build, the ender.js files will include all packages inlined for his development pleasure.

note: The node_modules folder is the directory NPM uses for installing packages. Keeping this makes building your ender files faster, but is otherwise optional. If you'd prefer to have this directory cleaned up after your build checkout the just method below.

Just (-j, just)

The just method is exactly the same as build, except it will remove the node_modules folder after it has completed building. Use this if you don't plan on rebuilding ender very often or are worried about directory sizes on your machine. Using just, looks like:

$ ender just scriptjs qwery underscore

This will generate

  • an uncompressed ender.js file
  • a compressed ender.min.js file.

note: just will completely remove the node_modules folder itself... think rm -rf... so use at your own risk

Async (-a, async)

The async method generates a library which asynchronously loads its packages using script.js. This is clutch when trying to cut down on initial page loads. To build an async library, run something like:

$ ender async domready qwery underscore

Each package is then loaded using script.js's "new school" style of loading and given a special 'ender' event which you can later hook into by using Ender's ready method -- check it out below:

$.ready('ender', function() {
  //all ender packages have loaded async...
  $('#container').emit('click'); //boosh

note: a module must have a bridge file to be asynchronously loaded

If you weren't already, it may be a good idea to get familiar with the script.js API.

note: There is no need to include script.js when using the async build method -- it will be included by default

Info (-i, info, list)

info will give you the current status of your built Ender library. This information includes

  • the build type
  • gzipped file size
  • a list of all the current packages (with version numbers and descriptions).

To run info, change directories into your ender installation and type:

$ ender info

Add (+, add, set)

It's not always possible to know which packages you may or may not want when beginning a new project and ender wants to encourage you to be as agile as possible! Build your initial library light and push in more packages whenever you run into the need. To do this, use Ender's add method. Run:

$ ender add backbone

The above will append backbone to your existing ender.js and ender.min.js builds. You may also use add to update (or rollback) a package to a particular version:

$ ender set bean@0.0.3

Remove (-d, remove)

Removing packages is sometimes even more important than pushing them on! To remove a package from your current build, simply run:

$ ender remove backbone

Refresh (., refresh)

The refresh method will refresh your library with the latest stable builds from your activated packages. Just run:

$ ender refresh

Help (help)

help, as you might expect, gives you a simple run through of the available methods.

$ ender help


Ender supports package versioning through npm. To install a project at a specific version simply include the version number, prefixed by an '@':

$ ender build qwery bean@0.0.2 underscore

To remove a versioned package no need to include the version number

$ ender remove bean

Also, as you might expect, you can also include versions when adding packages to an already existing build:

$ ender add underscore@0.1.0


Because Ender relies on NPM for package management -- extending your ender library is as simple as publishing to NPM -- let's check it out.


If you haven't already registered your project with NPM, create a file called package.json in your package root. A completed package file should look something like this:

  "name": "blamo",
  "description": "a thing that blams the o's",
  "version": "1.0.0",
  "homepage": "",
  "authors": ["Mr. Blam", "Miss O"],
  "repository": {
    "type": "git",
    "url": ""
  "main": "./src/project/blamo.js",
  "ender": "./src/exports/ender.js"

Have a look at the Qwery package.json file to get a better idea of this in practice.

An important thing to note in this object above is the special ender property ender. This property points to your bridge file, an integration file which Ender uses to connect your package code with the ender-js object. If you don't provide this integration file, or if you're trying to include a package which wasn't intended to work with Ender, no worries! Ender will automatically default to a CommonJS module integration and add the exported methods directly to ender as top level methods. More on this below.

The bridge

The bridge is an optional javascript integration file used to connect your code with the ender-js api. The ender-js api is detailed below.

note: The bridge is required for asynchronously loading your package with the async build method.


The front end API provided by ender-js is what glues together and ultimately offers cohesion and a sense of familiarity to the different packages built into your library by Ender. It's simple, elegant, and super flexible. Let's take a look how you can leverage it, if you're interested in packaging your own stuff!

Top level methods

To create top level methods on the ender-js object ($) you can hook into it by calling the ender method:

  myUtility: myLibFn

The above code would provide $.myUtility()

The Internal chain

Another common desire for developers is to be able hook into the internal collection chain. To do this, simply call the same ender method above, but pass true as the second argument:

$.ender(myExtensions, true);

Within the scope of your extension methods, the internal prototype will be exposed to the developer with an existing elements instance property representing the node collection. This looks something like this in practice:

  rand: function () {
    return this.elements[Math.floor(Math.random() * this.elements.length)];
}, true);


You might consider having a look at how the Bonzo DOM utility utilizes this feature.

Selector Engine API

Ender-js also exposes a unique privileged variable called $._select, which allows you to set the ender-js selector engine. Setting the selector engine provides ender-js with the $ method, like this:

$('#foo .bar')

Setting the selector engine is done like so:

$._select = mySelectorEngine;

You can see it in practice in Qwery

This is great news if you're building a Mobile Webkit or Android application, simply set it to querySelectorAll:

$._select = function (selector, root) {
  return (root || document).querySelectorAll(selector);


The Jeesh is like a booster pack for ender. At only 10k the Jeesh can help you build anything from small prototypes to providing a solid base for large-scale rich application for desktop and mobile devices. At it's core, it's a collection of packages that we've found particularly useful for major use-case development endeavors -- but we encourage use to add and remove packages to really make it your own. Currently, the Jeesh includes:


DOM queries

$('#boosh a[rel~="bookmark"]').each(function (el) { ... });


$('#boosh p a[rel~="bookmark"]').hide().html('hello').css({
  color: 'red',
  'text-decoration': 'none'


$('#content a').bind('keydown input', handler);
$('#content a').emit('customEvent');
$('#content a').remove('click.myClick');


var Person = $.klass({
  walk: function () { ... }
var SuperHuman = Person.extend({
  walk: function () {
  fly: function () {}
(new SuperHuman('bob')).walk();


$.ajax('path/to/html', function (resp) {
  url: 'path/to/json',
  type: 'json',
  method: 'post',
  success: function (resp) {
  failure: function () {}

script loading

$.script(['mod1.js', 'mod2.js'], 'base', function () {
  // script is ready

// event driven. listen for 'base' files to load
$.script.ready('base', function () {



// uses native CSS-transitions when available
  opacity: 1,
  width: 300,
  color: '#ff0000',
  duration: 300,
  after: function () {


Utility methods provided by underscore are augmented onto the '$' object. Some basics are illustrated:

$.map(['a', 'b', 'c'], function (letter) {
  return letter.toUpperCase();
}); // => ['A', 'B', 'C']

$.uniq(['a', 'b', 'b', 'c', 'a']); // => ['a', 'b', 'c']

$[65 other methods]()

No Conflict

var ender = $.noConflict(); // return '$' back to its original owner


If you're looking to test drive this setup, have a play with the compiled source

<iframe id="fiddle-example" src=""></iframe>


We would love to hear how you're using ender or why you're not. What you love... what you hate... And we would love all the help we can get! Got a great idea? Open an issue, submit a pull request, or message us on twitter!


Ender is licensed under MIT - copyright 2011 Dustin Diaz & Jacob Thornton

For the individual modules, see their respective licenses.



that's correct, you're doom!