unpoly-rails 2.0.0.pre.rc11 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of unpoly-rails might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 16c5d23ef0ef94cd9a7cb5ef926ff4931aa1e2b19b32548c35b0fd527de83d91
4
- data.tar.gz: 4748c57d0da382a24dd48f594ca3f61838387dc3fd3630da416843d8c45dc079
3
+ metadata.gz: 60a37ba382e3664b7224d805da146e4a7364e7880dbcdb80580a0e9ef4406672
4
+ data.tar.gz: 8d899df9850761c7b07849b2ded8a241e334c9e4cbc3ac8dc5003af0629206ad
5
5
  SHA512:
6
- metadata.gz: 4b5ff85fee318e8200aef941b878d8bdac28872ff0a46e2e2468c3c28e883065daa30f96858418f900f6566632b0d469632ec8736cca550db2aa71c97fecacf0
7
- data.tar.gz: 8f51f5822089f69e36da2a3c8cf7942bec84965014f0de1ebb524aaf13288697301e8fa68c747ee4b8d89a5e623eed5768bd904a87e0989ad0490527bdca2774
6
+ metadata.gz: 9caee93e9aa5f35eb7d7dcb276f1e48b1231b2f003e3bd56285105869f15759cbf7d2cfc57cf66dd2470b85df54775826352ea568e81f1151d1a981c04f0bc69
7
+ data.tar.gz: e53cee4842b88880f71769552dee074e4f865bfbae43033daf6c6a13950c73f0e5bf284ab7b9babfaff5677400ae0811111a8fac9dbafdd6a53e8a67b8c67796
data/CHANGELOG.md CHANGED
@@ -3,67 +3,135 @@ Changelog
3
3
 
4
4
  Changes to this project will be documented in this file.
5
5
 
6
+ If you're upgrading from an older Unpoly version you should load [`unpoly-migrate.js`](https://unpoly.com/changes/upgrading) to enable deprecated APIs.
7
+
6
8
  You may browse a formatted and hyperlinked version of this file at <https://unpoly.com/changes>.
7
9
 
8
10
 
9
11
  2.0.0
10
12
  -----
11
13
 
12
- [See Unpoly 2 slides](http://triskweline.de/unpoly2-slides/)
13
-
14
- TODO
15
- ----
16
-
17
- This list is **far** from complete.
18
-
19
- - up.network.config.slowDelay is now 800 (up from 300)
20
- - up.network.config.cacheSize is now 50 (down from 70)
21
- - up.network.isBusy() / isIdle() takes preload events into account
22
- - up.observe() callback may return a promise that will prevent callback calls while running
23
- - `[aria-label]` attributes are no longer used to build a target selector
24
- - Options removed form modals: up-width, up-max-width, up-height. Use up-size or up-class.
25
- - Failed responses now change the URL
26
- - TODO ...
27
- - up.history.config.restoreScroll has been removed.
28
- - Feedback works when a layer has no history
29
- - Layer A11Y
30
- - inert
31
- - aria-hidden
32
- - focus new
33
- - focus return on close
34
- - up.nav sets [aria-current]
35
- - up.history.config.enabled
36
- - Requests sent by Unpoly no longer have a `X-Requested-With: XMLHttpRequest` header.
37
- If you need that old behavior: up.on('up:request:load', function(event) { event.request.headers['X-Requested-With'] = 'XMLHttpRequest' })
38
- - up.network.config.requestMetaKeys
39
- - up:link:follow is no longer sent when preloading, up:link:preload still is
40
- - Preserve focus when validating forms; Add { focus } option for fragment update
41
- - up.Request.prototype.isFatalError() has been removed without replacement. Network errors now reject with an error, and not a response.
42
- - [up-main], [up-main=overlay], [up-main=modal]
43
- - parseSelector can parse attribute selectors with prefix, infix, suffix, space-separated, dash-separated
44
- - up.validate() may now be called with a form element
45
- - validating emits up:form:validate instead of up:form:submit
46
- - When a compiler throws an error, other compilers will now run anyway
47
- - When a destructor throws an error, other destructors will now run anyway
48
- - Bootstrap integration
49
- - Minimal: active, nav, navbar
50
- - Bootstrap modal styles are no longer used for Unpoly modals
51
- - Now supports three major Bootstrap versions:
52
- - unpoly-bootstrap3.js
53
- - unpoly-bootstrap4.js
54
- - unpoly-bootstrap5.js
55
- - Hungry elements no longer get the transition by default. You need to set [up-transition] on the hungry element.
56
- - Rejections are now shown if the log is enabled
57
- - up.on() can passive: true
58
- - Preloads on touchstart and mousedown
59
- - Digit groups separators (`60_000`) are a stage 3 ES6 feature and also supported in number attributes.
14
+ Unpoly 2 ships with many new features and API improvements, unlocking many use cases that were not possible with Unpoly 1.
15
+
16
+ For an in-depth guide to all changes, see our [Unpoly 2 presentation](http://triskweline.de/unpoly2-slides/) (150 slides).
17
+
18
+ If you're upgrading from an older Unpoly version you should load [`unpoly-migrate.js`](https://unpoly.com/changes/upgrading) to enable deprecated APIs. Also see below for an [overview of breaking changes](#overview-of-breaking-changes).
19
+
20
+ ### Change overview
21
+
22
+ #### Less need for boilerplate configuration
23
+
24
+ - Fragment links often replace the primary content element of your application layout. For this purpose you can now define [default targets](/up-main) that are automatically updated when no target selector is given.
25
+ - Unpoly can be configured to [handle all links and forms](/handling-everything), without any `[up-...]` attributes.
26
+ - We have examined many real-world Unpoly apps for repetitive configuration and made these options the new default.
27
+
28
+ #### New Layer API
29
+
30
+ - A new [layer API](/up.layer) replaces modals and popups.
31
+ - Layers can be stacked infinitely.
32
+ - Layers are fully isolated, meaning a screen in one layer will not accidentally see elements or events from another layer. For instance, [fragment links](/up.link) will only update elements from the [current layer](/up.layer.current) unless you [explicitly target another layer](/layer-option).
33
+ - A variety of [overlay modes](/layer-terminology) are supported, such as modal dialogs, popup overlays or drawers. You may [customize their appearance and behavior](/customizing-overlays).
34
+
35
+ #### Subinteractions
36
+
37
+ - Overlays allow you to break up a complex screen into [subinteractions](/subinteractions).
38
+ - Subinteractions take place in overlays and may span one or many pages. The original screen remains open in the background.
39
+ - Once the subinteraction is *done*, the overlay is [closed](/closing-overlays) and a result value is communicated back to the parent layer.
40
+
41
+ #### Navigation intent
42
+
43
+ - You can now define whether a framgent update constitutes a user navigation. Switching screens needs other defaults than updating a tiny box.
44
+ - User navigation aborts earlier requests, fixing race conditions on slow connections.
45
+
46
+ #### Accessibility
47
+
48
+ - New overlays are focused automatically and trap focus in a cycle. Closing the overlay re-focuses the link that opened it.
49
+ - Focus is automatically managed when rendering major new content. A new [`[up-focus]` attribute](/focus-option) allows
50
+ you to explicitely move the user's focus as you update fragments.
51
+ - Keyboard navigation is supported everywhere.
52
+ - Focus, selection and scroll positions are preserved within an updated fragment.
53
+
54
+ #### Reworked Bootstrap integration
55
+
56
+ - The Bootstrap integration is now minimal and as unopinionated as possible. Little to no Bootstrap CSS is overridden.
57
+ - Bootstrap versions 3, 4 and 5 are now supported.
58
+
59
+ #### Quality of live improvements
60
+
61
+ - Unpoly now ships with a bandwidth-friendly [polling implementation](/up-poll) that handles many edge cases.
62
+ - The position of a clicked link is considered when deciding which element to replace. If possible, Unpoly will update an selector in the vicinity of the link that triggered the fragment update. This helps with multiple self-contained components (with the same selector) on the same page.
63
+ - The [log](/up.log) output is more much more compact and has a calmer formatting.
64
+ - New fragments are no longer revealed by default. Instead Unpoly scrolls to the top when the [main target](/up-main) has changed, but does not scroll otherwise.
65
+ - History is no longer changed by default. Instead Unpoly updates history only when a [main target](/up-main) has changed.
66
+ - All scroll-related options have been unified in a single [`[up-scroll]` attribute](/scroll-option).
67
+ - Many optimizations have been made to preserve bandwidth on slow connections. For example, Unpoly stops [preloading](/up-preload) and [polling](/up-poll) whenthe connection has high latency or low throughput.
68
+ - The client-side cache can be carefully managed by both the client and server.
69
+ - Unpoly 1 had many functions for updating fragments (`up.replace()`, `up.extract()`, `up.modal.extract()`, etc.). Unpoly 2 has unified these into a single function `up.render()`.
70
+ - Event handlers to `up:link:follow`, `up:form:submit` etc. may change the render options for the coming fragment update.
71
+ - Added more options to handle [unexpected server responses](/server-errors), including the new `up:fragment:loaded` event.
72
+
73
+ #### Extended server protocol
74
+
75
+ The optional server protocol has been extended with additional headers that the server may use to interact with the frontend. For example:
76
+
77
+ - The server may [emit events on the frontend](/X-Up-Events).
78
+ - The server may [close overlays](/X-Up-Accept).
79
+ - The server may [change the render target](/X-Up-Target) for a fragment update.
80
+
81
+ See `up.protocol` for a full list of features.
82
+
83
+ If you are using Ruby on Rails, the new protocol is already implemented by the [`unpoly-rails`](https://rubygems.org/gems/unpoly-rails) gem.
84
+
85
+ If you are using Elixir / Phoenix, the new protocol is already implemented by the [`ex_unpoly`](https://hex.pm/packages/ex_unpoly) package.
86
+
87
+
88
+ ### Overview of breaking changes
89
+
90
+ Please use [`unpoly-migrate.js`](/changes/upgrading) for a very smooth upgrade process from Unpoly 0.x or 1.x to Unpoly 2.0.
91
+
92
+ By loading <code>unpoly-migrate.js</code>, calls to most old APIs will be forwarded to the new version. A deprecation notice will be logged to your browser console. This way you can upgrade Unpoly, revive your application with a few changes, then replace deprecated API calls under green tests.
93
+
94
+ There's a short list of changes that we cannot fix with aliases.
95
+
96
+ #### Overlays (modals, popups) have different HTML
97
+
98
+ But it's similar. E.g. `<div class="modal">` becomes `<up-modal>`.
99
+
100
+ #### Unpoly only sees the current layer
101
+
102
+ You can target other layers with `{ layer: 'any' }`.
103
+
104
+ #### Async functions no longer wait for animations
105
+
106
+ You might or might not notice. In cases where you absolutely do need to wait, an `{ onFinished }` callback can be used.
107
+
108
+ #### Tooltips are no longer built-in
109
+
110
+ But there are a million better libraries.
111
+
112
+
113
+ ### Unpoly 1 maintenance
114
+
115
+ With the release of Unpoly we're ending maintenance of Unpoly 1. Expect little to no changes to Unpoly 1 in the future. GitHub issues that have been fixed in Unpoly 2 will be closed.
116
+
117
+ The legacy documentation for Unpoly 1.x has been archived to <https://v1.unpoly.com>.
118
+
60
119
 
61
120
 
62
121
  1.0.0
63
122
  -----
64
123
 
65
- - TODO
124
+ For six years Unpoly has been released under a 0.x version number. To establish the maturity and stability of the project, we're releasing today's version as 1.0.0.
125
+
126
+ There are only three changes from 0.62.1:
127
+
128
+ - Fix a bug where `up.util.escapeHTML()`` would not escape single quotes.
129
+ - Unpoly will no longer wait a JavaScript execution task to boot after `DOMContentLoaded`. This may improve the stability of test suites that previously interacted with the page too soon.
130
+ - You may now disable the Unpoly banner in the development console with `up.log.config.banner = false`. (change by @hfjallemark).
131
+
132
+ This is the last release of the 0.x API line. We're tracking its code in the [`1.x-stable`](https://github.com/unpoly/unpoly/tree/1.x-stable), but expect little to no changes in the future.
66
133
 
134
+ The next release will be [Unpoly 2](https://triskweline.de/unpoly2-slides). It will include major (but mostly backwards compatible) renovations to its API, unlocking many use cases that were not possible with Unpoly 1.
67
135
 
68
136
 
69
137
  0.62.1
@@ -300,6 +300,41 @@ Returns the first descendant element matching the given selector.
300
300
  return !event.defaultPrevented;
301
301
  };
302
302
 
303
+ }).call(this);
304
+ (function() {
305
+ var u;
306
+
307
+ u = up.util;
308
+
309
+ up.migrate.postCompile = function(elements, compiler) {
310
+ var element, i, keepValue, len, results, value;
311
+ if (keepValue = compiler.keep) {
312
+ up.migrate.warn('The { keep: true } option for up.compiler() has been removed. Have the compiler set [up-keep] attribute instead.');
313
+ value = u.isString(keepValue) ? keepValue : '';
314
+ results = [];
315
+ for (i = 0, len = elements.length; i < len; i++) {
316
+ element = elements[i];
317
+ results.push(element.setAttribute('up-keep', value));
318
+ }
319
+ return results;
320
+ }
321
+ };
322
+
323
+ up.migrate.targetMacro = function(queryAttr, fixedResultAttrs, callback) {
324
+ return up.macro("[" + queryAttr + "]", function(link) {
325
+ var optionalTarget, resultAttrs;
326
+ resultAttrs = u.copy(fixedResultAttrs);
327
+ if (optionalTarget = link.getAttribute(queryAttr)) {
328
+ resultAttrs['up-target'] = optionalTarget;
329
+ } else {
330
+ resultAttrs['up-follow'] = '';
331
+ }
332
+ e.setMissingAttrs(link, resultAttrs);
333
+ link.removeAttribute(queryAttr);
334
+ return typeof callback === "function" ? callback() : void 0;
335
+ });
336
+ };
337
+
303
338
  }).call(this);
304
339
 
305
340
  /***
@@ -538,6 +573,11 @@ Returns the first descendant element matching the given selector.
538
573
  up.migrate.renamedProperty(up.feedback.config, 'navs', 'navSelectors');
539
574
 
540
575
  }).call(this);
576
+
577
+ /***
578
+ @module up.link
579
+ */
580
+
541
581
  (function() {
542
582
  up.migrate.parseFollowOptions = function(parser) {
543
583
  parser.string('flavor');
@@ -549,6 +589,42 @@ Returns the first descendant element matching the given selector.
549
589
  return parser.boolean('restoreScroll');
550
590
  };
551
591
 
592
+
593
+ /***
594
+ [Follows](/up.follow) this link as fast as possible.
595
+
596
+ This is done by:
597
+
598
+ - [Following the link through AJAX](/a-up-follow) instead of a full page load
599
+ - [Preloading the link's destination URL](/a-up-preload)
600
+ - [Triggering the link on `mousedown`](/a-up-instant) instead of on `click`
601
+
602
+ \#\#\# Example
603
+
604
+ Use `[up-dash]` like this:
605
+
606
+ <a href="/users" up-dash=".main">User list</a>
607
+
608
+ This is shorthand for:
609
+
610
+ <a href="/users" up-target=".main" up-instant up-preload>User list</a>
611
+
612
+ @selector a[up-dash]
613
+ @param [up-dash='body']
614
+ The CSS selector to replace
615
+
616
+ Inside the CSS selector you may refer to this link as `&` ([like in Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector)).
617
+ @deprecated
618
+ To accelerate all links use `up.link.config.instantSelectors` and `up.link.config.preloadSelectors`.
619
+ */
620
+
621
+ up.migrate.targetMacro('up-dash', {
622
+ 'up-preload': '',
623
+ 'up-instant': ''
624
+ }, function() {
625
+ return up.migrate.deprecated('a[up-dash]', 'up.link.config.instantSelectors or up.link.config.preloadSelectors');
626
+ });
627
+
552
628
  }).call(this);
553
629
 
554
630
  /***
@@ -826,10 +902,10 @@ Returns the first descendant element matching the given selector.
826
902
  @param {string} up-modal
827
903
  The CSS selector that will be extracted from the response and displayed in a modal dialog.
828
904
  @deprecated
829
- Use `a[up-layer=modal]` instead.
905
+ Use `a[up-layer="new modal"]` instead.
830
906
  */
831
907
 
832
- up.link.targetMacro('up-modal', {
908
+ up.migrate.targetMacro('up-modal', {
833
909
  'up-layer': 'new modal'
834
910
  }, function() {
835
911
  return up.migrate.deprecated('a[up-modal]', 'a[up-layer="new modal"]');
@@ -846,10 +922,10 @@ Returns the first descendant element matching the given selector.
846
922
  @param {string} up-drawer
847
923
  The CSS selector that will be extracted from the response and displayed in a modal dialog.
848
924
  @deprecated
849
- Use `a[up-layer=drawer]` instead.
925
+ Use `a[up-layer="new drawer"]` instead.
850
926
  */
851
927
 
852
- up.link.targetMacro('up-drawer', {
928
+ up.migrate.targetMacro('up-drawer', {
853
929
  'up-layer': 'new drawer'
854
930
  }, function() {
855
931
  return up.migrate.deprecated('a[up-drawer]', 'a[up-layer="new drawer"]');
@@ -1065,15 +1141,6 @@ This feature is now deprecated.
1065
1141
 
1066
1142
  up.migrate.renamedProperty(up.network.config, 'slowDelay', 'badResponseTime');
1067
1143
 
1068
- up.migrate.handleNetworkPreloadArgs = function() {
1069
- var args, ref;
1070
- args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
1071
- if (u.isElementish(args[0])) {
1072
- up.migrate.warn('up.proxy.preload(link) has been renamed to up.link.preload(link)');
1073
- return (ref = up.link).preload.apply(ref, args);
1074
- }
1075
- };
1076
-
1077
1144
  up.migrate.handleRequestOptions = function(options) {
1078
1145
  return up.migrate.fixKey(options, 'data', 'params');
1079
1146
  };
@@ -1086,11 +1153,13 @@ This feature is now deprecated.
1086
1153
 
1087
1154
  \#\#\# Example
1088
1155
 
1089
- up.request('/search', { params: { query: 'sunshine' } }).then(function(text) {
1090
- console.log('The response text is %o', text)
1091
- }).catch(function() {
1092
- console.error('The request failed')
1093
- })
1156
+ ```
1157
+ up.ajax('/search', { params: { query: 'sunshine' } }).then(function(text) {
1158
+ console.log('The response text is %o', text)
1159
+ }).catch(function() {
1160
+ console.error('The request failed')
1161
+ })
1162
+ ```
1094
1163
 
1095
1164
  @function up.ajax
1096
1165
  @param {string} [url]
@@ -1129,6 +1198,13 @@ This feature is now deprecated.
1129
1198
  return up.cache.clear();
1130
1199
  };
1131
1200
 
1201
+ up.network.preload = function() {
1202
+ var args, ref;
1203
+ args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
1204
+ up.migrate.deprecated('up.proxy.preload(link)', 'up.link.preload(link)');
1205
+ return (ref = up.link).preload.apply(ref, args);
1206
+ };
1207
+
1132
1208
 
1133
1209
  /***
1134
1210
  @class up.Request
@@ -1183,26 +1259,6 @@ This feature is now deprecated.
1183
1259
  (function() {
1184
1260
  up.migrate.renamedProperty(up.radio.config, 'hungry', 'hungrySelectors');
1185
1261
 
1186
- }).call(this);
1187
- (function() {
1188
- var u;
1189
-
1190
- u = up.util;
1191
-
1192
- up.migrate.postCompile = function(elements, compiler) {
1193
- var element, i, keepValue, len, results, value;
1194
- if (keepValue = compiler.keep) {
1195
- up.migrate.warn('The { keep: true } option for up.compiler() has been removed. Have the compiler set [up-keep] attribute instead.');
1196
- value = u.isString(keepValue) ? keepValue : '';
1197
- results = [];
1198
- for (i = 0, len = elements.length; i < len; i++) {
1199
- element = elements[i];
1200
- results.push(element.setAttribute('up-keep', value));
1201
- }
1202
- return results;
1203
- }
1204
- };
1205
-
1206
1262
  }).call(this);
1207
1263
 
1208
1264
  /***
@@ -1 +1 @@
1
- (function(){up.framework.startExtension()}).call(this),function(){var u,p,e,t,r,a,n,i,o,l,c,s,m,d,g=[].slice;u=up.util,up.migrate=(p=new up.Config(function(){return{logLevel:"warn"}}),c=function(e,t,r){var a;return a=function(){return m("Property { %s } has been renamed to { %s } (found in %o)",t,r,e)},Object.defineProperty(e,t,{get:function(){return a(),this[r]},set:function(e){return a(),this[r]=e}})},a=function(e,t,r){if(u.isDefined(e[t]))return m("Property { %s } has been renamed to { %s } (found in %o)",t,r,e),u.renameKey(e,t,r)},o={},i=function(e,t){return o[e]=t},t=function(e){var t;return(t=o[e])?(m("Event "+e+" has been renamed to "+t),t):e},r=function(e){return u.uniq(u.map(e,t))},l=function(e,t){return Object.defineProperty(up,e,{get:function(){return m("up."+e+" has been renamed to up."+t),up[t]}})},d={},m=function(e){var t,r,a,n;if(a=e,t=2<=arguments.length?g.call(arguments,1):[],r=u.sprintf.apply(u,[a].concat(g.call(t))),!d[r])return d[r]=!0,(n=up.log)[p.logLevel].apply(n,["DEPRECATION",a].concat(g.call(t)))},e=function(e,t){return m(e+" has been deprecated. Use "+t+" instead.")},n=function(e){var t,r;return r=Promise.resolve(),t=r.then,r.then=function(){return m(e+" is now a sync function"),t.apply(this,arguments)},r},s=function(){return p.reset()},up.on("up:framework:reset",s),{deprecated:e,renamedPackage:l,renamedProperty:c,formerlyAsync:n,renamedEvent:i,fixEventTypes:r,fixKey:a,warn:m,loaded:!0,config:p})}.call(this),function(){var a=[].slice;up.util.only=function(e){var t,r;return r=e,t=2<=arguments.length?a.call(arguments,1):[],up.migrate.deprecated("up.util.only(object, ...keys)","up.util.pick(object, keys)"),up.util.pick(r,t)},up.util.except=function(e){var t,r;return r=e,t=2<=arguments.length?a.call(arguments,1):[],up.migrate.deprecated("up.util.except(object, ...keys)","up.util.omit(object, keys)"),up.util.omit(r,t)},up.util.parseUrl=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.parseUrl() has been renamed to up.util.parseURL()"),(t=up.util).parseURL.apply(t,e)},up.util.any=function(){var e;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.any() has been renamed to up.util.some()"),some.apply(null,e)},up.util.all=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.all() has been renamed to up.util.every()"),(t=up.util).every.apply(t,e)},up.util.detect=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.detect() has been renamed to up.util.find()"),(t=up.util).find.apply(t,e)},up.util.select=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.select() has been renamed to up.util.filter()"),(t=up.util).filter.apply(t,e)},up.util.setTimer=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.setTimer() has been renamed to up.util.timer()"),(t=up.util).timer.apply(t,e)},up.util.escapeHtml=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.deprecated("up.util.escapeHtml","up.util.escapeHTML"),(t=up.util).escapeHTML.apply(t,e)},up.util.selectorForElement=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.selectorForElement() has been renamed to up.fragment.toTarget()"),(t=up.fragment).toTarget.apply(t,e)},up.util.nextFrame=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.nextFrame() has been renamed to up.util.task()"),(t=up.util).task.apply(t,e)}}.call(this),function(){var r=[].slice;up.element.first=function(){var e,t;return e=1<=arguments.length?r.call(arguments,0):[],up.migrate.deprecated("up.element.first()","up.element.get()"),(t=up.element).get.apply(t,e)},up.element.createFromHtml=function(){var e,t;return e=1<=arguments.length?r.call(arguments,0):[],up.migrate.deprecated("up.element.createFromHtml","up.element.createFromHTML"),(t=up.element).createFromHTML.apply(t,e)}}.call(this),function(){var t=[].slice;up.migrate.renamedPackage("bus","event"),up.event.nobodyPrevents=function(){var e;return e=1<=arguments.length?t.call(arguments,0):[],up.migrate.deprecated("up.event.nobodyPrevents(type)","!up.emit(type).defaultPrevented"),!up.emit.apply(up,e).defaultPrevented}}.call(this),function(){up.migrate.renamedProperty(up.form.config,"fields","fieldSelectors"),up.migrate.renamedProperty(up.form.config,"submitButtons","submitButtonSelectors")}.call(this),function(){var p,r=[].slice;p=up.util,up.migrate.renamedPackage("flow","fragment"),up.migrate.renamedPackage("dom","fragment"),up.migrate.renamedProperty(up.fragment.config,"fallbacks","mainTargets"),up.migrate.handleResponseDocOptions=function(e){return up.migrate.fixKey(e,"html","document")},up.replace=function(e,t,r){return up.migrate.deprecated("up.replace(target, url)","up.navigate(target, { url })"),up.navigate(p.merge(r,{target:e,url:t}))},up.extract=function(e,t,r){return up.migrate.deprecated("up.extract(target, document)","up.navigate(target, { document })"),up.navigate(p.merge(r,{target:e,document:t}))},up.fragment.first=function(){var e,t;return e=1<=arguments.length?r.call(arguments,0):[],up.migrate.deprecated("up.fragment.first()","up.fragment.get()"),(t=up.fragment).get.apply(t,e)},up.first=up.fragment.first,up.migrate.handleScrollOptions=function(e){if(p.isUndefined(e.scroll)&&(p.isString(e.reveal)?(up.migrate.deprecated("Option { reveal: '"+e.reveal+"' }","{ scroll: '"+e.reveal+"' }"),e.scroll=e.reveal):!0===e.reveal?(up.migrate.deprecated("Option { reveal: true }","{ scroll: 'target' }"),e.scroll="target"):!1===e.reveal&&(up.migrate.deprecated("Option { reveal: false }","{ scroll: false }"),e.scroll=!1),p.isDefined(e.resetScroll)&&(up.migrate.deprecated("Option { resetScroll: true }","{ scroll: 'reset' }"),e.scroll="teset"),p.isDefined(e.restoreScroll)))return up.migrate.deprecated("Option { restoreScroll: true }","{ scroll: 'restore' }"),e.scroll="restore"},up.migrate.handleHistoryOption=function(e){if(p.isString(e.history)&&"auto"!==e.history)return up.migrate.warn("Passing a URL as { history } option is deprecated. Pass it as { location } instead."),e.location=e.history,e.history="auto"},up.migrate.handleRenderOptions=function(e){var t,r,a,n,u;for(up.migrate.handleHistoryOption(e),u=[],t=0,r=(n=["target","origin"]).length;t<r;t++)a=n[t],p.isJQuery(e[a])?(up.migrate.warn("Passing a jQuery collection as { %s } is deprecated. Pass it as a native element instead.",a),u.push(e[a]=up.element.get(e[a]))):u.push(void 0);return u}}.call(this),function(){up.migrate.renamedProperty(up.history.config,"popTargets","restoreTargets"),up.history.url=function(){return up.migrate.deprecated("up.history.url()","up.history.location"),up.history.location},up.migrate.renamedEvent("up:history:push","up:location:changed"),up.migrate.renamedEvent("up:history:pushed","up:location:changed"),up.migrate.renamedEvent("up:history:restore","up:location:changed"),up.migrate.renamedEvent("up:history:restored","up:location:changed"),up.migrate.renamedEvent("up:history:replaced","up:location:changed")}.call(this),function(){up.migrate.renamedPackage("navigation","feedback"),up.migrate.renamedProperty(up.feedback.config,"navs","navSelectors")}.call(this),function(){up.migrate.parseFollowOptions=function(e){return e.string("flavor"),e.string("width"),e.string("height"),e["boolean"]("closable"),e.booleanOrString("reveal"),e["boolean"]("resetScroll"),e["boolean"]("restoreScroll")}}.call(this),function(){up.migrate.handleLayerOptions=function(e){var t,r,a,n;for(up.migrate.fixKey(e,"flavor","mode"),up.migrate.fixKey(e,"closable","dismissable"),up.migrate.fixKey(e,"closeLabel","dismissLabel"),r=0,a=(n=["width","maxWidth","height"]).length;r<a;r++)e[t=n[r]]&&up.migrate.warn("Layer option { "+t+" } has been removed. Use { size } or { class } instead.");if(e.sticky&&up.migrate.warn("Layer option { sticky } has been removed. Give links an [up-peel=false] attribute to prevent layer dismissal on click."),e.template&&up.migrate.warn("Layer option { template } has been removed. Use { class } or modify the layer HTML on up:layer:open."),"page"===e.layer&&(up.migrate.warn("Option { layer: 'page' } has been renamed to { layer: 'root' }."),e.layer="root"),"modal"===e.layer||"popup"===e.layer)return up.migrate.warn("Option { layer: '"+e.layer+"' } has been removed. Did you mean { layer: 'overlay' }?"),e.layer="overlay"},up.migrate.handleTetherOptions=function(e){var t,r,a;if(r=(a=e.position.split("-"))[0],t=a[1])return up.migrate.warn("The position value %o is deprecated. Use %o instead.",e.position,{position:r,align:t}),e.position=r,e.align=t},up.migrate.registerLayerCloser=function(r){return r.registerClickCloser("up-close",function(e,t){return up.migrate.deprecated("[up-close]","[up-dismiss]"),r.dismiss(e,t)})},up.migrate.handleLayerConfig=function(e){return up.migrate.fixKey(e,"history","historyVisible")}}.call(this),function(){var e,a;a=up.util,e=new Error("up.modal.flavors has been removed without direct replacement. You may give new layers a { class } or modify layer elements on up:layer:open."),up.modal=a.literal({visit:function(e,t){return null==t&&(t={}),up.migrate.deprecated("up.modal.visit(url)",'up.layer.open({ url, mode: "modal" })'),up.layer.open(a.merge(t,{url:e,mode:"modal"}))},follow:function(e,t){return null==t&&(t={}),up.migrate.deprecated("up.modal.follow(link)",'up.follow(link, { layer: "modal" })'),up.follow(e,a.merge(t,{layer:"modal"}))},extract:function(e,t,r){return null==r&&(r={}),up.migrate.deprecated("up.modal.extract(target, document)",'up.layer.open({ document, mode: "modal" })'),up.layer.open(a.merge(r,{target:e,html:t,layer:"modal"}))},close:function(e){return null==e&&(e={}),up.migrate.deprecated("up.modal.close()","up.layer.dismiss()"),up.layer.dismiss(null,e),up.migrate.formerlyAsync("up.layer.dismiss()")},url:function(){return up.migrate.deprecated("up.modal.url()","up.layer.location"),up.layer.location},coveredUrl:function(){var e;return up.migrate.deprecated("up.modal.coveredUrl()","up.layer.parent.location"),null!=(e=up.layer.parent)?e.location:void 0},get_config:function(){return up.migrate.deprecated("up.modal.config","up.layer.config.modal"),up.layer.config.modal},contains:function(e){return up.migrate.deprecated("up.modal.contains()","up.layer.contains()"),up.layer.contains(e)},isOpen:function(){return up.migrate.deprecated("up.modal.isOpen()","up.layer.isOverlay()"),up.layer.isOverlay()},get_flavors:function(){throw e},flavor:function(){throw e}}),up.migrate.renamedEvent("up:modal:open","up:layer:open"),up.migrate.renamedEvent("up:modal:opened","up:layer:opened"),up.migrate.renamedEvent("up:modal:close","up:layer:dismiss"),up.migrate.renamedEvent("up:modal:closed","up:layer:dismissed"),up.link.targetMacro("up-modal",{"up-layer":"new modal"},function(){return up.migrate.deprecated("a[up-modal]",'a[up-layer="new modal"]')}),up.link.targetMacro("up-drawer",{"up-layer":"new drawer"},function(){return up.migrate.deprecated("a[up-drawer]",'a[up-layer="new drawer"]')})}.call(this),function(){var r;r=up.util,up.element,up.popup=r.literal({attach:function(e,t){return null==t&&(t={}),e=up.fragment.get(e),up.migrate.deprecated("up.popup.attach(origin)","up.layer.open({ origin, layer: 'popup' })"),up.layer.open(r.merge(t,{origin:e,layer:"popup"}))},close:function(e){return null==e&&(e={}),up.migrate.deprecated("up.popup.close()","up.layer.dismiss()"),up.layer.dismiss(null,e)},url:function(){return up.migrate.deprecated("up.popup.url()","up.layer.location"),up.layer.location},coveredUrl:function(){var e;return up.migrate.deprecated("up.popup.coveredUrl()","up.layer.parent.location"),null!=(e=up.layer.parent)?e.location:void 0},get_config:function(){return up.migrate.deprecated("up.popup.config","up.layer.config.popup"),up.layer.config.popup},contains:function(e){return up.migrate.deprecated("up.popup.contains()","up.layer.contains()"),up.layer.contains(e)},isOpen:function(){return up.migrate.deprecated("up.popup.isOpen()","up.layer.isOverlay()"),up.layer.isOverlay()},sync:function(){return up.migrate.deprecated("up.popup.sync()","up.layer.sync()"),up.layer.sync()}}),up.migrate.renamedEvent("up:popup:open","up:layer:open"),up.migrate.renamedEvent("up:popup:opened","up:layer:opened"),up.migrate.renamedEvent("up:popup:close","up:layer:dismiss"),up.migrate.renamedEvent("up:popup:closed","up:layer:dismissed"),up.link.targetMacro("up-popup",{"up-layer":"new popup"},function(){return up.migrate.deprecated("[up-popup]",'[up-layer="new popup"]')})}.call(this),function(){up.tooltip=up.macro("[up-tooltip]",function(e){return up.migrate.warn("[up-tooltip] has been deprecated. A [title] was set instead."),up.element.setMissingAttr(e,"title",e.getAttribute("up-tooltip"))})}.call(this),function(){var t,r,a=[].slice;r=up.util,up.migrate.renamedPackage("proxy","network"),up.migrate.renamedEvent("up:proxy:load","up:request:load"),up.migrate.renamedEvent("up:proxy:received","up:request:loaded"),up.migrate.renamedEvent("up:proxy:loaded","up:request:loaded"),up.migrate.renamedEvent("up:proxy:fatal","up:request:fatal"),up.migrate.renamedEvent("up:proxy:aborted","up:request:aborted"),up.migrate.renamedEvent("up:proxy:slow","up:request:late"),up.migrate.renamedEvent("up:proxy:recover","up:request:recover"),t=function(){return up.migrate.deprecated("up.proxy.config.preloadDelay","up.link.config.preloadDelay")},Object.defineProperty(up.network.config,"preloadDelay",{get:function(){return t(),up.link.config.preloadDelay},set:function(e){return t(),up.link.config.preloadDelay=e}}),up.migrate.renamedProperty(up.network.config,"maxRequests","concurrency"),up.migrate.renamedProperty(up.network.config,"slowDelay","badResponseTime"),up.migrate.handleNetworkPreloadArgs=function(){var e,t;if(e=1<=arguments.length?a.call(arguments,0):[],r.isElementish(e[0]))return up.migrate.warn("up.proxy.preload(link) has been renamed to up.link.preload(link)"),(t=up.link).preload.apply(t,e)},up.migrate.handleRequestOptions=function(e){return up.migrate.fixKey(e,"data","params")},up.ajax=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.deprecated("up.ajax()","up.request()"),t=function(e){return e.text},up.request.apply(up,e).then(t)},up.network.clear=function(){return up.migrate.deprecated("up.proxy.clear()","up.cache.clear()"),up.cache.clear()},up.Request.prototype.navigate=function(){return up.migrate.deprecated("up.Request#navigate()","up.Request#loadPage()"),this.loadPage()},up.Response.prototype.isSuccess=function(){return up.migrate.deprecated("up.Response#isSuccess()","up.Response#ok"),this.ok},up.Response.prototype.isError=function(){return up.migrate.deprecated("up.Response#isError()","!up.Response#ok"),!this.ok}}.call(this),function(){up.migrate.renamedProperty(up.radio.config,"hungry","hungrySelectors")}.call(this),function(){var o;o=up.util,up.migrate.postCompile=function(e,t){var r,a,n,u,p,i;if(n=t.keep){for(up.migrate.warn("The { keep: true } option for up.compiler() has been removed. Have the compiler set [up-keep] attribute instead."),i=o.isString(n)?n:"",p=[],a=0,u=e.length;a<u;a++)r=e[a],p.push(r.setAttribute("up-keep",i));return p}}}.call(this),function(){var r=[].slice;up.migrate.renamedPackage("layout","viewport"),up.migrate.renamedProperty(up.viewport.config,"viewports","viewportSelectors"),up.migrate.renamedProperty(up.viewport.config,"snap","revealSnap"),up.viewport.closest=function(){var e,t;return e=1<=arguments.length?r.call(arguments,0):[],up.migrate.deprecated("up.viewport.closest()","up.viewport.get()"),(t=up.viewport).get.apply(t,e)}}.call(this),function(){up.framework.stopExtension()}.call(this),function(){}.call(this);
1
+ (function(){up.framework.startExtension()}).call(this),function(){var u,p,e,t,r,a,n,i,o,l,c,s,d,m,g=[].slice;u=up.util,up.migrate=(p=new up.Config(function(){return{logLevel:"warn"}}),c=function(e,t,r){var a;return a=function(){return d("Property { %s } has been renamed to { %s } (found in %o)",t,r,e)},Object.defineProperty(e,t,{get:function(){return a(),this[r]},set:function(e){return a(),this[r]=e}})},a=function(e,t,r){if(u.isDefined(e[t]))return d("Property { %s } has been renamed to { %s } (found in %o)",t,r,e),u.renameKey(e,t,r)},o={},i=function(e,t){return o[e]=t},t=function(e){var t;return(t=o[e])?(d("Event "+e+" has been renamed to "+t),t):e},r=function(e){return u.uniq(u.map(e,t))},l=function(e,t){return Object.defineProperty(up,e,{get:function(){return d("up."+e+" has been renamed to up."+t),up[t]}})},m={},d=function(e){var t,r,a,n;if(a=e,t=2<=arguments.length?g.call(arguments,1):[],r=u.sprintf.apply(u,[a].concat(g.call(t))),!m[r])return m[r]=!0,(n=up.log)[p.logLevel].apply(n,["DEPRECATION",a].concat(g.call(t)))},e=function(e,t){return d(e+" has been deprecated. Use "+t+" instead.")},n=function(e){var t,r;return r=Promise.resolve(),t=r.then,r.then=function(){return d(e+" is now a sync function"),t.apply(this,arguments)},r},s=function(){return p.reset()},up.on("up:framework:reset",s),{deprecated:e,renamedPackage:l,renamedProperty:c,formerlyAsync:n,renamedEvent:i,fixEventTypes:r,fixKey:a,warn:d,loaded:!0,config:p})}.call(this),function(){var a=[].slice;up.util.only=function(e){var t,r;return r=e,t=2<=arguments.length?a.call(arguments,1):[],up.migrate.deprecated("up.util.only(object, ...keys)","up.util.pick(object, keys)"),up.util.pick(r,t)},up.util.except=function(e){var t,r;return r=e,t=2<=arguments.length?a.call(arguments,1):[],up.migrate.deprecated("up.util.except(object, ...keys)","up.util.omit(object, keys)"),up.util.omit(r,t)},up.util.parseUrl=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.parseUrl() has been renamed to up.util.parseURL()"),(t=up.util).parseURL.apply(t,e)},up.util.any=function(){var e;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.any() has been renamed to up.util.some()"),some.apply(null,e)},up.util.all=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.all() has been renamed to up.util.every()"),(t=up.util).every.apply(t,e)},up.util.detect=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.detect() has been renamed to up.util.find()"),(t=up.util).find.apply(t,e)},up.util.select=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.select() has been renamed to up.util.filter()"),(t=up.util).filter.apply(t,e)},up.util.setTimer=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.setTimer() has been renamed to up.util.timer()"),(t=up.util).timer.apply(t,e)},up.util.escapeHtml=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.deprecated("up.util.escapeHtml","up.util.escapeHTML"),(t=up.util).escapeHTML.apply(t,e)},up.util.selectorForElement=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.selectorForElement() has been renamed to up.fragment.toTarget()"),(t=up.fragment).toTarget.apply(t,e)},up.util.nextFrame=function(){var e,t;return e=1<=arguments.length?a.call(arguments,0):[],up.migrate.warn("up.util.nextFrame() has been renamed to up.util.task()"),(t=up.util).task.apply(t,e)}}.call(this),function(){var r=[].slice;up.element.first=function(){var e,t;return e=1<=arguments.length?r.call(arguments,0):[],up.migrate.deprecated("up.element.first()","up.element.get()"),(t=up.element).get.apply(t,e)},up.element.createFromHtml=function(){var e,t;return e=1<=arguments.length?r.call(arguments,0):[],up.migrate.deprecated("up.element.createFromHtml","up.element.createFromHTML"),(t=up.element).createFromHTML.apply(t,e)}}.call(this),function(){var t=[].slice;up.migrate.renamedPackage("bus","event"),up.event.nobodyPrevents=function(){var e;return e=1<=arguments.length?t.call(arguments,0):[],up.migrate.deprecated("up.event.nobodyPrevents(type)","!up.emit(type).defaultPrevented"),!up.emit.apply(up,e).defaultPrevented}}.call(this),function(){var o;o=up.util,up.migrate.postCompile=function(e,t){var r,a,n,u,p,i;if(n=t.keep){for(up.migrate.warn("The { keep: true } option for up.compiler() has been removed. Have the compiler set [up-keep] attribute instead."),i=o.isString(n)?n:"",p=[],a=0,u=e.length;a<u;a++)r=e[a],p.push(r.setAttribute("up-keep",i));return p}},up.migrate.targetMacro=function(n,u,p){return up.macro("["+n+"]",function(t){var r,a;return a=o.copy(u),(r=t.getAttribute(n))?a["up-target"]=r:a["up-follow"]="",e.setMissingAttrs(t,a),t.removeAttribute(n),"function"==typeof p?p():void 0})}}.call(this),function(){up.migrate.renamedProperty(up.form.config,"fields","fieldSelectors"),up.migrate.renamedProperty(up.form.config,"submitButtons","submitButtonSelectors")}.call(this),function(){var p,r=[].slice;p=up.util,up.migrate.renamedPackage("flow","fragment"),up.migrate.renamedPackage("dom","fragment"),up.migrate.renamedProperty(up.fragment.config,"fallbacks","mainTargets"),up.migrate.handleResponseDocOptions=function(e){return up.migrate.fixKey(e,"html","document")},up.replace=function(e,t,r){return up.migrate.deprecated("up.replace(target, url)","up.navigate(target, { url })"),up.navigate(p.merge(r,{target:e,url:t}))},up.extract=function(e,t,r){return up.migrate.deprecated("up.extract(target, document)","up.navigate(target, { document })"),up.navigate(p.merge(r,{target:e,document:t}))},up.fragment.first=function(){var e,t;return e=1<=arguments.length?r.call(arguments,0):[],up.migrate.deprecated("up.fragment.first()","up.fragment.get()"),(t=up.fragment).get.apply(t,e)},up.first=up.fragment.first,up.migrate.handleScrollOptions=function(e){if(p.isUndefined(e.scroll)&&(p.isString(e.reveal)?(up.migrate.deprecated("Option { reveal: '"+e.reveal+"' }","{ scroll: '"+e.reveal+"' }"),e.scroll=e.reveal):!0===e.reveal?(up.migrate.deprecated("Option { reveal: true }","{ scroll: 'target' }"),e.scroll="target"):!1===e.reveal&&(up.migrate.deprecated("Option { reveal: false }","{ scroll: false }"),e.scroll=!1),p.isDefined(e.resetScroll)&&(up.migrate.deprecated("Option { resetScroll: true }","{ scroll: 'reset' }"),e.scroll="teset"),p.isDefined(e.restoreScroll)))return up.migrate.deprecated("Option { restoreScroll: true }","{ scroll: 'restore' }"),e.scroll="restore"},up.migrate.handleHistoryOption=function(e){if(p.isString(e.history)&&"auto"!==e.history)return up.migrate.warn("Passing a URL as { history } option is deprecated. Pass it as { location } instead."),e.location=e.history,e.history="auto"},up.migrate.handleRenderOptions=function(e){var t,r,a,n,u;for(up.migrate.handleHistoryOption(e),u=[],t=0,r=(n=["target","origin"]).length;t<r;t++)a=n[t],p.isJQuery(e[a])?(up.migrate.warn("Passing a jQuery collection as { %s } is deprecated. Pass it as a native element instead.",a),u.push(e[a]=up.element.get(e[a]))):u.push(void 0);return u}}.call(this),function(){up.migrate.renamedProperty(up.history.config,"popTargets","restoreTargets"),up.history.url=function(){return up.migrate.deprecated("up.history.url()","up.history.location"),up.history.location},up.migrate.renamedEvent("up:history:push","up:location:changed"),up.migrate.renamedEvent("up:history:pushed","up:location:changed"),up.migrate.renamedEvent("up:history:restore","up:location:changed"),up.migrate.renamedEvent("up:history:restored","up:location:changed"),up.migrate.renamedEvent("up:history:replaced","up:location:changed")}.call(this),function(){up.migrate.renamedPackage("navigation","feedback"),up.migrate.renamedProperty(up.feedback.config,"navs","navSelectors")}.call(this),function(){up.migrate.parseFollowOptions=function(e){return e.string("flavor"),e.string("width"),e.string("height"),e["boolean"]("closable"),e.booleanOrString("reveal"),e["boolean"]("resetScroll"),e["boolean"]("restoreScroll")},up.migrate.targetMacro("up-dash",{"up-preload":"","up-instant":""},function(){return up.migrate.deprecated("a[up-dash]","up.link.config.instantSelectors or up.link.config.preloadSelectors")})}.call(this),function(){up.migrate.handleLayerOptions=function(e){var t,r,a,n;for(up.migrate.fixKey(e,"flavor","mode"),up.migrate.fixKey(e,"closable","dismissable"),up.migrate.fixKey(e,"closeLabel","dismissLabel"),r=0,a=(n=["width","maxWidth","height"]).length;r<a;r++)e[t=n[r]]&&up.migrate.warn("Layer option { "+t+" } has been removed. Use { size } or { class } instead.");if(e.sticky&&up.migrate.warn("Layer option { sticky } has been removed. Give links an [up-peel=false] attribute to prevent layer dismissal on click."),e.template&&up.migrate.warn("Layer option { template } has been removed. Use { class } or modify the layer HTML on up:layer:open."),"page"===e.layer&&(up.migrate.warn("Option { layer: 'page' } has been renamed to { layer: 'root' }."),e.layer="root"),"modal"===e.layer||"popup"===e.layer)return up.migrate.warn("Option { layer: '"+e.layer+"' } has been removed. Did you mean { layer: 'overlay' }?"),e.layer="overlay"},up.migrate.handleTetherOptions=function(e){var t,r,a;if(r=(a=e.position.split("-"))[0],t=a[1])return up.migrate.warn("The position value %o is deprecated. Use %o instead.",e.position,{position:r,align:t}),e.position=r,e.align=t},up.migrate.registerLayerCloser=function(r){return r.registerClickCloser("up-close",function(e,t){return up.migrate.deprecated("[up-close]","[up-dismiss]"),r.dismiss(e,t)})},up.migrate.handleLayerConfig=function(e){return up.migrate.fixKey(e,"history","historyVisible")}}.call(this),function(){var e,a;a=up.util,e=new Error("up.modal.flavors has been removed without direct replacement. You may give new layers a { class } or modify layer elements on up:layer:open."),up.modal=a.literal({visit:function(e,t){return null==t&&(t={}),up.migrate.deprecated("up.modal.visit(url)",'up.layer.open({ url, mode: "modal" })'),up.layer.open(a.merge(t,{url:e,mode:"modal"}))},follow:function(e,t){return null==t&&(t={}),up.migrate.deprecated("up.modal.follow(link)",'up.follow(link, { layer: "modal" })'),up.follow(e,a.merge(t,{layer:"modal"}))},extract:function(e,t,r){return null==r&&(r={}),up.migrate.deprecated("up.modal.extract(target, document)",'up.layer.open({ document, mode: "modal" })'),up.layer.open(a.merge(r,{target:e,html:t,layer:"modal"}))},close:function(e){return null==e&&(e={}),up.migrate.deprecated("up.modal.close()","up.layer.dismiss()"),up.layer.dismiss(null,e),up.migrate.formerlyAsync("up.layer.dismiss()")},url:function(){return up.migrate.deprecated("up.modal.url()","up.layer.location"),up.layer.location},coveredUrl:function(){var e;return up.migrate.deprecated("up.modal.coveredUrl()","up.layer.parent.location"),null!=(e=up.layer.parent)?e.location:void 0},get_config:function(){return up.migrate.deprecated("up.modal.config","up.layer.config.modal"),up.layer.config.modal},contains:function(e){return up.migrate.deprecated("up.modal.contains()","up.layer.contains()"),up.layer.contains(e)},isOpen:function(){return up.migrate.deprecated("up.modal.isOpen()","up.layer.isOverlay()"),up.layer.isOverlay()},get_flavors:function(){throw e},flavor:function(){throw e}}),up.migrate.renamedEvent("up:modal:open","up:layer:open"),up.migrate.renamedEvent("up:modal:opened","up:layer:opened"),up.migrate.renamedEvent("up:modal:close","up:layer:dismiss"),up.migrate.renamedEvent("up:modal:closed","up:layer:dismissed"),up.migrate.targetMacro("up-modal",{"up-layer":"new modal"},function(){return up.migrate.deprecated("a[up-modal]",'a[up-layer="new modal"]')}),up.migrate.targetMacro("up-drawer",{"up-layer":"new drawer"},function(){return up.migrate.deprecated("a[up-drawer]",'a[up-layer="new drawer"]')})}.call(this),function(){var r;r=up.util,up.element,up.popup=r.literal({attach:function(e,t){return null==t&&(t={}),e=up.fragment.get(e),up.migrate.deprecated("up.popup.attach(origin)","up.layer.open({ origin, layer: 'popup' })"),up.layer.open(r.merge(t,{origin:e,layer:"popup"}))},close:function(e){return null==e&&(e={}),up.migrate.deprecated("up.popup.close()","up.layer.dismiss()"),up.layer.dismiss(null,e)},url:function(){return up.migrate.deprecated("up.popup.url()","up.layer.location"),up.layer.location},coveredUrl:function(){var e;return up.migrate.deprecated("up.popup.coveredUrl()","up.layer.parent.location"),null!=(e=up.layer.parent)?e.location:void 0},get_config:function(){return up.migrate.deprecated("up.popup.config","up.layer.config.popup"),up.layer.config.popup},contains:function(e){return up.migrate.deprecated("up.popup.contains()","up.layer.contains()"),up.layer.contains(e)},isOpen:function(){return up.migrate.deprecated("up.popup.isOpen()","up.layer.isOverlay()"),up.layer.isOverlay()},sync:function(){return up.migrate.deprecated("up.popup.sync()","up.layer.sync()"),up.layer.sync()}}),up.migrate.renamedEvent("up:popup:open","up:layer:open"),up.migrate.renamedEvent("up:popup:opened","up:layer:opened"),up.migrate.renamedEvent("up:popup:close","up:layer:dismiss"),up.migrate.renamedEvent("up:popup:closed","up:layer:dismissed"),up.link.targetMacro("up-popup",{"up-layer":"new popup"},function(){return up.migrate.deprecated("[up-popup]",'[up-layer="new popup"]')})}.call(this),function(){up.tooltip=up.macro("[up-tooltip]",function(e){return up.migrate.warn("[up-tooltip] has been deprecated. A [title] was set instead."),up.element.setMissingAttr(e,"title",e.getAttribute("up-tooltip"))})}.call(this),function(){var t,r=[].slice;up.util,up.migrate.renamedPackage("proxy","network"),up.migrate.renamedEvent("up:proxy:load","up:request:load"),up.migrate.renamedEvent("up:proxy:received","up:request:loaded"),up.migrate.renamedEvent("up:proxy:loaded","up:request:loaded"),up.migrate.renamedEvent("up:proxy:fatal","up:request:fatal"),up.migrate.renamedEvent("up:proxy:aborted","up:request:aborted"),up.migrate.renamedEvent("up:proxy:slow","up:request:late"),up.migrate.renamedEvent("up:proxy:recover","up:request:recover"),t=function(){return up.migrate.deprecated("up.proxy.config.preloadDelay","up.link.config.preloadDelay")},Object.defineProperty(up.network.config,"preloadDelay",{get:function(){return t(),up.link.config.preloadDelay},set:function(e){return t(),up.link.config.preloadDelay=e}}),up.migrate.renamedProperty(up.network.config,"maxRequests","concurrency"),up.migrate.renamedProperty(up.network.config,"slowDelay","badResponseTime"),up.migrate.handleRequestOptions=function(e){return up.migrate.fixKey(e,"data","params")},up.ajax=function(){var e,t;return e=1<=arguments.length?r.call(arguments,0):[],up.migrate.deprecated("up.ajax()","up.request()"),t=function(e){return e.text},up.request.apply(up,e).then(t)},up.network.clear=function(){return up.migrate.deprecated("up.proxy.clear()","up.cache.clear()"),up.cache.clear()},up.network.preload=function(){var e,t;return e=1<=arguments.length?r.call(arguments,0):[],up.migrate.deprecated("up.proxy.preload(link)","up.link.preload(link)"),(t=up.link).preload.apply(t,e)},up.Request.prototype.navigate=function(){return up.migrate.deprecated("up.Request#navigate()","up.Request#loadPage()"),this.loadPage()},up.Response.prototype.isSuccess=function(){return up.migrate.deprecated("up.Response#isSuccess()","up.Response#ok"),this.ok},up.Response.prototype.isError=function(){return up.migrate.deprecated("up.Response#isError()","!up.Response#ok"),!this.ok}}.call(this),function(){up.migrate.renamedProperty(up.radio.config,"hungry","hungrySelectors")}.call(this),function(){var r=[].slice;up.migrate.renamedPackage("layout","viewport"),up.migrate.renamedProperty(up.viewport.config,"viewports","viewportSelectors"),up.migrate.renamedProperty(up.viewport.config,"snap","revealSnap"),up.viewport.closest=function(){var e,t;return e=1<=arguments.length?r.call(arguments,0):[],up.migrate.deprecated("up.viewport.closest()","up.viewport.get()"),(t=up.viewport).get.apply(t,e)}}.call(this),function(){up.framework.stopExtension()}.call(this),function(){}.call(this);
data/dist/unpoly.js CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  (function() {
7
7
  window.up = {
8
- version: "2.0.0-rc11"
8
+ version: "2.0.0"
9
9
  };
10
10
 
11
11
  }).call(this);
@@ -1259,6 +1259,7 @@ to not include another library in your asset bundle.
1259
1259
  @function up.util.last
1260
1260
  @param {Array<T>} array
1261
1261
  @return {T}
1262
+ @stable
1262
1263
  */
1263
1264
  last = function(array) {
1264
1265
  return array[array.length - 1];
@@ -1572,24 +1573,24 @@ to not include another library in your asset bundle.
1572
1573
  };
1573
1574
 
1574
1575
  /***
1575
- * Registers an empty rejection handler with the given promise.
1576
- * This prevents browsers from printing "Uncaught (in promise)" to the error
1577
- * console when the promise is rejected.
1578
- *
1579
- * This is helpful for event handlers where it is clear that no rejection
1580
- * handler will be registered:
1581
- *
1582
- * up.on('submit', 'form[up-target]', (event, $form) => {
1583
- * promise = up.submit($form)
1584
- * up.util.muteRejection(promise)
1585
- * })
1586
- *
1587
- * Does nothing if passed a missing value.
1588
- *
1589
- * @function up.util.muteRejection
1590
- * @param {Promise|undefined|null} promise
1591
- * @return {Promise}
1592
- * @internal
1576
+ Registers an empty rejection handler with the given promise.
1577
+ This prevents browsers from printing "Uncaught (in promise)" to the error
1578
+ console when the promise is rejected.
1579
+
1580
+ This is helpful for event handlers where it is clear that no rejection
1581
+ handler will be registered:
1582
+
1583
+ up.on('submit', 'form[up-target]', (event, $form) => {
1584
+ promise = up.submit($form)
1585
+ up.util.muteRejection(promise)
1586
+ })
1587
+
1588
+ Does nothing if passed a missing value.
1589
+
1590
+ @function up.util.muteRejection
1591
+ @param {Promise|undefined|null} promise
1592
+ @return {Promise}
1593
+ @internal
1593
1594
  */
1594
1595
  muteRejection = function(promise) {
1595
1596
  return promise != null ? promise["catch"](noop) : void 0;
@@ -2145,10 +2146,12 @@ Chrome, Firefox, Edge, Safari
2145
2146
  : Full support
2146
2147
 
2147
2148
  Internet Explorer 11
2148
- : Full support with a `Promise` polyfill like [es6-promise](https://github.com/stefanpenner/es6-promise) (2.4 KB).
2149
+ : Full support with a `Promise` polyfill like [es6-promise](https://github.com/stefanpenner/es6-promise) (2.4 KB).\
2150
+ Support may be removed when Microsoft retires IE11 in [June 2022](https://blogs.windows.com/windowsexperience/2021/05/19/the-future-of-internet-explorer-on-windows-10-is-in-microsoft-edge/).
2149
2151
 
2150
2152
  Internet Explorer 10 or lower
2151
- : Unpoly prevents itself from booting itself, leaving you with a classic server-side application.
2153
+ : Unpoly will not boot or [run compilers](/up.compiler),
2154
+ leaving you with a classic server-side application.
2152
2155
 
2153
2156
  @module up.browser
2154
2157
  */
@@ -2161,7 +2164,9 @@ Internet Explorer 10 or lower
2161
2164
  u = up.util;
2162
2165
 
2163
2166
  /***
2164
- Makes a full page request, replacing the entire JavaScript environment with a new page from the server response.
2167
+ Makes a full-page request, replacing the entire browser environment with a new page from the server response.
2168
+
2169
+ Also see `up.Request#loadPage()`.
2165
2170
 
2166
2171
  @function up.browser.loadPage
2167
2172
  @param {string} options.url
@@ -2171,7 +2176,7 @@ Internet Explorer 10 or lower
2171
2176
 
2172
2177
  Methods other than GET or POST will be [wrapped](/up.protocol.config#config.methodParam) in a POST request.
2173
2178
  @param {Object|Array|FormData|string} [options.params]
2174
- @external
2179
+ @experimental
2175
2180
  */
2176
2181
  loadPage = function(requestsAttrs) {
2177
2182
  return new up.Request(requestsAttrs).loadPage();
@@ -6300,8 +6305,12 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
6300
6305
  /***
6301
6306
  Each layer has an `up.Layer` instance.
6302
6307
 
6303
- Most functions in the `up.layer` (lowercase) package interact with the [current layer](/up.layer.current).
6304
- E.g. `up.layer.dismiss()` is a shortcut for `up.layer.current.dismiss()`.
6308
+ Most functions in the `up.layer` package interact with the [current layer](/up.layer.current).
6309
+ For example, `up.layer.dismiss()` is a shortcut for `up.layer.current.dismiss()`.
6310
+
6311
+ `up.layer.current` is set to the right layer in compilers and most events,
6312
+ even if that layer is not the frontmost layer. E.g. if you're compiling a fragment for a background layer, `up.layer.current` will be
6313
+ the background layer during compilation.
6305
6314
 
6306
6315
  @class up.Layer
6307
6316
  */
@@ -6334,6 +6343,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
6334
6343
 
6335
6344
  @property up.Layer#historyVisible
6336
6345
  @param {boolean} historyVisible
6346
+ @stable
6337
6347
  */
6338
6348
 
6339
6349
 
@@ -6425,7 +6435,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
6425
6435
  [Closes this overlay](/closing-overlays) with an accepting intent,
6426
6436
  e.g. when a change was confirmed or when a value was selected.
6427
6437
 
6428
- To dismiss a layer without an accepting intent, use `up.Layer#dismiss()` instead.
6438
+ To dismiss a layer *without* an accepting intent, use `up.Layer#dismiss()` instead.
6429
6439
 
6430
6440
  @function up.Layer#accept
6431
6441
  @param {any} [value]
@@ -6463,7 +6473,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
6463
6473
 
6464
6474
 
6465
6475
  /***
6466
- [Closes this overlay](/closing-overlays) without an accepting intent,
6476
+ [Closes this overlay](/closing-overlays) *without* an accepting intent,
6467
6477
  e.g. when a "Cancel" button was clicked.
6468
6478
 
6469
6479
  To close an overlay with an accepting intent, use `up.Layer#accept()` instead.
@@ -6538,7 +6548,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
6538
6548
  /***
6539
6549
  Returns whether this layer is the [root layer](/up.layer.root).
6540
6550
 
6541
- @function up.Layer#isFront
6551
+ @function up.Layer#isRoot
6542
6552
  @return {boolean}
6543
6553
  @stable
6544
6554
  */
@@ -6619,7 +6629,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
6619
6629
 
6620
6630
  Returns `undefined` if this layer has not opened a child layer.
6621
6631
 
6622
- A layer can have at most one child layer. Opening an overlay on a layer with an exiisting child will
6632
+ A layer can have at most one child layer. Opening an overlay on a layer with an existing child will
6623
6633
  first dismiss the existing child before replacing it with the new child.
6624
6634
 
6625
6635
  @property up.Layer#child
@@ -6635,6 +6645,10 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
6635
6645
  /***
6636
6646
  Returns an array of this layer's ancestor layers.
6637
6647
 
6648
+ The array elements are ordered by distance to this layer.
6649
+ The first element is this layer's direct parent. The last element
6650
+ is the [root layer](/up.layer.root).
6651
+
6638
6652
  @property up.Layer#ancestors
6639
6653
  @return {Array<up.Layer>} ancestors
6640
6654
  @stable
@@ -6650,6 +6664,10 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
6650
6664
 
6651
6665
  Descendant layers are all layers that visually overlay this layer.
6652
6666
 
6667
+ The array elements are ordered by distance to this layer.
6668
+ The first element is this layer's direct child. The last element
6669
+ is the [frontmost layer](/up.layer.front).
6670
+
6653
6671
  @property up.Layer#descendants
6654
6672
  @return {Array<up.Layer>} descendants
6655
6673
  @stable
@@ -6746,27 +6764,43 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
6746
6764
  up.follow(overlayLink) // listener is not called
6747
6765
 
6748
6766
  @function up.Layer#on
6767
+
6749
6768
  @param {string} types
6750
6769
  A space-separated list of event types to bind to.
6751
- @param {string} [selector]
6770
+
6771
+ @param {string|Function(): string} [selector]
6752
6772
  The selector of an element on which the event must be triggered.
6753
6773
 
6754
6774
  Omit the selector to listen to all events of the given type, regardless
6755
6775
  of the event target.
6776
+
6777
+ If the selector is not known in advance you may also pass a function
6778
+ that returns the selector. The function is evaluated every time
6779
+ an event with the given type is observed.
6780
+
6756
6781
  @param {boolean} [options.passive=false]
6757
6782
  Whether to register a [passive event listener](https://developers.google.com/web/updates/2016/06/passive-event-listeners).
6758
6783
 
6759
6784
  A passive event listener may not call `event.preventDefault()`.
6760
6785
  This in particular may improve the frame rate when registering
6761
6786
  `touchstart` and `touchmove` events.
6787
+
6788
+ @param {boolean} [options.once=true]
6789
+ Whether the listener should run at most once.
6790
+
6791
+ If `true` the listener will automatically be unbound
6792
+ after the first invocation.
6793
+
6762
6794
  @param {Function(event, [element], [data])} listener
6763
6795
  The listener function that should be called.
6764
6796
 
6765
6797
  The function takes the affected element as the second argument.
6766
6798
  If the element has an [`up-data`](/up-data) attribute, its value is parsed as JSON
6767
6799
  and passed as a third argument.
6800
+
6768
6801
  @return {Function()}
6769
6802
  A function that unbinds the event listeners when called.
6803
+
6770
6804
  @stable
6771
6805
  */
6772
6806
 
@@ -6781,13 +6815,12 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
6781
6815
  Unbinds an event listener previously bound with `up.Layer#on()`.
6782
6816
 
6783
6817
  @function up.Layer#off
6784
- @param {Element|jQuery} [element=document]
6785
6818
  @param {string} events
6786
- @param {string} [selector]
6819
+ @param {string|Function(): string} [selector]
6787
6820
  @param {Function(event, [element], [data])} listener
6788
6821
  The listener function to unbind.
6789
6822
 
6790
- Note that you must pass a reference to the exact same listener function
6823
+ Note that you must pass a reference to the same function reference
6791
6824
  that was passed to `up.Layer#on()` earlier.
6792
6825
  @stable
6793
6826
  */
@@ -6959,9 +6992,9 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
6959
6992
  /***
6960
6993
  This layer's location URL.
6961
6994
 
6962
- If the [frontmost layer](/up.layer.front) does not have [visible history](/up.Layer.prototype.historyVisible),
6995
+ If the layer has [no visible history](/up.Layer.prototype.historyVisible), this property
6996
+ still returns the URL of the content in the overlay. In this case
6963
6997
  the browser's address bar will show the location of an ancestor layer.
6964
- This property will return the URL the layer would use if it had visible history.
6965
6998
 
6966
6999
  When this layer opens a child layer with visible history, the browser URL will change to the child
6967
7000
  layer's location. When the child layer is closed, this layer's location will be restored.
@@ -7284,7 +7317,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
7284
7317
  If the destruction is animated, the callback will run after the animation has finished.
7285
7318
  @return {Promise}
7286
7319
  A resolved promise.
7287
- @private
7320
+ @internal
7288
7321
  */
7289
7322
 
7290
7323
  Overlay.prototype.destroyElements = function(options) {
@@ -7423,6 +7456,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
7423
7456
  /***
7424
7457
  @function up.Layer.OverlayWithViewport#openNow
7425
7458
  @param {Element} options.content
7459
+ @internal
7426
7460
  */
7427
7461
 
7428
7462
  OverlayWithViewport.prototype.createElements = function(content) {
@@ -8936,6 +8970,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
8936
8970
  @param {string} name
8937
8971
  @return {any}
8938
8972
  The value of the param with the given name.
8973
+ @internal
8939
8974
  */
8940
8975
 
8941
8976
  Params.prototype.getFirst = function(name) {
@@ -8954,6 +8989,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
8954
8989
  @param {string} name
8955
8990
  @return {Array}
8956
8991
  An array of all values with the given name.
8992
+ @internal
8957
8993
  */
8958
8994
 
8959
8995
  Params.prototype.getAll = function(name) {
@@ -9301,7 +9337,15 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
9301
9337
 
9302
9338
 
9303
9339
  /***
9304
- Instances of `up.RenderResult` describe the effects of [rendering](/up.fragment).
9340
+ Instances of `up.RenderResult` describe the effects of [rendering](/up.render).
9341
+
9342
+ It is returned by functions like `up.render()` or `up.navigate()`:
9343
+
9344
+ ```js
9345
+ let result = await up.render('.target', content: 'foo')
9346
+ console.log(result.fragments) // => [<div class="target">...</div>]
9347
+ console.log(result.layer) // => up.Layer.Root
9348
+ ```
9305
9349
 
9306
9350
  @class up.RenderResult
9307
9351
  */
@@ -9352,17 +9396,18 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
9352
9396
 
9353
9397
 
9354
9398
  /***
9355
- Instances of `up.Request` normalizes properties of an [AJAX request](/up.request)
9356
- such as the requested URL, form parameters and HTTP method.
9399
+ A normalized description of an [HTTP request](`up.request()`).
9357
9400
 
9358
9401
  You can queue a request using the `up.request()` method:
9359
9402
 
9360
- let request = up.request('/foo')
9361
- console.log(request.url)
9403
+ ```js
9404
+ let request = up.request('/foo')
9405
+ console.log(request.url)
9362
9406
 
9363
- // A request object is also a promise for its response
9364
- let response = await request
9365
- console.log(response.text)
9407
+ // A request object is also a promise for its response
9408
+ let response = await request
9409
+ console.log(response.text)
9410
+ ```
9366
9411
 
9367
9412
  @class up.Request
9368
9413
  */
@@ -9501,6 +9546,8 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
9501
9546
  /***
9502
9547
  The [layer](/up.layer) targeted by this request.
9503
9548
 
9549
+ Setting the `{ layer }` property will automatically derive `{ context }` and `{ mode }` properties.
9550
+
9504
9551
  To prevent memory leaks, this property is removed shortly after the response is received.
9505
9552
 
9506
9553
  @property up.Request#layer
@@ -9512,6 +9559,8 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
9512
9559
  /***
9513
9560
  The [layer](/up.layer) targeted by this request in case the server responds with an [error code](/server-errors).
9514
9561
 
9562
+ Setting the `{ failLayer }` property will automatically derive `{ failContext }` and `{ failMode }` properties.
9563
+
9515
9564
  To prevent memory leaks, this property is removed shortly after the response is received.
9516
9565
 
9517
9566
  @property up.Request#failLayer
@@ -9637,7 +9686,8 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
9637
9686
  Request.prototype.normalizeForCaching = function() {
9638
9687
  this.method = u.normalizeMethod(this.method);
9639
9688
  this.extractHashFromURL();
9640
- return this.transferParamsToURL();
9689
+ this.transferParamsToURL();
9690
+ return this.url = u.normalizeURL(this.url);
9641
9691
  };
9642
9692
 
9643
9693
  Request.prototype.evictExpensiveAttrs = function() {
@@ -9724,6 +9774,37 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
9724
9774
  });
9725
9775
  };
9726
9776
 
9777
+
9778
+ /***
9779
+ Loads this request object as a full-page request, replacing the entire browser environment
9780
+ with a new page from the server response.
9781
+
9782
+ The full-page request will be loaded with the [URL](/up.Request.prototype.url),
9783
+ [method](/up.Request.prototype.method) and [params](/up.Request.prototype.params)
9784
+ from this request object.
9785
+ Properties that are not possible in a full-page request (such as custom HTTP headers)
9786
+ will be ignored.
9787
+
9788
+ \#\#\# Example
9789
+
9790
+ ```javascript
9791
+ let request = await up.request('/path')
9792
+
9793
+ try {
9794
+ let response = await request('/path')
9795
+ } catch (result) {
9796
+ if (result.name === 'AbortError') {
9797
+ console.log('Request was aborted.')
9798
+ }
9799
+ }
9800
+
9801
+ request.abort()
9802
+ ```
9803
+
9804
+ @function up.Request#loadPage
9805
+ @experimental
9806
+ */
9807
+
9727
9808
  Request.prototype.loadPage = function() {
9728
9809
  up.network.abort();
9729
9810
  return new up.Request.FormRenderer(this).buildAndSubmit();
@@ -10303,7 +10384,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
10303
10384
 
10304
10385
 
10305
10386
  /***
10306
- Instances of `up.Response` describe the server response to an [AJAX request](/up.request).
10387
+ A response to an [HTTP request](`up.request()`).
10307
10388
 
10308
10389
  \#\#\# Example
10309
10390
 
@@ -11281,37 +11362,23 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
11281
11362
  Events
11282
11363
  ======
11283
11364
 
11284
- This module contains functions to [build](/up.event.build), [dispatch](/up.emit) and [listen to](/up.on) DOM events.
11365
+ This module contains functions to [emit](/up.emit) and [observe](/up.on) DOM events.
11285
11366
 
11286
- While the browser also ships with functions like [`Element#dispatchEvent()`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent)
11287
- and [`Element#addEventListener()`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) to
11288
- work with DOM events, you will find the functions in this module to be more convenient and feature-rich.
11367
+ While the browser also has built-in functions to work with events,
11368
+ you will find Unpoly's functions to be very concise and feature-rich.
11289
11369
 
11290
11370
  ## Events emitted by Unpoly
11291
11371
 
11292
- Most Unpoly interactions emit DOM events that are prefixed with `up:`.
11372
+ Most Unpoly features emit events that are prefixed with `up:`.
11293
11373
 
11294
- ```javascript
11295
- document.addEventListener('up:modal:opened', (event) => {
11296
- console.log('A new modal has just opened!')
11297
- })
11298
- ```
11374
+ Unpoly's own events are documented in their respective modules, for example:
11299
11375
 
11300
- Events often have both present and past forms. For example, `up:layer:open` is emitted before an overlay starts to open.
11301
- `up:layer:opened` is emitted when the overlay has appeared in the DOM tree.
11302
-
11303
- \#\#\# Preventing events
11304
-
11305
- You can prevent most present form events by calling `preventDefault()`:
11306
-
11307
- ```javascript
11308
- document.addEventListener('up:modal:open', (event) => {
11309
- if (event.url == '/evil') {
11310
- // Prevent the modal from opening
11311
- event.preventDefault()
11312
- }
11313
- })
11314
- ```
11376
+ | Event | Module |
11377
+ |-----------------------|--------------------|
11378
+ | `up:link:follow` | `up.link` |
11379
+ | `up:form:submit` | `up.form` |
11380
+ | `up:layer:open` | `up.layer` |
11381
+ | `up:request:late` | `up.network` |
11315
11382
 
11316
11383
  @see up.on
11317
11384
  @see up.emit
@@ -11454,12 +11521,16 @@ document.addEventListener('up:modal:open', (event) => {
11454
11521
  Multiple event types may be passed as either a space-separated string
11455
11522
  or as an array of types.
11456
11523
 
11457
- @param {string} [selector]
11524
+ @param {string|Function():string} [selector]
11458
11525
  The selector of an element on which the event must be triggered.
11459
11526
 
11460
11527
  Omit the selector to listen to all events of the given type, regardless
11461
11528
  of the event target.
11462
11529
 
11530
+ If the selector is not known in advance you may also pass a function
11531
+ that returns the selector. The function is evaluated every time
11532
+ an event with the given type is observed.
11533
+
11463
11534
  @param {boolean} [options.passive=false]
11464
11535
  Whether to register a [passive event listener](https://developers.google.com/web/updates/2016/06/passive-event-listeners).
11465
11536
 
@@ -11470,7 +11541,7 @@ document.addEventListener('up:modal:open', (event) => {
11470
11541
  @param {boolean} [options.once=true]
11471
11542
  Whether the listener should run at most once.
11472
11543
 
11473
- If `true` the listener will automatically be removed from the element
11544
+ If `true` the listener will automatically be unbound
11474
11545
  after the first invocation.
11475
11546
 
11476
11547
  @param {Function(event, [element], [data])} listener
@@ -11561,12 +11632,12 @@ document.addEventListener('up:modal:open', (event) => {
11561
11632
 
11562
11633
  @function up.off
11563
11634
  @param {Element|jQuery} [element=document]
11564
- @param {string} events
11635
+ @param {string|Function(): string} events
11565
11636
  @param {string} [selector]
11566
11637
  @param {Function(event, [element], [data])} listener
11567
11638
  The listener function to unbind.
11568
11639
 
11569
- Note that you must pass a reference to the exact same listener function
11640
+ Note that you must pass a reference to the same function reference
11570
11641
  that was passed to `up.on()` earlier.
11571
11642
  @stable
11572
11643
  */
@@ -11817,7 +11888,7 @@ document.addEventListener('up:modal:open', (event) => {
11817
11888
 
11818
11889
  This hyperlink will emit an `user:select` event when clicked:
11819
11890
 
11820
- ```
11891
+ ```html
11821
11892
  <a href='/users/5'
11822
11893
  up-emit='user:select'
11823
11894
  up-emit-props='{ "id": 5, "firstName": "Alice" }'>
@@ -12135,7 +12206,7 @@ There are existing implementations for various web frameworks:
12135
12206
 
12136
12207
  The time is encoded is the number of seconds elapsed since the [Unix epoch](https://en.wikipedia.org/wiki/Unix_time).
12137
12208
 
12138
- For instance, a modification date of December 24th, 1:51:46 PM UTC would produce the following header:
12209
+ For instance, a modification date of December 23th, 1:40:18 PM UTC would produce the following header:
12139
12210
 
12140
12211
  ```http
12141
12212
  X-Up-Target: .unread-count
@@ -12376,7 +12447,7 @@ There are existing implementations for various web frameworks:
12376
12447
  the response's HTML content.
12377
12448
 
12378
12449
  The header value is the acceptance value serialized as a JSON object.
12379
- To accept an overlay without value, set the header value to `null`.
12450
+ To accept an overlay without value, set the header value to the string `null`.
12380
12451
 
12381
12452
  \#\#\# Example
12382
12453
 
@@ -12422,7 +12493,7 @@ There are existing implementations for various web frameworks:
12422
12493
  the response's HTML content.
12423
12494
 
12424
12495
  The header value is the dismissal value serialized as a JSON object.
12425
- To accept an overlay without value, set the header value to `null`.
12496
+ To accept an overlay without value, set the header value to the string `null`.
12426
12497
 
12427
12498
  \#\#\# Example
12428
12499
 
@@ -12647,13 +12718,14 @@ There are existing implementations for various web frameworks:
12647
12718
  Logging
12648
12719
  =======
12649
12720
 
12650
- Unpoly can print debugging information to the developer console, e.g.:
12721
+ Unpoly can print debugging information to the [browser console](https://developer.chrome.com/docs/devtools/console/), e.g.:
12651
12722
 
12652
12723
  - Which [events](/up.event) are called
12653
12724
  - When we're [making requests to the network](/up.request)
12654
12725
  - Which [compilers](/up.syntax) are applied to which elements
12655
12726
 
12656
- You can activate logging by calling [`up.log.enable()`](/up.log.enable).
12727
+ @see up.log.enable
12728
+ @see up.log.disable
12657
12729
 
12658
12730
  @module up.log
12659
12731
  */
@@ -12769,7 +12841,7 @@ You can activate logging by calling [`up.log.enable()`](/up.log.enable).
12769
12841
  };
12770
12842
 
12771
12843
  /***
12772
- Makes future Unpoly events print vast amounts of debugging information to the developer console.
12844
+ Starts printing debugging information to the developer console.
12773
12845
 
12774
12846
  Debugging information includes which elements are being [compiled](/up.syntax)
12775
12847
  and which [events](/up.event) are being emitted.
@@ -12784,7 +12856,7 @@ You can activate logging by calling [`up.log.enable()`](/up.log.enable).
12784
12856
  };
12785
12857
 
12786
12858
  /***
12787
- Prevents future Unpoly events from printing vast amounts of debugging information to the developer console.
12859
+ Stops printing debugging information to the developer console.
12788
12860
 
12789
12861
  Errors will still be printed, even with logging disabled.
12790
12862
 
@@ -12826,24 +12898,26 @@ You can activate logging by calling [`up.log.enable()`](/up.log.enable).
12826
12898
  };
12827
12899
 
12828
12900
  /***
12829
- * Registers an empty rejection handler in case the given promise
12830
- * rejects with an AbortError or a failed up.Response.
12831
- *
12832
- * This prevents browsers from printing "Uncaught (in promise)" to the error
12833
- * console when the promise is rejected.
12834
- *
12835
- * This is helpful for event handlers where it is clear that no rejection
12836
- * handler will be registered:
12837
- *
12838
- * up.on('submit', 'form[up-target]', (event, form) => {
12839
- * promise = up.submit(form)
12840
- * up.util.muteRejection(promise)
12841
- * })
12842
- *
12843
- * @function up.log.muteUncriticalRejection
12844
- * @param {Promise} promise
12845
- * @return {Promise}
12846
- * @internal
12901
+ Registers an empty rejection handler in case the given promise
12902
+ rejects with an AbortError or a failed up.Response.
12903
+
12904
+ This prevents browsers from printing "Uncaught (in promise)" to the error
12905
+ console when the promise is rejected.
12906
+
12907
+ This is helpful for event handlers where it is clear that no rejection
12908
+ handler will be registered:
12909
+
12910
+ ```js
12911
+ up.on('submit', 'form[up-target]', (event, form) => {
12912
+ promise = up.submit(form)
12913
+ up.util.muteRejection(promise)
12914
+ })
12915
+ ```
12916
+
12917
+ @function up.log.muteUncriticalRejection
12918
+ @param {Promise} promise
12919
+ @return {Promise}
12920
+ @internal
12847
12921
  */
12848
12922
  muteUncriticalRejection = function(promise) {
12849
12923
  return promise["catch"](function(error) {
@@ -13415,9 +13489,7 @@ The `up.syntax` package lets you pair HTML elements with JavaScript behavior.
13415
13489
  History
13416
13490
  ========
13417
13491
 
13418
- In an Unpoly app, every page has an URL.
13419
-
13420
- [Fragment updates](/up.link) automatically update the URL.
13492
+ The `up.history` module helps you work with the browser history.
13421
13493
 
13422
13494
  @see up.history.location
13423
13495
  @see up:location:changed
@@ -13445,7 +13517,7 @@ In an Unpoly app, every page has an URL.
13445
13517
  Defines whether [fragment updates](/up.render) will update the browser's current URL.
13446
13518
 
13447
13519
  If set to `false` Unpoly will never change the browser URL.
13448
- @param {boolean} [config.restoreScroll=true]
13520
+ @param {boolean} [config.enabled=true]
13449
13521
  Whether to restore the known scroll positions
13450
13522
  when the user goes back or forward in history.
13451
13523
  @stable
@@ -13554,7 +13626,7 @@ In an Unpoly app, every page has an URL.
13554
13626
  address bar with the given URL.
13555
13627
 
13556
13628
  When the user restores the new history entry later,
13557
- Unpoly will replace the document body with the body from that URL.
13629
+ Unpoly will replace a selector from `up.history.config.restoreTargets` with the body from that URL.
13558
13630
 
13559
13631
  Note that [fragment navigation](/navigation) will automatically update the
13560
13632
  browser's location bar for you.
@@ -13588,7 +13660,7 @@ In an Unpoly app, every page has an URL.
13588
13660
 
13589
13661
  When a [layer](/up.layer) has no [visible history](/up.Layer.prototype.historyVisible), following a link
13590
13662
  will not cause the browser's address bar to be updated. In this case no `up:location:changed` event will be emitted.
13591
- There will however be an `up:layer:location:changed` event be emitted.
13663
+ However, a `up:layer:location:changed` will be emitted even if the address bar did not change.
13592
13664
 
13593
13665
  @event up:location:changed
13594
13666
  @param {string} event.url
@@ -13752,7 +13824,7 @@ In an Unpoly app, every page has an URL.
13752
13824
  - As fragments enter the page they are automatically [compiled](/up.compiler) to activate JavaScript behavior.
13753
13825
  - Fragment changes may be [animated](/up.motion).
13754
13826
  - Fragments are placed on a [layer](/up.layer) that is isolated from other layers.
13755
- Unpoly functions will only see or change fragments from the [current layer](/up.layer.current)
13827
+ Unpoly features will only see or change fragments from the [current layer](/up.layer.current)
13756
13828
  unless you [explicitly target another layer](/layer-option).
13757
13829
  - Fragments [know the URL from where they were loaded](/up.source).
13758
13830
  They can be [reloaded](/up.reload) or [polled periodically](/up-polled).
@@ -13815,7 +13887,7 @@ In an Unpoly app, every page has an URL.
13815
13887
  The default configuration tries, in this order:
13816
13888
 
13817
13889
  - If the URL has a `#hash`, scroll to the hash.
13818
- - If updating a [main target](/main), reset scroll positions.
13890
+ - If updating a [main target](/up-main), reset scroll positions.
13819
13891
 
13820
13892
  @param {boolean|string|Function(Element)} [config.autoFocus]
13821
13893
  How to focus when updating a fragment with `{ focus: 'auto' }`.
@@ -13827,7 +13899,7 @@ In an Unpoly app, every page has an URL.
13827
13899
  - Focus a `#hash` in the URL.
13828
13900
  - Focus an `[autofocus]` element in the new fragment.
13829
13901
  - If focus was lost with the old fragment, focus the new fragment.
13830
- - If updating a [main target](/main), focus the new fragment.
13902
+ - If updating a [main target](/up-main), focus the new fragment.
13831
13903
 
13832
13904
  @param {boolean} [config.runScripts=false]
13833
13905
  Whether to execute `<script>` tags in updated fragments.
@@ -13835,7 +13907,7 @@ In an Unpoly app, every page has an URL.
13835
13907
  Scripts will load asynchronously, with no guarantee of execution order.
13836
13908
 
13837
13909
  If you set this to `true`, mind that the `<body>` element is a default
13838
- [main target](/main). If you are including your global application scripts
13910
+ [main target](/up-main). If you are including your global application scripts
13839
13911
  at the end of your `<body>`
13840
13912
  for performance reasons, swapping the `<body>` will re-execute these scripts.
13841
13913
  In that case you must configure a different main target that does not include
@@ -14018,7 +14090,7 @@ In an Unpoly app, every page has an URL.
14018
14090
 
14019
14091
  The current and new elements must both match the same CSS selector.
14020
14092
  The selector is either given as `{ target }` option,
14021
- or a [main target](/main) is used as default.
14093
+ or a [main target](/up-main) is used as default.
14022
14094
 
14023
14095
  See the [fragment placement](/fragment-placement) selector for many examples for how you can target content.
14024
14096
 
@@ -14079,29 +14151,32 @@ In an Unpoly app, every page has an URL.
14079
14151
 
14080
14152
  @function up.render
14081
14153
 
14082
- @param {string|Element|jQuery} [target]
14154
+ @param {string|Element|jQuery|Array<string>} [target]
14083
14155
  The CSS selector to update.
14084
14156
 
14085
- If omitted a [main target](/main) will be rendered.
14157
+ If omitted a [main target](/up-main) will be rendered.
14086
14158
 
14087
- You can also pass a DOM element or jQuery element here, in which case a selector
14159
+ You may also pass a DOM element or jQuery element here, in which case a selector
14088
14160
  will be [inferred from the element attributes](/up.fragment.toTarget). The given element
14089
14161
  will also be used as [`{ origin }`](#options.origin) for the fragment update.
14090
14162
 
14163
+ You may also pass an array of selector alternatives. The first selector
14164
+ matching in both old and new content will be used.
14165
+
14091
14166
  Instead of passing the target as the first argument, you may also pass it as
14092
14167
  a [´{ target }`](#options.target) option..
14093
14168
 
14094
- @param {string|Element|jQuery} [options.target]
14169
+ @param {string|Element|jQuery|Array<string>} [options.target]
14095
14170
  The CSS selector to update.
14096
14171
 
14097
- If omitted a [main target](/main) will be rendered.
14172
+ See documentation for the [`target`](#target) parameter.
14098
14173
 
14099
14174
  @param {string|boolean} [options.fallback=false]
14100
14175
  Specifies behavior if the [target selector](/up.render#options.target) is missing from the current page or the server response.
14101
14176
 
14102
14177
  If set to a CSS selector string, Unpoly will attempt to replace that selector instead.
14103
14178
 
14104
- If set to `true` Unpoly will attempt to replace a [main target](/main) instead.
14179
+ If set to `true` Unpoly will attempt to replace a [main target](/up-main) instead.
14105
14180
 
14106
14181
  If set to `false` Unpoly will immediately reject the render promise.
14107
14182
 
@@ -14181,7 +14256,7 @@ In an Unpoly app, every page has an URL.
14181
14256
 
14182
14257
  If set to `'auto'` history will be updated if the `{ target }` matches
14183
14258
  a selector in `up.fragment.config.autoHistoryTargets`. By default this contains all
14184
- [main targets](/main).
14259
+ [main targets](/up-main).
14185
14260
 
14186
14261
  If set to `false`, the history will remain unchanged.
14187
14262
 
@@ -14237,11 +14312,12 @@ In an Unpoly app, every page has an URL.
14237
14312
  Also see [`up.request({ cache })`](/up.request#options.cache).
14238
14313
 
14239
14314
  @param {boolean|string} [options.clearCache]
14240
- Whether existing [cache](/up.cache) entries will be cleared with this request.
14315
+ Whether existing [cache](/up.cache) entries will be [cleared](/up.cache.clear) with this request.
14241
14316
 
14242
- By default a non-GET request will clear the entire cache.
14243
14317
  You may also pass a [URL pattern](/url-patterns) to only clear matching requests.
14244
14318
 
14319
+ By default a non-GET request will clear the entire cache.
14320
+
14245
14321
  Also see [`up.request({ clearCache })`](/up.request#options.clearCache) and `up.network.config.clearCache`.
14246
14322
 
14247
14323
  @param {Element|jQuery} [options.origin]
@@ -14370,7 +14446,7 @@ In an Unpoly app, every page has an URL.
14370
14446
  @param {string|Element|jQuery} [target]
14371
14447
  The CSS selector to update.
14372
14448
 
14373
- If omitted a [main target](/main) will be rendered.
14449
+ If omitted a [main target](/up-main) will be rendered.
14374
14450
 
14375
14451
  You can also pass a DOM element or jQuery element here, in which case a selector
14376
14452
  will be [inferred from the element attributes](/up.fragment.target). The given element
@@ -14400,17 +14476,19 @@ In an Unpoly app, every page has an URL.
14400
14476
  an entirely different page layout (like a maintenance page or fatal server error)
14401
14477
  which should be open with a full page load:
14402
14478
 
14403
- up.on('up:fragment:loaded', (event) => {
14404
- let isMaintenancePage = event.response.getHeader('X-Maintenance')
14479
+ ```js
14480
+ up.on('up:fragment:loaded', (event) => {
14481
+ let isMaintenancePage = event.response.getHeader('X-Maintenance')
14405
14482
 
14406
- if (isMaintenancePage) {
14407
- // Prevent the fragment update and don't update browser history
14408
- event.preventDefault()
14483
+ if (isMaintenancePage) {
14484
+ // Prevent the fragment update and don't update browser history
14485
+ event.preventDefault()
14409
14486
 
14410
- // Make a full page load for the same request.
14411
- event.request.loadPage()
14412
- }
14413
- })
14487
+ // Make a full page load for the same request.
14488
+ event.request.loadPage()
14489
+ }
14490
+ })
14491
+ ```
14414
14492
 
14415
14493
  Instead of preventing the update, listeners may also access the `event.renderOptions` object
14416
14494
  to mutate options to the `up.render()` call that will process the server response.
@@ -14424,6 +14502,7 @@ In an Unpoly app, every page has an URL.
14424
14502
  The server response.
14425
14503
  @param {Object} event.renderOptions
14426
14504
  Options for the `up.render()` call that will process the server response.
14505
+ @stable
14427
14506
  */
14428
14507
 
14429
14508
  /***
@@ -15123,9 +15202,10 @@ In an Unpoly app, every page has an URL.
15123
15202
 
15124
15203
  \#\#\# Example
15125
15204
 
15126
- element = document.createElement('span')
15127
- element.className = 'klass'
15128
- selector = up.fragment.toTarget(element) // returns '.klass'
15205
+ ```js
15206
+ element = up.element.createFromHTML('<span class="klass">...</span>')
15207
+ selector = up.fragment.toTarget(element) // returns '.klass'
15208
+ ```
15129
15209
 
15130
15210
  @function up.fragment.toTarget
15131
15211
  @param {string|Element|jQuery}
@@ -15300,10 +15380,13 @@ In an Unpoly app, every page has an URL.
15300
15380
  When no other render target is given, Unpoly will try to find and replace a main target.
15301
15381
 
15302
15382
  In most app layouts the main target should match the primary content area.
15303
- The default main targets are the HTML5 [`<main>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main) element,
15304
- any element with an `[up-main]` attribute and the current layer's
15305
- [topmost swappable element](/main). You may configure main target selectors
15306
- in `up.fragment.config.mainTargets`.
15383
+ The default main targets are:
15384
+
15385
+ - any element with an `[up-main]` attribute
15386
+ - the HTML5 [`<main>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main) element
15387
+ - the current layer's [topmost swappable element](/layer)
15388
+
15389
+ You may configure main target selectors in `up.fragment.config.mainTargets`.
15307
15390
 
15308
15391
  \#\#\# Example
15309
15392
 
@@ -15315,6 +15398,86 @@ In an Unpoly app, every page has an URL.
15315
15398
  @experimental
15316
15399
  */
15317
15400
 
15401
+ /***
15402
+ Updates this element when no other render target is given.
15403
+
15404
+ \#\#\# Example
15405
+
15406
+ Many links simply replace the main content element in your application layout.
15407
+
15408
+ Unpoly lets you mark this elements as a default target using the `[up-main]` attribute:
15409
+
15410
+ ```html
15411
+ <body>
15412
+ <div class="layout">
15413
+ <div class="layout--side">
15414
+ ...
15415
+ </div>
15416
+ <div class="layout--content" up-main>
15417
+ ...
15418
+ </div>
15419
+ </div>
15420
+ </body>
15421
+ ```
15422
+
15423
+ Once a main target is configured, you no longer need `[up-target]` in a link.\
15424
+ Use `[up-follow]` and the `[up-main]` element will be replaced:
15425
+
15426
+ ```html
15427
+ <a href="/foo" up-follow>...</a>
15428
+ ```
15429
+
15430
+ If you want to update something more specific, you can still use `[up-target]`:
15431
+
15432
+ ```html
15433
+ <a href="/foo" up-target=".profile">...</a>
15434
+ ```
15435
+
15436
+ Instead of assigning `[up-main]` you may also configure an existing selector in `up.fragment.config.mainTargets`:
15437
+
15438
+ ```js
15439
+ up.fragment.config.mainTargets.push('.layout--content')
15440
+ ```
15441
+
15442
+ Overlays can use different main targets
15443
+ ---------------------------------------
15444
+
15445
+ Overlays often use a different default selector, e.g. to exclude a navigation bar.
15446
+
15447
+ To define a different main target for an overlay, set the [layer mode](/layer-terminology) as the
15448
+ value of the `[up-main]` attribute:
15449
+
15450
+ ```html
15451
+ <body>
15452
+ <div class="layout" up-main="root">
15453
+ <div class="layout--side">
15454
+ ...
15455
+ </div>
15456
+ <div class="layout--content" up-main="modal">
15457
+ ...
15458
+ </div>
15459
+ </div>
15460
+ </body>
15461
+ ```
15462
+
15463
+ Instead of assigning `[up-main]` you may also configure layer-specific targets in `up.layer.config`:
15464
+
15465
+ ```js
15466
+ up.layer.config.popup.mainTargets.push('.menu') // for popup overlays
15467
+ up.layer.config.drawer.mainTargets.push('.menu') // for drawer overlays
15468
+ up.layer.config.overlay.mainTargets.push('.layout--content') // for all overlay modes
15469
+ ```
15470
+
15471
+ @selector [up-main]
15472
+ @param [up-main]
15473
+ A space-separated list of [layer modes](/layer-terminology) for which to use this main target.
15474
+
15475
+ Omit the attribute value to define a main target for *all* layer modes.
15476
+
15477
+ To use a different main target for all overlays (but not the root layer), set `[up-main=overlay]`.
15478
+ @stable
15479
+ */
15480
+
15318
15481
  /***
15319
15482
  To make a server request without changing a fragment, use the `:none` selector.
15320
15483
 
@@ -15359,7 +15522,7 @@ In an Unpoly app, every page has an URL.
15359
15522
  For the [root layer](/up.layer.root) it is the `<body>` element. For an overlay
15360
15523
  it is the target with which the overlay was opened with.
15361
15524
 
15362
- In canonical usage the topmost swappable element is often a [main element](/main).
15525
+ In canonical usage the topmost swappable element is often a [main element](/up-main).
15363
15526
 
15364
15527
  \#\#\# Example
15365
15528
 
@@ -16380,11 +16543,16 @@ Animation
16380
16543
 
16381
16544
  When you [update a page fragment](/up.link) you can animate the change.
16382
16545
 
16383
- Let's say you are using an [`up-follow`](/a-up-follow) link to update an element
16384
- with content from the server. You can add an attribute [`up-transition`](/a-up-follow#up-transition)
16385
- to smoothly fade out the old element while fading in the new element:
16546
+ You can add an attribute [`[up-transition]`](/a-up-transition) to your
16547
+ links or forms to smoothly fade out the old element while fading in the new element:
16386
16548
 
16387
- <a href="/users" up-target=".list" up-transition="cross-fade">Show users</a>
16549
+ ```html
16550
+ <a href="/users"
16551
+ up-target=".list"
16552
+ up-transition="cross-fade">
16553
+ Show users
16554
+ </a>
16555
+ ```
16388
16556
 
16389
16557
  \#\#\# Transitions vs. animations
16390
16558
 
@@ -16392,10 +16560,17 @@ When we morph between an old and a new element, we call it a *transition*.
16392
16560
  In contrast, when we animate a new element without simultaneously removing an
16393
16561
  old element, we call it an *animation*.
16394
16562
 
16395
- An example for an animation is opening a new dialog. We can animate the appearance
16396
- of the dialog by adding an [`[up-animation]`](/a-up-modal#up-animation) attribute to the opening link:
16563
+ An example for an animation is opening a new overlay. We can animate the appearance
16564
+ of the dialog by adding an [`[up-animation]`](/a-up-animation) attribute to the opening link:
16397
16565
 
16398
- <a href="/users" up-modal=".list" up-animation="move-from-top">Show users</a>
16566
+ ```html
16567
+ <a href="/users"
16568
+ up-target=".list"
16569
+ up-layer="new"
16570
+ up-animation="move-from-top">
16571
+ Show users
16572
+ </a>
16573
+ ```
16399
16574
 
16400
16575
  \#\#\# Which animations are available?
16401
16576
 
@@ -16405,17 +16580,16 @@ and [predefined animations](/up.animate#named-animations).
16405
16580
  You can define custom animations using `up.transition()` and
16406
16581
  `up.animation()`.
16407
16582
 
16583
+ @see a[up-transition]
16408
16584
  @see up.animation
16409
- @see up.animate
16410
16585
  @see up.transition
16411
- @see up.morph
16412
16586
 
16413
16587
  @module up.motion
16414
16588
  */
16415
16589
 
16416
16590
  (function() {
16417
16591
  up.motion = (function() {
16418
- var animate, animateNow, applyConfig, composeTransitionFn, config, e, findAnimationFn, findNamedAnimation, findTransitionFn, finish, isEnabled, isNone, morph, motionController, namedAnimations, namedTransitions, pickDefault, registerAnimation, registerMoveMotions, registerOpacityAnimation, registerTransition, reset, skipAnimate, swapElementsDirectly, translateCSS, u, untranslatedBox, warnIfDisabled, willAnimate;
16592
+ var animate, animateNow, applyConfig, composeTransitionFn, config, e, findAnimationFn, findNamedAnimation, findTransitionFn, finish, isEnabled, isNone, morph, motionController, namedAnimations, namedTransitions, pickDefault, registerAnimation, registerMoveAnimations, registerOpacityAnimation, registerTransition, reset, skipAnimate, swapElementsDirectly, translateCSS, u, untranslatedBox, warnIfDisabled, willAnimate;
16419
16593
  u = up.util;
16420
16594
  e = up.element;
16421
16595
  namedAnimations = {};
@@ -16433,9 +16607,12 @@ You can define custom animations using `up.transition()` and
16433
16607
 
16434
16608
  See [W3C documentation](http://www.w3.org/TR/css3-transitions/#transition-timing-function)
16435
16609
  for a list of pre-defined timing functions.
16436
- @param {boolean} [config.enabled=true]
16610
+ @param {boolean} [config.enabled]
16437
16611
  Whether animation is enabled.
16438
16612
 
16613
+ By default animations are enabled, unless the user has configured their
16614
+ system to [minimize non-essential motion](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion).
16615
+
16439
16616
  Set this to `false` to disable animation globally.
16440
16617
  This can be useful in full-stack integration tests.
16441
16618
  @stable
@@ -16477,15 +16654,19 @@ You can define custom animations using `up.transition()` and
16477
16654
 
16478
16655
  \#\#\# Example
16479
16656
 
16480
- up.animate('.warning', 'fade-in')
16657
+ ```js
16658
+ up.animate('.warning', 'fade-in')
16659
+ ```
16481
16660
 
16482
16661
  You can pass additional options:
16483
16662
 
16484
- up.animate('.warning', 'fade-in', {
16485
- delay: 1000,
16486
- duration: 250,
16487
- easing: 'linear'
16488
- })
16663
+ ```
16664
+ up.animate('.warning', 'fade-in', {
16665
+ delay: 1000,
16666
+ duration: 250,
16667
+ easing: 'linear'
16668
+ })
16669
+ ```
16489
16670
 
16490
16671
  \#\#\# Named animations
16491
16672
 
@@ -16510,9 +16691,11 @@ You can define custom animations using `up.transition()` and
16510
16691
  By passing an object instead of an animation name, you can animate
16511
16692
  the CSS properties of the given element:
16512
16693
 
16513
- var warning = document.querySelector('.warning')
16514
- warning.style.opacity = 0
16515
- up.animate(warning, { opacity: 1 })
16694
+ ```
16695
+ var warning = document.querySelector('.warning')
16696
+ warning.style.opacity = 0
16697
+ up.animate(warning, { opacity: 1 })
16698
+ ```
16516
16699
 
16517
16700
  CSS properties must be given in `kebab-case`, not `camelCase`.
16518
16701
 
@@ -16618,7 +16801,7 @@ You can define custom animations using `up.transition()` and
16618
16801
  Animations are completed by jumping to the last animation frame instantly.
16619
16802
  Promises returned by animation and transition functions instantly settle.
16620
16803
 
16621
- Emits the `up:motion:finish` event that is already handled by `up.animate()`.
16804
+ Emits the `up:motion:finish` event that is handled by `up.animate()`.
16622
16805
 
16623
16806
  Does nothing if there are no animation to complete.
16624
16807
 
@@ -16816,18 +16999,20 @@ You can define custom animations using `up.transition()` and
16816
16999
  });
16817
17000
 
16818
17001
  /***
16819
- Defines a named transition that [morphs](/up.element) from one element to another.
17002
+ Defines a named transition that [morphs](/up.morph) from one element to another.
16820
17003
 
16821
17004
  \#\#\# Example
16822
17005
 
16823
17006
  Here is the definition of the pre-defined `cross-fade` animation:
16824
17007
 
16825
- up.transition('cross-fade', (oldElement, newElement, options) ->
16826
- Promise.all([
16827
- up.animate(oldElement, 'fade-out', options),
16828
- up.animate(newElement, 'fade-in', options)
16829
- ])
16830
- )
17008
+ ```js
17009
+ up.transition('cross-fade', (oldElement, newElement, options) ->
17010
+ Promise.all([
17011
+ up.animate(oldElement, 'fade-out', options),
17012
+ up.animate(newElement, 'fade-in', options)
17013
+ ])
17014
+ )
17015
+ ```
16831
17016
 
16832
17017
  It is recommended that your transitions use [`up.animate()`](/up.animate),
16833
17018
  passing along the `options` that were passed to you.
@@ -16862,10 +17047,12 @@ You can define custom animations using `up.transition()` and
16862
17047
 
16863
17048
  Here is the definition of the pre-defined `fade-in` animation:
16864
17049
 
16865
- up.animation('fade-in', function(element, options) {
16866
- element.style.opacity = 0
16867
- up.animate(element, { opacity: 1 }, options)
16868
- })
17050
+ ```js
17051
+ up.animation('fade-in', function(element, options) {
17052
+ element.style.opacity = 0
17053
+ up.animate(element, { opacity: 1 }, options)
17054
+ })
17055
+ ```
16869
17056
 
16870
17057
  It is recommended that your definitions always end by calling
16871
17058
  calling [`up.animate()`](/up.animate) with an object argument, passing along
@@ -16933,7 +17120,7 @@ You can define custom animations using `up.transition()` and
16933
17120
  e.setStyle(element, translateCSS(0, 0));
16934
17121
  return element.getBoundingClientRect();
16935
17122
  };
16936
- registerMoveMotions = function(direction, boxToTransform) {
17123
+ registerMoveAnimations = function(direction, boxToTransform) {
16937
17124
  var animationFromName, animationToName;
16938
17125
  animationToName = "move-to-" + direction;
16939
17126
  animationFromName = "move-from-" + direction;
@@ -16951,22 +17138,22 @@ You can define custom animations using `up.transition()` and
16951
17138
  return animateNow(element, translateCSS(0, 0), options);
16952
17139
  });
16953
17140
  };
16954
- registerMoveMotions('top', function(box) {
17141
+ registerMoveAnimations('top', function(box) {
16955
17142
  var travelDistance;
16956
17143
  travelDistance = box.top + box.height;
16957
17144
  return translateCSS(0, -travelDistance);
16958
17145
  });
16959
- registerMoveMotions('bottom', function(box) {
17146
+ registerMoveAnimations('bottom', function(box) {
16960
17147
  var travelDistance;
16961
17148
  travelDistance = up.viewport.rootHeight() - box.top;
16962
17149
  return translateCSS(0, travelDistance);
16963
17150
  });
16964
- registerMoveMotions('left', function(box) {
17151
+ registerMoveAnimations('left', function(box) {
16965
17152
  var travelDistance;
16966
17153
  travelDistance = box.left + box.width;
16967
17154
  return translateCSS(-travelDistance, 0);
16968
17155
  });
16969
- registerMoveMotions('right', function(box) {
17156
+ registerMoveAnimations('right', function(box) {
16970
17157
  var travelDistance;
16971
17158
  travelDistance = up.viewport.rootWidth() - box.left;
16972
17159
  return translateCSS(travelDistance, 0);
@@ -16981,10 +17168,17 @@ You can define custom animations using `up.transition()` and
16981
17168
  [Follows](/a-up-follow) this link and swaps in the new fragment
16982
17169
  with an animated transition.
16983
17170
 
17171
+ Note that transitions are not possible when replacing the `body`
17172
+ element.
17173
+
16984
17174
  \#\#\# Example
16985
17175
 
16986
17176
  ```html
16987
- <a href="/page2" up-transition="move-left">Next page</a>
17177
+ <a href="/page2"
17178
+ up-target=".story"
17179
+ up-transition="move-left">
17180
+ Next page
17181
+ </a>
16988
17182
  ```
16989
17183
 
16990
17184
  @selector a[up-transition]
@@ -16996,6 +17190,7 @@ You can define custom animations using `up.transition()` and
16996
17190
  The transition to use when the server responds with an error code.
16997
17191
 
16998
17192
  @see server-errors
17193
+ @stable
16999
17194
  */
17000
17195
 
17001
17196
  /***
@@ -17005,7 +17200,9 @@ You can define custom animations using `up.transition()` and
17005
17200
  \#\#\# Example
17006
17201
 
17007
17202
  ```html
17008
- <form action="/tasks" up-transition="cross-fade">
17203
+ <form action="/tasks"
17204
+ up-target=".content"
17205
+ up-transition="cross-fade">
17009
17206
  ...
17010
17207
  </form>
17011
17208
  ```
@@ -17019,6 +17216,7 @@ You can define custom animations using `up.transition()` and
17019
17216
  The transition to use when the server responds with an error code.
17020
17217
 
17021
17218
  @see server-errors
17219
+ @stable
17022
17220
  */
17023
17221
  up.on('up:framework:boot', warnIfDisabled);
17024
17222
  up.on('up:framework:reset', reset);
@@ -17059,47 +17257,25 @@ You can define custom animations using `up.transition()` and
17059
17257
  Network requests
17060
17258
  ================
17061
17259
 
17062
- TODO: Rewrite this page
17063
-
17064
- Unpoly comes with a number of tricks to shorten the latency between browser and server.
17065
-
17066
- \#\#\# Server responses are cached by default
17067
-
17068
- Unpoly caches server responses for a few minutes,
17069
- making requests to these URLs return instantly.
17070
- All Unpoly functions and selectors go through this cache, unless
17071
- you explicitly pass a `{ cache: false }` option or set an `up-cache="false"` attribute.
17072
-
17073
- The cache holds up to 50 responses for 5 minutes. You can configure the cache size and expiry using
17074
- [`up.network.config`](/up.network.config), or clear the cache manually using [`up.cache.clear()`](/up.cache.clear).
17075
-
17076
- Also the entire cache is cleared with every non-`GET` request (like `POST` or `PUT`).
17077
-
17078
- If you need to make cache-aware requests from your [custom JavaScript](/up.syntax),
17079
- use [`up.request()`](/up.request).
17080
-
17081
- \#\#\# Preloading links
17082
-
17083
- Unpoly also lets you speed up reaction times by [preloading
17084
- links](/a-up-preload) when the user hovers over the click area (or puts the mouse/finger
17085
- down). This way the response will already be cached when
17086
- the user releases the mouse/finger.
17260
+ Unpoly ships with an optimized HTTP client for fast and effective
17261
+ communication with your server-side app.
17087
17262
 
17088
- \#\#\# Spinners
17263
+ While you can use the browser's native `fetch()` function,
17264
+ Unpoly's `up.request()` has a number of convenience features:
17089
17265
 
17090
- You can listen to the [`up:request:late`](/up:request:late) event to implement a spinner
17091
- that appears during a long-running request.
17092
-
17093
- \#\#\# More acceleration
17094
-
17095
- Other Unpoly modules contain even more tricks to outsmart network latency:
17096
-
17097
- - [Instantaneous feedback for links that are currently loading](/a.up-active)
17098
- - [Follow links on `mousedown` instead of `click`](/a-up-instant)
17266
+ - Requests may be [cached](/up.request#options.cache) to reuse responses and enable [preloading](/a-up-preload).
17267
+ - Requests send [additional HTTP headers](/up.protocol) that the server may use to optimize its response.
17268
+ For example, when updating a [fragment](/up.fragment), the fragment's selector is automatically sent
17269
+ as an `X-Up-Target` header. The server may choose to only render the targeted fragment.
17270
+ - Useful events like `up:request:loaded` or `up:request:late` are emitted throughout the request/response
17271
+ lifecycle.
17272
+ - When too many requests are sent concurrently, excessive requests are [queued](/up.network.config#config.concurrency).
17273
+ This prevents exhausting the user's bandwidth and limits race conditions in end-to-end tests.
17274
+ - A very concise API requiring zero boilerplate code.
17099
17275
 
17100
17276
  @see up.request
17101
- @see up.Request
17102
17277
  @see up.Response
17278
+ @see up:request:late
17103
17279
 
17104
17280
  @module up.network
17105
17281
  */
@@ -17117,8 +17293,8 @@ You can define custom animations using `up.transition()` and
17117
17293
  Additional requests are queued. [Preload](/a-up-preload) requests are
17118
17294
  always queued behind non-preload requests.
17119
17295
 
17120
- You might find it useful to set the request concurrency `1` in full-stack
17121
- integration tests (e.g. Selenium) to prevent race conditions.
17296
+ You might find it useful to set the request concurrency `1` in end-to-end tests
17297
+ to prevent race conditions.
17122
17298
 
17123
17299
  Note that your browser might [impose its own request limit](http://www.browserscope.org/?category=network)
17124
17300
  regardless of what you configure here.
@@ -17220,7 +17396,7 @@ You can define custom animations using `up.transition()` and
17220
17396
 
17221
17397
  @stable
17222
17398
  */
17223
- var abortRequests, cache, config, handleCaching, isBusy, isIdle, isSafeMethod, makeRequest, mimicLocalRequest, parseRequestOptions, preload, queue, queueRequest, registerAliasForRedirect, reset, shouldReduceRequests, useCachedRequest;
17399
+ var abortRequests, cache, config, handleCaching, isBusy, isIdle, isSafeMethod, makeRequest, mimicLocalRequest, parseRequestOptions, queue, queueRequest, registerAliasForRedirect, reset, shouldReduceRequests, useCachedRequest;
17224
17400
  config = new up.Config(function() {
17225
17401
  return {
17226
17402
  concurrency: 4,
@@ -17278,13 +17454,24 @@ You can define custom animations using `up.transition()` and
17278
17454
  /***
17279
17455
  Removes all [cache](/up.cache.get) entries.
17280
17456
 
17281
- Unpoly also automatically clears the cache whenever it processes
17282
- a request with an [unsafe](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1)
17283
- HTTP method like `POST`.
17457
+ To only remove some cache entries, pass a [URL pattern](/url-patterns):
17458
+
17459
+ ```js
17460
+ up.cache.clear('/users/*')
17461
+ ```
17462
+
17463
+ \#\#\# Other reasons the cache may clear
17464
+
17465
+ By default Unpoly automatically clears the entire cache whenever it processes
17466
+ a request with an non-GET HTTP method. To customize this rule, use `up.network.config.clearCache`.
17284
17467
 
17285
17468
  The server may also clear the cache by sending an [`X-Up-Cache: clear`](/X-Up-Cache) header.
17286
17469
 
17287
17470
  @function up.cache.clear
17471
+ @param {string} [pattern]
17472
+ A [URL pattern](/url-patterns) matching cache entries that should be cleared.
17473
+
17474
+ If omitted, the entire cache is cleared.
17288
17475
  @stable
17289
17476
  */
17290
17477
 
@@ -17342,39 +17529,45 @@ You can define custom animations using `up.transition()` and
17342
17529
  Makes an AJAX request to the given URL.
17343
17530
 
17344
17531
  Returns an `up.Request` object which contains information about the request.
17345
- The request object is also a promise for its `up.Response`.
17532
+ This request object is also a promise for an `up.Response` that contains
17533
+ the response text, headers, etc.
17346
17534
 
17347
17535
  \#\#\# Example
17348
17536
 
17349
- let request = up.request('/search', { params: { query: 'sunshine' } })
17350
- console.log('We made a request to', request.url)
17537
+ ```js
17538
+ let request = up.request('/search', { params: { query: 'sunshine' } })
17539
+ console.log('We made a request to', request.url)
17351
17540
 
17352
- let response = await request
17353
- console.log('The response text is', response.text)
17541
+ let response = await request
17542
+ console.log('The response text is', response.text)
17543
+ ```
17354
17544
 
17355
17545
  \#\#\# Error handling
17356
17546
 
17357
17547
  The returned promise will fulfill with an `up.Response` when the server
17358
17548
  responds with an HTTP status of 2xx (like `200`).
17359
17549
 
17360
- When the server responds with an error code (like `422` or `500`), the promise
17550
+ When the server responds with an HTTP error code (like `422` or `500`), the promise
17361
17551
  will *reject* with `up.Response`.
17362
17552
 
17363
17553
  When the request fails from a fatal error (like a timeout or loss of connectivity),
17364
17554
  the promise will reject with an [`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) object.
17365
17555
 
17366
- Here is an example for a complete control flow that also handles errors:
17556
+ Here is an example for a complete control flow that handles both HTTP error codes
17557
+ and fatal errors:
17367
17558
 
17368
- try {
17369
- let response = await up.request('/search', { params: { query: 'sunshine' } })
17370
- console.log('Successful response with text:', response.text)
17371
- } catch (e) {
17372
- if (e instanceof up.Response) {
17373
- console.log('Server responded with HTTP status %s and text %s', e.status, e.text)
17374
- } else {
17375
- console.log('Fatal error during request:', e.message)
17376
- }
17377
- }
17559
+ ```js
17560
+ try {
17561
+ let response = await up.request('/search', { params: { query: 'sunshine' } })
17562
+ console.log('Successful response with text:', response.text)
17563
+ } catch (e) {
17564
+ if (e instanceof up.Response) {
17565
+ console.log('Server responded with HTTP status %s and text %s', e.status, e.text)
17566
+ } else {
17567
+ console.log('Fatal error during request:', e.message)
17568
+ }
17569
+ }
17570
+ ```
17378
17571
 
17379
17572
  \#\#\# Caching
17380
17573
 
@@ -17417,10 +17610,13 @@ You can define custom animations using `up.transition()` and
17417
17610
 
17418
17611
  With `{ cache: false }` (the default) Unpoly will always make a network request.
17419
17612
 
17420
- @param {boolean} [options.clearCache]
17421
- Whether to clear the cache after this request.
17613
+ @param {boolean|string} [options.clearCache]
17614
+ Whether to [clear](/up.cache.clear) the [cache](/up.cache.get) after this request.
17422
17615
 
17423
- Defaults to the result of `up.network.config.clearCache`.
17616
+ You may also pass a [URL pattern](/url-patterns) to only clear matching requests.
17617
+
17618
+ Defaults to the result of `up.network.config.clearCache`, which
17619
+ defaults to clearing the entire cache after a non-GET request.
17424
17620
 
17425
17621
  @param {Object} [options.headers={}]
17426
17622
  An object of additional HTTP headers.
@@ -17445,13 +17641,13 @@ You can define custom animations using `up.transition()` and
17445
17641
  @param {string} [options.target='body']
17446
17642
  The CSS selector that will be sent as an `X-Up-Target` header.
17447
17643
 
17448
- @param {string} [options.layer='current']
17449
- The [layer](/up.layer) this request is associated with.
17450
-
17451
17644
  @param {string} [options.failTarget='body']
17452
17645
  The CSS selector that will be sent as an `X-Up-Fail-Target` header.
17453
17646
 
17454
17647
  @param {string} [options.layer='current']
17648
+ The [layer](/up.layer) this request is associated with.
17649
+
17650
+ @param {string} [options.failLayer='current']
17455
17651
  The [layer](/up.layer) this request is associated with if the server [sends a HTTP status code](/server-errors).
17456
17652
 
17457
17653
  @param {Element} [options.origin]
@@ -17503,16 +17699,6 @@ You can define custom animations using `up.transition()` and
17503
17699
  return cache.clear(clearCache);
17504
17700
  }
17505
17701
  };
17506
- preload = function() {
17507
- var args, base, options;
17508
- args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
17509
- if (typeof (base = up.migrate).handleNetworkPreloadArgs === "function") {
17510
- base.handleNetworkPreloadArgs.apply(base, args);
17511
- }
17512
- options = parseRequestOptions(args);
17513
- options.preload = true;
17514
- return makeRequest(options);
17515
- };
17516
17702
  parseRequestOptions = function(args) {
17517
17703
  var base, options;
17518
17704
  options = u.extractOptions(args);
@@ -17624,18 +17810,24 @@ You can define custom animations using `up.transition()` and
17624
17810
 
17625
17811
  Without arguments, this will abort all pending requests:
17626
17812
 
17627
- up.network.abort()
17813
+ ```js
17814
+ up.network.abort()
17815
+ ```
17628
17816
 
17629
17817
  To abort a given `up.Request` object, pass it as the first argument:
17630
17818
 
17631
- let request = up.request('/path')
17632
- up.network.abort(request)
17819
+ ```js
17820
+ let request = up.request('/path')
17821
+ up.network.abort(request)
17822
+ ```
17633
17823
 
17634
17824
  To abort all requests matching a condition, pass a function that takes a request
17635
17825
  and returns a boolean value. Unpoly will abort all request for which the given
17636
17826
  function returns `true`. E.g. to abort all requests with a HTTP method as `GET`:
17637
17827
 
17638
- up.network.abort((request) => request.method == 'GET')
17828
+ ```js
17829
+ up.network.abort((request) => request.method == 'GET')
17830
+ ```
17639
17831
 
17640
17832
  @function up.network.abort
17641
17833
  @param {up.Request|boolean|Function(up.Request): boolean} [matcher=true]
@@ -17797,7 +17989,6 @@ You can define custom animations using `up.transition()` and
17797
17989
  up.on('up:framework:reset', reset);
17798
17990
  return {
17799
17991
  request: makeRequest,
17800
- preload: preload,
17801
17992
  cache: cache,
17802
17993
  isIdle: isIdle,
17803
17994
  isBusy: isBusy,
@@ -17891,7 +18082,7 @@ You can define custom animations using `up.transition()` and
17891
18082
  up.layer.config.modal.openAnimation = 'move-from-top'
17892
18083
  ```
17893
18084
 
17894
- To configure an additional [main target](/main)
18085
+ To configure an additional [main target](/up-main)
17895
18086
  for overlay of any mode:
17896
18087
 
17897
18088
  ```js
@@ -18198,7 +18389,7 @@ You can define custom animations using `up.transition()` and
18198
18389
  If set to `true` the overlay location and title will be shown in browser UI.
18199
18390
 
18200
18391
  If set to `'auto'` history will be visible if the initial overlay
18201
- content matches a [main target](/main).
18392
+ content matches a [main target](/up-main).
18202
18393
 
18203
18394
  @param {string|Function} [options.animation]
18204
18395
  The opening animation.
@@ -18333,11 +18524,25 @@ You can define custom animations using `up.transition()` and
18333
18524
  */
18334
18525
 
18335
18526
  /***
18336
- TODO: Docs
18527
+ This event is emitted after a new overlay has been placed into the DOM.
18528
+
18529
+ The event is emitted right before the opening animation starts. Because the overlay
18530
+ has not been rendered by the browser, this makes it a good occasion to
18531
+ [customize overlay elements](/customizing-overlays#customizing-overlay-elements):
18532
+
18533
+ ```js
18534
+ up.on('up:layer:opened', function(event) {
18535
+ if (isChristmas()) {
18536
+ up.element.affix(event.layer.element, '.santa-hat', text: 'Merry Christmas!')
18537
+ }
18538
+ })
18539
+ ```
18337
18540
 
18338
18541
  @event up:layer:opened
18339
18542
  @param {Element} event.origin
18543
+ The link element that is opening the overlay.
18340
18544
  @param {up.Layer} event.layer
18545
+ The [layer object](/up.Layer) that is opening.
18341
18546
  @stable
18342
18547
  */
18343
18548
 
@@ -18345,7 +18550,7 @@ You can define custom animations using `up.transition()` and
18345
18550
  This event is emitted after a layer's [location property](/up.Layer.prototype.location)
18346
18551
  has changed value.
18347
18552
 
18348
- This event is also emitted when a layer [without history](/up.Layer.prototype.historyVisible)
18553
+ This event is also emitted when a layer [without visible history](/up.Layer.prototype.historyVisible)
18349
18554
  has reached a new location.
18350
18555
 
18351
18556
  @param {string} event.location
@@ -18381,6 +18586,7 @@ You can define custom animations using `up.transition()` and
18381
18586
  A promise that will settle when the overlay closes.
18382
18587
 
18383
18588
  When the overlay was accepted, the promise will fulfill with the overlay's acceptance value.
18589
+
18384
18590
  When the overlay was dismissed, the promise will reject with the overlay's dismissal value.
18385
18591
 
18386
18592
  @stable
@@ -18412,7 +18618,7 @@ You can define custom animations using `up.transition()` and
18412
18618
  };
18413
18619
 
18414
18620
  /***
18415
- [Follows](/a-up-follow) this link and opens the result in a new layer.
18621
+ [Follows](/a-up-follow) this link and opens the result in a new overlay.
18416
18622
 
18417
18623
  \#\#\# Example
18418
18624
 
@@ -18453,7 +18659,7 @@ You can define custom animations using `up.transition()` and
18453
18659
  If set to `true` the overlay location and title will be shown in browser UI.
18454
18660
 
18455
18661
  If set to `'auto'` history will be visible if the initial overlay
18456
- content matches a [main target](/main).
18662
+ content matches a [main target](/up-main).
18457
18663
 
18458
18664
  @param [up-dismissable]
18459
18665
  How the overlay may be [dismissed](/closing-overlays) by the user.
@@ -18656,12 +18862,33 @@ You can define custom animations using `up.transition()` and
18656
18862
  The *current* layer is usually the [frontmost layer](/up.layer.front).
18657
18863
  There are however some cases where the current layer is a layer in the background:
18658
18864
 
18659
- - While an element in a background layer is [compiled](/up.compiler).
18865
+ - While an element in a background layer is being [compiled](/up.compiler).
18660
18866
  - While an Unpoly event like `up:request:loaded` is being triggered from a background layer.
18661
- - While a running event listener was bound to a background layer using `up.Layer#on()`.
18867
+ - While an event listener bound to a background layer using `up.Layer#on()` is being called.
18662
18868
 
18663
18869
  To temporarily change the current layer from your own code, use `up.Layer#asCurrent()`.
18664
18870
 
18871
+ \#\#\# Remembering the current layer
18872
+
18873
+ Most functions in the `up.layer` package affect the current layer. E.g. `up.layer.dismiss()`
18874
+ is shorthand for `up.layer.current.dismiss()`.
18875
+
18876
+ As described above `up.layer.current` is set to the right layer in compilers and most events,
18877
+ even if that layer is not the frontmost layer.
18878
+
18879
+ If you have async code, the current layer may change when your callback is called.
18880
+ To address this you may retrieve the current layer for later reference:
18881
+
18882
+ ```js
18883
+ function dismissCurrentLayerIn(seconds) {
18884
+ let savedLayer = up.layer.current // returns an up.Layer object
18885
+ let dismiss = () => savedLayer.dismiss()
18886
+ setTimeout(dismiss, seconds * 1000)
18887
+ }
18888
+
18889
+ dismissCurrentLayerIn(10) //
18890
+ ```
18891
+
18665
18892
  @property up.layer.current
18666
18893
  @param {up.Layer} current
18667
18894
  @stable
@@ -18705,6 +18932,9 @@ You can define custom animations using `up.transition()` and
18705
18932
  /***
18706
18933
  Returns the [root layer](/layer-terminology).
18707
18934
 
18935
+ The root layer represents the initial page before any overlay was [opened](/opening-overlays).
18936
+ The root layer always exists and cannot be closed.
18937
+
18708
18938
  @property up.layer.root
18709
18939
  @param {up.Layer} root
18710
18940
  @stable
@@ -18715,6 +18945,9 @@ You can define custom animations using `up.transition()` and
18715
18945
 
18716
18946
  If no overlay is open, an empty array is returned.
18717
18947
 
18948
+ To get an array of *all* layers including the [root layer](/up.layer.root),
18949
+ use `up.layer.stack`.
18950
+
18718
18951
  @property up.layer.overlays
18719
18952
  @param {Array<up.Layer>} overlays
18720
18953
  @stable
@@ -18753,13 +18986,13 @@ You can define custom animations using `up.transition()` and
18753
18986
  /***
18754
18987
  [Accepts](/closing-overlays) the [current layer](up.layer.current).
18755
18988
 
18756
- This is a shortcut for `up.layer.current.dismiss()`.
18757
- See `up.Layer#dismiss()` for more documentation.
18989
+ This is a shortcut for `up.layer.current.accept()`.
18990
+ See `up.Layer#accept()` for more documentation.
18758
18991
 
18759
- @function up.layer.dismiss
18992
+ @function up.layer.accept
18760
18993
  @param {any} [value]
18761
18994
  @param {Object} [options]
18762
- @return
18995
+ @stable
18763
18996
  */
18764
18997
 
18765
18998
  /***
@@ -18771,7 +19004,7 @@ You can define custom animations using `up.transition()` and
18771
19004
  @function up.layer.dismiss
18772
19005
  @param {any} [value]
18773
19006
  @param {Object} [options]
18774
- @return
19007
+ @stable
18775
19008
  */
18776
19009
 
18777
19010
  /***
@@ -18780,7 +19013,7 @@ You can define custom animations using `up.transition()` and
18780
19013
  This is a shortcut for `up.layer.current.isRoot()`.
18781
19014
  See `up.Layer#isRoot()` for more documentation..
18782
19015
 
18783
- @function up.layer.isFront
19016
+ @function up.layer.isRoot
18784
19017
  @return {boolean}
18785
19018
  @stable
18786
19019
  */
@@ -18817,7 +19050,7 @@ You can define custom animations using `up.transition()` and
18817
19050
  @function up.layer.on
18818
19051
  @param {string} types
18819
19052
  A space-separated list of event types to bind to.
18820
- @param {string} [selector]
19053
+ @param {string|Function(): string} [selector]
18821
19054
  The selector of an element on which the event must be triggered.
18822
19055
  @param {Object} [options]
18823
19056
  @param {Function(event, [element], [data])} listener
@@ -18834,9 +19067,8 @@ You can define custom animations using `up.transition()` and
18834
19067
  See `up.Layer#off()` for more documentation.
18835
19068
 
18836
19069
  @function up.layer.off
18837
- @param {Element|jQuery} [element=document]
18838
19070
  @param {string} events
18839
- @param {string} [selector]
19071
+ @param {string|Function(): string} [selector]
18840
19072
  @param {Function(event, [element], [data])} listener
18841
19073
  The listener function to unbind.
18842
19074
  @stable
@@ -18849,7 +19081,6 @@ You can define custom animations using `up.transition()` and
18849
19081
  See `up.Layer#emit()` for more documentation.
18850
19082
 
18851
19083
  @function up.layer.emit
18852
- @param {Element|jQuery} [target=up.layer.element]
18853
19084
  @param {string} eventType
18854
19085
  @param {Object} [props={}]
18855
19086
  @stable
@@ -18879,7 +19110,7 @@ You can define custom animations using `up.transition()` and
18879
19110
  */
18880
19111
 
18881
19112
  /***
18882
- The location of the [current layer](/up.layer.current).
19113
+ The location URL of the [current layer](/up.layer.current).
18883
19114
 
18884
19115
  This is a shortcut for `up.layer.current.location`.
18885
19116
  See `up.Layer#location` for more documentation.
@@ -18890,9 +19121,8 @@ You can define custom animations using `up.transition()` and
18890
19121
  */
18891
19122
 
18892
19123
  /***
18893
- The [current layer](/up.layer.current)'s mode which governs its appearance and behavior.
18894
-
18895
- @see layer-terminology
19124
+ The [current layer](/up.layer.current)'s [mode](/up.layer.mode)
19125
+ which governs its appearance and behavior.
18896
19126
 
18897
19127
  @property up.layer.mode
18898
19128
  @param {string} mode
@@ -19001,7 +19231,7 @@ new page is loading.
19001
19231
  var slice = [].slice;
19002
19232
 
19003
19233
  up.link = (function() {
19004
- var ATTRIBUTES_SUGGESTING_FOLLOW, LINKS_WITH_LOCAL_HTML, LINKS_WITH_REMOTE_HTML, combineFollowableSelectors, config, convertClicks, didUserDragAway, e, follow, followMethod, followOptions, followURL, forkEventAsUpClick, fullClickableSelector, fullFollowSelector, fullInstantSelector, fullPreloadSelector, isFollowDisabled, isFollowable, isInstant, isInstantDisabled, isPreloadDisabled, isSafe, lastMousedownTarget, linkPreloader, makeClickable, makeFollowable, parseRequestOptions, preload, reset, shouldFollowEvent, shouldPreload, targetMacro, u, willCache;
19234
+ var ATTRIBUTES_SUGGESTING_FOLLOW, LINKS_WITH_LOCAL_HTML, LINKS_WITH_REMOTE_HTML, combineFollowableSelectors, config, convertClicks, didUserDragAway, e, follow, followMethod, followOptions, followURL, forkEventAsUpClick, fullClickableSelector, fullFollowSelector, fullInstantSelector, fullPreloadSelector, isFollowDisabled, isFollowable, isInstant, isInstantDisabled, isPreloadDisabled, isSafe, lastMousedownTarget, linkPreloader, makeClickable, makeFollowable, parseRequestOptions, preload, reset, shouldFollowEvent, shouldPreload, u, willCache;
19005
19235
  u = up.util;
19006
19236
  e = up.element;
19007
19237
  linkPreloader = new up.LinkPreloader();
@@ -19018,9 +19248,10 @@ new page is loading.
19018
19248
  };
19019
19249
 
19020
19250
  /***
19021
- TODO: Docs
19022
- TODO: Doucment that noInstantSelectors and noPreloadSelectors inherit from noFollowSelectors
19023
- TODO: Document that noFollowSelectors already excludes cross-origin, rel=download, [target], [href^=#], javascript: hrefs
19251
+ Configures defaults for link handling.
19252
+
19253
+ In particular you can configure Unpoly to handle [all links on the page](/handling-everything)
19254
+ without requiring developers to set `[up-...]` attributes.
19024
19255
 
19025
19256
  @property up.link.config
19026
19257
 
@@ -19093,7 +19324,7 @@ new page is loading.
19093
19324
 
19094
19325
  If set to `false`, Unpoly will never preload links.
19095
19326
 
19096
- @param {Array<string>} [config.cickableSelectors]
19327
+ @param {Array<string>} [config.clickableSelectors]
19097
19328
  A list of CSS selectors matching elements that should behave like links or buttons.
19098
19329
 
19099
19330
  @see [up-clickable]
@@ -19167,7 +19398,7 @@ new page is loading.
19167
19398
  /***
19168
19399
  Follows the given link with JavaScript and updates a fragment with the server response.
19169
19400
 
19170
- By default the layer's [main element](/main)
19401
+ By default the layer's [main element](/up-main)
19171
19402
  will be replaced. Attributes like `a[up-target]`
19172
19403
  or `a[up-layer]` will be honored.
19173
19404
 
@@ -19229,8 +19460,24 @@ new page is loading.
19229
19460
  };
19230
19461
 
19231
19462
  /***
19232
- Parses the `render()` options that would be used to
19233
- [`follow`](/up.follow) the given link, but does not [render](/up.render).
19463
+ Parses the [render](/up.render) options that would be used to
19464
+ [`follow`](/up.follow) the given link, but does not render.
19465
+
19466
+ \#\#\# Example
19467
+
19468
+ Given a link with some `[up-...]` attributes:
19469
+
19470
+ ```html
19471
+ <a href="/foo" up-target=".content" up-layer="new">...</a>
19472
+ ```
19473
+
19474
+ We can parse the link's render options like this:
19475
+
19476
+ ```js
19477
+ let link = document.querySelector('a[href="/foo"]')
19478
+ let options = up.link.followOptions(link)
19479
+ // => { url: '/foo', method: 'GET', target: '.content', layer: 'new', ... }
19480
+ ```
19234
19481
 
19235
19482
  @function up.link.followOptions
19236
19483
  @param {Element|jQuery|string} link
@@ -19348,7 +19595,10 @@ new page is loading.
19348
19595
  @param {Object} options
19349
19596
  See options for `up.follow()`.
19350
19597
  @return {Promise}
19351
- A promise that will be fulfilled when the request was loaded and cached
19598
+ A promise that will be fulfilled when the request was loaded and cached.
19599
+
19600
+ When preloading is [disabled](/up.link.config#config.preloadEnabled) the promise
19601
+ rejects with an `AbortError`.
19352
19602
  @stable
19353
19603
  */
19354
19604
  preload = function(link, options) {
@@ -19452,7 +19702,7 @@ new page is loading.
19452
19702
  @function up.link.makeFollowable
19453
19703
  @param {Element|jQuery|string} link
19454
19704
  The element or selector for the link to make followable.
19455
- @stable
19705
+ @experimental
19456
19706
  */
19457
19707
  makeFollowable = function(link) {
19458
19708
  if (!isFollowable(link)) {
@@ -19588,6 +19838,13 @@ new page is loading.
19588
19838
  If the user activates an element using their keyboard, the `up:click` event will be emitted
19589
19839
  when the key is pressed even if the element has an `[up-instant]` attribute.
19590
19840
 
19841
+ \#\#\# Only unmodified clicks are considered
19842
+
19843
+ To prevent overriding native browser behavior, the `up:click` is only emitted for unmodified clicks.
19844
+
19845
+ In particular, it is not emitted when the user holds `Shift`, `CTRL` or `Meta` while clicking.
19846
+ Neither it is emitted when the user clicks with a secondary mouse button.
19847
+
19591
19848
  @event up:click
19592
19849
  @param {Element} event.target
19593
19850
  The clicked element.
@@ -19610,20 +19867,6 @@ new page is loading.
19610
19867
  method = followMethod(link);
19611
19868
  return up.network.isSafeMethod(method);
19612
19869
  };
19613
- targetMacro = function(queryAttr, fixedResultAttrs, callback) {
19614
- return up.macro("[" + queryAttr + "]", function(link) {
19615
- var optionalTarget, resultAttrs;
19616
- resultAttrs = u.copy(fixedResultAttrs);
19617
- if (optionalTarget = link.getAttribute(queryAttr)) {
19618
- resultAttrs['up-target'] = optionalTarget;
19619
- } else {
19620
- resultAttrs['up-follow'] = '';
19621
- }
19622
- e.setMissingAttrs(link, resultAttrs);
19623
- link.removeAttribute(queryAttr);
19624
- return typeof callback === "function" ? callback() : void 0;
19625
- });
19626
- };
19627
19870
 
19628
19871
  /***
19629
19872
  [Follows](/up.follow) this link with JavaScript and updates a fragment with the server response.
@@ -19639,7 +19882,7 @@ new page is loading.
19639
19882
  <a href="/posts/5" up-follow up-target=".content">Read post</a>
19640
19883
  ```
19641
19884
 
19642
- If no `[up-target]` attribute is set, the [main target](/main) is updated.
19885
+ If no `[up-target]` attribute is set, the [main target](/up-main) is updated.
19643
19886
 
19644
19887
  \#\#\# Advanced fragment changes
19645
19888
 
@@ -19676,14 +19919,14 @@ new page is loading.
19676
19919
  @param [up-target]
19677
19920
  The CSS selector to update.
19678
19921
 
19679
- If omitted a [main target](/main) will be rendered.
19922
+ If omitted a [main target](/up-main) will be rendered.
19680
19923
 
19681
19924
  @param [up-fallback]
19682
19925
  Specifies behavior if the [target selector](/up.render#options.target) is missing from the current page or the server response.
19683
19926
 
19684
19927
  If set to a CSS selector, Unpoly will attempt to replace that selector instead.
19685
19928
 
19686
- If set to `true` Unpoly will attempt to replace a [main target](/main) instead.
19929
+ If set to `true` Unpoly will attempt to replace a [main target](/up-main) instead.
19687
19930
 
19688
19931
  If set to `false` Unpoly will immediately reject the render promise.
19689
19932
 
@@ -19757,7 +20000,7 @@ new page is loading.
19757
20000
 
19758
20001
  If set to `auto` history will be updated if the `[up-target]` matches
19759
20002
  a selector in `up.fragment.config.autoHistoryTargets`. By default this contains all
19760
- [main targets](/main).
20003
+ [main targets](/up-main).
19761
20004
 
19762
20005
  If set to `false`, the history will remain unchanged.
19763
20006
 
@@ -19917,37 +20160,6 @@ new page is loading.
19917
20160
  @stable
19918
20161
  */
19919
20162
 
19920
- /***
19921
- [Follows](/up.follow) this link as fast as possible.
19922
-
19923
- This is done by:
19924
-
19925
- - [Following the link through AJAX](/a-up-follow) instead of a full page load
19926
- - [Preloading the link's destination URL](/a-up-preload)
19927
- - [Triggering the link on `mousedown`](/a-up-instant) instead of on `click`
19928
-
19929
- \#\#\# Example
19930
-
19931
- Use `[up-dash]` like this:
19932
-
19933
- <a href="/users" up-dash=".main">User list</a>
19934
-
19935
- This is shorthand for:
19936
-
19937
- <a href="/users" up-target=".main" up-instant up-preload>User list</a>
19938
-
19939
- @selector a[up-dash]
19940
- @param [up-dash='body']
19941
- The CSS selector to replace
19942
-
19943
- Inside the CSS selector you may refer to this link as `&` ([like in Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector)).
19944
- @stable
19945
- */
19946
- targetMacro('up-dash', {
19947
- 'up-preload': '',
19948
- 'up-instant': ''
19949
- });
19950
-
19951
20163
  /***
19952
20164
  Add an `[up-expand]` attribute to any element to enlarge the click area of a
19953
20165
  descendant link.
@@ -20036,7 +20248,6 @@ new page is loading.
20036
20248
  isFollowable: isFollowable,
20037
20249
  shouldFollowEvent: shouldFollowEvent,
20038
20250
  followMethod: followMethod,
20039
- targetMacro: targetMacro,
20040
20251
  convertClicks: convertClicks,
20041
20252
  config: config,
20042
20253
  combineFollowableSelectors: combineFollowableSelectors
@@ -20065,7 +20276,7 @@ The `up.form` module helps you work with non-trivial forms.
20065
20276
  var slice = [].slice;
20066
20277
 
20067
20278
  up.form = (function() {
20068
- var ATTRIBUTES_SUGGESTING_SUBMIT, abortScheduledValidate, autosubmit, config, e, fieldSelector, findFields, findSwitcherForTarget, findValidateTarget, findValidateTargetFromConfig, focusedField, fullSubmitSelector, getContainer, isSubmitDisabled, observe, observeCallbackFromElement, reset, submit, submitButtonSelector, submitOptions, submittingButton, switchTarget, switchTargets, switcherValues, u, validate;
20279
+ var ATTRIBUTES_SUGGESTING_SUBMIT, abortScheduledValidate, autosubmit, config, e, fieldSelector, findFields, findSwitcherForTarget, findValidateTarget, findValidateTargetFromConfig, focusedField, fullSubmitSelector, getContainer, isSubmitDisabled, isSubmittable, observe, observeCallbackFromElement, reset, submit, submitButtonSelector, submitOptions, submittingButton, switchTarget, switchTargets, switcherValues, u, validate;
20069
20280
  u = up.util;
20070
20281
  e = up.element;
20071
20282
  ATTRIBUTES_SUGGESTING_SUBMIT = ['[up-submit]', '[up-target]', '[up-layer]', '[up-transition]'];
@@ -20242,8 +20453,26 @@ The `up.form` module helps you work with non-trivial forms.
20242
20453
  });
20243
20454
 
20244
20455
  /***
20245
- Parses the `render()` options that would be used to
20246
- [`submit`](/up.submit) the given form, but does not [render](/up.render).
20456
+ Parses the [render](/up.render) options that would be used to
20457
+ [`submit`](/up.submit) the given form, but does not render.
20458
+
20459
+ \#\#\# Example
20460
+
20461
+ Given a form element:
20462
+
20463
+ ```html
20464
+ <form action="/foo" method="post" up-target=".content">
20465
+ ...
20466
+ </form>
20467
+ ```
20468
+
20469
+ We can parse the link's render options like this:
20470
+
20471
+ ```js
20472
+ let form = document.querySelector('form')
20473
+ let options = up.form.submitOptions(form)
20474
+ // => { url: '/foo', method: 'POST', target: '.content', ... }
20475
+ ```
20247
20476
 
20248
20477
  @param {Element|jQuery|string} form
20249
20478
  The form to submit.
@@ -20296,7 +20525,23 @@ The `up.form` module helps you work with non-trivial forms.
20296
20525
  /***
20297
20526
  This event is [emitted](/up.emit) when a form is [submitted](/up.submit) through Unpoly.
20298
20527
 
20299
- The event is emitted on the`<form>` element.
20528
+ The event is emitted on the `<form>` element.
20529
+
20530
+ When the form is being [validated](/input-up-validate), this event is not emitted.
20531
+ Instead an `up:form:validate` event is emitted.
20532
+
20533
+ \#\#\# Changing render options
20534
+
20535
+ Listeners may inspect and manipulate [render options](/up.render) for the coming fragment update.
20536
+
20537
+ The code below will use a custom [transition](/up-transition)
20538
+ when a form submission [fails](/server-errors):
20539
+
20540
+ ```js
20541
+ up.on('up:form:submit', function(event, form) {
20542
+ event.renderOptions.failTransition = 'shake'
20543
+ })
20544
+ ```
20300
20545
 
20301
20546
  @event up:form:submit
20302
20547
  @param {Element} event.target
@@ -20310,7 +20555,11 @@ The `up.form` module helps you work with non-trivial forms.
20310
20555
  @stable
20311
20556
  */
20312
20557
  up.on('up:click', submitButtonSelector, function(event, button) {
20313
- return button.focus();
20558
+ var form;
20559
+ form = e.closest(button, 'form');
20560
+ if (form && isSubmittable(form)) {
20561
+ return button.focus();
20562
+ }
20314
20563
  });
20315
20564
 
20316
20565
  /***
@@ -20395,10 +20644,10 @@ The `up.form` module helps you work with non-trivial forms.
20395
20644
  /***
20396
20645
  [Observes](/up.observe) a field or form and submits the form when a value changes.
20397
20646
 
20398
- Both the form and the changed field will be assigned a CSS class [`form-up-active`](/form-up-active)
20647
+ Both the form and the changed field will be assigned a CSS class [`.up-active`](/form-up-active)
20399
20648
  while the autosubmitted form is processing.
20400
20649
 
20401
- The unobtrusive variant of this is the [`up-autosubmit`](/form-up-autosubmit) attribute.
20650
+ The unobtrusive variant of this is the [`[up-autosubmit]`](/form-up-autosubmit) attribute.
20402
20651
 
20403
20652
  @function up.autosubmit
20404
20653
  @param {string|Element|jQuery} target
@@ -20452,7 +20701,9 @@ The `up.form` module helps you work with non-trivial forms.
20452
20701
 
20453
20702
  \#\#\# Example
20454
20703
 
20455
- up.validate('input[name=email]', { target: '.email-errors' })
20704
+ ```js
20705
+ up.validate('input[name=email]', { target: '.email-errors' })
20706
+ ```
20456
20707
 
20457
20708
  @function up.validate
20458
20709
  @param {string|Element|jQuery} field
@@ -20496,6 +20747,7 @@ The `up.form` module helps you work with non-trivial forms.
20496
20747
  @param event.preventDefault()
20497
20748
  Event listeners may call this method to prevent the validation request
20498
20749
  being sent to the server.
20750
+ @stable
20499
20751
  */
20500
20752
  switcherValues = function(field) {
20501
20753
  var checkedButton, form, groupName, meta, value, values;
@@ -20608,6 +20860,30 @@ The `up.form` module helps you work with non-trivial forms.
20608
20860
  return element;
20609
20861
  }
20610
20862
  };
20863
+
20864
+ /***
20865
+ Returns whether the given form will be [submitted](/up.follow) through Unpoly
20866
+ instead of making a full page load.
20867
+
20868
+ By default Unpoly will follow forms if the element has
20869
+ one of the following attributes:
20870
+
20871
+ - `[up-submit]`
20872
+ - `[up-target]`
20873
+ - `[up-layer]`
20874
+ - `[up-transition]`
20875
+
20876
+ To consider other selectors to be submittable, see `up.form.config.submitSelectors`.
20877
+
20878
+ @function up.form.isSubmittable
20879
+ @param {Element|jQuery|string} form
20880
+ The form to check.
20881
+ @stable
20882
+ */
20883
+ isSubmittable = function(form) {
20884
+ form = up.fragment.get(form);
20885
+ return e.matches(form, fullSubmitSelector()) && !isSubmitDisabled(form);
20886
+ };
20611
20887
  isSubmitDisabled = function(form) {
20612
20888
  return e.matches(form, config.noSubmitSelectors.join(','));
20613
20889
  };
@@ -20628,7 +20904,7 @@ The `up.form` module helps you work with non-trivial forms.
20628
20904
  </form>
20629
20905
  ```
20630
20906
 
20631
- \#\#\# Failed submission
20907
+ \#\#\# Handling validation errors
20632
20908
 
20633
20909
  When the server was unable to save the form due to invalid params,
20634
20910
  it will usually re-render an updated copy of the form with
@@ -20643,19 +20919,35 @@ The `up.form` module helps you work with non-trivial forms.
20643
20919
  [`:status` option to `render`](http://guides.rubyonrails.org/layouts_and_rendering.html#the-status-option)
20644
20920
  for this:
20645
20921
 
20646
- class UsersController < ApplicationController
20647
-
20648
- def create
20649
- user_params = params[:user].permit(:email, :password)
20650
- @user = User.new(user_params)
20651
- if @user.save?
20652
- sign_in @user
20653
- else
20654
- render 'form', status: :bad_request
20655
- end
20656
- end
20922
+ ```ruby
20923
+ class UsersController < ApplicationController
20657
20924
 
20925
+ def create
20926
+ user_params = params[:user].permit(:email, :password)
20927
+ @user = User.new(user_params)
20928
+ if @user.save?
20929
+ sign_in @user
20930
+ else
20931
+ render 'form', status: :bad_request
20658
20932
  end
20933
+ end
20934
+
20935
+ end
20936
+ ```
20937
+
20938
+ You may define different option for the failure case by infixing an attribute with `fail`:
20939
+
20940
+ ```html
20941
+ <form method="post" action="/action"
20942
+ up-target=".content"
20943
+ up-fail-target="form"
20944
+ up-scroll="auto"
20945
+ up-fail-scroll=".errors">
20946
+ ...
20947
+ </form>
20948
+ ```
20949
+
20950
+ See [handling server errors](/server-errors) for details.
20659
20951
 
20660
20952
  Note that you can also use
20661
20953
  [`input[up-validate]`](/input-up-validate) to perform server-side
@@ -20663,7 +20955,7 @@ The `up.form` module helps you work with non-trivial forms.
20663
20955
 
20664
20956
  \#\#\# Giving feedback while the form is processing
20665
20957
 
20666
- The `<form>` element will be assigned a CSS class [`up-active`](/form.up-active) while
20958
+ The `<form>` element will be assigned a CSS class [`.up-active`](/form.up-active) while
20667
20959
  the submission is loading.
20668
20960
 
20669
20961
  \#\#\# Short notation
@@ -21073,7 +21365,7 @@ The `up.form` module helps you work with non-trivial forms.
21073
21365
  /***
21074
21366
  Submits this field's form when this field changes its values.
21075
21367
 
21076
- Both the form and the changed field will be assigned a CSS class [`up-active`](/form-up-active)
21368
+ Both the form and the changed field will be assigned a CSS class [`.up-active`](/form-up-active)
21077
21369
  while the autosubmitted form is loading.
21078
21370
 
21079
21371
  The programmatic variant of this is the [`up.autosubmit()`](/up.autosubmit) function.
@@ -21102,7 +21394,7 @@ The `up.form` module helps you work with non-trivial forms.
21102
21394
  </div>
21103
21395
 
21104
21396
  @selector input[up-autosubmit]
21105
- @param up-delay
21397
+ @param [up-delay]
21106
21398
  The number of miliseconds to wait after a change before the form is submitted.
21107
21399
  @stable
21108
21400
  */
@@ -21110,7 +21402,7 @@ The `up.form` module helps you work with non-trivial forms.
21110
21402
  /***
21111
21403
  Submits the form when any field changes.
21112
21404
 
21113
- Both the form and the field will be assigned a CSS class [`up-active`](/form-up-active)
21405
+ Both the form and the field will be assigned a CSS class [`.up-active`](/form-up-active)
21114
21406
  while the autosubmitted form is loading.
21115
21407
 
21116
21408
  The programmatic variant of this is the [`up.autosubmit()`](/up.autosubmit) function.
@@ -21125,7 +21417,7 @@ The `up.form` module helps you work with non-trivial forms.
21125
21417
  </form>
21126
21418
 
21127
21419
  @selector form[up-autosubmit]
21128
- @param up-delay
21420
+ @param [up-delay]
21129
21421
  The number of miliseconds to wait after a change before the form is submitted.
21130
21422
  @stable
21131
21423
  */
@@ -21137,6 +21429,7 @@ The `up.form` module helps you work with non-trivial forms.
21137
21429
  config: config,
21138
21430
  submit: submit,
21139
21431
  submitOptions: submitOptions,
21432
+ isSubmittable: isSubmittable,
21140
21433
  observe: observe,
21141
21434
  validate: validate,
21142
21435
  autosubmit: autosubmit,
@@ -21162,43 +21455,53 @@ Navigation feedback
21162
21455
  ===================
21163
21456
 
21164
21457
  The `up.feedback` module adds useful CSS classes to links while they are loading,
21165
- or when they point to the current URL. By styling these classes you may
21166
- provide instant feedback to user interactions. This improves the perceived speed of your interface.
21458
+ or when they point to the current URL.
21459
+
21460
+ By styling these classes you may provide instant feedback to user interactions,
21461
+ improving the perceived speed of your interface.
21167
21462
 
21168
21463
 
21169
21464
  \#\#\# Example
21170
21465
 
21171
21466
  Let's say we have an `<nav>` element with two links, pointing to `/foo` and `/bar` respectively:
21172
21467
 
21173
- <nav>
21174
- <a href="/foo" up-follow>Foo</a>
21175
- <a href="/bar" up-follow>Bar</a>
21176
- </nav>
21468
+ ```html
21469
+ <nav>
21470
+ <a href="/foo" up-follow>Foo</a>
21471
+ <a href="/bar" up-follow>Bar</a>
21472
+ </nav>
21473
+ ```
21177
21474
 
21178
21475
  By giving the navigation bar the `[up-nav]` attribute, links pointing to the current browser address are highlighted
21179
21476
  as we navigate through the site.
21180
21477
 
21181
21478
  If the current URL is `/foo`, the first link is automatically marked with an [`.up-current`](/a.up-current) class:
21182
21479
 
21183
- <nav up-nav>
21184
- <a href="/foo" up-follow class="up-current">Foo</a>
21185
- <a href="/bar" up-follow>Bar</a>
21186
- </nav>
21480
+ ```html
21481
+ <nav up-nav>
21482
+ <a href="/foo" up-follow class="up-current">Foo</a>
21483
+ <a href="/bar" up-follow>Bar</a>
21484
+ </nav>
21485
+ ```
21187
21486
 
21188
21487
  When the user clicks on the `/bar` link, the link will receive the [`up-active`](/a.up-active) class while it is waiting
21189
21488
  for the server to respond:
21190
21489
 
21191
- <nav up-nav>
21192
- <a href="/foo" up-follow class="up-current">Foo</a>
21193
- <a href="/bar" up-follow class="up-active">Bar</a>
21194
- </div>
21490
+ ```
21491
+ <nav up-nav>
21492
+ <a href="/foo" up-follow class="up-current">Foo</a>
21493
+ <a href="/bar" up-follow class="up-active">Bar</a>
21494
+ </div>
21495
+ ```
21195
21496
 
21196
21497
  Once the response is received the URL will change to `/bar` and the `up-active` class is removed:
21197
21498
 
21198
- <nav up-nav>
21199
- <a href="/foo" up-follow>Foo</a>
21200
- <a href="/bar" up-follow class="up-current">Bar</a>
21201
- </nav>
21499
+ ```html
21500
+ <nav up-nav>
21501
+ <a href="/foo" up-follow>Foo</a>
21502
+ <a href="/bar" up-follow class="up-current">Bar</a>
21503
+ </nav>
21504
+ ```
21202
21505
 
21203
21506
  @see [up-nav]
21204
21507
  @see a.up-current
@@ -21504,7 +21807,7 @@ Once the response is received the URL will change to `/bar` and the `up-active`
21504
21807
  */
21505
21808
 
21506
21809
  /***
21507
- Links within `[up-nav]` may use the `[up-alias]` attribute to pass an [URL pattern](/url-patterns) for which they
21810
+ Links within `[up-nav]` may use the `[up-alias]` attribute to pass a [URL pattern](/url-patterns) for which they
21508
21811
  should also be highlighted as [`.up-current`](a.up-current).
21509
21812
 
21510
21813
  \#\#\# Example
@@ -21517,7 +21820,7 @@ Once the response is received the URL will change to `/bar` and the `up-active`
21517
21820
  </div>
21518
21821
  ```
21519
21822
 
21520
- To pass more than one alternative URLs, use an [URL pattern](/url-patterns).
21823
+ To pass more than one alternative URLs, use a [URL pattern](/url-patterns).
21521
21824
 
21522
21825
  @selector a[up-alias]
21523
21826
  @param up-alias