web-dev-qa-db-fra.com

Vérifier si un utilisateur a fait défiler vers le bas

Je crée un système de pagination (un peu comme Facebook) où le contenu est chargé lorsque l'utilisateur fait défiler l'écran vers le bas. J'imagine que la meilleure façon de le faire est de savoir quand l'utilisateur est au bas de la page et d'exécuter une requête ajax pour charger plus de messages.

Le seul problème est que je ne sais pas comment vérifier si l'utilisateur a fait défiler la page au bas de la page avec jQuery. Des idées?

Je dois trouver un moyen de vérifier si l'utilisateur a fait défiler le bas de la page avec jQuery.

583
Johnny

Utilisez le .scroll() event sur window, comme ceci:

$(window).scroll(function() {
   if($(window).scrollTop() + $(window).height() == $(document).height()) {
       alert("bottom!");
   }
});

Vous pouvez le tester ici , cela prend le défilement supérieur de la fenêtre, donc combien de fois il fait défiler, ajoute la hauteur de la fenêtre visible et vérifie si cela est égal à la hauteur du contenu global (document). Si vous vouliez plutôt vérifier si l'utilisateur est près de en bas, cela ressemblerait à ceci:

$(window).scroll(function() {
   if($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
       alert("near bottom!");
   }
});

Vous pouvez tester cette version ici , ajustez simplement ce 100 en fonction du pixel à partir du bas sur lequel vous souhaitez déclencher.

925
Nick Craver

La réponse de Nick Craver fonctionne bien, évitez le fait que la valeur de $(document).height() varie selon le navigateur.

Pour que cela fonctionne sur tous les navigateurs, utilisez cette fonction de James Padolsey :

function getDocHeight() {
    var D = document;
    return Math.max(
        D.body.scrollHeight, D.documentElement.scrollHeight,
        D.body.offsetHeight, D.documentElement.offsetHeight,
        D.body.clientHeight, D.documentElement.clientHeight
    );
}

à la place de $(document).height(), de sorte que le code final est:

$(window).scroll(function() {
       if($(window).scrollTop() + $(window).height() == getDocHeight()) {
           alert("bottom!");
       }
   });
107
Miles O'Keefe

Je ne sais pas exactement pourquoi cela n'a pas encore été publié, mais selon la documentation de MDN , le moyen le plus simple consiste à utiliser des propriétés javascript natives:

element.scrollHeight - element.scrollTop === element.clientHeight

Renvoie true lorsque vous êtes au bas d'un élément défilable. Si simplement en utilisant javascript:

element.addEventListener('scroll', function(event)
{
    var element = event.target;
    if (element.scrollHeight - element.scrollTop === element.clientHeight)
    {
        console.log('scrolled');
    }
});

scrollHeight supporte largement les navigateurs, de 8 à plus précis, alors que clientHeight et scrollTop sont tous les deux supportés par tout le monde. Même c'est-à-dire 6. Cela devrait être sécurisé entre navigateurs.

67

Pour ceux qui utilisent la solution de Nick et reçoivent des alertes/événements répétés, vous pouvez ajouter une ligne de code au-dessus de l'exemple d'alerte:

$(window).scroll(function() {
   if($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
       $(window).unbind('scroll');
       alert("near bottom!");
   }
});

Cela signifie que le code ne sera déclenché que la première fois que vous vous trouvez à moins de 100 pixels du bas du document. Cela ne se répètera pas si vous faites défiler vers le haut, puis le bas, ce qui peut être utile ou non, en fonction de l'utilisation du code de Nick.

46
Tim Carr

En plus de l’excellente réponse acceptée par Nick Craver, vous pouvez limiter l’événement de défilement afin qu’il ne soit pas déclenché aussi souvent, ainsi augmentant les performances du navigateur:

var _throttleTimer = null;
var _throttleDelay = 100;
var $window = $(window);
var $document = $(document);

$document.ready(function () {

    $window
        .off('scroll', ScrollHandler)
        .on('scroll', ScrollHandler);

});

function ScrollHandler(e) {
    //throttle event:
    clearTimeout(_throttleTimer);
    _throttleTimer = setTimeout(function () {
        console.log('scroll');

        //do work
        if ($window.scrollTop() + $window.height() > $document.height() - 100) {
            alert("near bottom!");
        }

    }, _throttleDelay);
}
39
George Filippakos

La réponse de Nick Craver doit être légèrement modifiée pour fonctionner sur iOS 6 Safari Mobile et devrait être:

$(window).scroll(function() {
   if($(window).scrollTop() + window.innerHeight == $(document).height()) {
       alert("bottom!");
   }
});

La modification de $ (window) .height () en window.innerHeight doit être effectuée car lorsque la barre d'adresse est masquée, 60 pixels supplémentaires sont ajoutés au La hauteur de la fenêtre, mais l'utilisation de $(window).height() ne reflète pas reflète ce changement, alors que l'utilisation de window.innerHeight l'est.

Note: la propriété window.innerHeight inclut également la hauteur de la barre de défilement horizontale (si elle est rendue), contrairement à $(window).height() qui n'inclut pas la hauteur de la barre de défilement horizontale. Ce n'est pas un problème dans Mobile Safari, mais cela peut entraîner un comportement inattendu sur les autres navigateurs ou les futures versions de Mobile Safari. Remplacer == par >= pourrait résoudre ce problème dans les cas d'utilisation les plus courants.

En savoir plus sur la propriété window.innerHeightici

36
Yosi

Voici une approche assez simple:

Elm.onscroll = function() {
    if(Elm.scrollTop + Elm.clientHeight == Elm.scrollHeight) //User has scrolled to the bottom of the element
}
19
Frederik Witte

Voici un morceau de code qui vous aidera à déboguer votre code. J'ai testé les réponses ci-dessus et je les ai trouvées boguées. J'ai tester les suivants sur Chrome, IE, Firefox, IPad (Safari). Je n'ai pas d'autres installés pour tester ...

<script type="text/javascript">
   $(function() {
      $(window).scroll(function () {
         var docElement = $(document)[0].documentElement;
         var winElement = $(window)[0];

         if ((docElement.scrollHeight - winElement.innerHeight) == winElement.pageYOffset) {
            alert('bottom');
         }
      });
   });
</script>

Il y a peut-être une solution plus simple, mais je me suis arrêté au point où IT WORKED

Si vous rencontrez toujours des problèmes avec un navigateur non autorisé, voici du code pour vous aider à déboguer:

<script type="text/javascript">
   $(function() {
      $(window).scroll(function () {
         var docElement = $(document)[0].documentElement;
         var details = "";
         details += '<b>Document</b><br />';
         details += 'clientHeight:' + docElement.clientHeight + '<br />';
         details += 'clientTop:' + docElement.clientTop + '<br />';
         details += 'offsetHeight:' + docElement.offsetHeight + '<br />';
         details += 'offsetParent:' + (docElement.offsetParent == null) + '<br />';
         details += 'scrollHeight:' + docElement.scrollHeight + '<br />';
         details += 'scrollTop:' + docElement.scrollTop + '<br />';

         var winElement = $(window)[0];
         details += '<b>Window</b><br />';
         details += 'innerHeight:' + winElement.innerHeight + '<br />';
         details += 'outerHeight:' + winElement.outerHeight + '<br />';
         details += 'pageYOffset:' + winElement.pageYOffset + '<br />';
         details += 'screenTop:' + winElement.screenTop + '<br />';
         details += 'screenY:' + winElement.screenY + '<br />';
         details += 'scrollY:' + winElement.scrollY + '<br />';

         details += '<b>End of page</b><br />';
         details += 'Test:' + (docElement.scrollHeight - winElement.innerHeight) + '=' + winElement.pageYOffset + '<br />';
         details += 'End of Page? ';
         if ((docElement.scrollHeight - winElement.innerHeight) == winElement.pageYOffset) {
             details += 'YES';
         } else {
             details += 'NO';
         }

         $('#test').html(details);
      });
   });
</script>
<div id="test" style="position: fixed; left:0; top: 0; z-index: 9999; background-color: #FFFFFF;">

J'espère que cela sauvera du temps à quelqu'un.

14
Talon
var elemScrolPosition = elem.scrollHeight - elem.scrollTop - elem.clientHeight;

Il calcule la barre de défilement de la distance jusqu'au bas de l'élément . Égal à 0, si la barre de défilement a atteint le bas 

10
Vasyl Gutnyk

S'il vous plaît vérifier cette réponse

 window.onscroll = function(ev) {
    if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
       console.log("bottom");
    }
};

Vous pouvez faire footerHeight - document.body.offsetHeight pour voir si vous êtes près du pied de page ou si vous avez atteint le pied de page.

10
Junaid Qadir

Ce sont mes deux centimes:

$('#container_element').scroll( function(){
        console.log($(this).scrollTop()+' + '+ $(this).height()+' = '+ ($(this).scrollTop() + $(this).height())   +' _ '+ $(this)[0].scrollHeight  );
        if($(this).scrollTop() + $(this).height() == $(this)[0].scrollHeight){
            console.log('bottom found');
        }
    });
9
ddanone

Pure JS avec cross-browser et debouncing _ ​​(Assez bon performance)

var CheckIfScrollBottom = debouncer(function() {
    if(getDocHeight() == getScrollXY()[1] + window.innerHeight) {
       console.log('Bottom!');
    }
},500);

document.addEventListener('scroll',CheckIfScrollBottom);

function debouncer(a,b,c){var d;return function(){var e=this,f=arguments,g=function(){d=null,c||a.apply(e,f)},h=c&&!d;clearTimeout(d),d=setTimeout(g,b),h&&a.apply(e,f)}}
function getScrollXY(){var a=0,b=0;return"number"==typeof window.pageYOffset?(b=window.pageYOffset,a=window.pageXOffset):document.body&&(document.body.scrollLeft||document.body.scrollTop)?(b=document.body.scrollTop,a=document.body.scrollLeft):document.documentElement&&(document.documentElement.scrollLeft||document.documentElement.scrollTop)&&(b=document.documentElement.scrollTop,a=document.documentElement.scrollLeft),[a,b]}
function getDocHeight(){var a=document;return Math.max(a.body.scrollHeight,a.documentElement.scrollHeight,a.body.offsetHeight,a.documentElement.offsetHeight,a.body.clientHeight,a.documentElement.clientHeight)}

Démo:http://jsbin.com/geherovena/edit?js,output

_ {PS: Debouncer, getScrollXY, getDocHeight non écrit par moi} _

_ {Je viens de montrer comment ça marche, et comment je vais faire} _

5
l2aelba

Vous pouvez essayer le code suivant,

$("#dashboard-scroll").scroll(function(){
    var ele = document.getElementById('dashboard-scroll');
    if(ele.scrollHeight - ele.scrollTop === ele.clientHeight){
       console.log('at the bottom of the scroll');
    }
});
3
Shahrukh Anwar

Nick répond bien, mais vous aurez des fonctions qui se répètent lors du défilement ou qui ne fonctionneront pas du tout si la fenêtre est zoomée. Je suis venu avec une solution facile juste math.round la première hauteur et cela fonctionne comme supposé.

    if (Math.round($(window).scrollTop()) + $(window).innerHeight() == $(document).height()){
    loadPagination();
    $(".go-up").css("display","block").show("slow");
}
3
Florin Andrei

Essayez ceci pour la condition de correspondance si faites défiler vers le bas

if ($(this)[0].scrollHeight - $(this).scrollTop() == 
    $(this).outerHeight()) {

    //code for your custom logic

}
2
Hiren Patel

Toutes ces solutions ne fonctionnent pas pour moi sous Firefox et Chrome, j'utilise donc les fonctions personnalisées de Miles O'Keefe et meder omuraliev comme ceci:

function getDocHeight()
{
    var D = document;
    return Math.max(
        D.body.scrollHeight, D.documentElement.scrollHeight,
        D.body.offsetHeight, D.documentElement.offsetHeight,
        D.body.clientHeight, D.documentElement.clientHeight
    );
}

function getWindowSize()
{
  var myWidth = 0, myHeight = 0;
  if( typeof( window.innerWidth ) == 'number' ) {
    //Non-IE
    myWidth = window.innerWidth;
    myHeight = window.innerHeight;
  } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
    //IE 6+ in 'standards compliant mode'
    myWidth = document.documentElement.clientWidth;
    myHeight = document.documentElement.clientHeight;
  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
    //IE 4 compatible
    myWidth = document.body.clientWidth;
    myHeight = document.body.clientHeight;
  }
  return [myWidth, myHeight];
}

$(window).scroll(function()
{
    if($(window).scrollTop() + getWindowSize()[1] == getDocHeight())
    {
        alert("bottom!");
    }
});
1
hayj

Laissez-moi montrer l'approche sans JQuery. Fonction JS simple: 

function isVisible(elem) {
  var coords = elem.getBoundingClientRect();
  var topVisible = coords.top > 0 && coords.top < 0;
  var bottomVisible = coords.bottom < shift && coords.bottom > 0;
  return topVisible || bottomVisible;
}

Petit exemple comment l'utiliser:

var img = document.getElementById("pic1");
    if (isVisible(img)) { img.style.opacity = "1.00";  }
1
Alexei Zababurin

Cela donne des résultats précis, lorsqu’il vérifie un élément défilant (c’est-à-dire pas window):

// `element` is a native JS HTMLElement
if ( element.scrollTop == (element.scrollHeight - element.offsetHeight) )
    // Element scrolled to bottom

offsetHeight doit donner la réelle visible hauteur d'un élément (y compris les barres de défilement, la marge, et), et scrollHeight est la hauteur entière d'un élément, y compris les zones invisibles (débordées).

jQuery 's .outerHeight() devrait donner un résultat similaire à celui de JS .offsetHeight -- La documentation dans MDN pour offsetHeight ne permet pas de déterminer avec précision sa prise en charge multi-navigateurs. Pour couvrir plus d'options, ceci est plus complet:

var offsetHeight = ( container.offsetHeight ? container.offsetHeight : $(container).outerHeight() );
if  ( container.scrollTop == (container.scrollHeight - offsetHeight) ) {
   // scrolled to bottom
}

0
Yuval A.

Pour arrêter l'alerte répétée de la réponse de Nick

ScrollActivate();

function ScrollActivate() {
    $(window).on("scroll", function () {
        if ($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
            $(window).off("scroll");
            alert("near bottom!");
        }
    });
}
0
Arun Prasad E S

Google Chrome donne toute la hauteur de la page si vous appelez $(window).height()

À la place, utilisez window.innerHeight pour récupérer la hauteur de votre fenêtre. Le chèque nécessaire devrait être:

if($(window).scrollTop() + window.innerHeight > $(document).height() - 50) {
    console.log("reached bottom!");
}
0
alierdogan7

J'ai utilisé @ddanone answear et ajouté Ajax call. 

$('#mydiv').on('scroll', function(){
  function infiniScroll(this);
});

function infiniScroll(mydiv){
console.log($(mydiv).scrollTop()+' + '+ $(mydiv).height()+' = '+ ($(mydiv).scrollTop() + $(mydiv).height())   +' _ '+ $(mydiv)[0].scrollHeight  );

if($(mydiv).scrollTop() + $(mydiv).height() == $(mydiv)[0].scrollHeight){
    console.log('bottom found');
    if(!$.active){ //if there is no ajax call active ( last ajax call waiting for results ) do again my ajax call
        myAjaxCall();
    }
}

}

0
Henrique C.

Ma solution en clair js:

let el=document.getElementById('el');
el.addEventListener('scroll', function (e) {
		if (el.scrollHeight - el.scrollTop - el.clientHeight<0) {
      console.log('Bottom')
    }
});
#el{
  width:300px;
  height:100px;
  overflow-y:scroll;
}
<div id="el">
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
</div>

0
Bakos Bence

Voici mes deux cents comme la réponse acceptée ne m'a pas fonctionné.

var documentAtBottom = (document.documentElement.scrollTop + window.innerHeight) >= document.documentElement.scrollHeight;
0
Vince Panuccio