[change] ResponderEvent support for multi-input devices

Certain devices support both mouse and touch inputs. The Responder
plugin needs to support this. Previously it would specific touch-only
dependencies if touch support was detected.

The recommended way to prevent browsers firing mouse events after touch
events is to call `preventDefault` on the touch event. This may be
problematic if/when `View` and `Touchable` support URLs/hrefs.

Fix #169
This commit is contained in:
Nicolas Gallagher
2016-07-20 14:26:42 -07:00
parent f2772b89bf
commit 6a9212df40
2 changed files with 17 additions and 14 deletions
+12 -10
View File
@@ -2,7 +2,6 @@
import EventConstants from 'react/lib/EventConstants'
import EventPluginRegistry from 'react/lib/EventPluginRegistry'
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment'
import ResponderEventPlugin from 'react/lib/ResponderEventPlugin'
import ResponderTouchHistoryStore from 'react/lib/ResponderTouchHistoryStore'
import normalizeNativeEvent from './normalizeNativeEvent'
@@ -19,14 +18,9 @@ const {
topTouchStart
} = EventConstants.topLevelTypes
const supportsTouch = ExecutionEnvironment.canUseDOM && (
'ontouchstart' in window ||
window.DocumentTouch && document instanceof window.DocumentTouch
)
const endDependencies = supportsTouch ? [ topTouchCancel, topTouchEnd ] : [ topMouseUp ]
const moveDependencies = supportsTouch ? [ topTouchMove ] : [ topMouseMove ]
const startDependencies = supportsTouch ? [ topTouchStart ] : [ topMouseDown ]
const endDependencies = [ topTouchCancel, topTouchEnd, topMouseUp ]
const moveDependencies = [ topTouchMove, topMouseMove ]
const startDependencies = [ topTouchStart, topMouseDown ]
/**
* Setup ResponderEventPlugin dependencies
@@ -51,7 +45,15 @@ ResponderTouchHistoryStore.recordTouchTrack = (topLevelType, nativeEvent) => {
if ((topLevelType === topMouseMove) && !ResponderTouchHistoryStore.touchHistory.touchBank.length) {
return
}
originalRecordTouchTrack.call(ResponderTouchHistoryStore, topLevelType, normalizeNativeEvent(nativeEvent))
// Cancel mouse events that browsers fire after touch events
if (topLevelType === topTouchStart || topLevelType === topTouchMove || topLevelType === topTouchEnd) {
if (nativeEvent.target.getAttribute('href') !== undefined) {
nativeEvent.preventDefault()
}
}
const normalizedEvent = normalizeNativeEvent(nativeEvent)
originalRecordTouchTrack.call(ResponderTouchHistoryStore, topLevelType, normalizedEvent)
}
EventPluginRegistry.injectEventPluginsByName({
+5 -4
View File
@@ -33,7 +33,7 @@ function normalizeTouchEvent(nativeEvent) {
const event = {
changedTouches,
domEvent: nativeEvent,
originalEvent: nativeEvent,
pageX: nativeEvent.pageX,
pageY: nativeEvent.pageY,
target: nativeEvent.target,
@@ -67,14 +67,14 @@ function normalizeMouseEvent(nativeEvent) {
screenX: nativeEvent.screenX,
screenY: nativeEvent.screenY,
target: nativeEvent.target,
timestamp: nativeEvent.timestamp || Date.now()
timestamp: Date.now()
}]
return {
changedTouches: touches,
domEvent: nativeEvent,
identifier: touches[0].identifier,
locationX: nativeEvent.offsetX,
locationY: nativeEvent.offsetY,
originalEvent: nativeEvent,
pageX: nativeEvent.pageX,
pageY: nativeEvent.pageY,
target: nativeEvent.target,
@@ -84,7 +84,8 @@ function normalizeMouseEvent(nativeEvent) {
}
function normalizeNativeEvent(nativeEvent) {
const mouse = nativeEvent.type.indexOf('mouse') >= 0
const eventType = nativeEvent.type || (nativeEvent.originalEvent && nativeEvent.originalEvent.type) || ''
const mouse = eventType.indexOf('mouse') >= 0
return mouse ? normalizeMouseEvent(nativeEvent) : normalizeTouchEvent(nativeEvent)
}