2012-03-23 7 views
22

Ho una pagina che visualizza i messaggi e voglio che funzioni come Facebook, ma senza il caricatore pigro. I messaggi vengono visualizzati in ordine cronologico, ultimi ultimi.jquery - impedisce alla finestra di modificare la posizione di scorrimento mentre antepone gli articoli a un elenco?

L'elenco dei messaggi è inizialmente popolato x il numero dei messaggi più recenti e la finestra scorre verso il basso. Quando l'utente inizia a leggere il thread, legge dal basso verso l'alto. Se arrivano in cima, possono caricare altri messaggi ... Li faccio fare clic su un pulsante ... Facebook ha un caricatore pigro. I nuovi messaggi vengono aggiunti all'elenco.

Problema: quando i nuovi messaggi vengono anteposti, i messaggi esistenti vengono spostati verso il basso, causando all'utente la perdita della loro posizione di "visualizzazione". Come posso mantenere la posizione attuale della vista dell'utente mentre aggiungo i nuovi messaggi? Per un esempio, apri un lungo thread di messaggi in facebook, scorri verso l'alto causando l'aggiunta di nuovi messaggi ... la posizione della tua vista non cambia anche se la posizione di scorrimento lo fa.

risposta

41

memorizzare un riferimento al primo messaggio prima di precedere i nuovi messaggi, e dopo precedi, imposta di scorrimento per l'offset di quel messaggio:

$(document).on('scroll', function() { 
    var scroll = $(document).scrollTop(); 
    if (scroll < 1) { 
     // Store eference to first message 
     var firstMsg = $('.message:first'); 

     // Prepend new message here (I'm just cloning...) 
     $('body').prepend(firstMsg.clone()); 

     // After adding new message(s), set scroll to position of 
     // what was the first message 
     $(document).scrollTop(firstMsg.offset().top); 
    } 
}); 

Demo: http://jsfiddle.net/GRnQY/

Edit: Ho notato che lo volevi con un pulsante. Potrebbe essere necessario fare un po 'di più per la matematica:

$(document).on('click', '#loadMore', function() { 
    var firstMsg = $('.message:first'); 

    // Where the page is currently: 
    var curOffset = firstMsg.offset().top - $(document).scrollTop(); 

    // Prepend 
    firstMsg.before(firstMsg.clone()); 

    // Offset to previous first message minus original offset/scroll 
    $(document).scrollTop(firstMsg.offset().top-curOffset); 
}); 

Demo: http://jsfiddle.net/GRnQY/5/

+6

La seconda soluzione è FANTASTICA - grazie mille, questo è stato molto utile per l'implementazione di un "inverso infinito scroll" ai messaggi di Facebook. –

+0

Se si sta utilizzando unjax, aggiungere '$ (selector) .scrollTop (firstMsg.offset(). Top-curOffset);' sull'attributo ajax 'success' per il corretto funzionamento dello scroll – user3284463

+0

Awesome! Grazie Jeff! – Can

5

Non c'è bisogno di jQuery qui, solo verificare le modifiche negli elementi scrollHeight e regolare lo scrollTop conseguenza, ad esempio:

var lastScrollHeight = el.scrollHeight; 
for(var n=0; n<10; n++){ 
    // Prepend here... 
} 
var scrollDiff = el.scrollHeight - lastScrollHeight; 
el.scrollTop += scrollDiff; 

Demo

http://jsfiddle.net/fkqqv28e/

jQuery

Per accedere al nodo DOM nativo da una raccolta jQuery, utilizzare l'accesso matrice; es .:

var lastScrollHeight = $('#myElement')[0].scrollHeight; 
for(var n=0; n<10; n++){ 
    $('#myElement').prepend('<div>prepended '+Math.random()+'</div>'); 
} 
var scrollDiff = $('#myElement')[0].scrollHeight - lastScrollHeight; 
$('#myElement')[0].scrollTop += scrollDiff; 
0

Ho appena trovato una variazione di questo. ho staccato un gran numero di elementi, li ho elaborati e poi li ho attaccati di nuovo. questo non viene completato in modo sincrono in Chrome, quindi non ho potuto impostare $ el.scrollTop (oldval) in modo affidabile. Ho trovato questa soluzione ha funzionato per me.

1

Alcune persone che arrivano qui possono semplicemente voler aggiungere contenuti senza che l'attuale focus si aggiri. La modifica della demo di Jeff B sopra per utilizzare l'obiettivo evento click rende questo idioma più portabile:

someButton.on('click', function() { 
    var curOffset = $(this).offset().top - $(document).scrollTop(); 
    // add content to your heart's content. 
    $(document).scrollTop($(this).offset().top-curOffset); 
}); 

c.f. http://jsfiddle.net/bwz8uLvt/1/ (variante della demo di Jeff B sopra ma con il pulsante [aggiungi altro] in un punto arbitrario nella pagina).

0

È inoltre possibile mantenere la posizione di scorrimento in base all'offset fino alla parte inferiore della pagina/elemento.

var ScrollFromBottom = $(document).height() - $(window).scrollTop(); 

//ajax - add messages -- geenrate html code then add to dom 

//set scroll position 
$(window).scrollTop($(document).height() - ScrollFromBottom);