逆無限スクロールをしようとしています。最新の 10 件のコメントを受け取るコメント リストがあり、ユーザーが上にスクロールして次の 10 件を取得できるようにしたい - 「前の取得」リンクで最新のコメントを表示する FB と同様ですが、リンクではなくスクロールイベント。
私はhttp://jsfiddle.net/vojtajina/U7Bz9/から始めて、それを逆の無限スクロールに変更しようとしましたが、すぐに次のような結果になりました:
function Main($scope, $timeout) {
$scope.items = [];
var counter = 0;
$scope.loadMore = function() {
// simulate an ajax request
$timeout( function() {
for (var i = 0; i < 5; i++) {
$scope.items.unshift({id: counter});
counter += 10;
}}, 1000);
};
$scope.loadMore();
}
angular.module('scroll', []).directive('whenScrolled', ['$timeout', function($timeout) {
return function(scope, elm, attr) {
var raw = elm[0];
$timeout(function() {
raw.scrollTop = raw.scrollHeight;
}, 1100);
elm.bind('scroll', function() {
// note: if test for < 100 get into infinite loop due to
// the delayed render
if (raw.scrollTop === 0) {
var sh = raw.scrollHeight
scope.$apply(attr.whenScrolled);
// the items are not loaded and rendered yet, so
// this math doesn't work
raw.scrollTop = raw.scrollHeight - sh;
}
});
};
}]);
http://jsfiddle.net/digger69/FwWqb/2/
問題は、次の 10 個のアイテムが取得されると、それらがリストの一番上に追加され、リスト全体が再レンダリングされ、リストの最初にあったアイテムが完全にスクロールされて表示されなくなることです。フィドル項目では「40」が一番上にあり、スクロールして(少し下に)スクロールしてから上にスクロールすると、項目「90」が一番上になります。レンダリング後にスクロール領域の上部に「40」を保持するための適切な戦略を探しています。
注:フィドルでは、スクロールイベントの一番上のliを保存し、タイムアウトを追加してajax呼び出しをシミュレートするまでscrollIntoView()を呼び出すことで、機能させることができました。タイムアウトを使用すると、リクエストが戻ってきて新しい要素がレンダリングされる前に、上部の li がスクロールして表示されます:/
var top = elm.find("li")[0];
scope.$apply(attr.whenScrolled);
top.scrollIntoView();