Stop setInterval() after a Specific Class Becomes Visible [duplicate] - javascript

This question already has answers here:
Stop setInterval call in JavaScript
(7 answers)
Closed 1 year ago.
Currently what I'm trying to do is have a function that looks for if the #discountbox element is visible then clone that #discountbox element and place it after .pricebox. Right now what's happening is that it is placing it after .pricebox and cloning it indefinitely.
How can I get the setInterval to stop after it finds #discountbox and clones it once?
HTML
<div id="discountbox" class="discount-summary">
You get $5 Off
</div>
<div id="modal">
<span class="price-box">
$20.50
</span>
</div>
Javascript
jQuery(document).ready(addDiscountsummary);
function addDiscountsummary () {
if($('#discountbox').is(':visible')){ //if the container is visible on the page
$("#discountbox").clone().insertAfter("#modal span.price-box"); //insert add to cart button after view contents buttons
} else {
setInterval(addDiscountsummary, 1000); //check every 1000 ms
}
}

you're looking for clearInterval() or as mentioned, a better solution would be to use setTimeout and clearTimeout instead
jQuery(document).ready(addDiscountsummary);
function addDiscountsummary () {
if($('#discountbox').is(':visible')){ //if the container is visible on the page
$("#discountbox").clone().insertAfter("#modal span.price-box");
clearTimeout(window.nextTimeout);
} else {
window.nextTimeout = setTimeout(addDiscountsummary, 1000); //check every 1000 ms
}
}

After it finds the button
Call clearInterval() method to stop your interval.

Try adding:
var testData = !!document.getElementById("discountbox");
if(testData=="true"){clearInterval(addDiscountsummary)}
else{};
To your code.
This checks if the element exists in the code and returns true if the element exists:
var testData = !!document.getElementById("discountbox");
This stops the loop testData returns true.
if(testData=="true"){clearInterval(addDiscountsummary)}

clearInterval(intervalID) will do the trick.
When your doc loads, set the interval. Make sure the ID (which I am calling interval) is first created outside of any function, available to the rest of the page. When your item is found, clearInterval(interval)
let interval
jQuery(document).ready(function() {
interval = setInterval(addDiscountsummary, 1000);
});
function addDiscountsummary() {
if ($('#discountbox').is(':visible')) {
$("#discountbox").clone().insertAfter("#modal span.price-box");
clearInterval(interval)
}

Related

Update div only if a certain conditions holds true

I am writing a simple webserver with micropython.
I want to switch on a relay for a certain duration (given in input by the user from the HTML form).
When the relay is off, I display a div with the input form for the duration and the activation button.
When the relay is on, the same div is replaced with a countdown; when the relay is on I want to refresh the div every second so that the countdown is updated. When the relay is off, I don't want the div to update because otherwise, if you try to input the duration, every second the input number in the box is cleared.
My div is updated by the following script:
<script>
$(document).ready(function () {
setInterval(function () {
$("#div_name").load(window.location.href + " #heatingDiv");
}, 1000);
});
</script>
The div is:
<div id="div_name">
<h1>Title</h1>
insert_content
</div>
The keyword "insert_content" is replaced with the HTML code inside the micropython program (accordingly to the relay state) before the HTML response is sent.
With the previous code everything works fine except for the fact that the div is updated every second even when the relay is off, making it impossible to input the duration in the form.
What I'd like to do is passing an argument to the script similarly as when one uses onClick to call it (I can modify "state" within micropython before sending the response):
<div id="div_name(state)">
<h1>Title</h1>
insert_content
</div>
and the script should look like:
<script>
$(document).ready(function () {
setInterval(function (var state) {
if(state){
$("#div_name").load(window.location.href + " #heatingDiv");
}
}, 1000);
});
</script>
Of course this does not work because id=div_name is not a function call: it is just to give an idea of what I'd like to achieve.
How can I do that?
Why not use a data attribute:
const $div = $("#div_name");
const state = $div.data('state');
if (state) {
setInterval(function() {
$div.load(window.location.href + " #heatingDiv");
}, 1000);
}
// if you are wanting to do the interval to check if the state changes, you could change it around
setInterval(function() {
const state = $div.data('state');
if (state) {
$div.load(window.location.href + " #heatingDiv");
}
}, 1000);
<div id="div_name" data-state="state">
<h1>Title</h1>
insert_content
</div>
Perhaps if you are only wanting to run the load when the state changes, you may be better of with a MutationObserver watching the data attribute instead of a timeout

Click event doesn't produce any result

total noob here.
I'm writing a countdown timer that starts clicking on a "Start" button. No matter what I do, the timer always starts at the load of the page. And I mean that, when using live server on VS Code, every time I give the page a save, the timer starts.
No error appears in the console.
Probably I'm missing something really basilar, but I would love some help!
const btnStart = document.querySelector('.start');
const startTimer = function() {
let time = 10;
const timer = setInterval(function() {
const min = String(Math.trunc(time/60));
const sec = String(time%60);
time --;
input.value = `${min.length <= 9 ? min.padStart(2, 0) : min}:${sec.length <= 9 ?sec.padStart (2, 0) : sec}`;
if(time == 0){
setTimeout(function(){clearInterval(timer);
startTimer();}, 1000)
}
}, 1000)
}
btnStart.addEventListener('click', startTimer);
Html elements part:
<div class="main-container">
<input type="text" class="input" placeholder="MM:SS">
<div class="buttons-container">
Start
<button class="start">START</button>
Stop
Reset
</div>
</div>
You new edit to the question answered the question.
You're using VSCode LiveShare. When you save, it doesn't actually reload the page, it just loads the changes.
Since you're recursively calling startTimer(); (it's calling itself inside a setTimeout), it will never stop since it's not a full reload.
The easiest way to fix this is to reload your page manually (Ctrl+r or Command+r)
The harder way you could solve this is to store timer as a global variable, and on load, if timer exists, run clearInterval(timer)

Animate text change over time with JavaScript

I need to animate text change over time that never stops.
I've found this simple example with jquery:
$(function() {
$('#header-text-change').fadeOut(500, function() {
$(this).text('Some other text!').fadeIn(500);
});
});
Now I need to have more than one predefined text and that animation loops forever.
Thanks.
You can use setInterval() function to loop every N milliseconds.
Look this code snippet:
This example reset the index variable to 0 when hits TEXTS.length
var TEXTS = ["Some other text!", "Lord of the Rings", "Avengers", "Whatever text"];
var index = 0;
$(function() {
setInterval(function() {
$('#header-text-change').fadeOut(500, function() {
$(this).text(TEXTS[index++]).fadeIn(500);
if (index === TEXTS.length)
index = 0
});
}, 1000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1 id="header-text-change">
Hellow World!!
</h1>
See? now your code is looping, in this case every one second (1000ms).
function fadeout(){$('#header-text-change').fadeOut(undefined,changeText)}
function changeText(){
// implements your logic for changing the text
fadein();
}
function fadein(){$('#header-text-change').fadeIn(undefined,fadeout)}
You call fadeout and it loops using the callbacks( and they are named so you can reference them). Passing undefined as the first argument to fadeOut/fadeIn will use the default value of 400ms, you could change that by passing a variable that stores how long you want the animation to take.

adding class to array elements through loop

I need the loop that checks input fields from 'inputs' array, and if there are empty fields, special dialog need to be displayed near them, and after the dialog is displayed I need class 'style' to be added to the input field near which the dialog was displayed, then dialog should go to the next emppty field and add class 'style' to it. And so on until all empty inputs have class 'style'.
The problem is, in my loop after the dialog is displayed class 'style' is added only to the last element from the array, but it should be added to every empty element with delays in between.
This is my loop, but as I said it is not working properly:
for(i=0;i<inputs.length;i++){
var now = inputs[i];
var top = inputs[i].attr('top');
if(!now.val()){
if(dialog.css('display')=='none'){now.addClass('style');dialog.css('top',top).fadeIn(200);}
else{dialog.delay(300).animate({"top": top}, 500, function(){now.addClass('style');});
}else{now.removeClass('style');}}
P.S. Sorry for my English.
This is happening because the function that is calling 'addClass' is happening after the 300 millisecond animation. By that time, the value of the 'i' variable has changed because the for loop will continue to run.
You may just be able to have the 'now.addClass' call before the 'animate' and delay. Otherwise, you will have to break the loop and continue after the animation is complete to prevent the variable from being overwritten.
Here is an example of what I was talking about. The code below will process 1 input at a time and not continue to the next until the current one is finished processing (this code has not been tested):
var offset = -1;
var inputs = (something goes here)
iterateInputs();
function iterateInputs()
{
offset++;
if (typeof inputs[offset] != 'undefined')
{
eachInput();
}
else
{
// all done!
}
}
function eachInput()
{
var now = inputs[offset];
var top = inputs[offset].attr('top');
if (!now.val())
{
if (dialog.css('display')=='none')
{
now.addClass('style');
dialog.css('top', top).fadeIn(200, function(){
iterateInputs();
});
}
else
{
dialog.delay(300).animate({"top": top}, 500, function(){
now.addClass('style');
iterateInputs();
});
}
}
else
{
now.removeClass('style');
iterateInputs();
}
}

make div text disappear after 5 seconds using jquery?

i need to make a div text disappear after x seconds of displaying it using an ajax call
can you help me on this please ?
thanks
You can use empty() to remove a <div> contents:
setTimeout(fade_out, 5000);
function fade_out() {
$("#mydiv").fadeOut().empty();
}
assuming:
<div id="mydiv">
...
</div>
You can do this with an anonymous function if you prefer:
setTimeout(function() {
$("#mydiv").fadeOut().empty();
}, 5000);
or even:
var fade_out = function() {
$("#mydiv").fadeOut().empty();
}
setTimeout(fade_out, 5000);
The latter is sometimes preferred because it pollutes the global namespace less.
You can try the .delay()
$(".formSentMsg").delay(3200).fadeOut(300);
call the div set the delay time in milliseconds and set the property you want to change, in this case I used .fadeOut() so it could be animated, but you can use .hide() as well.
http://api.jquery.com/delay/
$.doTimeout( 5000, function(){
// hide the div
});
You would need to set something like setTimeout('$("#id").fadeOut("slow")', 5000) but other than that it depends on what the rest of your code looks like
This should work:
$(document).ready(function() {
$.doTimeout(5000, function() {
$('#mydiv').fadeOut();
});
});
You may need to display div text again after it has disappeared.
This can be done in 1 line.
$('#div_id').empty().show().html(message).delay(3000).fadeOut(300);
This Answer is without jQuery, you can just grab your element and know its index position.
Then use it in the div below. I will be your div's index number in dom.
const div = document.querySelectorAll('div');
setTimeout(() => {
div[i].textContent = '';
}, 3000);

Categories

Resources