Wednesday, April 11, 2012

Copy jQuery click event from one element to another



Today I had to solve a task wich seemed to be quite easy... I had to copy a "click" event from an element. To copy an "onclick" attribute...it's a piece of cake. BUT, how do you copy a jQuery "click" event?

I found an interesting conversation about this problem here, but I couldn't find a solution for my problem:
http://forum.jquery.com/topic/how-do-i-copy-the-click-event-from-one-element-to-another.

I'm not 100% sure you understand my problem, so here are some example codes:


This is a common "a" tag with an onclick attribute:

<a href="javascript:void(null)" onclick="alert('onclick event triggered')" id="test_element">Trigger OnClick</a>

This click event can be copied with this code:

jQuery("#test_element").attr("onclick")




BUT, what's the case with this method?

<a href="javascript:void(null)" id="test_element">Trigger OnClick</a>

And with this Javascript:

jQuery("#test_element").click(function() {
    alert("jQuery click event triggered");
})




How do I copy this click event?

Well, I dove in jQuery-s source code because I knew it can be done. jQuery has a .clone() function which has an attribute to decide, whether to copy the events too or not. This is what I found:

function cloneCopyEvent( src, dest ) {

 if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
  return;
 }

 var type, i, l,
  oldData = jQuery._data( src ),
  curData = jQuery._data( dest, oldData ),
  events = oldData.events;

 if ( events ) {
  delete curData.handle;
  curData.events = {};

  for ( type in events ) {
   for ( i = 0, l = events[ type ].length; i < l; i++ ) {
    jQuery.event.add( dest, type, events[ type ][ i ] );
   }
  }
 }

 // make the cloned public data object a copy from the original
 if ( curData.data ) {
  curData.data = jQuery.extend( {}, curData.data );
 }
}


The most interesting part is this:

oldData = jQuery._data( src ),
curData = jQuery._data( dest, oldData ),
events = oldData.events;


The events are saved inside (jQuery._data( src )).events. To stay by my example, the solution will look like this:

(jQuery._data( jQuery("#test_element")[0] )).events.click[0].handler


This way I can make a copy of the function bound to the element. And of course, if there are more bindings to one element, they can be reached with "...click[1].handler", "...click[2].handler", etc.


I hope this little trick helped you too.





No comments:

Post a Comment