开发者

jQuery: Get reference to click event and trigger it later?

开发者 https://www.devze.com 2023-04-12 22:38 出处:网络
I want to wrap an existing click event in some extra code. Basically I have a multi part form in an accordion and I want to trigger validation on the accordion header click. The accordion code is use

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

Basically I have a multi part form in an accordion and I want to trigger validation on the accordion header click. The accordion code is used elsewhere and I don't want to change it.

Here's what I've 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 because it's trying to do this.trigger inside the originalClick function and I don't think this is what jQuery expects it to be.

EDIT: Updated code. This works but it is a bit 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($(t开发者_运维技巧his).next().find('.calculate-step').attr('data-step'));
                $.proxy(originalClick, currentAccordion)(e);
            }
        });
    });


I think this:

var originalClick = currentAccordion.click;

Isn't actually doing what you think it is - you're capturing a reference to the jQuery click function, rather than event handler you added, so when you call originalClick() it's equivalent to: $(value).click()


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 bit weird (why do we store the click events in the variable "y"?)

Originally I tried to run the handlers in x.click, but they seem to be destroyed when we call .off("click"). Creating a copy of the handlers in a separate variable "y" worked. Sorry I don't have an in depth explanation, but I believe 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/


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

In jQuery, you use the $.proxy() method to do this.

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

Personally, I'd look at creating callback hooks in your Accordion, or making use of existing callbacks (if they exist) that trigger when opening or closing an accordion pane.

Hope that helps :)


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

Starting with a brute-force approach, what you'd need to do is:

  • Save references to all the currently bound handlers
  • Unbind them
  • Add your own handler, and fire the saved ones when needed
  • Make sure new handlers bound to click are catched too

This looks like a job for an event filter plugin, but I couldn't find one. If the last point is not required in your application, then it's a bit simpler.

Edit: After some research, the bindIf function shown here looks to be what you'd need (or at least give a general direction)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号