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()
{...};
Related
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/
I'd been using Swiffy to output .fla files pretty easily, but then I was tipped off that the display would alternate "flashing" white over half the project if viewed in Landscape Mode on a iPad. Very strange behavior, which I couldn't replicate on any other device.
So, I've moved on to trying to use CreateJS to fix the issue. I only know enough JS at this time to get by editing code developed by others, so I've been very ineffective so far.
I've gotten this far:
/* js
this.stop();
var t=setTimeout(function(){(this.play())}, 1000);
*/
or
/* js
this.stop();
setTimeout(this.play(), 1000);
*/
I've not been able to get the animation to mind the timeout, and I've tried MANY different variants to try and make some magic happen. All it does is immediately loads the next frame, it doesn't pause at all. Where am I going wrong here?
Here is the original Actionscript:
stop();
var shortTimer:Timer=new Timer(1000);
shortTimer.addEventListener(TimerEvent.TIMER, timerN1);
shortTimer.start();
function timerN1(e:TimerEvent):void{
play();
shortTimer.reset();
}
Any help would be very appreciated, as I've gotten no where on my own trying to fix this is in my off time for several weeks, and my client is becoming increasingly angry. More of a designer, still very uneducated as far as programming is concerned. Again, even a suggestion would be super helpful at this point. Can't seem to crack it.
This syntax is more correct:
/* js
this.stop();
var t=setTimeout(function(){(this.play())}, 1000);
*/
However, you may find that "this" is Window, not the MovieClip that calls it. You can get around this by using a local reference (in this case, its "_this").
/* js
this.stop();
var _this = this;
var t=setTimeout(function(){
console.log(this, _this);
_this.play();
}, 1000);
*/
You can test this by looking at your console, and seeing what the difference between "this" and "_this" is.
Cheers.
Could you possibly post more of the code you are working with? Have you tried using the onAnimationEnd function:
var _this = this;
_this.onAnimationEnd = function() {
_this.stop();
setTimeout(function(){
_this.play();
}, 1000)
}
Try this to keep your scope alive inside your setTimeout function :
sprite.on('animationend', function(event) {
event.target.stop();
setTimeout(animationend.bind(event.target), 1000);
});
function animationend() {
this.gotoAndPlay('run');
}
With the use of .bind() you can pass an object as the scope in the called function. More information here.
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?
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.
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.