Reattach a removed event handler doesn't work - javascript

I want to remove the click of an element when it is clicked (I'm using off() for this), and want to reattach the click when the element isn't clicked ('actived'). To indicate it is not clicked, I'm using a class named 'disabled'.
But when I remove, I cant add it again. It just doesn't attach the event again!
This is what I'm trying to do:
$('.my-element').on('click', function() {
$('.my-element').off('click');
});
var disabled = setInterval(function() {
if($('.my-element').hasClass('not-clicked')) {
$('.my-element').on();
}
}, 1000);
I'm using setInterval() to watch whether the element isn't clicked. If it isn't, it can be using on() again.
I have even tried to remove the event handler in the browser console:
$('.my-element').off();
But when I try to reattach the event handler...
$('.my-element').on();
It doesn't work, and will not repeat the behavior.

jQuery.on() doesn't remember removed events, but you can save the current events before removing them with:
var handlers;
$('.my-element').on('click', function() {
handlers = $.extend(true, {}, $._data( this, "events" ));
$('.my-element').off('click');
});
and then attach with:
$(".my-element").on("click", handlers.click[0].handler);

Using on and off without any parameters has no effect. Ideally you should pass the name of the event and it's handler to those methods.
var handler = function() {
// ...
}
$('.my-element').on('click.namespace', handler);
// ...
$('.my-element').off('click.namespace', handler);
If the handler should be called only once you could also consider using the one method. Also using setIntevarl here is a bad idea. You should bind the handler right after adding the class. In this case I'd suggest using event delegation technique:
$('#aStaticParent').on('click', '.my-element.not-clicked', function() {
// the handler is called only if the element has `not-clicked` className
$(this).removeClass('not-clicked');
});

Related

jQuery remove scroll listener after reach certain point [duplicate]

I have an input type="image". This acts like the cell notes in Microsoft Excel. If someone enters a number into the text box that this input-image is paired with, I setup an event handler for the input-image. Then when the user clicks the image, they get a little popup to add some notes to the data.
My problem is that when a user enters a zero into the text box, I need to disable the input-image's event handler. I have tried the following, but to no avail.
$('#myimage').click(function { return false; });
jQuery ≥ 1.7
With jQuery 1.7 onward the event API has been updated, .bind()/.unbind() are still available for backwards compatibility, but the preferred method is using the on()/off() functions. The below would now be,
$('#myimage').click(function() { return false; }); // Adds another click event
$('#myimage').off('click');
$('#myimage').on('click.mynamespace', function() { /* Do stuff */ });
$('#myimage').off('click.mynamespace');
jQuery < 1.7
In your example code you are simply adding another click event to the image, not overriding the previous one:
$('#myimage').click(function() { return false; }); // Adds another click event
Both click events will then get fired.
As people have said you can use unbind to remove all click events:
$('#myimage').unbind('click');
If you want to add a single event and then remove it (without removing any others that might have been added) then you can use event namespacing:
$('#myimage').bind('click.mynamespace', function() { /* Do stuff */ });
and to remove just your event:
$('#myimage').unbind('click.mynamespace');
This wasn't available when this question was answered, but you can also use the live() method to enable/disable events.
$('#myimage:not(.disabled)').live('click', myclickevent);
$('#mydisablebutton').click( function () { $('#myimage').addClass('disabled'); });
What will happen with this code is that when you click #mydisablebutton, it will add the class disabled to the #myimage element. This will make it so that the selector no longer matches the element and the event will not be fired until the 'disabled' class is removed making the .live() selector valid again.
This has other benefits by adding styling based on that class as well.
This can be done by using the unbind function.
$('#myimage').unbind('click');
You can add multiple event handlers to the same object and event in jquery. This means adding a new one doesn't replace the old ones.
There are several strategies for changing event handlers, such as event namespaces. There are some pages about this in the online docs.
Look at this question (that's how I learned of unbind). There is some useful description of these strategies in the answers.
How to read bound hover callback functions in jquery
If you want to respond to an event just one time, the following syntax should be really helpful:
$('.myLink').bind('click', function() {
//do some things
$(this).unbind('click', arguments.callee); //unbind *just this handler*
});
Using arguments.callee, we can ensure that the one specific anonymous-function handler is removed, and thus, have a single time handler for a given event. Hope this helps others.
maybe the unbind method will work for you
$("#myimage").unbind("click");
I had to set the event to null using the prop and the attr. I couldn't do it with one or the other. I also could not get .unbind to work. I am working on a TD element.
.prop("onclick", null).attr("onclick", null)
If event is attached this way, and the target is to be unattached:
$('#container').on('click','span',function(eo){
alert(1);
$(this).off(); //seams easy, but does not work
$('#container').off('click','span'); //clears click event for every span
$(this).on("click",function(){return false;}); //this works.
});​
You may be adding the onclick handler as inline markup:
<input id="addreport" type="button" value="Add New Report" onclick="openAdd()" />
If so, the jquery .off() or .unbind() won't work. You need to add the original event handler in jquery as well:
$("#addreport").on("click", "", function (e) {
openAdd();
});
Then the jquery has a reference to the event handler and can remove it:
$("#addreport").off("click")
VoidKing mentions this a little more obliquely in a comment above.
If you use $(document).on() to add a listener to a dynamically created element then you may have to use the following to remove it:
// add the listener
$(document).on('click','.element',function(){
// stuff
});
// remove the listener
$(document).off("click", ".element");
To remove ALL event-handlers, this is what worked for me:
To remove all event handlers mean to have the plain HTML structure without all the event handlers attached to the element and its child nodes. To do this, jQuery's clone() helped.
var original, clone;
// element with id my-div and its child nodes have some event-handlers
original = $('#my-div');
clone = original.clone();
//
original.replaceWith(clone);
With this, we'll have the clone in place of the original with no event-handlers on it.
Good Luck...
Updated for 2014
Using the latest version of jQuery, you're now able to unbind all events on a namespace by simply doing $( "#foo" ).off( ".myNamespace" );
Best way to remove inline onclick event is $(element).prop('onclick', null);
Thanks for the information. very helpful i used it for locking page interaction while in edit mode by another user. I used it in conjunction with ajaxComplete. Not necesarily the same behavior but somewhat similar.
function userPageLock(){
$("body").bind("ajaxComplete.lockpage", function(){
$("body").unbind("ajaxComplete.lockpage");
executePageLock();
});
};
function executePageLock(){
//do something
}
In case .on() method was previously used with particular selector, like in the following example:
$('body').on('click', '.dynamicTarget', function () {
// Code goes here
});
Both unbind() and .off() methods are not going to work.
However, .undelegate() method could be used to completely remove handler from the event for all elements which match the current selector:
$("body").undelegate(".dynamicTarget", "click")
I know this comes in late, but why not use plain JS to remove the event?
var myElement = document.getElementById("your_ID");
myElement.onclick = null;
or, if you use a named function as an event handler:
function eh(event){...}
var myElement = document.getElementById("your_ID");
myElement.addEventListener("click",eh); // add event handler
myElement.removeEventListener("click",eh); //remove it
This also works fine .Simple and easy.see http://jsfiddle.net/uZc8w/570/
$('#myimage').removeAttr("click");
if you set the onclick via html you need to removeAttr ($(this).removeAttr('onclick'))
if you set it via jquery (as the after the first click in my examples above) then you need to unbind($(this).unbind('click'))
All the approaches described did not work for me because I was adding the click event with on() to the document where the element was created at run-time:
$(document).on("click", ".button", function() {
doSomething();
});
My workaround:
As I could not unbind the ".button" class I just assigned another class to the button that had the same CSS styles. By doing so the live/on-event-handler ignored the click finally:
// prevent another click on the button by assigning another class
$(".button").attr("class","buttonOff");
Hope that helps.
Hope my below code explains all.
HTML:
(function($){
$("#btn_add").on("click",function(){
$("#btn_click").on("click",added_handler);
alert("Added new handler to button 1");
});
$("#btn_remove").on("click",function(){
$("#btn_click").off("click",added_handler);
alert("Removed new handler to button 1");
});
function fixed_handler(){
alert("Fixed handler");
}
function added_handler(){
alert("new handler");
}
$("#btn_click").on("click",fixed_handler);
$("#btn_fixed").on("click",fixed_handler);
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn_click">Button 1</button>
<button id="btn_add">Add Handler</button>
<button id="btn_remove">Remove Handler</button>
<button id="btn_fixed">Fixed Handler</button>
I had an interesting case relevant to this come up at work today where there was a scroll event handler for $(window).
// TO ELIMINATE THE RE-SELECTION AND
// RE-CREATION OF THE SAME OBJECT REDUNDANTLY IN THE FOLLOWING SNIPPETS
let $window = $(window);
$window.on('scroll', function() { .... });
But, to revoke that event handler, we can't just use
$window.off('scroll');
because there are likely other scroll event handlers on this very common target, and I'm not interested in hosing that other functionality (known or unknown) by turning off all of the scroll handlers.
My solution was to first abstract the handler functionality into a named function, and use that in the event listener setup.
function handleScrollingForXYZ() { ...... }
$window.on('scroll', handleScrollingForXYZ);
And then, conditionally, when we need to revoke that, I did this:
$window.off('scroll', $window, handleScrollingForXYZ);
The janky part is the 2nd parameter, which is redundantly selecting the original selector. But, the jquery documentation for .off() only provides one method signature for specifying the handler to remove, which requires this middle parameter to be
A selector which should match the one originally passed to .on() when attaching event handlers.
I haven't ventured to test it out with a null or '' as the 2nd parameter, but perhaps the redundant $window isn't necessary.

jquery off not working

I can't unbind event use off.
I was trying to bind click event, then bind mouseleave event and callback unbind click, but not working.
el is dom create and append by script that's why I use document.on... el
so I tried below include commented code for test not working too.... do I miss understand something?
jquery-1.11.1.min.js
https://jsfiddle.net/70t6jtns/
var el = $('div')
$(document).on('click', el, function() {
console.log('oncli')
});
//$(document).on('mouseleave', el, function() {
//$(document).off('click', el, function() {
//console.log('offcli')
//});
//$(document).off('click', el);
el.off('click');
//});
First, on doesn't accept jQuery objects as the second argument, so $(document).on('click', el, function() {... doesn't make sense.
The main issue is that you're using event delegation in one case but expecting a directly-attached handler in the other case. You're attaching your click handler to document, but then trying to detach it from a specific element (el). You have to remove it from the same thing you attached it to.
If you want to attach the handler to el and detach it later, use el consistently as the target:
el.on("click", function() { ...
then
el.off("click");
If the handler has to be delegated, you'll want to be sure, again, that you're removing the same thing you're adding. So for instance,
$(document).on("click", "selector-for-the-element", function() { ...
then
$(document).off("click", "selector-for-the-element");
I was facing the same issue. Because i added the on listener on document and trying off with element. that was the issue in my case.

jQuery remove event handler which is specified in the View

My understanding is that when using the unbind and off jQuery methods, I should be able to remove an event handler from an element as follows
The textbox created in the view, with an onkeypress event handler applied
#Html.TextBoxFor(Function(m) m.sometext, New With {.onkeypress = "eventhandler();", .id = "theID"}
The JavaScript which is trying to remove the event
function eventhandler()
{
alert("should only hit once");
// this doesnt unbind the event
$("#theID").unbind("onkeypress");
// Nor does
$("#theID").off();
//???
}
My thinking could be that the unbind only works with bind and the off only works when on is used. I say this as the jQuery API website states
The .off() method removes event handlers that were attached with .on()
If this is the case, can I not apply the handler in the view at all?
I'd like to add I want to do this in the view and I want to apply a unique ID which is from the ViewModel
Any help would be helpful
Thanks
You can use either removeAttr()
$('#theID').removeAttr('onkeypress');
or set the event handler to null
$('#theID'')[0].onkeypress = null;

How to overwrite event handler for 'click' event in javaScript?

I want to overwrite event handler for click event. This is the event handler I have attached initially.
document.querySelector("[data-id='start-btn']")
.addEventListener("click", function (evt) {
//some code
});
Again after some condition, I want to over write this handler and attach new for 'click' event.
//removing
document.querySelector("[data-id='start-btn']")
.removeEventListener("click", function (evt) {
//some code
}, false);
//attaching new
document.querySelector("[data-id='start-btn']")
.addEventListener("click", function (evt) {
//code
});
But still it is executing the previous event handler.I have used removeEventListener(but I guess, its not working).
Guide me where I am going wrong.
The only way to remove a handler added with addEventListener is to use removeEventListener with exactly the same arguments. That means you'll need a reference to the original function:
var handler = function (evt) {
//some code
};
document.querySelector("[data-id='start-btn']").addEventListener("click", handler);
then to remove
document.querySelector("[data-id='start-btn']").removeEventListener("click", handler);
removeEventListener makes sense really only when using function references rather than passing an entire function body to both it and addEventListener, which would potentially mean mass duplication of code (and, as you've found, doesn't work anyway.)
So, prepare a reference to your function:
function my_func() { /* code */ }
And pass it as the handler argument to add/removeEventListener
document.querySelector('query').addEventListener('click', my_func);
document.querySelector('query').removeEventListener('click', my_func);
There is an easier way that utilises an older coding standard. If you specifically want only one event handler for a given type and element, you can use the DOM-zero onclick.
document.querySelector('query').onClick = my_func;
document.querySelector('query').onClick = my_func2; /* my_func() will no longer fire */
As you can see from some other answers, removing an event listener can be kind of a nightmare. Thankfully in certain circumstances there is an easier way: add another event listener that fires earlier and cancels out the rest.
In my case there was a click event handler I wanted to override and I was able to add another event handler with useCapture=true (among other things) to override it.
document.body.addEventListener('click',function (e) {
if (e.target.innerHTML.toLowerCase() == 'regular') {
e.target.insertAdjacentHTML('afterend','<div>One we do <strong>not want</strong></div>');
e.preventDefault();
}
});
document.body.addEventListener('click',function (e) {
if (e.target.innerHTML.toLowerCase() == 'fixed') {//or any event or other pre-/evaluations/conditions here
e.target.insertAdjacentHTML('afterend','<div>One we <strong>do want</strong></div>');
e.preventDefault();
e.stopPropagation();
}
//document.querySelector('.somethingelse').click();//etc.
},true);
<div>Regular</div>
<div>Fixed</div>
I was building a chrome extension and for some reason removeEventListener was not working as expected. The solution I came up with was to use the cloneNode method.
The documentation says
Cloning a node copies all of its attributes and their values,
including intrinsic (inline) listeners. It does not copy event
listeners added using addEventListener() or those assigned to element
properties.
What I did was created a clone for my actual element and replaced it with the cloned one. This removes all event listeners from the element. A simple example will be like
let newClonedElem = myActualElem.cloneNode(true);
myActualElem.parentNode.replaceChild(newClonedElem, myActualElem);

How to remove an event handler passed as a property of an object in jQuery?

I'm using a plugin that I cannot modify directly, but I'd like to remove some event handlers from DOM elements that this plugin is attaching.
The plugin does this:
var openOnClick = function() {
$('#selector').on({
click: function(e) {
e.preventDefault();
plugin.showPanel($(this));
}
})
};
It later calls openOnClick();
I want to remove this event completely. I tried $('#selector').off('click'), but this does not work. I assume this is because it is not just a simple 'click' event attached to the #selector.
What are my options to get rid of this event?
Did you try an
e.stopPropagation()
or just an
return false;
in the body of your click handler function ?

Categories