I've been watching the threads discussing event delegation as I think
it's a great way to speed up apps.

All of the solutions I've seen take a similar approach in using a CSS
selector to match elements for the event, and a parent element to
attach the event to.

I thought I'd try a different approach, namely using a single event
attached to the document and using an API identical to Event.observe
to register the events.

My first bash at this code is below, a fair bit of lifted from
Prototype's event handling. I've called this Event.register rather
than Event.delegate to avoid any confusion in the differing approach
to other event delegation.

// Event.register

Object.extend(Event, (function(){
  var registerable = $w('click mouseover');
  var cache = {};

  function getEventID(element) {
    if (element._prototypeEventID) return element._prototypeEventID
[0];
    arguments.callee.id = arguments.callee.id || 1;
    return element._prototypeEventID = [++arguments.callee.id];
  }

  function getCacheForID(id) {
    return cache[id] = cache[id] || { };
  }

  function getWrappersForEventName(id, eventName) {
    var c = getCacheForID(id);
    return c[eventName] = c[eventName] || [];
  }

  function dispatch(e){
    var element = e.target;
    while(!e.stopped && element && element.nodeType == 1){
      var id = getEventID(element);
      var c = getWrappersForEventName(id, e.type);
      c.invoke('call', this, e);
      element = element.up();
    }
  }

  function initialize(e){
    registerable.each(function(eventName){
      document.observe(eventName, dispatch);
    });
  }

  function register(element, eventName, handler){
    var id = getEventID(element);
    var c = getWrappersForEventName(id, eventName);
    if (c.pluck("handler").include(handler)) return false;
    var wrapper = function(event){
      handler.call(element, event);
    };
    wrapper.handler = handler;
    c.push(wrapper);
    return wrapper;
  }

  document.observe('dom:loaded', initialize);

  return {
    register : function(element, eventName, callback){
      element = $(element);
      if(registerable.include(eventName)){
        register(element, eventName, callback);
        return element
      }else{
        return Event.observe(element, eventName, callback);
      }
    }
  };
})());

// Example usage

function log(e){
  console.log(e.target);
}

$$('a').each(function(link){
  Event.register(link, 'click', log);
});

I'd be interested to hear any feedback about my approach, in
particular about any potential performance pitfalls this may cause.
It's a first bash, and I've not tested it outside of Firefox.


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Prototype: Core" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to