Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add offset? #78

Open
jamesryan-dev opened this issue Apr 11, 2019 · 1 comment
Open

Add offset? #78

jamesryan-dev opened this issue Apr 11, 2019 · 1 comment

Comments

@jamesryan-dev
Copy link

Has any1 been able to add an offset so isInView triggers slightly before or after element leaves viewport?

@svarup
Copy link

svarup commented Oct 26, 2019

With offset to preloading the image when it's getting close to entering the viewport. To do this, you can now add a data-offset attribute to your target element. For example:

<img data-offset="300">

also support visible area using third parameter on on, one event for example:

$('div').on('inview', function (event, visible, topOrBottomOrBoth) {
 if (visible == true) {
    // element is now visible in the viewport
    if (topOrBottomOrBoth == 'top') {
      // top part of element is visible
    } else if (topOrBottomOrBoth == 'bottom') {
      // bottom part of element is visible
    } else {
      // whole part of element is visible
    }
  } else {
    // element has gone out of viewport
  }
});

updated jquery.inview:

/**
 * author Christopher Blum
 *    - based on the idea of Remy Sharp, http://remysharp.com/2009/01/26/element-in-view-event-plugin/
 *    - forked from http://github.com/zuk/jquery.inview/
 */
(function (factory) {
  if (typeof define == 'function' && define.amd) {
    // AMD
    define(['jquery'], factory);
  } else if (typeof exports === 'object') {
    // Node, CommonJS
    module.exports = factory(require('jquery'));
  } else {
      // Browser globals
    factory(jQuery);
  }
}(function ($) {

  var inviewObjects = [], viewportSize, viewportOffset,
      d = document, w = window, documentElement = d.documentElement, timer;

  $.event.special.inview = {
    add: function(data) {
      inviewObjects.push({ data: data, $element: $(this), element: this });
      // Use setInterval in order to also make sure this captures elements within
      // "overflow:scroll" elements or elements that appeared in the dom tree due to
      // dom manipulation and reflow
      // old: $(window).scroll(checkInView);
      //
      // By the way, iOS (iPad, iPhone, ...) seems to not execute, or at least delays
      // intervals while the user scrolls. Therefore the inview event might fire a bit late there
      //
      // Don't waste cycles with an interval until we get at least one element that
      // has bound to the inview event.
      if (!timer && inviewObjects.length) {
         timer = setInterval(checkInView, 250);
      }
    },

    remove: function(data) {
      for (var i=0; i<inviewObjects.length; i++) {
        var inviewObject = inviewObjects[i];
        if (inviewObject.element === this && inviewObject.data.guid === data.guid) {
          inviewObjects.splice(i, 1);
          break;
        }
      }

      // Clear interval when we no longer have any elements listening
      if (!inviewObjects.length) {
         clearInterval(timer);
         timer = null;
      }
    }
  };

  function getViewportSize() {
    var mode, domObject, size = { height: w.innerHeight, width: w.innerWidth };

    // if this is correct then return it. iPad has compat Mode, so will
    // go into check clientHeight/clientWidth (which has the wrong value).
    if (!size.height) {
      mode = d.compatMode;
      if (mode || !$.support.boxModel) { // IE, Gecko
        domObject = mode === 'CSS1Compat' ?
          documentElement : // Standards
          d.body; // Quirks
        size = {
          height: domObject.clientHeight,
          width:  domObject.clientWidth
        };
      }
    }

    return size;
  }

  function getViewportOffset() {
    return {
      top:  w.pageYOffset || documentElement.scrollTop   || d.body.scrollTop,
      left: w.pageXOffset || documentElement.scrollLeft  || d.body.scrollLeft
    };
  }

  function checkInView() {
    if (!inviewObjects.length) {
      return;
    }

    var i = 0, $elements = $.map(inviewObjects, function(inviewObject) {
      var selector  = inviewObject.data.selector,
          $element  = inviewObject.$element;
      return selector ? $element.find(selector) : $element;
    });

    viewportSize   = viewportSize   || getViewportSize();
    viewportOffset = viewportOffset || getViewportOffset();

    for (; i<inviewObjects.length; i++) {
      // Ignore elements that are not in the DOM tree
      if (!$.contains(documentElement, $elements[i][0])) {
        continue;
      }

      var $element      	= $($elements[i]),
          elementSize   	= { height: $element[0].offsetHeight, width: $element[0].offsetWidth },
          elementOffset 	= $element.offset(),
          wasInView        	= $element.data('inview') || false;

      // Don't ask me why because I haven't figured out yet:
      // viewportOffset and viewportSize are sometimes suddenly null in Firefox 5.
      // Even though it sounds weird:
      // It seems that the execution of this function is interferred by the onresize/onscroll event
      // where viewportOffset and viewportSize are unset
      if (!viewportOffset || !viewportSize) {
        return;
      }

      var elBottom 			= elementOffset.top + elementSize.height,
          offset 			= $element.data('offset') || 0,
          isBottomVisible 	= elBottom + offset >= viewportOffset.top && elementOffset.top <= viewportOffset.top,
          viewportBottom 	= viewportOffset.top + viewportSize.height;
          isTopVisible 		= elementOffset.top - offset <= viewportBottom && elBottom >= viewportBottom,
          inView 			= elementOffset.top >= viewportOffset.top && elBottom <= viewportBottom,
          inViewWithOffset 	= inView || isBottomVisible || isTopVisible || (elementOffset.top <= viewportOffset.top && elBottom >= viewportBottom);

        if (inViewWithOffset) {
          var visPart = (isTopVisible) ? 'top' : (isBottomVisible) ? 'bottom' : 'both';
	      if (!wasInView || wasInView !== visPart) {
	        $element.data('inview', visPart).trigger('inview', [true, visPart]);
	      }
      } else if (!inView && wasInView) {
        $element.data('inview', false).trigger('inview', [false]);
      }
    }
  }

  $(w).on("scroll resize scrollstop", function() {
    viewportSize = viewportOffset = null;
  });

  // IE < 9 scrolls to focused elements without firing the "scroll" event
  if (!documentElement.addEventListener && documentElement.attachEvent) {
    documentElement.attachEvent("onfocusin", function() {
      viewportOffset = null;
    });
  }
}));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants