Skip to content

Commit

Permalink
v3
Browse files Browse the repository at this point in the history
  • Loading branch information
Pessimistress committed Aug 24, 2024
1 parent ba410f5 commit ca19360
Show file tree
Hide file tree
Showing 106 changed files with 3,417 additions and 1,645 deletions.
2 changes: 2 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ module.exports = getESLintConfig({
files: ['**/*.ts', '**/*.tsx', '**/*.d.ts'],
rules: {
indent: 0,
'max-statements': 1,
complexity: 1,
'@typescript-eslint/ban-ts-comment': 0,
'@typescript-eslint/explicit-module-boundary-types': 0,
'@typescript-eslint/no-unsafe-assignment': 0,
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ yarn-error.log
.idea
.reify-cache
.nyc_output
dist.min.js
10 changes: 9 additions & 1 deletion .ocularrc.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
/** @typedef {import('ocular-dev-tools').OcularConfig} OcularConfig */
import {resolve} from 'path';

/** @type OcularConfig */
export default {
lint: {
paths: ['src', 'examples', 'test', 'docs']
},

bundle: {
globalName: 'mjolnir',
target: ['chrome110', 'firefox110', 'safari15'],
format: 'umd'
},

typescript: {
project: 'tsconfig.build.json'
},
Expand All @@ -16,7 +24,7 @@ export default {
},

entry: {
test: 'test/index.js',
test: 'test/node.ts',
'test-browser': 'index.html',
size: ['test/size.js']
}
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

mjolnir.js is a JavaScript event and gesture handling module.

Please refer to the extensive documentation on the [website](https://uber-web.github.io/mjolnir.js)
Please refer to the API documentation on the [website](https://visgl.github.io/mjolnir.js)
210 changes: 65 additions & 145 deletions docs/api-reference/event-manager.md
Original file line number Diff line number Diff line change
@@ -1,83 +1,60 @@
# EventManager

Provides a unified API for subscribing to events about both basic input events (e.g. 'mousemove', 'touchstart', 'wheel') and gestural input (e.g. 'click', 'tap', 'panstart').
Provides a unified API for subscribing to events about both basic input events (e.g. 'pointermove', 'keydown', 'wheel') and gestural input (e.g. 'click', 'tap', 'panstart').

## Usage
## Constructor

```js
import {EventManager} from 'mjolnir.js';

const eventManager = new EventManager(document.getElementById('container'));
function onClick(event) {}
function onPinch(event) {}
Creates a new `EventManager` instance.

eventManager.on({
click: onClick,
pinch: onPinch
});
```ts
import {EventManager} from 'mjolnir.js';

// ...
eventManager.destroy();
const eventManager = new EventManager(target, options);
```

**Note:** While EventManager supports mouse and touch events, we recommend the use of [Pointer Events](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events) when possible for the broadest input device compatibility.
* `target` (HTMLElement) - DOM element on which event handlers will be registered.
* `options` (object) - Options
- `events` (object) - A map from event names to their handler functions, to register on init.
- `recognizers` (RecognizerTuple[]) - Gesture recognizers. See [Recognize Gestures](#recognize-gestures) section below for usage.
- `touchAction` (string) - Allow browser default touch actions. See [touch-action CSS property](https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action). Use 'compute' to automatically set as the least restrictive value to support the recognizers. Default `'compute'`.
- `tabIndex` (number) - The [tabindex](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) of the root element. Default `0`.
- `cssProps` (object) - Optional CSS properties to apply to the tarfet element. Default `{userSelect: 'none', touchCallout: 'none'}`.

## Methods

### constructor

Creates a new `EventManager` instance.

`new EventManager(element, {events, recognizers})`

- `element` {DOM Element, optional} - DOM element on which event handlers will be registered. Default `null`.
- `options` {Object, optional} - Options
- `events` {Object} - A map from event names to their handler functions, to register on init.
- `recognizers` - {Object} Gesture recognizers from Hammer.js to register, as an Array in [Hammer.Recognizer format](http://hammerjs.github.io/api/#hammermanager). If not provided, a default set of recognizers will be used. See "Gesture Events" section below for more details.
- `recognizerOptions` - {Object} Override the default options of `recognizers`. Keys are recognizer names and values are recognizer options. For a list of default recognizers, see "Gesture Events" section below.
- `rightButton` - {Boolean} Recognizes click and drag from pressing the right mouse button. Default `false`. If turned on, the context menu will be disabled.
- `touchAction` - {String} Allow browser default touch actions. Default `none`. See [hammer.js doc](http://hammerjs.github.io/touch-action/).
- `tabIndex` - {Number} The [tabindex](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) of the root element. Default `0`.

### destroy

Tears down internal event management implementations.

`eventManager.destroy()`

Note: It is important to call `destroy` when done since `EventManager` adds event listeners to `window`.

### setElement

Set the DOM element on which event handlers will be registered. If element has been set, events will be unregistered from the previous element.

`eventManager.setElement(element)`
```ts
eventManager.destroy();
```

- `element` {DOM Element, optional} - DOM element on which event handlers will be registered.
*Note: It is recommended to call `destroy` when done since `EventManager` adds event listeners to `window`.*

### on

Register an event handler function to be called on `event`.

```js
```ts
eventManager.on(event, handler, options);
eventManager.on(eventMap, options);
```

- `event` {String} - An event name
- `handler` {Function} - The function to be called on `event`.
- `eventMap` {Object} - A map from event names to their handler functions
- `options` {Object, optional}
- `srcElement` {Node} - The source element of this event. If provided, only events that are targeting this element or its decendants will invoke the handler. If ignored, default to the root element of the event manager. Events are propagated up the DOM tree.
- `priority` {Number} - Handlers targeting the same `srcElement` will be executed by their priorities (higher numbers first). Handlers with the same priority will be executed in the order of registration. Default `0`.
- `event` (string) - An event name
- `handler` ((event: MjolnirEvent) => void) - The function to be called on `event`.
- `eventMap` (object) - A map from event names to their handler functions
- `options` (object, optional)
+ `srcElement` (HTMLElement) - The source element of this event. If provided, only events that are targeting this element or its decendants will invoke the handler. If ignored, default to the root element of the event manager. Events are propagated up the DOM tree.
+ `priority` (number) - Handlers targeting the same `srcElement` will be executed by their priorities (higher numbers first). Handlers with the same priority will be executed in the order of registration. Default `0`.

** Note: Unlike the DOM event system, developers are responsible of deregistering event handlers when `srcElement` is removed. **
*Note: Unlike the DOM event system, developers are responsible of deregistering event handlers when `srcElement` is removed.*

### once

Register a one-time event handler function to be called on `event`. The handler is removed once it has been called.

```js
```ts
eventManager.once(event, handler, options);
eventManager.once(eventMap, options);
```
Expand All @@ -88,7 +65,7 @@ Expects the same arguments as [on](#on).

Register an event handler function to be called on `event`. This handler does not ask the event to be recognized from user input; rather, it "intercepts" the event if some other handler is getting it.

```js
```ts
eventManager.watch(event, handler, options);
eventManager.watch(eventMap, options);
```
Expand All @@ -97,13 +74,13 @@ Expects the same arguments as [on](#on).

For example, we want a child element to block any `dblclick` event from bubbling up to root. The root may or may not be actually listening to `dblclick`. If the root did not register a handler, and we use

```js
```ts
eventManager.on('dblClick', evt => evt.stopPropagation(), {srcElement: <child>});
```

It will enable the `DoubleTapRecognizer`. Recognizers for gestures add additional overhead, and may cause subtle behavioral changes. In this case, recognizing `dblclick` events will cause the `click` events to be fired with a small delay. Since we only want to be notified _if_ a `dblclick` event is fired, it is safer to use:
It will enable the double tap recognizer. Recognizers for gestures add additional overhead, and may cause subtle behavioral changes. In this case, recognizing `dblclick` events will cause the `click` events to be fired with a small delay. Since we only want to be notified _if_ a `dblclick` event is fired, it is safer to use:

```js
```ts
eventManager.watch('dblClick', evt => evt.stopPropagation(), {srcElement: <child>});
```

Expand All @@ -114,104 +91,47 @@ eventManager.watch('dblClick', evt => evt.stopPropagation(), {srcElement: <child
`eventManager.off(event, handler)`
`eventManager.off(eventMap)`

- `event` {String} - An event name
- `handler` {Function} - The function to be called on `event`.
- `eventMap` {Object} - A map from event names to their handler functions
- `event` (string) - An event name
- `handler` ((event: MjolnirEvent) => void) - The function to be called on `event`.
- `eventMap` (object) - A map from event names to their handler functions

## Supported Events and Gestures
## Events and Gestures

### Basic input events

Keyboard events are fired when focus is on the EventManager's target element or its decendants, unless typing into a text input.

- `'keydown'`
- `'keyup'`

Mouse event and pointer event names are interchangeable.

- `'mousedown'` | `'pointerdown'`
- `'mousemove'` | `'pointermove'`
- `'mouseup'` | `'pointerup'`
- `'mouseover'` | `'pointerover'`
- `'mouseout'` | `'pointerout'`
- `'mouseleave'` | `'pointerleave'`
- `'pointerdown'`
- `'pointermove'`
- `'pointerup'`
- `'pointerover'`
- `'pointerout'`
- `'pointerleave'`
- `'wheel'`
- `'contextmenu'`

### Gesture events

The following events are generated with [hammer.js](http://hammerjs.github.io/)recognizers. You may fine-tune the behavior of these events by supplying `recognizerOptions` to the `EventManager` constructor.

- The following events are controlled by the `rotate` ([Hammer.Rotate](https://hammerjs.github.io/recognizer-rotate/)) recognizer:
- `'rotate'`
- `'rotatestart'`
- `'rotatemove'`
- `'rotateend'`
- `'rotatecancel'`
- The following events are controlled by the `pinch` ([Hammer.Pinch](https://hammerjs.github.io/recognizer-pinch/)) recognizer:
- `'pinch'`
- `'pinchin'`
- `'pinchout'`
- `'pinchstart'`
- `'pinchmove'`
- `'pinchend'`
- `'pinchcancel'`
- The following events are controlled by the `swipe` ([Hammer.Swipe](https://hammerjs.github.io/recognizer-swipe/)) recognizer:
- `'swipe'`
- `'swipeleft'`
- `'swiperight'`
- `'swipeup'`
- `'swipedown'`
- The following events are controlled by the `tripan` ([Hammer.Pan](https://hammerjs.github.io/recognizer-pan/)) recognizer (3-finger pan):
- `'tripan'`
- `'tripanstart'`
- `'tripanmove'`
- `'tripanup'`
- `'tripandown'`
- `'tripanleft'`
- `'tripanright'`
- `'tripanend'`
- `'tripancancel'`
- The following events are controlled by the `pan` ([Hammer.Pan](https://hammerjs.github.io/recognizer-pan/)) recognizer:
- `'pan'`
- `'panstart'`
- `'panmove'`
- `'panup'`
- `'pandown'`
- `'panleft'`
- `'panright'`
- `'panend'`
- `'pancancel'`
- The following events are controlled by the `Press` ([Hammer.Pan](https://hammerjs.github.io/recognizer-press/)) recognizer:
- `'press'`
- The following events are controlled by the `doubletap` ([Hammer.Pan](https://hammerjs.github.io/recognizer-tap/)) recognizer:
- `'doubletap'`
- `'dblclick'` - alias of `doubletap`
- The following events are controlled by the `tap` ([Hammer.Pan](https://hammerjs.github.io/recognizer-tap/)) recognizer:
- `'tap'` - a single click. Not fired if double clicking.
- `'click'` - alias of `tap`
- The following events are controlled by the `anytap` ([Hammer.Pan](https://hammerjs.github.io/recognizer-tap/)) recognizer:
- `'anytap'` - like `click`, but fired twice if double clicking.
- `'anyclick'` - alias of `anytap`

## Event handling shims

`EventManager` currently uses Hammer.js for gesture and touch support, but Hammer.js does not support all input event types out of the box. Therefore, `EventManager` employs the following modules to shim the missing functionality:

### KeyInput

Handles keyboard events.

### MoveInput

Handles pointer/touch/mouse move events while no button pressed, and leave events (for when the cursor leaves the DOM element registered with `EventManager`).

### WheelInput

Handles mouse wheel events and trackpad events that emulate mouse wheel events. Note that this module is stateful: it tracks time elapsed between events in order to determine the magnitude/scroll distance of an event.

## Remarks

- Current implementation delegates touch and gesture event registration and handling to Hammer.js. Includes shims for handling event not supported by Hammer.js, such as keyboard input, mouse move, and wheel input. This dependency structure may change in the future.

- Hammer.js unsafely references `window` and `document`, and so will fail in environments without these constructs (e.g. Node). To mitigate this, Hammer.js modules are conditionally `require()`d, and replaced with mocks in non-browser environments.
Remarks:
- Keyboard events are fired when focus is on the EventManager's target element or its decendants, unless typing into a text input.

### Recognize gestures

To emit gesture events from user input, the application should pass a list of recognizers to the `EventManager` constructor.
Each item in the `recognizers` list can be either a recognizer instance, or an array in the following form:

- `recognizer` - a recognizer instance
- `recognizeWith` (string | string[]) - Allow another gesture to be recognized simultaneously with this one. For example an interaction can trigger pinch and rotate at the same time.
- `requireFailure` (string | string[]) - Another recognizer is mutually exclusive with this one. For example an interaction could be singletap or doubletap; pan-horizontal or pan-vertical; but never both.

The following recognizers are available for use:

- [Pan](./pan.md)
- [Pinch](./pinch.md)
- [Press](./press.md)
- [Rotate](./rotate.md)
- [Swipe](./swipe.md)
- [Tap](./tap.md)


## Source

https://github.com/visgl/mjolnir.js/blob/master/src/event-manager.ts
21 changes: 0 additions & 21 deletions docs/api-reference/event.md

This file was deleted.

38 changes: 38 additions & 0 deletions docs/api-reference/pan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Pan

Recognized when the pointer is down and moved in the allowed direction.

## Constructor

```ts
import {EventManager, Pan, InputDirection} from 'mjolnir.js';

const eventManager = new EventManager({
// ...
recognizers: [
new Pan({direction: InputDirection.Horizontal})
]
});
```

* `options` (object, optional) - Options
- `event` (string) - Name of the event. Default `'pan'`.
- `pointers` (number) - Required pointers. Default `1`.
- `threshold` (number) - Minimal pan distance required before recognizing. Default `10`.
- `direction` {InputDirection} - Direction of the panning. Default `InputDirection.All`.

## Events

- pan, together with all of below
- panstart
- panmove
- panend
- pancancel
- panleft
- panright
- panup
- pandown

## Source

https://github.com/visgl/mjolnir.js/blob/master/src/hammerjs/recognizers/pan.ts
Loading

0 comments on commit ca19360

Please sign in to comment.