examples/lib/delegate.js
function Delegate(root) {
		var


			/**
			 * Keep a reference to the current instance
			 *
			 * @internal
			 * @type Delegate
			 */
			that = this,


			/**
			 * Maintain a list of listeners, indexed by event name
			 *
			 * @internal
			 * @type Object
			 */
			listenerList = {};

		if (typeof root === 'string') {
			root = document.querySelector(root);
		}

		if (!root || !root.addEventListener) {
			throw new TypeError('Root node not specified');
		}


		/**
		 * Attach a handler to one event for all elements that match the selector, now or in the future
		 *
		 * The handler function receives three arguments: the DOM event object, the node that matched the selector while the event was bubbling
		 * and a reference to itself. Within the handler, 'this' is equal to the second argument.
		 * The node that actually received the event can be accessed via 'event.target'.
		 *
		 * @param {string} eventType Listen for these events (in a space-separated list)
		 * @param {string} selector Only handle events on elements matching this selector
		 * @param {Object} [eventData] If this parameter is not specified, the third parameter must be the handler
		 * @param {function()} handler Handler function - event data passed here will be in event.data
		 * @returns {Delegate} This method is chainable
		 */
		this.on = function() {
			Array.prototype.unshift.call(arguments, that, listenerList, root);
			on.apply(that, arguments);
			return this;
		};


		/**
		 * Remove an event handler for elements that match the selector, forever
		 *
		 * @param {string} eventType Remove handlers for events matching this type, considering the other parameters
		 * @param {string} [selector] If this parameter is omitted, only handlers which match the other two will be removed
		 * @param {function()} [handler] If this parameter is omitted, only handlers which match the previous two will be removed
		 * @returns {Delegate} This method is chainable
		 */
		this.off = function() {
			Array.prototype.unshift.call(arguments, that, listenerList, root);
			off.apply(that, arguments);
			return this;
		};


		/**
		 * Handle an arbitrary event
		 *
		 * @private
		 * @param {Event} event
		 */
		this.handle = function(event) {
			handle.call(that, listenerList, root, event);
		};
	}
function Delegate(root) {
		var


			/**
			 * Keep a reference to the current instance
			 *
			 * @internal
			 * @type Delegate
			 */
			that = this,


			/**
			 * Maintain a list of listeners, indexed by event name
			 *
			 * @internal
			 * @type Object
			 */
			listenerList = {};

		if (typeof root === 'string') {
			root = document.querySelector(root);
		}

		if (!root || !root.addEventListener) {
			throw new TypeError('Root node not specified');
		}


		/**
		 * Attach a handler to one event for all elements that match the selector, now or in the future
		 *
		 * The handler function receives three arguments: the DOM event object, the node that matched the selector while the event was bubbling
		 * and a reference to itself. Within the handler, 'this' is equal to the second argument.
		 * The node that actually received the event can be accessed via 'event.target'.
		 *
		 * @param {string} eventType Listen for these events (in a space-separated list)
		 * @param {string} selector Only handle events on elements matching this selector
		 * @param {Object} [eventData] If this parameter is not specified, the third parameter must be the handler
		 * @param {function()} handler Handler function - event data passed here will be in event.data
		 * @returns {Delegate} This method is chainable
		 */
		this.on = function() {
			Array.prototype.unshift.call(arguments, that, listenerList, root);
			on.apply(that, arguments);
			return this;
		};


		/**
		 * Remove an event handler for elements that match the selector, forever
		 *
		 * @param {string} eventType Remove handlers for events matching this type, considering the other parameters
		 * @param {string} [selector] If this parameter is omitted, only handlers which match the other two will be removed
		 * @param {function()} [handler] If this parameter is omitted, only handlers which match the previous two will be removed
		 * @returns {Delegate} This method is chainable
		 */
		this.off = function() {
			Array.prototype.unshift.call(arguments, that, listenerList, root);
			off.apply(that, arguments);
			return this;
		};


		/**
		 * Handle an arbitrary event
		 *
		 * @private
		 * @param {Event} event
		 */
		this.handle = function(event) {
			handle.call(that, listenerList, root, event);
		};
	}
DOM event delegator

The delegator will listen for events that bubble up to the root node.

@constructor
@param {Node|DOMWindow|string} root The root node, a window object or a selector string