Skip to content

Instantly share code, notes, and snippets.

@RStankov
Created February 18, 2009 21:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save RStankov/66568 to your computer and use it in GitHub Desktop.
Save RStankov/66568 to your computer and use it in GitHub Desktop.
(function(){
function delegateHandler(e){
((this.retrieve('prototype_delegates') || $H()).get(e.eventName || e.type) || []).each(function(pair){
if (element = e.findElement(pair.key)){
pair.value.invoke('call', element, e, element);
}
});
}
function delegate(element, selector, event, handler){
element = $(element);
var store = Element.retrieve(element, 'prototype_delegates');
if (Object.isUndefined(store)){
Element.store(element, 'prototype_delegates', store = $H());
}
var eventStore = store.get(event);
if (Object.isUndefined(eventStore)){
Event.observe(element, event, delegateHandler);
store.set(event, $H()).set(selector, [handler]);
} else {
(eventStore.get(selector) || eventStore.set(selector, [])).push(handler);
}
return element;
}
function clearEvent(element, store, event){
store.unset(event);
Event.stopObserving(element, event, delegateHandler);
};
function clearSelector(element, store, selector, event, estore){
estore.unset(selector);
if (estore.values().length == 0){
clearEvent(element, store, event);
}
}
// stopDelegating(element[, selector[, event[, handler]]])
function stopDelegating(element, selector, event, handler){
element = $(element);
var store = Element.retrieve(element, 'prototype_delegates');
if (Object.isUndefined(store)) return;
switch(arguments.length){
case 1: store.each(function(pair){ clearEvent(element, store, pair.key); }); break;
case 2: store.each(function(pair){ clearSelector(element, store, selector, pair.key, pair.value); }); break;
case 3:
var estore = store.get(event);
if (estore) clearSelector(element, store, selector, event, estore);
break;
default:
case 4:
var estore = store.get(event);
if (!estore) return;
var sstore = estore.get(selector);
if (sstore){
sstore = sstore.reject(function(c){ return c == handler; });
if (sstore.length > 0){
estore.set(selector, sstore);
} else {
clearSelector(element, store, selector, event, estore);
}
}
}
}
// expose
document.delegate = delegate.methodize();
document.stopDelegating = stopDelegating.methodize();
Event.delegate = delegate;
Event.stopDelegating = stopDelegating;
Element.addMethods({ delegate: delegate, stopDelegating: stopDelegating });
})();
@metaskills
Copy link

I just saw this link from my "Unobtrusive JS In Rails 3 With Prototype":http://metaskills.net/2010/1/29/unobtrusive-js-in-rails-3-with-prototype article. Really clean stuff and delegation is something I have to get better at, especially when adding/removing elements. BTW, I just noticed that Element.on in the new 1.7 RC of prototype. Cheers!

@RStankov
Copy link
Author

:)

Yes 1.7 will have Event.on, but before there wasn't such method available. If you are interested you can check my CD3.Behaviors ( http://github.com/RStankov/controldepo-3-widgets/blob/master/src/behaviors.js )
It has event delegation build in ( soon I will update it to use Event.on ). With it you could something like:

CD3.Behaviors({
    'body:click': {
        'a[data-method=delete]': MyJsObject.linkToDelete
    }
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment