Toggling Classes Voids the Event function? - javascript

I thought this would work, but whenever I click on the element with the class name of one and it changes to the class named two, I can't get the second event to work. What am I missing here?
//first event
$('.one').on('click', function () {
$('.one').attr('class', 'two');
});
//second event
$('.two').on('click', function () {
$('.two').attr('class', 'one');
});

You need to delegate the event to a static parent..
The problem is , because you seem to dynamically change the class you need to bind the event every single time you change the class.. So delegating it should remove this problem..
Also You can write this as a Single event..
$('body').on('click','.one' , '.two', function() {
if( $(this).hasClass('one'){
function1();
}
else if( $(this).hasClass('two'){
function2();
}
$(this).toggleClass('one two');
});

Why not more simple :) http://jsfiddle.net/XZeNE/1/ or this http://jsfiddle.net/4mJJe/
use API - toggleClass
Further HTML CHange Dmeo http://jsfiddle.net/vuLQK/1/
code
$('.one').on('click', function() {
$(this).toggleClass('two');
});​
HTML change
$('.one').on('click', function() {
$(this).toggleClass(function(){
if($(this).hasClass('two'))
$(this).html('NOw its class two HTML HULK');
else
$(this).html('CLASS ONE HTML IRONMAN' );
return "two";
})
});
​

You should use .on to attach to one of the ancestors of the 2 elements and then use the selector argument to match the event target. The selectors won't match elements that aren't present when the handlers are bound.

$(function () {
$("#container").delegate(".one", "click", function () {
$(this).attr('class', 'two');
});
$("#container").delegate(".two", "click", function () {
$(this).attr('class', 'one');
});
})

Related

JS: append cannot find attr

$(".btn").click(function()
{
$(".content").append(
"<div class='randomDiv' id='1'></div>"
);
}
If above is "active" then I cannot:
$(".randomDiv").click(function()
{
alert($(this.attr("id")));
}
I've googled and found out that it is because JS is loaded before I append, but haven't found a solution how to "register after load" on JS.
Either:
Attach the event handler when you create the element
$(".btn").click(function() {
$("<div class='randomDiv' id='1'></div>")
.on("click", myFunction)
.appendTo(".content");
}
function myFunction() {
alert($(this.attr("id")));
}
… so the element does exist when you bind the event handler
Use a delegated handler
$(document).on("click", ".randomDiv", function () {
alert($(this.attr("id")));
});
… that captures all the click events as they bubble up the document and checks which elements they came from.
$(".content").on('click', '.randomDiv', function()
{
alert($(this.attr("id")));
}
$(".content") can be replaced with any existing parent item of randomDiv. Say content div is inside page-left div then above code can be written as
$(".page-left").on('click', '.randomDiv', function()
{
alert($(this.attr("id")));
}
Or even
$(document).on('click', '.randomDiv', function()
{
alert($(this.attr("id")));
}
which bind event to the document level in DOM
Depending upon the version of jQuery you should use live, delegate, bind or on function.
If you append the element dynamically then the normal click function wont work. Use
$(document).on("click",".randomDiv",function(event){
alert($(this).attr("id"));
});

Binding multiple event handler pairs on dynamically generated elements in jquery with on

I have some dynamically generated elements with the class my-class on which I want to bind some events. I have the below code which works properly.
$(document).on("event1", ".my-class", function () {
alert("Event 1");
});
$(document).on("event2", ".my-class", function () {
alert("Event 2");
});
I want to refactor it so that there can be a single call to on for the category. Something like this
$(document).on(".my-class", {
"event1": function() {alert("Event1")},
"event2": function() {alert("Event2")}
});
Is this possible in jquery?
There might be a better way, but I've used this before and it worked for me:
Demo Fiddle
I wouldn't delegate off the document, instead I'd use the closest parent container.
JS:
$('body').on('click mouseenter', 'div', function(e) {
if (e.type === 'click') {
$('div').html('clicked');
}
else { //you'd need an else if here if you had more than two event types
$('div').html('mouse enter');
}
});

Click event is not working for dynamically changed class in jquery

I have two class .btnn and .sleep_avail sometimes i changes the css of a anchor from .btnn to .sleep_avail
Now i have two function for anchor click
$('.btnn').click(function () {
alert('yes btn');
});
And Second one is
$('.sleep_avail').click(function () {
alert('yes sleep');
});
Now when i click on the anchor with class sleep_avail which is changed dynamically from btnn class the event written for btnn raised and i get response accordingly. But what i need is that the event for sleep_avail should be raised. Kindly help.
Anytime, you use dynamically created tags, you must use
$(document).on('#event','#selector',function () {...});
so here
$(document).on('click','.sleep_avail',function () {...});
Because event handlers bind to the currently elements, they have to exist on the page when .on()is called
Here is the working DEMO http://jsfiddle.net/ARBdU/
$(document).on('click','.btnn, .sleep_avail',function () {
if($(this).hasClass('btnn'))
{
...
}
else if($(this).hasClass('sleep_avail'))
{
...
}
});
try
$(document).on('click','.sleep_avail',function () {

Binding a function that is already bound to another element

I have a bunch of elements that get three different classes: neutral, markedV and markedX. When a user clicks one of these elements, the classes toggle once: neutral -> markedV -> markedX -> neutral. Every click will switch the class and execute a function.
$(document).ready(function(){
$(".neutral").click(function markV(event) {
alert("Good!");
$(this).addClass("markedV").removeClass("neutral");
$(this).unbind("click");
$(this).click(markX(event));
});
$(".markedV").click(function markX(event) {
alert("Bad!");
$(this).addClass("markedX").removeClass("markedV");
$(this).unbind("click");
$(this).click(neutral(event));
});
$(".markedX").click(function neutral(event) {
alert("Ok!");
$(this).addClass("neutral").removeClass("markedX");
$(this).unbind("click");
$(this).click(markV(event));
});
});
But obviously this doesn't work. I think I have three obstacles:
How to properly bind the changing element to the already defined function, sometimes before it's actually defined?
How to make sure to pass the event to the newly bound function [I guess it's NOT accomplished by sending 'event' to the function like in markX(event)]
The whole thing looks repetitive, the only thing that's changing is the alert action (Though each function will act differently, not necessarily alert). Is there a more elegant solution to this?
There's no need to constantly bind and unbind the event handler.
You should have one handler for all these options:
$(document).ready(function() {
var classes = ['neutral', 'markedV', 'markedX'],
methods = {
neutral: function (e) { alert('Good!') },
markedV: function (e) { alert('Bad!') },
markedX: function (e) { alert('Ok!') },
};
$( '.' + classes.join(',.') ).click(function (e) {
var $this = $(this);
$.each(classes, function (i, v) {
if ( $this.hasClass(v) ) {
methods[v].call(this, e);
$this.removeClass(v).addClass( classes[i + 1] || classes[0] );
return false;
}
});
});
});
Here's the fiddle: http://jsfiddle.net/m3CyX/
For such cases you need to attach the event to a higher parent and Delegate the event .
Remember that events are attached to the Elements and not to the classes.
Try this approach
$(document).ready(function () {
$(document).on('click', function (e) {
var $target = e.target;
if ($target.hasClass('markedV')) {
alert("Good!");
$target.addClass("markedV").removeClass("neutral");
} else if ($target.hasClass('markedV')) {
alert("Bad!");
$target.addClass("markedX").removeClass("markedV");
} else if ($target.hasClass('markedX')) {
alert("Ok!");
$target.addClass("neutral").removeClass("markedX");
}
});
});
OR as #Bergi Suggested
$(document).ready(function () {
$(document).on('click', 'markedV',function (e) {
alert("Good!");
$(this).addClass("markedV").removeClass("neutral");
});
$(document).on('click', 'markedX',function (e) {
alert("Bad!");
$(this).addClass("markedX").removeClass("markedV");
});
$(document).on('click', 'neutral',function (e) {
alert("Ok!");
$(this).addClass("neutral").removeClass("markedX");
});
});
Here document can be replaced with any static parent container..
How to properly bind the changing element to the already defined function, sometimes before it's actually defined?
You don't bind elements to functions, you bind handler functions to events on elements. You can't use a function before it is defined (yet you might use a function above the location in the code where it was declared - called "hoisting").
How to make sure to pass the event to the newly bound function [I guess it's NOT accomplished by sending 'event' to the function like in markX(event)]
That is what happens implicitly when the handler is called. You only need to pass the function - do not call it! Yet your problem is that you cannot access the named function expressions from outside.
The whole thing looks repetitive, the only thing that's changing is the alert action (Though each function will act differently, not necessarily alert). Is there a more elegant solution to this?
Yes. Use only one handler, and decide dynamically what to do in the current state. Do not steadily bind and unbind handlers. Or use event delegation.

Jquery dynamically create link

I have a piece of JQuery that creates a row in a table and in one of the cells there is an X that is surrounded by a class. When it is dynamically created and then clicked on the click listener does not fire.
Here is the code.
$('#add').click(function() {
$( '#table' ).append('<td class="x">X</td></tr>');
});
$('.x').click(function() {
alert('Fired');
});
Since the <td> element does not yet exist when you register your event handler, you have to use live() or delegate() for the handler to be triggered later:
$(".x").live("click", function() {
alert("Fired");
});
$(".x").live("click", function()
{
alert("Fired");
});
Live adds events to anything added later in the DOM as well as what's currently there.
Instead of
$('.x').click(function() {
alert('Fired');
});
Change to this
$('.x').live('click', function() {
alert('Fired');
});
It binds the click function to any created element with class x
You need to use the .live function for content that's dynamically generated.
so replace
$('.x').click(function() {
with
$('.x').live('click',function() {
You are first creating the listener to all .x elements (of which there are presumably zero), then later adding new .x elements.
There are two solutions: one is to use jQuery live, the other is to rewrite your code:
var xClickHandler = function() {
alert('Fired');
};
$('#add').click(function() {
$('#table').append(
$('<td class="x">X</td></tr>').click(xClickHandler);
);
});
Use live instead of click:
$('.x').live("click", function() {
alert('Fired');
});
The html you are appending to the table has a typo, you have missed out the beggining tr tag:
$('#add').click(function() {
$( '#table' ).append('<tr><td class="x">X</td></tr>');
});
$('.x').click(function() {
alert('Fired');
});
I think you need to use the live method. http://api.jquery.com/live/
$('.x').live('click', function() {
// Live handler called.
});

Categories