forked from hackorum-dev/hackorum
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathswipe_nav_controller.js
More file actions
93 lines (78 loc) · 2.92 KB
/
swipe_nav_controller.js
File metadata and controls
93 lines (78 loc) · 2.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import { Controller } from "@hotwired/stimulus"
const SWIPE_DISTANCE_PX = 60
const SWIPE_AXIS_RATIO = 1.2
const SWIPE_TIME_MS = 700
export default class extends Controller {
connect() {
this.onPointerDown = this.onPointerDown.bind(this)
this.onPointerMove = this.onPointerMove.bind(this)
this.onPointerUp = this.onPointerUp.bind(this)
window.addEventListener("pointerdown", this.onPointerDown, { passive: true })
}
disconnect() {
window.removeEventListener("pointerdown", this.onPointerDown, { passive: true })
this.detachTrackingListeners()
}
onPointerDown(event) {
if (!event.isPrimary) return
if (event.pointerType !== "touch" && event.pointerType !== "pen") return
if (event.button && event.button !== 0) return
if (this.shouldIgnoreTarget(event.target)) return
this.tracking = true
this.pointerId = event.pointerId
this.startX = event.clientX
this.startY = event.clientY
this.startTime = performance.now()
this.lastX = event.clientX
this.lastY = event.clientY
window.addEventListener("pointermove", this.onPointerMove, { passive: true })
window.addEventListener("pointerup", this.onPointerUp, { passive: true })
window.addEventListener("pointercancel", this.onPointerUp, { passive: true })
}
onPointerMove(event) {
if (!this.tracking || event.pointerId !== this.pointerId) return
this.lastX = event.clientX
this.lastY = event.clientY
}
onPointerUp(event) {
if (!this.tracking || event.pointerId !== this.pointerId) return
const elapsed = performance.now() - this.startTime
const deltaX = this.lastX - this.startX
const deltaY = this.lastY - this.startY
this.tracking = false
this.pointerId = null
this.detachTrackingListeners()
if (elapsed > SWIPE_TIME_MS) return
if (Math.abs(deltaX) < SWIPE_DISTANCE_PX) return
if (Math.abs(deltaX) < Math.abs(deltaY) * SWIPE_AXIS_RATIO) return
if (deltaX > 0) {
window.history.back()
} else {
window.history.forward()
}
}
detachTrackingListeners() {
window.removeEventListener("pointermove", this.onPointerMove, { passive: true })
window.removeEventListener("pointerup", this.onPointerUp, { passive: true })
window.removeEventListener("pointercancel", this.onPointerUp, { passive: true })
}
shouldIgnoreTarget(target) {
if (!target) return true
if (target.closest("input, textarea, select, [contenteditable='true']")) return true
if (this.isInHorizontalScrollableArea(target)) return true
return false
}
isInHorizontalScrollableArea(target) {
let el = target
while (el && el !== document.body) {
const style = window.getComputedStyle(el)
const overflowX = style.overflowX
if ((overflowX === "auto" || overflowX === "scroll" || overflowX === "overlay") &&
el.scrollWidth > el.clientWidth + 1) {
return true
}
el = el.parentElement
}
return false
}
}