Created
February 18, 2009 21:49
-
-
Save RStankov/66568 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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 }); | |
})(); |
:)
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
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!