I think what you are looking for can be accomplished by re-evaluating how you bind your event in the first place. If you really want to see what is happening in the target object, you should be binding the event to the target object.
Having said that, lets try to find you a solution
Digging into the jQuery.event
stuff a little bit I don't see any "easy way" to accomplish this. However it seems the events are cached in the object using jQuery.data(elem,'events')
. There are a few options for you to explore
Copy bound events from one object to another
A potential event copying solution written and tested in jQuery 1.3.2:
(function($){
$.fn.proxyEventsFrom = function(target) {
// cache this for later
var $target = $(target);
return this.each(function() {
// store a copy of the element to use in the event handler callback
var elem = this;
// get a list of events that I subscribe to
var events = $(this).data("events") || {};
$.each(events, function(type, handlers) {
// bind onto this event on the target
$target.bind(type, function(event) {
var evArgs = arguments;
// store the element that event originally fired on in the event object.
event.proxyFrom = this;
$.each(handlers, function(guid, handler) {
var ret = handler.apply(elem, evArgs);
// to behave like other event handlers.
if( ret !== undefined ){
event.result = ret;
if ( ret === false ) {
event.preventDefault();
event.stopPropagation();
return false; // stop our each loop too
}
}
}); // end $.each(handlers, function(guid, handler)
return event.result;
}); // end $target.bind(type, function(event)
});// end $.each(events, function(type, handlers)
});// end this.each(function() {});
}; // end $.fn.proxyEventsFrom
})(jQuery);
$(someObject).proxyEventsFrom(targetObject);
This works by reading all the events that someObject
is listening for, and subsequently binding a new event on the targetObject
of the same event type that will call all of the event handlers on someObject
. The event handler on someObject
can look like this:
$(someObject).bind('alert', function(e) {
if (e.proxyFrom) { alert('Proxied Succesfully!'); }
alert('test');
});
$(someObject).proxyEventsFrom(targetObject);
$(targetObject).trigger('alert');
This approach could easily generate a recursive loop of event handlers if you proxied events to something that proxied back. Be careful.
Overriding jQuery.event.trigger
It is possible to override the event triggering function to accomplish what you desire, although I suggest against it for a few reasons: It is dangerous to override things in libraries, You'll end up with a lot more stuff than you want, and this function will only get called for uses of .trigger()
obviously - therefore doesn't apply to standard DOM events.
(function() { // wrap this in a closure so origTrigger can't be overwritten.
var origTrigger = jQuery.event.trigger;
jQuery.event.trigger = function(event, data, elem, bubbling)
{
if (elem === origTarget) {
if (origTrigger.call(this, event, data, otherObject, bubbling) === false) return;
}
return origTrigger.apply(this,arguments);
}
})();
Make the events of the target === the events of the other object
If the origTarget wont ever have events of its own bound you could copy the events object by reference.
// copy the events table by reference from otherObject "events" data
// (create if neccesary)
$.data(origTarget, 'events',
$.data(otherObject,'events') || $.data(otherObject,'events',{}));
// need to setup handler since jQuery isn't creating it for us
// function source found on line 2465 of jquery-1.3.2.js
var handle = $.data(origTarget, 'handle', function(){
return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
jQuery.event.handle.apply(arguments.callee.elem, arguments) :
undefined;
});
handle.elem = origTarget;
Custom 'handle' function
It was a long road to this solution, internally all jQuery events get passed through a 'handle' function that is stored in the $.data(elem, 'handle')
. So if you override that function on your target, you should be able to proxy the events over to the other object. This solution assumes you only ever have one extra listener, it could be adapted to have more than one listener pretty easily though. I think this is the best approach I've come up with yet:
jQuery.event.proxyEvents = function(fromObject, toObject) {
// create an new handle function
var newHandle = function(event) {
// the test in the original handler returns undefined if jQuery.event.triggered
if (jQuery.event.triggered) return undefined;
// event should be safe - but just in case lets take a trick from
// jQuery.event.handle
event = arguments[0] = jQuery.event.fix(event || window.event);
// if we have a "listener"
if (arguments.callee.listener) {
// set proxyFrom for access in bound event handlers
event.proxyFrom = arguments.callee.elem;
// call the root "handle" function on the listener
jQuery.event.handle.apply(arguments.callee.listener, arguments);
// if we got a result of false from the event callbacks - exit early
if (event.result === false) return;
// clean that proxy property out
delete event.proxyFrom;
}
// this is all the basic 'handle' function does:
jQuery.event.handle.apply(arguments.callee.elem, arguments);
};
// properties of the handler function
newHandle.elem = fromObject;
newHandle.listener = toObject;
// store it
jQuery.data(fromObject, 'handle', newHandle);
};
jQuery.event.proxyEvents(origTarget, otherObject);
It even works with DOM Elements (although you need to pass the element, not a jQuery object)
jQuery.event.proxyEvents($('span')[0], $('input')[0]);