在没有焦点的选项卡中执行时,setTimeout会发生奇怪的事情

时间:2011-08-19 15:44:25

标签: javascript jquery

  

可能重复:
  Run setTimeout only when tab is active

我观察到这种情况发生在Chrome和Firefox中,并且表现出一些不同。看起来当一个标签不在焦点上时,setTimeout仍然会执行,但它应该对执行操作的给定dom元素没有它应该采用的一些属性帐户。

例如,check out this page。面板5和6上有两个幻灯片。为这个幻灯片提供动力的功能会影响元素的可见性和位置(使它们在没有摆动的情况下通过正确的反弹缓和到中心缩小,我将步进功能一起攻击) 。如果您正在查看它们,它们可以正常工作,但是如果您将其切换到另一个地方,然后再切换回幻灯片,您会看到setTimeout已经提前了很多次,但是图像都被打包了,应该弹出的古代没有(好像它们在标签失焦时没有被隐藏或可见),或者它们将奇迹般地转移到舞台的最右侧(就好像它们的坐标不存在一样)或者在浏览器窗口未对焦时出错。

阻止这种情况发生的最佳方法是什么?除非/直到浏览器窗口具有焦点,否则不会触发setTimeout?

一种解决方案是使用css3变换而不是高度和宽度,这至少可以让我不必在屏幕外处理元素的坐标,但它不会改变这样的事实: setTimeout变得一团糟,很奇怪。

以下是实际功能:

// dom element goes out
function popOut(cssFilter, dur){
    var aPop = this;
    aPop.duration = dur;
    $(cssFilter+':visible').stop(false,true).each(function(){
        var my = this;
        my.X = $(this).position().left;
        my.Y = $(this).position().top;
        $(this).animate({'height': 0, 'width': 0}, {'duration': aPop.duration, 'easing': 'easeOutElastic', step: function(now, fx){
            if(fx.prop == 'height')     $(this).css('top', ((fx.start - now)/2) + my.Y);
            else if(fx.prop == 'width') $(this).css('left', ((fx.start - now)/2) + my.X);
        }, queue: true, complete: function(){
            $(this).css({'top': my.Y,'left': my.X, 'display': 'none'});
        } });        
    });
}

// dom element comes in
function popIn(cssFilter, dur){
    var aPop = this;
    aPop.duration = dur;
    $(cssFilter+':hidden').stop(false,true).each(function(){
        var my = this;
        my.H = this.height,
        my.W = this.width;
        $(this).css({ 'height': 0, 'width': 0, 'display': 'block'});
        my.X = $(this).position().left,
        my.Y = $(this).position().top;
        $(this).css({ 'left' :(my.X + my.W/2), 'top' : (my.Y + my.H/2)}).animate({'height': my.H, 'width': my.W}, { 'duration': aPop.duration, 'easing': 'easeOutElastic', step: function(now, fx){
            if(fx.prop == 'height')     $(this).css('top', ((fx.end - now)/2) + my.Y);
            else if(fx.prop == 'width') $(this).css('left', ((fx.end - now)/2) + my.X);
        }, queue: true, complete: function(){ 
            $(this).css({'top': my.Y, 'left': my.X, 'display': 'block'});
        } });        
    })
}

// dom element slideshow
function popSlideshower(classToCycle, pauseButtonPanelId){
    var thisPop = this;
    // the items that have the classToCycle class need to also have classes ploink1, ploink2, ploink3... ploinkn - to specify order of displaywhatchamacallit
    $('.'+classToCycle+":not(.ploink1)").hide();

    this.totCount = $('.'+classToCycle+':not(.also)').length; // the also class allows there to be multiple images with the same ploink number; the also ploinks will not go toward the total count
    this.currentIndex = 1;
    this.classOfCycler = classToCycle;
    this.currentlyPlaying = true;

    // prepend button to the given narrative block id
    $('#c_'+pauseButtonPanelId+' .narrative').prepend('<p style="text-align: center;"><a href="#" id="'+classToCycle+'-pauseButt" class="inlineButton"><span>Pause Slideshow</span></a></p>');

    $('#'+classToCycle+'-pauseButt').click(function(aClick){
        aClick.preventDefault();
        $(this).blur(); // removes the weird dotted outline in FF

        if(thisPop.currentlyPlaying) {
            $(this).html('<span>Continue</span>');
            thisPop.currentlyPlaying = false;
        }
        else {
            $(this).html('<span>Pause</span>');    
            thisPop.currentlyPlaying = true;
        }
    });

    this.popPloink = function(){
        if(this.currentlyPlaying){ // this method allows multiple slideshows to stay synchronized; the timeout never stops firing, even though the slideshow stops advancing
            var nextIndex = this.currentIndex == this.totCount ? 1 : this.currentIndex + 1;

            popOut("."+this.classOfCycler+".ploink"+this.currentIndex, 700);
            popIn("."+this.classOfCycler+".ploink"+nextIndex, 700);

            this.currentIndex = nextIndex;
        }
        setTimeout(function() { thisPop.popPloink(); }, 4000);
    }
    setTimeout(function() { thisPop.popPloink(); }, 4000);
}

0 个答案:

没有答案