简体   繁体   中英

How to cancel jQuery.click from pure javascript code?

To make it simple:

I have a webpage. It has some scripts, one of which bind a click event to an <a> tag.

$('#someId').click(function() {
    ......
});

I want to add a pure javascript to this page (I'm not allowed to modify other js files) and take control of the click event. What I have tried is as follows:

document.getElementById('someId').onclick = function (event) {
    if (someCondition) {
        // cancel this click event 
        event.preventDefault();
        event.stopPropagation();
        event.cancel = true;
        return false;
    } else {
        // do something else.
    }
};

This piece of code seems not working. I need some help.

UPDATE

Sorry for my ambiguous language. By "pure javascript" I mean "using basic javascript manipulations instead of jQuery methods."

I want to add a pure javascript to this page (I'm not allowed to modify other js files) and take control of the click event.

If the code is going to be on that page, it can use jQuery, which is good because that's also the only way you can unregister the jQuery-registered handler:

$("#someId").off("click").on("click", function() {
    // Your new code here
});

Calling .off("click") on an element removes all jQuery-registered click handlers from that element.

That said, usually there's a better approach than clobbering the handlers registered by other code on the page.


Why you can't unregister the jQuery-registered handler without using jQuery: The first time a particular event is hooked on a particular element via jQuery, jQuery registers one handler (its own) to use for that event on that element; if more handlers are attached, it just adds them to its own internal list, it doesn't register those with the DOM. Instead, when the DOM event is fired, jQuery walks through its list of handlers and triggers them.

To unregister jQuery's actual handler for the event on the element, you'd have to get a reference to the specific function instance jQuery used when registering it. ( removeEventListener doesn't have the equivalent of the above "clear all of them"). That reference is only available from data structures inside jQuery's closure, so you can't get at it without using jQuery.


What should I do if other handlers need to resume to be executed under some circumstances in the $.on() block?

Ah, that's much more difficult. It all depends on more of the context than is present in your question. Some options:

  1. By far the best thing is to modify the other code that is handling clicks. But I understand you're saying you can't do that.

  2. jQuery calls handlers in the order they were registered (this is one reason it handles calling multiple handlers itself; different browsers do things in different orders). So if you can hook click on #someId before the other code does, then you can reliably use event.stopImmediatePropagation() to prevent other handlers from being called. That won't work, of course, if your handler isn't first in the list, because the other handlers will have been called first.

  3. If there's an element within the #someId element that completely fills it, you can hook click on that element instead, and then use event.stopPropagation() to prevent the event from bubbling up to the #someId element.

  4. And of course, if there isn't an element like #3, you could probably insert one (dynamically, with code) and move #someId 's contents into it, so you could inject your handler into the bubbling.

  5. You can dive into jQuery's internals and figure out how to access the event handler chain and manipulate it. It used to be quite easy; I think recent versions have made it harder. This would be, of course, going into undocumented territory that could change with any "dot" release.

There is one more possible solution, but unfortunately it has some browser compatibility issues. The point is to use css pointer-events property and onmousedown event like this:

$('a').click(function() {
    alert('jquery');
});

var i = 0;
btn.onmousedown = function(ev) {
    if (i++ % 2 == 0) {
        btn.style.pointerEvents = 'none'; // disable clicks

        setTimeout(function() {
            btn.style.pointerEvents = 'auto'; // enable back in 500 ms
        }, 500);
    }
};

See compatibility here and the demo is here

For IE you can try element disabled property in a same way.

And sure it's better to use jQuery for this (if it is used already in your project)

You need to add the click listener after the page has loaded.

window.onload=function(){
    //your code here.
};

If you are trying to disable the button after the click, add the 'disabled' property to the button and remove the click listener.

document.getElementById('someId').onclick = null;
document.getElementById('someId').disabled = true;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM