UNPKG

vue-scroll

Version:
203 lines (197 loc) 5.84 kB
/** * vue-scroll vundefined * (c) 2019 Wang Pin * @license MIT */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = global || self, global.VueScroll = factory()); }(this, (function () { 'use strict'; var debounce = function (func, delay) { var inDebounce; return function() { var context = this; var args = arguments; clearTimeout(inDebounce); inDebounce = setTimeout(function () { return func.apply(context, args); }, delay); } }; var throttle = function (func, limit) { var lastFunc; var lastRan; return function() { var context = this; var args = arguments; if (!lastRan) { func.apply(context, args); lastRan = Date.now(); } else { clearTimeout(lastFunc); lastFunc = setTimeout(function() { if (Date.now() - lastRan >= limit) { func.apply(context, args); lastRan = Date.now(); } }, limit - (Date.now() - lastRan)); } } }; var isNumber = function(arg) { return typeof arg === 'number' && arg !== NaN }; var isFunction = function(arg) { return typeof arg === 'function' }; var isObject = function(arg) { return Object.prototype.toString.call(arg) === '[object Object]' }; var isInteger = function(arg) { return isNumber(arg) && Math.round(arg) === arg }; var get = function(arg, path, def) { try { return eval(("arg." + path)) } catch (err) { return def } }; var dom = (function () { var listeners = new Map(); var SCROLL = 'scroll'; function addEventListener (element, event, funcs, opt) { function fn (e) { var data; var target = e.target || e.srcElement; e = e || window.e; if (e.type === SCROLL) { if (target === document) { data = { scrollTop: get(document, 'body.scrollTop', 0), scrollLeft: get(document, 'body.scrollLeft', 0) }; } else { data = { scrollTop: get(target, 'scrollTop', 0), scrollLeft: get(target, 'scrollLeft', 0) }; } } funcs.forEach(function (f) { f(e, data); }); } if (isObject(opt)) { if (isInteger(opt.throttle) && isFinite(opt.throttle) && opt.throttle > -1) { fn = throttle(fn, opt.throttle); } if (isInteger(opt.debounce) && isFinite(opt.debounce) && opt.debounce > -1) { fn = debounce(fn, opt.debounce); } } if (event === SCROLL) { if(element === document.body || element === document || element === window) { document.onscroll = fn; } else { if (element.addEventListener) { element.addEventListener(event, fn); } else { element.attachEvent('on' + event, fn); } } } } function bind (element, event, fn, opt) { var funcs, eventFuncs; if (!isFunction(fn)) { throw new Error('Scroll handler is not a function'); } if (!listeners.has(element)) { listeners.set(element, new Map()); } funcs = listeners.get(element); if (!funcs.has(event)) { funcs.set(event, []); } eventFuncs = funcs.get(event); if (!eventFuncs.length) { addEventListener(element, event, eventFuncs, opt); } eventFuncs.push(fn); } function unbind (element, event, fn) { var funcs, eventFuncs; if (!isFunction(fn)) { return; } if (!listeners.has(element)) { listeners.set(element, new Map()); } funcs = listeners.get(element); if (!funcs.has(event)) { funcs.set(event, []); } eventFuncs = funcs.get(event); if (eventFuncs.indexOf(fn) > -1) { eventFuncs.splice(eventFuncs.indexOf(fn), 1); return true; } return false; } return { bind: bind, unbind: unbind } })(); var vuescroll = new Object; vuescroll.install = function (Vue, options) { options = options || {}; var SCROLL = 'scroll'; var THROTTLE = 'throttle'; var DEBOUNCE = 'debounce'; var VALID_ARGS = [THROTTLE, DEBOUNCE]; function bindValue (el, value, arg) { var fn, opt = Object.assign({}, options); if (isObject(value) || isFunction(value)) { fn = value; if (VALID_ARGS.indexOf(arg) > -1) { fn = value.fn; if (arg === THROTTLE) { opt = { throttle: value.throttle}; } else if(arg === DEBOUNCE) { opt = { debounce: value.debounce}; } } try { dom.bind(el, SCROLL, fn, opt); } catch(err) { console.warn('Unexpected error happened when binding listener'); } } else { console.warn('Unexpected scroll properties'); } } function unbindValue (el, value, arg) { var fn; if (isObject(value) || isFunction(value)) { fn = value; if (VALID_ARGS.indexOf(arg) > -1) { fn = value.fn; } dom.unbind(el, SCROLL, fn); } } Vue.directive(SCROLL, { bind: function(el, binding, vnode, oldVnode) { bindValue(el, binding.value, binding.arg); }, inserted: function(el, binding) { }, update: function(el, binding) { if (binding.value === binding.oldValue) { return; } bindValue(el, binding.value, binding.arg); unbindValue(el, binding.oldValue, binding.arg); }, unbind: function(el, binding) { unbindValue(el, binding.value, binding.arg); } }); }; return vuescroll; })));