Skip to content

Commit

Permalink
feat: add support for body lock on iOS
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich authored Jan 15, 2020
2 parents 2196af8 + 9f54379 commit d778408
Showing 1 changed file with 37 additions and 2 deletions.
39 changes: 37 additions & 2 deletions src/useLockBodyScroll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,33 @@ export function getClosestBody(el: Element | HTMLElement | HTMLIFrameElement | n
return getClosestBody((el as HTMLElement).offsetParent!);
}

function preventDefault(rawEvent: TouchEvent): boolean {
const e = rawEvent || window.event;
// 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;
}

export interface BodyInfoItem {
counter: number;
initialOverflow: CSSStyleDeclaration['overflow'];
}

const isIosDevice =
typeof window !== 'undefined' &&
window.navigator &&
window.navigator.platform &&
/iP(ad|hone|od)/.test(window.navigator.platform);

const bodies: Map<HTMLElement, BodyInfoItem> = new Map();

const doc: Document | undefined = typeof document === 'object' ? document : undefined;

let documentListenerAdded = false;

export default !doc
? function useLockBodyMock(_locked: boolean = true, _elementRef?: RefObject<HTMLElement>) {}
: function useLockBody(locked: boolean = true, elementRef?: RefObject<HTMLElement>) {
Expand All @@ -40,15 +58,32 @@ export default !doc
if (locked) {
if (!bodyInfo) {
bodies.set(body, { counter: 1, initialOverflow: body.style.overflow });
body.style.overflow = 'hidden';
if (isIosDevice) {
if (!documentListenerAdded) {
document.addEventListener('touchmove', preventDefault, { passive: false });

documentListenerAdded = true;
}
} else {
body.style.overflow = 'hidden';
}
} else {
bodies.set(body, { counter: bodyInfo.counter + 1, initialOverflow: bodyInfo.initialOverflow });
}
} else {
if (bodyInfo) {
if (bodyInfo.counter === 1) {
bodies.delete(body);
body.style.overflow = bodyInfo.initialOverflow;
if (isIosDevice) {
body.ontouchmove = null;

if (documentListenerAdded) {
document.removeEventListener('touchmove', preventDefault);
documentListenerAdded = false;
}
} else {
body.style.overflow = bodyInfo.initialOverflow;
}
} else {
bodies.set(body, { counter: bodyInfo.counter - 1, initialOverflow: bodyInfo.initialOverflow });
}
Expand Down

0 comments on commit d778408

Please sign in to comment.