I'm trying to execute a piece of code each time a specific element has a certain class in jQuery.
The problem I'm experiencing is that the code only executes once, then seems unactive. I'm using an if statement, but I also tried while. When I tried while the nothing really worked so that wasn't a good idea. Is there any solution? Here's the code:
if($(".slide:first").hasClass("active-slide")) {
$(".prev").hide();
$(".next").click (function () {
$(".prev").show();
});
}
JQuery queries are performed only once. You could execute it in an interval:
var checkPage = function(){
if($(".slide:first").hasClass("active-slide")) {
$(".prev").hide();
$(".next").click (function () {
$(".prev").show();
});
}
}
var intrvl = setInterval( checkPage, 300 );
This might work, but it could become really slow on big pages.
I'd rather attach the checkPage() function to the slide change event.
Wrap it in a each(), so that it executes every time slider:first occurs.
$(".slide:first-child").each(function(){
// your function goes here
});
EDIT: :first only targets the first instance of it on the page, so it will only fire one time anyway. You are probably looking for :first-child.
Related
You'll have to forgive me if I show any kind of ineptitude here, jquery and java isn't my usual area of work. But here goes:
I have a page that shows a random list of items that are pulled from a server using an API call. The idea is that every time the user clicks "generate" a new list is produced and inserted into the page. This works but it's very fast and all the user sees is a list rapidly changing. To spruce things up I've decided to put some nice animations and effects in.
I've got a jquery function that loops through each element in the list of child elements and toggles the css style of the child element so that an effect from the animate.css library is applied. The problem is when I have another function that loads the new list and this is called immediately and therefore all of the css transitions are ignored; or rather they don't get a chance to run because the second method immediately triggers.
I've tried using a callback and had no joy, I've tried using deferred objects. No luck at all.
Here's the code I have so far:
function removeOldContent() {
$('#removableContent > div').each(function (index) {
var elm = $(this);
setTimeout(function () {
elm.toggleClass('customAnim', function () {
$(this).remove();
});
}, index * 150);
});
}
function getList() {
var rId = $('.tab-content').find('.active').data('d-id');
var serviceUrl = '/GetRandom/GetList';
$.ajax({
type: 'POST',
url: serviceUrl,
data: {
reportId : rId
},
success: function(data) {
$('#reportContainer').html(data).fadeIn('slow');
}
});
}
Ideally I'd like to be able to let removeOldContent() finish completely, after all the timeouts have run. And then trigger getList() to update the content. I'll work on making a nice transition for the inbound data but first I just need to get this working.
Any advice or pointers would be greatly appreciated.
***** Update ******
I've made a fiddle. Not giving me the same error as my dev env but should be close enough for you to see
https://jsfiddle.net/rdt1pfhk/9/
Your problem is with the timing of events. Your removeOldContent function uses a setTimeout function which in turn animates and removes the items from the DOM. Your getList() function was executing before the other function had finished. I put a quick untidy solution together using your fiddle. I return a jquery deferred object from you removeOldContent method and then only call the getList when that is resolved (and the older items removed from the dom). It is not the neatest but it will point you in the right direction. I updated your fiddle here: https://jsfiddle.net/rdt1pfhk/16/
function removeOldContent() {
var deferred = new jQuery.Deferred();
....
return deferred;
}
$(document).on('click', '.quickPick', function (e) {
removeOldContent().then(function(){
getList();
});
});
If I understood correctly you need to only delay some functions for as long as you need. I think the answer you are looking for could be found here:
How to delay calling of javascript function?
Also, I'd like to mention that I don't see a
$(document).ready(function () {
//your code here
});
anywhere. Maybe I'm wrong but since you mentioned that CSS is ignored, are you sure the page is loaded before your code starts being executed?
So in my js script I use jQuery, at the top I wrote:
$(function() {
myFunc();
function myFunc() {
console.log("1");
}
});
"1" is only printed once which means myFunc only ran once, I want it to run every frame/millisecond or basically as fast as it can over and over and over again. Why doesn't it happen like so? If I'm doing it wrong, how can I achieve the effect I want, and what is my mistake?
#Vadim Tatarnikov to call as soon as faster a function in jquery use
window.setInterval() with minimum time interval try the below code
<script type="text/javascript" src="jquery.js"></script>//add your jquery script file
<script type="text/javascript">
$(document).ready(function(){
window.setInterval(function(){
myFunc();
},1);//here i put time interval=1 millisecond
});
function myFunc(){
console.log("1");
}
This will call myFunc() in every 1 millisecond just run and see the console.
you have written IIFE (immediately invoked function expressions) and the main function runs only once.
You need to call your inner function using setInterval with 0 milliseconds gap.
$(function(){
function myFunc(){
console.log("1");
}
setInterval(myFunc,0);
});
your anonymous function (the outer one) runs when the page is loaded. This places a call to myFunc which outputs 1 to the console and then ends. If you wanted to loop you might try calling myFunc at the end of the myFunc function, but if you did this you would find that your browser would hang and that eventually you run out of memory. This is because the call stack would grow and grow, never allowing the UI to respond as javascript is completely in control!
Alternatively, you can use setTimeout(myFunc, delay) at the end of your method, which will call it again after a certain amount of milliseconds has passed. This will not fill the call stack and will allow the UI to respond, but you will have to specify the interval.
A final way is to use 'setInterval(myFunc, delay)' in the place of your outerbody call to 'myFunc()'. This will repeatedly call your function every 'delay' milliseconds forever.
From the comments, it seems to be clear that you are in dire need to having a Responsive Framework.
Bootstrap is the most popular HTML, CSS, and JS framework for developing responsive, mobile first projects on the web.
It removes the need for having/designing separate pages for mobile and desktop.
Just go through the pre-defined bunch of CSS classes and you are set.
No need to write complex logic for window resizing and all that..
Hope it helps.
If you just need to check for changing window size per your comment, try
$(function () {
$(window).resize(function () {
//insert code here
});
});
you can use setTimeout() for execute same function after some interval assume 5 seconds
$(function() {
myFunc(); // call initially when dom is ready
function myFunc() {
console.log("1");
setTimeout(function(){ myFunc(); }, 5000) // runs after every 5 seconds
}
});
you can use setInterval() as well.
$(function() {
function myFunc() {
console.log("1");
}
setInterval(myFunc,0);
});
Your code only runs once (when the page loads). If you want to run code as fast as your computer can handle, use while(true) {/Your Code here.../} or var interval = setInterval(1, function() {/Your Code Here/});will run the code every 0.001 seconds, and clearInterval(interval); to stop the code from running. See this link for more details.
You can do by:
while(1){
myFunc();
}
But explain your requirement first.
If you want a function to run every time you should be placing your function in setInterval with interval of 1ms though its not a recommended way of doing it.
$(function(){
setInterval(myFunc,1)
function myFunc(){
console.log("1");
}
});
could you please explain your use case for the same,or you could also try to wrap your function call inside a loop.
I'm trying to get a javascript function to run only once. I've seen this question has been asked before, e.g. Function in javascript that can be called only once, but I can't get the solutions in here to work. I'm not sure if it's because I've got nested functions, or whether there's something I'm missing. Essentially, I'm trying to run a function which, when a webpage is scrolled, it:
- runs a little animation on a canvas in the header
- reduces the size of the header
- leaves it at that
But when there is any subsequent scrolling, the animation keeps re-running. Here's a summarised version of the non-working code:
$(document).on("scroll",function(){
var arrange_title = function(){
//some code
};
if($(document).scrollTop()>0){
arrange_title();
arrange_title = function(){};
setTimeout(function(){
$("header").removeClass("large").addClass("small");
},1000);
}
});
I've also tried declaring a global variable, setting it to "false" in a "window.onload" function, then set it to true in an if function that runs the animation (the if function running only if the variable is false), but that doesn't stop it either. Thoughts?
What you're looking for is something along the lines of listenToOnce where the listener fires the one time, but never again. This could be modified to a number of calls, but the logic is like so:
Register the listener.
Then once the listener fires, remove it.
See .off
$(document).on("scroll",function(){
var arrange_title = function(){
//some code
};
if($(document).scrollTop()>0){
arrange_title();
arrange_title = function(){};
setTimeout(function(){
$("header").removeClass("large").addClass("small");
// $(document).off('scroll'); // or here
},1000);
}
$(document).off('scroll'); // remove listener, you can place this in the setTimeout if you wish to make sure that the classes are added/removed
});
Don't use a time out. That is why you are getting in trouble. Declare a variable outside of your function using var, that will make it global. Your code should be inside of a check for that variable. Before executing your code the first time but inside of the check, change that variable so that the code will never run again.
Try avoid setTimeout. Almost all animation can be watched for end.
function doHeaderAnimation() {
return $('header').animate();
}
function makeHeaderSmall() {
$("header").removeClass("large").addClass("small");
}
function handleScroll(event) {
if ($(document).scrollTop() > 0) {
doHeaderAnimation().then(makeHeaderSmall);
$(document).off("scroll", handleScroll);
}
}
$(document).on("scroll", handleScroll);
I'm trying to find a way to stop a function at a certain point until something does not have a specific class anymore. I cannot change the place where this class is being assigned and removed because it's a plugin.
I was thinking of doing something like this
function DoSomething() {
while ($('div.divControl').hasClass('playing'))
{
//Wait here
}
};
Is this the correct way to go?
This will block so the element will never be changed, as no other code will execute.
What you need to use is an interval:
var interval = setInterval(DoSomething, 500);
function DoSomething() {
if ($('div.divControl').hasClass('playing'))
{
// Do something
clearInterval(interval);
}
};
This will execute the function every half second. The interval will be cancelled after the function succeeds.
No, that will just hang the browser as it goes into an infinite loop.
Your best bet (as best I can think at the moment anyhow) is to do a setTimeout on the function and have it check to see if it your div still has the class every quarter of a second or so.
Still, not nice at all =[
I'm using jQuery to change the HTML of a tag, and the new HTML can be a very long string.
$("#divToChange").html(newHTML);
I then want to select elements created in the new HTML, but if I put the code immediately following the above line it seems to create a race condition with a long string where the changes that html() is making may not necessarily be finished rendering. In that case, trying to select the new elements won't always work.
What I want to know is, is there an event fired or some other way of being notified when changes to html() have finished rendering ? I came across the jQuery watch plugin, which works alright as workaround but it's not ideal. Is there a better way ?
As a commenter already mentioned, JavaScript is single threaded, so you can't get race conditions.
What may trip you up however, is the fact that the UI will not update itself based on JavaScript, until a thread is finished. This means that the entire method must finish, including all code after you call html(...), before the browser will render the content.
If your code after calling html(...) relies on the layout of the page being recalculated before continuing, you can do something like this:
$("#divToChange").html(newHTML);
setTimeout(function() {
// Insert code to be executed AFTER
// the page renders the markup
// added using html(...) here
}, 1);
Using setTimeout(...) with a time of 1 in JavaScript defers execution until after the current JavaScript code in the calling function finishes and the browser has updated the UI. This may solve your problem, though it is difficult to tell unless you can provide a reproducible example of the error you're getting.
use .ready jQuery function
$("#divToChange").html(newHTML).ready(function () {
// run when page is rendered
});
It's 7 years latter and I just ran into a scenario exactly like the one #mikel described, where I couldn't avoid a "timer based solution". So, I'm just sharing the solution I developed, in case anyone out there is still having issues with this.
I hate having setTimeouts and setIntervals in my code. So, I created a small plugin that you can put where you think it's best. I used setInterval, but you can change it to setTimeout or another solution you have in mind. The idea is simply to create a promise and keep checking for the element. We resolve the promise once it is ready.
// jquery.ensure.js
$.ensure = function (selector) {
var promise = $.Deferred();
var interval = setInterval(function () {
if ($(selector)[0]) {
clearInterval(interval);
promise.resolve();
}
}, 1);
return promise;
};
// my-app.js
function runWhenMyElementExists () {
// run the code that depends on #my-element
}
$.ensure('#my-element')
.then(runWhenMyElementExists);