-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Swiper utility function for touch swipe events (#85)
* feat: Add Swiper utility function for touch swipe events * test: Add swipe tests * refactor: eslint configuration and refactor based on a review * fix: update the method to assign the mock to event target * feat: allow configure deadZone * feat: add destroy method --------- Co-authored-by: Alecell <[email protected]> Co-authored-by: Diogo Ferreira Reis <[email protected]>
- Loading branch information
1 parent
fe864ac
commit b4039ec
Showing
3 changed files
with
208 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
export function initializeSwiper({ deadZone = 50 } = {}) { | ||
const coordinates = { | ||
$element: null, | ||
xDown: null, | ||
yDown: null, | ||
xUp: null, | ||
yUp: null, | ||
}; | ||
|
||
const dispatchSwipeLeft = () => { | ||
const event = new Event('swipe-left'); | ||
coordinates.$element.dispatchEvent(event); | ||
}; | ||
|
||
const dispatchSwipeRight = () => { | ||
const event = new Event('swipe-right'); | ||
coordinates.$element.dispatchEvent(event); | ||
}; | ||
|
||
const dispatchSwipeUp = () => { | ||
const event = new Event('swipe-up'); | ||
coordinates.$element.dispatchEvent(event); | ||
}; | ||
|
||
const dispatchSwipeDown = () => { | ||
const event = new Event('swipe-down'); | ||
coordinates.$element.dispatchEvent(event); | ||
}; | ||
|
||
function swipeDirection() { | ||
const xDiff = coordinates.xUp - coordinates.xDown; | ||
const yDiff = coordinates.yUp - coordinates.yDown; | ||
|
||
const isHorizontal = Math.abs(xDiff) > Math.abs(yDiff); | ||
const isLeft = xDiff < 0; | ||
const isRight = xDiff > 0; | ||
const isUp = yDiff < 0; | ||
const isDown = yDiff > 0; | ||
|
||
if (isHorizontal && isLeft) dispatchSwipeLeft(); | ||
if (isHorizontal && isRight) dispatchSwipeRight(); | ||
if (!isHorizontal && isUp) dispatchSwipeUp(); | ||
if (!isHorizontal && isDown) dispatchSwipeDown(); | ||
} | ||
|
||
function handleTouchStart(event) { | ||
coordinates.$element = event.target; | ||
|
||
coordinates.xDown = event.touches[0].clientX; | ||
coordinates.yDown = event.touches[0].clientY; | ||
} | ||
|
||
function handleTouchEnd(event) { | ||
coordinates.xUp = event.changedTouches[0].clientX; | ||
coordinates.yUp = event.changedTouches[0].clientY; | ||
|
||
const xDiff = coordinates.xUp - coordinates.xDown; | ||
const yDiff = coordinates.yUp - coordinates.yDown; | ||
|
||
|
||
const didSwipe = Math.abs(xDiff) > deadZone || Math.abs(yDiff) > deadZone; | ||
|
||
if (didSwipe) swipeDirection(); | ||
} | ||
|
||
window.addEventListener('touchstart', handleTouchStart, false); | ||
window.addEventListener('touchend', handleTouchEnd, false); | ||
|
||
return function destroy() { | ||
window.removeEventListener('touchstart', handleTouchStart); | ||
window.removeEventListener('touchend', handleTouchEnd); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
import { describe, expect, it, beforeEach } from 'vitest'; | ||
import { initializeSwiper } from './swiper'; | ||
|
||
describe('Swiper', () => { | ||
initializeSwiper(); | ||
const mockElement = document.createElement('div'); | ||
const touchStartEvent = new Event('touchstart'); | ||
const touchEndEvent = new Event('touchend'); | ||
Object.defineProperty(touchStartEvent, 'target', { | ||
writable: false, | ||
value: mockElement, | ||
}); | ||
|
||
let eventFired = { | ||
swipeLeft: false, | ||
swipeRight: false, | ||
swipeUp: false, | ||
swipeDown: false, | ||
}; | ||
|
||
mockElement.addEventListener('swipe-left', () => { | ||
eventFired.swipeLeft = true; | ||
}); | ||
mockElement.addEventListener('swipe-right', () => { | ||
eventFired.swipeRight = true; | ||
}); | ||
mockElement.addEventListener('swipe-up', () => { | ||
eventFired.swipeUp = true; | ||
}); | ||
mockElement.addEventListener('swipe-down', () => { | ||
eventFired.swipeDown = true; | ||
}); | ||
|
||
beforeEach(() => { | ||
eventFired = { | ||
swipeLeft: false, | ||
swipeRight: false, | ||
swipeUp: false, | ||
swipeDown: false, | ||
}; | ||
}); | ||
|
||
it('dispatches swipe-left event', () => { | ||
touchStartEvent.touches = [{ clientX: 200, clientY: 0 }]; | ||
touchEndEvent.changedTouches = [{ clientX: 0, clientY: 100 }]; | ||
|
||
window.dispatchEvent(touchStartEvent); | ||
window.dispatchEvent(touchEndEvent); | ||
|
||
expect(eventFired.swipeLeft).toBe(true); | ||
expect(eventFired.swipeRight).toBe(false); | ||
expect(eventFired.swipeUp).toBe(false); | ||
expect(eventFired.swipeDown).toBe(false); | ||
}); | ||
|
||
it('dispatches swipe-right event', () => { | ||
touchStartEvent.touches = [{ clientX: 0, clientY: 0 }]; | ||
touchEndEvent.changedTouches = [{ clientX: 200, clientY: 100 }]; | ||
|
||
window.dispatchEvent(touchStartEvent); | ||
window.dispatchEvent(touchEndEvent); | ||
|
||
expect(eventFired.swipeLeft).toBe(false); | ||
expect(eventFired.swipeRight).toBe(true); | ||
expect(eventFired.swipeUp).toBe(false); | ||
expect(eventFired.swipeDown).toBe(false); | ||
}); | ||
|
||
it('dispatches swipe-up event', () => { | ||
touchStartEvent.touches = [{ clientX: 0, clientY: 200 }]; | ||
touchEndEvent.changedTouches = [{ clientX: 100, clientY: 0 }]; | ||
|
||
window.dispatchEvent(touchStartEvent); | ||
window.dispatchEvent(touchEndEvent); | ||
|
||
expect(eventFired.swipeLeft).toBe(false); | ||
expect(eventFired.swipeRight).toBe(false); | ||
expect(eventFired.swipeUp).toBe(true); | ||
expect(eventFired.swipeDown).toBe(false); | ||
}); | ||
|
||
it('dispatches swipe-down event', () => { | ||
touchStartEvent.touches = [{ clientX: 0, clientY: 0 }]; | ||
touchEndEvent.changedTouches = [{ clientX: 100, clientY: 200 }]; | ||
|
||
window.dispatchEvent(touchStartEvent); | ||
window.dispatchEvent(touchEndEvent); | ||
|
||
expect(eventFired.swipeLeft).toBe(false); | ||
expect(eventFired.swipeRight).toBe(false); | ||
expect(eventFired.swipeUp).toBe(false); | ||
expect(eventFired.swipeDown).toBe(true); | ||
}); | ||
|
||
it('does not dispatch any event when swipe is not detected', () => { | ||
touchStartEvent.touches = [{ clientX: 0, clientY: 0 }]; | ||
touchEndEvent.changedTouches = [{ clientX: 0, clientY: 0 }]; | ||
|
||
window.dispatchEvent(touchStartEvent); | ||
window.dispatchEvent(touchEndEvent); | ||
|
||
expect(eventFired.swipeLeft).toBe(false); | ||
expect(eventFired.swipeRight).toBe(false); | ||
expect(eventFired.swipeUp).toBe(false); | ||
expect(eventFired.swipeDown).toBe(false); | ||
}); | ||
|
||
it('does not dispatch any event when swipe is not long enough', () => { | ||
touchStartEvent.touches = [{ clientX: 0, clientY: 0 }]; | ||
touchEndEvent.changedTouches = [{ clientX: 50, clientY: 50 }]; | ||
|
||
window.dispatchEvent(touchStartEvent); | ||
window.dispatchEvent(touchEndEvent); | ||
|
||
expect(eventFired.swipeLeft).toBe(false); | ||
expect(eventFired.swipeRight).toBe(false); | ||
expect(eventFired.swipeUp).toBe(false); | ||
expect(eventFired.swipeDown).toBe(false); | ||
}); | ||
|
||
it('dispatches vertical event when direction is esqual', () => { | ||
touchStartEvent.touches = [{ clientX: 0, clientY: 0 }]; | ||
touchEndEvent.changedTouches = [{ clientX: 51, clientY: 51 }]; | ||
|
||
window.dispatchEvent(touchStartEvent); | ||
window.dispatchEvent(touchEndEvent); | ||
|
||
expect(eventFired.swipeLeft).toBe(false); | ||
expect(eventFired.swipeRight).toBe(false); | ||
expect(eventFired.swipeUp).toBe(false); | ||
expect(eventFired.swipeDown).toBe(true); | ||
}); | ||
}); |