123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- (function (global, factory) {
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
- typeof define === 'function' && define.amd ? define(factory) :
- (global.infiniteScroll = factory());
- }(this, function () { 'use strict';
- var ctx = '@@InfiniteScroll';
- var throttle = function throttle(fn, delay) {
- var now, lastExec, timer, context, args; //eslint-disable-line
- var execute = function execute() {
- fn.apply(context, args);
- lastExec = now;
- };
- return function () {
- context = this;
- args = arguments;
- now = Date.now();
- if (timer) {
- clearTimeout(timer);
- timer = null;
- }
- if (lastExec) {
- var diff = delay - (now - lastExec);
- if (diff < 0) {
- execute();
- } else {
- timer = setTimeout(function () {
- execute();
- }, diff);
- }
- } else {
- execute();
- }
- };
- };
- var getScrollTop = function getScrollTop(element) {
- if (element === window) {
- return Math.max(window.pageYOffset || 0, document.documentElement.scrollTop);
- }
- return element.scrollTop;
- };
- var getComputedStyle = document.defaultView.getComputedStyle;
- var getScrollEventTarget = function getScrollEventTarget(element) {
- var currentNode = element;
- // bugfix, see http://w3help.org/zh-cn/causes/SD9013 and http://stackoverflow.com/questions/17016740/onscroll-function-is-not-working-for-chrome
- while (currentNode && currentNode.tagName !== 'HTML' && currentNode.tagName !== 'BODY' && currentNode.nodeType === 1) {
- var overflowY = getComputedStyle(currentNode).overflowY;
- if (overflowY === 'scroll' || overflowY === 'auto') {
- return currentNode;
- }
- currentNode = currentNode.parentNode;
- }
- return window;
- };
- var getVisibleHeight = function getVisibleHeight(element) {
- if (element === window) {
- return document.documentElement.clientHeight;
- }
- return element.clientHeight;
- };
- var getElementTop = function getElementTop(element) {
- if (element === window) {
- return getScrollTop(window);
- }
- return element.getBoundingClientRect().top + getScrollTop(window);
- };
- var isAttached = function isAttached(element) {
- var currentNode = element.parentNode;
- while (currentNode) {
- if (currentNode.tagName === 'HTML') {
- return true;
- }
- if (currentNode.nodeType === 11) {
- return false;
- }
- currentNode = currentNode.parentNode;
- }
- return false;
- };
- var doBind = function doBind() {
- if (this.binded) return; // eslint-disable-line
- this.binded = true;
- var directive = this;
- var element = directive.el;
- var throttleDelayExpr = element.getAttribute('infinite-scroll-throttle-delay');
- var throttleDelay = 200;
- if (throttleDelayExpr) {
- throttleDelay = Number(directive.vm[throttleDelayExpr] || throttleDelayExpr);
- if (isNaN(throttleDelay) || throttleDelay < 0) {
- throttleDelay = 200;
- }
- }
- directive.throttleDelay = throttleDelay;
- directive.scrollEventTarget = getScrollEventTarget(element);
- directive.scrollListener = throttle(doCheck.bind(directive), directive.throttleDelay);
- directive.scrollEventTarget.addEventListener('scroll', directive.scrollListener);
- this.vm.$on('hook:beforeDestroy', function () {
- directive.scrollEventTarget.removeEventListener('scroll', directive.scrollListener);
- });
- var disabledExpr = element.getAttribute('infinite-scroll-disabled');
- var disabled = false;
- if (disabledExpr) {
- this.vm.$watch(disabledExpr, function (value) {
- directive.disabled = value;
- if (!value && directive.immediateCheck) {
- doCheck.call(directive);
- }
- });
- disabled = Boolean(directive.vm[disabledExpr]);
- }
- directive.disabled = disabled;
- var distanceExpr = element.getAttribute('infinite-scroll-distance');
- var distance = 0;
- if (distanceExpr) {
- distance = Number(directive.vm[distanceExpr] || distanceExpr);
- if (isNaN(distance)) {
- distance = 0;
- }
- }
- directive.distance = distance;
- var immediateCheckExpr = element.getAttribute('infinite-scroll-immediate-check');
- var immediateCheck = true;
- if (immediateCheckExpr) {
- immediateCheck = Boolean(directive.vm[immediateCheckExpr]);
- }
- directive.immediateCheck = immediateCheck;
- if (immediateCheck) {
- doCheck.call(directive);
- }
- var eventName = element.getAttribute('infinite-scroll-listen-for-event');
- if (eventName) {
- directive.vm.$on(eventName, function () {
- doCheck.call(directive);
- });
- }
- };
- var doCheck = function doCheck(force) {
- var scrollEventTarget = this.scrollEventTarget;
- var element = this.el;
- var distance = this.distance;
- if (force !== true && this.disabled) return; //eslint-disable-line
- var viewportScrollTop = getScrollTop(scrollEventTarget);
- var viewportBottom = viewportScrollTop + getVisibleHeight(scrollEventTarget);
- var shouldTrigger = false;
- if (scrollEventTarget === element) {
- shouldTrigger = scrollEventTarget.scrollHeight - viewportBottom <= distance;
- } else {
- var elementBottom = getElementTop(element) - getElementTop(scrollEventTarget) + element.offsetHeight + viewportScrollTop;
- shouldTrigger = viewportBottom + distance >= elementBottom;
- }
- if (shouldTrigger && this.expression) {
- this.expression();
- }
- };
- var InfiniteScroll = {
- bind: function bind(el, binding, vnode) {
- el[ctx] = {
- el: el,
- vm: vnode.context,
- expression: binding.value
- };
- var args = arguments;
- el[ctx].vm.$on('hook:mounted', function () {
- el[ctx].vm.$nextTick(function () {
- if (isAttached(el)) {
- doBind.call(el[ctx], args);
- }
- el[ctx].bindTryCount = 0;
- var tryBind = function tryBind() {
- if (el[ctx].bindTryCount > 10) return; //eslint-disable-line
- el[ctx].bindTryCount++;
- if (isAttached(el)) {
- doBind.call(el[ctx], args);
- } else {
- setTimeout(tryBind, 50);
- }
- };
- tryBind();
- });
- });
- },
- unbind: function unbind(el) {
- if (el && el[ctx] && el[ctx].scrollEventTarget) el[ctx].scrollEventTarget.removeEventListener('scroll', el[ctx].scrollListener);
- }
- };
- var install = function install(Vue) {
- Vue.directive('InfiniteScroll', InfiniteScroll);
- };
- if (window.Vue) {
- window.infiniteScroll = InfiniteScroll;
- Vue.use(install); // eslint-disable-line
- }
- InfiniteScroll.install = install;
- return InfiniteScroll;
- }));
|