Copying Events From One JavaScript Element To Another JavaScript Element

Problem Statement

We have a situation where we cannot access the methods that are calling the event handler of an element that is needed for a new element. For this, we need to bind specific events, like click and onchange, of one element to another element. 


Before learning the solution for this, I would like to share some scenarios where I  benefitted from this approach.
In one of my applications, the functionality is defined as - there is a dropdown where I am filling the data from the back-end data store and binding a Click event with some methods which are private to this scope. Now, in another scenario, I am forced to refresh the panel but shouldn't reload this dropdown data. So, the only solution is to have a variable holding this drop-down's inner HTML and once the panel is refreshed, reset this drop-down's inner HTML back to it. In this process, we are losing all the events bound dynamically.
So, I thought of having a copy of events before refreshing the panel and again, re-binding the same events to the drop-down. Before going to the solution, we need to understand about jQuery._data() method. Below is a short explanation of this method.
jQuery internally maintains all the events' information that is attached or detached for each individual element in the DOM. The _data() is the internal (or private) method of jQuery that is used to access all the event-related data of a given DOM element.
Before jQuery 1.8, all the events could be accessed with public method. Now, with jQuery 1.8 and above, they are not allowed to access the event information using data() method because of the removal of the conflicts of having the same names for the data variable and event names. Instead, we can access all the events by calling _data() method (method starts with '_' symbol represents a private and undocumented method). 
For example, if we want to read the event information from an element id 'myele', we use this code.
  1. $._data($("#myele"), "events");    
  2. //or    
  3. jQuery._data($("#myele"), "events");    
Hah, now we are good to understand the following solution to our problem. In the following generic method, we are trying to push all the specific events (Click event) of a given element and returning the same.
  1. var eleEvents = getEvents("click", $('#divpanel').find('li a')[0]);    
  2. var getEvents = function(eventType, eleSource) {    
  3.     var eleEvents = [];    
  4.     var allEvents = jQuery._data(eleSource, "events");    
  5.     if (typeof allEvents === "object") {    
  6.         if (typeof allEvents[eventType] === "object") {    
  7.             for (var i = 0; i < allEvents[eventType].length; i++) {    
  8.                 eleEvents.push(allEvents[eventType][i].handler);    
  9.             }    
  10.         }    
  11.     }    
  12.     return eleEvents;    
  13. }   
As it will be the same handler for all the elements, we took only the first element from the array.
Once we get all the events in an array, we can apply these events to any element. In our case, I need to re-apply to the same element after refreshing the screen/panel.
  1. //Restoring events again after new filter view if (eleEvents.length > 0)     
  2. {         
  3.   for (var i = 0; i < eleEvents.length; i++)     
  4.   {              
  5.     $('#divpanel').find('li a').bind("click", runSearchItemLinkEvents[i]);      
  6.   }     
  7. }  
Now, you will be having the same functionality as you had before refreshing a panel and there is no need to maintain a duplicate copy or make the already existing private methods public and disturb the existing functionality.
I hope this article helps you.