Почему высота содержимого, загруженного через 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;
}