Permalink
Browse files

Initial commit

  • Loading branch information...
0 parents commit f8fa1e4807860f2ef7ac2b519c0ae2427c9edbbd @nickstenning committed Aug 13, 2008
Showing with 546 additions and 0 deletions.
  1. +54 −0 README.md
  2. +58 −0 examples/textsize.html
  3. +28 −0 lib/controller.js
  4. +73 −0 lib/delegator.js
  5. +333 −0 vendor/mootools-1.2-core.js
@@ -0,0 +1,54 @@
+MooDelegate
+===========
+
+A simple library for event delegation using the
+(MooTools)[http://mootools.net] JavaScript library. At it's simplest,
+delegator.js implements a #delegate method on Element, so you can call:
+
+$('myelement').delegate('li.delete', 'click', function () {
+ this.dispose();
+});
+
+This would make sure that any child of 'myelement' that was a list item with
+the class "delete" would be removed from the DOM when it was clicked. This
+applies no matter when the list item was added to the DOM: even if it was
+added *after* the call to delegate.
+
+A more advanced (and yet simpler) way to use MooDelegate is to use the
+included Controller class:
+
+HTML:
+
+ <div id="textsizeController">
+ <span>Hello</span>
+ <button id="bigger">Bigger</button>
+ <button id="smaller">Smaller</button>
+ </div>
+
+JS:
+
+ var TextSizeController = new Class({
+ Extends: Controller,
+
+ // ... see examples/textsize.html for the full example.
+
+ controls: {
+ '#bigger click': function () {
+ this.increaseSize();
+ },
+ '#smaller click': function () {
+ this.decreaseSize();
+ }
+ }
+
+ });
+
+ window.addEvent('domready', function () {
+ new TextSizeController($('textsizeController'));
+ });
+
+
+OK, so it's a silly example, but you should get the idea. Once you've made
+that call to new TextSizeController in the above example, you could remove the
+"bigger" button from the DOM, to prevent the user making the text bigger, and then put it back in, and it would work just as expected.
+
@@ -0,0 +1,58 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html>
+ <head>
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+ <title>TextSize Controller Demo</title>
+ <script src="../vendor/mootools-1.2-core.js" type="text/javascript" charset="utf-8"></script>
+ <script src="../lib/delegator.js" type="text/javascript" charset="utf-8"></script>
+ <script src="../lib/controller.js" type="text/javascript" charset="utf-8"></script>
+
+ <script type="text/javascript" charset="utf-8">
+
+ var TextSizeController = new Class({
+ Extends: Controller,
+ span: function () {
+ return this.element.getElement('span');
+ },
+ adjustSize: function (change) {
+ this.span().setStyle('font-size',
+ this.span().getStyle('font-size').toInt() + change);
+ },
+ increaseSize: function () {
+ this.adjustSize(1);
+ },
+ decreaseSize: function () {
+ this.adjustSize(-1);
+ },
+
+ controls: {
+ '#bigger click': function () {
+ this.increaseSize();
+ },
+ '#smaller click': function () {
+ this.decreaseSize();
+ }
+ }
+
+ });
+
+ window.addEvent('domready', function () {
+ new TextSizeController($('textsizeController'));
+ });
+ </script>
+ </head>
+ <body>
+
+ <div id="textsizeController">
+ <p>
+ <span>Hello</span>
+ </p>
+ <p>
+ <button id="bigger">Bigger</button>
+ <button id="smaller">Smaller</button>
+ </p>
+ </div>
+
+ </body>
+</html>
@@ -0,0 +1,28 @@
+var Controller = new Class({
+
+ controls: {},
+
+ initialize: function (element, controls) {
+ this.element = element;
+ this.element.store('app:controller', this);
+ this.setControls(controls);
+ this.delegateControls();
+ },
+
+ setControls: function (controls) {
+ this.controls = $merge(this.controls, controls);
+ },
+
+ delegateControls: function () {
+ $each(this.controls, function (fn, desc) {
+ var desc = desc.trim().split(" "), type = desc.pop(), selector = desc.join(" ");
+ this.element.delegate(selector, type, fn, this);
+ }, this);
+ }
+});
+
+Element.implement({
+ controller: function () {
+ return this.retrieve('app:controller');
+ }
+});
@@ -0,0 +1,73 @@
+var Delegator = new Class({
+
+ quirks: {
+ focus: 'handleFocus',
+ blur: 'handleBlur',
+ reset: 'handleFormAction',
+ submit: 'handleFormAction'
+ },
+
+ initialize: function(element, selector, type, fn, binding) {
+ this.element = $(element);
+ this.type = type;
+ this.selector = selector;
+ this.fn = fn;
+ this.binding = binding;
+
+ this.eventHandler = function (e) {
+ if (e.target.match(selector)) {
+ return fn.apply($pick(binding, $(e.target)), [e]);
+ }
+ };
+ },
+
+ delegate: function () {
+ $pick(this[this.quirks[this.type]], this.handle).apply(this);
+ return this.element;
+ },
+
+ handle: function () {
+ this.element.addEvent(this.type, this.eventHandler);
+ },
+
+ handleFocus: function () {
+ if (Browser.Engine.trident) {
+ this.element.onfocusin = this.eventHandler;
+ } else {
+ this.handleCapture();
+ }
+ },
+
+ handleBlur: function () {
+ if (Browser.Engine.trident) {
+ this.element.onfocusout = this.eventHandler;
+ } else {
+ this.handleCapture();
+ }
+ },
+
+ handleCapture: function () {
+ // The last argument to addEventListener causes the event to be raised
+ // on capture, rather than on bubble. See http://tinyurl.com/636x4d
+ this.element.addEventListener(this.type, this.eventHandler, true);
+ },
+
+ handleFormAction: function () {
+ this.element.addEvent('click', function (e) {
+ // If target element is an {input,button} with type this.type, which
+ // will be either reset or submit, raise the event on the element's
+ // form.
+ if ( $(e.target).match('[type=' + this.type + ']') &&
+ $(e.target.form).match(this.selector) ) {
+
+ return this.fn.apply($pick(this.binding, $(e.target.form)), [e]);
+ }
+ }.bind(this));
+ }
+});
+
+Element.implement({
+ delegate: function (selector, type, fn, binding) {
+ return new Delegator(this, selector, type, fn, binding).delegate();
+ }
+});
Oops, something went wrong.

0 comments on commit f8fa1e4

Please sign in to comment.