How can I re enable a setInterval after I called clearInterval? - javascript

Here's my javascript:
<script type="text/javascript">
var timer;
$(document).ready(function () {
timer = setInterval(updatetimerdisplay, 1000);
$('.countdown').change(function () {
timer = setInterval(updatetimerdisplay, 1000);
});
function updatetimerdisplay() {
$(".auctiondiv .auctiondivleftcontainer .countdown").each(function () {
var newValue = parseInt($(this).text(), 10) - 1;
$(this).text(newValue);
if (newValue >= 9) {
$(this).css("color", "");
$(this).css("color", "#4682b4");
}
if (newValue == 8) {
$(this).css("color", "");
$(this).css("color", "#f3982e");
}
if (newValue == 5) {
$(this).css("color", "");
$(this).css("color", "Red");
}
if (newValue <= 1) {
//$(this).parent().fadeOut();
clearInterval(timer);
}
});
}
});
var updateauctionstimer = setInterval(function () {
$("#refreshauctionlink").click();
}, 2000);
function updateauctions(response) {
var data = $.parseJSON(response);
$(data).each(function () {
var divId = "#" + this.i;
if ($(divId + " .auctiondivrightcontainer .latestbidder").text() != this.b) {
$(divId + " .auctiondivrightcontainer .latestbidder").fadeOut().fadeIn();
$(divId + " .auctiondivrightcontainer .auctionprice .actualauctionprice").fadeOut().fadeIn();
$(divId + " .auctiondivleftcontainer .countdown").fadeOut().fadeIn();
}
$(divId + " .auctiondivrightcontainer .latestbidder").html(this.b);
$(divId + " .auctiondivrightcontainer .auctionprice .actualauctionprice").html(this.p);
if ($(divId + " .auctiondivleftcontainer .countdown").text() < this.t) {
$(divId + " .auctiondivleftcontainer .countdown").html(this.t);
}
});
}
</script>
Basically, I want to turn the timer back on, if any .countdown element has it's text change.
The text will change because of an AJAX call I use to update that value.
Currently the timer doesn't re enable and the countdown freezes after the value of .Countdown is changed. I think that the change() event fires when the text of an element changes. Is this correct?
Any glaring mistakes on my part?

Your code contains a loop and condition:
function updatetimerdisplay() {
$(".auctiondiv .auctiondivleftcontainer .countdown").each(function () {
...
if (newValue <= 1) {
//$(this).parent().fadeOut();
clearInterval(timer);
}
...
}
}
It's very likely that one of these elements have a value which satisfy the condition newValue <= 1. In that case, the timer will stop. Even when you change the contents of an input field, the timer will immediately stop after that run.
If you have to support multiple timers, use a wallet of timers (var timers = {};timers.time1=... or var timers = [];timers[0] = ...). If you have to support only a few timeouts, you can even use variables (var timer1=... ,timer2=..., timer3=...;).

You are trying to bind the change event before the elements exist. Put that code inside the ready event handler:
$(document).ready(function () {
timer = setInterval(updatetimerdisplay, 1000);
$('.countdown').change(function () {
timer = setInterval(updatetimerdisplay, 1000);
});
});
You also might want set the timer variable to an identifiable value when the timer is off (e.g. null), so that you can check for that value before you start a timer to prevent from starting multiple timers.

Related

JavaScript clearTimeout not firing correctly

I have a submit function on a textbox with JavaScript. When the script fires, it checks a Kendo grid for a certain article and adds +1 to its quantity as well as opening the corresponding cell in editing mode. What I want to achieve is that on every submit the timer that starts grid.editCell() will reset its timer.
Currently, the event fires properly. However, the timer doesn't get reset, although the clearTimeout() does work if I just simply start the timer and then clear it right afterwards.
JavaScript:
$('#txtBarcode').submit(function (e) {
var grid = $("#PickListDetailGrid").data("kendoGrid");
var dataSource = $("#PickListDetailGrid").data("kendoGrid").dataSource;
var allData = grid.dataSource.data();
var code = this.value;
var notification = $("#notification").data("kendoNotification");
var timer = null;
clearTimeout(timer);
$.each(allData, function (index, item) {
if (item.ArticleID == code) {
clearTimeout(timer);
timer = null;
if (item.Quantity > item.PickedQuantity && item.PickedQuantity.toString().length < 4) {
var edit = function () {
if (item.PickedQuantity != item.Quantity && timer != null) {
grid.select("tr:eq(" + (index) + ")");
grid.editCell("tr:eq(" + (index + 1) + ") td:eq(" + (5) + ")");
} else {
//do nothing
}
}
item.PickedQuantity++;
item.dirty = true;
dataSource.sync();
if (item.PickedQuantity != item.Quantity) {
console.log("tik tok");
if (timer) {
clearTimeout(timer); //cancel the previous timer.
timer = null;
}
timer = setTimeout(edit, 3000);
} else {
clearTimeout(timer);
timer = null;
}
document.getElementById("txtBarcode").value = "";
} else {
if (item.PickedQuantity.toString().length > 4) {
notification.hide();
notification.show({
message: "Added item"
}, "upload-success");
} else {
notification.hide();
notification.show({
title: "Quantity Error",
message: "You already picked this item to the maximum"
}, "error");
document.getElementById("txtBarcode").value = "";
grid.select("tr:eq(" + (index) + ")");
grid.editCell("tr:eq(" + (index + 1) + ") td:eq(" + (5) + ")");
$('.focus :input').focus();
}
}
}
})
})
You can try delay function like this. The delay function should be outside of the each function.
var delay = (function() {
var timer = 0;
return function(callback, ms) {
clearTimeout(timer);
timer = setTimeout(callback, ms);
};
})();
delay(function() {
//do something
}, 3000);
The problem was that var timer = null; had to be outside of the submit function to be properly cleared and set to null before assigning a new setTimeout() to it.

Dynamically create multiple slide shows using setTimeout

I want to create a slide show of the number of objects in the "SliderArray" array when I click on the button.
The current JSfiddle is available in standalone mode.
When I take the function into the loop, things get messy
var myFunction = function() {
if (counter == 0) {
$('#' + sliderarray[0].slaytarray[counter].id).fadeIn();
frametime = sliderarray[0].slaytarray[counter].frame_time * 1000;
counter++;
} else if (counter == sliderarray[0].slaytarray.length) {
$('#' + sliderarray[0].slaytarray[counter - 1].id).fadeOut();
counter = 0;
frametime = 0;
} else {
$('#' + sliderarray[0].slaytarray[counter - 1].id).fadeOut();
$('#' + sliderarray[0].slaytarray[counter].id).fadeIn();
frametime = sliderarray[0].slaytarray[counter].frame_time * 1000;
counter++;
}
timeout = setTimeout(myFunction, frametime);
}
var timeout = setTimeout(myFunction, frametime);
And here my objects
This is "messy" because you never manipulate the second slider.
I fixed it by using a .forEach on the sliderarray:
var myFunction = function() {
if (counter == 0) {
sliderarray.forEach(function (slider) {
$('#' + slider.slaytarray[counter].id).fadeIn();
frametime = slider.slaytarray[counter].frame_time * 1000;
});
counter++;
} else if (counter == sliderarray[0].slaytarray.length) {
sliderarray.forEach(function (slider) {
$('#' + slider.slaytarray[counter - 1].id).fadeOut();
});
counter = 0;
frametime = 0;
} else {
sliderarray.forEach(function (slider) {
$('#' + slider.slaytarray[counter - 1].id).fadeOut();
$('#' + slider.slaytarray[counter].id).fadeIn();
frametime = slider.slaytarray[counter].frame_time * 1000;
});
counter++;
}
There is still a problem for the frametime because you're only using once when two are needed. I'll just let you look into it.
See updated JSFiddle

Temporarily Disable a DIV while setInterval is running

I want to disable some part of my html while Im running setInterval and make it back again after the setInterval is complete.
How is it?
<div id="on">CLICK THIS : <span id="status">ENABLED</span></div>
<button id="run">LOAD</button
$('#run').on('click', function () {
var i = 0;
var go = setInterval(function () {
i++;
$('#run').html('Loading ' + i + ' or 10...');
$('#status').html('DISABLED');
$('#on').unbind('click keyup keypress keydown');
if (i === 10) {
clearInterval(go);
$('#status').html('ENABLED');
$('#run').html('DONE');
}
}, 1000);
});
$('#on').on('click', function () {
$('#status').html('CLICKING');
});
Here, what i want to achieve is that when i click the Loading Button the Click This should not accept any click event until the loading is DONE. But click is still triggered. Is there any other way to do this?
[And i dont want to use disabled="disabled"]
If you do not want a click event to trigger a callback unbind the event or set a flag that is checked in the callback. Also you are doing the unbind within the callback, so event will not be unbound till it is called for the first time
$('#run').on('click', function () {
var i = 0;
$('#status').html('DISABLED');
$("#on").unbind('click keyup keypress keydown');
var go = setInterval(function () {
i++;
$('#run').html('Loading ' + i + ' or 10...');
if (i === 10) {
clearInterval(go);
$('#status').html('ENABLED');
$('#run').html('DONE');
$("#on").on("click",onDivClicked);
}
}, 1000);
});
$('#on').on('click', onDivClicked);
function onDivClicked(){
$('#status').html('CLICKING');
}
Or setting a flag
$('#on').data("active",true);
$('#run').on('click', function () {
var i = 0;
$('#status').html('DISABLED');
$("#on").data("active",false);
var go = setInterval(function () {
i++;
$('#run').html('Loading ' + i + ' or 10...');
if (i === 10) {
clearInterval(go);
$('#status').html('ENABLED');
$('#run').html('DONE');
$("#on").data("active",true);
}
}, 1000);
});
$('#on').on('click', function () {
if(!$(this).data("active")) return;
$('#status').html('CLICKING');
});
demo
$('#run').on('click', function () {
var i = 0;
var go = setInterval(function () {
i++;
$('#on').attr("running","true");
$('#run').html('Loading ' + i + ' or 10...');
$('#status').html('DISABLED');
if (i === 10) {
clearInterval(go);
$('#status').html('ENABLED');
$('#run').html('DONE');
$('#on').removeAttr("running");
}
}, 1000);
});
$('#on').on('click', function () {
var running = $(this).attr('running');
if (typeof running !== typeof undefined && running !== false) {
}
else{
$('#status').html('CLICKING');
}
});
Maybe this helps
function foo(){
var i = 0;
$('#on').off('click', foo);
var go = setInterval(function () {
i++;
$('#run').html('Loading ' + i + ' or 10...');
$('#status').html('DISABLED');
$(document).unbind('click keyup keypress keydown');
if (i === 10) {
clearInterval(go);
$('#on').on('click', foo);
$('#status').html('ENABLED');
$('#run').html('DONE');
}
}
$('#on').on('click', foo);

Initialize onchange event inside a loop - Javascript

I'm trying to bind an onChange event to 7 dropdowns inside a loop. But when any of dropdown changes, the onChange event for the last one is always executed.
$(function () {
for (var i = 1; i <= 7; i++) {
$('select[id$="bodysys' + i + '"]').change(function () {
if (this.value == "99")
enabletextbox($('input[id$="bodysys' + i + 'spec"]')[0]);
});
}
}
How to make onChange work for all elements separately?
This is called the last one only problem, and is solved using a closure:
$(function () {
for (var i = 1; i <= 7; i++) {
(function (i) {
$('select[id$="bodysys' + i + '"]').change(function () {
if (this.value == "99")
enabletextbox($('input[id$="bodysys' + i + 'spec"]')[0]);
});
})(i);
}
}
It creates a new scope, so when i is changed in the original scope, it will not be changed in the old scope.
$('select[id*="bodysys"]').each(function (index) {
$(this).change(function () {
if ($("option:selected", this).val() == "99")
enabletext($('input[id$="bodysys' + (index + 1) + 'spec"]')[0]);
});
});
This way works too.

pause and continue using setInterval

what i want to achieve is when you click this href pause/continue the timer pauses and continues when pressed again.
<script>
$(document).ready(function () {
var counter = 10;
var id = setInterval(function() {
counter--;
if(counter > 0) {
var msg = 'You can continue ' + counter + ' seconds';
$('#notice').text(msg);
} else {
$('#notice').hide();
$('#download').show();
clearInterval(id);
}
}, 1000);
});
</script>
My HTML in relevance to the jQuery is here if you need.
Continue !!<p id="notice">
You can continue in 10 seconds</p>
Well, I would just have your pause event set a boolean, and then check that boolean before you decrement your counter:
pause/continue
and
var ispaused=false;
function setPause(){
ispaused=!ispaused;
}
and
$(document).ready(function () {
var counter = 10;
var id = setInterval(function() {
if(!ispaused){ ////the only new line I added from your example above
counter--;
if(counter > 0) {
var msg = 'You can continue ' + counter + ' seconds';
$('#notice').text(msg);
} else {
$('#notice').hide();
$('#download').show();
clearInterval(id);
}
}
}, 1000);
});
That should do it, right?

Categories

Resources