/*! * Vue-Lazyload.js v1.3.5 * (c) 2023 Awe * Released under the MIT License. */ function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var assignSymbols$1 = createCommonjsModule(function (module) { var toString = Object.prototype.toString; var isEnumerable = Object.prototype.propertyIsEnumerable; var getSymbols = Object.getOwnPropertySymbols; module.exports = function (target) { for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } if (!isObject(target)) { throw new TypeError('expected the first argument to be an object'); } if (args.length === 0 || typeof Symbol !== 'function' || typeof getSymbols !== 'function') { return target; } var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = args[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var arg = _step.value; var names = getSymbols(arg); var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = names[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var key = _step2.value; if (isEnumerable.call(arg, key)) { target[key] = arg[key]; } } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return target; }; function isObject(val) { return typeof val === 'function' || toString.call(val) === '[object Object]' || Array.isArray(val); } }); var assignSymbols$2 = /*#__PURE__*/Object.freeze({ __proto__: null, 'default': assignSymbols$1, __moduleExports: assignSymbols$1 }); var assignSymbols = ( assignSymbols$2 && assignSymbols$1 ) || assignSymbols$2; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var assignDeep = createCommonjsModule(function (module) { var toString = Object.prototype.toString; var isValidKey = function isValidKey(key) { return key !== '__proto__' && key !== 'constructor' && key !== 'prototype'; }; var assign = module.exports = function (target) { for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } var i = 0; if (isPrimitive(target)) target = args[i++]; if (!target) target = {}; for (; i < args.length; i++) { if (isObject(args[i])) { var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = Object.keys(args[i])[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var key = _step.value; if (isValidKey(key)) { if (isObject(target[key]) && isObject(args[i][key])) { assign(target[key], args[i][key]); } else { target[key] = args[i][key]; } } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } assignSymbols(target, args[i]); } } return target; }; function isObject(val) { return typeof val === 'function' || toString.call(val) === '[object Object]'; } function isPrimitive(val) { return (typeof val === 'undefined' ? 'undefined' : _typeof(val)) === 'object' ? val === null : typeof val !== 'function'; } }); var inBrowser = typeof window !== 'undefined' && window !== null; var hasIntersectionObserver = checkIntersectionObserver(); function checkIntersectionObserver() { if (inBrowser && 'IntersectionObserver' in window && 'IntersectionObserverEntry' in window && 'intersectionRatio' in window.IntersectionObserverEntry.prototype) { // Minimal polyfill for Edge 15's lack of `isIntersecting` // See: https://github.com/w3c/IntersectionObserver/issues/211 if (!('isIntersecting' in window.IntersectionObserverEntry.prototype)) { Object.defineProperty(window.IntersectionObserverEntry.prototype, 'isIntersecting', { get: function get() { return this.intersectionRatio > 0; } }); } return true; } return false; } var modeType = { event: 'event', observer: 'observer' // CustomEvent polyfill for IE };var CustomEvent = function () { if (!inBrowser) return; // not IE if (typeof window.CustomEvent === 'function') return window.CustomEvent; function CustomEvent(event, params) { params = params || { bubbles: false, cancelable: false, detail: undefined }; var evt = document.createEvent('CustomEvent'); evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); return evt; } CustomEvent.prototype = window.Event.prototype; return CustomEvent; }(); function remove(arr, item) { if (!arr.length) return; var index = arr.indexOf(item); if (index > -1) return arr.splice(index, 1); } function some(arr, fn) { var has = false; for (var i = 0, len = arr.length; i < len; i++) { if (fn(arr[i])) { has = true; break; } } return has; } function getBestSelectionFromSrcset(el, scale) { if (el.tagName !== 'IMG' || !el.getAttribute('data-srcset')) return; var options = el.getAttribute('data-srcset'); var result = []; var container = el.parentNode; var containerWidth = container.offsetWidth * scale; var spaceIndex = void 0; var tmpSrc = void 0; var tmpWidth = void 0; options = options.trim().split(','); options.map(function (item) { item = item.trim(); spaceIndex = item.lastIndexOf(' '); if (spaceIndex === -1) { tmpSrc = item; tmpWidth = 999998; } else { tmpSrc = item.substr(0, spaceIndex); tmpWidth = parseInt(item.substr(spaceIndex + 1, item.length - spaceIndex - 2), 10); } result.push([tmpWidth, tmpSrc]); }); result.sort(function (a, b) { if (a[0] < b[0]) { return 1; } if (a[0] > b[0]) { return -1; } if (a[0] === b[0]) { if (b[1].indexOf('.webp', b[1].length - 5) !== -1) { return 1; } if (a[1].indexOf('.webp', a[1].length - 5) !== -1) { return -1; } } return 0; }); var bestSelectedSrc = ''; var tmpOption = void 0; for (var i = 0; i < result.length; i++) { tmpOption = result[i]; bestSelectedSrc = tmpOption[1]; var next = result[i + 1]; if (next && next[0] < containerWidth) { bestSelectedSrc = tmpOption[1]; break; } else if (!next) { bestSelectedSrc = tmpOption[1]; break; } } return bestSelectedSrc; } function find(arr, fn) { var item = void 0; for (var i = 0, len = arr.length; i < len; i++) { if (fn(arr[i])) { item = arr[i]; break; } } return item; } var getDPR = function getDPR() { var scale = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; return inBrowser ? window.devicePixelRatio || scale : scale; }; function supportWebp() { if (!inBrowser) return false; var support = true; try { var elem = document.createElement('canvas'); if (elem.getContext && elem.getContext('2d')) { support = elem.toDataURL('image/webp').indexOf('data:image/webp') === 0; } } catch (err) { support = false; } return support; } function throttle(action, delay) { var timeout = null; var movement = null; var lastRun = 0; var needRun = false; return function () { needRun = true; if (timeout) { return; } var elapsed = Date.now() - lastRun; var context = this; var args = arguments; var runCallback = function runCallback() { lastRun = Date.now(); timeout = false; action.apply(context, args); }; if (elapsed >= delay) { runCallback(); } else { timeout = setTimeout(runCallback, delay); } if (needRun) { clearTimeout(movement); movement = setTimeout(runCallback, 2 * delay); } }; } function testSupportsPassive() { if (!inBrowser) return; var support = false; try { var opts = Object.defineProperty({}, 'passive', { get: function get() { support = true; } }); window.addEventListener('test', null, opts); } catch (e) {} return support; } var supportsPassive = testSupportsPassive(); var _ = { on: function on(el, type, func) { var capture = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; if (supportsPassive) { el.addEventListener(type, func, { capture: capture, passive: true }); } else { el.addEventListener(type, func, capture); } }, off: function off(el, type, func) { var capture = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; el.removeEventListener(type, func, capture); } }; var loadImageAsync = function loadImageAsync(item, resolve, reject) { var image = new Image(); if (!item || !item.src) { var err = new Error('image src is required'); return reject(err); } image.src = item.src; if (item.cors) { image.crossOrigin = item.cors; } image.onload = function () { resolve({ naturalHeight: image.naturalHeight, naturalWidth: image.naturalWidth, src: image.src }); }; image.onerror = function (e) { reject(e); }; }; var style = function style(el, prop) { return typeof getComputedStyle !== 'undefined' ? getComputedStyle(el, null).getPropertyValue(prop) : el.style[prop]; }; var overflow = function overflow(el) { return style(el, 'overflow') + style(el, 'overflow-y') + style(el, 'overflow-x'); }; var scrollParent = function scrollParent(el) { if (!inBrowser) return; if (!(el instanceof HTMLElement)) { return window; } var parent = el; while (parent) { if (parent === document.body || parent === document.documentElement) { break; } if (!parent.parentNode) { break; } if (/(scroll|auto)/.test(overflow(parent))) { return parent; } parent = parent.parentNode; } return window; }; function isObject(obj) { return obj !== null && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object'; } function ObjectKeys(obj) { if (!(obj instanceof Object)) return []; if (Object.keys) { return Object.keys(obj); } else { var keys = []; for (var key in obj) { if (obj.hasOwnProperty(key)) { keys.push(key); } } return keys; } } function ArrayFrom(arrLike) { var len = arrLike.length; var list = []; for (var i = 0; i < len; i++) { list.push(arrLike[i]); } return list; } function noop() {} var ImageCache = function () { function ImageCache(_ref) { var max = _ref.max; classCallCheck(this, ImageCache); this.options = { max: max || 100 }; this._caches = []; } createClass(ImageCache, [{ key: 'has', value: function has(key) { return this._caches.indexOf(key) > -1; } }, { key: 'add', value: function add(key) { if (this.has(key)) return; this._caches.push(key); if (this._caches.length > this.options.max) { this.free(); } } }, { key: 'free', value: function free() { this._caches.shift(); } }]); return ImageCache; }(); // el: { // state, // src, // error, // loading // } var ReactiveListener = function () { function ReactiveListener(_ref) { var el = _ref.el, src = _ref.src, error = _ref.error, loading = _ref.loading, bindType = _ref.bindType, $parent = _ref.$parent, options = _ref.options, cors = _ref.cors, elRenderer = _ref.elRenderer, imageCache = _ref.imageCache; classCallCheck(this, ReactiveListener); this.el = el; this.src = src; this.error = error; this.loading = loading; this.bindType = bindType; this.attempt = 0; this.cors = cors; this.naturalHeight = 0; this.naturalWidth = 0; this.options = options; this.rect = null; this.$parent = $parent; this.elRenderer = elRenderer; this._imageCache = imageCache; this.performanceData = { init: Date.now(), loadStart: 0, loadEnd: 0 }; this.filter(); this.initState(); this.render('loading', false); } /* * init listener state * @return */ createClass(ReactiveListener, [{ key: 'initState', value: function initState() { if ('dataset' in this.el) { this.el.dataset.src = this.src; } else { this.el.setAttribute('data-src', this.src); } this.state = { loading: false, error: false, loaded: false, rendered: false }; } /* * record performance * @return */ }, { key: 'record', value: function record(event) { this.performanceData[event] = Date.now(); } /* * update image listener data * @param {String} image uri * @param {String} loading image uri * @param {String} error image uri * @return */ }, { key: 'update', value: function update(_ref2) { var src = _ref2.src, loading = _ref2.loading, error = _ref2.error; var oldSrc = this.src; this.src = src; this.loading = loading; this.error = error; this.filter(); if (oldSrc !== this.src) { this.attempt = 0; this.initState(); } } /* * get el node rect * @return */ }, { key: 'getRect', value: function getRect() { this.rect = this.el.getBoundingClientRect(); } /* * check el is in view * @return {Boolean} el is in view */ }, { key: 'checkInView', value: function checkInView() { this.getRect(); return this.rect.top < window.innerHeight * this.options.preLoad && this.rect.bottom > this.options.preLoadTop && this.rect.left < window.innerWidth * this.options.preLoad && this.rect.right > 0; } /* * listener filter */ }, { key: 'filter', value: function filter() { var _this = this; ObjectKeys(this.options.filter).map(function (key) { _this.options.filter[key](_this, _this.options); }); } /* * render loading first * @params cb:Function * @return */ }, { key: 'renderLoading', value: function renderLoading(cb) { var _this2 = this; this.state.loading = true; loadImageAsync({ src: this.loading, cors: this.cors }, function (data) { _this2.render('loading', false); _this2.state.loading = false; cb(); }, function () { // handler `loading image` load failed cb(); _this2.state.loading = false; if (!_this2.options.silent) console.warn('VueLazyload log: load failed with loading image(' + _this2.loading + ')'); }); } /* * try load image and render it * @return */ }, { key: 'load', value: function load() { var _this3 = this; var onFinish = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : noop; if (this.attempt > this.options.attempt - 1 && this.state.error) { if (!this.options.silent) console.log('VueLazyload log: ' + this.src + ' tried too more than ' + this.options.attempt + ' times'); onFinish(); return; } if (this.state.rendered && this.state.loaded) return; if (this._imageCache.has(this.src)) { this.state.loaded = true; this.render('loaded', true); this.state.rendered = true; return onFinish(); } this.renderLoading(function () { _this3.attempt++; _this3.options.adapter['beforeLoad'] && _this3.options.adapter['beforeLoad'](_this3, _this3.options); _this3.record('loadStart'); loadImageAsync({ src: _this3.src, cors: _this3.cors }, function (data) { _this3.naturalHeight = data.naturalHeight; _this3.naturalWidth = data.naturalWidth; _this3.state.loaded = true; _this3.state.error = false; _this3.record('loadEnd'); _this3.render('loaded', false); _this3.state.rendered = true; _this3._imageCache.add(_this3.src); onFinish(); }, function (err) { !_this3.options.silent && console.error(err); _this3.state.error = true; _this3.state.loaded = false; _this3.render('error', false); }); }); } /* * render image * @param {String} state to render // ['loading', 'src', 'error'] * @param {String} is form cache * @return */ }, { key: 'render', value: function render(state, cache) { this.elRenderer(this, state, cache); } /* * output performance data * @return {Object} performance data */ }, { key: 'performance', value: function performance() { var state = 'loading'; var time = 0; if (this.state.loaded) { state = 'loaded'; time = (this.performanceData.loadEnd - this.performanceData.loadStart) / 1000; } if (this.state.error) state = 'error'; return { src: this.src, state: state, time: time }; } /* * $destroy * @return */ }, { key: '$destroy', value: function $destroy() { this.el = null; this.src = null; this.error = null; this.loading = null; this.bindType = null; this.attempt = 0; } }]); return ReactiveListener; }(); var DEFAULT_URL = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'; var DEFAULT_EVENTS = ['scroll', 'wheel', 'mousewheel', 'resize', 'animationend', 'transitionend', 'touchmove']; var DEFAULT_OBSERVER_OPTIONS = { rootMargin: '0px', threshold: 0 }; function Lazy(Vue) { return function () { function Lazy(_ref) { var preLoad = _ref.preLoad, error = _ref.error, throttleWait = _ref.throttleWait, preLoadTop = _ref.preLoadTop, dispatchEvent = _ref.dispatchEvent, loading = _ref.loading, attempt = _ref.attempt, _ref$silent = _ref.silent, silent = _ref$silent === undefined ? true : _ref$silent, scale = _ref.scale, listenEvents = _ref.listenEvents; _ref.hasbind; var filter = _ref.filter, adapter = _ref.adapter, observer = _ref.observer, observerOptions = _ref.observerOptions; classCallCheck(this, Lazy); this.version = '"1.3.5"'; this.mode = modeType.event; this.ListenerQueue = []; this.TargetIndex = 0; this.TargetQueue = []; this.options = { silent: silent, dispatchEvent: !!dispatchEvent, throttleWait: throttleWait || 200, preLoad: preLoad || 1.3, preLoadTop: preLoadTop || 0, error: error || DEFAULT_URL, loading: loading || DEFAULT_URL, attempt: attempt || 3, scale: scale || getDPR(scale), ListenEvents: listenEvents || DEFAULT_EVENTS, hasbind: false, supportWebp: supportWebp(), filter: filter || {}, adapter: adapter || {}, observer: !!observer, observerOptions: observerOptions || DEFAULT_OBSERVER_OPTIONS }; this._initEvent(); this._imageCache = new ImageCache({ max: 200 }); this.lazyLoadHandler = throttle(this._lazyLoadHandler.bind(this), this.options.throttleWait); this.setMode(this.options.observer ? modeType.observer : modeType.event); } /** * update config * @param {Object} config params * @return */ createClass(Lazy, [{ key: 'config', value: function config() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; assignDeep(this.options, options); } /** * output listener's load performance * @return {Array} */ }, { key: 'performance', value: function performance() { var list = []; this.ListenerQueue.map(function (item) { list.push(item.performance()); }); return list; } /* * add lazy component to queue * @param {Vue} vm lazy component instance * @return */ }, { key: 'addLazyBox', value: function addLazyBox(vm) { this.ListenerQueue.push(vm); if (inBrowser) { this._addListenerTarget(window); this._observer && this._observer.observe(vm.el); if (vm.$el && vm.$el.parentNode) { this._addListenerTarget(vm.$el.parentNode); } } } /* * add image listener to queue * @param {DOM} el * @param {object} binding vue directive binding * @param {vnode} vnode vue directive vnode * @return */ }, { key: 'add', value: function add(el, binding, vnode) { var _this = this; if (some(this.ListenerQueue, function (item) { return item.el === el; })) { this.update(el, binding); return Vue.nextTick(this.lazyLoadHandler); } var _valueFormatter2 = this._valueFormatter(binding.value), src = _valueFormatter2.src, loading = _valueFormatter2.loading, error = _valueFormatter2.error, cors = _valueFormatter2.cors; Vue.nextTick(function () { src = getBestSelectionFromSrcset(el, _this.options.scale) || src; _this._observer && _this._observer.observe(el); var container = Object.keys(binding.modifiers)[0]; var $parent = void 0; if (container) { $parent = vnode.context.$refs[container]; // if there is container passed in, try ref first, then fallback to getElementById to support the original usage $parent = $parent ? $parent.$el || $parent : document.getElementById(container); } if (!$parent) { $parent = scrollParent(el); } var newListener = new ReactiveListener({ bindType: binding.arg, $parent: $parent, el: el, loading: loading, error: error, src: src, cors: cors, elRenderer: _this._elRenderer.bind(_this), options: _this.options, imageCache: _this._imageCache }); _this.ListenerQueue.push(newListener); if (inBrowser) { _this._addListenerTarget(window); _this._addListenerTarget($parent); } _this.lazyLoadHandler(); Vue.nextTick(function () { return _this.lazyLoadHandler(); }); }); } /** * update image src * @param {DOM} el * @param {object} vue directive binding * @return */ }, { key: 'update', value: function update(el, binding, vnode) { var _this2 = this; var _valueFormatter3 = this._valueFormatter(binding.value), src = _valueFormatter3.src, loading = _valueFormatter3.loading, error = _valueFormatter3.error; src = getBestSelectionFromSrcset(el, this.options.scale) || src; var exist = find(this.ListenerQueue, function (item) { return item.el === el; }); if (!exist) { this.add(el, binding, vnode); } else { exist.update({ src: src, loading: loading, error: error }); } if (this._observer) { this._observer.unobserve(el); this._observer.observe(el); } this.lazyLoadHandler(); Vue.nextTick(function () { return _this2.lazyLoadHandler(); }); } /** * remove listener form list * @param {DOM} el * @return */ }, { key: 'remove', value: function remove$1(el) { if (!el) return; this._observer && this._observer.unobserve(el); var existItem = find(this.ListenerQueue, function (item) { return item.el === el; }); if (existItem) { this._removeListenerTarget(existItem.$parent); this._removeListenerTarget(window); remove(this.ListenerQueue, existItem); existItem.$destroy(); } } /* * remove lazy components form list * @param {Vue} vm Vue instance * @return */ }, { key: 'removeComponent', value: function removeComponent(vm) { if (!vm) return; remove(this.ListenerQueue, vm); this._observer && this._observer.unobserve(vm.el); if (vm.$parent && vm.$el.parentNode) { this._removeListenerTarget(vm.$el.parentNode); } this._removeListenerTarget(window); } }, { key: 'setMode', value: function setMode(mode) { var _this3 = this; if (!hasIntersectionObserver && mode === modeType.observer) { mode = modeType.event; } this.mode = mode; // event or observer if (mode === modeType.event) { if (this._observer) { this.ListenerQueue.forEach(function (listener) { _this3._observer.unobserve(listener.el); }); this._observer = null; } this.TargetQueue.forEach(function (target) { _this3._initListen(target.el, true); }); } else { this.TargetQueue.forEach(function (target) { _this3._initListen(target.el, false); }); this._initIntersectionObserver(); } } /* *** Private functions *** */ /* * add listener target * @param {DOM} el listener target * @return */ }, { key: '_addListenerTarget', value: function _addListenerTarget(el) { if (!el) return; var target = find(this.TargetQueue, function (target) { return target.el === el; }); if (!target) { target = { el: el, id: ++this.TargetIndex, childrenCount: 1, listened: true }; this.mode === modeType.event && this._initListen(target.el, true); this.TargetQueue.push(target); } else { target.childrenCount++; } return this.TargetIndex; } /* * remove listener target or reduce target childrenCount * @param {DOM} el or window * @return */ }, { key: '_removeListenerTarget', value: function _removeListenerTarget(el) { var _this4 = this; this.TargetQueue.forEach(function (target, index) { if (target.el === el) { target.childrenCount--; if (!target.childrenCount) { _this4._initListen(target.el, false); _this4.TargetQueue.splice(index, 1); target = null; } } }); } /* * add or remove eventlistener * @param {DOM} el DOM or Window * @param {boolean} start flag * @return */ }, { key: '_initListen', value: function _initListen(el, start) { var _this5 = this; this.options.ListenEvents.forEach(function (evt) { return _[start ? 'on' : 'off'](el, evt, _this5.lazyLoadHandler); }); } }, { key: '_initEvent', value: function _initEvent() { var _this6 = this; this.Event = { listeners: { loading: [], loaded: [], error: [] } }; this.$on = function (event, func) { if (!_this6.Event.listeners[event]) _this6.Event.listeners[event] = []; _this6.Event.listeners[event].push(func); }; this.$once = function (event, func) { var vm = _this6; function on() { vm.$off(event, on); func.apply(vm, arguments); } _this6.$on(event, on); }; this.$off = function (event, func) { if (!func) { if (!_this6.Event.listeners[event]) return; _this6.Event.listeners[event].length = 0; return; } remove(_this6.Event.listeners[event], func); }; this.$emit = function (event, context, inCache) { if (!_this6.Event.listeners[event]) return; _this6.Event.listeners[event].forEach(function (func) { return func(context, inCache); }); }; } /** * find nodes which in viewport and trigger load * @return */ }, { key: '_lazyLoadHandler', value: function _lazyLoadHandler() { var _this7 = this; var freeList = []; this.ListenerQueue.forEach(function (listener, index) { if (!listener.el || !listener.el.parentNode) { freeList.push(listener); } var catIn = listener.checkInView(); if (!catIn) return; listener.load(); }); freeList.forEach(function (item) { remove(_this7.ListenerQueue, item); item.$destroy(); }); } /** * init IntersectionObserver * set mode to observer * @return */ }, { key: '_initIntersectionObserver', value: function _initIntersectionObserver() { var _this8 = this; if (!hasIntersectionObserver) return; this._observer = new IntersectionObserver(this._observerHandler.bind(this), this.options.observerOptions); if (this.ListenerQueue.length) { this.ListenerQueue.forEach(function (listener) { _this8._observer.observe(listener.el); }); } } /** * init IntersectionObserver * @return */ }, { key: '_observerHandler', value: function _observerHandler(entries, observer) { var _this9 = this; entries.forEach(function (entry) { if (entry.isIntersecting) { _this9.ListenerQueue.forEach(function (listener) { if (listener.el === entry.target) { if (listener.state.loaded) return _this9._observer.unobserve(listener.el); listener.load(); } }); } }); } /** * set element attribute with image'url and state * @param {object} lazyload listener object * @param {string} state will be rendered * @param {bool} inCache is rendered from cache * @return */ }, { key: '_elRenderer', value: function _elRenderer(listener, state, cache) { if (!listener.el) return; var el = listener.el, bindType = listener.bindType; var src = void 0; switch (state) { case 'loading': src = listener.loading; break; case 'error': src = listener.error; break; default: src = listener.src; break; } if (bindType) { el.style[bindType] = 'url("' + src + '")'; } else if (el.getAttribute('src') !== src) { el.setAttribute('src', src); } el.setAttribute('lazy', state); this.$emit(state, listener, cache); this.options.adapter[state] && this.options.adapter[state](listener, this.options); if (this.options.dispatchEvent) { var event = new CustomEvent(state, { detail: listener }); el.dispatchEvent(event); } } /** * generate loading loaded error image url * @param {string} image's src * @return {object} image's loading, loaded, error url */ }, { key: '_valueFormatter', value: function _valueFormatter(value) { var src = value; var loading = this.options.loading; var error = this.options.error; // value is object if (isObject(value)) { if (!value.src && !this.options.silent) console.error('Vue Lazyload warning: miss src with ' + value); src = value.src; loading = value.loading || this.options.loading; error = value.error || this.options.error; } return { src: src, loading: loading, error: error }; } }]); return Lazy; }(); } Lazy.install = function (Vue) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var LazyClass = Lazy(Vue); var lazy = new LazyClass(options); var isVue2 = Vue.version.split('.')[0] === '2'; if (isVue2) { Vue.directive('lazy', { bind: lazy.add.bind(lazy), update: lazy.update.bind(lazy), componentUpdated: lazy.lazyLoadHandler.bind(lazy), unbind: lazy.remove.bind(lazy) }); } else { Vue.directive('lazy', { bind: lazy.lazyLoadHandler.bind(lazy), update: function update(newValue, oldValue) { assignDeep(this.vm.$refs, this.vm.$els); lazy.add(this.el, { modifiers: this.modifiers || {}, arg: this.arg, value: newValue, oldValue: oldValue }, { context: this.vm }); }, unbind: function unbind() { lazy.remove(this.el); } }); } }; var LazyComponent = function LazyComponent(lazy) { return { props: { tag: { type: String, default: 'div' } }, render: function render(h) { return h(this.tag, null, this.show ? this.$slots.default : null); }, data: function data() { return { el: null, state: { loaded: false }, rect: {}, show: false }; }, mounted: function mounted() { this.el = this.$el; lazy.addLazyBox(this); lazy.lazyLoadHandler(); }, beforeDestroy: function beforeDestroy() { lazy.removeComponent(this); }, methods: { getRect: function getRect() { this.rect = this.$el.getBoundingClientRect(); }, checkInView: function checkInView() { this.getRect(); return inBrowser && this.rect.top < window.innerHeight * lazy.options.preLoad && this.rect.bottom > 0 && this.rect.left < window.innerWidth * lazy.options.preLoad && this.rect.right > 0; }, load: function load() { this.show = true; this.state.loaded = true; this.$emit('show', this); }, destroy: function destroy() { return this.$destroy; } } }; }; LazyComponent.install = function (Vue) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var LazyClass = Lazy(Vue); var lazy = new LazyClass(options); Vue.component('lazy-component', LazyComponent(lazy)); }; var LazyContainerMananger = function () { function LazyContainerMananger(_ref) { var lazy = _ref.lazy; classCallCheck(this, LazyContainerMananger); this.lazy = lazy; lazy.lazyContainerMananger = this; this._queue = []; } createClass(LazyContainerMananger, [{ key: 'bind', value: function bind(el, binding, vnode) { var container = new LazyContainer({ el: el, binding: binding, vnode: vnode, lazy: this.lazy }); this._queue.push(container); } }, { key: 'update', value: function update(el, binding, vnode) { var container = find(this._queue, function (item) { return item.el === el; }); if (!container) return; container.update({ el: el, binding: binding, vnode: vnode }); } }, { key: 'unbind', value: function unbind(el, binding, vnode) { var container = find(this._queue, function (item) { return item.el === el; }); if (!container) return; container.clear(); remove(this._queue, container); } }]); return LazyContainerMananger; }(); var defaultOptions = { selector: 'img' }; var LazyContainer = function () { function LazyContainer(_ref2) { var el = _ref2.el, binding = _ref2.binding, vnode = _ref2.vnode, lazy = _ref2.lazy; classCallCheck(this, LazyContainer); this.el = null; this.vnode = vnode; this.binding = binding; this.options = {}; this.lazy = lazy; this._queue = []; this.update({ el: el, binding: binding }); } createClass(LazyContainer, [{ key: 'update', value: function update(_ref3) { var _this = this; var el = _ref3.el, binding = _ref3.binding; this.el = el; this.options = assignDeep({}, defaultOptions, binding.value); var imgs = this.getImgs(); imgs.forEach(function (el) { _this.lazy.add(el, assignDeep({}, _this.binding, { value: { src: 'dataset' in el ? el.dataset.src : el.getAttribute('data-src'), error: ('dataset' in el ? el.dataset.error : el.getAttribute('data-error')) || _this.options.error, loading: ('dataset' in el ? el.dataset.loading : el.getAttribute('data-loading')) || _this.options.loading } }), _this.vnode); }); } }, { key: 'getImgs', value: function getImgs() { return ArrayFrom(this.el.querySelectorAll(this.options.selector)); } }, { key: 'clear', value: function clear() { var _this2 = this; var imgs = this.getImgs(); imgs.forEach(function (el) { return _this2.lazy.remove(el); }); this.vnode = null; this.binding = null; this.lazy = null; } }]); return LazyContainer; }(); LazyContainer.install = function (Vue) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var LazyClass = Lazy(Vue); var lazy = new LazyClass(options); var lazyContainer = new LazyContainer({ lazy: lazy }); var isVue2 = Vue.version.split('.')[0] === '2'; if (isVue2) { Vue.directive('lazy-container', { bind: lazyContainer.bind.bind(lazyContainer), componentUpdated: lazyContainer.update.bind(lazyContainer), unbind: lazyContainer.unbind.bind(lazyContainer) }); } else { Vue.directive('lazy-container', { update: function update(newValue, oldValue) { lazyContainer.update(this.el, { modifiers: this.modifiers || {}, arg: this.arg, value: newValue, oldValue: oldValue }, { context: this.vm }); }, unbind: function unbind() { lazyContainer.unbind(this.el); } }); } }; var LazyImage = function LazyImage(lazyManager) { return { props: { src: [String, Object], tag: { type: String, default: 'img' } }, render: function render(h) { return h(this.tag, { attrs: { src: this.renderSrc } }, this.$slots.default); }, data: function data() { return { el: null, options: { src: '', error: '', loading: '', attempt: lazyManager.options.attempt }, state: { loaded: false, error: false, attempt: 0 }, rect: {}, renderSrc: '' }; }, watch: { src: function src() { this.init(); lazyManager.addLazyBox(this); lazyManager.lazyLoadHandler(); } }, created: function created() { this.init(); this.renderSrc = this.options.loading; }, mounted: function mounted() { this.el = this.$el; lazyManager.addLazyBox(this); lazyManager.lazyLoadHandler(); }, beforeDestroy: function beforeDestroy() { lazyManager.removeComponent(this); }, methods: { init: function init() { var _lazyManager$_valueFo = lazyManager._valueFormatter(this.src), src = _lazyManager$_valueFo.src, loading = _lazyManager$_valueFo.loading, error = _lazyManager$_valueFo.error; this.state.loaded = false; this.options.src = src; this.options.error = error; this.options.loading = loading; this.renderSrc = this.options.loading; }, getRect: function getRect() { this.rect = this.$el.getBoundingClientRect(); }, checkInView: function checkInView() { this.getRect(); return inBrowser && this.rect.top < window.innerHeight * lazyManager.options.preLoad && this.rect.bottom > 0 && this.rect.left < window.innerWidth * lazyManager.options.preLoad && this.rect.right > 0; }, load: function load() { var _this = this; var onFinish = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : noop; if (this.state.attempt > this.options.attempt - 1 && this.state.error) { if (!lazyManager.options.silent) console.log('VueLazyload log: ' + this.options.src + ' tried too more than ' + this.options.attempt + ' times'); onFinish(); return; } var src = this.options.src; loadImageAsync({ src: src }, function (_ref) { var src = _ref.src; _this.renderSrc = src; _this.state.loaded = true; }, function (e) { _this.state.attempt++; _this.renderSrc = _this.options.error; _this.state.error = true; }); } } }; }; LazyImage.install = function (Vue) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var LazyClass = Lazy(Vue); var lazy = new LazyClass(options); Vue.component('lazy-image', LazyImage(lazy)); }; var index = { /* * install function * @param {Vue} Vue * @param {object} options lazyload options */ install: function install(Vue) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var LazyClass = Lazy(Vue); var lazy = new LazyClass(options); var lazyContainer = new LazyContainerMananger({ lazy: lazy }); var isVue2 = Vue.version.split('.')[0] === '2'; Vue.prototype.$Lazyload = lazy; if (options.lazyComponent) { Vue.component('lazy-component', LazyComponent(lazy)); } if (options.lazyImage) { Vue.component('lazy-image', LazyImage(lazy)); } if (isVue2) { Vue.directive('lazy', { bind: lazy.add.bind(lazy), update: lazy.update.bind(lazy), componentUpdated: lazy.lazyLoadHandler.bind(lazy), unbind: lazy.remove.bind(lazy) }); Vue.directive('lazy-container', { bind: lazyContainer.bind.bind(lazyContainer), componentUpdated: lazyContainer.update.bind(lazyContainer), unbind: lazyContainer.unbind.bind(lazyContainer) }); } else { Vue.directive('lazy', { bind: lazy.lazyLoadHandler.bind(lazy), update: function update(newValue, oldValue) { assignDeep(this.vm.$refs, this.vm.$els); lazy.add(this.el, { modifiers: this.modifiers || {}, arg: this.arg, value: newValue, oldValue: oldValue }, { context: this.vm }); }, unbind: function unbind() { lazy.remove(this.el); } }); Vue.directive('lazy-container', { update: function update(newValue, oldValue) { lazyContainer.update(this.el, { modifiers: this.modifiers || {}, arg: this.arg, value: newValue, oldValue: oldValue }, { context: this.vm }); }, unbind: function unbind() { lazyContainer.unbind(this.el); } }); } } }; export { Lazy, LazyComponent, LazyContainerMananger as LazyContainer, LazyImage, index as default };