Почему высота содержимого, загруженного через AJAX infinity scroll, не измеряется правильно после загрузки?
я загружаю сообщения, состоящие из фотографий или видео в основной div моего сайта с бесконечность прокрутки (реализовано через AJAX). Система работает почти так же, как на любом популярном веб-сайте meme.
Проблема: каждый пост имеет раздел тела слева и контейнер социальной кнопки справа. Я хочу, чтобы контейнер социальных кнопок перемещался вдоль тела сообщения по мере прокрутки пользователем и останавливался в нижней части родительского div, чтобы им может понравиться, когда они достигнут нижней части столба. Проблема в том, что некоторые из сообщений, загруженных через мою функцию прокрутки AJAX, похоже, не вычисляют высоту родителей должным образом, и они либо никогда не перемещаются, либо не прыгают прямо в нижнюю часть родительского div, когда верхняя часть окна браузера достигает их. вот наглядная иллюстрация желаемого поведения.
реализация: Я не смог скомпилировать рабочий jsFiddle, который будет имитировать поведение запросов AJAX, загружающих изображения и видео в сочетании с вызовами "прокрутки". Вот мои попытки реализации и отладки:
каждая статья имеет следующую структуру:
<div class="article-container">
<div class="article-body-left"><img src="..."></div>
<div class="social-buttons-right">
<div class="facebook-button">...</div>
</div>
</div>
после завершения каждого запроса AJAX я пытаюсь использовать "прокрутку", чтобы определить каждую из позиций контейнеров социальных кнопок и изменить их как пользователь прокручивает с помощью ajaxComplete ():
$(document).ajaxComplete(function() {
bind_sticky_boxes();
});
function bind_sticky_boxes() {
$(window).on('scroll', function() {
$('.social-buttons-right').not('.following').each( function() {
var element = $(this).addClass('following'),
originalY = element.offset().top,
parent_offset = element.parent().offset().top,
parent_height = element.parent().height(),
element_height = element.height(),
destination = originalY+parent_height-element.height() -10;
$(window).on('scroll', function(event) {
var scrollTop = $(window).scrollTop();
if (scrollTop > originalY - 10){
element.css('position','absolute');
element.css('top',(scrollTop - parent_offset + 10) + 'px');
element.css('right', '0px');
if (scrollTop > (destination -10 ) ) {
element.css('top',parent_height-element_height);
element.css('right', '0px');
element.css('bottom', '0px');
}
} else {
element.css('position','relative');
element.css('top','initial');
element.css('left', 'initial');
element.css('right','initial');
element.css('bottom', 'initial');
}
});
});
});
}
отладка и примечания: в функция прокрутки отлично работает после первого запроса AJAX, но затем несколько прерывается как некоторые из .социальные кнопки-правый не следуйте вдоль тела статьи или не прыгайте прямо в нижнюю часть родительского div во время прокрутки сайта.
когда я осмотрел элементы, которые плохо себя ведут, я обнаружил, что все они имеют ".После", что означает, что функция прокрутки нашла их, но они также получают плохое сочетание свойств css, которые дает bind_sticky_boxes их.
это заставляет меня поверить, что это имеет какое-то отношение к вычислению высоты во время загрузки изображения, поэтому я использовал requestanimationframe (), чтобы немного подождать, а затем setTimeout(function(){..}, 2000), чтобы вызвать привязку прокрутки еще позже. Ни один из них не решил проблему (последний все равно не был решением.) Я также попытался вызвать запросы AJAX немного раньше, но это, казалось, имело еще худший эффект для некоторых причина.
обновление: теперь я убежден, что проблема связана с вычислением родительской высоты. Я поменял свойства css для уникальных классов с теми же атрибутами и заметил, что изменение класса для элементов неправильного поведения происходит почти всегда в начале родительского div, что я считаю сильным признаком того, что его высота не вычисляется должным образом сразу после добавления его к основному div.
в отношении моего свитка бесконечности. Я не включаю весь AJAX, поскольку я не думаю, что это строго связано с проблемой. Но я добавляю контент к основному div следующим образом:
success: function(response){
if ( max_page >= paged){
$('#page').append(response.content);
} else{
has_content = false;
}
loading = false;
}
после загрузки страницы я инициирую прокрутку бесконечности. AJAX-запросы запускаются, когда пользователь достигает элемента с id загрузить больше постов, который находится под основной оболочкой.
$(window).on('load',function(){
$(window).on('scroll', function() {
var element_position = $('#load-more-posts').offset().top + $('#load-more-posts').outerHeight() - window.innerHeight;
var y_scroll_pos = $(window).scrollTop();
if( ( y_scroll_pos >= element_position ) && !loading) {
paged++;
load_more_posts();
}
});
});
1 ответов
проблема в том, что в настоящее время расчет различных свойств высоты/положения привязан к событию прокрутки, которое может сработать до загрузки изображений, добавленных через AJAX, и поэтому будет вычислено неправильно. Чтобы решить эту проблему, мне пришлось привязать его к событию load, чтобы убедиться, что фотографии готовы к использованию.
$('.article-body-left img').one('load', function() {
var element = $(this).parent().parent().find('.social-buttons-right'),
originalY = element.offset().top,
parent_offset = element.parent().offset().top,
parent_height = element.parent().height(),
element_height = element.height(),
destination = parent_offset+parent_height-element.height() -10;
//alert("Element offset: "+originalY+"\nParent offset: "+parent_offset+"\nParent height: "+parent_height+"\nElement height: "+element_height+"\nDestination: "+destination);
$(window).on('scroll', function(event) {
var scrollTop = $(window).scrollTop();
if (scrollTop > originalY - 10){
element.removeClass('above').removeClass('below').addClass('along');
element.css('top',(parseInt(scrollTop - parent_offset + 10)) + 'px');
if (scrollTop > (destination -10 ) ) {
element.removeClass('above').removeClass('along').addClass('below');
element.css('top','');
}
} else {
element.removeClass('below').removeClass('along').addClass('above');
element.css('top','');
}
});
}).each(function() {
if(this.complete) $(this).load();
});
CSS:
.along{
position: absolute;
right : 0px;
}
.below{
position: absolute;
right: 0px;
bottom: 0px;
}
.above{
position: relative;
}