This commit is contained in:
David Štaleker
2024-02-23 12:56:54 +01:00
parent 18bac3de1c
commit 28d1630749
1388 changed files with 558637 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
import updateGeometry from '../update-geometry';
export default function(i) {
const element = i.element;
i.event.bind(i.scrollbarY, 'mousedown', e => e.stopPropagation());
i.event.bind(i.scrollbarYRail, 'mousedown', e => {
const positionTop =
e.pageY -
window.pageYOffset -
i.scrollbarYRail.getBoundingClientRect().top;
const direction = positionTop > i.scrollbarYTop ? 1 : -1;
i.element.scrollTop += direction * i.containerHeight;
updateGeometry(i);
e.stopPropagation();
});
i.event.bind(i.scrollbarX, 'mousedown', e => e.stopPropagation());
i.event.bind(i.scrollbarXRail, 'mousedown', e => {
const positionLeft =
e.pageX -
window.pageXOffset -
i.scrollbarXRail.getBoundingClientRect().left;
const direction = positionLeft > i.scrollbarXLeft ? 1 : -1;
i.element.scrollLeft += direction * i.containerWidth;
updateGeometry(i);
e.stopPropagation();
});
}

View File

@@ -0,0 +1,104 @@
import * as CSS from '../lib/css';
import * as DOM from '../lib/dom';
import cls, {
addScrollingClass,
removeScrollingClass,
} from '../lib/class-names';
import updateGeometry from '../update-geometry';
import { toInt } from '../lib/util';
export default function(i) {
bindMouseScrollHandler(i, [
'containerWidth',
'contentWidth',
'pageX',
'railXWidth',
'scrollbarX',
'scrollbarXWidth',
'scrollLeft',
'x',
'scrollbarXRail',
]);
bindMouseScrollHandler(i, [
'containerHeight',
'contentHeight',
'pageY',
'railYHeight',
'scrollbarY',
'scrollbarYHeight',
'scrollTop',
'y',
'scrollbarYRail',
]);
}
function bindMouseScrollHandler(
i,
[
containerHeight,
contentHeight,
pageY,
railYHeight,
scrollbarY,
scrollbarYHeight,
scrollTop,
y,
scrollbarYRail,
]
) {
const element = i.element;
let startingScrollTop = null;
let startingMousePageY = null;
let scrollBy = null;
function mouseMoveHandler(e) {
if (e.touches && e.touches[0]) {
e[pageY] = e.touches[0].pageY;
}
element[scrollTop] =
startingScrollTop + scrollBy * (e[pageY] - startingMousePageY);
addScrollingClass(i, y);
updateGeometry(i);
e.stopPropagation();
if (e.type.startsWith('touch') && e.changedTouches.length > 1) {
e.preventDefault();
}
}
function mouseUpHandler() {
removeScrollingClass(i, y);
i[scrollbarYRail].classList.remove(cls.state.clicking);
i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);
}
function bindMoves(e, touchMode) {
startingScrollTop = element[scrollTop];
if (touchMode && e.touches) {
e[pageY] = e.touches[0].pageY;
}
startingMousePageY = e[pageY];
scrollBy =
(i[contentHeight] - i[containerHeight]) /
(i[railYHeight] - i[scrollbarYHeight]);
if (!touchMode) {
i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);
e.preventDefault();
} else {
i.event.bind(i.ownerDocument, 'touchmove', mouseMoveHandler);
}
i[scrollbarYRail].classList.add(cls.state.clicking);
e.stopPropagation();
}
i.event.bind(i[scrollbarY], 'mousedown', e => {
bindMoves(e);
});
i.event.bind(i[scrollbarY], 'touchstart', e => {
bindMoves(e, true);
});
}

View File

@@ -0,0 +1,148 @@
import * as DOM from '../lib/dom';
import updateGeometry from '../update-geometry';
import { isEditable } from '../lib/util';
export default function(i) {
const element = i.element;
const elementHovered = () => DOM.matches(element, ':hover');
const scrollbarFocused = () =>
DOM.matches(i.scrollbarX, ':focus') || DOM.matches(i.scrollbarY, ':focus');
function shouldPreventDefault(deltaX, deltaY) {
const scrollTop = Math.floor(element.scrollTop);
if (deltaX === 0) {
if (!i.scrollbarYActive) {
return false;
}
if (
(scrollTop === 0 && deltaY > 0) ||
(scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)
) {
return !i.settings.wheelPropagation;
}
}
const scrollLeft = element.scrollLeft;
if (deltaY === 0) {
if (!i.scrollbarXActive) {
return false;
}
if (
(scrollLeft === 0 && deltaX < 0) ||
(scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)
) {
return !i.settings.wheelPropagation;
}
}
return true;
}
i.event.bind(i.ownerDocument, 'keydown', e => {
if (
(e.isDefaultPrevented && e.isDefaultPrevented()) ||
e.defaultPrevented
) {
return;
}
if (!elementHovered() && !scrollbarFocused()) {
return;
}
let activeElement = document.activeElement
? document.activeElement
: i.ownerDocument.activeElement;
if (activeElement) {
if (activeElement.tagName === 'IFRAME') {
activeElement = activeElement.contentDocument.activeElement;
} else {
// go deeper if element is a webcomponent
while (activeElement.shadowRoot) {
activeElement = activeElement.shadowRoot.activeElement;
}
}
if (isEditable(activeElement)) {
return;
}
}
let deltaX = 0;
let deltaY = 0;
switch (e.which) {
case 37: // left
if (e.metaKey) {
deltaX = -i.contentWidth;
} else if (e.altKey) {
deltaX = -i.containerWidth;
} else {
deltaX = -30;
}
break;
case 38: // up
if (e.metaKey) {
deltaY = i.contentHeight;
} else if (e.altKey) {
deltaY = i.containerHeight;
} else {
deltaY = 30;
}
break;
case 39: // right
if (e.metaKey) {
deltaX = i.contentWidth;
} else if (e.altKey) {
deltaX = i.containerWidth;
} else {
deltaX = 30;
}
break;
case 40: // down
if (e.metaKey) {
deltaY = -i.contentHeight;
} else if (e.altKey) {
deltaY = -i.containerHeight;
} else {
deltaY = -30;
}
break;
case 32: // space bar
if (e.shiftKey) {
deltaY = i.containerHeight;
} else {
deltaY = -i.containerHeight;
}
break;
case 33: // page up
deltaY = i.containerHeight;
break;
case 34: // page down
deltaY = -i.containerHeight;
break;
case 36: // home
deltaY = i.contentHeight;
break;
case 35: // end
deltaY = -i.contentHeight;
break;
default:
return;
}
if (i.settings.suppressScrollX && deltaX !== 0) {
return;
}
if (i.settings.suppressScrollY && deltaY !== 0) {
return;
}
element.scrollTop -= deltaY;
element.scrollLeft += deltaX;
updateGeometry(i);
if (shouldPreventDefault(deltaX, deltaY)) {
e.preventDefault();
}
});
}

View File

@@ -0,0 +1,158 @@
import * as CSS from '../lib/css';
import cls from '../lib/class-names';
import updateGeometry from '../update-geometry';
import { env } from '../lib/util';
export default function(i) {
const element = i.element;
let shouldPrevent = false;
function shouldPreventDefault(deltaX, deltaY) {
const roundedScrollTop = Math.floor(element.scrollTop);
const isTop = element.scrollTop === 0;
const isBottom =
roundedScrollTop + element.offsetHeight === element.scrollHeight;
const isLeft = element.scrollLeft === 0;
const isRight =
element.scrollLeft + element.offsetWidth === element.scrollWidth;
let hitsBound;
// pick axis with primary direction
if (Math.abs(deltaY) > Math.abs(deltaX)) {
hitsBound = isTop || isBottom;
} else {
hitsBound = isLeft || isRight;
}
return hitsBound ? !i.settings.wheelPropagation : true;
}
function getDeltaFromEvent(e) {
let deltaX = e.deltaX;
let deltaY = -1 * e.deltaY;
if (typeof deltaX === 'undefined' || typeof deltaY === 'undefined') {
// OS X Safari
deltaX = (-1 * e.wheelDeltaX) / 6;
deltaY = e.wheelDeltaY / 6;
}
if (e.deltaMode && e.deltaMode === 1) {
// Firefox in deltaMode 1: Line scrolling
deltaX *= 10;
deltaY *= 10;
}
if (deltaX !== deltaX && deltaY !== deltaY /* NaN checks */) {
// IE in some mouse drivers
deltaX = 0;
deltaY = e.wheelDelta;
}
if (e.shiftKey) {
// reverse axis with shift key
return [-deltaY, -deltaX];
}
return [deltaX, deltaY];
}
function shouldBeConsumedByChild(target, deltaX, deltaY) {
// FIXME: this is a workaround for <select> issue in FF and IE #571
if (!env.isWebKit && element.querySelector('select:focus')) {
return true;
}
if (!element.contains(target)) {
return false;
}
let cursor = target;
while (cursor && cursor !== element) {
if (cursor.classList.contains(cls.element.consuming)) {
return true;
}
const style = CSS.get(cursor);
// if deltaY && vertical scrollable
if (deltaY && style.overflowY.match(/(scroll|auto)/)) {
const maxScrollTop = cursor.scrollHeight - cursor.clientHeight;
if (maxScrollTop > 0) {
if (
(cursor.scrollTop > 0 && deltaY < 0) ||
(cursor.scrollTop < maxScrollTop && deltaY > 0)
) {
return true;
}
}
}
// if deltaX && horizontal scrollable
if (deltaX && style.overflowX.match(/(scroll|auto)/)) {
const maxScrollLeft = cursor.scrollWidth - cursor.clientWidth;
if (maxScrollLeft > 0) {
if (
(cursor.scrollLeft > 0 && deltaX < 0) ||
(cursor.scrollLeft < maxScrollLeft && deltaX > 0)
) {
return true;
}
}
}
cursor = cursor.parentNode;
}
return false;
}
function mousewheelHandler(e) {
const [deltaX, deltaY] = getDeltaFromEvent(e);
if (shouldBeConsumedByChild(e.target, deltaX, deltaY)) {
return;
}
let shouldPrevent = false;
if (!i.settings.useBothWheelAxes) {
// deltaX will only be used for horizontal scrolling and deltaY will
// only be used for vertical scrolling - this is the default
element.scrollTop -= deltaY * i.settings.wheelSpeed;
element.scrollLeft += deltaX * i.settings.wheelSpeed;
} else if (i.scrollbarYActive && !i.scrollbarXActive) {
// only vertical scrollbar is active and useBothWheelAxes option is
// active, so let's scroll vertical bar using both mouse wheel axes
if (deltaY) {
element.scrollTop -= deltaY * i.settings.wheelSpeed;
} else {
element.scrollTop += deltaX * i.settings.wheelSpeed;
}
shouldPrevent = true;
} else if (i.scrollbarXActive && !i.scrollbarYActive) {
// useBothWheelAxes and only horizontal bar is active, so use both
// wheel axes for horizontal bar
if (deltaX) {
element.scrollLeft += deltaX * i.settings.wheelSpeed;
} else {
element.scrollLeft -= deltaY * i.settings.wheelSpeed;
}
shouldPrevent = true;
}
updateGeometry(i);
shouldPrevent = shouldPrevent || shouldPreventDefault(deltaX, deltaY);
if (shouldPrevent && !e.ctrlKey) {
e.stopPropagation();
e.preventDefault();
}
}
if (typeof window.onwheel !== 'undefined') {
i.event.bind(element, 'wheel', mousewheelHandler);
} else if (typeof window.onmousewheel !== 'undefined') {
i.event.bind(element, 'mousewheel', mousewheelHandler);
}
}

View File

@@ -0,0 +1,220 @@
import updateGeometry from '../update-geometry';
import cls from '../lib/class-names';
import * as CSS from '../lib/css';
import { env } from '../lib/util';
export default function(i) {
if (!env.supportsTouch && !env.supportsIePointer) {
return;
}
const element = i.element;
function shouldPrevent(deltaX, deltaY) {
const scrollTop = Math.floor(element.scrollTop);
const scrollLeft = element.scrollLeft;
const magnitudeX = Math.abs(deltaX);
const magnitudeY = Math.abs(deltaY);
if (magnitudeY > magnitudeX) {
// user is perhaps trying to swipe up/down the page
if (
(deltaY < 0 && scrollTop === i.contentHeight - i.containerHeight) ||
(deltaY > 0 && scrollTop === 0)
) {
// set prevent for mobile Chrome refresh
return window.scrollY === 0 && deltaY > 0 && env.isChrome;
}
} else if (magnitudeX > magnitudeY) {
// user is perhaps trying to swipe left/right across the page
if (
(deltaX < 0 && scrollLeft === i.contentWidth - i.containerWidth) ||
(deltaX > 0 && scrollLeft === 0)
) {
return true;
}
}
return true;
}
function applyTouchMove(differenceX, differenceY) {
element.scrollTop -= differenceY;
element.scrollLeft -= differenceX;
updateGeometry(i);
}
let startOffset = {};
let startTime = 0;
let speed = {};
let easingLoop = null;
function getTouch(e) {
if (e.targetTouches) {
return e.targetTouches[0];
} else {
// Maybe IE pointer
return e;
}
}
function shouldHandle(e) {
if (e.pointerType && e.pointerType === 'pen' && e.buttons === 0) {
return false;
}
if (e.targetTouches && e.targetTouches.length === 1) {
return true;
}
if (
e.pointerType &&
e.pointerType !== 'mouse' &&
e.pointerType !== e.MSPOINTER_TYPE_MOUSE
) {
return true;
}
return false;
}
function touchStart(e) {
if (!shouldHandle(e)) {
return;
}
const touch = getTouch(e);
startOffset.pageX = touch.pageX;
startOffset.pageY = touch.pageY;
startTime = new Date().getTime();
if (easingLoop !== null) {
clearInterval(easingLoop);
}
}
function shouldBeConsumedByChild(target, deltaX, deltaY) {
if (!element.contains(target)) {
return false;
}
let cursor = target;
while (cursor && cursor !== element) {
if (cursor.classList.contains(cls.element.consuming)) {
return true;
}
const style = CSS.get(cursor);
// if deltaY && vertical scrollable
if (deltaY && style.overflowY.match(/(scroll|auto)/)) {
const maxScrollTop = cursor.scrollHeight - cursor.clientHeight;
if (maxScrollTop > 0) {
if (
(cursor.scrollTop > 0 && deltaY < 0) ||
(cursor.scrollTop < maxScrollTop && deltaY > 0)
) {
return true;
}
}
}
// if deltaX && horizontal scrollable
if (deltaX && style.overflowX.match(/(scroll|auto)/)) {
const maxScrollLeft = cursor.scrollWidth - cursor.clientWidth;
if (maxScrollLeft > 0) {
if (
(cursor.scrollLeft > 0 && deltaX < 0) ||
(cursor.scrollLeft < maxScrollLeft && deltaX > 0)
) {
return true;
}
}
}
cursor = cursor.parentNode;
}
return false;
}
function touchMove(e) {
if (shouldHandle(e)) {
const touch = getTouch(e);
const currentOffset = { pageX: touch.pageX, pageY: touch.pageY };
const differenceX = currentOffset.pageX - startOffset.pageX;
const differenceY = currentOffset.pageY - startOffset.pageY;
if (shouldBeConsumedByChild(e.target, differenceX, differenceY)) {
return;
}
applyTouchMove(differenceX, differenceY);
startOffset = currentOffset;
const currentTime = new Date().getTime();
const timeGap = currentTime - startTime;
if (timeGap > 0) {
speed.x = differenceX / timeGap;
speed.y = differenceY / timeGap;
startTime = currentTime;
}
if (shouldPrevent(differenceX, differenceY)) {
e.preventDefault();
}
}
}
function touchEnd() {
if (i.settings.swipeEasing) {
clearInterval(easingLoop);
easingLoop = setInterval(function() {
if (i.isInitialized) {
clearInterval(easingLoop);
return;
}
if (!speed.x && !speed.y) {
clearInterval(easingLoop);
return;
}
if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
clearInterval(easingLoop);
return;
}
if (!i.element) {
clearInterval(easingLoop);
return;
}
applyTouchMove(speed.x * 30, speed.y * 30);
speed.x *= 0.8;
speed.y *= 0.8;
}, 10);
}
}
if (env.supportsTouch) {
i.event.bind(element, 'touchstart', touchStart);
i.event.bind(element, 'touchmove', touchMove);
i.event.bind(element, 'touchend', touchEnd);
} else if (env.supportsIePointer) {
if (window.PointerEvent) {
i.event.bind(element, 'pointerdown', touchStart);
i.event.bind(element, 'pointermove', touchMove);
i.event.bind(element, 'pointerup', touchEnd);
} else if (window.MSPointerEvent) {
i.event.bind(element, 'MSPointerDown', touchStart);
i.event.bind(element, 'MSPointerMove', touchMove);
i.event.bind(element, 'MSPointerUp', touchEnd);
}
}
}