Detectando cuando el usuario se desplaza hasta la parte inferior del div con jQuery

218

Tengo un cuadro div (llamado flujo) con una cantidad variable de contenido dentro. Este divbox tiene desbordamiento establecido en automático.

Ahora, lo que estoy tratando de hacer es que, cuando use el desplazamiento hacia la parte inferior de este cuadro DIV, cargue más contenido en la página, sé cómo hacer esto (cargar el contenido) pero no sé cómo detectar cuando el usuario se ha desplazado hasta la parte inferior de la etiqueta div? Si quisiera hacerlo durante toda la página, tomaría .scrollTop y restaría eso de .height.

Pero parece que no puedo hacer eso aquí?

Intenté tomar .scrollTop de flux, y luego envolver todo el contenido dentro de un div llamado inner, pero si tomo la Altura interna del flujo, devuelve 564px (el div se establece en 500 como altura) y la altura de 'innner' devuelve 1064, y el scrolltop, cuando en la parte inferior del div dice 564.

¿Que puedo hacer?

Eax
fuente

Respuestas:

420

Hay algunas propiedades / métodos que puede usar:

$().scrollTop()//how much has been scrolled
$().innerHeight()// inner height of the element
DOMElement.scrollHeight//height of the content of the element

Entonces puede tomar la suma de las dos primeras propiedades, y cuando es igual a la última propiedad, ha llegado al final:

jQuery(function($) {
    $('#flux').on('scroll', function() {
        if($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
            alert('end reached');
        }
    })
});

http://jsfiddle.net/doktormolle/w7X9N/

Editar: Actualicé 'bind' a 'on' según:

A partir de jQuery 1.7, el método .on () es el método preferido para adjuntar controladores de eventos a un documento.

Dr. Molle
fuente
2
Hará el enlace cuando el DOM esté listo para asegurarse de que el elemento # flux ya esté disponible.
Dr.Molle
1
debe actualizar su respuesta usando ON en lugar de bind, bind está en desuso a favor de On
ncubica
34
Nota: Cuando un usuario usa niveles de zoom en su navegador, esto puede no funcionar. Zoom hace innerHeight()que se informen decimales En el caso de un usuario alejándose, la suma de scrollTop()y innerHeight()siempre será al menos una fracción menor scrollHeight. Terminé agregando una zona de amortiguación de 20px. El condicional resultante fue if(el.scrollTop() + el.innerHeight() >= el[0].scrollHeight - 20)donde eles igual $(this).
Nick
1
Esta es la mejor respuesta que me funcionó muy bien. Gracias
Ashish Yadav
1
Ya no funciona, ¿podría confirmar por qué no funciona? Gracias
Umair Shah Yousafzai
50

Encontré una solución que cuando desplaza su ventana y el final de un div que se muestra desde abajo le da una alerta.

$(window).bind('scroll', function() {
    if($(window).scrollTop() >= $('.posts').offset().top + $('.posts').outerHeight() - window.innerHeight) {
        alert('end reached');
    }
});

En este ejemplo, si se desplaza hacia abajo cuando div ( .posts) termina, le dará una alerta.

ehsan Aghaei
fuente
gracias por esto, pero ¿cómo puedo hacer que el div se anime cuando llegue al fondo de ese div? también cuando te desplazas hacia arriba detecta la parte superior de ese div y luego anima también. Al igual que aquí en este sitio web lazada.com.ph/apple el comportamiento de la barra lateral Espero que puedan ayudarme :)
Alyssa Reyes
Funciona como una magia, pero el problema es que la alerta se ejecuta dos veces, por lo que si tiene una llamada de una función dentro, se ejecutará dos veces
Afaf
1
@ 1616 Tengo una variable var running = falsedeclarada antes de esto. Dentro del condicional, verifico ¡De if(!running) { running = true; // and continue logic } esta manera solo se llama una vez! Cuando el AJAX se complete, establezcarunning = false;
Jacob Raccuia
1
Se trata de la ventana, pero la pregunta es sobre div.
Alexander Volkov
42

Aunque la pregunta se hizo hace 5,5 años, aún es más que relevante en el contexto actual de UI / UX. Y me gustaría agregar mis dos centavos.

var element = document.getElementById('flux');
if (element.scrollHeight - element.scrollTop === element.clientHeight)
    {
        // element is at the end of its scroll, load more content
    }

Fuente: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Determine_if_an_element_has_been_totally_scrolled

Algunos elementos no le permitirán desplazarse a la altura completa del elemento. En esos casos puedes usar:

var element = docuement.getElementById('flux');
if (element.offsetHeight + element.scrollTop === element.scrollHeight) {
  // element is at the end of its scroll, load more content
}
Pensando
fuente
2
Esta es la solución que está buscando si no está usando jQuery.
Petter Pettersson
¿Existe el controlador de eventos?
Alexander Volkov
@AlexanderVolkov onscroll es el evento relacionado.
Pensando el
9

Solo una nota adicional aquí, ya que encontré esto cuando busco una solución para un div fijo que quiero desplazar. Para mi escenario, descubrí que es preferible tener en cuenta el relleno en el div para que pueda llegar al final exactamente. Entonces, ampliando la respuesta de @ Dr.Molle, agrego lo siguiente

$('#flux').bind('scroll', function() {
    var scrollPosition = $(this).scrollTop() + $(this).outerHeight();
    var divTotalHeight = $(this)[0].scrollHeight 
                          + parseInt($(this).css('padding-top'), 10) 
                          + parseInt($(this).css('padding-bottom'), 10)
                          + parseInt($(this).css('border-top-width'), 10)
                          + parseInt($(this).css('border-bottom-width'), 10);

    if( scrollPosition == divTotalHeight )
    {
      alert('end reached');
    }
  });

Eso le dará la ubicación precisa, incluido el relleno y los bordes.

Alexander Millar
fuente
7

aunque esto funcionó para mí

$(window).scroll(function() {
  if ($(window).scrollTop() >= (($(document).height() - $(window).height()) - $('#divID').innerHeight())) {
    console.log('div reached');
  }
});
Ricardo Rivas
fuente
3

Si necesita usar esto en un div que tiene overflow-y como oculto o desplazarse, algo como esto puede ser lo que necesita.

if ($('#element').prop('scrollHeight') - $('#element').scrollTop() <= Math.ceil($('#element').height())) {
    at_bottom = true;
}

Encontré que se necesitaba ceil porque el desplazamiento de la altura de la hélice parece redondearse, o tal vez por alguna otra razón que hace que esto sea menos de 1.

ganso
fuente
3

Si no está utilizando la función Math.round (), la solución sugerida por Dr.Molle no funcionará en algunos casos cuando la ventana de un navegador tiene un zoom.

Por ejemplo $ (this) .scrollTop () + $ (this) .innerHeight () = 600

$ (esto) [0] .scrollHeight rendimientos = 599.99998

600> = 599.99998 falla.

Aquí está el código correcto:

jQuery(function($) {
    $('#flux').on('scroll', function() {
        if(Math.round($(this).scrollTop() + $(this).innerHeight(), 10) >= Math.round($(this)[0].scrollHeight, 10)) {
            alert('end reached');
        }
    })
});

También puede agregar algunos píxeles de margen adicionales si no necesita una condición estricta

var margin = 4

jQuery(function($) {
    $('#flux').on('scroll', function() {
        if(Math.round($(this).scrollTop() + $(this).innerHeight(), 10) >= Math.round($(this)[0].scrollHeight, 10) - margin) {
            alert('end reached');
        }
    })
});
Павел Гавриленко
fuente
2

En el uso simple de DOM, puede verificar la condición

element.scrollTop + element.clientHeight == element.scrollHeight

si es verdad, entonces has llegado al final.

Louay Alosh
fuente
1

Si alguien obtiene scrollHeightcomo undefined, seleccione los elementos del primer subelemento:mob_top_menu[0].scrollHeight

Starwave
fuente
1

No estoy seguro de si es de alguna ayuda, pero así es como lo hago.

Tengo un panel de índice que es más grande que la ventana y lo dejo desplazarse hasta el final de este índice. Luego lo arreglo en posición. El proceso se invierte una vez que te desplazas hacia la parte superior de la página.

Saludos.

<style type="text/css">
    .fixed_Bot {    
            position: fixed;     
            bottom: 24px;    
        }     
</style>

<script type="text/javascript">
    $(document).ready(function () {
        var sidebarheight = $('#index').height();
        var windowheight = $(window).height();


        $(window).scroll(function () {
            var scrollTop = $(window).scrollTop();

            if (scrollTop >= sidebarheight - windowheight){
                $('#index').addClass('fixed_Bot');
            }
            else {
                $('#index').removeClass('fixed_Bot');
            }                   
        });
    });

</script>
Israel Chapa
fuente
1

A pesar de que esto se hizo hace casi 6 años, todavía es un tema candente en el diseño de UX, aquí hay un fragmento de demostración si algún novato quería usar

$(function() {

  /* this is only for demonstration purpose */
  var t = $('.posts').html(),
    c = 1,
    scroll_enabled = true;

  function load_ajax() {

    /* call ajax here... on success enable scroll  */
    $('.posts').append('<h4>' + (++c) + ' </h4>' + t);

    /*again enable loading on scroll... */
    scroll_enabled = true;

  }


  $(window).bind('scroll', function() {
    if (scroll_enabled) {

      /* if 90% scrolled */
    if($(window).scrollTop() >= ($('.posts').offset().top + $('.posts').outerHeight()-window.innerHeight)*0.9) {

        /* load ajax content */
        scroll_enabled = false;  
        load_ajax();
      }

    }

  });

});
h4 {
  color: red;
  font-size: 36px;
  background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class="posts">
  Lorem ipsum dolor sit amet  Consectetuer augue nibh lacus at <br> Pretium Donec felis dolor penatibus <br> Phasellus consequat Vivamus dui lacinia <br> Ornare nonummy laoreet lacus Donec <br> Ut ut libero Curabitur id <br> Dui pretium hendrerit
  sapien Pellentesque <br> Lorem ipsum dolor sit amet <br> Consectetuer augue nibh lacus at <br> Pretium Donec felis dolor penatibus <br> Phasellus consequat Vivamus dui lacinia <br> Ornare nonummy laoreet lacus Donec <br> Ut ut libero Curabitur id <br>  Dui pretium hendrerit sapien Pellentesque <br> Lorem ipsum dolor sit amet <br> Consectetuer augue nibh lacus at <br> Pretium Donec felis dolor penatibus <br> Phasellus consequat Vivamus dui lacinia <br> Ornare nonummy laoreet lacus Donec <br> Ut ut
  libero Curabitur id <br> Dui pretium hendrerit sapien Pellentesque <br> Lorem ipsum dolor sit amet <br> Consectetuer augue nibh lacus at <br> Pretium Donec felis dolor penatibus <br> Phasellus consequat Vivamus dui lacinia <br> Ornare nonummy laoreet
  lacus Donec <br> Ut ut libero Curabitur id <br> Dui pretium hendrerit sapien Pellentesque
</div>

Akshay Hegde
fuente
0

Chicos, esta es la solución al problema del zoom, funciona con todos los niveles de zoom, en caso de que lo necesiten:

if ( Math.abs(elem.offset().top) + elem.height() + elem.offset().top >= elem.outerHeight() ) {
                    console.log("bottom");
                    // We're at the bottom!
                }
            });
        }
Liad Livnat
fuente
0
$(window).on("scroll", function() {
    //get height of the (browser) window aka viewport
    var scrollHeight = $(document).height();
    // get height of the document 
    var scrollPosition = $(window).height() + $(window).scrollTop();
    if ((scrollHeight - scrollPosition) / scrollHeight === 0) {
        // code to run when scroll to bottom of the page
    }
});

Este es el código en github.

aki_sud
fuente
-1

Aquí hay otra versión.

El código clave es la función scroller () que toma la entrada como la altura del div que contiene la sección de desplazamiento, usando overflow: scroll. Se aproxima a 5 px desde la parte superior o 10 px desde la parte inferior como en la parte superior o inferior. De lo contrario, es demasiado sensible. Parece que 10px es el mínimo. Verá que agrega 10 a la altura div para obtener la altura inferior. Supongo que 5px podría funcionar, no lo probé extensamente. YMMV. scrollHeight devuelve la altura del área de desplazamiento interior, no la altura mostrada del div, que en este caso es de 400 px.

<?php

$scrolling_area_height=400;
echo '
<script type="text/javascript">
          function scroller(ourheight) {
            var ourtop=document.getElementById(\'scrolling_area\').scrollTop;
            if (ourtop > (ourheight-\''.($scrolling_area_height+10).'\')) {
                alert(\'at the bottom; ourtop:\'+ourtop+\' ourheight:\'+ourheight);
            }
            if (ourtop <= (5)) {
                alert(\'Reached the top\');
            }
          }
</script>

<style type="text/css">
.scroller { 
            display:block;
            float:left;
            top:10px;
            left:10px;
            height:'.$scrolling_area_height.';
            border:1px solid red;
            width:200px;
            overflow:scroll; 
        }
</style>

$content="your content here";

<div id="scrolling_area" class="scroller">
onscroll="var ourheight=document.getElementById(\'scrolling_area\').scrollHeight;
        scroller(ourheight);"
        >'.$content.'
</div>';

?>
John Ostrowick
fuente
1
-1 porque generar código javascript + css desde php es una mala práctica (difícil de mantener, sin reutilización, sin optimizaciones de sitios web, etc.). Además, como señaló @Alexander Millar, el desplazamiento de 10px se puede corregir teniendo en cuenta el relleno. Cualquiera que esté considerando usar este código debería pensarlo dos veces ...
Kapitein Witbaard