---
name: "up.on"
area: "API"
kind: "JavaScript function"
parent: "up.event module"
url: "https://unpoly.com/api/up.on"
---
<nav aria-label="Unpoly docs">[All docs](https://unpoly.com/index.md) · [up.event module](https://unpoly.com/api/up.event.md)</nav>

# up.on([element], types, [selector], [options], listener)

Listens to a [DOM event](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Events) on `document` or a given element.

`up.on()` has some quality of life improvements over [`Element#addEventListener()`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener):

- You may pass a selector for [event delegation](https://davidwalsh.name/event-delegate).
- The [event target](https://developer.mozilla.org/en-US/docs/Web/API/Event/target) is automatically passed as a second argument.
- Your event listener will not be called when Unpoly has not [booted](https://unpoly.com/api/up.boot.md) in an unsupported browser
- You may register a listener to multiple events by passing a space-separated list of event names (e.g. `"click mousedown"`)
- You may register a listener to multiple elements in a single `up.on()` call, by passing a [list](https://unpoly.com/api/List.md) of elements.
- Any [data attached to the observed element](https://unpoly.com/learn/data.md) will be passed as a third argument to your handler function.

You can prevent the event from being processed further with [up.event.halt(event)](https://unpoly.com/api/up.event.halt.md).

<nav aria-label="Contents">

#### Contents

- [Basic example](#basic-example)
- [Event delegation](#event-delegation)
- [Attaching data](#attaching-data)
- [Unbinding an event listener](#unbinding-an-event-listener)
- [Binding to multiple elements](#binding-to-multiple-elements)
- [Binding to multiple event types](#binding-to-multiple-event-types)
- [Parameters](#parameters)
- [Return value](#return-value)

</nav>

## Basic example {#basic-example}

The code below will call the listener when a `<a>` is clicked anywhere in the `document`:

```js
up.on('click', 'a', function(event, element) {
  console.log("Click on a link %o", element)
})
```

You may also bind the listener to a given element instead of `document`:

```js
let form = document.querySelector('form')
up.on(form, 'click', function(event, form) {
  console.log("Click within %o", form)
})
```

## Event delegation {#event-delegation}

You may pass both an element and a selector for [event delegation](https://davidwalsh.name/event-delegate).

The example below registers a single event listener to the given `form`, but only calls the listener when the clicked element is a `select` element:

```
let form = document.querySelector('form')
up.on(form, 'click', 'select', function(event, select) {
  console.log("Click on select %o within %o", select, form)
})
```

## Attaching data {#attaching-data}

Any [data attached to the observed element](https://unpoly.com/learn/data.md) will be passed to your event handler.

For instance, this element has attached data in its [`[up-data]`](https://unpoly.com/api/up-data.md) attribute:

```html
<span class="user" up-data="{ age: 18, name: 'Bob' }">Bob</span>
```

The parsed data will be passed to your event handler as a third argument:

```js
up.on('click', '.user', function(event, element, data) {
  console.log("This is %o who is %o years old", data.name, data.age)
})
```

## Unbinding an event listener {#unbinding-an-event-listener}

`up.on()` returns a function that unbinds the event listeners when called:

```js
// Define the listener
let listener =  function(event) { ... }

// Binding the listener returns an unbind function
let unbind = up.on('click', listener)

// Unbind the listener
unbind()
```

There is also a function [`up.off()`](https://unpoly.com/api/up.off.md) which you can use for the same purpose:

```js
// Define the listener
let listener =  function(event) { ... }

// Bind the listener
up.on('click', listener)

// Unbind the listener
up.off('click', listener)
```

## Binding to multiple elements {#binding-to-multiple-elements}

You may register a listener to multiple elements in a single `up.on()` call, by passing a [list](https://unpoly.com/api/List.md) of elements:

```js
let allForms = document.querySelectorAll('form')
up.on(allForms, 'submit', function(event, form) {
  console.log('Submitting form %o', form)
})
```

## Binding to multiple event types {#binding-to-multiple-event-types}

You may register a listener to multiple event types by separating types with a space or comma:

```js
let element = document.querySelector(...)
up.on(element, 'mouseenter mouseleave', function(event) {
  console.log('Mouse entered or left')
})
```

---

## Parameters {#parameters}

### Observed events {#parameters-observed-events}

#### [element=document] {#element}

(optional)

The element on which to register the event listener.

If no element is given, the listener is registered on the `document`.

Type: [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) | [jQuery](https://learn.jquery.com/using-jquery-core/jquery-object/)

#### types {#types}

(required)

The event types to bind to.

Multiple event types may be passed as either a space-separated string (`'foo bar'`), a comma-separated string (`'foo, bar'`) or as an array of types (`['foo', 'bar']`).

Type: string | [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<string>

#### [selector] {#selector}

(optional)

The selector of an element on which the event must be triggered.

Omit the selector to listen to all events of the given type, regardless of the event target.

If the selector is not known in advance you may also pass a function that returns the selector. The function is evaluated every time an event with the given type is observed.

Type: string | Function():string

### Listener {#parameters-listener}

#### [options.passive=false] {#options.passive}

(optional)

Whether to register a [passive event listener](https://developers.google.com/web/updates/2016/06/passive-event-listeners).

A passive event listener may not call `event.preventDefault()`. This in particular may improve the frame rate when registering `touchstart` and `touchmove` events.

Type: boolean

#### [options.once=false] {#options.once}

(optional)

Whether the listener should run at most once.

If `true` the listener will automatically be unbound after the first invocation.

Type: boolean

#### [options.capture=false] {#options.capture}

(optional)

Whether the listener should run before the event is emitted on the element.

See [event capturing](https://javascript.info/bubbling-and-capturing#capturing) for more information about DOM event processing phases.

Type: boolean

#### listener {#listener}

(required)

The listener function that should be called.

The function takes the observed element as a second argument. The element's [attached data](https://unpoly.com/learn/data.md) is passed as a third argument.

Type: Function(event, [element], [[data](https://unpoly.com/learn/data.md)])

---

## Return value {#return-value}

A function that unbinds the event listeners when called.

Type: Function()

