2015-12-22 16 views
8

Sto caricando post composti di immagini o video nel div principale del mio sito web con scroll infinito (implementato tramite AJAX). Il sistema funziona praticamente come su qualsiasi sito web di meme popolare.Perché l'altezza del contenuto caricata tramite lo scorrimento AJAX infinito non viene misurata correttamente dopo il caricamento?

Il problema: Ogni post ha una sezione del corpo a sinistra e un contenitore di pulsante sociale a destra. Voglio che il contenitore dei pulsanti sociali si sposti lungo il corpo del post mentre l'utente scorre, e si ferma nella parte inferiore del div genitore in modo che possa piacere quando raggiunge il fondo del post. Il problema è che alcuni dei post caricati tramite la mia funzione di scorrimento AJAX non sembrano calcolare correttamente l'altezza dei genitori e non si spostano mai o salgono direttamente alla parte inferiore del div genitore quando la parte superiore della finestra del browser li raggiunge . Here is a visual illustration del comportamento desiderato.

Implementazione: Non ero in grado di compilare un jsFiddle funzionante che simulasse il comportamento delle richieste AJAX caricando immagini e video combinati con le chiamate su "scorrimento". Qui è la mia implementazione e debug tentativi:

Ogni articolo ha la seguente struttura:

<div class="article-container"> 
    <div class="article-body-left"><img src="..."></div> 
    <div class="social-buttons-right"> 
     <div class="facebook-button">...</div> 
    </div> 
</div> 

Dopo ogni richiesta AJAX è completo provo ad usare il 'scroll' per determinare ciascuno dei sociali contenitori pulsante posizioni e modificarli come l'utente scorre utilizzando 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'); 
       } 
      }); 
    }); 
    }); 
} 

Debug e note: la funzione di scorrimento funziona bene dopo la prima richiesta AJAX, ma un po 'si rompe dopo alcuni di .social-buttons-right non seguire il corpo dell'articolo o saltare direttamente alla parte inferiore del div padre durante lo scorrimento del sito.

Quando ho controllato gli elementi che si comportano in modo anomalo, ho scoperto che tutti hanno il ".following", il che significa che la funzione di scorrimento li ha trovati, ma ottengono anche un cattivo mix delle proprietà css fornite da bind_sticky_boxes.

Questo mi porta a credere che abbia qualcosa a che fare con il calcolo dell'altezza durante il caricamento dell'immagine, quindi ho usato requestanimationframe() per aspettare un po 'e poi setTimeout (function() {..}, 2000) per attivare il scorrere legare anche più tardi. Nessuno di questi ha veramente risolto il problema (quest'ultima non era comunque una soluzione). Ho anche provato a innescare le richieste AJAX un po 'prima, ma per qualche motivo sembrava avere un effetto ancora peggiore.

Aggiornamento: Ora sono convinto che il problema sia correlato al calcolo dell'altezza genitore. Ho scambiato le proprietà CSS per classi univoche con gli stessi attributi e ho notato che il cambio di classe per elementi anomali si verifica quasi sempre all'inizio del div genitore, che ritengo essere una forte indicazione che l'altezza non viene calcolata correttamente subito dopo aggiungendolo al div principale

Riguardo al mio scorrimento infinito. Non includo l'intera AJAX perché non penso sia strettamente correlata al problema. Ma aggiungo il contenuto al div principale in questo modo:

success: function(response){ 
      if (max_page >= paged){ 
       $('#page').append(response.content); 
      } else{ 
       has_content = false; 
      } 
      loading = false; 
      } 

Dopo aver completato la pagina, avvio il mio scorrimento infinito.Le richieste AJAX si attivano quando l'utente raggiunge l'elemento con l'id load-more-posts, che si trova sotto il wrapper principale.

$(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(); 
     } 
    });  

});

+0

@Mayank non riesco nemmeno a ottenere il diritto di layout. jsFiddle aggiunge una sorta di margine di cui non posso sbarazzarmi. Voglio .post-body deve essere lasciato e .post-social avere ragione, ma c'è un margine in .post-body che non riesco a rimuovere .. Entrambi sono dentro .post-container ... non so perché il margine è there https://jsfiddle.net/hu0om6d3/4/ – PeterTheLobster

+1

Non vedo problemi con la tua AJAX, vedo comunque problemi con il tuo CSS. Puoi pubblicare un'immagine che mostra come vuoi che assomigli? – LGSon

+0

@LGSon Scusa devo andare per la cena di natale .. posterò più domani. Aggiungerò solo che metto il css all'interno di classi separate e lo scambio tra loro in modo che non si mescolino e che funzioni bene per la prima richiesta di ajax. E 'solo che dopo aver aggiunto nuovi post nelle seguenti richieste l'altezza del genitore sembra essere calcolata male, come se non ci fosse immagine al suo interno e il contenitore del pulsante social salti alla fine del genitore. Quindi perché penso che abbia a che fare con il caricamento delle immagini. Migliorerò la domanda con maggiori dettagli domani. – PeterTheLobster

risposta

3

Il problema è che attualmente il calcolo delle varie proprietà di altezza/posizione è associato all'evento di scorrimento, che può essere attivato prima che le immagini aggiunte tramite AJAX vengano caricate e quindi da calcolare in modo errato. Per risolvere questo problema ho dovuto legarlo all'evento di caricamento, per assicurarmi che le immagini siano pronte per essere utilizzate.

$('.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; 
} 
Problemi correlati