Unbinding click handlers on certain classes - javascript

I have a table cell that I want to be able to be clicked. But once it is clicked it will have the class ".clicked". When any table cell has this class, I do not want to be clickable. Is there any way to do this?

Also you can use .off() method to unbind any events.
$('td').on('click', function(){
$(this).addClass('clicked').off('click');
})

This is easily done by inserting some code at the top of the event handler.
$('td').click(function(e) {
if ($(this).hasClass('clicked')) {
e.stopPropagation();
e.preventDefault();
return;
}
// the rest of your code here
});
The other, more involved, way, is to use event delegation and only fire the function if the element doesn't have the class when it's clicked:
$('table').on('click', 'td:not(.clicked)', function() {
// your code here
});

You can use the .one() event registration method to do it, it will un-register the handler once the event is fired.
$('td').one('click', function(){
console.log('hanlded', this)
})
Another solution could be
$('table').on('click', ':not(.clicked)', function(){
console.log('hanlded', this)
})

Just add :not(.clicked) to whatever selector you're using to exclude clicked cells.

Related

Remove function for a specific element │$(this).off() does not work

I am binding a click event to .call elements like that
$('body div').on('click', '.call', function() {
$(this).off('click'); //after click i want to unbind the 'click' for this .call only
//however its not workinng.
*... some code here ....*
})
If i do $(body div).off('click', '.call'), all .call elements lost their functionality. I dont want that. How i can remove click function from just clicked .call
You can not unbind the click from the element since the event is not attached to that element. So you need to handle it by either removing the class that you are looking for in the event delegation or add logic of some sort to see if it is clicked.
If you can remove the class, that would be the easiest solution.
$('body div').on('click', '.call', function() {
$(this).removeClass("call");
/* rest of logic */
})
or you can add a class and check for it
$('body div').on('click', '.call', function() {
var elem = $(this);
if (elem.hasClass("called")) return;
elem.addClass("called");
/* rest of logic */
})
you could use data() instead of a class or you could add :not logic to the event delegation selector.
You might look into using $().one http://api.jquery.com/one/
This binds a callback to an element once, and unbinds it once it has been executed.

Removing a class doesn't disable the event listener function associated with the removed class

I did a fiddle to demonstrate my problem.
I am having problem to turn off a function activated by a class, any ideas?
$(document).ready(function(){
$('.changeText').click(function(){
$(this).html( $(this).html() == 'Test' ? 'Changed' : 'Test' );
});
$('.changeBG').click(function(){
$(this).css('background-color', 'red');
});
/* in some cases I need to turn off changeBG function */
$('.changeBG').removeClass('changeBG');
// but if you click the div it still turns into red.
});
Thanks in advance.
You could delegate the event handler to a common ancestor.
In doing so, it will only work if that element has that specific class because a check is made when the click event is actually fired (rather than when the event handler is attached).
Example Here
$(document).on('click', '.changeBG', function(){
$(this).css('background-color', 'red');
});
In the example above, document is the common ancestor. Depending on your markup, you will probably want to change that to the closest, constant, ancestor element so that the event isn't fired every time you click on the document.
Alternatively, you could also use the .off() method, and remove that specific event handler by utilizing event namespaces.
You can attach a specific click event named click.changeBG:
$('.changeBG').on('click.changeBG', function(){
$(this).css('background-color', 'red');
});
Then remove that specific event using .off('click.changeBG'):
Example Here
$('.changeBG').removeClass('changeBG').off('click.changeBG');
You need to remove the handler directly:
$('.changeBG').off('click')
Note: off is jQuery 1.7+, otherwise use unbind.
What happens is that the line $('.changeText').click(... attaches an handler to all elements with class changeText. Removing the class does not remove the handler.
This is because the handler is attached to the element and not the class. The class you referred while attaching is just a filter. You have just changed the class. Not the event that is associated with it:
// Do this
$('.changeBG').removeClass('.changeBG').off("click");
Or, when you click check for the class:
$('.changeBG').click(function(){
if ($(this).hasClass("changeBG"))
$(this).css('background-color', 'red');
});

Use of Binding after Unbinding

I found a code as shown below.
Html code:
<div id="myButton">Click Here</div>
JQuery Code:
$("#myButton").unbind("click").bind("click",function(){
alert("Working")
});
What is the need of unbind("click") before binding the element?
It is also working if unbind is not used. like shown below
$("#myButton").bind("click",function(){
alert("Working")
});
Which one is best? what is the difference?
This only makes sure, that there is no other click event listener attached. So your handler will be the only handler acting upon clicking the #myButton
Edit: as #T.J. Crowder noted in the comments, unbind() will not affect handlers attached in different way than by calling bind().
It is also worth noting, that:
as of jQuery 1.7, the .on() and .off() methods are preferred to attach and remove event handlers on elements
(excerpt from the jQuery.unbind() doc). In fact, unbind() is implemented internally by the off() method).
Consider:
$("#myButton").bind('click', function () {
console.log('click 1');
});
$("#myButton").unbind('click').bind('click', function () {
console.log('click 2');
});
// When clicked, prints "click 2"
Versus:
$("#myButton").bind('click', function () {
console.log('click 1');
});
// note: no unbind here
$("#myButton").bind('click', function () {
console.log('click 2');
});
// When clicked, prints "clicked 1" followed by "clicked 2"
By unbinding "click" event on an element, you are actually removing all the onclick events associated with that element. i.e. if your html form's input field has an onclick event and it calls a function, it will be unbound. After an unbind, you are binding another click event which will call your function onclick of that element.
$("#myButton").unbind("click").bind("click",function(){
alert("Working")
});
jQuery bind() function is used to attach an event handler to elements, while the unbind() is used to detached an existing event handler from elements. please see a demo http://www.mkyong.com/wp-content/uploads/jQuery/jQuery-bind-unbind-example.html
Without url of this html code , i'm not sure that #myButtonelement whether has other click handler attached ,but what is certain is unbind method remove all the handler on this element , i think the author only want to trigger one click event.
Also, you can see if there is other event handler on debug inspector of browser.
Hope this will help you.

switch on/off javascript

I am trying to make a swith on / off javascript, but I have a problem: I click always comes in my first class despite my class change.
I have always the same result : on->on or off->off. I check in Firebug my html is changed correctly...
Here my simplified code :
$('.off').on('click', function(e) {
e.stopPropagation();
e.preventDefault();
alert('off');
$(this).removeClass('off');
$(this).addClass('on');
});
$('.on').on('click', function(e) {
e.stopPropagation();
e.preventDefault();
alert('on');
$(this).removeClass('on');
$(this).addClass('off');
});
if anyone has a suggestion, I would be very grateful !!
The event handlers are bound on pageload, so changing the class won't change the event handlers, as they are attach to whatever elements existed at the time of binding. To attach them to future elements, i.e. when you change the classes, you'll need delegated event handlers, but an easier solution in my opinion is to just toggle the classes or use a flag:
$('.off').on('click', function(e) {
e.preventDefault();
var state = $(this).is('.off') ? 'on' : 'off';
alert(state);
$(this).toggleClass('off on');
});
FIDDLE
It can be confusing, but even if you remove the .off class, the event handler is still bound to the same element, as it had the .off class at the time of binding!
Either .off or .on does not exist when you first bind with .on. You need to use event delegation, or you can rewrite this so that it's bound to another class and maintain on/off state. I will show you both methods.
Delegation
$(document).on('click', '.off', function(e) {
$(this).removeClass('off').addClass('on');
}).on('click', '.on', function(e) {
$(this).removeClass('on').addClass('off');
});
http://jsfiddle.net/ExplosionPIlls/2PHJg/
Internal state
$(".switch").on('click', function () {
if ($(this).is('.off')) {
$(this).removeClass('off').addClass('on');
}
else {
$(this).removeClass('on').addClass('off');
}
});
http://jsfiddle.net/ExplosionPIlls/2PHJg/1/
This problem is caused because $('.on') and $('.off') only gets evaluated once, when your javascript code runs.
You have to use event delegation to solve the problem. Modify the code the following way. I describe below what it means.
$('#container').on('click', '.off', function(e) {
e.stopPropagation();
e.preventDefault();
alert('off');
$(this).removeClass('off');
$(this).addClass('on');
});
$('#container').on('click', '.on', function(e) {
e.stopPropagation();
e.preventDefault();
alert('on');
$(this).removeClass('on');
$(this).addClass('off');
});
In the place of #container use a selector which selects a parent of your .on / .off elements. In the second parameter of your on() call, youy have to specify the element for which you want to listen for events.
This way the event handler will run properly, even if the class of your elements change.
The problem is that the event handlers are bound when the code first runs, so when the class changes, the event handlers aren't rebound. One way to fix this is to assign the element a class that doesn't change, and use that for the event handler.
Example:
$('.button').on('click', function(e) {
e.stopPropagation();
e.preventDefault();
$(this).toggleClass('off on');
});
You can see a working example at http://codepen.io/skimberk1/pen/GJhna.

Set the mouseover Attribute of a div using JQuery

I would like to set an attribute for a div. I have done this:
$('#row-img_1').onmouseover = function (){ alert('foo'); };
$('#row-img_2').onmouseout = function (){ alert('foo2'); };
However, the above has not worked, it does not alert when mouse is over or when it moves out.
I have also tried the $('#row-img_1').attr(); and I could not get this to work either.
I am aware that I should be using a more effective event handling system but my divs are dynamically generated. Plus this is a small project. ;)
Thanks all for any help.
You need to bind the event function to the element. Setting the event attributes has no effect, as they are interpreted only when the page is loading. Therefore, you need to connect the event callback in a different manner:
$('#row-img_1').mouseover(function() {
alert('foo');
});
$('#row-img_2').mouseout(function() {
alert('foo2');
});
In jQuery, there are two more events: mouseenter and mouseleave. These are similar, but mouseenter does not fire upon moving the mouse from a child element to the main element, whereas mouseover will fire the event again. The same logic applies to mouseleave vs mouseout.
However, jquery provides a shortcut for this kind of usage: the .hover method.
$('#row-img_1').bind('mouseenter', function(event){
// event handler for mouseenter
});
$('#row-img_1').bind('mouseleave', function(event){
// event handler for mouseleave
});
or use jQuerys hover event which effectivly does the same
$('#row-img_1').hover(function(){
// event handler for mouseenter
}, function(){
// event handler for mouseleave
});
Events are registered as functions passed as attributes, like this:
$('#row-img_1').mouseover(function (){ alert('foo'); });
$('#row-img_2').mouseout(function (){ alert('foo2'); });
Also, note the missing on from the onmouseover.
$('#row-img_1').mouseover(function() {
alert('foo');
});

Categories