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');
});
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!
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.
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.
$(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/
$(".switch").on('click', function () {
if ($(this).is('.off')) {
$(this).removeClass('off').addClass('on');
}
else {
$(this).removeClass('on').addClass('off');
}
});
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.