Changelog ========= Changes to this project will be documented in this file. This project mostly adheres to [Semantic Versioning](http://semver.org/). 0.56.0 ------ This release includes major performance improvements and a new animation engine. Beware of the breaking change with [`.up-current`](/up-nav-a.up-current)! ### Navigation feedback Maintaining the [`.up-current`](/up-nav-a.up-current) on all links turned out to be a major performance bottleneck, so we had to make some breaking changes: - The [`.up-current`](/up-nav-a.up-current) class is now only assigned to links with an [`[up-nav]`](/up-nav) attribute, or to links within a container with an [`[up-nav]`](/up-nav) attribute. You should assign the [`[up-nav]`](/up-nav) attribute to all navigational elements that rely on `.up-current` for styling`. - You can also globally configure selectors for your navigational elements in `up.feedback.config.navs`: up.feedback.config.navs.push('.my-nav-bar') - The normalized URLs of [`[up-nav]`](/up-nav) links are now cached for performance reasons. - [`[up-nav]`](/up-nav) links are only updated once when multiple fragments are updated in a single [replacement](/a-up-target). ### Animation - When performing an [animated page transition](/up.motion) Unpoly will no longer create copies of the old and new fragment versions. The animation will instead be performed on the original fragment versions. - When animating an element with an existing [CSS transition](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions), Unpoly will now pause the CSS transition in its current state, perform the animation, then resume the CSS transition. - Unpoly now does less work when animation is disabled globally through `up.motion.config.enabled = false`. - [`up.morph()`](/up.morph) will now expect the new fragment version to be detached from the DOM before morphing. - [`up.morph()`](/up.morph) will now detach the old fragment version from the DOM after morphing. - The [`up.morph()`](/up.morph) function has been demoted from *stable* to *experimental*. - [`up.motion.finish()`](/up.motion.finish) now longer queries the DOM when there are no active animations. ### Application layout - When Unpoly cannot find the viewport of an element, it will now always considers `document` to be the viewport. ### Fragment updates - The [`up:fragment:destroyed`](/up:fragment:destroyed) event is now emitted after the fragment has been removed from the DOM. The event is emitted on the former parent of the removed fragment. ### Utility functions - Fix a bug where `up.util.isBlank()` returned `true` for a function value ### General - Partially remove jQuery from internal code for performance reasons. We want to eventually remove jQuery as a dependency. - Cache the results of feature detection for performance reasons. - Unpoly is now more efficient when selecting elements from the DOM. - Unpoly is now more efficient when reacting to mouse events. 0.55.1 ------ This release restores support for Internet Explorer 11, which we accidentally broke in 0.55.0. Thanks to [@foobear](https://github.com/foobear) for helping with this. 0.55.0 ------ ### Fragment updates - Unpoly now detects when an [`[up-target]`](/up-target) with multiple selectors would [replace](/up.replace) the same element multiple times. In such a case the target selector will be shortened to contain the element once. - Unpoly now detects when an [`[up-target]`](/up-target) with multiple selectors contains nested elements. In such a case the target selector will be shortened to only contain the outmost element. ### Utility functions - [`up.util.uniq()`](/up.util.uniq) now works on DOM elements and other object references. - New experimental function [`up.util.uniqBy()`](/up.util.uniqBy). This function is like [`uniq`](/up.util.uniq), accept that the given function is invoked for each element to generate the value for which uniquness is computed. - Changes to [utility functions](/up.util) that work on lists ([`up.util.each()`](/up.util.each), [`up.util.map()`](/up.util.map), [`up.util.all()`](/up.util.all), [`up.util.any()`](/up.util.any), [`up.util.select()`](/up.util.select), [`up.util.reject()`](/up.util.reject)): - List functions now accept a property name instead of a mapping function: ``` users = [{ name: 'foo' }, { name: 'bar' }] up.util.map(users, 'name') // ['foo', 'bar'] ``` - List functions now pass the iteration index as a second argument to the given function: ``` users = [{ name: 'foo' }, { name: 'bar' }] up.util.map(users, function(user, index) { return index }) // [0, 1] ``` 0.54.1 ------ This release contains no new features, but will help you when using tools like Babel or Webpack: - Unpoly now ship without any uses of [`eval()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval) in its JavaScript sources. Use of `eval()` had previously prevented minifiers from shortening local variables in some files. - Documentation in Unpoly's JavaScript sources can no longer be confused with [JSDoc](http://usejsdoc.org/) comments. Unpoly does not use JSDoc, but some build pipelines eagerly look for JSDoc comments to generate type information. 0.54.0 ------ ### Passive updates - [`[up-hungry]`](/up-hungry) elements will now also be updated when the server responds with an error code. This helps when `[up-hungry]` is used to display error messages. ### Forms - When a [form is submitted](/form-up-target) you can now consistently refer to that form element as `&` in CSS selectors ([like in Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector)). E.g. to reveal the first error message within a failed form submission: ```
``` In this case `& .error` will be replaced by `#my-form .error` before submission. This affects CSS selectors in the following HTML attributes: - `form[up-target]` - `form[up-fail-target]` - `form[up-reveal]` - `form[up-fail-reveal]` ### Linking to fragments * When a [link is followed](/a-up-target) you can now consistently refer to that link element as `&` in CSS selectors ([like in Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector)). This affects CSS selectors in the following HTML attributes: - `a[up-target]` - `a[up-fail-target]` - `a[up-reveal]` - `a[up-fail-reveal]` ### Fragment update API - New option for [`up.replace()`](/up.replace): `{ keep: false }` will disable preservation of [`[up-keep]`](/up-keep) elements. - New option for [`up.replace()`](/up.replace): `{ hungry: false }` will disable updates of [`[up-hungry]`](/up-hungry) elements. 0.53.4 ------ ### Passive updates - Updates for [`[up-hungry]`](/up-hungry) elements will no longer auto-close a [modal dialog](/up.modal). - Updates for [`[up-hungry]`](/up-hungry) elements will no longer auto-close a [popup overlay](/up.popup). - CSRF-related `` tags are no longer updated automatically with every request. This is to prevent unnecessary DOM jitter in applications that don't rotate CSRF tokens. ### Popup overlays - Calling `up.popup.attach()` without a target selector will now throw an error. 0.53.2 ------ ### General - Failed requests in event handlers of CSS selectors like `form[up-target]` no longer print `Uncaught (in promise)` to the error console. You still need to catch and handle rejected promises in your own code when it calls Unpoly functions. ### Animated transitions - Fix a bug where a page transition would flicker if [revealing](/up.reveal) was animated globally by setting `up.layout.config.duration`. ### Preloading - Fix a bug where [preloading](/a-up-target) would not always be aborted when stopping to hover before [`up.proxy.config.preloadDelay`](/up.proxy.config#up.proxy.config.preloadDelay). 0.53.1 ------ ### General - Fix a bug where replacing the first element on the page (in DOM order) would shift the scroll position if animation is disabled. - Fix a bug where query params would be lost when Unpoly would fall back to a full page load. ### Optional server protocol - The optional cookie the server can send to [signal the initial request method](/up.protocol#signaling-the-initial-request-method) will now be removed as soon as Unpoly has booted. ### Animations - Fix a bug where the animation `move-from-top` would finish instantly after animating with `move-to-top`. - Fix a bug where the animation `move-from-right` would finish instantly after animating with `move-to-right`. - Fix a bug where the animation `move-from-bottom` would finish instantly after animating with `move-to-bottom`. - Fix a bug where the animation `move-from-left` would finish instantly after animating with `move-to-left` 0.53.0 ------ ### New module: Passive updates Thi work-in-progress package [`up.radio`](/up.radio) will contain functionality to passively receive updates from the server. Currently the following functionality is implemented: - Elements with an [`[up-hungry]`](/up-hungry) attribute are [updated](/up.replace) whenever there is a matching element found in a successful response. The element is replaced even when it isn't [targeted](/a-up-target) directly. Use cases for this are unread message counters or notification flashes. Such elements often live in the layout, outside of the content area that is being replaced. - When a reserver response contains a `` or `` element, it is automatically updated in the current page. ### General - Changes when generating CSS selectors for elements: - `[aria-label]` attributes are used if no better attributes exist (like `[id]` or `[up-id]` attributes). - Attribute values with quotes are now escaped if they appear in an attribute selector. - Attribute selectors now use double quotes instead of single quotes. - When a `[name]` attribute is used, the tag name is also used. E.g. `meta[name="csrf-token"]`. - Element IDs that contain non-word characters (e.g. slashes, spaces, dots), will now generate an attribute selector like `[id="foo/bar"]`. ### Forms - You can give forms an `[up-fail-reveal]` attribute to indicate which element should be [revealed](/up.reveal) when the server responds with an error. You may use this, for example, to reveal the first validation error message: ``` ``` - Forms with an `[up-reveal]` attribute will now only honor the attribute when the form submission was successful. - Forms with an `[up-restore-scroll]` attribute will now only honor the attribute when the form submission was successful. - Forms with an `[up-reveal="css-selector"]` attribute will no longer crash when the selector could not be found. - Fix a bug where you couldn't submit a form if it's ID contains a slash character ([#46](https://github.com/unpoly/unpoly/issues/46)). ### Links - You can give links an `[up-fail-reveal]` attribute to indicate which element should be [revealed](/up.reveal) when the server responds with an error - Links with an `[up-reveal]` attribute will now only honor the attribute when the link could be followed successfully. - Links with an `[up-restore-scroll]` attribute will now only honor the attribute when the link could be followed successfully. - Links with an `[up-reveal="css-selector"]` attribute will no longer crash when the selector could not be found. ### Animations - When [replacing](/up.replace) multiple elements, it is no longer possible to use different [transitions](/up.morph) for each element. The same transition is always applied to all elements. 0.52.0 ------ ### Browser support - No longer prints an error to console when registering a [macro](/up.macro) on an unsupported browser. ### AJAX requests - Unpoly can now detect the final URL of a redirect response without the [optional server protocol](/up.protocol). The server protocol is still needed to detect redirects on Internet Explorer 11. - When making HTTP requests Unpoly will now always merge params in the URL's query section with params from the `{ data }` option. ### Forms - [Following](/up.follow) a link now emits an [`up:link:follow`](/up:link:follow) event. The event can be prevented. ### Forms - [Submitting](/up.submit) a form through Unpoly now emits an [`up:form:submit`](/up:form:submit) event. The event can be prevented. 0.51.1 ------ ### Fragment updates - Fix a bug where Unpoly would crash when replacing a fragment with a `