Skip to content

Commit 07b81dc

Browse files
committed
Create SCROLL_LOCK_DISABLE_HORIZONTAL_ATTR attribute
1 parent 2410e03 commit 07b81dc

File tree

4 files changed

+36
-17
lines changed

4 files changed

+36
-17
lines changed

src/components/Filter/FilterInput.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
</button>
3838
<div
3939
:class="['filter__input-box-wrapper', { 'scrolling': isScrolling }]"
40-
v-bind="{[SCROLL_LOCK_DISABLE_ATTR]: true}"
40+
v-bind="{[SCROLL_LOCK_DISABLE_HORIZONTAL_ATTR]: true}"
4141
@scroll="handleScroll"
4242
>
4343
<TagList
@@ -129,7 +129,7 @@
129129
import ClearRoundedIcon from 'theme/components/Icons/ClearRoundedIcon.vue';
130130
import multipleSelection from 'docc-render/mixins/multipleSelection';
131131
import handleScrollbar from 'docc-render/mixins/handleScrollbar';
132-
import { SCROLL_LOCK_DISABLE_ATTR } from 'docc-render/utils/scroll-lock';
132+
import { SCROLL_LOCK_DISABLE_HORIZONTAL_ATTR } from 'docc-render/utils/scroll-lock';
133133
import FilterIcon from 'theme/components/Icons/FilterIcon.vue';
134134
import TagList from './TagList.vue';
135135
@@ -227,7 +227,7 @@ export default {
227227
SuggestedTagsId,
228228
AXinputProperties,
229229
showSuggestedTags: false,
230-
SCROLL_LOCK_DISABLE_ATTR,
230+
SCROLL_LOCK_DISABLE_HORIZONTAL_ATTR,
231231
};
232232
},
233233
computed: {

src/components/Filter/TagList.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
role="listbox"
2525
:aria-multiselectable="areTagsRemovable ? 'true' : 'false'"
2626
aria-orientation="horizontal"
27-
v-bind="{[SCROLL_LOCK_DISABLE_ATTR]: true}"
27+
v-bind="{[SCROLL_LOCK_DISABLE_HORIZONTAL_ATTR]: true}"
2828
@keydown.left.capture.prevent="focusPrev"
2929
@keydown.right.capture.prevent="focusNext"
3030
@keydown.up.capture.prevent="focusPrev"
@@ -62,7 +62,7 @@
6262
import { isSingleCharacter } from 'docc-render/utils/input-helper';
6363
import handleScrollbar from 'docc-render/mixins/handleScrollbar';
6464
import keyboardNavigation from 'docc-render/mixins/keyboardNavigation';
65-
import { SCROLL_LOCK_DISABLE_ATTR } from 'docc-render/utils/scroll-lock';
65+
import { SCROLL_LOCK_DISABLE_HORIZONTAL_ATTR } from 'docc-render/utils/scroll-lock';
6666
import Tag from './Tag.vue';
6767
6868
export default {
@@ -73,7 +73,7 @@ export default {
7373
],
7474
data() {
7575
return {
76-
SCROLL_LOCK_DISABLE_ATTR,
76+
SCROLL_LOCK_DISABLE_HORIZONTAL_ATTR,
7777
};
7878
},
7979
props: {

src/utils/scroll-lock.js

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ let isLocked = false;
1212
let initialClientY = -1;
1313
let initialClientX = -1;
1414
let scrolledClientY = 0;
15-
// Adds this attribute to an inner scrollable element to allow it to scroll
15+
// Adds this attribute to an vertical scrollable element to allow it to scroll
1616
export const SCROLL_LOCK_DISABLE_ATTR = 'data-scroll-lock-disable';
17+
// Adds this attribute to an horizontal scrollable element to allow it to scroll
18+
export const SCROLL_LOCK_DISABLE_HORIZONTAL_ATTR = 'data-scroll-lock-horizontal-disable';
1719

1820
const isIosDevice = () => window.navigator
1921
&& window.navigator.platform
@@ -74,19 +76,17 @@ function advancedUnlock(targetElement) {
7476
document.removeEventListener('touchmove', preventDefault);
7577
}
7678

77-
const isVerticalScroll = ({ scrollHeight, scrollWidth }) => scrollHeight > scrollWidth;
78-
7979
/**
8080
* Handles the scrolling of the targetElement
8181
* @param {TouchEvent} event
8282
* @param {HTMLElement} targetElement
8383
* @return {boolean}
8484
*/
85-
function handleScroll(event, target) {
85+
function handleScroll(event, target, isHorizontal) {
8686
const clientY = event.targetTouches[0].clientY - initialClientY;
8787
const clientX = event.targetTouches[0].clientX - initialClientX;
8888

89-
if (isVerticalScroll(target)) {
89+
if (!isHorizontal) {
9090
if (target.scrollTop === 0 && clientY > 0) {
9191
// element is at the top of its scroll.
9292
return preventDefault(event);
@@ -110,7 +110,7 @@ function handleScroll(event, target) {
110110
* Advanced scroll locking for iOS devices.
111111
* @param targetElement
112112
*/
113-
function advancedLock(targetElement) {
113+
function advancedLock(targetElement, isHorizontal = false) {
114114
// add a scroll listener to the body
115115
document.addEventListener('touchmove', preventDefault, { passive: false });
116116
if (!targetElement) return;
@@ -126,7 +126,7 @@ function advancedLock(targetElement) {
126126
targetElement.ontouchmove = (event) => {
127127
if (event.targetTouches.length === 1) {
128128
// detect single touch.
129-
handleScroll(event, targetElement);
129+
handleScroll(event, targetElement, isHorizontal);
130130
}
131131
};
132132
}
@@ -149,9 +149,12 @@ export default {
149149
} else {
150150
// lock everything but target element
151151
advancedLock(targetElement);
152-
// lock everything but disabled targets
152+
// lock everything but disabled targets with vertical scrolling
153153
const disabledTargets = document.querySelectorAll(`[${SCROLL_LOCK_DISABLE_ATTR}]`);
154154
disabledTargets.forEach(target => advancedLock(target));
155+
// lock everything but disabled targets with horizontal scrolling
156+
const disabledHorizontalTargets = document.querySelectorAll(`[${SCROLL_LOCK_DISABLE_HORIZONTAL_ATTR}]`);
157+
disabledHorizontalTargets.forEach(target => advancedLock(target, true));
155158
}
156159
isLocked = true;
157160
},
@@ -167,7 +170,8 @@ export default {
167170
advancedUnlock(targetElement);
168171
// revert the old scroll position for disabled targets
169172
const disabledTargets = document.querySelectorAll(`[${SCROLL_LOCK_DISABLE_ATTR}]`);
170-
disabledTargets.forEach(target => advancedUnlock(target));
173+
const disabledHorizontalTargets = document.querySelectorAll(`[${SCROLL_LOCK_DISABLE_HORIZONTAL_ATTR}]`);
174+
[...disabledTargets, ...disabledHorizontalTargets].forEach(target => advancedUnlock(target));
171175
} else {
172176
// remove all inline styles added by the `simpleLock` function
173177
document.body.style.removeProperty('overflow');

tests/unit/utils/scroll-lock.spec.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* See https://swift.org/CONTRIBUTORS.txt for Swift project authors
99
*/
1010

11-
import scrollLock, { SCROLL_LOCK_DISABLE_ATTR } from 'docc-render/utils/scroll-lock';
11+
import scrollLock, { SCROLL_LOCK_DISABLE_ATTR, SCROLL_LOCK_DISABLE_HORIZONTAL_ATTR } from 'docc-render/utils/scroll-lock';
1212
import { createEvent, parseHTMLString } from '../../../test-utils';
1313

1414
const { platform } = window.navigator;
@@ -32,6 +32,7 @@ describe('scroll-lock', () => {
3232
<div class="container">
3333
<div class="scrollable">long</div>
3434
<div ${SCROLL_LOCK_DISABLE_ATTR}="true" class="disabled-target"></div>
35+
<div ${SCROLL_LOCK_DISABLE_HORIZONTAL_ATTR}="true" class="disabled-horizontal-target"></div>
3536
</div>
3637
`);
3738
document.body.appendChild(DOM);
@@ -90,23 +91,37 @@ describe('scroll-lock', () => {
9091

9192
it('adds event listeners to the disabled targets too', () => {
9293
const disabledTarget = DOM.querySelector('.disabled-target');
94+
const disabledHorizontalTarget = DOM.querySelector('.disabled-horizontal-target');
9395
// init the scroll lock
9496
scrollLock.lockScroll(container);
9597
// assert event listeners are attached
9698
expect(disabledTarget.ontouchstart).toEqual(expect.any(Function));
9799
expect(disabledTarget.ontouchmove).toEqual(expect.any(Function));
100+
expect(disabledHorizontalTarget.ontouchstart).toEqual(expect.any(Function));
101+
expect(disabledHorizontalTarget.ontouchmove).toEqual(expect.any(Function));
98102

99103
scrollLock.unlockScroll(container);
100104
expect(disabledTarget.ontouchmove).toBeFalsy();
101105
expect(disabledTarget.ontouchstart).toBeFalsy();
106+
expect(disabledHorizontalTarget.ontouchstart).toBeFalsy();
107+
expect(disabledHorizontalTarget.ontouchmove).toBeFalsy();
102108
});
103109

104110
it('prevent event if user tries to perform vertical scroll in an horizontal scrolling element', () => {
105-
Object.defineProperty(container, 'scrollWidth', { value: 100, writable: true });
111+
// set horizontal scrolling element only
112+
DOM = parseHTMLString(`
113+
<div class="container">
114+
<div class="scrollable">long</div>
115+
<div ${SCROLL_LOCK_DISABLE_HORIZONTAL_ATTR}="true" class="disabled-horizontal-target"></div>
116+
</div>
117+
`);
118+
document.body.appendChild(DOM);
119+
container = DOM.querySelector('.container');
106120

107121
const touchStartEvent = {
108122
targetTouches: [{ clientY: 0, clientX: 0 }],
109123
};
124+
// perform vertical scroll
110125
const touchMoveEvent = {
111126
targetTouches: [{ clientY: -10, clientX: 0 }],
112127
preventDefault,

0 commit comments

Comments
 (0)