UNPKG

appear-polyfill

Version:

[![npm](https://img.shields.io/npm/v/rax-appear.svg)](https://www.npmjs.com/package/rax-appear)

142 lines (137 loc) 5.43 kB
"use strict"; exports.__esModule = true; exports.IntersectionObserverMode = void 0; exports.createIntersectionObserver = createIntersectionObserver; exports.destroyAllIntersectionObserver = destroyAllIntersectionObserver; var _IntersectionObserver = _interopRequireDefault(require("./IntersectionObserver")); var _intersectionObserver; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // Shared intersectionObserver instance. var intersectionObserverMap = {}; var IntersectionObserverMode = { DEFAULT: 'default', PRE_APPEAR: 'pre' }; exports.IntersectionObserverMode = IntersectionObserverMode; var intersectionObserverHandleIMap = (_intersectionObserver = {}, _intersectionObserver[IntersectionObserverMode.DEFAULT] = handleIntersect, _intersectionObserver[IntersectionObserverMode.PRE_APPEAR] = handlePreIntersect, _intersectionObserver); var IntersectionObserver = function () { if (typeof window !== 'undefined' && 'IntersectionObserver' in window && 'IntersectionObserverEntry' in window && 'intersectionRatio' in window.IntersectionObserverEntry.prototype) { // features are natively supported return window.IntersectionObserver; } else { // polyfilled IntersectionObserver return _IntersectionObserver.default; } }(); function generateThreshold(number) { var thresholds = []; for (var index = 0; index < number; index++) { thresholds.push(index / number); } return thresholds; } var defaultCustomOptions = { threshold: generateThreshold(10), rootMargin: '0px 0px 0px 0px' }; /** suggest default & pre modes */ function createIntersectionObserver(type, customOptions) { if (customOptions === void 0) { customOptions = defaultCustomOptions; } var _customOptions = customOptions, threshold = _customOptions.threshold, preAppear = _customOptions.preAppear; var options = { root: null, rootMargin: type === IntersectionObserverMode.PRE_APPEAR ? preAppear : defaultCustomOptions.rootMargin, threshold: threshold != null ? threshold : defaultCustomOptions.threshold }; intersectionObserverMap[type] = new IntersectionObserver(intersectionObserverHandleIMap[type], options); return _observerElement(type); } function destroyAllIntersectionObserver() { (Object.keys(intersectionObserverMap) || []).forEach(function (key) { var current = intersectionObserverMap[key]; if (current) { current.disconnect(); } }); intersectionObserverMap = {}; } function _observerElement(type) { return function (element) { if (!intersectionObserverMap[type]) createIntersectionObserver(); if (element === document) element = document.documentElement; intersectionObserverMap[type].observe(element); }; } function handleIntersect(entries) { entries.forEach(function (entry) { var target = entry.target, boundingClientRect = entry.boundingClientRect, intersectionRatio = entry.intersectionRatio; var _getElementY = getElementY(target, boundingClientRect), currentY = _getElementY.currentY, beforeY = _getElementY.beforeY; // is in view if (intersectionRatio > 0.01 && !isTrue(target.getAttribute('data-appeared')) && !appearOnce(target, 'appear')) { target.setAttribute('data-appeared', 'true'); target.setAttribute('data-has-appeared', 'true'); target.dispatchEvent(createEvent('appear', { direction: currentY > beforeY ? 'up' : 'down' })); } else if (intersectionRatio === 0 && isTrue(target.getAttribute('data-appeared')) && !appearOnce(target, 'disappear')) { target.setAttribute('data-appeared', 'false'); target.setAttribute('data-has-disappeared', 'true'); target.dispatchEvent(createEvent('disappear', { direction: currentY > beforeY ? 'up' : 'down' })); } target.setAttribute('data-before-current-y', currentY); }); } function handlePreIntersect(entries) { entries.forEach(function (entry) { var target = entry.target, boundingClientRect = entry.boundingClientRect, intersectionRatio = entry.intersectionRatio; var _getElementY2 = getElementY(target, boundingClientRect), currentY = _getElementY2.currentY, beforeY = _getElementY2.beforeY; // is in view if (intersectionRatio > 0.01 && !isTrue(target.getAttribute('data-pre-appeared')) && !appearOnce(target, 'appear')) { target.setAttribute('data-pre-appeared', 'true'); target.dispatchEvent(createEvent('preappear', { direction: currentY > beforeY ? 'up' : 'down' })); } }); } /** * need appear again when node has isonce or data-once */ function appearOnce(node, type) { var isOnce = isTrue(node.getAttribute('isonce')) || isTrue(node.getAttribute('data-once')); var appearType = type === 'appear' ? 'data-has-appeared' : 'data-has-disappeared'; return isOnce && isTrue(node.getAttribute(appearType)); } function isTrue(flag) { return flag && flag !== 'false'; } function createEvent(eventName, data) { return new CustomEvent(eventName, { bubbles: false, cancelable: true, detail: data }); } function getElementY(target, boundingClientRect) { // pollfill doesn't have top attribute var currentY = boundingClientRect.y || boundingClientRect.top; var beforeY = parseInt(target.getAttribute('data-before-current-y')) || currentY; return { currentY: currentY, beforeY: beforeY }; }