JQuery: get a link to a click event and call it later?

I want to wrap an existing click event in some additional code.

Basically I have a form for several parts in the accordion, and I want to activate the check by clicking on the header of the accordion. The accordion code is used elsewhere and I do not want to change it.

Here is what I tried:

//Take the click events off the accordion elements and wrap them to trigger validation $('.accordion h1').each(function (index, value) { var currentAccordion = $(value); //Get reference to original click var originalClick = currentAccordion.click; //unbind original click currentAccordion.unbind('click'); //bind new event currentAccordion.click(function () { //Trigger validation if ($('#aspnetForm').valid()) { current = parseInt($(this).next().find('.calculate-step').attr('data-step')); //Call original click. originalClick(); } }); }); 

jQuery throws an error as it tries to execute this.trigger inside the originalClick function, and I don't think this is what JQuery expects.

EDIT: Updated code. It works, but it's a little ugly!

  //Take the click events off the accordion elements and wrap them to trigger validation $('.accordion h1').each(function (index, value) { var currentAccordion = $(value); var originalClick = currentAccordion.data("events")['click'][0].handler; currentAccordion.unbind('click'); currentAccordion.click(function (e) { if ($('#aspnetForm').valid()) { current = parseInt($(this).next().find('.calculate-step').attr('data-step')); $.proxy(originalClick, currentAccordion)(e); } }); }); 
+4
source share
4 answers

I think:

 var originalClick = currentAccordion.click; 

In fact, you are not doing what you think you are writing a link to the jQuery click function, not the event handler you added, so when you call originalClick (), this is equivalent to: $ (value) .click ()

+4
source

I finally came up with something reliable:

 $(".remove").each(function(){ // get all our click events and store them var x = $._data($(this)[0], "events"); var y = {} for(i in x.click) { if(x.click[i].handler) { y[i] = x.click[i].handler; } } // stop our click event from running $(this).off("click") // re-add our click event with a confirmation $(this).click(function(){ if(confirm("Are you sure?")) { // if they click yes, run click events! for(i in y) { y[i]() } return true; } // if they click cancel, return false return false; }) }) 

This may seem a little strange (why do we save click events in the variable "y"?)

I initially tried to run the handlers in x.click, but they seemed to be destroyed when we call .off ("click"). A copy of the handlers was created in a separate variable "y". Sorry, I don’t have a detailed explanation, but I believe that the .off ("click") method removes the click event from our document along with the handlers.

http://www.frankforte.ca/blog/32/unbind-a-click-event-store-it-and-re-add-the-event-later-with-jquery/

+2
source

currentAccordion.click is a jQuery function, not an actual event.

Starting with brute force approach, you will need to do the following:

  • Save links to all currently associated handlers
  • Untie them
  • Add your own handler and run the saved ones if necessary.
  • Make sure the new click-bound handlers are also hooked.

This seems to work for an event filter plugin, but I could not find it. If the last point is not required in your application, this is a little easier.

Edit:. After some research, the bindIf function shown here looks exactly as you need. (or at least give a general direction)

+1
source

I am not a jQuery user, but in Javascript you can set the context of this keyword.

JQuery uses the $ method for this . proxy () .

 $.proxy(originalClick, value); originalClick(); 

Personally, I would look at creating callback hooks in your Accordion or using existing callbacks (if they exist) that start when you open or close the accordion panel.

Hope that helps :)

+1
source

All Articles