2011-06-01 49 views
2

看看下面的代码(另外,你需要jquery.js,jquery.viewport.jsjquery.scrollTo.js)。什么可以使jQuery的解除绑定功能不能按预期工作?

我希望从这个脚本的行为是每当我滚动页面,红色行(<tr>元素与alwaysVisible类)应该刚好插入该表的最顶部可见行(<tr>元)下方。然后,应该滚动页面,以便这些红色行中的第一行在视口顶部“正好”出现。实际上发生的是makeVisibleWhatMust();被重复调用,直到我到达页面的末尾。我认为$(window).unbind('scroll');会保持makeVisibleWhatMust();不再被调用,但显然这是行不通的。

任何想法为什么?

这里是JavaScript我写道:

function makeVisibleWhatMust() 
{ 
    $('#testContainer').text($('#testContainer').text() + 'called\n'); 
    $('table.scrollTable').each 
    (
    function() 
    { 
     var table = this; 
     $($('tr.alwaysVisible', table).get().reverse()).each 
     (
    function() 
    { 
     $(this).insertAfter($('tr:in-viewport:not(.alwaysVisible)', table)[0]); 
    } 
    ); 
     $(window).unbind('scroll'); 
     $(window).scrollTo($('tr.alwaysVisible')[0]); 
     $(window).bind('scroll', makeVisibleWhatMust); 
    } 
); 
} 

$(document).ready 
(
    function() 
    { 
    $(window).bind('scroll', makeVisibleWhatMust); 
    } 
); 

这里是一个HTML页面来测试它:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 
    <head> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    <title>Scroll Tables Test Page</title> 

    <script type="text/javascript" src="jQuery.js"></script> 
    <script type="text/javascript" src="jquery.viewport.js"></script> 
    <script type="text/javascript" src="jquery.scrollTo.js"></script> 
    <script type="text/javascript" src="scrollTable.js"></script> 

    <style type="text/css"> 
     table th, table td 
     { 
    border: 1px solid #000; 
    padding: .3em; 
     } 
     .alwaysVisible 
     { 
    background: #F66; 
     } 
    </style> 
    </head> 
    <body> 
    <table class="scrollTable"> 
     <thead> 
    <tr class="alwaysVisible"> 
     <th>Row name</th> 
     <th>Content</th> 
    </tr> 
    <tr class="alwaysVisible"> 
     <th>Row 2</th> 
     <th>Row 2</th> 
    </tr> 
     </thead> 
     <tbody> 
    <script type="text/javascript"> 
     for(var i = 0; i < 50; ++i) 
     { 
     document.writeln("<tr><td>Row " + i + "</td><td>Content</td></tr>"); 
     } 
    </script> 
     </tbody> 
     <tfoot> 
    <tr> 
     <td>Footer</td> 
     <td>Footer 2</td> 
    </tr> 
     </tfoot> 
    </table> 
    <div id="testContainer">TEST CONTAINER</div> 
    </body> 
</html> 

回答

0

我觉得你的问题是,scrollTo使用animate

// From the plugin's source 
function animate(callback){ 
    $elem.animate(attr, duration, settings.easing, callback && function(){ 
     callback.call(this, target, settings); 
    }); 
}; 

and animate使用定时器执行 动画。结果是.scrollTo将在滚动完成之前返回,并且您将重新绑定滚动处理程序,而scrollTo仍在滚动。因此,当你不期待他们的事件。

一个简单的方法是使用一个标志,告诉makeVisibleWhatMustscrollTo的滚动和使用scrollTo回调清除标志,当它完成,像这样:

function makeVisibleWhatMust() { 
    // Ignore the event if we're doing the scrolling. 
    if(makeVisibleWhatMust.isScrolling) 
    return; 
    $('#testContainer').text($('#testContainer').text() + 'called\n'); 
    $('table.scrollTable').each(function() { 
     var table = this; 
     $($('tr.alwaysVisible', table).get().reverse()).each(function() { 
     $(this).insertAfter($('tr:in-viewport:not(.alwaysVisible)', table)[0]); 
     }); 
     makeVisibleWhatMust.isScrolling = true; 
     $(window).scrollTo($('tr.alwaysVisible')[0], { 
     onAfter: function() { makeVisibleWhatMust.isScrolling = false; } 
     }); 
    } 
); 
} 
makeVisibleWhatMust.isScrolling = false; 

而且这里有一个现场版这似乎工作:http://jsfiddle.net/ambiguous/ZEx6M/1/

+0

@mu太短:我认为你是对的问题,但你的解决方案不起作用。我得到和以前完全一样的结果。现在我真的不明白。 – Shawn 2011-06-01 20:40:46

+0

@Shawn:我在JavaScript中输入了一个错字(太多的右括号)。我修正了这个问题并添加了一个jsfiddle链接。 – 2011-06-01 20:55:28

+0

@mu太短:所以它工作!这非常令人好奇,因为当我在“本地”测试时,完全相同的代码不起作用,但在JSFiddle中起作用。我想知道我的“本地设置”(在文本文件中保存代码并在Firefox中打开html文件)和JSFiddle(也在Firefox中运行)之间的这种行为差异可以解释为什么。我想这个问题值得自己去考虑。无论如何,感谢(工作)解决方案! – Shawn 2011-06-01 21:06:32

相关问题