I am currently setting up two buttons, start and stop for a jquery loop on html5. The start button works perfectly but whatever I try the 'stop' button remains inactive. I have seen many examples about stopping the loop but none seems to resolve the issue in the button being unresponsive. Sorry if this is such a simple question, but as a student I am quite frustrated and thus asking. cheers
"use strict";
var current_banner_num = 1;
$(document).ready(function(){
$("#banner-base").css("visibility","hidden");
$("#banner-"+current_banner_num).show();
var next_button = $("#start").button();
var stop_button = $("#stop").button();
next_button.click(function(){
var timer = setInterval(myCode, 2000);
function myCode() {
//$("#banner-"+current_banner_num).hide();
$("#banner-"+current_banner_num).fadeTo(800, 0);
if (current_banner_num == 4) {
current_banner_num = 1;
}
else {
current_banner_num++;
}
$("#banner-"+current_banner_num).fadeTo(800, 1);
}
});
stop_button.click(function(){
function abortTimer(){
clearInterval(timer);
}
});
});
You are just defining a function again and again here. Just get rid of the function in the event handler:
stop_button.click(function(){
clearInterval(timer);
});
This would execute the clearInterval(), while the code in your original question just defines a function, but doesn't call or do anything as you said. Hope it gets solved.
I think you have 2 problems in your code. timer variable is not visible outside of next_button.click(function(){ ... }); because it is local for this function, so you need to make it a little bit global; second problem is that in stop_button.click(function(){ ... }); you just declare function abortTimer but do not call it (in general, it is not necessary to declare that function). I think your code should be like:
"use strict";
var current_banner_num = 1;
$(document).ready(function(){
$("#banner-base").css("visibility","hidden");
$("#banner-"+current_banner_num).show();
var next_button = $("#start").button();
var stop_button = $("#stop").button();
var timer = null;
next_button.click(function(){
timer = setInterval(function(){
//$("#banner-"+current_banner_num).hide();
$("#banner-"+current_banner_num).fadeTo(800, 0);
if (current_banner_num == 4) {
current_banner_num = 1;
}
else {
current_banner_num++;
}
$("#banner-"+current_banner_num).fadeTo(800, 1);
}, 2000);
});
stop_button.click(function(){
clearInterval(timer);
});
});
Also it wasn't necessary to declare function myCode in nextButton function, so i clear it too for you
Use a global variable instead of a local one ,unwrap the clearInterval function
"use strict";
var current_banner_num = 1;
$(document).ready(function(){
$("#banner-base").css("visibility","hidden");
$("#banner-"+current_banner_num).show();
var next_button = $("#start").button();
var stop_button = $("#stop").button();
var timer = null;
next_button.click(function(){
timer = setInterval(myCode, 2000);
function myCode() {
//$("#banner-"+current_banner_num).hide();
$("#banner-"+current_banner_num).fadeTo(800, 0);
if (current_banner_num == 4) {
current_banner_num = 1;
}
else {
current_banner_num++;
}
$("#banner-"+current_banner_num).fadeTo(800, 1);
}
});
stop_button.click(function(){
clearInterval(timer);
});
});
Related
I have 31 images and I want to display them one after another as the background of a div. I only want it to change when the user hovers over the div. My problem right now is that it just flips through all the images really fast. I am attempting to use setTimeout, but it isn't working. How can I make the delay work?
The name of the div is About_Me_Block and the images are called frame1.gif,frame2.gif ...etc
Here is my code:
function changeImg(counter) {
$('#About_Me_Block').attr("style", "background-image: url(playGif/frame" + counter + ".gif);");
}
$(document).ready(function() {
var hoverAnimate = []
"use strict";
$('#About_Me_Block').mouseenter(function() {
hoverAnimate[0] = true;
var counter = 0;
while (hoverAnimate[0]) {
console.log(counter);
setTimeout(changeImg(counter), 1000);
counter++;
if (counter === 32)
hoverAnimate[0] = false;
}
});
$('#About_Me_Block').mouseleave(function() {
hoverAnimate[0] = false;
$(this).attr("style", "background-image: url(play.jpeg);");
});
});
setTimeout doesn't wait for the function to end, it works lile threading in other languages.
To achieve a what you want, you need to call setTimeout from the changeImg function.
var counter = 0;
$(document).ready(function() {
var hoverAnimate = []
"use strict";
$('#About_Me_Block').mouseenter(function() {
hoverAnimate[0] = true;
counter = 0;
changeImg();
});
$('#About_Me_Block').mouseleave(function() {
hoverAnimate[0] = false;
$(this).attr("style", "background-image: url(play.jpeg);");
});
});
function changeImg() {
$('#About_Me_Block').attr("style", "background-image: url(playGif/frame" + counter + ".gif);");
counter++;
if (counter < 32 && hoverAnimate[0]) {
setTimeout(changeImg, 1000);
} else {
hoverAnimate[0] = false;
}
}
the reason they happen all at once is because while statement doesn't have delay, so all setTimeout will be set up at the same time, thus, calling changeImg all at once.
To solve this problem, you can replace setTimeout with setInterval. Instead of using while, you can just call setInterval like
var counter = 0;
var myTimer = setInterval(changeImg, 1000);
and update counter inside changeImg every time it gets called. After looping, don't forget to
clearInterval(myTimer)
It seems you need to read up on how setTimeout works. It essentially places a reminder to run a function after a given amount of milliseconds have passed. So, when you do setTimeout(changImg(counter), 1000) you are calling changImg(counter) which returns undefined. Therein producing this setTimeout(undefined, 1000) which is why it flips really fast.
So, you can use bind to allow the function to be called later with that parameter built in. Also, make sure you remove the reminders once done with clearTimeout.
function changeImg(counter) {
$('#About_Me_Block').attr("style", "background-image: url(playGif/frame" + counter + ".gif);");
}
$(document).ready(function() {
var hoverAnimate = false, id;
function loop(counter) {
if(hoverAnimate || counter < 32) {
changeImg(counter);
id = setTimeout(loop.bind(this, counter++), 1000);
}
}
$('#About_Me_Block').mouseenter(function() {
hoverAnimate = true;
id = setTimeout(loop.bind(this, 0), 1000);
});
$('#About_Me_Block').mouseleave(function() {
hoverAnimate = false;
// Don't want a reminder for a random counter to wake up.
clearTimeout(id);
$(this).attr("style", "background-image: url(play.jpeg);");
});
});
Two methods for timers - setTimeout and SetInterval (single / repeating)
// setInterval is also in milliseconds
var intervalHandle = setInterval(<yourFuncToChangeImage>,5000);
//this handle loop and make example loop stop
yourelement.yourEvent = function() {
clearInterval(intervalHandle);
};
I made a control (numeric spinner up and down), to work in a table:
JSFIDDLE: http://jsfiddle.net/Leandro1981/wn8vd/1/
and I want simulate the "mousedown, increment while mouse button is helding" but I can't do it. I tried to mix it with the following and functional script:
JSFIDDLE: http://jsfiddle.net/Leandro1981/kKW85/
but I couldn't make it.
My last attempt here:
http://jsfiddle.net/Leandro1981/S8Zt9/1/
Maybe the wrong is the
timeout = setInterval(function () {
But I couldn't figure out. I'm using bootstrap 3, so I can't use some JQuery UI plugins...
Any help will be preciated!
Please comment below if you have any question, comment or anything to improve this question, and sorry for my english :)
Please be free to use my code/control in any way.
Thanks and kind regards
Write a factory to set up each control so you get a closure over the variables, now it's just a matter of being able to make it work given the relevant elements. For this, you'll need to
Listen for mousedown on the up and down nodes to set off the changes
Start a timeout loop to keep doing your change
Listen for mouseup on window to ensure you cancel the timeout loop (you may also want to listen for mouseout/loss of focus)
So all together,
function spinFactory(node, up, down) { // I wrote this vanilla :D
var spinning, delta;
window.addEventListener('mouseup', stopSpin);
function spin() {
node.value = +node.value + delta;
spinning = setTimeout(spin, 500);
}
function stopSpin() { // maybe also invoke this on mouseout/loss of focus
window.clearTimeout(spinning);
delta = 0;
}
up.addEventListener('mousedown', function spinUp() {
delta = 1;
spin();
});
down.addEventListener('mousedown', function spinDown() {
delta = -1;
spin();
});
}
// apply to your control, used a bit of jQuery to make life easier
$('.PNET-spinner').each(function () {
spinFactory(
this.getElementsByTagName('input')[0],
$(this).find('.btn:first-of-type')[0],
$(this).find('.btn:last-of-type')[0]
);
});
DEMO
I have updated the Fiddle here ... Please check this and it might helps you..
Script
$('.PNET-spinner .btn:first-of-type').on('mousedown', function (e) {
var timer, proxy = this;
timer = setInterval(function () {
increment(proxy);
}, 200);
$(document).one("mouseup", function () {
increment(proxy);
if (timer) clearInterval(timer);
});
});
$('.PNET-spinner .btn:last-of-type').on('mousedown', function () {
var timer, proxy = this;
timer = setInterval(function () {
decrement(proxy);
}, 200);
$(document).one("mouseup", function () {
decrement(proxy);
if (timer) clearInterval(timer);
});
});
function increment(proxy) {
var numupdown = $('.PNET-spinner input', $(proxy).closest("tr"));
var inputValue = parseInt($(numupdown).val(), 10);
inputValue++;
$(numupdown).val(inputValue);
}
function decrement(proxy) {
var numupdown = $('.PNET-spinner input', $(proxy).closest("tr"));
var inputValue = parseInt($(numupdown).val(), 10);
if (inputValue > 1) {
inputValue--;
$(numupdown).val(inputValue);
}
}
You simply need to take care of two things. First, your function to increment and decrement the value in the textbox should be called again and again till user do mouseout or mouseup. Second, make surethis has the right value in var numupdown = $('.PNET-spinner input', $(this).closest("tr"));
Following code shows how to do it for the increment button. Similar thing, you can implement for decrement button.
var timeout;
var inc = function () {
var myThis = this;
var numupdown = $('.PNET-spinner input', $(this).closest("tr"));
var inputValue = parseInt($(numupdown).val(), 10);
inputValue++;
console.log(inputValue);
$(numupdown).val(inputValue);
clearTimeout(timeout);
timeout = setTimeout(function(){
//http://stackoverflow.com/questions/3630054/how-do-i-pass-the-this-context-to-a-function
inc.apply(myThis, arguments);
}, 1000);
};
var incStop = function(){
clearTimeout(timeout);
}
$('.PNET-spinner .btn:first-of-type').on('mousedown', inc);
$('.PNET-spinner .btn:first-of-type').on('mouseup', incStop);
$('.PNET-spinner .btn:first-of-type').on('mouseout', incStop);
Check this DEMO here.
I have trouble with timer in button click. When i click button startpause() method is called there i set start timer and stop timer. It works fine when I click button normally(one click after sometime another click) but when I click the button again and again speedly the timer starts to jump with 2-3 secs. Seems like more than one timer is running.. Anyone have any idea....?? here time is my timer method
function startpause() {
if(FLAG_CLICK) {
setTimeout(tim,1000);
FLAG_CLICK = false;
}
else {
clearTimeout(ti);
FLAG_CLICK = true;
}
}
function tim() {
time.innerHTML = t;
t = t + 1;
ti= setTimeout("tim()", 1000);
}
Try this:
// assuming you declared ti and t out here, cuz I hope they're not global
var t = 0;
var ti;
var running = false;
function startpause() {
clearTimeout(ti);
if(!running) {
ti = setTimeout(tim,1000);
running = true;
} else {
running = false;
}
}
function tim() {
time.innerHTML = t;
t = t + 1;
ti = setTimeout(tim,1000);
}
You can read more about the .setTimeout() here: https://developer.mozilla.org/en/docs/DOM/window.setTimeout
Also, see the jsfiddle I just created: http://jsfiddle.net/4BMhd/
You need to store setTimeout somewhere in order to manipulate it later.
var myVar;
function myFunction()
{
myVar=setTimeout(function(){alert("Hello")},3000);
}
function myStopFunction()
{
clearTimeout(myVar);
}
ref http://www.w3schools.com/js/js_timing.asp
Maybe you must change this:
if(FLAG_CLICK) {
setTimeout(tim,1000);
FLAG_CLICK = false;
}
to:
if(FLAG_CLICK) {
tim();
FLAG_CLICK = false;
}
It seems works for me normally
This is a followup to this question, where I found out how to make code be repeated every x seconds. Is it possible to make an event that can change this? I.e. I have a checkbox which is meant to control whether this is repeated or not, so I figured I'd need something like this:
$(checkbox).bind("change", function() {
switch(whether if it is ticked or not) {
case [ticked]:
// Make the code repeat, while preserving the ability to stop it repeating
case [unticked]:
// Make the code stop repeating, while preserving the ability to start again
}
});
I have no idea what I could put in the cases.
You can do it by assigning your setInterval function to a variable.
var interval = setInterval(function() { }, 1000);
and then you can stop setInterval by
clearInterval(interval);
p.s.
to start your interval you need to call var interval = setInterval(function() { }, 1000); again
You can either stop and start the interval:
var timer;
function start() {
timer = window.setInterval(function(){
// do something
}, 1000);
}
function stop() {
window.clearInterval(timer);
}
start();
$(checkbox).bind("change", function() {
if ($(this).is(':checked')) {
start();
} else {
stop();
}
});
Or you can have a flag causing the interval to skip the code:
var enabled = true;
var timer = window.setInterval(function(){
if (!enabled) {
// do something
}
}, 1000);
$(checkbox).bind("change", function() {
enabled = $(this).is(':checked');
});
function fooFunc() {
$('#foo').text(+new Date());
}
var id;
var shouldBeStopped = false;
$('input').change(function() {
if (shouldBeStopped)
clearInterval(id);
else
id = setInterval(fooFunc, 200);
shouldBeStopped = !shouldBeStopped;
});
Live DEMO
I am trying to write a javascript function that when called performs function DoSomething() once,
but can be triggered to perform the function repeatedly until triggered to stop.
I am using setTimeout() function. I am not sure if this is best method from performance and memory point of view.
Also I would like to avoid global variable if possible
<!DOCTYPE html>
<html>
<script src="jquery.js"></script>
<script>
var globalCheckInventory = false;
$(document).ready(function(){
// start checking inventory
globalCheckInventory = true;
myTimerFunction();
});
// check inventory at regular intervals, until condition is met in DoSomething
function myTimerFunction(){
DoSomething();
if (globalCheckInventory == true)
{
setTimeout(myTimerFunction, 5000);
}
}
// when condition is met stop checking inventory
function DoSomething() {
alert("got here 1 ");
var condition = 1;
var state = 2 ;
if (condition == state)
{
globalCheckInventory = false;
}
}
</script>
This is probably the easier way to do what you're describing:
$(function () {
var myChecker = setInterval(function () {
if (breakCondition) {
clearInterval(myChecker);
} else {
doSomething();
}
}, 500);
});
Another way to do it would be the store the timer ID and use setInterval and clearInterval
var timer = setInterval(DoSomething);
function DoSomething() {
if (condition)
clearInterval(timer);
}
I see nothing wrong with your implementation other than the pollution of the global namespace. You can use a closure (self-executing function) to limit the scope of your variables like this:
(function(){
var checkInventory = false, inventoryTimer;
function myTimerFunction() { /* ... */ }
function doSomething() { /* ... */ }
$(document).ready(function(){
checkInventory = true;
/* save handle to timer so you can cancel or reset the timer if necessary */
inventoryTimer = setTimeout(myTimerFunction, 5000);
});
})();
Encapsulate it:
function caller(delegate, persist){
delegate();
if(persist){
var timer = setInterval(delegate, 300);
return {
kill: function(){
clearInterval(timer);
}
}
}
}
var foo = function(){
console.log('foo');
}
var _caller = caller(foo, true);
//to stop: _caller.kill()