appear-polyfill
Version:
[](https://www.npmjs.com/package/rax-appear)
142 lines (137 loc) • 5.43 kB
JavaScript
;
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
};
}