2015-04-29 15 views
17

Sto tentando di attivare un evento quando la barra di scorrimento raggiunge la fine. Ho trovato questo this example. Ecco il mio codice. Il problema è che non chiama affatto loadmore(). I valori delle statments console sono:Angularjs: come attivare l'evento quando lo scorrimento raggiunge la parte inferiore della barra di scorrimento in div?

848 
899 
in scroll 
881 
899 
in scroll 
892 
899 
in scroll 
897 
899 
in scroll 
900 
899 

Sembra che non va mai a quello if! La parte strana è che se eseguo il debug in inspect element, si attiva l'evento. ..... mia direttiva:

directive('scrolly', function() { 
    return { 
     restrict: 'A', 
     link: function (scope, element, attrs) { 
      var raw = element[0]; 
      console.log('loading directive'); 
      element.bind('scroll', function() { 
       console.log('in scroll'); 
       console.log(raw.scrollTop + raw.offsetHeight); 
       console.log(raw.scrollHeight); 
       if (raw.scrollTop + raw.offsetHeight == raw.scrollHeight) { //at the bottom 
        scope.$apply(attrs.scrolly); 
       } 
      }) 
     } 
    } 

risposta

19

Invece di controllare per l'uguaglianza, si prega di verificare se il lato sinistro è maggiore del lato destro nella if in quanto questo è il caso per la barra di scorrimento per essere in fondo

raw.scrollTop + raw.offsetHeight > raw.scrollHeight 

Questo è il funzionamento jsfiddle.

+0

Grazie di lavoro ora – Sara

+2

Deve essere '> =' perché se si sostituisce 'overflow: scroll;' con 'overflow: scroll-y;' (es. sbarazzarsi della barra di scorrimento inferiore inutilizzata) quindi 'raw.scrollTop + raw.offsetHeight' non sarà mai più di' raw.scrollHeight' – Stalinko

+0

Stalinko, hai assolutamente ragione! – Julsy

4

ero alla ricerca di un frammento per aiutarmi a fare questo, ma non ho trovato nulla vale la pena così sono arrivato fino a questo abbastanza facile da usare direttiva per fare questo

'use strict'; 
// Tested with Angular 1.3, 1.4.8 
angular.module('scrollToEnd', []) 
    /** 
    * @ngdoc directive 
    * @name scrollToEnd:scrollToEnd 
    * @scope 
    * @restrict A 
    * 
    * @description 
    * Supply a handler to be called when this element is scrolled all the way to any extreme. 
    * The callback must have the following signature: 
    * void function (direction:'top'|'bottom'|'left'|'right') 
    * If the `bindToWindow` attribute is truthy, the callback will be issued for the window 
    * instead of the element that the directive is on. 
    * 
    * Example usage: 
    * `<div scroll-to-end="scrollToEndWindow" bind-to-window="true">` 
    * This will call the controller's `scrollToEndWindow` function whenever the window reaches 
    * the edges when scrolling. If the div itself is a scrollable element for which the 
    * handler should be called instead, remove the bind-to-window attribute entirely. 
    * 
    * @param {function} emScrollToEnd Callback to be invoked 
    * @param {boolean}  bindToWindow  Bind to the window instead of the element 
    * 
    */ 
    .directive('scrollToEnd', function ($window) { 
    // Get the specified element's computed style (height, padding, etc.) in integer form 
    function getStyleInt(elem, prop) { 
     try { 
     return parseInt(window.getComputedStyle(elem, null).getPropertyValue(prop), 10); 
     } catch (e) { 
     return parseInt(elem.currentStyle[prop], 10); 
     } 
    } 

    // Get the 'innerHeight' equivalent for a non-window element, including padding 
    function getElementDimension(elem, prop) { 
     switch (prop) { 
     case 'width': 
      return getStyleInt(elem, 'width') + 
      getStyleInt(elem, 'padding-left') + 
      getStyleInt(elem, 'padding-right'); 
     case 'height': 
      return getStyleInt(elem, 'height') + 
      getStyleInt(elem, 'padding-top') + 
      getStyleInt(elem, 'padding-bottom'); 
     /*default: 
      return null;*/ 
     } 
    } 
    return { 
     restrict: 'A', 
     scope: { 
     callback: '=scrollToEnd' 
     }, 
     link: function (scope, elem, attr) { 
     var callback = scope.callback || function() {}; 
     var boundToWindow = attr.bindToWindow; 
     var body = document.body; 
     var html = document.documentElement; 
     var boundElement = boundToWindow ? angular.element($window) : elem; 
     var oldScrollX = 0; 
     var oldScrollY = 0; 
     var handleScroll = function() { 
      // Dimensions of the content, including everything scrollable 
      var contentWidth; 
      var contentHeight; 
      // The dimensions of the container with the scrolling, only the visible part 
      var viewportWidth; 
      var viewportHeight; 
      // The offset of how much the user has scrolled 
      var scrollX; 
      var scrollY; 

      if (boundToWindow) { 
      // Window binding case - Populate Dimensions 
      contentWidth = Math.max(
       body.scrollWidth, 
       body.offsetWidth, 
       html.clientWidth, 
       html.scrollWidth, 
       html.offsetWidth 
      ); 
      contentHeight = Math.max(
       body.scrollHeight, 
       body.offsetHeight, 
       html.clientHeight, 
       html.scrollHeight, 
       html.offsetHeight 
      ); 
      viewportWidth = window.innerWidth; 
      viewportHeight = window.innerHeight; 
      scrollX = (window.pageXOffset || html.scrollLeft) - (html.clientLeft || 0); 
      scrollY = (window.pageYOffset || html.scrollTop) - (html.clientTop || 0); 
      } else { 
      // DOM element case - Populate Dimensions 
      var domElement = boundElement[0]; 
      contentWidth = domElement.scrollWidth; 
      contentHeight = domElement.scrollHeight; 
      viewportWidth = getElementDimension(domElement, 'width'); 
      viewportHeight = getElementDimension(domElement, 'height'); 
      scrollX = domElement.scrollLeft; 
      scrollY = domElement.scrollTop; 
      } 

      var scrollWasInXDirection = oldScrollX !== scrollX; 
      var scrollWasInYDirection = oldScrollY !== scrollY; 
      oldScrollX = scrollX; 
      oldScrollY = scrollY; 

      if (scrollWasInYDirection && scrollY === 0) { 
      callback('top'); 
      } else if (scrollWasInYDirection && scrollY === contentHeight - viewportHeight) { 
      callback('bottom'); 
      } else if (scrollWasInXDirection && scrollX === 0) { 
      callback('left'); 
      } else if (scrollWasInXDirection && scrollX === contentWidth - viewportWidth) { 
      callback('right'); 
      } 
     }; 
     boundElement.bind('scroll', handleScroll); 
     // Unbind the event when scope is destroyed 
     scope.$on('$destroy', function() { 
      boundElement.unbind('scroll', handleScroll); 
     }); 
     } 
    }; 
    }); 

https://gist.github.com/podrezo/f80f35d6d0655f4d550cac4747c110ff

Ecco un jsfiddle per provarlo:

https://jsfiddle.net/va4x5r26/2/

Funziona con angolare 1.3 e 1.4.8, e testato su IE10 e Chrome 5 5.

+0

Girare 'handleScroll' in una funzione rimossa migliorerebbe davvero questo. Tuttavia, ottimo lavoro! –

+0

Grazie; questa è una buona idea –

7

Tu mi ha dato un paio di buoni consigli ... Ecco un esempio di lavoro completo per chiunque altro che si imbatte in questo post:

JS:

app.controller("controller", function ($scope) { 
    $scope.test = function() { 
     alert("hello!"); 
    } 
} 

HTML:

<div class="br-section1" on-scroll-to-bottom="test()"> 
</div> 

Direttiva app:

app.directive('onScrollToBottom', function ($document) { 
    //This function will fire an event when the container/document is scrolled to the bottom of the page 
    return { 
     restrict: 'A', 
     link: function (scope, element, attrs) { 

      var doc = angular.element($document)[0].body; 

      $document.bind("scroll", function() { 

       //console.log('in scroll'); 
       //console.log("scrollTop + offsetHeight:" + (doc.scrollTop + doc.offsetHeight)); 
       //console.log("scrollHeight: " + doc.scrollHeight); 

       if (doc.scrollTop + doc.offsetHeight >= doc.scrollHeight) { 
        //run the event that was passed through 
        scope.$apply(attrs.onScrollToBottom); 
       } 
      }); 
     } 
    }; 
}); 
+0

Questo non funziona per me. In effetti il ​​codice dell'OP aggiunto alla risposta di Rathish funziona come un incantesimo per me. Ma la tua soluzione non ha funzionato. – shanti