---
area: "Changes"
parent: "Changes"
url: "https://unpoly.com/changes/0.50.0"
released: "2017-12-06"
---
<nav aria-label="Unpoly docs">[All docs](https://unpoly.com/index.md) · [Changes](https://unpoly.com/changes.md)</nav>

# Version 0.50.0

Released on December 06, 2017 with [33 commits](https://github.com/unpoly/unpoly/commits/v0.50.0)

This is a major update with some breaking changes. Expect a few more updates like this as we move closer to our 1.0 release in 2018.

<nav aria-label="Contents">

- [General](#general)
- [Browser support](#browser-support)
- [AJAX](#ajax)
- [Links](#links)
- [Fragment updates](#fragment-updates)
- [History](#history)
- [Forms](#forms)
- [Tooltips](#tooltips)
- [Server protocol](#server-protocol)
- [Animation](#animation)
- [Modals](#modals)
- [Popups](#popups)
- [Events](#events)
- [Utility functions](#utility-functions)
- [Ruby on Rails bindings](#ruby-on-rails-bindings)

</nav>

## General {#general}

- jQuery 3 is now supported in addition to jQuery 1.9+ and jQuery 2.
- ⚠️ Unpoly now uses [native Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises) instead of jQuery deferreds.
- You can now help improve Unpoly's documentation by clicking an _Edit this page_ link on any [unpoly.com](https://unpoly.com/index.md) subpage (like [`[up-follow]`](https://unpoly.com/api/up-follow.md)).

## Browser support {#browser-support}

- ⚠️ To enable support for Internet Explorer 11 you need to install a Polyfill for [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises). We recommend [ES6-promise](https://github.com/stefanpenner/es6-promise) (2.4 KB gzipped).
- Fix a bug where Unpoly would not boot on Safari 9 and 10 if the initial page was loaded with a `POST` method.

## AJAX {#ajax}

- ⚠️ Unpoly now uses [native XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) instead of `jQuery.ajax()`. If you have been hacking into Unpoly's networking through `jQuery.ajaxPrefilter()`, you must now use the [`up:proxy:load`](https://unpoly.com/up:proxy:load) event.
- 🧩 [`up.ajax()`](https://unpoly.com/api/up.ajax.md) has been deprecated since its signature is incompatible with native promises. Please use [`up.request()`](https://unpoly.com/api/up.request.md) instead, whose promise fulfills with an [`up.Response`](https://unpoly.com/api/up.Response.md) object.
- 🧩 The `up:proxy:received` event has been renamed to [`up:proxy:loaded`](https://unpoly.com/up:proxy:loaded).
- ⚠️ The [`up:proxy:load`](https://unpoly.com/up:proxy:load) event properties have changed. You can now access request properties through a key `{ request }`, e.g. `event.request.url`.
- The [`up:proxy:load`](https://unpoly.com/up:proxy:load) event can now be prevented to prevent a request from being sent to the network.
- The [`up:proxy:load`](https://unpoly.com/up:proxy:load) event now allows listeners to change request headers by manipulating the `event.request.headers` object.
- A new event [`up:proxy:fatal`](https://unpoly.com/up:proxy:fatal) will be [emitted](https://unpoly.com/api/up.emit.md) when an [AJAX request](https://unpoly.com/api/up.request.md) encounters fatal error like a timeout or loss of network connectivity.

## Links {#links}

- ⚠️ Links with unsafe HTTP methods like `POST` are no longer marked as [`.up-current`](https://unpoly.com/api/up-current.md), even if their `[href]` matches the current URL.
- New experimental function [`up.link.isSafe()`](https://unpoly.com/api/up.link.isSafe.md). It returns whether the given link has a [safe](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1) HTTP method like `GET`.

## Fragment updates {#fragment-updates}

- When a selector was not found in the response, the error notification now offers a link to show the unexpected response.
- ⚠️ The event [`up:fragment:destroy`](https://unpoly.com/up:fragment:destroy) can no longer be prevented.

## History {#history}

- Clicking a link with an [`[up-restore-scroll]`](https://unpoly.com/api/up-follow.md#up-restore-scroll) attribute will no longer crash if no previous scroll position for given URL is known ([#25](https://github.com/unpoly/unpoly/issues/25))
- Fix a bug where going back in history would sometimes not call destructors ([#24](https://github.com/unpoly/unpoly/issues/24))

## Forms {#forms}

- [`up.observe()`](https://unpoly.com/api/up.observe.md) no longer sends multiple callbacks when a previous callback was slow to respond.

## Tooltips {#tooltips}

- Fix a bug where tooltips would sometimes stay open when many tooltips are opened and closed concurrently.

## Server protocol {#server-protocol}

- When the server [signals a redirect with a `X-Up-Location` header](https://unpoly.com/api/up.protocol.md#redirect-detection), sending a [`X-Up-Method`](https://unpoly.com/api/X-Up-Method.md) header is now optional. If it is missing, `GET` is assumed.
- Unpoly will often update a different selector in case the request fails. This second selector is now sent to the server as a [`X-Up-Fail-Target`](https://unpoly.com/api/X-Up-Fail-Target.md) header.
- You can now [configure how CSRF tokens are sent your server-side framework](https://unpoly.com/api/up.protocol.config.md).
- ⚠️ CSRF tokens are no longer sent for cross-domain requests.

## Animation {#animation}

- ⚠️ `up.motion.none()` has been removed without replacement. Just pass `false` or the string `'none'` to indicate a animation or transition which has no visual effects and completes instantly.
- ⚠️ [`up.motion.finish()`](https://unpoly.com/api/up.motion.finish.md) is now async. It returns a promise that fulfills when all animations are finished.
- ⚠️ [`up.motion.finish()`](https://unpoly.com/api/up.motion.finish.md) now also finishes animations in ancestors of the given element.

## Modals {#modals}

- [`up.follow()`](https://unpoly.com/api/up.follow.md) will now open a modal if the given link has an [`[up-modal]`](https://unpoly.com/api/up-modal.md) attribute
- [`[up-modal]`](https://unpoly.com/api/up-modal.md) links can now have an `[up-fail-target]` attribute to indicate which selector to replace for an non-200 response
- Fix a bug where preloading an up-modal link would create an invisible .up-modal container in the DOM.

## Popups {#popups}

- [`up.follow()`](https://unpoly.com/api/up.follow.md) will now open a popup if the given link has [`[up-popup]`](https://unpoly.com/api/up-popup.md) attribute
- up-popup links can now have an up-fail-target attribute to indicate which selector to replace for an non-200 response
- Fix a bug where preloading an up-popup link would create an invisible .up-popup container in the DOM.
- ⚠️ [`up.popup.attach()`](https://unpoly.com/api/up.popup.attach.md) now throws an error if neither `{ url }` nor `{ html }` options are given.

## Events {#events}

- ⚠️ When async functions emit an event and that event is prevented, the async function now rejects with an [`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error).
- ⚠️ When async functions are called wth `{ confirm: true }` and the user denies confirmation, the async function now rejects with an [`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error).

## Utility functions {#utility-functions}

- ⚠️ [`up.util.setTimer()`](https://unpoly.com/up.util.setTimer) is now always async, even when called with a delay of `0` (zero). The function is now stable.
- ⚠️ `up.util.isHash()` has been removed without replacement. In your code you can replace `up.util.isHash(x)` with `up.util.isObject(x) && !up.util.isFunction(x)`.
- ⚠️ `up.util.resolvedDeferred()` has been removed without replacement. Use `Promise.resolve()` instead.
- ⚠️ `up.util.resolvedPromise()` has been removed without replacement. Use `Promise.resolve(`) instead.
- ⚠️ `up.util.rejectedPromise()` has been removed without replacement. Use `Promise.reject()` instead.
- ⚠️ `up.util.unresolvableDeferred()` has been removed without replacement. Use `new Promise(function() {})` instead.
- ⚠️ `up.motion.when()` has been removed without replacement. Use `Promise.all()` instead.
- [`up.util.isString()`](https://unpoly.com/api/up.util.isString.md) now also returns true for `String` instances (in addition to string literals)
- [`up.util.isNumber()`](https://unpoly.com/api/up.util.isNumber()) now also returns true for `Number` instances (in addition to number literals)

## Ruby on Rails bindings {#ruby-on-rails-bindings}

- New method `up.fail_target` available in controllers, helpers and views. It returns the selector targeted for a failed response.
- New method `up.fail_target?(target)` available in controllers, helpers and views. It returns whether the given selector is targeted for a failed response.
- New method `up.any_target?(target)` available in controllers, helpers and views. It returns whether the given selector is targeted for a either a successful or failed response.

