Consistent access to browser events with Pointer Events API
Tags: javascript, beginners, codenewbie
Published: 2019-11-05 11:03:12

Thank god it's christmas! 🌲 Ok, it's not. But if you're a web developer nowadays, it's starting to feel like christmas. And it's because of this:

> Added support for the Pointer Events API enabling consistent access to mouse, trackpad, touch, and Apple Pencil events.
>
> -- <cite>Safari 13 Release Notes</cite>

Thus the last resistance against the __Pointer Events API__ has fallen with [Safari 13](https://developer.apple.com/documentation/safari_release_notes/safari_13_release_notes) and it's now available across [all major browsers](https://caniuse.com/#feat=pointer). And this is simply __awesome__!

But don't thank Apple! Belive it or not, pointer events (which are not to be mixed up with the CSS property `pointer-events`) were originally introduced for the Internet Explorer 10 by Microsoft for their Surface devices. 😳

## How does it work?

> Having a single event model for pointers can simplify creating Web sites and applications and provide a good user experience regardless of the user's hardware.
>
> -- <cite>Mozilla Developer Network</cite>

Roughly speaking, mouse and touch events are summarized by abstracting input devices like mouse and touch pens as pointing devices. So you don't need to specify different event handlers for different device types any longer.

```javascript
document.addEventListener('mousedown', () => {
  // do something on mousedown
});

document.addEventListener('touchdown', () => {
  // do something on touchdown
});
```

Instead you can now simply apply one handler to *rule them all*.

```javascript
document.addEventListener('pointerdown', () => {
  // do something on mousedown or touchdown
});

```

You might now ask: "*But can I still react to different device types?*" Yes, you can! That's what the `pointerType` property of the event is for.

```javascript
document.addEventListener('pointerdown', (e) => {
  switch (e.pointerType) {
    case 'mouse': {
      console.log('Pointer type detected: mouse');
      break;
    }
    case 'pen': {
      console.log('Pointer type detected: pen');
      break;
    }
    case 'touch': {
      console.log('Pointer type detected: touch');
      break;
    }
    default: {
      console.log('PointerType is unknown or could not be detected');
    }
  }
});
```

## A look at the API

The `PointerEvent` interface extends the `MouseEvent` interface and defines 10 different pointer event types that can be mapped to more or less known mouse or touch events and which are well documented at [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events):

| Pointer Event        | Mouse Event    |
| -------------------- | -------------- |
| `pointerover`        | `mouseover`    |
| `pointerover`        | `mouseover`    |
| `pointerenter`       | `mouseenter`   |
| `pointerdown`        | `mousedown`    |
| `pointermove`        | `mousemove`    |
| `pointerup`          | `mouseup`      |
| `pointercancel`      | no equivalent  |
| `pointerout`         | `mouseout`     |
| `pointerleave`       | `mouseleave`   |
| `gotpointercapture`  | no equivalent  |
| `lostpointercapture` | no equivalent  |

You also have access to the following read-only properties which give you some additional information about the event:

| Property             | Description    |
| -------------------- | -------------- |
| `pointerId`          | a unique identifier for the pointer    |
| `width`              | magnitude on the X axis in pixels    |
| `height`             | magnitude on the Y axis in pixels   |
| `pressure`           | normalized pressure of the pointer input    |
| `tangentialPressure` | normalized tangential pressure of the pointer input    |
| `tiltX`              | angle between the Y-Z plane and the plane containing both the pointer axis and the Y axis      |
| `tiltY`              | angle between the X-Z plane and the plane containing both the pointer axis and the X axis.  |
| `twist`              | the clockwise rotation of the pointer     |
| `pointerType`        | indicates the device type   |
| `isPrimary`  | indicates if the pointer represents the primary pointer of this pointer type  |

## Polyfill

If you have to support [browsers that haven't yet implemented the Pointer Events API](https://caniuse.com/#feat=pointer) you can easily use a [polyfill](https://github.com/jquery/PEP) maintained by the jQuery team. But you can also do some basic feature detection and go with a fallback solution instead.

```javascript
if (window.PointerEvent) {
  // Hello Pointer Events
} else {
  // Oh... Hi fallback... it's you.
}
```

Thanks for reading this article. I hope you'll enjoy using the Pointer Events API like I do. What are your thoughts about this? Tell me in the comments section below!