# Keyboard

Class · extends [`EventHandler`](https://api.playcanvas.com/engine/classes/EventHandler.md) · category: Input Devices

Source: https://github.com/playcanvas/engine/blob/f059dc005842f76e052cdf44d8370c8c7ec475ac/src/platform/input/keyboard.js#L79

Manages keyboard input by tracking key states and dispatching events. Extends [EventHandler](https://api.playcanvas.com/engine/classes/EventHandler.md)
in order to fire `keydown` and `keyup` events (see [KeyboardEvent](https://api.playcanvas.com/engine/classes/KeyboardEvent.md)).

Allows the state of individual keys to be queried to check if they are currently pressed or were
pressed/released since the last update. The class automatically handles browser visibility
changes and window blur events by clearing key states. The Keyboard instance must be attached to
a DOM element before it can detect key events.

Key state is derived from the legacy `KeyboardEvent.keyCode` property. Browsers populate it for
real input, but a hand-constructed `new KeyboardEvent(...)` leaves it at 0, so synthesized events
must set `keyCode` explicitly in order to be observed.

[Keyboard#wasPressed](https://api.playcanvas.com/engine/classes/Keyboard.md#waspressed) and [Keyboard#wasReleased](https://api.playcanvas.com/engine/classes/Keyboard.md#wasreleased) compare against a snapshot taken
once per frame, so a keydown and keyup delivered within the same task are seen by neither. Hold
the key across at least one frame.

Your application's Keyboard instance is managed and accessible via [AppBase#keyboard](https://api.playcanvas.com/engine/classes/AppBase.md#keyboard).

For pointer-lock-aware, frame-accumulated input deltas rather than raw events, see
[KeyboardMouseSource](https://api.playcanvas.com/engine/classes/KeyboardMouseSource.md), [GamepadSource](https://api.playcanvas.com/engine/classes/GamepadSource.md) and [MultiTouchSource](https://api.playcanvas.com/engine/classes/MultiTouchSource.md), which feed
[InputController](https://api.playcanvas.com/engine/classes/InputController.md)s such as [OrbitController](https://api.playcanvas.com/engine/classes/OrbitController.md), [FlyController](https://api.playcanvas.com/engine/classes/FlyController.md) and
[FocusController](https://api.playcanvas.com/engine/classes/FocusController.md).

## Constructors

### constructor

```ts
new Keyboard(element?: Element | Window, options?: object)
```

Create a new Keyboard instance.

**Parameters**

- `element` (`Element | Window`, optional): Element to attach Keyboard to. Note that elements like
  &lt;div&gt; can't accept focus by default. To use keyboard events on an element like this it
  must have a value of 'tabindex' e.g. tabindex="0". See
  [here](https://www.w3.org/WAI/GL/WCAG20/WD-WCAG20-TECHS/SCR29.html) for more details.
- `options` (`object`, optional, default `{}`): Optional options object.
    - `options.preventDefault` (`boolean`, optional): Call preventDefault() in key event handlers.
      This stops the default action of the event occurring. e.g. Ctrl+T will not open a new
      browser tab.
    - `options.stopPropagation` (`boolean`, optional): Call stopPropagation() in key event handlers.
      This stops the event bubbling up the DOM so no parent handlers will be notified of the
      event.

**Example**

```ts
// attach keyboard listeners to the window
const keyboard = new Keyboard(window);
```

## Properties

### preventDefault

```ts
preventDefault: boolean
```

Call preventDefault() in key event handlers.

### stopPropagation

```ts
stopPropagation: boolean
```

Call stopPropagation() in key event handlers.

## Methods

### attach

```ts
attach(element: Element | Window): void
```

Attach the keyboard event handlers to an Element. If already attached, this first detaches
and clears current and previous key states, even when attaching to the same element. No
`keyup` events are fired. Unlike [Mouse#attach](https://api.playcanvas.com/engine/classes/Mouse.md#attach), held input states are not preserved.

**Parameters**

- `element` (`Element | Window`): The element to listen for keyboard events on.

### detach

```ts
detach(): void
```

Detach the keyboard event handlers from the element it is attached to and clear current and
previous key states. This does not fire `keyup` events.

### isPressed

```ts
isPressed(key: number): boolean
```

Return true if the key is currently down.

**Parameters**

- `key` (`number`): The keyCode of the key to test. See the KEY_* constants.

**Returns** `boolean`: True if the key was pressed, false if not.

### wasPressed

```ts
wasPressed(key: number): boolean
```

Returns true if the key was pressed since the last update.

**Parameters**

- `key` (`number`): The keyCode of the key to test. See the KEY_* constants.

**Returns** `boolean`: True if the key was pressed.

### wasReleased

```ts
wasReleased(key: number): boolean
```

Returns true if the key was released since the last update.

**Parameters**

- `key` (`number`): The keyCode of the key to test. See the KEY_* constants.

**Returns** `boolean`: True if the key was pressed.

## Events

### EVENT_KEYDOWN

```ts
static EVENT_KEYDOWN: string = 'keydown'
```

Fired when a key is pressed. The handler is passed a [KeyboardEvent](https://api.playcanvas.com/engine/classes/KeyboardEvent.md).

**Example**

```ts
const onKeyDown = (e) => {
    if (e.key === KEY_SPACE) {
        // space key pressed
    }
    e.event.preventDefault(); // Use original browser event to prevent browser action.
};

app.keyboard.on('keydown', onKeyDown, this);
```

### EVENT_KEYUP

```ts
static EVENT_KEYUP: string = 'keyup'
```

Fired when a key is released. The handler is passed a [KeyboardEvent](https://api.playcanvas.com/engine/classes/KeyboardEvent.md).

**Example**

```ts
const onKeyUp = (e) => {
    if (e.key === KEY_SPACE) {
        // space key released
    }
    e.event.preventDefault(); // Use original browser event to prevent browser action.
};

app.keyboard.on('keyup', onKeyUp, this);
```

## Inherited from [EventHandler](https://api.playcanvas.com/engine/classes/EventHandler.md)

- `fire(name: string, arg1?: any, arg2?: any, arg3?: any, arg4?: any, arg5?: any, arg6?: any, arg7?: any, arg8?: any): EventHandler`
- `hasEvent(name: string): boolean`
- `off(name?: string, callback?: HandleEventCallback, scope?: any): EventHandler`
- `on(name: string, callback: HandleEventCallback, scope?: any): EventHandle`
- `once(name: string, callback: HandleEventCallback, scope?: any): EventHandle`
