From your comment:
I just can't see how this is achieved when you have to tell the subject which elements to trigger by selectors instead of the subject having a list that the observer can register to
Please correct me if I'm wrong, but you seem to be misunderstanding how the pattern was implemented in jQuery. You don't "tell the subject which elements to trigger", and the subject doesn't have "a list that the observer can register to" either. It works like this:
- The subject/publisher emits/triggers certain events (on certain circumstances you define).
- The observer/subscriber listens to certain events. It keeps a list of the events it subscribed to.
- That's all based on DOM events, so it's limited by the DOM Event Model.
For example, consider the following HTML:
<div id="div1">div 1</div>
<div id="div2">div 2</div>
Let's make the inner divs trigger a custom event called 'custom'
. You define when that should happen, on this example this will happen when they are clicked:
$('div').on('click', function(e) {
$(this).trigger('custom');
});
Now let's make the document
element subscribe to that custom event:
$(document).on('custom', function(e) {
console.log('document is handling custom event triggered by ' + e.target.id);
});
When the custom event is triggered by one of the divs, the observer/subscriber is notified and a message is logged to the console.
The example uses document
as the observer for a reason: events bubble up the DOM tree, and can only be caught by elements that are ancestors of the one that triggered it. Since document
is the root of the DOM tree, it can see all events. If #div1
was our observer, it would only see events triggered by #div1
itself, but not the ones triggered by #div2
.
Maybe that limitation is what confused you?
There are ways to circumvent that limitation, but usually, if you want to do something to #div1
based upon an event triggered by #div2
, you just do it from the callback you have setup on the document
element (or the closest common ancestor to both divs). Anyway, it seems you really want an alternative, so here is one in the form of a jQuery plugin:
$.fn.observe = function(eventName, callback) {
return this.each(function(){
var el = this;
$(document).on(eventName, function(){
callback.apply(el, arguments);
})
});
}
You can use it like this:
$('#div1').observe('custom', function(e) {
// do something
});
Live example: http://jsfiddle.net/JwJsP/1