jQuery slider - setTimeout crossbrowser glitch? - javascript

Ok, I tried to create another slider of preloaded images (whatever you wanna call it) with only two directional buttons. Got the animations the way I wanted them and the control idea was from a tutorial.
(Tutorial: How to Make Auto-Advancing Slideshows)
So, I adapted the autoadvance solution to my needs and got everything working OK. But, when I tried to run it in FF (8.0) I got a little problem. After a button click it does everything as it should except the part where the animation continues after the preset 3 seconds time, while IE (8.0) does not have problems (didn't tested in other browsers).
What am I doing wrong?
Here is the necessary code:
Html part:
<div id=imgholder1>
<div id="imgholder2"></div>
</div>
<div id="bwd" class="button"><</div>
<div id="fwd" class="button">></div>
jQuery/JavaScript:
var traker=0;
$(document).ready(function(){
var numOfImages=4;
var timeOut = null;
(function autoAdvance(){
$('#fwd').trigger('click',[true]);
timeOut = setTimeout(autoAdvance,3000);
})();
function preload(imgIndex,numImages){
$("#imgholder1").css('background-image','url("'+imgIndex+'.jpg")');
$("#imgholder2").hide(0);
imgIndex < numImages ? imgIndex++ : imgIndex=1
$("#imgholder2").css('background-image','url("'+imgIndex+'.jpg")');
traker=imgIndex;
}
preload(1,numOfImages);
function animate(imgIndex,numImages){
$("#imgholder2").fadeIn("slow",function(){
preload(imgIndex,numImages);
});
}
$("#fwd").bind("click",function(e,simulated){
animate(traker,numOfImages);
if(!simulated){
clearTimeout(timeOut);
timeOut = setTimeout(autoAdvance,3000);
}
});
$("#bwd").bind("click",function(){
var temp=traker-2;
if(temp == 0){temp=numOfImages;}
if(temp == -1){temp=numOfImages-1;}
$("#imgholder2").css('background-image','url("'+temp+'.jpg")');
animate(temp,numOfImages);
clearTimeout(timeOut);
timeOut = setTimeout(autoAdvance,3000);
});
});

At first glance, it looks like your timeout variable is in the wrong scope - declare it outside of everything so that it is shared between functions:
var traker=0;
var timeOut;
Personally, I also avoid using reserved method keywords that are close like that, so use:
var tmr;
Also, you should use window.setTimeout rather than just setTimeout

The Fix!
This:
(function autoAdvance(){
$('#fwd').trigger('click',[true]);
timeOut = setTimeout(autoAdvance,3000);
})();
should look like this:
function autoAdvance(){
$('#fwd').trigger('click',[true]);
timeOut = setTimeout(autoAdvance,3000);
}
autoAdvance();
FF didn't recognize self calling function autoAdvance otherwise.

Related

Javascript - how to create a timed redirect button and a different button to cancel it

I have the following code. Pressing the first button sends the user to a different URL after 10 seconds.
However, I am also trying to get the second button to cancel that redirect if pressed before those 10 seconds. This doesn't seem to work and the URL redirect still occurs.
I have looked online for various solutions and I am unable to get anything to work. I have also tried swapping out setTimeout/clearTimeout with setInterval/clearInterval and other variations of the code.
I would be willing to have the code changed completely or use Jquery instead etc. I have been trying to do this for past couple of days so any help would be greatly appreciated.
If the redirect countdown could also start again from 10 seconds if the first button is pressed again after pressing the second button, that would be also great.
Javascript
<script>
var redirectTime = "10000";
var redirectURL = "https://realmbound.com";
function timedRedirect() {
var timeoutHandle = window.setTimeout("location.href = redirectURL;",redirectTime);
}
function stopTimer() {
clearTimeout(timeoutHandle);
}
</script>
HTML
<button onclick="JavaScript:timedRedirect()">Click me for a timed redirect.</button>
<button onclick="JavaScript:stopTimer()">Stop Timer.</button>
Your timeoutHandle is in scope function, you must delcare it to global scope it in your order to access it on stopTimer().
let redirectTime = "1000";
let redirectURL = "https://realmbound.com";
let timeoutHandle;
function timedRedirect() {
timeoutHandle = window.setTimeout("location.href = redirectURL;",redirectTime);
}
function stopTimer() {
clearTimeout(timeoutHandle);
}
<button onclick="JavaScript:timedRedirect()">Click me for a timed redirect.</button>
<button onclick="JavaScript:stopTimer()">Stop Timer.</button>
The rest of the code is fine.
Your solution is correct, only thing that you missed is to scope timeoutHandle variable as global scope so that stopTimer function can access it.
here is the working fixed version of your solution:
https://jsfiddle.net/8uw7f19k/1/
Hope it helps ;-)

Js Animation using setInterval getting slow over time

I have a web site which displays a portfolio using this scrollbar http://manos.malihu.gr/jquery-custom-content-scroller/ .
I want to have an automatic scroll when the page is
fully loaded. When a user pass over the portfolio it stops the scroll and whe, he leaves it starts moving again.
It currently works well but sometimes it's getting slow or sluggish randomly.
Is there something wrong with my js function?
Here's the page having problems : http://www.lecarreau.net/new/spip.php?rubrique5 (I need the change the hosting provider, I know the site is slow).
This is the function:
(function($){
var timerId = 0;
$(window).load(function(){
$("#carousel").show().mCustomScrollbar( {
mouseWheel:false,
mouseWheelPixels:50,
horizontalScroll:true,
setHeight:370,
scrollButtons:{
enable: true,
scrollSpeed:50
},
advanced:{
updateOnContentResize:true
}
});
timerId = setInterval(function(){myTimer()},50);
$('#carousel').mouseenter(function () {
clearInterval(timerId);
});
$('#carousel').mouseleave(function () {
timerId = setInterval(function(){myTimer()},50);
});
});
})(jQuery);
function myTimer()
{
var width = $(".mCSB_container").width();
var left = $(".mCSB_container").position().left;
if (width-left>0) {
var scrollTo = -left+4;
$("#carousel").mCustomScrollbar("scrollTo", scrollTo);
}
}
Is there something obvious I'm missing?
Timing in the browser is never guaranteed. Since all functionality contents for time on a single event loop, continuous repeated tasks sometimes get a little janky.
One thing you could do that might decrease the jank is to cache the jQuery objects you're creating every 50ms:
var mCSBContainerEl = $(".mCSB_container");
var carouselEl = $("#carousel")
function myTimer()
{
var width = mCSBContainerEl.width();
var left = mCSBContainerEl.position().left;
if (width-left>0) {
var scrollTo = -left+4;
carouselEl.mCustomScrollbar("scrollTo", scrollTo);
}
}
Selecting these to elements only needs to happen once. From there they can just reference a variable instead of having to find the element on the page and wrap it in jQuery again and again.
Caching the variable in this case depends on them being in the DOM when the code runs, which isn't guaranteed here. You may have to move the variable assignment and function declaration into the function passed to load.
Also, as John Smith suggested, consider checking out requestAnimationFrame. Here's a shim I use by Paul Irish: http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/

Javascript/jQuery can't seem to get ClearInterval to work

I am reading a jQuery book and trying to do an example. In the example lightning flashes on the screen, and that part works fine. The problem is that when you switch tabs, and then switch back, the lightning starts flashing in rapid succession. The problem is supposed to be fixed using the window.onblur and window.onfocus events, but it's not working. Can anybody see what I am doing wrong?
There are three hidden lightning pictures with different id's, and three different functions that make each one flash. goLightning() sets the interval for each function to go, and stopLightning() should clear that interval. That part is what seems not to be working for all I know. Here is the code:
$(document).ready(function(){
goLightning();
window.onblur = stopLightning;
window.onfocus = goLightning;
var int1; var int2; var int3;
// this function sets the lightning interval
function goLightning() {
int1 = setInterval(function() { lightning_one(); },4000);
int2 = setInterval(function() { lightning_two(); },5000);
int3 = setInterval(function() { lightning_three(); },7000);
}
// this function clears the lightning when the window isn't focused
function stopLightning() {
window.clearInterval(int1);
window.clearInterval(int2);
window.clearInterval(int3);
}
// these three functions make the lightning flash and seem to be working fine
function lightning_one() {
$("#container #lightning1").fadeIn(250).fadeOut(250);
}
function lightning_two() {
$("#container #lightning2").fadeIn(250).fadeOut(250);
}
function lightning_three() {
$("#container #lightning3").fadeIn(250).fadeOut(250);
}
});
I have no idea why this isn't working. It seems like stopLightning() isn't clearing the interval, or window.onblur isn't working. Anyway, any feedback would be helpful. Thanks!
Add stopLightning() to the beginning to goLightning(), before setting the new intervals.
Re-arrange the following lines:
goLightning();
window.onblur = stopLightning;
window.onfocus = goLightning;
var int1; var int2; var int3;
in to this instead:
var int1, int2, int3, w = window;
w.onblur = stopLightning;
w.onfocus = goLightning;
goLightning();
Next, use the variable w instead of window in the stopLightning() function to ensure you use a reference to the proper window. Also, as #Kolink mentioned, it wouldn't hurt to put a call to stopLightning() at the beginning of your goLightning() function to ensure you don't have multiple instances running in the event the focus event gets fired more than once.
EDIT I moved the call to goLightning() after having set up the events - untested but I think it would be better that way?

setTimeout memory leak in Titanium Appcelerator

I've done a little bit of research and have found that using setTimeout() causes a bad memory leak, as seen on this post. I'm hoping to find a remedy or an alternative.
What I have is a small view appearing on the screen when any of my many buttons is touched. At the same time I set a timeout to fadeout the small view after 3 seconds. When the button is first pressed, I also clear the timeout so that I don't continue setting multiple ones. Though now while analyzing my code I see that I'm setting an interval and clearing a timeout. Not sure if this is part of my issue. It looks like this:
var Modal = Titanium.UI.createView({
width:151,
height:83,
owner: null,
myView: null,
});
var modalTimer;
var addModal = function(){
clearInterval(modalTimer);
theView.add(Modal);
modalTimer = setTimeout( function() {
removeModal();
changeTurn();
},3000);
}
playerButton.addEventListener('click',function(){
addModal();
});
Thanks!!!
I may have solved this issue with the following:
var Modal = Titanium.UI.createView({
width:151,
height:83,
owner: null,
myView: null,
});
var modalTimer;
var addModal = function(){
clearTimeout(modalTimer);
theView.add(Modal);
modalTimer = setTimeout(removeModal(),3000);
}
playerButton.addEventListener('click',function(){
addModal();
});
I put my changeTurn() function in my removeModal() function, and removed the anonymous function from setTimeout. I also corrected the clearTimeout confusion. I still have to see how well this holds up over extended gameplay, but from first impressions this has fixed my issues. I hope this helps anyone with similar issues.
I don't know if this helps but I have noticed that my app crashes if i use:
modalTimer = setTimeout(removeModal(),3000);
but doesn't if i use
modalTimer = setTimeout(removeModal, 3000);
where removeModal is defined as
var removeModal = function()
{...};

setTimeout not working on safari mobile

I have a function that shows a menu when clicking on it, and I want it to disappear after 5 seconds. This is my javascript - it works properly on desktop browser but it doesn't disappear on the mobile ones.
$(function() {
$('#prod_btn').click(function() {
$(this).addClass('selected').next('ul').css('display', 'block');
setTimeout(hideMenu, 5000);
});
});
function hideMenu() {
$('#prod_btn').removeClass('selected').next('ul').css('display', 'none');
}
Where is the problem?
Thanks
I've just had the same problem. My code is running great in any browser on my Mac, but on iOs devices it doesn't work.
I use ".bind(this)" on my timeout function and that is what is causing the problem for me.
When I extend the function object with ".bind" in my script it works like a charm.
My code is something like this:
searchTimeout = setTimeout(function() {
...
}.bind(this),250);
For this to work on iOs devices I (like mentioned above) just added this:
Function.prototype.bind = function(parent) {
var f = this;
var args = [];
for (var a = 1; a < arguments.length; a++) {
args[args.length] = arguments[a];
}
var temp = function() {
return f.apply(parent, args);
}
return(temp);
}
I don't see any .bind on your setTimeout, but for others with the same problem this may be the issue. That's why I'm posting :-)
I moved your example to a jsbin, and it's working on my iphone 4.
Please test it out going here from your devices: http://jsbin.com/asihac/5
You can see the code here http://jsbin.com/asihac/5/edit
The example is using jQuery - latest and I only added the required css class.
this doesn't apply to your code, but a common problem with long-running scripts failing on iOS devices is that MobileSafari kills a javascript thread after 10 seconds have elapsed. you should be able to use setTimeout and/or setInterval to work around this, or you can avoid it by making a shortcut to it and thereby running it as an app. see https://discussions.apple.com/thread/2298038, particularly the comments by Dane Harrigan.
Keep in mind also that any setTimeout function is actually likely fire while DOM elements are rendering if the delay is set to a value too short. While that might seem obvious, it can be easily confused with no method firing whatsoever. A good way to test is to have an alert prompt run.
window.onLoad(alert("hey!"));
Then check to see if your function fires after.

Categories