#jquery #jquery-plugins #scroll #unbind
#jquery #jquery-плагины #прокрутка #отменить привязку
Вопрос:
Взгляните на следующий код (дополнительно вам понадобится jquery.js, jquery.viewport.js и jquery.scrollTo.js ).
Поведение, которое я ожидал бы от этого скрипта, заключается в том, что всякий раз, когда я прокручиваю страницу, красные строки ( <tr>
элементы с классом alwaysVisible
) должны вставляться прямо под самой верхней видимой строкой ( <tr>
элементом) этой таблицы. Затем страницу следует прокрутить так, чтобы первая из этих красных строк отображалась «точно» в верхней части окна просмотра. Что на самом деле происходит, так это то, что makeVisibleWhatMust();
вызывается неоднократно, пока я не дойду до конца страницы. Я думал, что $(window).unbind('scroll');
это удержит makeVisibleWhatMust();
от повторного вызова, но, по-видимому, это не работает.
Есть идеи, почему?
Вот JavaScript, который я написал:
function makeVisibleWhatMust()
{
$('#testContainer').text( $('#testContainer').text() 'calledn');
$('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>
Ответ №1:
Я думаю, ваша проблема в том, что scrollTo
использует animate
:
// From the plugin's source
function animate( callback ){
$elem.animate( attr, duration, settings.easing, callback amp;amp; function(){
callback.call(this, target, settings);
});
};
И animate
использует таймер для выполнения анимации. В результате это .scrollTo
вернется до завершения прокрутки, и вы повторно свяжете свой обработчик прокрутки, пока scrollTo
все еще выполняется прокрутка. Отсюда и события, когда вы их не ожидаете.
Простым решением было бы использовать флаг, чтобы сообщить, makeVisibleWhatMust
что scrollTo
выполняется прокрутка, и использовать scrollTo
обратный вызов, чтобы снять флаг, когда это будет сделано, что-то вроде этого:
function makeVisibleWhatMust() {
// Ignore the event if we're doing the scrolling.
if(makeVisibleWhatMust.isScrolling)
return;
$('#testContainer').text( $('#testContainer').text() 'calledn');
$('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 /
Комментарии:
1. @mu слишком короткое: я думаю, вы правы насчет проблемы, но ваше решение не работает. Я получаю точно такой же результат, как и раньше. Теперь я действительно не понимаю..
2. @Shawn: У меня была опечатка в JavaScript (слишком много закрывающих круглых скобок). Я исправил это и добавил ссылку jsfiddle.
3. @mu слишком короткое: так что это работает! Это очень любопытно, потому что точно такой же код не работает, когда я тестирую его «локально», но работает в JSFiddle. Интересно, чем может быть объяснена эта разница в поведении между моей «локальной настройкой» (сохранение кода в текстовых файлах и открытие html-файла в Firefox) и JSFiddle (также запущенным в Firefox).. Я думаю, эта проблема заслуживает отдельного вопроса. В любом случае, спасибо за (рабочее) решение!
4. @Shawn: Работает ли полностью развернутая версия скрипки? Попробуйте это: fiddle.jshell.net/ambiguous/ZEx6M/1/show/light
5. @mu слишком короткий: Да, это работает отлично (или, по крайней мере, это работает так, как ожидалось! Я действительно думаю, что конечный результат немного изменчивый, но это уже другая история : p)