[d565449] | 1 | /**
|
---|
| 2 | * --------------------------------------------------------------------------
|
---|
| 3 | * Bootstrap util/swipe.js
|
---|
| 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
---|
| 5 | * --------------------------------------------------------------------------
|
---|
| 6 | */
|
---|
| 7 |
|
---|
| 8 | import EventHandler from '../dom/event-handler.js'
|
---|
| 9 | import Config from './config.js'
|
---|
| 10 | import { execute } from './index.js'
|
---|
| 11 |
|
---|
| 12 | /**
|
---|
| 13 | * Constants
|
---|
| 14 | */
|
---|
| 15 |
|
---|
| 16 | const NAME = 'swipe'
|
---|
| 17 | const EVENT_KEY = '.bs.swipe'
|
---|
| 18 | const EVENT_TOUCHSTART = `touchstart${EVENT_KEY}`
|
---|
| 19 | const EVENT_TOUCHMOVE = `touchmove${EVENT_KEY}`
|
---|
| 20 | const EVENT_TOUCHEND = `touchend${EVENT_KEY}`
|
---|
| 21 | const EVENT_POINTERDOWN = `pointerdown${EVENT_KEY}`
|
---|
| 22 | const EVENT_POINTERUP = `pointerup${EVENT_KEY}`
|
---|
| 23 | const POINTER_TYPE_TOUCH = 'touch'
|
---|
| 24 | const POINTER_TYPE_PEN = 'pen'
|
---|
| 25 | const CLASS_NAME_POINTER_EVENT = 'pointer-event'
|
---|
| 26 | const SWIPE_THRESHOLD = 40
|
---|
| 27 |
|
---|
| 28 | const Default = {
|
---|
| 29 | endCallback: null,
|
---|
| 30 | leftCallback: null,
|
---|
| 31 | rightCallback: null
|
---|
| 32 | }
|
---|
| 33 |
|
---|
| 34 | const DefaultType = {
|
---|
| 35 | endCallback: '(function|null)',
|
---|
| 36 | leftCallback: '(function|null)',
|
---|
| 37 | rightCallback: '(function|null)'
|
---|
| 38 | }
|
---|
| 39 |
|
---|
| 40 | /**
|
---|
| 41 | * Class definition
|
---|
| 42 | */
|
---|
| 43 |
|
---|
| 44 | class Swipe extends Config {
|
---|
| 45 | constructor(element, config) {
|
---|
| 46 | super()
|
---|
| 47 | this._element = element
|
---|
| 48 |
|
---|
| 49 | if (!element || !Swipe.isSupported()) {
|
---|
| 50 | return
|
---|
| 51 | }
|
---|
| 52 |
|
---|
| 53 | this._config = this._getConfig(config)
|
---|
| 54 | this._deltaX = 0
|
---|
| 55 | this._supportPointerEvents = Boolean(window.PointerEvent)
|
---|
| 56 | this._initEvents()
|
---|
| 57 | }
|
---|
| 58 |
|
---|
| 59 | // Getters
|
---|
| 60 | static get Default() {
|
---|
| 61 | return Default
|
---|
| 62 | }
|
---|
| 63 |
|
---|
| 64 | static get DefaultType() {
|
---|
| 65 | return DefaultType
|
---|
| 66 | }
|
---|
| 67 |
|
---|
| 68 | static get NAME() {
|
---|
| 69 | return NAME
|
---|
| 70 | }
|
---|
| 71 |
|
---|
| 72 | // Public
|
---|
| 73 | dispose() {
|
---|
| 74 | EventHandler.off(this._element, EVENT_KEY)
|
---|
| 75 | }
|
---|
| 76 |
|
---|
| 77 | // Private
|
---|
| 78 | _start(event) {
|
---|
| 79 | if (!this._supportPointerEvents) {
|
---|
| 80 | this._deltaX = event.touches[0].clientX
|
---|
| 81 |
|
---|
| 82 | return
|
---|
| 83 | }
|
---|
| 84 |
|
---|
| 85 | if (this._eventIsPointerPenTouch(event)) {
|
---|
| 86 | this._deltaX = event.clientX
|
---|
| 87 | }
|
---|
| 88 | }
|
---|
| 89 |
|
---|
| 90 | _end(event) {
|
---|
| 91 | if (this._eventIsPointerPenTouch(event)) {
|
---|
| 92 | this._deltaX = event.clientX - this._deltaX
|
---|
| 93 | }
|
---|
| 94 |
|
---|
| 95 | this._handleSwipe()
|
---|
| 96 | execute(this._config.endCallback)
|
---|
| 97 | }
|
---|
| 98 |
|
---|
| 99 | _move(event) {
|
---|
| 100 | this._deltaX = event.touches && event.touches.length > 1 ?
|
---|
| 101 | 0 :
|
---|
| 102 | event.touches[0].clientX - this._deltaX
|
---|
| 103 | }
|
---|
| 104 |
|
---|
| 105 | _handleSwipe() {
|
---|
| 106 | const absDeltaX = Math.abs(this._deltaX)
|
---|
| 107 |
|
---|
| 108 | if (absDeltaX <= SWIPE_THRESHOLD) {
|
---|
| 109 | return
|
---|
| 110 | }
|
---|
| 111 |
|
---|
| 112 | const direction = absDeltaX / this._deltaX
|
---|
| 113 |
|
---|
| 114 | this._deltaX = 0
|
---|
| 115 |
|
---|
| 116 | if (!direction) {
|
---|
| 117 | return
|
---|
| 118 | }
|
---|
| 119 |
|
---|
| 120 | execute(direction > 0 ? this._config.rightCallback : this._config.leftCallback)
|
---|
| 121 | }
|
---|
| 122 |
|
---|
| 123 | _initEvents() {
|
---|
| 124 | if (this._supportPointerEvents) {
|
---|
| 125 | EventHandler.on(this._element, EVENT_POINTERDOWN, event => this._start(event))
|
---|
| 126 | EventHandler.on(this._element, EVENT_POINTERUP, event => this._end(event))
|
---|
| 127 |
|
---|
| 128 | this._element.classList.add(CLASS_NAME_POINTER_EVENT)
|
---|
| 129 | } else {
|
---|
| 130 | EventHandler.on(this._element, EVENT_TOUCHSTART, event => this._start(event))
|
---|
| 131 | EventHandler.on(this._element, EVENT_TOUCHMOVE, event => this._move(event))
|
---|
| 132 | EventHandler.on(this._element, EVENT_TOUCHEND, event => this._end(event))
|
---|
| 133 | }
|
---|
| 134 | }
|
---|
| 135 |
|
---|
| 136 | _eventIsPointerPenTouch(event) {
|
---|
| 137 | return this._supportPointerEvents && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)
|
---|
| 138 | }
|
---|
| 139 |
|
---|
| 140 | // Static
|
---|
| 141 | static isSupported() {
|
---|
| 142 | return 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0
|
---|
| 143 | }
|
---|
| 144 | }
|
---|
| 145 |
|
---|
| 146 | export default Swipe
|
---|