Calling setInterval from within function - javascript

I'm making a slider and i ran into problem. I'm practicing modular js and this code works fine for the first time, but setInterval won't repeat itself so the slides continue changing. How to make it work? Thanks in advance.
var currentSlide = 1;
var slider = {
init: function(){
this.cacheDom();
this.setInt();
},
cacheDom: function(){
this.$panel = $('.slider');
this.$actPan = this.$panel.find('.panel.active');
},
setInt: function(){
return setInterval(this.mainFunction(), 3000);
},
mainFunction: function(){
this.$actPan.fadeOut(2000, this.showNextPanel());
this.$panel.find('.tabs li:nth-child('+ currentSlide +')').find('img').attr('src', 'images/g4228.png');
},
showNextPanel: function(){
this.$panel.find('#panel' + currentSlide).removeClass('active');
this.revert();
},
revert: function(){
currentSlide++;
if(currentSlide === 4){currentSlide = 1;}
this.$panel.find('.tabs li:nth-child('+ currentSlide +')').find('img').attr('src', 'images/g4228.png');
this.$panel.find('#panel' + currentSlide).fadeIn(2000, this.adder());
},
adder: function(){
this.$panel.find('#panel' + currentSlide).addClass('active');
}
};
slider.init();
So, I'm thinking that only setInt and init functions needs changing.

The problem is this line:
return setInterval(this.mainFunction(), 3000);
This is calling this.mainFunction() and passing the result to setInterval; setInterval needs to be passed a function to call on an interval. Replace that with this:
return setInterval(this.mainFunction.bind(this), 3000);
The bind is needed so that this is preserved when setInterval calls it.

Related

Javascript, anyway to do a 'whileFocused' eventListener? (No JQuery)

Is there a way to implement or simulate a 'while focused' bind on a dom element?
Say log a message every second, starting when onfocus occurs, but stops upon leaving.
Considering this:
myinput.addEventListener("focus", function(){
setInterval(function(){
console.log('Mouse on:' + this)
}, 1000);
});
the only thing I can think of was using a global variable like:
var isfocused = false;
myinput.addEventListener("focus", function(){
isfocused = true;
setInterval(function(){
if (isfocused)
console.log('Mouse on:' + this)
}, 1000);
});
then adding another listener for onblur to toggle 'isfocused'
But that feels.....just wrong. And plus the setInterval would continue firing off in the background right?
Slight improvement to #Scott Schwalbe
(function(){
var intervalId;
myinput.addEventListener("focus", function(){
intervalId = setInterval(function(){
console.log('Mouse on:' + this)
}, 1000);
});
myinput.addEventListener("blur", function(){
clearInterval(intervalId);
});
})();
1) Wrap it in Immediately Invoked Function Expression to keep the global variable space pure.
2) The 'unfocus' event is really 'blur'
window.setInterval returns an id for your interval callback. You can then pass in that id to window.clearInterval(id) to stop it. Something like
var intervalId;
myinput.addEventListener("focus", function(){
intervalId = setInterval(function(){
console.log('Mouse on:' + this)
}, 1000);
});
myinput.addEventListener("unfocus", function(){
clearInterval(intervalId);
});

How to stop method execution defined in setTimeout

I am facing one problem in JS, please help me to resolve this.. I have two methods they are simultaneously executing one after other.. I have to stop them after second click on image.
Below is my JS code
I am calling fadeIn(img1, img2, img3) after first click on image then some animation will be goes on, once I click second time the whole animation(method execution) should be stopped.
var t1 = 0;
var t2 = 0;
function fadeIn(img1, img2, img3) {
$(imgIdForClick_1).addClass('animated pulse');
$('#cashBar1').addClass('animated pulse');
$('#cashBarDec1').addClass('animated pulse');
var t1 = setTimeout(function() {
fadeOut(img1, img2, img3);
if (clickCount_1 >= 2) {
alert("clicked 1");
return false;
}
}, 500);
//t1 = setTimeout(fadeOut, 500);
};
function fadeOut(img11, img22, img33) {
$(imgIdForClick_1).removeClass('animated pulse');
$('#cashBar1').removeClass('animated pulse');
$('#cashBarDec1').removeClass('animated pulse');
var t2 = setTimeout(function() {
fadeIn(img11, img22, img33);
if (clickCount_1 >= 2) {
alert("clicked 2");
return false;
}
}, 500);
//t2 = setTimeout(fadeIn, 500);
};
By below code I am calling this snippet in first click
imgId1 = $('#img1');
imgId2 = $('#cashBar1');
imgId3 = $('#cashBarDec1');
fadeIn(imgId1, imgId2, imgId3);
After second click
clickCount_1 varibale will be 2
clearTimeout(t1);
clearTimeout(t2);
See the DEMO. Click on the image to stop animation.
I have added a flag that would be checked upon the call of the function, and if the value is true then and then only the functions would be called. The flag would be set to false when clicked on image, so the function would be called no longer.
code:
var animate = true;
function fadeIn() {
$('#pulseDiv').find('div#advisersDiv').delay(400).addClass("pulse");
if(animate == true)
{
setTimeout(fadeOut,1000);
}
};
function fadeOut() {
$('#pulseDiv').find('div#advisersDiv').delay(400).removeClass("pulse");
if(animate == true)
{
setTimeout(fadeIn,1000);
}
};
fadeIn();
$('#image').click(function(){
animate = false;
alert('now the animation will stop');
});

unexpected indentifier javascript

Here I have a problem,I want to do a slider and I have an unexpected identifier on line window.clearTimeout(timer) in both functions nextSlide() and prevSlide(). Can you help me ?
var timer = new Object;
function slider(){
nextSlide();
window.setTimeout(slider, 5000);
}
function nextSlide(){
var $Slides = $(".contenu");
$Slides.animate(
{left: "-=213px"},
1000,
function(){
$Slides.data("currentSlide",$Slides.data("currentSlide")+1);
if($Slides.data("currentSlide") > $Slides.data("nbSlides")) {
$Slides.data("currentSlide",1).css({left:"-213px"});
}
}
window.clearTimeout(timer);
timer = window.setTimeout(slider, 5000);
);
}
function prevSlide(){
var $Slides = $(".contenu");
$Slides.animate(
{left:"+=213px"},
1000,
function(){
$Slides.data("currentSlide", $Slides.data("currentSlide")-1);
if($Slides.data("currentSlide") == 0) {
$Slides.data("currentSlide",$Slides.data("nbSlides")).css({left:-(213*$Slides.data("currentSlide"))});
}
}
window.clearTimeout(timer);
timer = window.setTimeout(slider, 5000);
);
}
Here the loading :
$(function(){
slider();
$('#slider').addClass('slider');
var $Slides = $('.contenu');
var _step = $Slides.find(".slide:first").width();
$Slides.data("currentSlide",1).data("nbSlides",$Slides.find('.slide').size());
$Slides.find(".slide:last").clone().prependTo(".contenu");
$Slides.find(".slide:first").next().clone().appendTo('.contenu');
$Slides.find(".slide:first").addClass("clone").end().css({left:-_step});
$Slides.width($Slides.find(".slide").size()*_step);
$('.next').bind("click", nextSlide);
$('.prev').bind("click", prevSlide);
});
thx for help. ;)
You are still in the .animate() call, you should move ); up to above window.clearTimeout(timer).
This answer assumes you want to set the timeOut directly after you start the animation, if you want to set the timeOut in the callback of the animation you should do what is in David's answer and move it up to above }.
EDIT:
Based on your comments I made this function for you:
function nextSlide(){
var $Slides = $(".contenu");
$Slides.animate(
{left: "-=213px"},
1000,
function(){
$Slides.data("currentSlide",$Slides.data("currentSlide")+1);
if($Slides.data("currentSlide") > $Slides.data("nbSlides")) {
$Slides.data("currentSlide",1).css({left:"-213px"});
}
window.clearTimeout(timer);
timer = window.setTimeout(slider, 5000);
}
);
}
Function call parameters should be separated by commata , however in your case, you separate them by semicolons ; - the line ends with a semicolon instead of a comma. also the next line. This is not a function body with multiple statements, but a function call (to animate) so you need to use commas.
On the other hand - these are probably not arguments, so you need to move the closing ); part above these lines instead, so that they become separate statements instead of function parameters.
This code snippet:
window.clearTimeout(timer);
timer = window.setTimeout(slider, 5000);
is placed out of context. You need to place it inside a function or in the global scope to make it work, f.ex:
function(){
$Slides.data("currentSlide", $Slides.data("currentSlide")-1);
if($Slides.data("currentSlide") == 0) {
$Slides.data("currentSlide",$Slides.data("nbSlides")).css({left:-(213*$Slides.data("currentSlide"))});
}
window.clearTimeout(timer);
timer = window.setTimeout(slider, 5000);
}

clearTimeout on dynamically updating timer

I've got a timer that I'm updating dynamically.
------------------update --------------------------
when I first posted the question, I didn't think it mattered that the timer was being called from within a backbone view, but I believe as a result of that, I can't use a global variable (or at least a global variable isn't working). I'll be calling multiple timers, so setting only one global variable and deleting it won't work. I need to be able to clear a single timer without clearing the others.
What I start the timer,
function countDown(end_time, divid){
var tdiv = document.getElementById(divid),
to;
this.rewriteCounter = function(){
if (end_time >= MyApp.start_time)
{
tdiv.innerHTML = Math.round(end_time - MyApp.start_time);
}
else {
alert('times up');
}
};
this.rewriteCounter();
to = setInterval(this.rewriteCounter,1000);
}
in my app, I initiate the timer in a backbone view with
MyApp.Views.Timer = Backbone.View.extend({
el: 'div#timer',
initialize: function(){
timer = this.model;
this.render();
},
events: {
"clicked div#add_time": "update_timer"
}
render: function(){
$(this.el).append(HandlebarsTemplates['timer'](timer);
this.start_timer();
},
start_timer: function(){
delete main_timer; // this doesn't work :(
clearTimtout(main_timer); //this doesn't work either :(
var main_timer = setTimeout(new countDown(timed.length, 'main_timer'),timed.length*1000);
},
update_timer: function(){
timed.length=timed.length+30
this.start_timer();
}
});
so what I'm trying to do is to update the timer, kill the old timer, and then restart it with the new values. I have different timers, so just calling the timed.length within the countdown function won't work.
var main_timer = setTimeout(new countDown(timed.length, 'main_timer'),timed_length*1000);
This statement creates a local variable main_timer. Instead you have to create a global variable and use that to clear the time out as shown below
clearTimtout(main_timer);
main_timer = setTimeout(new countDown(timed.length, 'main_timer'),timed_length*1000);
EDIT:
use a function as setTimeout handler as shown below
clearTimeout(main_timer);
main_timer = setTimeout(function(){
new countDown(timed.length, 'main_timer');
},timed_length*1000);
note: hope timed.length and timed_length are correct.
EDIT:
modify countdown like given below.
function countDown(end_time, divid){
var tdiv = document.getElementById(divid),
to;
this.rewriteCounter = function(){
if (end_time >= MyApp.start_time)
{
tdiv.innerHTML = Math.round(end_time - MyApp.start_time);
}
else {
alert('times up');
}
};
this.clearRewriteCounter = function(){
clearInterval(to);
}
this.rewriteCounter();
to = setInterval(this.rewriteCounter,1000);
return this;
}
and in MyApp.Views.Timer
MyApp.Views.Timer = Backbone.View.extend({
el: 'div#timer',
initialize: function(){
timer = this.model;
this.render();
},
events: {
"clicked div#add_time": "update_timer"
}
render: function(){
$(this.el).append(HandlebarsTemplates['timer'](timer);
this.start_timer();
},
start_timer: function(){
clearTimeout(this.main_timer);
this.main_timer = setTimeout(function(){
if(this.countDownInstance){
this.countDownInstance.clearRewriteCounter();
}
this.countDownInstance = new countDown(timed.length, 'main_timer');
},timed_length*1000);
},
update_timer: function(){
timed.length=timed.length+30
this.start_timer();
}
});

jquery/javascript blur/focus & settimeout

When mouse is over a product number (focus) then show some product information.
When user is not longer over a product number (blur), then wait 3 seconds, then hide details.
$('.productNumber').live('blur', function() {
setTimeout(function(){
var divToPutData = $(this);
divToPutData.hide();
}, 3000);
});
Now user says that if user moves mouse back within those 5 seconds to stop the count down, until a blur event fires again. No sure how to do this with setTimeout.
Use clearTimeout()
var myTimeout = null;
$('.productNumber').live('mouseover', function() {
//If timeout is still active, clear
if(myTimeout != null)
clearTimeout(myTimeout);
});
$('.productNumber').live('blur', function() {
//Store the ID returned by setTimeout
myTimout = setTimeout(function(){ divToPutData.hide(); }, 3000);
});
Use the function clearTimeout.
setTimeout returns a numeric id, you can store it in a variable, and then pass it to the clearTimeout function:
var myTimeout = setTimeout ( function(){alert(2);}, 1000);
clearTimeout(myTimeout);
var t;
$('.productNumber').live('mouseover', function() {
clearTimeout(t);
});
$('.productNumber').live('mouseout', function() {
t = setTimeout(function(){
divToPutData.hide();
}, 3000);
});
have the setTimeout assigned to a variable, so you can cancel it on hover again
var hideTimeout;
$('.productNumber').live('blur',function() {
hideTimeout = setTimeout(function() {
divToPutData.hide();
}, 3000);
});
$('.productNumber').live('mouseover',function() {
clearTimeout(hideTimeout);
// Do the show stuff
}
jQuery is not my strongest language, so you may need to modify this slightly, but this is the general approach to this scenario.
Use the jQuery stop() to abort any ongoing animation
Test it here: http://jsfiddle.net/T7kRr/1/
jQuery
$(".productNumber").hover(
function () {
$(this).find(".productDesc:last").stop(true, true).show();
},
function () {
$(this).find(".productDesc:last").delay(3000).fadeOut();
}
);
HTML
<div class="productNumber">1001<span class="productDesc" style="display:none">iPhone</span></div>
<div class="productNumber">2001<span class="productDesc" style="display:none">iPad</span></div>
<div class="productNumber">3333<span class="productDesc" style="display:none">TV</span></div>
<div class="productNumber">9999<span class="productDesc" style="display:none">HiFi</span></div>

Categories

Resources