Skip to content
This repository has been archived by the owner on Aug 1, 2024. It is now read-only.

Commit

Permalink
RELNOTES[NEW]: Add basic support for pointer event types.
Browse files Browse the repository at this point in the history
- Add BrowserEvent#pointerType property.
- Add BrowserFeature#[MS]POINTER_EVENTS checks.
- Add PointerFallbackEventType enum to simplify replacing mouse events with pointer events.

NEW: replaced switch statement with object lookup in BrowserEvent.getPointerType_.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=167759144
  • Loading branch information
John Plaisted committed Sep 6, 2017
1 parent 2c1bf21 commit 339594e
Show file tree
Hide file tree
Showing 9 changed files with 255 additions and 10 deletions.
1 change: 1 addition & 0 deletions alltests.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ var _allTests = [
'closure/goog/events/eventtarget_via_googevents_test.html',
'closure/goog/events/eventtarget_via_w3cinterface_test.html',
'closure/goog/events/event_test.html',
'closure/goog/events/eventtype_test.html',
'closure/goog/events/filedrophandler_test.html',
'closure/goog/events/imehandler_test.html',
'closure/goog/events/inputhandler_test.html',
Expand Down
5 changes: 3 additions & 2 deletions closure/goog/deps.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

70 changes: 65 additions & 5 deletions closure/goog/events/browserevent.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
* - altKey {boolean} Was alt key depressed
* - shiftKey {boolean} Was shift key depressed
* - metaKey {boolean} Was meta key depressed
* - pointerId {number} Pointer ID
* - pointerType {string} Pointer type, e.g. 'mouse', 'pen', or 'touch'
* - defaultPrevented {boolean} Whether the default action has been prevented
* - state {Object} History state object
*
Expand All @@ -45,7 +47,9 @@

goog.provide('goog.events.BrowserEvent');
goog.provide('goog.events.BrowserEvent.MouseButton');
goog.provide('goog.events.BrowserEvent.PointerType');

goog.require('goog.debug');
goog.require('goog.events.BrowserFeature');
goog.require('goog.events.Event');
goog.require('goog.events.EventType');
Expand Down Expand Up @@ -185,6 +189,16 @@ goog.events.BrowserEvent = function(opt_e, opt_currentTarget) {
*/
this.platformModifierKey = false;

/**
* @type {number}
*/
this.pointerId = 0;

/**
* @type {string}
*/
this.pointerType = '';

/**
* The browser event object.
* @private {Event}
Expand All @@ -209,15 +223,45 @@ goog.events.BrowserEvent.MouseButton = {
};


/**
* Normalized pointer type constants for pointer events.
* @enum {string}
*/
goog.events.BrowserEvent.PointerType = {
MOUSE: 'mouse',
PEN: 'pen',
TOUCH: 'touch'
};


/**
* Static data for mapping mouse buttons.
* @type {!Array<number>}
* @deprecated Use {@code goog.events.BrowserEvent.IE_BUTTON_MAP} instead.
*/
goog.events.BrowserEvent.IEButtonMap = [
goog.events.BrowserEvent.IEButtonMap = goog.debug.freeze([
1, // LEFT
4, // MIDDLE
2 // RIGHT
];
]);


/**
* Static data for mapping mouse buttons.
* @const {!Array<number>}
*/
goog.events.BrowserEvent.IE_BUTTON_MAP = goog.events.BrowserEvent.IEButtonMap;


/**
* Static data for mapping MSPointerEvent types to PointerEvent types.
* @const {!Object<number, goog.events.BrowserEvent.PointerType>}
*/
goog.events.BrowserEvent.IE_POINTER_TYPE_MAP = goog.debug.freeze({
2: goog.events.BrowserEvent.PointerType.TOUCH,
3: goog.events.BrowserEvent.PointerType.PEN,
4: goog.events.BrowserEvent.PointerType.MOUSE
});


/**
Expand Down Expand Up @@ -252,8 +296,6 @@ goog.events.BrowserEvent.prototype.init = function(e, opt_currentTarget) {
relatedTarget = null;
}
}
// TODO(arv): Use goog.events.EventType when it has been refactored into its
// own file.
} else if (type == goog.events.EventType.MOUSEOVER) {
relatedTarget = e.fromElement;
} else if (type == goog.events.EventType.MOUSEOUT) {
Expand Down Expand Up @@ -294,6 +336,8 @@ goog.events.BrowserEvent.prototype.init = function(e, opt_currentTarget) {
this.shiftKey = e.shiftKey;
this.metaKey = e.metaKey;
this.platformModifierKey = goog.userAgent.MAC ? e.metaKey : e.ctrlKey;
this.pointerId = e.pointerId || 0;
this.pointerType = goog.events.BrowserEvent.getPointerType_(e);
this.state = e.state;
this.event_ = e;
if (e.defaultPrevented) {
Expand Down Expand Up @@ -324,7 +368,7 @@ goog.events.BrowserEvent.prototype.isButton = function(button) {
return button == goog.events.BrowserEvent.MouseButton.LEFT;
} else {
return !!(
this.event_.button & goog.events.BrowserEvent.IEButtonMap[button]);
this.event_.button & goog.events.BrowserEvent.IE_BUTTON_MAP[button]);
}
} else {
return this.event_.button == button;
Expand Down Expand Up @@ -407,3 +451,19 @@ goog.events.BrowserEvent.prototype.preventDefault = function() {
goog.events.BrowserEvent.prototype.getBrowserEvent = function() {
return this.event_;
};


/**
* Extracts the pointer type from the given event.
* @param {!Event} e
* @return {string} The pointer type, e.g. 'mouse', 'pen', or 'touch'.
* @private
*/
goog.events.BrowserEvent.getPointerType_ = function(e) {
if (goog.isString(e.pointerType)) {
return e.pointerType;
}
// IE10 uses integer codes for pointer type.
// https://msdn.microsoft.com/en-us/library/hh772359(v=vs.85).aspx
return goog.events.BrowserEvent.IE_POINTER_TYPE_MAP[e.pointerType] || '';
};
49 changes: 49 additions & 0 deletions closure/goog/events/browserevent_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ goog.require('goog.userAgent');

var stubs = new goog.testing.PropertyReplacer();
var Button = goog.events.BrowserEvent.MouseButton;
var PointerType = goog.events.BrowserEvent.PointerType;

function setUp() {
stubs.reset();
Expand Down Expand Up @@ -120,11 +121,42 @@ function testTouchEventHandling() {
assertEquals(target, touchCancel.target);
}

function testPointerEvent() {
var event = createPointerEvent('pointerdown', 123, PointerType.MOUSE);
assertEquals(123, event.pointerId);
assertEquals(PointerType.MOUSE, event.pointerType);
}

function testMSPointerEvent() {
var event = createPointerEvent('MSPointerDown', 123, 4 /* mouse */);
assertEquals(123, event.pointerId);
assertEquals(PointerType.MOUSE, event.pointerType);
}

function testUnsupportedPointerEvent() {
var event = createMouseEvent('mousedown', 1);
assertEquals(0, event.pointerId);
assertEquals('', event.pointerType);
}

/**
* @param {string} type
* @param {number} button
* @param {boolean=} opt_ctrlKey
* @return {!goog.events.BrowserEvent}
*/
function createMouseEvent(type, button, opt_ctrlKey) {
return new goog.events.BrowserEvent(
{type: type, button: button, ctrlKey: !!opt_ctrlKey});
}

/**
* @param {string} type
* @param {!Element} target
* @param {!goog.math.Coordinate} clientCoords
* @param {!goog.math.Coordinate} screenCoords
* @return {!goog.events.BrowserEvent}
*/
function createTouchEvent(type, target, clientCoords, screenCoords) {
return new goog.events.BrowserEvent({
type: type,
Expand All @@ -138,6 +170,23 @@ function createTouchEvent(type, target, clientCoords, screenCoords) {
});
}

/**
* @param {string} type
* @param {number} pointerId
* @param {string} pointerType
* @return {!goog.events.BrowserEvent}
*/
function createPointerEvent(type, pointerId, pointerType) {
return new goog.events.BrowserEvent(
{type: type, pointerId: pointerId, pointerType: pointerType});
}

/**
* @param {!goog.events.BrowserEvent} event
* @param {goog.events.BrowserEvent.MouseButton} button
* @param {boolean} isActionButton
* @return {!goog.events.BrowserEvent}
*/
function assertIsButton(event, button, isActionButton) {
for (var key in Button) {
assertEquals(
Expand Down
16 changes: 16 additions & 0 deletions closure/goog/events/browserfeature.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,22 @@ goog.events.BrowserFeature = {
(goog.global['navigator']['maxTouchPoints'] ||
goog.global['navigator']['msMaxTouchPoints']))),

/**
* Whether addEventListener supports W3C standard pointer events.
* http://www.w3.org/TR/pointerevents/
*/
POINTER_EVENTS: ('PointerEvent' in goog.global),

/**
* Whether addEventListener supports MSPointer events (only used in IE10).
* http://msdn.microsoft.com/en-us/library/ie/hh772103(v=vs.85).aspx
* http://msdn.microsoft.com/library/hh673557(v=vs.85).aspx
*/
MSPOINTER_EVENTS:
('MSPointerEvent' in goog.global &&
!!(goog.global['navigator'] &&
goog.global['navigator']['msPointerEnabled'])),

/**
* Whether addEventListener supports {passive: true}.
* https://developers.google.com/web/updates/2016/06/passive-event-listeners
Expand Down
64 changes: 64 additions & 0 deletions closure/goog/events/eventtype.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@


goog.provide('goog.events.EventType');
goog.provide('goog.events.PointerFallbackEventType');

goog.require('goog.events.BrowserFeature');
goog.require('goog.userAgent');


Expand Down Expand Up @@ -293,3 +295,65 @@ goog.events.EventType = {
BEFOREPRINT: 'beforeprint',
AFTERPRINT: 'afterprint'
};


/**
* Returns one of the given pointer fallback event names in order of preference:
* 1. pointerEventName
* 2. msPointerEventName
* 3. mouseEventName
* @param {string} pointerEventName
* @param {string} msPointerEventName
* @param {string} mouseEventName
* @return {string} The supported pointer or mouse event name.
* @private
*/
goog.events.getPointerFallbackEventName_ = function(
pointerEventName, msPointerEventName, mouseEventName) {
if (goog.events.BrowserFeature.POINTER_EVENTS) {
return pointerEventName;
}
if (goog.events.BrowserFeature.MSPOINTER_EVENTS) {
return msPointerEventName;
}
return mouseEventName;
};


/**
* Constants for pointer event names that fall back to corresponding mouse event
* names on unsupported platforms. These are intended to be drop-in replacements
* for corresponding values in {@code goog.events.EventType}.
* @enum {string}
*/
goog.events.PointerFallbackEventType = {
POINTERDOWN: goog.events.getPointerFallbackEventName_(
goog.events.EventType.POINTERDOWN, goog.events.EventType.MSPOINTERDOWN,
goog.events.EventType.MOUSEDOWN),
POINTERUP: goog.events.getPointerFallbackEventName_(
goog.events.EventType.POINTERUP, goog.events.EventType.MSPOINTERUP,
goog.events.EventType.MOUSEUP),
POINTERCANCEL: goog.events.getPointerFallbackEventName_(
goog.events.EventType.POINTERCANCEL,
goog.events.EventType.MSPOINTERCANCEL,
// When falling back to mouse events, there is no MOUSECANCEL equivalent
// of POINTERCANCEL. In this case POINTERUP already falls back to MOUSEUP
// which represents both UP and CANCEL. POINTERCANCEL does not fall back
// to MOUSEUP to prevent listening twice on the same event.
'mousecancel'), // non-existent event; will never fire
POINTERMOVE: goog.events.getPointerFallbackEventName_(
goog.events.EventType.POINTERMOVE, goog.events.EventType.MSPOINTERMOVE,
goog.events.EventType.MOUSEMOVE),
POINTEROVER: goog.events.getPointerFallbackEventName_(
goog.events.EventType.POINTEROVER, goog.events.EventType.MSPOINTEROVER,
goog.events.EventType.MOUSEOVER),
POINTEROUT: goog.events.getPointerFallbackEventName_(
goog.events.EventType.POINTEROUT, goog.events.EventType.MSPOINTEROUT,
goog.events.EventType.MOUSEOUT),
POINTERENTER: goog.events.getPointerFallbackEventName_(
goog.events.EventType.POINTERENTER, goog.events.EventType.MSPOINTERENTER,
goog.events.EventType.MOUSEENTER),
POINTERLEAVE: goog.events.getPointerFallbackEventName_(
goog.events.EventType.POINTERLEAVE, goog.events.EventType.MSPOINTERLEAVE,
goog.events.EventType.MOUSELEAVE)
};
9 changes: 9 additions & 0 deletions closure/goog/events/eventtype_test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE html><!-- DO NOT EDIT. This file auto-generated by generate_closure_unit_tests.js --><!--
Copyright 2017 The Closure Library Authors. All Rights Reserved.
Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
--><html><head><meta charset="UTF-8">
<script src="../base.js"></script>
<script>goog.require('goog.events.EventTypeTest');</script>
<title>Closure Unit Tests - goog.events.EventTypeTest</title></head><body></body></html>
45 changes: 45 additions & 0 deletions closure/goog/events/eventtype_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2017 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

goog.provide('goog.events.EventTypeTest');
goog.setTestOnly('goog.events.EventTypeTest');

goog.require('goog.events.BrowserFeature');
goog.require('goog.events.EventType');
goog.require('goog.events.PointerFallbackEventType');
goog.require('goog.testing.jsunit');
goog.require('goog.userAgent');

function testPointerFallbackEventType() {
if (goog.events.BrowserFeature.POINTER_EVENTS) {
// Pointer events are supported; use W3C PointerEvent
assertEquals(
goog.events.EventType.POINTERDOWN,
goog.events.PointerFallbackEventType.POINTERDOWN);
} else if (goog.events.BrowserFeature.MSPOINTER_EVENTS) {
// Only IE10 should support MSPointerEvent
assertTrue(
goog.userAgent.IE && goog.userAgent.isVersionOrHigher('10') &&
!goog.userAgent.isVersionOrHigher('11'));
// W3C PointerEvent not supported; fall back to MSPointerEvent
assertEquals(
goog.events.EventType.MSPOINTERDOWN,
goog.events.PointerFallbackEventType.POINTERDOWN);
} else {
// Pointer events not supported; fall back to MouseEvent
assertEquals(
goog.events.EventType.MOUSEDOWN,
goog.events.PointerFallbackEventType.POINTERDOWN);
}
}
Loading

0 comments on commit 339594e

Please sign in to comment.