Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@fastkit/body-scroll-lock

Package Overview
Dependencies
Maintainers
1
Versions
204
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fastkit/body-scroll-lock - npm Package Compare versions

Comparing version 0.6.10 to 0.6.11

183

dist/body-scroll-lock.cjs.js

@@ -5,10 +5,187 @@ 'use strict';

var helpers = require('@fastkit/helpers');
const isIosDevice = helpers.IN_WINDOW &&
!!window.navigator &&
!!window.navigator.platform &&
/iP(ad|hone|od)/.test(window.navigator.platform);
let locks = [];
let documentListenerAdded = false;
let initialClientY = -1;
let previousBodyOverflowSetting;
let previousBodyPaddingRight;
// returns true if `el` should be allowed to receive touchmove events.
const allowTouchMove = (el) => locks.some((lock) => {
if (lock.options.allowTouchMove && lock.options.allowTouchMove(el)) {
return true;
}
return false;
});
const preventDefault = (rawEvent) => {
const e = rawEvent || window.event;
// For the case whereby consumers adds a touchmove event listener to document.
// Recall that we do document.addEventListener('touchmove', preventDefault, { passive: false })
// in disableBodyScroll - so if we provide this opportunity to allowTouchMove, then
// the touchmove event on document will break.
if (allowTouchMove(e.target)) {
return true;
}
// Do not prevent if the event has more than one touch (usually meaning this is a multi touch gesture like pinch to zoom).
if (e.touches.length > 1)
return true;
if (e.preventDefault)
e.preventDefault();
return false;
};
const setOverflowHidden = (options) => {
// Setting overflow on body/documentElement synchronously in Desktop Safari slows down
// the responsiveness for some reason. Setting within a setTimeout fixes this.
setTimeout(() => {
// If previousBodyPaddingRight is already set, don't set it again.
if (previousBodyPaddingRight === undefined) {
const reserveScrollBarGap = !!options && options.reserveScrollBarGap === true;
const scrollBarGap = window.innerWidth - document.documentElement.clientWidth;
if (reserveScrollBarGap && scrollBarGap > 0) {
previousBodyPaddingRight = document.body.style.paddingRight;
document.body.style.paddingRight = `${scrollBarGap}px`;
}
}
// If previousBodyOverflowSetting is already set, don't set it again.
if (previousBodyOverflowSetting === undefined) {
previousBodyOverflowSetting = document.body.style.overflow;
document.body.style.overflow = 'hidden';
}
});
};
const restoreOverflowSetting = () => {
// Setting overflow on body/documentElement synchronously in Desktop Safari slows down
// the responsiveness for some reason. Setting within a setTimeout fixes this.
setTimeout(() => {
if (previousBodyPaddingRight !== undefined) {
document.body.style.paddingRight = previousBodyPaddingRight;
// Restore previousBodyPaddingRight to undefined so setOverflowHidden knows it
// can be set again.
previousBodyPaddingRight = undefined;
}
if (previousBodyOverflowSetting !== undefined) {
document.body.style.overflow = previousBodyOverflowSetting;
// Restore previousBodyOverflowSetting to undefined
// so setOverflowHidden knows it can be set again.
previousBodyOverflowSetting = undefined;
}
});
};
// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Problems_and_solutions
const isTargetElementTotallyScrolled = (targetElement) => targetElement
? targetElement.scrollHeight - targetElement.scrollTop <=
targetElement.clientHeight
: false;
const handleScroll = (event, targetElement) => {
const clientY = event.targetTouches[0].clientY - initialClientY;
if (allowTouchMove(event.target)) {
return false;
}
if (targetElement && targetElement.scrollTop === 0 && clientY > 0) {
// element is at the top of its scroll.
return preventDefault(event);
}
if (isTargetElementTotallyScrolled(targetElement) && clientY < 0) {
// element is at the top of its scroll.
return preventDefault(event);
}
event.stopPropagation();
return true;
};
const disableBodyScroll = (targetElement, options) => {
return;
if (!helpers.IN_WINDOW)
return;
if (isIosDevice) {
// targetElement must be provided, and disableBodyScroll must not have been
// called on this targetElement before.
if (!targetElement) {
// eslint-disable-next-line no-console
console.error('disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.');
return;
}
if (targetElement &&
!locks.some((lock) => lock.targetElement === targetElement)) {
const lock = {
targetElement,
options: options || {},
};
locks = [...locks, lock];
targetElement.ontouchstart = (event) => {
if (event.targetTouches.length === 1) {
// detect single touch.
initialClientY = event.targetTouches[0].clientY;
}
};
targetElement.ontouchmove = (event) => {
if (event.targetTouches.length === 1) {
// detect single touch.
handleScroll(event, targetElement);
}
};
if (!documentListenerAdded) {
document.addEventListener('touchmove', preventDefault, {
passive: false,
});
documentListenerAdded = true;
}
}
}
else {
setOverflowHidden(options);
const lock = {
targetElement,
options: options || {},
};
locks = [...locks, lock];
}
};
const clearAllBodyScrollLocks = () => {
return;
if (!helpers.IN_WINDOW)
return;
if (isIosDevice) {
// Clear all locks ontouchstart/ontouchmove handlers, and the references.
locks.forEach((lock) => {
lock.targetElement.ontouchstart = null;
lock.targetElement.ontouchmove = null;
});
if (documentListenerAdded) {
document.removeEventListener('touchmove', preventDefault, { passive: false });
documentListenerAdded = false;
}
locks = [];
// Reset initial clientY.
initialClientY = -1;
}
else {
restoreOverflowSetting();
locks = [];
}
};
const enableBodyScroll = (targetElement) => {
return;
if (!helpers.IN_WINDOW)
return;
if (isIosDevice) {
if (!targetElement) {
// eslint-disable-next-line no-console
console.error('enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices.');
return;
}
targetElement.ontouchstart = null;
targetElement.ontouchmove = null;
locks = locks.filter((lock) => lock.targetElement !== targetElement);
if (documentListenerAdded && locks.length === 0) {
document.removeEventListener('touchmove', preventDefault, { passive: false });
documentListenerAdded = false;
}
}
else {
locks = locks.filter((lock) => lock.targetElement !== targetElement);
if (!locks.length) {
restoreOverflowSetting();
}
}
};

@@ -15,0 +192,0 @@

@@ -5,10 +5,187 @@ 'use strict';

var helpers = require('@fastkit/helpers');
const isIosDevice = helpers.IN_WINDOW &&
!!window.navigator &&
!!window.navigator.platform &&
/iP(ad|hone|od)/.test(window.navigator.platform);
let locks = [];
let documentListenerAdded = false;
let initialClientY = -1;
let previousBodyOverflowSetting;
let previousBodyPaddingRight;
// returns true if `el` should be allowed to receive touchmove events.
const allowTouchMove = (el) => locks.some((lock) => {
if (lock.options.allowTouchMove && lock.options.allowTouchMove(el)) {
return true;
}
return false;
});
const preventDefault = (rawEvent) => {
const e = rawEvent || window.event;
// For the case whereby consumers adds a touchmove event listener to document.
// Recall that we do document.addEventListener('touchmove', preventDefault, { passive: false })
// in disableBodyScroll - so if we provide this opportunity to allowTouchMove, then
// the touchmove event on document will break.
if (allowTouchMove(e.target)) {
return true;
}
// Do not prevent if the event has more than one touch (usually meaning this is a multi touch gesture like pinch to zoom).
if (e.touches.length > 1)
return true;
if (e.preventDefault)
e.preventDefault();
return false;
};
const setOverflowHidden = (options) => {
// Setting overflow on body/documentElement synchronously in Desktop Safari slows down
// the responsiveness for some reason. Setting within a setTimeout fixes this.
setTimeout(() => {
// If previousBodyPaddingRight is already set, don't set it again.
if (previousBodyPaddingRight === undefined) {
const reserveScrollBarGap = !!options && options.reserveScrollBarGap === true;
const scrollBarGap = window.innerWidth - document.documentElement.clientWidth;
if (reserveScrollBarGap && scrollBarGap > 0) {
previousBodyPaddingRight = document.body.style.paddingRight;
document.body.style.paddingRight = `${scrollBarGap}px`;
}
}
// If previousBodyOverflowSetting is already set, don't set it again.
if (previousBodyOverflowSetting === undefined) {
previousBodyOverflowSetting = document.body.style.overflow;
document.body.style.overflow = 'hidden';
}
});
};
const restoreOverflowSetting = () => {
// Setting overflow on body/documentElement synchronously in Desktop Safari slows down
// the responsiveness for some reason. Setting within a setTimeout fixes this.
setTimeout(() => {
if (previousBodyPaddingRight !== undefined) {
document.body.style.paddingRight = previousBodyPaddingRight;
// Restore previousBodyPaddingRight to undefined so setOverflowHidden knows it
// can be set again.
previousBodyPaddingRight = undefined;
}
if (previousBodyOverflowSetting !== undefined) {
document.body.style.overflow = previousBodyOverflowSetting;
// Restore previousBodyOverflowSetting to undefined
// so setOverflowHidden knows it can be set again.
previousBodyOverflowSetting = undefined;
}
});
};
// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Problems_and_solutions
const isTargetElementTotallyScrolled = (targetElement) => targetElement
? targetElement.scrollHeight - targetElement.scrollTop <=
targetElement.clientHeight
: false;
const handleScroll = (event, targetElement) => {
const clientY = event.targetTouches[0].clientY - initialClientY;
if (allowTouchMove(event.target)) {
return false;
}
if (targetElement && targetElement.scrollTop === 0 && clientY > 0) {
// element is at the top of its scroll.
return preventDefault(event);
}
if (isTargetElementTotallyScrolled(targetElement) && clientY < 0) {
// element is at the top of its scroll.
return preventDefault(event);
}
event.stopPropagation();
return true;
};
const disableBodyScroll = (targetElement, options) => {
return;
if (!helpers.IN_WINDOW)
return;
if (isIosDevice) {
// targetElement must be provided, and disableBodyScroll must not have been
// called on this targetElement before.
if (!targetElement) {
// eslint-disable-next-line no-console
console.error('disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.');
return;
}
if (targetElement &&
!locks.some((lock) => lock.targetElement === targetElement)) {
const lock = {
targetElement,
options: options || {},
};
locks = [...locks, lock];
targetElement.ontouchstart = (event) => {
if (event.targetTouches.length === 1) {
// detect single touch.
initialClientY = event.targetTouches[0].clientY;
}
};
targetElement.ontouchmove = (event) => {
if (event.targetTouches.length === 1) {
// detect single touch.
handleScroll(event, targetElement);
}
};
if (!documentListenerAdded) {
document.addEventListener('touchmove', preventDefault, {
passive: false,
});
documentListenerAdded = true;
}
}
}
else {
setOverflowHidden(options);
const lock = {
targetElement,
options: options || {},
};
locks = [...locks, lock];
}
};
const clearAllBodyScrollLocks = () => {
return;
if (!helpers.IN_WINDOW)
return;
if (isIosDevice) {
// Clear all locks ontouchstart/ontouchmove handlers, and the references.
locks.forEach((lock) => {
lock.targetElement.ontouchstart = null;
lock.targetElement.ontouchmove = null;
});
if (documentListenerAdded) {
document.removeEventListener('touchmove', preventDefault, { passive: false });
documentListenerAdded = false;
}
locks = [];
// Reset initial clientY.
initialClientY = -1;
}
else {
restoreOverflowSetting();
locks = [];
}
};
const enableBodyScroll = (targetElement) => {
return;
if (!helpers.IN_WINDOW)
return;
if (isIosDevice) {
if (!targetElement) {
// eslint-disable-next-line no-console
console.error('enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices.');
return;
}
targetElement.ontouchstart = null;
targetElement.ontouchmove = null;
locks = locks.filter((lock) => lock.targetElement !== targetElement);
if (documentListenerAdded && locks.length === 0) {
document.removeEventListener('touchmove', preventDefault, { passive: false });
documentListenerAdded = false;
}
}
else {
locks = locks.filter((lock) => lock.targetElement !== targetElement);
if (!locks.length) {
restoreOverflowSetting();
}
}
};

@@ -15,0 +192,0 @@

10

dist/body-scroll-lock.esm-bundler.js

@@ -1,2 +0,4 @@

const isIosDevice = (typeof document !== 'undefined') &&
import { IN_WINDOW } from '@fastkit/helpers';
const isIosDevice = IN_WINDOW &&
!!window.navigator &&

@@ -93,3 +95,3 @@ !!window.navigator.platform &&

const disableBodyScroll = (targetElement, options) => {
if (!(typeof document !== 'undefined'))
if (!IN_WINDOW)
return;

@@ -141,3 +143,3 @@ if (isIosDevice) {

const clearAllBodyScrollLocks = () => {
if (!(typeof document !== 'undefined'))
if (!IN_WINDOW)
return;

@@ -164,3 +166,3 @@ if (isIosDevice) {

const enableBodyScroll = (targetElement) => {
if (!(typeof document !== 'undefined'))
if (!IN_WINDOW)
return;

@@ -167,0 +169,0 @@ if (isIosDevice) {

{
"name": "@fastkit/body-scroll-lock",
"version": "0.6.10",
"version": "0.6.11",
"description": "@fastkit/body-scroll-lock",

@@ -26,4 +26,4 @@ "main": "index.js",

"dependencies": {
"@fastkit/tiny-logger": "0.6.10"
"@fastkit/tiny-logger": "0.6.11"
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc