Skip to content

Commit

Permalink
Update prevention of sensitive navigation to support multi browsers
Browse files Browse the repository at this point in the history
  • Loading branch information
yhatt committed May 11, 2021
1 parent e747486 commit ab551df
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 12 deletions.
38 changes: 35 additions & 3 deletions src/templates/bespoke/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,41 @@ export default function bespokeNavigation({

e.preventDefault()

// Prevent too sensitive navigation on trackpad
if (Math.abs(e.wheelDelta) < 60) return
// Prevent too sensitive navigation on trackpad and magic mouse
const currentWheelDelta = Math.sqrt(e.deltaX ** 2 + e.deltaY ** 2)

if (e.wheelDelta !== undefined) {
if (e.webkitForce === undefined) {
// [Chromium]
// Chromium has (a deprecated) wheelDelta value and it is following the
// pre-defeind WHEEL_DELTA (=120). It means a required delta for
// scrolling 3 lines. We have set a threshold as 40 (required to scroll
// 1 line).
if (Math.abs(e.wheelDelta) < 40) return
}

// [WebKit]
// WebKit's wheelDelta value will just return 3 times numbers from the
// standard delta values, so using the standard delta will be better
// than depending on deprecated values.
//
// Both of Chromium and Webkit are starting scroll from 4 pixels by a
// event of the mouse wheel notch. If set a threshold to require 1 line
// of scroll, the navigation by mouse wheel may be insensitive. So we
// have set a threshold as 4 pixels.
//
// It means Safari is more sensitive to Multi-touch devices than other
// browsers.
if (e.deltaMode === e.DOM_DELTA_PIXEL && currentWheelDelta < 4) return
} else {
// [Firefox]
// Firefox only has delta values provided by the standard wheel event.
//
// It will report 36 as the delta of the minimum tick for the regular
// mouse wheel because Firefox's default font size is 12px and 36px is
// required delta to scroll 3 lines at once.
if (e.deltaMode === e.DOM_DELTA_PIXEL && currentWheelDelta < 12) return
}

// Suppress momentum scrolling by trackpad
if (wheelIntervalTimer) clearTimeout(wheelIntervalTimer)
Expand All @@ -68,7 +101,6 @@ export default function bespokeNavigation({
}, interval)

const debouncing = Date.now() - lastWheelNavigationAt < interval
const currentWheelDelta = Math.sqrt(e.deltaX ** 2 + e.deltaY ** 2)
const attenuated = currentWheelDelta <= lastWheelDelta

lastWheelDelta = currentWheelDelta
Expand Down
22 changes: 13 additions & 9 deletions test/templates/bespoke.ts
Original file line number Diff line number Diff line change
Expand Up @@ -453,25 +453,25 @@ describe("Bespoke template's browser context", () => {
const now = jest.spyOn(Date, 'now')
now.mockImplementation(() => 1000)

dispatch({ deltaY: 1 })
dispatch({ deltaY: 120 })
expect(deck.slide()).toBe(1)

// Suppress navigation by continuous scrolling
dispatch({ deltaY: 3 })
dispatch({ deltaY: 240 })
expect(deck.slide()).toBe(1)

// +300ms
now.mockImplementation(() => 1300)
jest.advanceTimersByTime(300)

dispatch({ deltaY: 1 })
dispatch({ deltaY: 120 })
expect(deck.slide()).toBe(2)

// Backward
now.mockImplementation(() => 1600)
jest.advanceTimersByTime(600)

dispatch({ deltaY: -1 })
dispatch({ deltaY: -120 })
expect(deck.slide()).toBe(1)
})

Expand All @@ -495,10 +495,14 @@ describe("Bespoke template's browser context", () => {
now.mockImplementation(() => 2000)

// Navigate if detected a not attenuated delta
dispatch({ deltaX: 10 })
dispatch({ deltaX: 100 })
expect(deck.slide()).toBe(2)
})

it.todo(
'does not react against the wheel event that only have a slightly wheel delta'
)

describe('when the target element is scrollable', () => {
const overflowAuto = (decl = 'overflow') => {
const elm = document.createElement('div')
Expand Down Expand Up @@ -528,19 +532,19 @@ describe("Bespoke template's browser context", () => {
const now = jest.spyOn(Date, 'now')
now.mockImplementation(() => 1000)

dispatch({ deltaY: 1 }, overflowAutoElement)
dispatch({ deltaY: 120 }, overflowAutoElement)
expect(deck.slide()).toBe(0)

dispatch({ deltaY: 1 }, notScrollableElement)
dispatch({ deltaY: 120 }, notScrollableElement)
expect(deck.slide()).toBe(1)

now.mockImplementation(() => 2000)
jest.runAllTimers()

dispatch({ deltaY: 1 }, overflowYAutoElement)
dispatch({ deltaY: 120 }, overflowYAutoElement)
expect(deck.slide()).toBe(1)

dispatch({ deltaX: 1 }, overflowYAutoElement)
dispatch({ deltaX: 120 }, overflowYAutoElement)
expect(deck.slide()).toBe(2)
})
})
Expand Down

0 comments on commit ab551df

Please sign in to comment.