Firing a function with a newly added class - javascript

I've tried to simplify it, simple enough to make my question clearer.
The alert 'I am a boy' didn't popup with even after the addClass has been executed.
Here is my code:
$(".first").click(function () {
var a = $(this).html();
if (a=='On') {
$(this).removeClass('first').unbind().addClass('second');
$(this).html('Off');
}
});
$(".second").click(function () {
alert('I am a boy');
});
<button class="first">On</button>

This behavior is because you are apply a class to an element after the DOM has loaded, in other words dynamically. Because of this, your event listener attached to the control for '.second' isn't aware of the newly added class and doesn't fire when you click on that control.
To fix this, you simply need to apply your event listener to a parent DOM object, typically $(document) or $('body'), this will ensure it is aware of any children with dynamically added classes.
As George Bailey said, you can refer here for a in depth explanation.
In regards to your specific code, the fix is to simply adjust it as so:
$(".first").click(function () {
var a = $(this).html();
if (a=='On') {
$(this).removeClass('first').unbind().addClass('second');
$(this).html('Off');
}
});
/* Changed this:
$(".second").click(function () {
alert('I am a boy');
});
*/
// To this:
$(document).on('click', '.second', function () {
console.log('I am a boy');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="first">On</button>

The function you pass to $.post doesn’t run until later (a callback). So the class is added after you try to select it. Do it inside the callback, the same way you added the class (and you don’t need to select that class, just use $this)

Related

javascript events not working with dynamic content added with json

I'm stuck with a situation where my DOM elements are generated dynamically based on $.getJSON and Javascript functions for this elements are not working. I'll post some general idea on my code because I'm looking just an direction of what should I do in this situation.
site.js contains general features like
$(document).ready(function() {
$('.element').on('click', function() {
$(this).toggleClass('active');
});
$(".slider").slider({
// some slider UI code...
});
});
After that:
$.getJSON('json/questions.json', function (data) {
// generating some DOM elements...
});
I have also tried to wrap all site.js content into function refresh_scripts() and call it after $.getJSON() but nothing seems to be working.
Firstly you need to use a delegated event handler to catch events on dynamically appended elements. Then you can call the .slider() method again within the success handler function to instantiate the plugin on the newly appended content. Try this:
$(document).ready(function(){
$('#parentElement').on('click', '.element', function() {
$(this).toggleClass('active');
});
var sliderOptions = { /* slider options here */ };
$(".slider").slider(sliderOptions);
$.getJSON('json/questions.json', function(data) {
// generating some DOM elements...
$('#parentElement .slider').slider(sliderOptions);
});
});
Instead of calling on directly on the element, call it on a parent that isn't dynamically added and then use the optional selector parameter to narrow it to the element.
$('.parent').on('click', '.element', () => {
// do something
});
The difference between this and:
$('.element').on('click', () => {});
is with $('.element').on(), you're only applying the listener to the elements that are currently in that set. If it's added after, it won't be there.
Applying it to $(.parent), that parent is always there, and will then filter it to all of it's children, regardless when they're added.
the easiest way is to add this after you add/generate your DOM
$('script[src="site.js"]').remove();
$('head').append('<script src="site.js"></script>');
of course your js function that generates DOM needs to be on another file than your site.js

.class selector not working

I'm working in a card game system that the player can select the card by clicking on it and then select the place to put it on. My problem is that when the player click on the target place, nothing happens.
This is my try: http://jsfiddle.net/5qMHz/
And this is my code:
function target() {
$(".target").on("click", function() {
$("#"+x).appendTo(this);
console.log(x);
});
};
What's wrong?
Try binding with document, since you change the class during document ready and there was no element with the class target initially
$(document).on("click",".target", function() {
$("#" + x).appendTo(this);
console.log(x);
}
WORKING FIDDLE
Firstly, your practice of putting function references in to jQuery objects is rather odd. The problem however is that because the .target class is applied after DOM load you need to use a delegate selector. Try this:
var $card
$(".card").on("click", function () {
$card = $(this);
if ($(".myslot").length) {
if ($(".myslot").is(':empty')) {
$(".myslot:empty").addClass("target");
} else {
alert('No empty slots');
}
}
});
$('.field').on('click', ".target", function () {
$card.appendTo(this);
$card = $();
});
Example fiddle
At the moment you are trying to bind the event handler, the elements don't have a class target yet. From the documentation:
Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to .on().
(Technically the elements exist, but they are not (yet) addressable by the class target)
You have three options to solve this:
Add the class to your HTML markup.
Bind the handler after you added the class to the elements.
Use event delegation.
The first two don't really fit to your use case, since your are adding the class target in response to an other event and the number of elements with the class target changes over time. This is a good use case for event delegation though:
$('.field').on('click', '.target', function() {
// ...
});

Wait until HTML elements gets a class then do something

I am waiting for the document.ready event in order to do something on my page.
Alas some other script, which I cannot change, has not worked its magic yet once my script is called. Hence, jquery selection on the class name fails as the class does not yet exist in the DOM.
This is why I want tell my function to listen until an element gets a certain class, then do something with it.
How do I achieve this?
Something like this (pseudo code) :
var timer = setInterval(function() {
if (element.className=='someclass') {
//run some other function
goDoMyStuff();
clearInterval(timer);
}
}, 200);
or listen for the element to be inserted:
function flagInsertedElement(event) {
var el=event.target;
}
document.addEventListener('DOMNodeInserted', flagInsertedElement, false);
jQuery version:
$(document).on('DOMNodeInserted', function(e) {
if (e.target.className=='someclass') {
goDoMyStuff();
}
});
There's also the liveQuery plugin:
$("#future_element").livequery(function(){
//element created
});
Or if this is a regular event handler, delegated events with jQuery's on();
You could trigger some event once you added the class.
Example:
$('#ele').addClass('theClass');
$(document).trigger('classGiven')
$(document).bind('classGiven',function(){
//do what you need
});
I'm sorry if I got your question wrong but why not just doing something plain as this on document.ready ? :
$("#myelement").addClass('myclass');
if($("#myelement").hasClass('myclass')) {
alert('do stuff here');
}

Javascript error when I try to add click event to span

Does anyone know what I'm doing wrong here?
var spanclickhandler = $('.officeapprovalspan').click(function () {
// do some stuff
});
Basically, I have this spanclickhandler. Anything with the class officeapprovalspan on loading the page gets this assigned to its click event. No problems there.
In another place I have the code:
$(this).replaceWith('<span class="officeapprovalspan">wero<span>');
$(document).on('click', '.officeapprovalspan', spanclickhandler);
So I'm replacing some HTML with a new span of this class. I use the on to add the click event to the spans of class officeapprovalspan. I gather I have to do this because the new span will not have the click handler attached to it.
So that's OK, but when I click the new span I get this error:
Anyone know what I'm doing wrong and how to fix?
The click method doesn't return the event handler, it returns the jQuery object. Define the event handler first, and use it in the click method:
var spanclickhandler = function () {
...
do some stuff
...
};
$('.officeapprovalspan').click(spanclickhandler);
This chunk of code doesn't do what you think it does (I'm pretty sure that handler function isn't returned):
var spanclickhandler = $('.officeapprovalspan').click(function () {
...
do some stuff
...
});
I suggest you code it like this, which should work:
var spanclickhandler = function () {
...
do some stuff
...
}
$('.officeapprovalspan').click(spanclickhandler);
What you want to do is:
var spanclickhandler = function () {
...
do some stuff
...
};
$(this).replaceWith('<span class="officeapprovalspan">wero<span>');
$('.officeapprovalspan').on('click', spanclickhandler);
OR BETTER
$(document).on('click', '.officeapprovalspan' function () {
...
do some stuff
...
});
// Because 'on' will attach event on DOM element even if they are not created yet, if you define a selector descendant inside. You can replace `document` by the nearest top parent of all your `.officeapprovalspan` and it will improve performance. `document` is not really optimal here
$(this).replaceWith('<span class="officeapprovalspan">wero<span>');
spanclickhandler returns a jQuery object, $('.officeapprovalspan') in this case. You need to either create a separate function or use event namescapes.
Can you just do this:
$(this).replaceWith('<span class="officeapprovalspan">wero<span>').click(spanclickhandler);

Adding a function to onclick event by Javascript!

Is it possible to add a onclick event to any button by jquery or something like we add class?
function onload()
{
//add a something() function to button by id
}
Calling your function something binding the click event on the element with a ID
$('#id').click(function(e) {
something();
});
$('#id').click(something);
$('#id').bind("click", function(e) { something(); });
Live has a slightly difference, it will bind the event for any elements added, but since you are using the ID it probably wont happen, unless you remove the element from the DOM and add back later on (with the same ID).
$('#id').live("click", function(e) { something(); });
Not sure if this one works in any case, it adds the attribute onclick on your element: (I never use it)
$('#id').attr("onclick", "something()");
Documentation
Click
Bind
Live
Attr
Yes. You could write it like this:
$(document).ready(function() {
$(".button").click(function(){
// do something when clicked
});
});
$('#id').click(function() {
// do stuff
});
Yes. Something like the following should work.
$('#button_id').click(function() {
// do stuff
});

Categories

Resources