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');
}
Related
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)
What is the most elegant way to beautify the following code? I would like to get rid of duplicated code:
$('#popup_settings_enable_name').click(function() {
$el = $('#popup_settings_name_field');
if ($(this).prop('checked')) {
$el.removeAttr("disabled");
} else {
$el.attr("disabled", "disabled");
}
}).each(function() {
$el = $('#popup_settings_name_field');
if ($(this).prop('checked')) {
$el.removeAttr("disabled");
} else {
$el.attr("disabled", "disabled");
}
});
You can simply trigger the click event handler after installing it using .triggerHandler:
$('#popup_settings_enable_name')
.click(function() {
// ...
})
.triggerHandler('click');
Note that .trigger would also do the exact same thing in many cases, but there are subtle differences between .trigger and .triggerHandler you should be aware of. The manual page makes clear mention of them.
You can simply trigger the event to execute the handler for initialisation:
$('#popup_settings_enable_name').click(function() {
…
}).click();
Another method would be to just use a function declaration:
function update() {
// a little simplification:
$('#popup_settings_name_field').prop("disabled", !this.checked);
}
$('#popup_settings_enable_name').click(update).each(update);
Triggering the click event manually could have unintended side effects (what if there are other delegates that have also been assigned the click event?)
I would suggest refactoring the duplicated code into its own method, then simply pass that method into the jQuery .click() function, and then passing it into the jQuery .each() function.
Is there a way to check if jQuery fired the page load events yet, or do you have to roll your own? I need to alter the behavior of links, but I don't want to wait until the page finishes loading because the user could conceivably click on a link on, say, the top half of the page before the page finishes loading. Right now I'm doing it like this:
var pageLoaded = false;
$(function() {
pageLoaded = true;
});
function changeLinks() {
$("a[data-set-already!='true']").each(function() {
$(this).attr("data-set-already", "true").click(...);
});
// Is there something along the lines of jQuery.pageWasLoaded that I can
// use instead?
if (!pageLoaded) {
window.setTimeout(changeLinks, 100);
}
}
changeLinks(); // Added per #jondavidjohn's question
Since you are using the document ready shorthand, I'm guessing you mean when the dom is loaded. For this:
$.isReady
You could use setInterval and clear the interval on domready:
var changeLinksInterval = setInterval(function () {
$("a[data-set-already!='true']").each(function() {
$(this).attr("data-set-already", "true").click(...);
});
}, 100);
$(function () {
clearInterval(changeLinksInterval);
});
By the way, in your code example, you shouldn't need .each() - you should be able to call .attr() and .click() directly and let jQuery do the looping. Unless there is more to your .each() code that you didn't post.
$("a[data-set-already!='true']").attr("data-set-already", "true").click(...);
you could use .live() to initiate a click event that needs additional work when binding.
$("a[data-set-already!='true']").live(function(){
// since this event will only fire once per anchor tag, you
// can safely bind click events within it without worrying
// about getting duplicate bound click events.
var $this = $(this);
$this
.data("dataSetAlready",true)
.click(myClickHandler);
});
this is also a useful technique for late-initializing plugins on elements that may not exist at domReady.
So im trying do disable links on some <li> ellements that have been loaded in from another page using an .load() function, but for some reason i'm not able to effect those list items.
var from_post = false;
$(document).ready(function() {
//so this is the function that loads in data from another page
$("#gallery").load('http://localhost/index.php/site/gallerys_avalible/ #gallerys_avalible'), function() {
console.log('hello');
// sense there are no other li elliments on the page i thought this
// would be okay. but this function never gets called, i've moved it
// all over i just recently attached it to the load function thinking
// that maybe if the load was not complete it would not run, but i
// have had no luck.
$('li').click(function (e) {
e.preventDefault();
console.log("I have been clicked!");
return false;
});
};
$('#addNew').click(function () {
console.log('i got called');
$('#new_form').fadeIn(1000);
});
$('form').submit(function() {
if(from_post) {
//submit form
return true;
} else {
//dont submit form.
return false;
}
});
any help would be greatly appreciated, oh and the other thing is that i can run this function through firebug, and it works 100% fine. so im stumped.
You are closing your call to .load() too early. You have:
$("#gallery").load('http://...'), function() {
That just calls load and then declares a function. But, that function is not bound to the success handler and it will never be executed. You need the ) to be on the other side of the function declaration so that the function is included as a parameter to your call to load:
$("#gallery").load('http://...', function() {
...
});
Fix that and your code works: http://jsfiddle.net/gilly3/WdqDY/
Try a future-proof event observer like live or delegate:
$('li').live('click', function(){})
or, this method is preferred if you know the parent:
$('#gallery').delegate('li','click',function(){})
The reason for needing this is your click events are being bound to elements that are on the page at the time of the binding. Any li's added later will not see that binding which is how live or delegate works. They bind to the parent and traverse the child nodes every (click in this case) event to see if the event applies to an existing child.
Use .live('click', ...) or .delegate() instead of .click(...).
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
});