2

次のコードを見てください (さらに、jquery.jsjquery.viewport.js、およびjquery.scrollTo.jsが必要です)。

このスクリプトに期待する動作は、ページをスクロールするたびに、そのテーブルの一番上に表示されている行 (要素) のすぐ下に赤い行 ( <tr>class を持つ要素) が挿入されることです。次に、これらの赤い行の最初の行がビューポートの上部に「正確に」表示されるように、ページをスクロールする必要があります。実際に何が起こるかというと、ページの最後に到達するまで繰り返し呼び出されます。二度と呼び出されないようにしようと思ったが、どうやらこれはうまくいかないようだ。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>
4

1 に答える 1

0

あなたが問題だと思うのは、次のものをscrollTo使用することですanimate

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

タイマーanimateを使用してアニメーションを実行します。結果は、スクロールが完了する前に戻り、まだスクロール.scrollToしている間にスクロール ハンドラを再バインドします。scrollToしたがって、予期しないイベントが発生します。

簡単な解決策は、フラグを使用してスクロール中であることを伝え、完了時にコールバックを使用しmakeVisibleWhatMustてフラグをクリアすることです。たとえば、次のようになります。scrollToscrollTo

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/

于 2011-06-01T20:21:07.813 に答える