unpoly-rails 2.0.0.pre.rc7 → 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 +4 -4
- data/CHANGELOG.md +117 -49
- data/README.md +6 -5
- data/dist/unpoly-migrate.js +99 -18
- data/dist/unpoly-migrate.min.js +1 -1
- data/dist/unpoly.js +1412 -799
- data/dist/unpoly.min.js +6 -6
- data/lib/unpoly/rails/engine.rb +28 -0
- data/lib/unpoly/rails/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 60a37ba382e3664b7224d805da146e4a7364e7880dbcdb80580a0e9ef4406672
|
4
|
+
data.tar.gz: 8d899df9850761c7b07849b2ded8a241e334c9e4cbc3ac8dc5003af0629206ad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
-
|
23
|
-
-
|
24
|
-
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
-
|
29
|
-
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
- up.
|
36
|
-
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
-
|
42
|
-
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
-
|
47
|
-
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
-
|
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
|
-
|
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
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
[Unpoly](https://unpoly.com)
|
1
|
+
[Unpoly 2](https://unpoly.com)
|
2
2
|
======
|
3
3
|
|
4
4
|
Unobtrusive JavaScript framework for server-side applications
|
@@ -6,7 +6,9 @@ Unobtrusive JavaScript framework for server-side applications
|
|
6
6
|
|
7
7
|
[Unpoly](https://unpoly.com) enables fast and flexible frontends with minimal changes to your server-side code.
|
8
8
|
|
9
|
-
This repository is home to both the Unpoly JavaScript code and its (optional) bindings for Ruby on Rails (`unpoly-rails` gem).
|
9
|
+
This repository is home to both the Unpoly 2 JavaScript code and its (optional) bindings for Ruby on Rails (`unpoly-rails` gem).
|
10
|
+
|
11
|
+
If you're looking for the code of Unpoly 0.x or 1.0, use the [`1.x-stable`](https://github.com/unpoly/unpoly/tree/1.x-stable) branch.
|
10
12
|
|
11
13
|
|
12
14
|
Getting started
|
@@ -33,6 +35,7 @@ Install dependencies for tests:
|
|
33
35
|
|
34
36
|
- Install Ruby 2.3.8
|
35
37
|
- Install Bundler by running `gem install bundler`
|
38
|
+
- Install Node.js (required for building the library)
|
36
39
|
- `cd` into `spec_app`
|
37
40
|
- Install dependencies by running `bundle install`
|
38
41
|
|
@@ -50,11 +53,9 @@ To run RSpec tests for the `unpoly-rails` gem:
|
|
50
53
|
|
51
54
|
### Making a new release
|
52
55
|
|
53
|
-
We are currently feeding
|
56
|
+
We are currently feeding two release channels:
|
54
57
|
|
55
|
-
- Manual download from GitHub
|
56
58
|
- npm
|
57
|
-
- Bower (which is based on Git and version tags)
|
58
59
|
- Rubygems (as the `unpoly-rails` gem)
|
59
60
|
|
60
61
|
We always release to all channel simultaneously.
|
data/dist/unpoly-migrate.js
CHANGED
@@ -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.
|
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,16 +922,21 @@ 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.
|
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"]');
|
856
932
|
});
|
857
933
|
|
858
934
|
}).call(this);
|
935
|
+
|
936
|
+
/***
|
937
|
+
@module up.layer
|
938
|
+
*/
|
939
|
+
|
859
940
|
(function() {
|
860
941
|
var e, u;
|
861
942
|
|
@@ -1060,15 +1141,6 @@ This feature is now deprecated.
|
|
1060
1141
|
|
1061
1142
|
up.migrate.renamedProperty(up.network.config, 'slowDelay', 'badResponseTime');
|
1062
1143
|
|
1063
|
-
up.migrate.handleNetworkPreloadArgs = function() {
|
1064
|
-
var args, ref;
|
1065
|
-
args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
|
1066
|
-
if (u.isElementish(args[0])) {
|
1067
|
-
up.migrate.warn('up.proxy.preload(link) has been renamed to up.link.preload(link)');
|
1068
|
-
return (ref = up.link).preload.apply(ref, args);
|
1069
|
-
}
|
1070
|
-
};
|
1071
|
-
|
1072
1144
|
up.migrate.handleRequestOptions = function(options) {
|
1073
1145
|
return up.migrate.fixKey(options, 'data', 'params');
|
1074
1146
|
};
|
@@ -1081,11 +1153,13 @@ This feature is now deprecated.
|
|
1081
1153
|
|
1082
1154
|
\#\#\# Example
|
1083
1155
|
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
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
|
+
```
|
1089
1163
|
|
1090
1164
|
@function up.ajax
|
1091
1165
|
@param {string} [url]
|
@@ -1124,6 +1198,13 @@ This feature is now deprecated.
|
|
1124
1198
|
return up.cache.clear();
|
1125
1199
|
};
|
1126
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
|
+
|
1127
1208
|
|
1128
1209
|
/***
|
1129
1210
|
@class up.Request
|
data/dist/unpoly-migrate.min.js
CHANGED
@@ -1 +1 @@
|
|
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(){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 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
|
8
|
+
version: "2.0.0"
|
9
9
|
};
|
10
10
|
|
11
11
|
}).call(this);
|
@@ -110,20 +110,21 @@ to not include another library in your asset bundle.
|
|
110
110
|
};
|
111
111
|
|
112
112
|
/***
|
113
|
-
Normalizes
|
114
|
-
that can be checked for equality with other normalized URLs.
|
115
|
-
|
116
|
-
By default hashes are ignored, search queries are included.
|
113
|
+
Normalizes the given URL or path.
|
117
114
|
|
118
115
|
@function up.util.normalizeURL
|
119
116
|
@param {boolean} [options.host='cross-domain']
|
120
117
|
Whether to include protocol, hostname and port in the normalized URL.
|
118
|
+
|
119
|
+
By default the host is only included if it differ's from the page's hostname.
|
121
120
|
@param {boolean} [options.hash=false]
|
122
121
|
Whether to include an `#hash` anchor in the normalized URL
|
123
122
|
@param {boolean} [options.search=true]
|
124
123
|
Whether to include a `?query` string in the normalized URL
|
125
124
|
@param {boolean} [options.stripTrailingSlash=false]
|
126
125
|
Whether to strip a trailing slash from the pathname
|
126
|
+
@return {string}
|
127
|
+
The normalized URL.
|
127
128
|
@internal
|
128
129
|
*/
|
129
130
|
normalizeURL = function(urlOrAnchor, options) {
|
@@ -178,6 +179,15 @@ to not include another library in your asset bundle.
|
|
178
179
|
If the given URL is not fully qualified, it is assumed to be relative
|
179
180
|
to the current page.
|
180
181
|
|
182
|
+
\#\#\# Example
|
183
|
+
|
184
|
+
```js
|
185
|
+
let parsed = up.util.parseURL('/path?foo=value')
|
186
|
+
parsed.pathname // => '/path'
|
187
|
+
parsed.search // => '/?foo=value'
|
188
|
+
parsed.hash // => ''
|
189
|
+
```
|
190
|
+
|
181
191
|
@function up.util.parseURL
|
182
192
|
@return {Object}
|
183
193
|
The parsed URL as an object with
|
@@ -732,7 +742,7 @@ to not include another library in your asset bundle.
|
|
732
742
|
@function up.util.isList
|
733
743
|
@param value
|
734
744
|
@return {boolean}
|
735
|
-
@
|
745
|
+
@stable
|
736
746
|
*/
|
737
747
|
isList = function(value) {
|
738
748
|
return isArray(value) || isNodeList(value) || isArguments(value) || isJQuery(value) || isHTMLCollection(value);
|
@@ -775,9 +785,20 @@ to not include another library in your asset bundle.
|
|
775
785
|
};
|
776
786
|
|
777
787
|
/***
|
788
|
+
Returns the given value if it is [array-like](/up.util.isList), otherwise
|
789
|
+
returns an array with the given value as its only element.
|
790
|
+
|
791
|
+
\#\#\# Example
|
792
|
+
|
793
|
+
```js
|
794
|
+
up.util.wrapList([1, 2, 3]) // => [1, 2, 3]
|
795
|
+
up.util.wrapList('foo') // => ['foo']
|
796
|
+
```
|
797
|
+
|
778
798
|
@function up.util.wrapList
|
799
|
+
@param {any} value
|
779
800
|
@return {Array|NodeList|jQuery}
|
780
|
-
@
|
801
|
+
@experimental
|
781
802
|
*/
|
782
803
|
wrapList = function(value) {
|
783
804
|
if (isList(value)) {
|
@@ -1238,6 +1259,7 @@ to not include another library in your asset bundle.
|
|
1238
1259
|
@function up.util.last
|
1239
1260
|
@param {Array<T>} array
|
1240
1261
|
@return {T}
|
1262
|
+
@stable
|
1241
1263
|
*/
|
1242
1264
|
last = function(array) {
|
1243
1265
|
return array[array.length - 1];
|
@@ -1281,6 +1303,7 @@ to not include another library in your asset bundle.
|
|
1281
1303
|
@function up.util.pick
|
1282
1304
|
@param {Object} object
|
1283
1305
|
@param {Array} keys
|
1306
|
+
@return {Object}
|
1284
1307
|
@stable
|
1285
1308
|
*/
|
1286
1309
|
pick = function(object, keys) {
|
@@ -1294,6 +1317,20 @@ to not include another library in your asset bundle.
|
|
1294
1317
|
}
|
1295
1318
|
return filtered;
|
1296
1319
|
};
|
1320
|
+
|
1321
|
+
/***
|
1322
|
+
Returns a copy of the given object that only contains
|
1323
|
+
properties that pass the given tester function.
|
1324
|
+
|
1325
|
+
@function up.util.pickBy
|
1326
|
+
@param {Object} object
|
1327
|
+
@param {Function<string, string, object>} tester
|
1328
|
+
A function that will be called with each property.
|
1329
|
+
|
1330
|
+
The arguments are the property value, key and the entire object.
|
1331
|
+
@return {Object}
|
1332
|
+
@experimental
|
1333
|
+
*/
|
1297
1334
|
pickBy = function(object, tester) {
|
1298
1335
|
var filtered, key, value;
|
1299
1336
|
tester = iteratee(tester);
|
@@ -1359,8 +1396,20 @@ to not include another library in your asset bundle.
|
|
1359
1396
|
If the given `value` is a function, calls the function with the given `args`.
|
1360
1397
|
Otherwise it just returns `value`.
|
1361
1398
|
|
1399
|
+
\#\#\# Example
|
1400
|
+
|
1401
|
+
```js
|
1402
|
+
up.util.evalOption(5) // => 5
|
1403
|
+
|
1404
|
+
let fn = () => 1 + 2
|
1405
|
+
up.util.evalOption(fn) // => 3
|
1406
|
+
```
|
1407
|
+
|
1362
1408
|
@function up.util.evalOption
|
1363
|
-
@
|
1409
|
+
@param {any} value
|
1410
|
+
@param {Array} ...args
|
1411
|
+
@return {any}
|
1412
|
+
@experimental
|
1364
1413
|
*/
|
1365
1414
|
evalOption = function() {
|
1366
1415
|
var args, value;
|
@@ -1384,7 +1433,7 @@ to not include another library in your asset bundle.
|
|
1384
1433
|
|
1385
1434
|
@function up.util.escapeHTML
|
1386
1435
|
@param {string} string
|
1387
|
-
The text that should be escaped
|
1436
|
+
The text that should be escaped.
|
1388
1437
|
@stable
|
1389
1438
|
*/
|
1390
1439
|
escapeHTML = function(string) {
|
@@ -1400,6 +1449,17 @@ to not include another library in your asset bundle.
|
|
1400
1449
|
escapeRegExp = function(string) {
|
1401
1450
|
return string.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
|
1402
1451
|
};
|
1452
|
+
|
1453
|
+
/***
|
1454
|
+
Deletes the property with the given key from the given object
|
1455
|
+
and returns its value.
|
1456
|
+
|
1457
|
+
@function up.util.pluckKey
|
1458
|
+
@param {Object} object
|
1459
|
+
@param {string} key
|
1460
|
+
@return {any}
|
1461
|
+
@experimental
|
1462
|
+
*/
|
1403
1463
|
pluckKey = function(object, key) {
|
1404
1464
|
var value;
|
1405
1465
|
value = object[key];
|
@@ -1431,7 +1491,6 @@ to not include another library in your asset bundle.
|
|
1431
1491
|
@param {Array<Function()>} functions
|
1432
1492
|
@return {Function()}
|
1433
1493
|
A function that will call all `functions` if called.
|
1434
|
-
|
1435
1494
|
@internal
|
1436
1495
|
*/
|
1437
1496
|
sequence = function(functions) {
|
@@ -1447,7 +1506,13 @@ to not include another library in your asset bundle.
|
|
1447
1506
|
};
|
1448
1507
|
|
1449
1508
|
/***
|
1450
|
-
Flattens the given `array` a single level
|
1509
|
+
Flattens the given `array` a single depth level.
|
1510
|
+
|
1511
|
+
\#\#\# Example
|
1512
|
+
|
1513
|
+
```js
|
1514
|
+
let nested = [1, [2, 3], [4]]
|
1515
|
+
up.util.flatten(nested) // => [1, 2, 3, 4]
|
1451
1516
|
|
1452
1517
|
@function up.util.flatten
|
1453
1518
|
@param {Array} array
|
@@ -1472,7 +1537,7 @@ to not include another library in your asset bundle.
|
|
1472
1537
|
|
1473
1538
|
/***
|
1474
1539
|
Maps each element using a mapping function,
|
1475
|
-
then flattens the result into a new array.
|
1540
|
+
then [flattens](/up.util.flatten) the result into a new array.
|
1476
1541
|
|
1477
1542
|
@function up.util.flatMap
|
1478
1543
|
@param {Array} array
|
@@ -1508,24 +1573,24 @@ to not include another library in your asset bundle.
|
|
1508
1573
|
};
|
1509
1574
|
|
1510
1575
|
/***
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1519
|
-
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
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
|
1529
1594
|
*/
|
1530
1595
|
muteRejection = function(promise) {
|
1531
1596
|
return promise != null ? promise["catch"](noop) : void 0;
|
@@ -2081,10 +2146,12 @@ Chrome, Firefox, Edge, Safari
|
|
2081
2146
|
: Full support
|
2082
2147
|
|
2083
2148
|
Internet Explorer 11
|
2084
|
-
: 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/).
|
2085
2151
|
|
2086
2152
|
Internet Explorer 10 or lower
|
2087
|
-
: Unpoly
|
2153
|
+
: Unpoly will not boot or [run compilers](/up.compiler),
|
2154
|
+
leaving you with a classic server-side application.
|
2088
2155
|
|
2089
2156
|
@module up.browser
|
2090
2157
|
*/
|
@@ -2097,7 +2164,9 @@ Internet Explorer 10 or lower
|
|
2097
2164
|
u = up.util;
|
2098
2165
|
|
2099
2166
|
/***
|
2100
|
-
Makes a full
|
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()`.
|
2101
2170
|
|
2102
2171
|
@function up.browser.loadPage
|
2103
2172
|
@param {string} options.url
|
@@ -2107,7 +2176,7 @@ Internet Explorer 10 or lower
|
|
2107
2176
|
|
2108
2177
|
Methods other than GET or POST will be [wrapped](/up.protocol.config#config.methodParam) in a POST request.
|
2109
2178
|
@param {Object|Array|FormData|string} [options.params]
|
2110
|
-
@
|
2179
|
+
@experimental
|
2111
2180
|
*/
|
2112
2181
|
loadPage = function(requestsAttrs) {
|
2113
2182
|
return new up.Request(requestsAttrs).loadPage();
|
@@ -2239,7 +2308,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
2239
2308
|
var slice = [].slice;
|
2240
2309
|
|
2241
2310
|
up.element = (function() {
|
2242
|
-
var CSS_LENGTH_PROPS, MATCH_FN_NAME, SINGLETON_PATTERN, SINGLETON_TAG_NAMES, affix, all, ancestor, around, attributeSelector, booleanAttr, booleanOrStringAttr, callbackAttr, closest, closestAttr, computedStyle, computedStyleNumber, concludeCSSTransition, createDocumentFromHTML, createFromHTML, createFromSelector, cssLength, elementTagName, extractFromStyleObject, first, fixedToAbsolute, getList, getOne, getRoot, hasCSSTransition, hide, idSelector, inlineStyle, insertBefore, isDetached, isInSubtree, isSingleton, isSingletonSelector, isVisible, jsonAttr, matches, metaContent, normalizeStyleValueForWrite, numberAttr, paint, remove, replace, setAttrs, setInlineStyle, setMissingAttr, setMissingAttrs, setTemporaryAttrs, setTemporaryStyle, show, stringAttr, subtree, toSelector, toggle, toggleAttr, toggleClass, trueAttributeSelector, u, unwrap, upAttrs, valueToList, wrapChildren;
|
2311
|
+
var CSS_LENGTH_PROPS, MATCH_FN_NAME, SINGLETON_PATTERN, SINGLETON_TAG_NAMES, affix, all, ancestor, around, attributeSelector, booleanAttr, booleanOrStringAttr, callbackAttr, classSelector, closest, closestAttr, computedStyle, computedStyleNumber, concludeCSSTransition, createDocumentFromHTML, createFromHTML, createFromSelector, cssLength, elementTagName, extractFromStyleObject, first, fixedToAbsolute, getList, getOne, getRoot, hasCSSTransition, hide, idSelector, inlineStyle, insertBefore, isDetached, isInSubtree, isSingleton, isSingletonSelector, isVisible, jsonAttr, matches, metaContent, normalizeStyleValueForWrite, numberAttr, paint, remove, replace, setAttrs, setInlineStyle, setMissingAttr, setMissingAttrs, setTemporaryAttrs, setTemporaryStyle, show, stringAttr, subtree, toSelector, toggle, toggleAttr, toggleClass, trueAttributeSelector, u, unwrap, upAttrs, valueToList, wrapChildren;
|
2243
2312
|
u = up.util;
|
2244
2313
|
MATCH_FN_NAME = up.browser.isIE11() ? 'msMatchesSelector' : 'matches';
|
2245
2314
|
|
@@ -2521,6 +2590,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
2521
2590
|
[this WHATWG mailing list post](http://lists.w3.org/Archives/Public/public-whatwg-archive/2014Apr/0094.html).
|
2522
2591
|
|
2523
2592
|
@function up.element.show
|
2593
|
+
@param {Element} element
|
2524
2594
|
@stable
|
2525
2595
|
*/
|
2526
2596
|
show = function(element) {
|
@@ -2559,8 +2629,10 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
2559
2629
|
@param {Element} element
|
2560
2630
|
The element for which to add or remove the class.
|
2561
2631
|
@param {string} className
|
2562
|
-
|
2563
|
-
@param {
|
2632
|
+
The class which should be added or removed.
|
2633
|
+
@param {Boolean} [newPresent]
|
2634
|
+
Pass `true` to add the class to the element or `false` to remove it.
|
2635
|
+
|
2564
2636
|
If omitted, the class will be added if missing and removed if present.
|
2565
2637
|
@stable
|
2566
2638
|
*/
|
@@ -2909,6 +2981,15 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
2909
2981
|
}
|
2910
2982
|
};
|
2911
2983
|
|
2984
|
+
/***
|
2985
|
+
@function up.element.classSelector
|
2986
|
+
@internal
|
2987
|
+
*/
|
2988
|
+
classSelector = function(klass) {
|
2989
|
+
klass = klass.replace(/:/g, '\\:');
|
2990
|
+
return "." + klass;
|
2991
|
+
};
|
2992
|
+
|
2912
2993
|
/***
|
2913
2994
|
Always creates a full document with a <html> root, even if the given `html`
|
2914
2995
|
is only a fragment.
|
@@ -3442,6 +3523,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
3442
3523
|
affix: affix,
|
3443
3524
|
toSelector: toSelector,
|
3444
3525
|
idSelector: idSelector,
|
3526
|
+
classSelector: classSelector,
|
3445
3527
|
isSingleton: isSingleton,
|
3446
3528
|
isSingletonSelector: isSingletonSelector,
|
3447
3529
|
attributeSelector: attributeSelector,
|
@@ -4986,7 +5068,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
4986
5068
|
};
|
4987
5069
|
|
4988
5070
|
CompilerPass.prototype.runCompiler = function(compiler) {
|
4989
|
-
var
|
5071
|
+
var base, i, len, match, matches;
|
4990
5072
|
matches = this.select(compiler.selector);
|
4991
5073
|
if (!matches.length) {
|
4992
5074
|
return;
|
@@ -5002,15 +5084,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
5002
5084
|
this.compileOneElement(compiler, match);
|
5003
5085
|
}
|
5004
5086
|
}
|
5005
|
-
|
5006
|
-
value = u.isString(keepValue) ? keepValue : '';
|
5007
|
-
results = [];
|
5008
|
-
for (j = 0, len1 = matches.length; j < len1; j++) {
|
5009
|
-
match = matches[j];
|
5010
|
-
results.push(match.setAttribute('up-keep', value));
|
5011
|
-
}
|
5012
|
-
return results;
|
5013
|
-
}
|
5087
|
+
return typeof (base = up.migrate).postCompile === "function" ? base.postCompile(matches, compiler) : void 0;
|
5014
5088
|
};
|
5015
5089
|
|
5016
5090
|
CompilerPass.prototype.compileOneElement = function(compiler, element) {
|
@@ -6231,8 +6305,12 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6231
6305
|
/***
|
6232
6306
|
Each layer has an `up.Layer` instance.
|
6233
6307
|
|
6234
|
-
Most functions in the `up.layer`
|
6235
|
-
|
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.
|
6236
6314
|
|
6237
6315
|
@class up.Layer
|
6238
6316
|
*/
|
@@ -6259,66 +6337,46 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6259
6337
|
|
6260
6338
|
|
6261
6339
|
/***
|
6262
|
-
|
6263
|
-
|
6264
|
-
Available layer modes are:
|
6340
|
+
Whether fragment updates within this layer can affect browser history and window title.
|
6265
6341
|
|
6266
|
-
|
6267
|
-
- `'modal'`
|
6268
|
-
- `'popup'`
|
6269
|
-
- `'drawer'`
|
6270
|
-
- `'cover'`
|
6342
|
+
If a layer does not have visible history, its desendant layers cannot have history either.
|
6271
6343
|
|
6272
|
-
@property up.Layer#
|
6273
|
-
@param {
|
6344
|
+
@property up.Layer#historyVisible
|
6345
|
+
@param {boolean} historyVisible
|
6274
6346
|
@stable
|
6275
6347
|
*/
|
6276
6348
|
|
6277
6349
|
|
6278
6350
|
/***
|
6279
|
-
|
6351
|
+
This layer's mode which governs its appearance and behavior.
|
6280
6352
|
|
6281
|
-
@
|
6282
|
-
|
6353
|
+
@see layer-terminology
|
6354
|
+
|
6355
|
+
@property up.Layer#mode
|
6356
|
+
@param {string} mode
|
6357
|
+
@stable
|
6283
6358
|
*/
|
6284
6359
|
|
6285
6360
|
|
6286
6361
|
/***
|
6287
|
-
This layer's context
|
6288
|
-
|
6289
|
-
Think of *context* as [session storage](/https://makandracards.com/makandra/32865), but specific to a [layer](/up.layer)
|
6290
|
-
rather than specific to an entire browser tab.
|
6291
|
-
|
6292
|
-
You may access the context object's properties like a regular JavaScript object.
|
6362
|
+
This layer's [context](/context).
|
6293
6363
|
|
6294
6364
|
\#\#\# Example
|
6295
6365
|
|
6366
|
+
You may access the context properties like a regular JavaScript object.
|
6367
|
+
|
6296
6368
|
```js
|
6297
6369
|
let layer = up.layer.current
|
6298
6370
|
layer.context.message = 'Please select a contact'
|
6299
6371
|
console.log(layer.context) // logs "{ message: 'Please select a contact' }"
|
6300
6372
|
```
|
6301
6373
|
|
6302
|
-
\#\#\# Accessing the context from the server
|
6303
|
-
|
6304
|
-
The context is is sent as an `X-Up-Context` header along with every
|
6305
|
-
[request](/up.request) to the server. The server may also update the updating
|
6306
|
-
layer's context by including an `X-Up-Context` header in its response.
|
6307
|
-
|
6308
6374
|
@property up.Layer#context
|
6309
6375
|
@param {Object} context
|
6310
|
-
|
6311
|
-
*/
|
6312
|
-
|
6313
|
-
|
6314
|
-
/***
|
6315
|
-
Whether fragment updates within this layer will affect [browser history](/up.history).
|
6316
|
-
|
6317
|
-
If a layer does not have visible history, its desendant layers cannot have history either.
|
6376
|
+
The context object.
|
6318
6377
|
|
6319
|
-
|
6320
|
-
@
|
6321
|
-
@stable
|
6378
|
+
If no context has been set an empty object is returned.
|
6379
|
+
@experimental
|
6322
6380
|
*/
|
6323
6381
|
|
6324
6382
|
Layer.prototype.keys = function() {
|
@@ -6377,7 +6435,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6377
6435
|
[Closes this overlay](/closing-overlays) with an accepting intent,
|
6378
6436
|
e.g. when a change was confirmed or when a value was selected.
|
6379
6437
|
|
6380
|
-
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.
|
6381
6439
|
|
6382
6440
|
@function up.Layer#accept
|
6383
6441
|
@param {any} [value]
|
@@ -6415,7 +6473,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6415
6473
|
|
6416
6474
|
|
6417
6475
|
/***
|
6418
|
-
[Closes this overlay](/closing-overlays) without an accepting intent,
|
6476
|
+
[Closes this overlay](/closing-overlays) *without* an accepting intent,
|
6419
6477
|
e.g. when a "Cancel" button was clicked.
|
6420
6478
|
|
6421
6479
|
To close an overlay with an accepting intent, use `up.Layer#accept()` instead.
|
@@ -6490,7 +6548,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6490
6548
|
/***
|
6491
6549
|
Returns whether this layer is the [root layer](/up.layer.root).
|
6492
6550
|
|
6493
|
-
@function up.Layer#
|
6551
|
+
@function up.Layer#isRoot
|
6494
6552
|
@return {boolean}
|
6495
6553
|
@stable
|
6496
6554
|
*/
|
@@ -6571,7 +6629,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6571
6629
|
|
6572
6630
|
Returns `undefined` if this layer has not opened a child layer.
|
6573
6631
|
|
6574
|
-
A layer can have at most one child layer. Opening an overlay on a layer with an
|
6632
|
+
A layer can have at most one child layer. Opening an overlay on a layer with an existing child will
|
6575
6633
|
first dismiss the existing child before replacing it with the new child.
|
6576
6634
|
|
6577
6635
|
@property up.Layer#child
|
@@ -6587,6 +6645,10 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6587
6645
|
/***
|
6588
6646
|
Returns an array of this layer's ancestor layers.
|
6589
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
|
+
|
6590
6652
|
@property up.Layer#ancestors
|
6591
6653
|
@return {Array<up.Layer>} ancestors
|
6592
6654
|
@stable
|
@@ -6602,6 +6664,10 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6602
6664
|
|
6603
6665
|
Descendant layers are all layers that visually overlay this layer.
|
6604
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
|
+
|
6605
6671
|
@property up.Layer#descendants
|
6606
6672
|
@return {Array<up.Layer>} descendants
|
6607
6673
|
@stable
|
@@ -6661,7 +6727,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6661
6727
|
|
6662
6728
|
|
6663
6729
|
/***
|
6664
|
-
Listens to a
|
6730
|
+
Listens to a [DOM event](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Events) that originated
|
6665
6731
|
on an element [contained](/up.Layer.prototype.contains) by this layer.
|
6666
6732
|
|
6667
6733
|
This will ignore events emitted on elements in [descendant](/up.Layer.prototype.descendants) overlays,
|
@@ -6698,27 +6764,43 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6698
6764
|
up.follow(overlayLink) // listener is not called
|
6699
6765
|
|
6700
6766
|
@function up.Layer#on
|
6767
|
+
|
6701
6768
|
@param {string} types
|
6702
6769
|
A space-separated list of event types to bind to.
|
6703
|
-
|
6770
|
+
|
6771
|
+
@param {string|Function(): string} [selector]
|
6704
6772
|
The selector of an element on which the event must be triggered.
|
6705
6773
|
|
6706
6774
|
Omit the selector to listen to all events of the given type, regardless
|
6707
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
|
+
|
6708
6781
|
@param {boolean} [options.passive=false]
|
6709
6782
|
Whether to register a [passive event listener](https://developers.google.com/web/updates/2016/06/passive-event-listeners).
|
6710
6783
|
|
6711
6784
|
A passive event listener may not call `event.preventDefault()`.
|
6712
6785
|
This in particular may improve the frame rate when registering
|
6713
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
|
+
|
6714
6794
|
@param {Function(event, [element], [data])} listener
|
6715
6795
|
The listener function that should be called.
|
6716
6796
|
|
6717
6797
|
The function takes the affected element as the second argument.
|
6718
6798
|
If the element has an [`up-data`](/up-data) attribute, its value is parsed as JSON
|
6719
6799
|
and passed as a third argument.
|
6800
|
+
|
6720
6801
|
@return {Function()}
|
6721
6802
|
A function that unbinds the event listeners when called.
|
6803
|
+
|
6722
6804
|
@stable
|
6723
6805
|
*/
|
6724
6806
|
|
@@ -6733,13 +6815,12 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6733
6815
|
Unbinds an event listener previously bound with `up.Layer#on()`.
|
6734
6816
|
|
6735
6817
|
@function up.Layer#off
|
6736
|
-
@param {Element|jQuery} [element=document]
|
6737
6818
|
@param {string} events
|
6738
|
-
@param {string} [selector]
|
6819
|
+
@param {string|Function(): string} [selector]
|
6739
6820
|
@param {Function(event, [element], [data])} listener
|
6740
6821
|
The listener function to unbind.
|
6741
6822
|
|
6742
|
-
Note that you must pass a reference to the
|
6823
|
+
Note that you must pass a reference to the same function reference
|
6743
6824
|
that was passed to `up.Layer#on()` earlier.
|
6744
6825
|
@stable
|
6745
6826
|
*/
|
@@ -6911,9 +6992,9 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6911
6992
|
/***
|
6912
6993
|
This layer's location URL.
|
6913
6994
|
|
6914
|
-
If the
|
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
|
6915
6997
|
the browser's address bar will show the location of an ancestor layer.
|
6916
|
-
This property will return the URL the layer would use if it had visible history.
|
6917
6998
|
|
6918
6999
|
When this layer opens a child layer with visible history, the browser URL will change to the child
|
6919
7000
|
layer's location. When the child layer is closed, this layer's location will be restored.
|
@@ -7236,7 +7317,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
7236
7317
|
If the destruction is animated, the callback will run after the animation has finished.
|
7237
7318
|
@return {Promise}
|
7238
7319
|
A resolved promise.
|
7239
|
-
@
|
7320
|
+
@internal
|
7240
7321
|
*/
|
7241
7322
|
|
7242
7323
|
Overlay.prototype.destroyElements = function(options) {
|
@@ -7375,6 +7456,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
7375
7456
|
/***
|
7376
7457
|
@function up.Layer.OverlayWithViewport#openNow
|
7377
7458
|
@param {Element} options.content
|
7459
|
+
@internal
|
7378
7460
|
*/
|
7379
7461
|
|
7380
7462
|
OverlayWithViewport.prototype.createElements = function(content) {
|
@@ -8888,6 +8970,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
8888
8970
|
@param {string} name
|
8889
8971
|
@return {any}
|
8890
8972
|
The value of the param with the given name.
|
8973
|
+
@internal
|
8891
8974
|
*/
|
8892
8975
|
|
8893
8976
|
Params.prototype.getFirst = function(name) {
|
@@ -8906,6 +8989,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
8906
8989
|
@param {string} name
|
8907
8990
|
@return {Array}
|
8908
8991
|
An array of all values with the given name.
|
8992
|
+
@internal
|
8909
8993
|
*/
|
8910
8994
|
|
8911
8995
|
Params.prototype.getAll = function(name) {
|
@@ -9253,7 +9337,15 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9253
9337
|
|
9254
9338
|
|
9255
9339
|
/***
|
9256
|
-
Instances of `up.RenderResult` describe the effects of [rendering](/up.
|
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
|
+
```
|
9257
9349
|
|
9258
9350
|
@class up.RenderResult
|
9259
9351
|
*/
|
@@ -9304,17 +9396,18 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9304
9396
|
|
9305
9397
|
|
9306
9398
|
/***
|
9307
|
-
|
9308
|
-
such as the requested URL, form parameters and HTTP method.
|
9399
|
+
A normalized description of an [HTTP request](`up.request()`).
|
9309
9400
|
|
9310
9401
|
You can queue a request using the `up.request()` method:
|
9311
9402
|
|
9312
|
-
|
9313
|
-
|
9403
|
+
```js
|
9404
|
+
let request = up.request('/foo')
|
9405
|
+
console.log(request.url)
|
9314
9406
|
|
9315
|
-
|
9316
|
-
|
9317
|
-
|
9407
|
+
// A request object is also a promise for its response
|
9408
|
+
let response = await request
|
9409
|
+
console.log(response.text)
|
9410
|
+
```
|
9318
9411
|
|
9319
9412
|
@class up.Request
|
9320
9413
|
*/
|
@@ -9341,6 +9434,23 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9341
9434
|
*/
|
9342
9435
|
|
9343
9436
|
|
9437
|
+
/***
|
9438
|
+
The [hash component](https://en.wikipedia.org/wiki/URI_fragment) of this request's URL.
|
9439
|
+
|
9440
|
+
The `{ hash }` property is automatically extracted from the given URL:
|
9441
|
+
|
9442
|
+
```js
|
9443
|
+
let request = up.request({ url: '/path#section' })
|
9444
|
+
request.url // => '/path'
|
9445
|
+
request.hash // => '#section'
|
9446
|
+
```
|
9447
|
+
|
9448
|
+
@property up.Request#hash
|
9449
|
+
@param {string} hash
|
9450
|
+
@stable
|
9451
|
+
*/
|
9452
|
+
|
9453
|
+
|
9344
9454
|
/***
|
9345
9455
|
[Parameters](/up.Params) that should be sent as the request's payload.
|
9346
9456
|
|
@@ -9351,7 +9461,9 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9351
9461
|
|
9352
9462
|
|
9353
9463
|
/***
|
9354
|
-
The CSS selector
|
9464
|
+
The CSS selector targeted by this request.
|
9465
|
+
|
9466
|
+
The selector will be sent as an `X-Up-Target` header.
|
9355
9467
|
|
9356
9468
|
@property up.Request#target
|
9357
9469
|
@param {string} target
|
@@ -9360,7 +9472,10 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9360
9472
|
|
9361
9473
|
|
9362
9474
|
/***
|
9363
|
-
The CSS selector
|
9475
|
+
The CSS selector targeted by this request in case the server responds
|
9476
|
+
with an [error code](/server-errors).
|
9477
|
+
|
9478
|
+
The selector will be sent as an `X-Up-Fail-Target` header.
|
9364
9479
|
|
9365
9480
|
@property up.Request#failTarget
|
9366
9481
|
@param {string} failTarget
|
@@ -9371,7 +9486,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9371
9486
|
/***
|
9372
9487
|
An object of additional HTTP headers.
|
9373
9488
|
|
9374
|
-
|
9489
|
+
Unpoly will by default send a number of custom request headers.
|
9375
9490
|
See `up.protocol` and `up.network.config.metaKeys` for details.
|
9376
9491
|
|
9377
9492
|
@property up.Request#headers
|
@@ -9407,25 +9522,71 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9407
9522
|
|
9408
9523
|
|
9409
9524
|
/***
|
9410
|
-
|
9525
|
+
The [context](/contact) of the layer targeted by this request.
|
9526
|
+
|
9527
|
+
The context object will be sent as an `X-Up-Context` header.
|
9411
9528
|
|
9412
9529
|
@property up.Request#context
|
9413
9530
|
@param {Object} context
|
9414
|
-
@
|
9531
|
+
@experimental
|
9415
9532
|
*/
|
9416
9533
|
|
9417
9534
|
|
9418
9535
|
/***
|
9419
|
-
|
9536
|
+
The [context](/contact) of the layer targeted by this request in case the server responds with an [error code](/server-errors).
|
9537
|
+
|
9538
|
+
The context object will be sent as an `X-Up-Fail-Context` header.
|
9420
9539
|
|
9421
9540
|
@property up.Request#failContext
|
9422
9541
|
@param {Object} failContext
|
9423
|
-
@
|
9542
|
+
@experimental
|
9543
|
+
*/
|
9544
|
+
|
9545
|
+
|
9546
|
+
/***
|
9547
|
+
The [layer](/up.layer) targeted by this request.
|
9548
|
+
|
9549
|
+
Setting the `{ layer }` property will automatically derive `{ context }` and `{ mode }` properties.
|
9550
|
+
|
9551
|
+
To prevent memory leaks, this property is removed shortly after the response is received.
|
9552
|
+
|
9553
|
+
@property up.Request#layer
|
9554
|
+
@param {up.Layer} layer
|
9555
|
+
@experimental
|
9556
|
+
*/
|
9557
|
+
|
9558
|
+
|
9559
|
+
/***
|
9560
|
+
The [layer](/up.layer) targeted by this request in case the server responds with an [error code](/server-errors).
|
9561
|
+
|
9562
|
+
Setting the `{ failLayer }` property will automatically derive `{ failContext }` and `{ failMode }` properties.
|
9563
|
+
|
9564
|
+
To prevent memory leaks, this property is removed shortly after the response is received.
|
9565
|
+
|
9566
|
+
@property up.Request#failLayer
|
9567
|
+
@param {up.Layer} layer
|
9568
|
+
@experimental
|
9569
|
+
*/
|
9570
|
+
|
9571
|
+
|
9572
|
+
/***
|
9573
|
+
The element that triggered the request.
|
9574
|
+
|
9575
|
+
For example, when this request was triggered by a click on a link, the lonk
|
9576
|
+
element is set as the `{ origin }`.
|
9577
|
+
|
9578
|
+
To prevent memory leaks, this property is removed shortly after the response is received.
|
9579
|
+
|
9580
|
+
@property up.Request#origin
|
9581
|
+
@param {Element} origin
|
9582
|
+
@experimental
|
9424
9583
|
*/
|
9425
9584
|
|
9426
9585
|
|
9427
9586
|
/***
|
9428
|
-
|
9587
|
+
The [mode](/up.Layer.prototype.mode) of the layer targeted by this request.
|
9588
|
+
|
9589
|
+
The value will be sent as an `X-Up-Mode` header.
|
9429
9590
|
|
9430
9591
|
@property up.Request#mode
|
9431
9592
|
@param {string} mode
|
@@ -9434,7 +9595,9 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9434
9595
|
|
9435
9596
|
|
9436
9597
|
/***
|
9437
|
-
|
9598
|
+
The [mode](/up.Layer.prototype.mode) of the layer targeted by this request in case the server responds with an [error code](/server-errors).
|
9599
|
+
|
9600
|
+
The value will be sent as an `X-Up-Fail-Mode` header.
|
9438
9601
|
|
9439
9602
|
@property up.Request#failMode
|
9440
9603
|
@param {string} failMode
|
@@ -9443,7 +9606,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9443
9606
|
|
9444
9607
|
|
9445
9608
|
/***
|
9446
|
-
|
9609
|
+
The format in which the [request params](/up.Layer.prototype.params) will be encoded.
|
9447
9610
|
|
9448
9611
|
@property up.Request#contentType
|
9449
9612
|
@param {string} contentType
|
@@ -9452,13 +9615,22 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9452
9615
|
|
9453
9616
|
|
9454
9617
|
/***
|
9455
|
-
|
9618
|
+
The payload that the request will encode into its body.
|
9619
|
+
|
9620
|
+
By default Unpoly will build a payload from the given `{ params }` option.
|
9456
9621
|
|
9457
9622
|
@property up.Request#payload
|
9458
9623
|
@param {string} payload
|
9459
9624
|
@stable
|
9460
9625
|
*/
|
9461
9626
|
|
9627
|
+
|
9628
|
+
/***
|
9629
|
+
@property up.Request#preload
|
9630
|
+
@param {boolean} preload
|
9631
|
+
@experimental
|
9632
|
+
*/
|
9633
|
+
|
9462
9634
|
Request.prototype.keys = function() {
|
9463
9635
|
return ['method', 'url', 'hash', 'params', 'target', 'failTarget', 'headers', 'timeout', 'preload', 'cache', 'clearCache', 'layer', 'mode', 'context', 'failLayer', 'failMode', 'failContext', 'origin', 'solo', 'queueTime', 'wrapMethod', 'contentType', 'payload', 'onQueued'];
|
9464
9636
|
};
|
@@ -9514,7 +9686,8 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9514
9686
|
Request.prototype.normalizeForCaching = function() {
|
9515
9687
|
this.method = u.normalizeMethod(this.method);
|
9516
9688
|
this.extractHashFromURL();
|
9517
|
-
|
9689
|
+
this.transferParamsToURL();
|
9690
|
+
return this.url = u.normalizeURL(this.url);
|
9518
9691
|
};
|
9519
9692
|
|
9520
9693
|
Request.prototype.evictExpensiveAttrs = function() {
|
@@ -9601,6 +9774,37 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9601
9774
|
});
|
9602
9775
|
};
|
9603
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
|
+
|
9604
9808
|
Request.prototype.loadPage = function() {
|
9605
9809
|
up.network.abort();
|
9606
9810
|
return new up.Request.FormRenderer(this).buildAndSubmit();
|
@@ -10180,7 +10384,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
10180
10384
|
|
10181
10385
|
|
10182
10386
|
/***
|
10183
|
-
|
10387
|
+
A response to an [HTTP request](`up.request()`).
|
10184
10388
|
|
10185
10389
|
\#\#\# Example
|
10186
10390
|
|
@@ -10292,6 +10496,14 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
10292
10496
|
@experimental
|
10293
10497
|
*/
|
10294
10498
|
|
10499
|
+
|
10500
|
+
/***
|
10501
|
+
Changes to the current [context](/context) as [set by the server](/X-Up-Context).
|
10502
|
+
|
10503
|
+
@property up.Response#context
|
10504
|
+
@experimental
|
10505
|
+
*/
|
10506
|
+
|
10295
10507
|
Response.prototype.keys = function() {
|
10296
10508
|
return ['method', 'url', 'text', 'status', 'request', 'xhr', 'target', 'title', 'acceptLayer', 'dismissLayer', 'eventPlans', 'context', 'clearCache', 'headers'];
|
10297
10509
|
};
|
@@ -10838,7 +11050,8 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
10838
11050
|
|
10839
11051
|
}).call(this);
|
10840
11052
|
(function() {
|
10841
|
-
var e, u
|
11053
|
+
var e, u,
|
11054
|
+
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
10842
11055
|
|
10843
11056
|
u = up.util;
|
10844
11057
|
|
@@ -10846,6 +11059,8 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
10846
11059
|
|
10847
11060
|
up.Tether = (function() {
|
10848
11061
|
function Tether(options) {
|
11062
|
+
this.sync = bind(this.sync, this);
|
11063
|
+
this.scheduleSync = bind(this.scheduleSync, this);
|
10849
11064
|
var base;
|
10850
11065
|
if (typeof (base = up.migrate).handleTetherOptions === "function") {
|
10851
11066
|
base.handleTetherOptions(options);
|
@@ -11147,37 +11362,26 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
11147
11362
|
Events
|
11148
11363
|
======
|
11149
11364
|
|
11150
|
-
This module contains functions to [
|
11365
|
+
This module contains functions to [emit](/up.emit) and [observe](/up.on) DOM events.
|
11151
11366
|
|
11152
|
-
While the browser also
|
11153
|
-
and
|
11154
|
-
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.
|
11155
11369
|
|
11156
11370
|
## Events emitted by Unpoly
|
11157
11371
|
|
11158
|
-
Most Unpoly
|
11159
|
-
|
11160
|
-
```javascript
|
11161
|
-
document.addEventListener('up:modal:opened', (event) => {
|
11162
|
-
console.log('A new modal has just opened!')
|
11163
|
-
})
|
11164
|
-
```
|
11165
|
-
|
11166
|
-
Events often have both present and past forms. For example, `up:layer:open` is emitted before an overlay starts to open.
|
11167
|
-
`up:layer:opened` is emitted when the overlay has appeared in the DOM tree.
|
11372
|
+
Most Unpoly features emit events that are prefixed with `up:`.
|
11168
11373
|
|
11169
|
-
|
11374
|
+
Unpoly's own events are documented in their respective modules, for example:
|
11170
11375
|
|
11171
|
-
|
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` |
|
11172
11382
|
|
11173
|
-
|
11174
|
-
|
11175
|
-
if (event.url == '/evil') {
|
11176
|
-
// Prevent the modal from opening
|
11177
|
-
event.preventDefault()
|
11178
|
-
}
|
11179
|
-
})
|
11180
|
-
```
|
11383
|
+
@see up.on
|
11384
|
+
@see up.emit
|
11181
11385
|
|
11182
11386
|
@module up.event
|
11183
11387
|
*/
|
@@ -11317,12 +11521,16 @@ document.addEventListener('up:modal:open', (event) => {
|
|
11317
11521
|
Multiple event types may be passed as either a space-separated string
|
11318
11522
|
or as an array of types.
|
11319
11523
|
|
11320
|
-
@param {string} [selector]
|
11524
|
+
@param {string|Function():string} [selector]
|
11321
11525
|
The selector of an element on which the event must be triggered.
|
11322
11526
|
|
11323
11527
|
Omit the selector to listen to all events of the given type, regardless
|
11324
11528
|
of the event target.
|
11325
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
|
+
|
11326
11534
|
@param {boolean} [options.passive=false]
|
11327
11535
|
Whether to register a [passive event listener](https://developers.google.com/web/updates/2016/06/passive-event-listeners).
|
11328
11536
|
|
@@ -11333,7 +11541,7 @@ document.addEventListener('up:modal:open', (event) => {
|
|
11333
11541
|
@param {boolean} [options.once=true]
|
11334
11542
|
Whether the listener should run at most once.
|
11335
11543
|
|
11336
|
-
If `true` the listener will automatically be
|
11544
|
+
If `true` the listener will automatically be unbound
|
11337
11545
|
after the first invocation.
|
11338
11546
|
|
11339
11547
|
@param {Function(event, [element], [data])} listener
|
@@ -11424,12 +11632,12 @@ document.addEventListener('up:modal:open', (event) => {
|
|
11424
11632
|
|
11425
11633
|
@function up.off
|
11426
11634
|
@param {Element|jQuery} [element=document]
|
11427
|
-
@param {string} events
|
11635
|
+
@param {string|Function(): string} events
|
11428
11636
|
@param {string} [selector]
|
11429
11637
|
@param {Function(event, [element], [data])} listener
|
11430
11638
|
The listener function to unbind.
|
11431
11639
|
|
11432
|
-
Note that you must pass a reference to the
|
11640
|
+
Note that you must pass a reference to the same function reference
|
11433
11641
|
that was passed to `up.on()` earlier.
|
11434
11642
|
@stable
|
11435
11643
|
*/
|
@@ -11680,8 +11888,12 @@ document.addEventListener('up:modal:open', (event) => {
|
|
11680
11888
|
|
11681
11889
|
This hyperlink will emit an `user:select` event when clicked:
|
11682
11890
|
|
11683
|
-
```
|
11684
|
-
<a href='/users/5
|
11891
|
+
```html
|
11892
|
+
<a href='/users/5'
|
11893
|
+
up-emit='user:select'
|
11894
|
+
up-emit-props='{ "id": 5, "firstName": "Alice" }'>
|
11895
|
+
Alice
|
11896
|
+
</a>
|
11685
11897
|
|
11686
11898
|
<script>
|
11687
11899
|
up.on('a', 'user:select', function(event) {
|
@@ -11696,6 +11908,7 @@ document.addEventListener('up:modal:open', (event) => {
|
|
11696
11908
|
The type of the event to be emitted.
|
11697
11909
|
@param [up-emit-props='{}']
|
11698
11910
|
The event properties, serialized as JSON.
|
11911
|
+
@stable
|
11699
11912
|
*/
|
11700
11913
|
executeEmitAttr = function(event, element) {
|
11701
11914
|
var eventProps, eventType, forkedEvent;
|
@@ -11764,7 +11977,7 @@ There are existing implementations for various web frameworks:
|
|
11764
11977
|
- [Roda](https://github.com/adam12/roda-unpoly)
|
11765
11978
|
- [Rack](https://github.com/adam12/rack-unpoly) (Sinatra, Padrino, Hanami, Cuba, ...)
|
11766
11979
|
- [Phoenix](https://elixirforum.com/t/unpoly-a-framework-like-turbolinks/3614/15) (Elixir)
|
11767
|
-
- [PHP](https://github.com/
|
11980
|
+
- [PHP](https://github.com/webstronauts/php-unpoly) (Symfony, Laravel, Stack)
|
11768
11981
|
|
11769
11982
|
@module up.protocol
|
11770
11983
|
*/
|
@@ -11987,68 +12200,35 @@ There are existing implementations for various web frameworks:
|
|
11987
12200
|
The timestamp must be explicitely set by the user as an `[up-time]` attribute on the fragment.
|
11988
12201
|
It should indicate the time when the fragment's underlying data was last changed.
|
11989
12202
|
|
11990
|
-
|
11991
|
-
|
11992
|
-
If no timestamp is known, Unpoly will send a value of zero (`X-Up-Reload-From-Time: 0`).
|
11993
|
-
|
11994
|
-
\#\#\# Example
|
12203
|
+
See `[up-time]` for a detailed example.
|
11995
12204
|
|
11996
|
-
|
11997
|
-
was last changed. For instance, when the last message in a list was received from December 24th, 1:51:46 PM UTC:
|
12205
|
+
\#\#\# Format
|
11998
12206
|
|
11999
|
-
|
12000
|
-
<div class="messages" up-time="1608730818">
|
12001
|
-
...
|
12002
|
-
</div>
|
12003
|
-
```
|
12207
|
+
The time is encoded is the number of seconds elapsed since the [Unix epoch](https://en.wikipedia.org/wiki/Unix_time).
|
12004
12208
|
|
12005
|
-
|
12209
|
+
For instance, a modification date of December 23th, 1:40:18 PM UTC would produce the following header:
|
12006
12210
|
|
12007
12211
|
```http
|
12212
|
+
X-Up-Target: .unread-count
|
12008
12213
|
X-Up-Reload-From-Time: 1608730818
|
12009
12214
|
```
|
12010
12215
|
|
12011
|
-
|
12216
|
+
If no timestamp is known, Unpoly will send a value of zero (`X-Up-Reload-From-Time: 0`).
|
12012
12217
|
|
12013
|
-
|
12014
|
-
|
12218
|
+
@header X-Up-Reload-From-Time
|
12219
|
+
@stable
|
12220
|
+
*/
|
12221
|
+
contextFromXHR = function(xhr) {
|
12222
|
+
return extractHeader(xhr, 'context', JSON.parse);
|
12223
|
+
};
|
12224
|
+
|
12225
|
+
/***
|
12226
|
+
This request header contains the targeted layer's [context](/context), serialized as JSON.
|
12015
12227
|
|
12016
|
-
The
|
12017
|
-
|
12228
|
+
The user may choose to not send this header by configuring
|
12229
|
+
`up.network.config.requestMetaKeys`.
|
12018
12230
|
|
12019
|
-
|
12020
|
-
class MessagesController < ApplicationController
|
12021
|
-
|
12022
|
-
def index
|
12023
|
-
if up.reload_from_time == current_user.last_message_at
|
12024
|
-
up.render_nothing
|
12025
|
-
else
|
12026
|
-
@messages = current_user.messages.order(time: :desc).to_a
|
12027
|
-
render 'index'
|
12028
|
-
end
|
12029
|
-
end
|
12030
|
-
|
12031
|
-
end
|
12032
|
-
```
|
12033
|
-
|
12034
|
-
Only rendering when needed saves <b>CPU time</b> on your server, which spends most of its response time rendering HTML.
|
12035
|
-
|
12036
|
-
This also reduces the <b>bandwidth cost</b> for a request/response exchange to **~1 KB**.
|
12037
|
-
|
12038
|
-
@header X-Up-Reload-From-Time
|
12039
|
-
@stable
|
12040
|
-
*/
|
12041
|
-
contextFromXHR = function(xhr) {
|
12042
|
-
return extractHeader(xhr, 'context', JSON.parse);
|
12043
|
-
};
|
12044
|
-
|
12045
|
-
/***
|
12046
|
-
This request header contains the targeted layer's [context](/up.context), serialized as JSON.
|
12047
|
-
|
12048
|
-
The user may choose to not send this header by configuring
|
12049
|
-
`up.network.config.requestMetaKeys`.
|
12050
|
-
|
12051
|
-
\#\#\# Example
|
12231
|
+
\#\#\# Example
|
12052
12232
|
|
12053
12233
|
```http
|
12054
12234
|
X-Up-Context: { "lives": 3 }
|
@@ -12084,11 +12264,11 @@ There are existing implementations for various web frameworks:
|
|
12084
12264
|
the request was in flight will get overridden by the server-provided context.
|
12085
12265
|
|
12086
12266
|
@header X-Up-Context
|
12087
|
-
@
|
12267
|
+
@experimental
|
12088
12268
|
*/
|
12089
12269
|
|
12090
12270
|
/***
|
12091
|
-
This request header contains the [context](/
|
12271
|
+
This request header contains the [context](/context) of the layer
|
12092
12272
|
targeted for a failed fragment update, serialized as JSON.
|
12093
12273
|
|
12094
12274
|
A fragment update is considered *failed* if the server responds with a
|
@@ -12107,7 +12287,7 @@ There are existing implementations for various web frameworks:
|
|
12107
12287
|
```
|
12108
12288
|
|
12109
12289
|
@header X-Up-Fail-Context
|
12110
|
-
@
|
12290
|
+
@experimental
|
12111
12291
|
*/
|
12112
12292
|
|
12113
12293
|
/***
|
@@ -12267,7 +12447,7 @@ There are existing implementations for various web frameworks:
|
|
12267
12447
|
the response's HTML content.
|
12268
12448
|
|
12269
12449
|
The header value is the acceptance value serialized as a JSON object.
|
12270
|
-
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`.
|
12271
12451
|
|
12272
12452
|
\#\#\# Example
|
12273
12453
|
|
@@ -12313,7 +12493,7 @@ There are existing implementations for various web frameworks:
|
|
12313
12493
|
the response's HTML content.
|
12314
12494
|
|
12315
12495
|
The header value is the dismissal value serialized as a JSON object.
|
12316
|
-
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`.
|
12317
12497
|
|
12318
12498
|
\#\#\# Example
|
12319
12499
|
|
@@ -12425,10 +12605,12 @@ There are existing implementations for various web frameworks:
|
|
12425
12605
|
Configures strings used in the optional [server protocol](/up.protocol).
|
12426
12606
|
|
12427
12607
|
@property up.protocol.config
|
12608
|
+
|
12428
12609
|
@param {string} [config.csrfHeader='X-CSRF-Token']
|
12429
12610
|
The name of the HTTP header that will include the
|
12430
12611
|
[CSRF token](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Synchronizer_token_pattern)
|
12431
12612
|
for AJAX requests.
|
12613
|
+
|
12432
12614
|
@param {string|Function(): string} [config.csrfParam]
|
12433
12615
|
The `name` of the hidden `<input>` used for sending a
|
12434
12616
|
[CSRF token](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Synchronizer_token_pattern) when
|
@@ -12440,7 +12622,10 @@ There are existing implementations for various web frameworks:
|
|
12440
12622
|
|
12441
12623
|
Defaults to the `content` attribute of a `<meta>` tag named `csrf-param`:
|
12442
12624
|
|
12443
|
-
|
12625
|
+
```html
|
12626
|
+
<meta name="csrf-param" content="authenticity_token" />
|
12627
|
+
```
|
12628
|
+
|
12444
12629
|
@param {string|Function(): string} [config.csrfToken]
|
12445
12630
|
The [CSRF token](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Synchronizer_token_pattern)
|
12446
12631
|
to send for unsafe requests. The token will be sent as either a HTTP header (for AJAX requests)
|
@@ -12451,7 +12636,10 @@ There are existing implementations for various web frameworks:
|
|
12451
12636
|
|
12452
12637
|
Defaults to the `content` attribute of a `<meta>` tag named `csrf-token`:
|
12453
12638
|
|
12454
|
-
|
12639
|
+
```
|
12640
|
+
<meta name='csrf-token' content='secret12345'>
|
12641
|
+
```
|
12642
|
+
|
12455
12643
|
@param {string} [config.methodParam='_method']
|
12456
12644
|
The name of request parameter containing the original request method when Unpoly needs to wrap
|
12457
12645
|
the method.
|
@@ -12530,13 +12718,14 @@ There are existing implementations for various web frameworks:
|
|
12530
12718
|
Logging
|
12531
12719
|
=======
|
12532
12720
|
|
12533
|
-
Unpoly can print debugging information to the
|
12721
|
+
Unpoly can print debugging information to the [browser console](https://developer.chrome.com/docs/devtools/console/), e.g.:
|
12534
12722
|
|
12535
12723
|
- Which [events](/up.event) are called
|
12536
12724
|
- When we're [making requests to the network](/up.request)
|
12537
12725
|
- Which [compilers](/up.syntax) are applied to which elements
|
12538
12726
|
|
12539
|
-
|
12727
|
+
@see up.log.enable
|
12728
|
+
@see up.log.disable
|
12540
12729
|
|
12541
12730
|
@module up.log
|
12542
12731
|
*/
|
@@ -12559,11 +12748,14 @@ You can activate logging by calling [`up.log.enable()`](/up.log.enable).
|
|
12559
12748
|
Debugging information includes which elements are being [compiled](/up.syntax)
|
12560
12749
|
and which [events](/up.event) are being emitted.
|
12561
12750
|
Note that errors will always be printed, regardless of this setting.
|
12562
|
-
@
|
12751
|
+
@param {boolean} [options.banner=true]
|
12752
|
+
Print the Unpoly banner to the developer console.
|
12753
|
+
@stable
|
12563
12754
|
*/
|
12564
12755
|
config = new up.Config(function() {
|
12565
12756
|
return {
|
12566
|
-
enabled: sessionStore.get('enabled')
|
12757
|
+
enabled: sessionStore.get('enabled'),
|
12758
|
+
banner: true
|
12567
12759
|
};
|
12568
12760
|
});
|
12569
12761
|
reset = function() {
|
@@ -12621,6 +12813,9 @@ You can activate logging by calling [`up.log.enable()`](/up.log.enable).
|
|
12621
12813
|
};
|
12622
12814
|
printBanner = function() {
|
12623
12815
|
var color, logo, text;
|
12816
|
+
if (!config.banner) {
|
12817
|
+
return;
|
12818
|
+
}
|
12624
12819
|
logo = " __ _____ ___ ___ / /_ __\n" + ("/ // / _ \\/ _ \\/ _ \\/ / // / " + up.version + "\n") + "\\___/_//_/ .__/\\___/_/\\_. / \n" + " / / / /\n\n";
|
12625
12820
|
text = "";
|
12626
12821
|
if (!up.migrate.loaded) {
|
@@ -12638,7 +12833,7 @@ You can activate logging by calling [`up.log.enable()`](/up.log.enable).
|
|
12638
12833
|
return console.log(logo + text);
|
12639
12834
|
}
|
12640
12835
|
};
|
12641
|
-
up.on('up:
|
12836
|
+
up.on('up:app:boot', printBanner);
|
12642
12837
|
up.on('up:framework:reset', reset);
|
12643
12838
|
setEnabled = function(value) {
|
12644
12839
|
sessionStore.set('enabled', value);
|
@@ -12646,7 +12841,7 @@ You can activate logging by calling [`up.log.enable()`](/up.log.enable).
|
|
12646
12841
|
};
|
12647
12842
|
|
12648
12843
|
/***
|
12649
|
-
|
12844
|
+
Starts printing debugging information to the developer console.
|
12650
12845
|
|
12651
12846
|
Debugging information includes which elements are being [compiled](/up.syntax)
|
12652
12847
|
and which [events](/up.event) are being emitted.
|
@@ -12661,7 +12856,7 @@ You can activate logging by calling [`up.log.enable()`](/up.log.enable).
|
|
12661
12856
|
};
|
12662
12857
|
|
12663
12858
|
/***
|
12664
|
-
|
12859
|
+
Stops printing debugging information to the developer console.
|
12665
12860
|
|
12666
12861
|
Errors will still be printed, even with logging disabled.
|
12667
12862
|
|
@@ -12703,24 +12898,26 @@ You can activate logging by calling [`up.log.enable()`](/up.log.enable).
|
|
12703
12898
|
};
|
12704
12899
|
|
12705
12900
|
/***
|
12706
|
-
|
12707
|
-
|
12708
|
-
|
12709
|
-
|
12710
|
-
|
12711
|
-
|
12712
|
-
|
12713
|
-
|
12714
|
-
|
12715
|
-
|
12716
|
-
|
12717
|
-
|
12718
|
-
|
12719
|
-
|
12720
|
-
|
12721
|
-
|
12722
|
-
|
12723
|
-
|
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
|
12724
12921
|
*/
|
12725
12922
|
muteUncriticalRejection = function(promise) {
|
12726
12923
|
return promise["catch"](function(error) {
|
@@ -12756,20 +12953,11 @@ You can activate logging by calling [`up.log.enable()`](/up.log.enable).
|
|
12756
12953
|
Custom JavaScript
|
12757
12954
|
=================
|
12758
12955
|
|
12759
|
-
|
12760
|
-
in order to integrate libraries or implement custom behavior.
|
12956
|
+
The `up.syntax` package lets you pair HTML elements with JavaScript behavior.
|
12761
12957
|
|
12762
|
-
|
12763
|
-
|
12764
|
-
|
12765
|
-
with a `grid` class, use this compiler:
|
12766
|
-
|
12767
|
-
up.compiler('.grid', function(element) {
|
12768
|
-
new Masonry(element, { itemSelector: '.grid--item' })
|
12769
|
-
})
|
12770
|
-
|
12771
|
-
The compiler function will be called on matching elements when the page loads
|
12772
|
-
or when a matching fragment is [inserted via AJAX](/up.link) later.
|
12958
|
+
@see up.compiler
|
12959
|
+
@see [up-data]
|
12960
|
+
@see up.macro
|
12773
12961
|
|
12774
12962
|
@module up.syntax
|
12775
12963
|
*/
|
@@ -12804,14 +12992,17 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
12804
12992
|
Use compilers to activate your custom Javascript behavior on matching
|
12805
12993
|
elements.
|
12806
12994
|
|
12807
|
-
You should migrate your [`DOMContentLoaded`](https://
|
12995
|
+
You should migrate your [`DOMContentLoaded`](https://developer.mozilla.org/en-US/docs/Web/API/Window/DOMContentLoaded_event)
|
12808
12996
|
callbacks to compilers. This will make sure they run both at page load and
|
12809
12997
|
when a new fragment is inserted later.
|
12810
|
-
|
12998
|
+
See [Making JavaScripts work with fragment updates](/legacy-scripts) for advice
|
12999
|
+
on migrating legacy scripts.
|
13000
|
+
|
13001
|
+
It will also organize your JavaScript snippets by selector.
|
12811
13002
|
|
12812
13003
|
\#\#\# Example
|
12813
13004
|
|
12814
|
-
This
|
13005
|
+
This compiler will insert the current time into a
|
12815
13006
|
`<div class='current-time'></div>`:
|
12816
13007
|
|
12817
13008
|
```js
|
@@ -12872,55 +13063,34 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
12872
13063
|
|
12873
13064
|
An alternative way to register a destructor function is `up.destructor()`.
|
12874
13065
|
|
12875
|
-
\#\#\#
|
13066
|
+
\#\#\# Passing parameters to a compiler
|
12876
13067
|
|
12877
|
-
|
12878
|
-
|
12879
|
-
For instance, a container for a [Google Map](https://developers.google.com/maps/documentation/javascript/tutorial)
|
12880
|
-
might attach the location and names of its marker pins:
|
13068
|
+
Use the `[up-data]` attribute to attach structured data to a DOM element.
|
13069
|
+
The data will be parsed and passed to your compiler function.
|
12881
13070
|
|
12882
|
-
|
12883
|
-
|
12884
|
-
|
12885
|
-
{ "lat": 48.75, "lng": 11.45, "title": "Ingolstadt" }
|
12886
|
-
]'></div>
|
12887
|
-
```
|
12888
|
-
|
12889
|
-
The JSON will be parsed and handed to your compiler as a second argument:
|
12890
|
-
|
12891
|
-
```js
|
12892
|
-
up.compiler('.google-map', function(element, pins) {
|
12893
|
-
var map = new google.maps.Map(element)
|
13071
|
+
Alternatively your compiler may access attributes for the compiled element
|
13072
|
+
via the standard [`Element#getAttribute()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute)
|
13073
|
+
method.
|
12894
13074
|
|
12895
|
-
|
12896
|
-
|
12897
|
-
new google.maps.Marker({
|
12898
|
-
position: position,
|
12899
|
-
map: map,
|
12900
|
-
title: pin.title
|
12901
|
-
})
|
12902
|
-
})
|
12903
|
-
})
|
12904
|
-
```
|
13075
|
+
Unpoly also provides utility functions to read an element attribute and
|
13076
|
+
cast it to a given type:
|
12905
13077
|
|
12906
|
-
|
13078
|
+
- `up.element.booleanAttr(element, attr)`
|
13079
|
+
- `up.element.numberAttr(element, attr)`
|
13080
|
+
- `up.element.jsonAttr(element, attr)`
|
12907
13081
|
|
12908
13082
|
@function up.compiler
|
12909
13083
|
@param {string} selector
|
12910
13084
|
The selector to match.
|
12911
13085
|
@param {number} [options.priority=0]
|
12912
13086
|
The priority of this compiler.
|
13087
|
+
|
12913
13088
|
Compilers with a higher priority are run first.
|
12914
13089
|
Two compilers with the same priority are run in the order they were registered.
|
12915
13090
|
@param {boolean} [options.batch=false]
|
12916
13091
|
If set to `true` and a fragment insertion contains multiple
|
12917
|
-
elements matching the
|
12918
|
-
with
|
12919
|
-
@param {boolean} [options.keep=false]
|
12920
|
-
If set to `true` compiled fragment will be [persisted](/up-keep) during
|
12921
|
-
fragment updates.
|
12922
|
-
|
12923
|
-
This has the same effect as setting an `up-keep` attribute on the element.
|
13092
|
+
elements matching `selector`, the `compiler` function is only called once
|
13093
|
+
with all these elements.
|
12924
13094
|
@param {Function(element, data)} compiler
|
12925
13095
|
The function to call when a matching element is inserted.
|
12926
13096
|
|
@@ -12957,10 +13127,12 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
12957
13127
|
This jQuery compiler will insert the current time into a
|
12958
13128
|
`<div class='current-time'></div>`:
|
12959
13129
|
|
12960
|
-
|
12961
|
-
|
12962
|
-
|
12963
|
-
|
13130
|
+
```js
|
13131
|
+
up.$compiler('.current-time', function($element) {
|
13132
|
+
var now = new Date()
|
13133
|
+
$element.text(now.toString())
|
13134
|
+
})
|
13135
|
+
```
|
12964
13136
|
|
12965
13137
|
@function up.$compiler
|
12966
13138
|
@param {string} selector
|
@@ -12984,33 +13156,40 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
12984
13156
|
/***
|
12985
13157
|
Registers a [compiler](/up.compiler) that is run before all other compilers.
|
12986
13158
|
|
12987
|
-
|
13159
|
+
A macro lets you set UJS attributes that will be compiled afterwards.
|
13160
|
+
|
13161
|
+
If you want default attributes for *every* link and form, consider customizing your
|
13162
|
+
[navigation options](/navigation).
|
12988
13163
|
|
12989
13164
|
\#\#\# Example
|
12990
13165
|
|
12991
13166
|
You will sometimes find yourself setting the same combination of UJS attributes again and again:
|
12992
13167
|
|
12993
|
-
|
12994
|
-
|
12995
|
-
|
13168
|
+
```html
|
13169
|
+
<a href="/page1" up-layer="new modal" up-class="warning" up-animation="shake">Page 1</a>
|
13170
|
+
<a href="/page1" up-layer="new modal" up-class="warning" up-animation="shake">Page 1</a>
|
13171
|
+
<a href="/page1" up-layer="new modal" up-class="warning" up-animation="shake">Page 1</a>
|
13172
|
+
```
|
12996
13173
|
|
12997
|
-
We would much rather define a new `[
|
13174
|
+
We would much rather define a new `[smooth-link]` attribute that let's us
|
12998
13175
|
write the same links like this:
|
12999
13176
|
|
13000
|
-
|
13001
|
-
|
13002
|
-
|
13177
|
+
```html
|
13178
|
+
<a href="/page1" smooth-link>Page 1</a>
|
13179
|
+
<a href="/page2" smooth-link>Page 2</a>
|
13180
|
+
<a href="/page3" smooth-link>Page 3</a>
|
13181
|
+
```
|
13003
13182
|
|
13004
13183
|
We can define the `[content-link]` attribute by registering a macro that
|
13005
13184
|
sets the `[up-target]`, `[up-transition]` and `[up-duration]` attributes for us:
|
13006
13185
|
|
13007
|
-
|
13008
|
-
|
13009
|
-
|
13010
|
-
|
13011
|
-
|
13012
|
-
|
13013
|
-
|
13186
|
+
```
|
13187
|
+
up.macro('[smooth-link]', function(link) {
|
13188
|
+
link.setAttribute('up-target', '.content')
|
13189
|
+
link.setAttribute('up-transition', 'cross-fade')
|
13190
|
+
link.setAttribute('up-duration', '300')
|
13191
|
+
})
|
13192
|
+
```
|
13014
13193
|
|
13015
13194
|
@function up.macro
|
13016
13195
|
@param {string} selector
|
@@ -13043,13 +13222,15 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
13043
13222
|
|
13044
13223
|
\#\#\# Example
|
13045
13224
|
|
13046
|
-
|
13047
|
-
|
13048
|
-
|
13049
|
-
|
13050
|
-
|
13051
|
-
|
13052
|
-
|
13225
|
+
```js
|
13226
|
+
up.$macro('[content-link]', function($link) {
|
13227
|
+
$link.attr(
|
13228
|
+
'up-target': '.content',
|
13229
|
+
'up-transition': 'cross-fade',
|
13230
|
+
'up-duration':'300'
|
13231
|
+
)
|
13232
|
+
})
|
13233
|
+
```
|
13053
13234
|
|
13054
13235
|
@function up.$macro
|
13055
13236
|
@param {string} selector
|
@@ -13111,6 +13292,7 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
13111
13292
|
|
13112
13293
|
/***
|
13113
13294
|
Applies all compilers on the given element and its descendants.
|
13295
|
+
|
13114
13296
|
Unlike [`up.hello()`](/up.hello), this doesn't emit any events.
|
13115
13297
|
|
13116
13298
|
@function up.syntax.compile
|
@@ -13139,8 +13321,8 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
13139
13321
|
})
|
13140
13322
|
```
|
13141
13323
|
|
13142
|
-
An alternative way to register a destructor function is to
|
13143
|
-
it from your compiler function.
|
13324
|
+
An alternative way to register a destructor function is to
|
13325
|
+
[`return` it from your compiler function](/up.compiler#cleaning-up-after-yourself).
|
13144
13326
|
|
13145
13327
|
@function up.destructor
|
13146
13328
|
@param {Element} element
|
@@ -13164,6 +13346,7 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
13164
13346
|
|
13165
13347
|
/***
|
13166
13348
|
Runs any destructor on the given fragment and its descendants in the same layer.
|
13349
|
+
|
13167
13350
|
Unlike [`up.destroy()`](/up.destroy), this does not emit any events
|
13168
13351
|
and does not remove the element from the DOM.
|
13169
13352
|
|
@@ -13182,20 +13365,23 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
13182
13365
|
};
|
13183
13366
|
|
13184
13367
|
/***
|
13185
|
-
|
13186
|
-
If yes, parses the attribute value as JSON and returns the parsed object.
|
13368
|
+
Returns the given element's `[up-data]`, parsed as a JavaScript object.
|
13187
13369
|
|
13188
|
-
Returns `undefined` if the element has no `up-data` attribute.
|
13370
|
+
Returns `undefined` if the element has no `[up-data]` attribute.
|
13189
13371
|
|
13190
13372
|
\#\#\# Example
|
13191
13373
|
|
13192
13374
|
You have an element with JSON data serialized into an `up-data` attribute:
|
13193
13375
|
|
13194
|
-
|
13376
|
+
```html
|
13377
|
+
<span class='person' up-data='{ "age": 18, "name": "Bob" }'>Bob</span>
|
13378
|
+
```
|
13195
13379
|
|
13196
13380
|
Calling `up.syntax.data()` will deserialize the JSON string into a JavaScript object:
|
13197
13381
|
|
13198
|
-
|
13382
|
+
```js
|
13383
|
+
up.syntax.data('.person') // returns { age: 18, name: 'Bob' }
|
13384
|
+
```
|
13199
13385
|
|
13200
13386
|
@function up.data
|
13201
13387
|
@param {string|Element|jQuery} element
|
@@ -13208,39 +13394,49 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
13208
13394
|
*/
|
13209
13395
|
|
13210
13396
|
/***
|
13211
|
-
|
13397
|
+
Attaches structured data to an element, to be consumed by a compiler.
|
13398
|
+
|
13399
|
+
If an element with an `[up-data]` attribute enters the DOM,
|
13212
13400
|
Unpoly will parse the JSON and pass the resulting object to any matching
|
13213
|
-
[`up.compiler()`](/up.compiler)
|
13401
|
+
[`up.compiler()`](/up.compiler) functions.
|
13402
|
+
|
13403
|
+
\#\#\# Example
|
13214
13404
|
|
13215
13405
|
For instance, a container for a [Google Map](https://developers.google.com/maps/documentation/javascript/tutorial)
|
13216
13406
|
might attach the location and names of its marker pins:
|
13217
13407
|
|
13218
|
-
|
13219
|
-
|
13220
|
-
|
13221
|
-
|
13408
|
+
```html
|
13409
|
+
<div class='google-map' up-data='[
|
13410
|
+
{ "lat": 48.36, "lng": 10.99, "title": "Friedberg" },
|
13411
|
+
{ "lat": 48.75, "lng": 11.45, "title": "Ingolstadt" }
|
13412
|
+
]'></div>
|
13413
|
+
```
|
13222
13414
|
|
13223
13415
|
The JSON will be parsed and handed to your compiler as a second argument:
|
13224
13416
|
|
13225
|
-
|
13226
|
-
|
13227
|
-
|
13228
|
-
|
13229
|
-
|
13230
|
-
|
13231
|
-
|
13232
|
-
|
13233
|
-
|
13234
|
-
})
|
13417
|
+
```js
|
13418
|
+
up.compiler('.google-map', function(element, pins) {
|
13419
|
+
var map = new google.maps.Map(element)
|
13420
|
+
pins.forEach(function(pin) {
|
13421
|
+
var position = new google.maps.LatLng(pin.lat, pin.lng)
|
13422
|
+
new google.maps.Marker({
|
13423
|
+
position: position,
|
13424
|
+
map: map,
|
13425
|
+
title: pin.title
|
13235
13426
|
})
|
13427
|
+
})
|
13428
|
+
})
|
13429
|
+
```
|
13236
13430
|
|
13237
13431
|
Similarly, when an event is triggered on an element annotated with
|
13238
13432
|
[`up-data`], the parsed object will be passed to any matching
|
13239
13433
|
[`up.on()`](/up.on) handlers.
|
13240
13434
|
|
13241
|
-
|
13242
|
-
|
13243
|
-
|
13435
|
+
```js
|
13436
|
+
up.on('click', '.google-map', function(event, element, pins) {
|
13437
|
+
console.log("There are %d pins on the clicked map", pins.length)
|
13438
|
+
})
|
13439
|
+
```
|
13244
13440
|
|
13245
13441
|
@selector [up-data]
|
13246
13442
|
@param up-data
|
@@ -13293,9 +13489,10 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
13293
13489
|
History
|
13294
13490
|
========
|
13295
13491
|
|
13296
|
-
|
13492
|
+
The `up.history` module helps you work with the browser history.
|
13297
13493
|
|
13298
|
-
|
13494
|
+
@see up.history.location
|
13495
|
+
@see up:location:changed
|
13299
13496
|
|
13300
13497
|
@module up.history
|
13301
13498
|
*/
|
@@ -13320,7 +13517,7 @@ In an Unpoly app, every page has an URL.
|
|
13320
13517
|
Defines whether [fragment updates](/up.render) will update the browser's current URL.
|
13321
13518
|
|
13322
13519
|
If set to `false` Unpoly will never change the browser URL.
|
13323
|
-
@param {boolean} [config.
|
13520
|
+
@param {boolean} [config.enabled=true]
|
13324
13521
|
Whether to restore the known scroll positions
|
13325
13522
|
when the user goes back or forward in history.
|
13326
13523
|
@stable
|
@@ -13429,7 +13626,7 @@ In an Unpoly app, every page has an URL.
|
|
13429
13626
|
address bar with the given URL.
|
13430
13627
|
|
13431
13628
|
When the user restores the new history entry later,
|
13432
|
-
Unpoly will replace
|
13629
|
+
Unpoly will replace a selector from `up.history.config.restoreTargets` with the body from that URL.
|
13433
13630
|
|
13434
13631
|
Note that [fragment navigation](/navigation) will automatically update the
|
13435
13632
|
browser's location bar for you.
|
@@ -13463,7 +13660,7 @@ In an Unpoly app, every page has an URL.
|
|
13463
13660
|
|
13464
13661
|
When a [layer](/up.layer) has no [visible history](/up.Layer.prototype.historyVisible), following a link
|
13465
13662
|
will not cause the browser's address bar to be updated. In this case no `up:location:changed` event will be emitted.
|
13466
|
-
|
13663
|
+
However, a `up:layer:location:changed` will be emitted even if the address bar did not change.
|
13467
13664
|
|
13468
13665
|
@event up:location:changed
|
13469
13666
|
@param {string} event.url
|
@@ -13536,9 +13733,11 @@ In an Unpoly app, every page has an URL.
|
|
13536
13733
|
register = function() {
|
13537
13734
|
window.history.scrollRestoration = 'manual';
|
13538
13735
|
window.addEventListener('popstate', pop);
|
13539
|
-
|
13540
|
-
|
13541
|
-
|
13736
|
+
if (up.protocol.initialRequestMethod() === 'GET') {
|
13737
|
+
return replace(currentLocation(), {
|
13738
|
+
event: false
|
13739
|
+
});
|
13740
|
+
}
|
13542
13741
|
};
|
13543
13742
|
if (typeof jasmine !== "undefined" && jasmine !== null) {
|
13544
13743
|
return register();
|
@@ -13601,31 +13800,48 @@ In an Unpoly app, every page has an URL.
|
|
13601
13800
|
})();
|
13602
13801
|
|
13603
13802
|
}).call(this);
|
13803
|
+
(function() {
|
13804
|
+
var e, u,
|
13805
|
+
slice = [].slice;
|
13604
13806
|
|
13605
|
-
|
13606
|
-
Fragment update API
|
13607
|
-
===================
|
13608
|
-
|
13609
|
-
The `up.fragment` module exposes a high-level Javascript API to [update](/up.replace) or
|
13610
|
-
[destroy](/up.destroy) page fragments.
|
13611
|
-
|
13612
|
-
Fragments are [compiled](/up.compiler) elements that can be updated from a server URL.
|
13613
|
-
They also exist on a layer (page, modal, popup).
|
13807
|
+
u = up.util;
|
13614
13808
|
|
13615
|
-
|
13616
|
-
is built from `up.fragment` functions. You may use them to extend Unpoly from your
|
13617
|
-
[custom Javascript](/up.syntax).
|
13809
|
+
e = up.element;
|
13618
13810
|
|
13619
|
-
@module up.fragment
|
13620
|
-
*/
|
13621
13811
|
|
13622
|
-
|
13623
|
-
|
13812
|
+
/***
|
13813
|
+
Fragment API
|
13814
|
+
===========
|
13815
|
+
|
13816
|
+
The `up.fragment` module offers a high-level JavaScript API to work with DOM elements.
|
13817
|
+
|
13818
|
+
A fragment is an element with some additional properties that are useful in the context of
|
13819
|
+
a server-rendered web application:
|
13820
|
+
|
13821
|
+
- Fragments are [identified by a CSS selector](/up.fragment.toTarget), like a `.class` or `#id`.
|
13822
|
+
- Fragments are usually updated by a [link](/a-up-follow) for [form](/form-up-submits) that targets their selector.
|
13823
|
+
When the server renders HTML with a matching element, the fragment is swapped with a new version.
|
13824
|
+
- As fragments enter the page they are automatically [compiled](/up.compiler) to activate JavaScript behavior.
|
13825
|
+
- Fragment changes may be [animated](/up.motion).
|
13826
|
+
- Fragments are placed on a [layer](/up.layer) that is isolated from other layers.
|
13827
|
+
Unpoly features will only see or change fragments from the [current layer](/up.layer.current)
|
13828
|
+
unless you [explicitly target another layer](/layer-option).
|
13829
|
+
- Fragments [know the URL from where they were loaded](/up.source).
|
13830
|
+
They can be [reloaded](/up.reload) or [polled periodically](/up-polled).
|
13831
|
+
|
13832
|
+
For low-level DOM utilities that complement the browser's native API, see `up.element`.
|
13833
|
+
|
13834
|
+
@see up.render
|
13835
|
+
@see up.navigate
|
13836
|
+
@see up.destroy
|
13837
|
+
@see up.reload
|
13838
|
+
@see up.fragment.get
|
13839
|
+
@see up.hello
|
13840
|
+
|
13841
|
+
@module up.fragment
|
13842
|
+
*/
|
13624
13843
|
|
13625
13844
|
up.fragment = (function() {
|
13626
|
-
var CSS_HAS_SUFFIX_PATTERN, closest, config, contains, destroy, e, emitFragmentDestroyed, emitFragmentInserted, emitFragmentKeep, emitFragmentKept, emitFromKeepPlan, expandTargets, failKey, getAll, getDumb, getSmart, getSubtree, hasAutoHistory, hello, isDestroying, isGoodClassForTarget, isNotDestroying, markFragmentAsDestroying, matches, navigate, parseSelector, parseTargetAndOptions, reload, render, renderLocalContent, renderRemoteContent, reset, resolveOriginReference, sourceOf, successKey, timeOf, toTarget, u, visit;
|
13627
|
-
u = up.util;
|
13628
|
-
e = up.element;
|
13629
13845
|
|
13630
13846
|
/***
|
13631
13847
|
Configures defaults for fragment updates.
|
@@ -13671,7 +13887,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13671
13887
|
The default configuration tries, in this order:
|
13672
13888
|
|
13673
13889
|
- If the URL has a `#hash`, scroll to the hash.
|
13674
|
-
- If updating a [main target](/main), reset scroll positions.
|
13890
|
+
- If updating a [main target](/up-main), reset scroll positions.
|
13675
13891
|
|
13676
13892
|
@param {boolean|string|Function(Element)} [config.autoFocus]
|
13677
13893
|
How to focus when updating a fragment with `{ focus: 'auto' }`.
|
@@ -13683,7 +13899,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13683
13899
|
- Focus a `#hash` in the URL.
|
13684
13900
|
- Focus an `[autofocus]` element in the new fragment.
|
13685
13901
|
- If focus was lost with the old fragment, focus the new fragment.
|
13686
|
-
- If updating a [main target](/main), focus the new fragment.
|
13902
|
+
- If updating a [main target](/up-main), focus the new fragment.
|
13687
13903
|
|
13688
13904
|
@param {boolean} [config.runScripts=false]
|
13689
13905
|
Whether to execute `<script>` tags in updated fragments.
|
@@ -13691,7 +13907,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13691
13907
|
Scripts will load asynchronously, with no guarantee of execution order.
|
13692
13908
|
|
13693
13909
|
If you set this to `true`, mind that the `<body>` element is a default
|
13694
|
-
[main target](/main). If you are including your global application scripts
|
13910
|
+
[main target](/up-main). If you are including your global application scripts
|
13695
13911
|
at the end of your `<body>`
|
13696
13912
|
for performance reasons, swapping the `<body>` will re-execute these scripts.
|
13697
13913
|
In that case you must configure a different main target that does not include
|
@@ -13699,6 +13915,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13699
13915
|
|
13700
13916
|
@stable
|
13701
13917
|
*/
|
13918
|
+
var CSS_HAS_SUFFIX_PATTERN, closest, config, contains, destroy, emitFragmentDestroyed, emitFragmentInserted, emitFragmentKeep, emitFragmentKept, emitFromKeepPlan, expandTargets, failKey, getAll, getDumb, getSmart, getSubtree, hasAutoHistory, hello, isDestroying, isGoodClassForTarget, isNotDestroying, markFragmentAsDestroying, matches, navigate, parseSelector, parseTargetAndOptions, reload, render, renderLocalContent, renderRemoteContent, reset, resolveOriginReference, sourceOf, successKey, timeOf, toTarget, visit;
|
13702
13919
|
config = new up.Config(function() {
|
13703
13920
|
return {
|
13704
13921
|
badTargetClasses: [/^up-/],
|
@@ -13719,13 +13936,8 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13719
13936
|
autoScroll: ['hash', 'layer-if-main']
|
13720
13937
|
};
|
13721
13938
|
});
|
13722
|
-
|
13723
|
-
|
13724
|
-
return up.layer.config.any.mainTargets;
|
13725
|
-
},
|
13726
|
-
set: function(value) {
|
13727
|
-
return up.layer.config.any.mainTargets = value;
|
13728
|
-
}
|
13939
|
+
u.delegate(config, 'mainTargets', function() {
|
13940
|
+
return up.layer.config.any;
|
13729
13941
|
});
|
13730
13942
|
reset = function() {
|
13731
13943
|
return config.reset();
|
@@ -13779,6 +13991,74 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13779
13991
|
return e.closestAttr(element, 'up-time') || '0';
|
13780
13992
|
};
|
13781
13993
|
|
13994
|
+
/***
|
13995
|
+
Sets the time when the fragment's underlying data was last changed.
|
13996
|
+
|
13997
|
+
This can be used to avoid rendering unchanged HTML when [reloading](/up.reload)
|
13998
|
+
a fragment. This saves <b>CPU time</b> and reduces the <b>bandwidth cost</b> for a
|
13999
|
+
request/response exchange to **~1 KB**.
|
14000
|
+
|
14001
|
+
\#\# Example
|
14002
|
+
|
14003
|
+
Let's say we display a list of recent messages.
|
14004
|
+
We use the `[up-poll]` attribute to reload the `.messages` fragment every 30 seconds:
|
14005
|
+
|
14006
|
+
```html
|
14007
|
+
<div class="messages" up-poll>
|
14008
|
+
...
|
14009
|
+
</div>
|
14010
|
+
```
|
14011
|
+
|
14012
|
+
The list is now always up to date. But most of the time there will not be new messages,
|
14013
|
+
and we waste resources sending the same unchanged HTML from the server.
|
14014
|
+
|
14015
|
+
We can improve this by setting an `[up-time]` attribute and the message list.
|
14016
|
+
The attribute value is the time of the most recent message.
|
14017
|
+
|
14018
|
+
The time is encoded as the number of seconds since [Unix epoch](https://en.wikipedia.org/wiki/Unix_time).
|
14019
|
+
When, for instance, the last message in a list was received from December 24th, 1:51:46 PM UTC,
|
14020
|
+
we use the following HTML:
|
14021
|
+
|
14022
|
+
```html
|
14023
|
+
<div class="messages" up-time="1608730818" up-poll>
|
14024
|
+
...
|
14025
|
+
</div>
|
14026
|
+
```
|
14027
|
+
|
14028
|
+
When reloading Unpoly will echo the `[up-time]` timestamp in an `X-Up-Reload-From-Time` header:
|
14029
|
+
|
14030
|
+
```http
|
14031
|
+
X-Up-Reload-From-Time: 1608730818
|
14032
|
+
```
|
14033
|
+
|
14034
|
+
The server can compare the time from the request with the time of the last data update.
|
14035
|
+
If no more recent data is available, the server can render nothing and respond with
|
14036
|
+
an [`X-Up-Target: :none`](/X-Up-Target) header.
|
14037
|
+
|
14038
|
+
Here is an example with [unpoly-rails](https://unpoly.com/install/rails):
|
14039
|
+
|
14040
|
+
```ruby
|
14041
|
+
class MessagesController < ApplicationController
|
14042
|
+
|
14043
|
+
def index
|
14044
|
+
if up.reload_from_time == current_user.last_message_at
|
14045
|
+
up.render_nothing
|
14046
|
+
else
|
14047
|
+
@messages = current_user.messages.order(time: :desc).to_a
|
14048
|
+
render 'index'
|
14049
|
+
end
|
14050
|
+
end
|
14051
|
+
|
14052
|
+
end
|
14053
|
+
```
|
14054
|
+
|
14055
|
+
@selector [up-time]
|
14056
|
+
@param {string} up-time
|
14057
|
+
The number of seconds between the [Unix epoch](https://en.wikipedia.org/wiki/Unix_time).
|
14058
|
+
and the time when the element's underlying data was last changed.
|
14059
|
+
@experimental
|
14060
|
+
*/
|
14061
|
+
|
13782
14062
|
/***
|
13783
14063
|
Sets this element's source URL for [reloading](/up.reload) and [polling](/up-poll)
|
13784
14064
|
|
@@ -13800,7 +14080,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13800
14080
|
</div>
|
13801
14081
|
|
13802
14082
|
@selector [up-source]
|
13803
|
-
@param {
|
14083
|
+
@param {string} up-source
|
13804
14084
|
The URL from which to reload this element.
|
13805
14085
|
@stable
|
13806
14086
|
*/
|
@@ -13810,7 +14090,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13810
14090
|
|
13811
14091
|
The current and new elements must both match the same CSS selector.
|
13812
14092
|
The selector is either given as `{ target }` option,
|
13813
|
-
or a [main target](/main) is used as default.
|
14093
|
+
or a [main target](/up-main) is used as default.
|
13814
14094
|
|
13815
14095
|
See the [fragment placement](/fragment-placement) selector for many examples for how you can target content.
|
13816
14096
|
|
@@ -13871,29 +14151,32 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13871
14151
|
|
13872
14152
|
@function up.render
|
13873
14153
|
|
13874
|
-
@param {string|Element|jQuery} [target]
|
14154
|
+
@param {string|Element|jQuery|Array<string>} [target]
|
13875
14155
|
The CSS selector to update.
|
13876
14156
|
|
13877
|
-
If omitted a [main target](/main) will be rendered.
|
14157
|
+
If omitted a [main target](/up-main) will be rendered.
|
13878
14158
|
|
13879
|
-
You
|
14159
|
+
You may also pass a DOM element or jQuery element here, in which case a selector
|
13880
14160
|
will be [inferred from the element attributes](/up.fragment.toTarget). The given element
|
13881
14161
|
will also be used as [`{ origin }`](#options.origin) for the fragment update.
|
13882
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
|
+
|
13883
14166
|
Instead of passing the target as the first argument, you may also pass it as
|
13884
14167
|
a [´{ target }`](#options.target) option..
|
13885
14168
|
|
13886
|
-
@param {string|Element|jQuery} [options.target]
|
14169
|
+
@param {string|Element|jQuery|Array<string>} [options.target]
|
13887
14170
|
The CSS selector to update.
|
13888
14171
|
|
13889
|
-
|
14172
|
+
See documentation for the [`target`](#target) parameter.
|
13890
14173
|
|
13891
14174
|
@param {string|boolean} [options.fallback=false]
|
13892
14175
|
Specifies behavior if the [target selector](/up.render#options.target) is missing from the current page or the server response.
|
13893
14176
|
|
13894
14177
|
If set to a CSS selector string, Unpoly will attempt to replace that selector instead.
|
13895
14178
|
|
13896
|
-
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.
|
13897
14180
|
|
13898
14181
|
If set to `false` Unpoly will immediately reject the render promise.
|
13899
14182
|
|
@@ -13973,12 +14256,12 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13973
14256
|
|
13974
14257
|
If set to `'auto'` history will be updated if the `{ target }` matches
|
13975
14258
|
a selector in `up.fragment.config.autoHistoryTargets`. By default this contains all
|
13976
|
-
[main targets](/main).
|
14259
|
+
[main targets](/up-main).
|
13977
14260
|
|
13978
14261
|
If set to `false`, the history will remain unchanged.
|
13979
14262
|
|
13980
14263
|
[Overlays](/up.layer) will only change the browser URL and window title if the overlay
|
13981
|
-
has [visible history](/up.layer.historyVisible), even
|
14264
|
+
has [visible history](/up.layer.historyVisible), even when `{ history: true }` is passed.
|
13982
14265
|
|
13983
14266
|
@param {string} [options.title]
|
13984
14267
|
An explicit document title to use after rendering.
|
@@ -14029,11 +14312,12 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
14029
14312
|
Also see [`up.request({ cache })`](/up.request#options.cache).
|
14030
14313
|
|
14031
14314
|
@param {boolean|string} [options.clearCache]
|
14032
|
-
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.
|
14033
14316
|
|
14034
|
-
By default a non-GET request will clear the entire cache.
|
14035
14317
|
You may also pass a [URL pattern](/url-patterns) to only clear matching requests.
|
14036
14318
|
|
14319
|
+
By default a non-GET request will clear the entire cache.
|
14320
|
+
|
14037
14321
|
Also see [`up.request({ clearCache })`](/up.request#options.clearCache) and `up.network.config.clearCache`.
|
14038
14322
|
|
14039
14323
|
@param {Element|jQuery} [options.origin]
|
@@ -14058,7 +14342,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
14058
14342
|
This is only relevant when updating a layer that is not the [frontmost layer](/up.layer.front).
|
14059
14343
|
|
14060
14344
|
@param {Object} [options.context]
|
14061
|
-
An object that will be merged into the [context](/
|
14345
|
+
An object that will be merged into the [context](/context) of the current layer once the fragment is rendered.
|
14062
14346
|
|
14063
14347
|
@param {boolean} [options.keep=true]
|
14064
14348
|
Whether [`[up-keep]`](/up-keep) elements will be preserved in the updated fragment.
|
@@ -14162,7 +14446,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
14162
14446
|
@param {string|Element|jQuery} [target]
|
14163
14447
|
The CSS selector to update.
|
14164
14448
|
|
14165
|
-
If omitted a [main target](/main) will be rendered.
|
14449
|
+
If omitted a [main target](/up-main) will be rendered.
|
14166
14450
|
|
14167
14451
|
You can also pass a DOM element or jQuery element here, in which case a selector
|
14168
14452
|
will be [inferred from the element attributes](/up.fragment.target). The given element
|
@@ -14192,17 +14476,19 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
14192
14476
|
an entirely different page layout (like a maintenance page or fatal server error)
|
14193
14477
|
which should be open with a full page load:
|
14194
14478
|
|
14195
|
-
|
14196
|
-
|
14479
|
+
```js
|
14480
|
+
up.on('up:fragment:loaded', (event) => {
|
14481
|
+
let isMaintenancePage = event.response.getHeader('X-Maintenance')
|
14197
14482
|
|
14198
|
-
|
14199
|
-
|
14200
|
-
|
14483
|
+
if (isMaintenancePage) {
|
14484
|
+
// Prevent the fragment update and don't update browser history
|
14485
|
+
event.preventDefault()
|
14201
14486
|
|
14202
|
-
|
14203
|
-
|
14204
|
-
|
14205
|
-
|
14487
|
+
// Make a full page load for the same request.
|
14488
|
+
event.request.loadPage()
|
14489
|
+
}
|
14490
|
+
})
|
14491
|
+
```
|
14206
14492
|
|
14207
14493
|
Instead of preventing the update, listeners may also access the `event.renderOptions` object
|
14208
14494
|
to mutate options to the `up.render()` call that will process the server response.
|
@@ -14216,6 +14502,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
14216
14502
|
The server response.
|
14217
14503
|
@param {Object} event.renderOptions
|
14218
14504
|
Options for the `up.render()` call that will process the server response.
|
14505
|
+
@stable
|
14219
14506
|
*/
|
14220
14507
|
|
14221
14508
|
/***
|
@@ -14601,7 +14888,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
14601
14888
|
- The [`up.element.all()`](/up.element.get) function simply returns the all elements matching a selector
|
14602
14889
|
without further filtering.
|
14603
14890
|
|
14604
|
-
@function up.fragment.
|
14891
|
+
@function up.fragment.all
|
14605
14892
|
|
14606
14893
|
@param {Element|jQuery} [root=document]
|
14607
14894
|
The root element for the search. Only the root's children will be matched.
|
@@ -14836,7 +15123,8 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
14836
15123
|
|
14837
15124
|
\#\#\# Skipping updates when nothing changed
|
14838
15125
|
|
14839
|
-
|
15126
|
+
You may use the `[up-time]` attribute to avoid rendering unchanged HTML when reloading
|
15127
|
+
a fragment. See `[up-time]` for a detailed example.
|
14840
15128
|
|
14841
15129
|
@function up.reload
|
14842
15130
|
@param {string|Element|jQuery} [target]
|
@@ -14914,11 +15202,12 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
14914
15202
|
|
14915
15203
|
\#\#\# Example
|
14916
15204
|
|
14917
|
-
|
14918
|
-
|
14919
|
-
|
15205
|
+
```js
|
15206
|
+
element = up.element.createFromHTML('<span class="klass">...</span>')
|
15207
|
+
selector = up.fragment.toTarget(element) // returns '.klass'
|
15208
|
+
```
|
14920
15209
|
|
14921
|
-
@function up.
|
15210
|
+
@function up.fragment.toTarget
|
14922
15211
|
@param {string|Element|jQuery}
|
14923
15212
|
The element for which to create a selector.
|
14924
15213
|
@stable
|
@@ -14941,7 +15230,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
14941
15230
|
selector = '';
|
14942
15231
|
for (i = 0, len = goodClasses.length; i < len; i++) {
|
14943
15232
|
klass = goodClasses[i];
|
14944
|
-
selector +=
|
15233
|
+
selector += e.classSelector(klass);
|
14945
15234
|
}
|
14946
15235
|
return selector;
|
14947
15236
|
} else {
|
@@ -15091,10 +15380,13 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
15091
15380
|
When no other render target is given, Unpoly will try to find and replace a main target.
|
15092
15381
|
|
15093
15382
|
In most app layouts the main target should match the primary content area.
|
15094
|
-
The default main targets are
|
15095
|
-
|
15096
|
-
|
15097
|
-
|
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`.
|
15098
15390
|
|
15099
15391
|
\#\#\# Example
|
15100
15392
|
|
@@ -15106,6 +15398,86 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
15106
15398
|
@experimental
|
15107
15399
|
*/
|
15108
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
|
+
|
15109
15481
|
/***
|
15110
15482
|
To make a server request without changing a fragment, use the `:none` selector.
|
15111
15483
|
|
@@ -15150,7 +15522,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
15150
15522
|
For the [root layer](/up.layer.root) it is the `<body>` element. For an overlay
|
15151
15523
|
it is the target with which the overlay was opened with.
|
15152
15524
|
|
15153
|
-
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).
|
15154
15526
|
|
15155
15527
|
\#\#\# Example
|
15156
15528
|
|
@@ -15247,36 +15619,39 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
15247
15619
|
|
15248
15620
|
up.visit = up.fragment.visit;
|
15249
15621
|
|
15622
|
+
|
15623
|
+
/***
|
15624
|
+
Returns the current [context](/context).
|
15625
|
+
|
15626
|
+
This is aliased as `up.layer.context`.
|
15627
|
+
|
15628
|
+
@property up.context
|
15629
|
+
@param {Object} context
|
15630
|
+
The context object.
|
15631
|
+
|
15632
|
+
If no context has been set an empty object is returned.
|
15633
|
+
@experimental
|
15634
|
+
*/
|
15635
|
+
|
15636
|
+
u.delegate(up, 'context', function() {
|
15637
|
+
return up.layer.current;
|
15638
|
+
});
|
15639
|
+
|
15250
15640
|
}).call(this);
|
15251
15641
|
|
15252
15642
|
/***
|
15253
15643
|
Scrolling viewports
|
15254
15644
|
===================
|
15255
15645
|
|
15256
|
-
The `up.viewport` module controls the scroll position
|
15646
|
+
The `up.viewport` module controls the scroll position and focus within scrollable containers ("viewports").
|
15257
15647
|
|
15258
15648
|
The default viewport for any web application is the main document. An application may
|
15259
15649
|
define additional viewports by giving the CSS property `{ overflow-y: scroll }` to any `<div>`.
|
15260
15650
|
|
15651
|
+
Also see documentation for the [scroll option](/scroll-option) and [focus option](focus-option).
|
15261
15652
|
|
15262
|
-
|
15263
|
-
|
15264
|
-
When following a [link to a fragment](/a-up-follow) Unpoly will automatically
|
15265
|
-
scroll the document's viewport to [reveal](/up.viewport) the updated content.
|
15266
|
-
|
15267
|
-
You should [make Unpoly aware](/up.viewport.config#config.fixedTop) of fixed elements in your
|
15268
|
-
layout, such as navigation bars or headers. Unpoly will respect these sticky
|
15269
|
-
elements when [revealing updated fragments](/up.reveal).
|
15270
|
-
|
15271
|
-
You should also [tell Unpoly](/up.viewport.config#config.viewportSelectors) when your application has more than one viewport,
|
15272
|
-
so Unpoly can pick the right viewport to scroll for each fragment update.
|
15273
|
-
|
15274
|
-
|
15275
|
-
\#\#\# Bootstrap integration
|
15276
|
-
|
15277
|
-
When using Bootstrap integration (`unpoly-bootstrap3.js` and `unpoly-bootstrap3.css`)
|
15278
|
-
Unpoly will automatically be aware of sticky Bootstrap components such as
|
15279
|
-
[fixed navbar](https://getbootstrap.com/examples/navbar-fixed-top/).
|
15653
|
+
@see up.reveal
|
15654
|
+
@see [up-fixed=top]
|
15280
15655
|
|
15281
15656
|
@module up.viewport
|
15282
15657
|
*/
|
@@ -15285,29 +15660,31 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15285
15660
|
var slice = [].slice;
|
15286
15661
|
|
15287
15662
|
up.viewport = (function() {
|
15288
|
-
var absolutize, allSelector, anchoredRight,
|
15663
|
+
var absolutize, allSelector, anchoredRight, closest, config, doFocus, e, f, firstHashTarget, fixedElements, getAll, getAround, getRoot, getScrollTops, getSubtree, isNativelyFocusable, isRoot, makeFocusable, parseOptions, pureHash, reset, resetScroll, restoreScroll, reveal, revealHash, rootHasReducedWidthFromScrollbar, rootHeight, rootOverflowElement, rootSelector, rootWidth, saveScroll, scroll, scrollTopKey, scrollTops, scrollbarWidth, scrollingController, setScrollTops, tryFocus, u, userScrolled, wasChosenAsOverflowingElement;
|
15289
15664
|
u = up.util;
|
15290
15665
|
e = up.element;
|
15291
15666
|
f = up.fragment;
|
15292
15667
|
|
15293
15668
|
/***
|
15294
|
-
Configures
|
15669
|
+
Configures defaults for scrolling.
|
15295
15670
|
|
15296
15671
|
@property up.viewport.config
|
15297
15672
|
@param {Array} [config.viewportSelectors]
|
15298
|
-
An array of CSS selectors that
|
15299
|
-
(containers that scroll their contents).
|
15673
|
+
An array of CSS selectors that match viewports.
|
15300
15674
|
@param {Array} [config.fixedTop]
|
15301
15675
|
An array of CSS selectors that find elements fixed to the
|
15302
15676
|
top edge of the screen (using `position: fixed`).
|
15677
|
+
|
15303
15678
|
See [`[up-fixed="top"]`](/up-fixed-top) for details.
|
15304
15679
|
@param {Array} [config.fixedBottom]
|
15305
|
-
An array of CSS selectors that
|
15680
|
+
An array of CSS selectors that match elements fixed to the
|
15306
15681
|
bottom edge of the screen (using `position: fixed`).
|
15682
|
+
|
15307
15683
|
See [`[up-fixed="bottom"]`](/up-fixed-bottom) for details.
|
15308
15684
|
@param {Array} [config.anchoredRight]
|
15309
15685
|
An array of CSS selectors that find elements anchored to the
|
15310
15686
|
right edge of the screen (using `right:0` with `position: fixed` or `position: absolute`).
|
15687
|
+
|
15311
15688
|
See [`[up-anchored="right"]`](/up-anchored-right) for details.
|
15312
15689
|
@param {number} [config.revealSnap]
|
15313
15690
|
When [revealing](/up.reveal) elements, Unpoly will scroll an viewport
|
@@ -15421,19 +15798,9 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15421
15798
|
};
|
15422
15799
|
|
15423
15800
|
/***
|
15424
|
-
|
15801
|
+
Scrolls the given element's viewport so the first rows of the
|
15425
15802
|
element are visible for the user.
|
15426
15803
|
|
15427
|
-
\#\#\# How Unpoly finds the viewport
|
15428
|
-
|
15429
|
-
The viewport (the container that is going to be scrolled)
|
15430
|
-
is the closest parent of the element that is either:
|
15431
|
-
|
15432
|
-
- the currently open [modal](/up.modal)
|
15433
|
-
- an element with the attribute `[up-viewport]`
|
15434
|
-
- the `<body>` element
|
15435
|
-
- an element matching the selector you have configured using `up.viewport.config.viewportSelectors.push('my-custom-selector')`
|
15436
|
-
|
15437
15804
|
\#\#\# Fixed elements obstructing the viewport
|
15438
15805
|
|
15439
15806
|
Many applications have a navigation bar fixed to the top or bottom,
|
@@ -15441,14 +15808,16 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15441
15808
|
|
15442
15809
|
You can make `up.reveal()` aware of these fixed elements
|
15443
15810
|
so it can scroll the viewport far enough so the revealed element is fully visible.
|
15444
|
-
To make `up.reveal()` aware fixed elements you can either:
|
15811
|
+
To make `up.reveal()` aware of fixed elements you can either:
|
15445
15812
|
|
15446
15813
|
- give the element an attribute [`up-fixed="top"`](/up-fixed-top) or [`up-fixed="bottom"`](up-fixed-bottom)
|
15447
15814
|
- [configure default options](/up.viewport.config) for `fixedTop` or `fixedBottom`
|
15448
15815
|
|
15449
15816
|
@function up.reveal
|
15817
|
+
|
15450
15818
|
@param {string|Element|jQuery} element
|
15451
15819
|
The element to reveal.
|
15820
|
+
|
15452
15821
|
@param {number} [options.scrollSpeed=1]
|
15453
15822
|
The speed of the scrolling motion when scrolling with `{ behavior: 'smooth' }`.
|
15454
15823
|
|
@@ -15456,6 +15825,7 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15456
15825
|
[native smooth scrolling](https://developer.mozilla.org/en-US/docs/Web/API/ScrollToOptions/behavior).
|
15457
15826
|
|
15458
15827
|
Defaults to `up.viewport.config.scrollSpeed`.
|
15828
|
+
|
15459
15829
|
@param {string} [options.revealSnap]
|
15460
15830
|
When the the revealed element would be closer to the viewport's top edge
|
15461
15831
|
than this value, Unpoly will scroll the viewport to the top.
|
@@ -15463,35 +15833,40 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15463
15833
|
Set to `0` to disable snapping.
|
15464
15834
|
|
15465
15835
|
Defaults to `up.viewport.config.revealSnap`.
|
15836
|
+
|
15466
15837
|
@param {string|Element|jQuery} [options.viewport]
|
15467
15838
|
The scrolling element to scroll.
|
15468
15839
|
|
15469
15840
|
Defaults to the [given element's viewport](/up.viewport.closest).
|
15841
|
+
|
15470
15842
|
@param {boolean} [options.top]
|
15471
15843
|
Whether to scroll the viewport so that the first element row aligns
|
15472
15844
|
with the top edge of the viewport.
|
15473
15845
|
|
15474
15846
|
Defaults to `up.viewport.config.revealTop`.
|
15847
|
+
|
15475
15848
|
@param {string}[options.behavior='auto']
|
15476
15849
|
When set to `'auto'`, this will immediately scroll to the new position.
|
15477
15850
|
|
15478
15851
|
When set to `'smooth'`, this will scroll smoothly to the new position.
|
15852
|
+
|
15479
15853
|
@param {number}[options.speed]
|
15480
15854
|
The speed of the scrolling motion when scrolling with `{ behavior: 'smooth' }`.
|
15481
15855
|
|
15482
15856
|
Defaults to `up.viewport.config.scrollSpeed`.
|
15857
|
+
|
15483
15858
|
@param {number} [options.padding]
|
15484
15859
|
The desired padding between the revealed element and the
|
15485
15860
|
closest [viewport](/up.viewport) edge (in pixels).
|
15486
15861
|
|
15487
15862
|
Defaults to `up.viewport.config.revealPadding`.
|
15863
|
+
|
15488
15864
|
@param {number|boolean} [options.snap]
|
15489
15865
|
Whether to snap to the top of the viewport if the new scroll position
|
15490
15866
|
after revealing the element is close to the top edge.
|
15491
15867
|
|
15492
15868
|
Defaults to `up.viewport.config.revealSnap`.
|
15493
|
-
|
15494
|
-
Whether to close overlays obscuring the layer of `element`.
|
15869
|
+
|
15495
15870
|
@return {Promise}
|
15496
15871
|
A promise that fulfills when the element is revealed.
|
15497
15872
|
|
@@ -15500,13 +15875,12 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15500
15875
|
|
15501
15876
|
When the scrolling is not animated, the promise will fulfill
|
15502
15877
|
in the next [microtask](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/).
|
15878
|
+
|
15503
15879
|
@stable
|
15504
15880
|
*/
|
15505
15881
|
reveal = function(element, options) {
|
15506
15882
|
var motion;
|
15507
|
-
options = u.options(options
|
15508
|
-
peel: true
|
15509
|
-
});
|
15883
|
+
options = u.options(options);
|
15510
15884
|
element = f.get(element, options);
|
15511
15885
|
if (!(options.layer = up.layer.get(element))) {
|
15512
15886
|
return up.error.failed.async('Cannot reveal a detached element');
|
@@ -15519,7 +15893,19 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15519
15893
|
};
|
15520
15894
|
|
15521
15895
|
/***
|
15522
|
-
|
15896
|
+
Focuses the given element.
|
15897
|
+
|
15898
|
+
Focusing an element will also [reveal](/up.reveal) it, unless `{ preventScroll: true }` is passed.
|
15899
|
+
|
15900
|
+
@function up.focus
|
15901
|
+
|
15902
|
+
@param {string|Element|jQuery} element
|
15903
|
+
The element to focus.
|
15904
|
+
|
15905
|
+
@param {[options.preventScroll=false]}
|
15906
|
+
Whether to prevent changes to the acroll position.
|
15907
|
+
|
15908
|
+
@experimental
|
15523
15909
|
*/
|
15524
15910
|
doFocus = function(element, options) {
|
15525
15911
|
var oldScrollTop, viewport;
|
@@ -15544,13 +15930,6 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15544
15930
|
doFocus(element, options);
|
15545
15931
|
return element === document.activeElement;
|
15546
15932
|
};
|
15547
|
-
autofocus = function(element, options) {
|
15548
|
-
var autofocusElement;
|
15549
|
-
if (autofocusElement = e.subtree(element, '[autofocus]')[0]) {
|
15550
|
-
doDocus(autofocusElement, options);
|
15551
|
-
return true;
|
15552
|
-
}
|
15553
|
-
};
|
15554
15933
|
isNativelyFocusable = function(element) {
|
15555
15934
|
return e.matches(element, 'a[href], button, textarea, input, select');
|
15556
15935
|
};
|
@@ -15620,6 +15999,9 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15620
15999
|
Returns a list of all the viewports contained within the
|
15621
16000
|
given selector or element.
|
15622
16001
|
|
16002
|
+
If the given element is itself a viewport, the element is included
|
16003
|
+
in the returned list.
|
16004
|
+
|
15623
16005
|
@function up.viewport.subtree
|
15624
16006
|
@param {string|Element|jQuery} target
|
15625
16007
|
@param {Object} options
|
@@ -15812,30 +16194,11 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15812
16194
|
|
15813
16195
|
The scroll positions will be associated with the current URL.
|
15814
16196
|
They can later be restored by calling [`up.viewport.restoreScroll()`](/up.viewport.restoreScroll)
|
15815
|
-
at the same URL, or by following a link with an [`[
|
16197
|
+
at the same URL, or by following a link with an [`[scroll="restore"]`](/a-up-follow#up-restore-scroll)
|
15816
16198
|
attribute.
|
15817
16199
|
|
15818
|
-
Unpoly automatically saves scroll positions before
|
15819
|
-
|
15820
|
-
|
15821
|
-
\#\#\# Examples
|
15822
|
-
|
15823
|
-
Should you need to save the current scroll positions outside of a [fragment update](/up.replace),
|
15824
|
-
you may call:
|
15825
|
-
|
15826
|
-
up.viewport.saveScroll()
|
15827
|
-
|
15828
|
-
Instead of saving the current scroll positions for the current URL, you may also pass another
|
15829
|
-
url or vertical scroll positionsfor each viewport:
|
15830
|
-
|
15831
|
-
up.viewport.saveScroll({
|
15832
|
-
url: '/inbox',
|
15833
|
-
tops: {
|
15834
|
-
'body': 0,
|
15835
|
-
'.sidebar', 100,
|
15836
|
-
'.main', 320
|
15837
|
-
}
|
15838
|
-
})
|
16200
|
+
Unpoly automatically saves scroll positions before [navigating](/navigation).
|
16201
|
+
You will rarely need to call this function yourself.
|
15839
16202
|
|
15840
16203
|
@function up.viewport.saveScroll
|
15841
16204
|
@param {string} [options.location]
|
@@ -16162,7 +16525,6 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
16162
16525
|
absolutize: absolutize,
|
16163
16526
|
focus: doFocus,
|
16164
16527
|
tryFocus: tryFocus,
|
16165
|
-
autofocus: autofocus,
|
16166
16528
|
makeFocusable: makeFocusable
|
16167
16529
|
});
|
16168
16530
|
})();
|
@@ -16181,11 +16543,16 @@ Animation
|
|
16181
16543
|
|
16182
16544
|
When you [update a page fragment](/up.link) you can animate the change.
|
16183
16545
|
|
16184
|
-
|
16185
|
-
|
16186
|
-
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:
|
16187
16548
|
|
16188
|
-
|
16549
|
+
```html
|
16550
|
+
<a href="/users"
|
16551
|
+
up-target=".list"
|
16552
|
+
up-transition="cross-fade">
|
16553
|
+
Show users
|
16554
|
+
</a>
|
16555
|
+
```
|
16189
16556
|
|
16190
16557
|
\#\#\# Transitions vs. animations
|
16191
16558
|
|
@@ -16193,10 +16560,17 @@ When we morph between an old and a new element, we call it a *transition*.
|
|
16193
16560
|
In contrast, when we animate a new element without simultaneously removing an
|
16194
16561
|
old element, we call it an *animation*.
|
16195
16562
|
|
16196
|
-
An example for an animation is opening a new
|
16197
|
-
of the dialog by adding an [`[up-animation]`](/a-up-
|
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:
|
16198
16565
|
|
16199
|
-
|
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
|
+
```
|
16200
16574
|
|
16201
16575
|
\#\#\# Which animations are available?
|
16202
16576
|
|
@@ -16206,12 +16580,16 @@ and [predefined animations](/up.animate#named-animations).
|
|
16206
16580
|
You can define custom animations using `up.transition()` and
|
16207
16581
|
`up.animation()`.
|
16208
16582
|
|
16583
|
+
@see a[up-transition]
|
16584
|
+
@see up.animation
|
16585
|
+
@see up.transition
|
16586
|
+
|
16209
16587
|
@module up.motion
|
16210
16588
|
*/
|
16211
16589
|
|
16212
16590
|
(function() {
|
16213
16591
|
up.motion = (function() {
|
16214
|
-
var
|
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;
|
16215
16593
|
u = up.util;
|
16216
16594
|
e = up.element;
|
16217
16595
|
namedAnimations = {};
|
@@ -16229,9 +16607,12 @@ You can define custom animations using `up.transition()` and
|
|
16229
16607
|
|
16230
16608
|
See [W3C documentation](http://www.w3.org/TR/css3-transitions/#transition-timing-function)
|
16231
16609
|
for a list of pre-defined timing functions.
|
16232
|
-
@param {boolean} [config.enabled
|
16610
|
+
@param {boolean} [config.enabled]
|
16233
16611
|
Whether animation is enabled.
|
16234
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
|
+
|
16235
16616
|
Set this to `false` to disable animation globally.
|
16236
16617
|
This can be useful in full-stack integration tests.
|
16237
16618
|
@stable
|
@@ -16273,15 +16654,19 @@ You can define custom animations using `up.transition()` and
|
|
16273
16654
|
|
16274
16655
|
\#\#\# Example
|
16275
16656
|
|
16276
|
-
|
16657
|
+
```js
|
16658
|
+
up.animate('.warning', 'fade-in')
|
16659
|
+
```
|
16277
16660
|
|
16278
16661
|
You can pass additional options:
|
16279
16662
|
|
16280
|
-
|
16281
|
-
|
16282
|
-
|
16283
|
-
|
16284
|
-
|
16663
|
+
```
|
16664
|
+
up.animate('.warning', 'fade-in', {
|
16665
|
+
delay: 1000,
|
16666
|
+
duration: 250,
|
16667
|
+
easing: 'linear'
|
16668
|
+
})
|
16669
|
+
```
|
16285
16670
|
|
16286
16671
|
\#\#\# Named animations
|
16287
16672
|
|
@@ -16306,9 +16691,11 @@ You can define custom animations using `up.transition()` and
|
|
16306
16691
|
By passing an object instead of an animation name, you can animate
|
16307
16692
|
the CSS properties of the given element:
|
16308
16693
|
|
16309
|
-
|
16310
|
-
|
16311
|
-
|
16694
|
+
```
|
16695
|
+
var warning = document.querySelector('.warning')
|
16696
|
+
warning.style.opacity = 0
|
16697
|
+
up.animate(warning, { opacity: 1 })
|
16698
|
+
```
|
16312
16699
|
|
16313
16700
|
CSS properties must be given in `kebab-case`, not `camelCase`.
|
16314
16701
|
|
@@ -16344,7 +16731,6 @@ You can define custom animations using `up.transition()` and
|
|
16344
16731
|
var animationFn, runNow, willRun;
|
16345
16732
|
element = up.fragment.get(element);
|
16346
16733
|
options = u.options(options);
|
16347
|
-
applyConfig(options);
|
16348
16734
|
animationFn = findAnimationFn(animation);
|
16349
16735
|
willRun = willAnimate(element, animation, options);
|
16350
16736
|
if (willRun) {
|
@@ -16357,6 +16743,7 @@ You can define custom animations using `up.transition()` and
|
|
16357
16743
|
}
|
16358
16744
|
};
|
16359
16745
|
willAnimate = function(element, animationOrTransition, options) {
|
16746
|
+
applyConfig(options);
|
16360
16747
|
return isEnabled() && !isNone(animationOrTransition) && options.duration > 0 && !e.isSingleton(element);
|
16361
16748
|
};
|
16362
16749
|
skipAnimate = function(element, animation) {
|
@@ -16365,7 +16752,6 @@ You can define custom animations using `up.transition()` and
|
|
16365
16752
|
}
|
16366
16753
|
return Promise.resolve();
|
16367
16754
|
};
|
16368
|
-
animCount = 0;
|
16369
16755
|
|
16370
16756
|
/***
|
16371
16757
|
Animates the given element's CSS properties using CSS transitions.
|
@@ -16415,7 +16801,7 @@ You can define custom animations using `up.transition()` and
|
|
16415
16801
|
Animations are completed by jumping to the last animation frame instantly.
|
16416
16802
|
Promises returned by animation and transition functions instantly settle.
|
16417
16803
|
|
16418
|
-
Emits the `up:motion:finish` event that is
|
16804
|
+
Emits the `up:motion:finish` event that is handled by `up.animate()`.
|
16419
16805
|
|
16420
16806
|
Does nothing if there are no animation to complete.
|
16421
16807
|
|
@@ -16613,18 +16999,20 @@ You can define custom animations using `up.transition()` and
|
|
16613
16999
|
});
|
16614
17000
|
|
16615
17001
|
/***
|
16616
|
-
Defines a named transition that [morphs](/up.
|
17002
|
+
Defines a named transition that [morphs](/up.morph) from one element to another.
|
16617
17003
|
|
16618
17004
|
\#\#\# Example
|
16619
17005
|
|
16620
17006
|
Here is the definition of the pre-defined `cross-fade` animation:
|
16621
17007
|
|
16622
|
-
|
16623
|
-
|
16624
|
-
|
16625
|
-
|
16626
|
-
|
16627
|
-
|
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
|
+
```
|
16628
17016
|
|
16629
17017
|
It is recommended that your transitions use [`up.animate()`](/up.animate),
|
16630
17018
|
passing along the `options` that were passed to you.
|
@@ -16659,10 +17047,12 @@ You can define custom animations using `up.transition()` and
|
|
16659
17047
|
|
16660
17048
|
Here is the definition of the pre-defined `fade-in` animation:
|
16661
17049
|
|
16662
|
-
|
16663
|
-
|
16664
|
-
|
16665
|
-
|
17050
|
+
```js
|
17051
|
+
up.animation('fade-in', function(element, options) {
|
17052
|
+
element.style.opacity = 0
|
17053
|
+
up.animate(element, { opacity: 1 }, options)
|
17054
|
+
})
|
17055
|
+
```
|
16666
17056
|
|
16667
17057
|
It is recommended that your definitions always end by calling
|
16668
17058
|
calling [`up.animate()`](/up.animate) with an object argument, passing along
|
@@ -16671,7 +17061,7 @@ You can define custom animations using `up.transition()` and
|
|
16671
17061
|
If you choose to *not* use `up.animate()` and roll your own
|
16672
17062
|
animation code instead, your code must honor the following contract:
|
16673
17063
|
|
16674
|
-
1. It must honor the options `{ duration, easing }
|
17064
|
+
1. It must honor the options `{ duration, easing }`, if given.
|
16675
17065
|
2. It must *not* remove any of the given elements from the DOM.
|
16676
17066
|
3. It returns a promise that is fulfilled when the transition has ended
|
16677
17067
|
4. If during the animation an event `up:motion:finish` is emitted on
|
@@ -16730,7 +17120,7 @@ You can define custom animations using `up.transition()` and
|
|
16730
17120
|
e.setStyle(element, translateCSS(0, 0));
|
16731
17121
|
return element.getBoundingClientRect();
|
16732
17122
|
};
|
16733
|
-
|
17123
|
+
registerMoveAnimations = function(direction, boxToTransform) {
|
16734
17124
|
var animationFromName, animationToName;
|
16735
17125
|
animationToName = "move-to-" + direction;
|
16736
17126
|
animationFromName = "move-from-" + direction;
|
@@ -16748,22 +17138,22 @@ You can define custom animations using `up.transition()` and
|
|
16748
17138
|
return animateNow(element, translateCSS(0, 0), options);
|
16749
17139
|
});
|
16750
17140
|
};
|
16751
|
-
|
17141
|
+
registerMoveAnimations('top', function(box) {
|
16752
17142
|
var travelDistance;
|
16753
17143
|
travelDistance = box.top + box.height;
|
16754
17144
|
return translateCSS(0, -travelDistance);
|
16755
17145
|
});
|
16756
|
-
|
17146
|
+
registerMoveAnimations('bottom', function(box) {
|
16757
17147
|
var travelDistance;
|
16758
17148
|
travelDistance = up.viewport.rootHeight() - box.top;
|
16759
17149
|
return translateCSS(0, travelDistance);
|
16760
17150
|
});
|
16761
|
-
|
17151
|
+
registerMoveAnimations('left', function(box) {
|
16762
17152
|
var travelDistance;
|
16763
17153
|
travelDistance = box.left + box.width;
|
16764
17154
|
return translateCSS(-travelDistance, 0);
|
16765
17155
|
});
|
16766
|
-
|
17156
|
+
registerMoveAnimations('right', function(box) {
|
16767
17157
|
var travelDistance;
|
16768
17158
|
travelDistance = up.viewport.rootWidth() - box.left;
|
16769
17159
|
return translateCSS(travelDistance, 0);
|
@@ -16778,10 +17168,17 @@ You can define custom animations using `up.transition()` and
|
|
16778
17168
|
[Follows](/a-up-follow) this link and swaps in the new fragment
|
16779
17169
|
with an animated transition.
|
16780
17170
|
|
17171
|
+
Note that transitions are not possible when replacing the `body`
|
17172
|
+
element.
|
17173
|
+
|
16781
17174
|
\#\#\# Example
|
16782
17175
|
|
16783
17176
|
```html
|
16784
|
-
<a href="/page2"
|
17177
|
+
<a href="/page2"
|
17178
|
+
up-target=".story"
|
17179
|
+
up-transition="move-left">
|
17180
|
+
Next page
|
17181
|
+
</a>
|
16785
17182
|
```
|
16786
17183
|
|
16787
17184
|
@selector a[up-transition]
|
@@ -16793,6 +17190,7 @@ You can define custom animations using `up.transition()` and
|
|
16793
17190
|
The transition to use when the server responds with an error code.
|
16794
17191
|
|
16795
17192
|
@see server-errors
|
17193
|
+
@stable
|
16796
17194
|
*/
|
16797
17195
|
|
16798
17196
|
/***
|
@@ -16802,7 +17200,9 @@ You can define custom animations using `up.transition()` and
|
|
16802
17200
|
\#\#\# Example
|
16803
17201
|
|
16804
17202
|
```html
|
16805
|
-
<form action="/tasks"
|
17203
|
+
<form action="/tasks"
|
17204
|
+
up-target=".content"
|
17205
|
+
up-transition="cross-fade">
|
16806
17206
|
...
|
16807
17207
|
</form>
|
16808
17208
|
```
|
@@ -16816,6 +17216,7 @@ You can define custom animations using `up.transition()` and
|
|
16816
17216
|
The transition to use when the server responds with an error code.
|
16817
17217
|
|
16818
17218
|
@see server-errors
|
17219
|
+
@stable
|
16819
17220
|
*/
|
16820
17221
|
up.on('up:framework:boot', warnIfDisabled);
|
16821
17222
|
up.on('up:framework:reset', reset);
|
@@ -16856,43 +17257,25 @@ You can define custom animations using `up.transition()` and
|
|
16856
17257
|
Network requests
|
16857
17258
|
================
|
16858
17259
|
|
16859
|
-
|
16860
|
-
|
16861
|
-
Unpoly comes with a number of tricks to shorten the latency between browser and server.
|
16862
|
-
|
16863
|
-
\#\#\# Server responses are cached by default
|
16864
|
-
|
16865
|
-
Unpoly caches server responses for a few minutes,
|
16866
|
-
making requests to these URLs return instantly.
|
16867
|
-
All Unpoly functions and selectors go through this cache, unless
|
16868
|
-
you explicitly pass a `{ cache: false }` option or set an `up-cache="false"` attribute.
|
16869
|
-
|
16870
|
-
The cache holds up to 50 responses for 5 minutes. You can configure the cache size and expiry using
|
16871
|
-
[`up.network.config`](/up.network.config), or clear the cache manually using [`up.cache.clear()`](/up.cache.clear).
|
16872
|
-
|
16873
|
-
Also the entire cache is cleared with every non-`GET` request (like `POST` or `PUT`).
|
17260
|
+
Unpoly ships with an optimized HTTP client for fast and effective
|
17261
|
+
communication with your server-side app.
|
16874
17262
|
|
16875
|
-
|
16876
|
-
|
17263
|
+
While you can use the browser's native `fetch()` function,
|
17264
|
+
Unpoly's `up.request()` has a number of convenience features:
|
16877
17265
|
|
16878
|
-
|
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.
|
16879
17275
|
|
16880
|
-
|
16881
|
-
|
16882
|
-
|
16883
|
-
the user releases the mouse/finger.
|
16884
|
-
|
16885
|
-
\#\#\# Spinners
|
16886
|
-
|
16887
|
-
You can listen to the [`up:request:late`](/up:request:late) event to implement a spinner
|
16888
|
-
that appears during a long-running request.
|
16889
|
-
|
16890
|
-
\#\#\# More acceleration
|
16891
|
-
|
16892
|
-
Other Unpoly modules contain even more tricks to outsmart network latency:
|
16893
|
-
|
16894
|
-
- [Instantaneous feedback for links that are currently loading](/a.up-active)
|
16895
|
-
- [Follow links on `mousedown` instead of `click`](/a-up-instant)
|
17276
|
+
@see up.request
|
17277
|
+
@see up.Response
|
17278
|
+
@see up:request:late
|
16896
17279
|
|
16897
17280
|
@module up.network
|
16898
17281
|
*/
|
@@ -16910,8 +17293,8 @@ You can define custom animations using `up.transition()` and
|
|
16910
17293
|
Additional requests are queued. [Preload](/a-up-preload) requests are
|
16911
17294
|
always queued behind non-preload requests.
|
16912
17295
|
|
16913
|
-
You might find it useful to set the request concurrency `1` in
|
16914
|
-
|
17296
|
+
You might find it useful to set the request concurrency `1` in end-to-end tests
|
17297
|
+
to prevent race conditions.
|
16915
17298
|
|
16916
17299
|
Note that your browser might [impose its own request limit](http://www.browserscope.org/?category=network)
|
16917
17300
|
regardless of what you configure here.
|
@@ -17013,7 +17396,7 @@ You can define custom animations using `up.transition()` and
|
|
17013
17396
|
|
17014
17397
|
@stable
|
17015
17398
|
*/
|
17016
|
-
var abortRequests, cache, config, handleCaching, isBusy, isIdle, isSafeMethod, makeRequest, mimicLocalRequest, parseRequestOptions,
|
17399
|
+
var abortRequests, cache, config, handleCaching, isBusy, isIdle, isSafeMethod, makeRequest, mimicLocalRequest, parseRequestOptions, queue, queueRequest, registerAliasForRedirect, reset, shouldReduceRequests, useCachedRequest;
|
17017
17400
|
config = new up.Config(function() {
|
17018
17401
|
return {
|
17019
17402
|
concurrency: 4,
|
@@ -17071,13 +17454,24 @@ You can define custom animations using `up.transition()` and
|
|
17071
17454
|
/***
|
17072
17455
|
Removes all [cache](/up.cache.get) entries.
|
17073
17456
|
|
17074
|
-
|
17075
|
-
|
17076
|
-
|
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`.
|
17077
17467
|
|
17078
17468
|
The server may also clear the cache by sending an [`X-Up-Cache: clear`](/X-Up-Cache) header.
|
17079
17469
|
|
17080
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.
|
17081
17475
|
@stable
|
17082
17476
|
*/
|
17083
17477
|
|
@@ -17135,39 +17529,45 @@ You can define custom animations using `up.transition()` and
|
|
17135
17529
|
Makes an AJAX request to the given URL.
|
17136
17530
|
|
17137
17531
|
Returns an `up.Request` object which contains information about the request.
|
17138
|
-
|
17532
|
+
This request object is also a promise for an `up.Response` that contains
|
17533
|
+
the response text, headers, etc.
|
17139
17534
|
|
17140
17535
|
\#\#\# Example
|
17141
17536
|
|
17142
|
-
|
17143
|
-
|
17537
|
+
```js
|
17538
|
+
let request = up.request('/search', { params: { query: 'sunshine' } })
|
17539
|
+
console.log('We made a request to', request.url)
|
17144
17540
|
|
17145
|
-
|
17146
|
-
|
17541
|
+
let response = await request
|
17542
|
+
console.log('The response text is', response.text)
|
17543
|
+
```
|
17147
17544
|
|
17148
17545
|
\#\#\# Error handling
|
17149
17546
|
|
17150
17547
|
The returned promise will fulfill with an `up.Response` when the server
|
17151
17548
|
responds with an HTTP status of 2xx (like `200`).
|
17152
17549
|
|
17153
|
-
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
|
17154
17551
|
will *reject* with `up.Response`.
|
17155
17552
|
|
17156
17553
|
When the request fails from a fatal error (like a timeout or loss of connectivity),
|
17157
17554
|
the promise will reject with an [`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) object.
|
17158
17555
|
|
17159
|
-
Here is an example for a complete control flow that
|
17556
|
+
Here is an example for a complete control flow that handles both HTTP error codes
|
17557
|
+
and fatal errors:
|
17160
17558
|
|
17161
|
-
|
17162
|
-
|
17163
|
-
|
17164
|
-
|
17165
|
-
|
17166
|
-
|
17167
|
-
|
17168
|
-
|
17169
|
-
|
17170
|
-
|
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
|
+
```
|
17171
17571
|
|
17172
17572
|
\#\#\# Caching
|
17173
17573
|
|
@@ -17210,10 +17610,13 @@ You can define custom animations using `up.transition()` and
|
|
17210
17610
|
|
17211
17611
|
With `{ cache: false }` (the default) Unpoly will always make a network request.
|
17212
17612
|
|
17213
|
-
@param {boolean} [options.clearCache]
|
17214
|
-
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.
|
17615
|
+
|
17616
|
+
You may also pass a [URL pattern](/url-patterns) to only clear matching requests.
|
17215
17617
|
|
17216
|
-
Defaults to the result of `up.network.config.clearCache
|
17618
|
+
Defaults to the result of `up.network.config.clearCache`, which
|
17619
|
+
defaults to clearing the entire cache after a non-GET request.
|
17217
17620
|
|
17218
17621
|
@param {Object} [options.headers={}]
|
17219
17622
|
An object of additional HTTP headers.
|
@@ -17238,13 +17641,13 @@ You can define custom animations using `up.transition()` and
|
|
17238
17641
|
@param {string} [options.target='body']
|
17239
17642
|
The CSS selector that will be sent as an `X-Up-Target` header.
|
17240
17643
|
|
17241
|
-
@param {string} [options.layer='current']
|
17242
|
-
The [layer](/up.layer) this request is associated with.
|
17243
|
-
|
17244
17644
|
@param {string} [options.failTarget='body']
|
17245
17645
|
The CSS selector that will be sent as an `X-Up-Fail-Target` header.
|
17246
17646
|
|
17247
17647
|
@param {string} [options.layer='current']
|
17648
|
+
The [layer](/up.layer) this request is associated with.
|
17649
|
+
|
17650
|
+
@param {string} [options.failLayer='current']
|
17248
17651
|
The [layer](/up.layer) this request is associated with if the server [sends a HTTP status code](/server-errors).
|
17249
17652
|
|
17250
17653
|
@param {Element} [options.origin]
|
@@ -17293,18 +17696,8 @@ You can define custom animations using `up.transition()` and
|
|
17293
17696
|
abortRequests(solo);
|
17294
17697
|
}
|
17295
17698
|
if (clearCache = options.clearCache) {
|
17296
|
-
return cache.clear(clearCache);
|
17297
|
-
}
|
17298
|
-
};
|
17299
|
-
preload = function() {
|
17300
|
-
var args, base, options;
|
17301
|
-
args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
|
17302
|
-
if (typeof (base = up.migrate).handleNetworkPreloadArgs === "function") {
|
17303
|
-
base.handleNetworkPreloadArgs.apply(base, args);
|
17699
|
+
return cache.clear(clearCache);
|
17304
17700
|
}
|
17305
|
-
options = parseRequestOptions(args);
|
17306
|
-
options.preload = true;
|
17307
|
-
return makeRequest(options);
|
17308
17701
|
};
|
17309
17702
|
parseRequestOptions = function(args) {
|
17310
17703
|
var base, options;
|
@@ -17417,18 +17810,24 @@ You can define custom animations using `up.transition()` and
|
|
17417
17810
|
|
17418
17811
|
Without arguments, this will abort all pending requests:
|
17419
17812
|
|
17420
|
-
|
17813
|
+
```js
|
17814
|
+
up.network.abort()
|
17815
|
+
```
|
17421
17816
|
|
17422
17817
|
To abort a given `up.Request` object, pass it as the first argument:
|
17423
17818
|
|
17424
|
-
|
17425
|
-
|
17819
|
+
```js
|
17820
|
+
let request = up.request('/path')
|
17821
|
+
up.network.abort(request)
|
17822
|
+
```
|
17426
17823
|
|
17427
17824
|
To abort all requests matching a condition, pass a function that takes a request
|
17428
17825
|
and returns a boolean value. Unpoly will abort all request for which the given
|
17429
17826
|
function returns `true`. E.g. to abort all requests with a HTTP method as `GET`:
|
17430
17827
|
|
17431
|
-
|
17828
|
+
```js
|
17829
|
+
up.network.abort((request) => request.method == 'GET')
|
17830
|
+
```
|
17432
17831
|
|
17433
17832
|
@function up.network.abort
|
17434
17833
|
@param {up.Request|boolean|Function(up.Request): boolean} [matcher=true]
|
@@ -17590,7 +17989,6 @@ You can define custom animations using `up.transition()` and
|
|
17590
17989
|
up.on('up:framework:reset', reset);
|
17591
17990
|
return {
|
17592
17991
|
request: makeRequest,
|
17593
|
-
preload: preload,
|
17594
17992
|
cache: cache,
|
17595
17993
|
isIdle: isIdle,
|
17596
17994
|
isBusy: isBusy,
|
@@ -17622,15 +18020,30 @@ You can define custom animations using `up.transition()` and
|
|
17622
18020
|
Layers
|
17623
18021
|
======
|
17624
18022
|
|
17625
|
-
|
18023
|
+
Unpoly allows you to [open page fragments in an overlay](/opening-overlays). Overlays may be stacked infinitely.
|
18024
|
+
|
18025
|
+
A variety of [overlay modes](/layer-terminology) are supported,
|
18026
|
+
such as modal dialogs, popup overlays or drawers. You may [customize their appearance and behavior](/customizing-overlays).
|
18027
|
+
|
18028
|
+
Layers are isolated, meaning a screen in one layer will not accidentally see elements
|
18029
|
+
or events from another layer. For instance, [fragment links](/up.link) will only update elements from the [current layer](/up.layer.current)
|
18030
|
+
unless you [explicitly target another layer](/layer-option).
|
18031
|
+
|
18032
|
+
Overlays allow you to break up a complex screen into [subinteractions](/subinteractions).
|
18033
|
+
Subinteractions take place in overlays and may span one or many pages. The original screen remains open in the background.
|
18034
|
+
Once the subinteraction is *done*, the overlay is closed and a result value is communicated back to the parent layer.
|
18035
|
+
|
18036
|
+
@see a[up-layer=new]
|
18037
|
+
@see up.layer.current
|
18038
|
+
@see up.layer.on
|
18039
|
+
@see up.layer.ask
|
17626
18040
|
|
17627
18041
|
@module up.layer
|
17628
18042
|
*/
|
17629
18043
|
|
17630
18044
|
up.layer = (function() {
|
17631
|
-
var LAYER_CLASSES, OVERLAY_CLASSES,
|
18045
|
+
var LAYER_CLASSES, OVERLAY_CLASSES, anySelector, api, ask, build, closeCallbackAttr, config, handlers, mainTargets, modeConfigs, normalizeOptions, open, openCallbackAttr, optionToString, reset, stack;
|
17632
18046
|
OVERLAY_CLASSES = [up.Layer.Modal, up.Layer.Popup, up.Layer.Drawer, up.Layer.Cover];
|
17633
|
-
OVERLAY_MODES = u.map(OVERLAY_CLASSES, 'mode');
|
17634
18047
|
LAYER_CLASSES = [up.Layer.Root].concat(OVERLAY_CLASSES);
|
17635
18048
|
|
17636
18049
|
/***
|
@@ -17669,7 +18082,7 @@ You can define custom animations using `up.transition()` and
|
|
17669
18082
|
up.layer.config.modal.openAnimation = 'move-from-top'
|
17670
18083
|
```
|
17671
18084
|
|
17672
|
-
To configure an additional [main target](/main)
|
18085
|
+
To configure an additional [main target](/up-main)
|
17673
18086
|
for overlay of any mode:
|
17674
18087
|
|
17675
18088
|
```js
|
@@ -17828,16 +18241,17 @@ You can define custom animations using `up.transition()` and
|
|
17828
18241
|
});
|
17829
18242
|
|
17830
18243
|
/***
|
17831
|
-
|
18244
|
+
A list of layers that are currently open.
|
17832
18245
|
|
17833
|
-
|
18246
|
+
The first element in the list is the [root layer](/up.layer.root).
|
18247
|
+
The last element is the [frontmost layer](/up.layer.front).
|
18248
|
+
|
18249
|
+
@property up.layer.stack
|
18250
|
+
@param {List<up.Layer>} stack
|
17834
18251
|
@stable
|
17835
18252
|
*/
|
17836
18253
|
stack = null;
|
17837
18254
|
handlers = [];
|
17838
|
-
isOverlayMode = function(mode) {
|
17839
|
-
return u.contains(OVERLAY_MODES, mode);
|
17840
|
-
};
|
17841
18255
|
mainTargets = function(mode) {
|
17842
18256
|
return u.flatMap(modeConfigs(mode), 'mainTargets');
|
17843
18257
|
};
|
@@ -17961,7 +18375,7 @@ You can define custom animations using `up.transition()` and
|
|
17961
18375
|
How the overlay may be [dismissed](/closing-overlays) by the user.
|
17962
18376
|
|
17963
18377
|
Supported values are `'key'`, `'outside'` and `'button'`.
|
17964
|
-
See [
|
18378
|
+
See [customizing dismiss controls](/closing-overlays#customizing-dismiss-controls)
|
17965
18379
|
for details.
|
17966
18380
|
|
17967
18381
|
You may enable multiple dismiss controls by passing an array or
|
@@ -17975,7 +18389,7 @@ You can define custom animations using `up.transition()` and
|
|
17975
18389
|
If set to `true` the overlay location and title will be shown in browser UI.
|
17976
18390
|
|
17977
18391
|
If set to `'auto'` history will be visible if the initial overlay
|
17978
|
-
content matches a [main target](/main).
|
18392
|
+
content matches a [main target](/up-main).
|
17979
18393
|
|
17980
18394
|
@param {string|Function} [options.animation]
|
17981
18395
|
The opening animation.
|
@@ -18074,22 +18488,61 @@ You can define custom animations using `up.transition()` and
|
|
18074
18488
|
};
|
18075
18489
|
|
18076
18490
|
/***
|
18077
|
-
|
18078
|
-
|
18079
|
-
|
18491
|
+
This event is emitted before an overlay is opened.
|
18492
|
+
|
18493
|
+
The overlay is not yet part of the [layer stack](/up.layer.stack) and has not yet been placed
|
18494
|
+
in the DOM. Listeners may prevent this event to prevent the overlay from opening.
|
18495
|
+
|
18496
|
+
The event is emitted on the `document`.
|
18497
|
+
|
18498
|
+
\#\#\# Changing layer options
|
18499
|
+
|
18500
|
+
Listeners may inspect and manipulate options for the overlay that is about to open.
|
18501
|
+
|
18502
|
+
For example, to give overlays the CSS class `.warning` if the initial URL contains
|
18503
|
+
the word `"confirm"`:
|
18504
|
+
|
18505
|
+
```js
|
18506
|
+
up.on('up:layer:open', function(event) {
|
18507
|
+
if (event.layerOptions.url.includes('confirm')) {
|
18508
|
+
event.layerOptions.class = 'warning'
|
18509
|
+
}
|
18510
|
+
})
|
18511
|
+
```
|
18080
18512
|
|
18081
18513
|
@event up:layer:open
|
18082
18514
|
@param {Object} event.layerOptions
|
18515
|
+
Options for the overlay that is about to open.
|
18516
|
+
|
18517
|
+
Listeners may inspect and change the options.
|
18518
|
+
All options for `up.layer.open()` may be used.
|
18083
18519
|
@param {Element} event.origin
|
18520
|
+
The link element that is opening the overlay.
|
18521
|
+
@param event.preventDefault()
|
18522
|
+
Event listeners may call this method to prevent the overlay from opening.
|
18084
18523
|
@stable
|
18085
18524
|
*/
|
18086
18525
|
|
18087
18526
|
/***
|
18088
|
-
|
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
|
+
```
|
18089
18540
|
|
18090
18541
|
@event up:layer:opened
|
18091
18542
|
@param {Element} event.origin
|
18543
|
+
The link element that is opening the overlay.
|
18092
18544
|
@param {up.Layer} event.layer
|
18545
|
+
The [layer object](/up.Layer) that is opening.
|
18093
18546
|
@stable
|
18094
18547
|
*/
|
18095
18548
|
|
@@ -18097,7 +18550,7 @@ You can define custom animations using `up.transition()` and
|
|
18097
18550
|
This event is emitted after a layer's [location property](/up.Layer.prototype.location)
|
18098
18551
|
has changed value.
|
18099
18552
|
|
18100
|
-
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)
|
18101
18554
|
has reached a new location.
|
18102
18555
|
|
18103
18556
|
@param {string} event.location
|
@@ -18133,6 +18586,7 @@ You can define custom animations using `up.transition()` and
|
|
18133
18586
|
A promise that will settle when the overlay closes.
|
18134
18587
|
|
18135
18588
|
When the overlay was accepted, the promise will fulfill with the overlay's acceptance value.
|
18589
|
+
|
18136
18590
|
When the overlay was dismissed, the promise will reject with the overlay's dismissal value.
|
18137
18591
|
|
18138
18592
|
@stable
|
@@ -18164,7 +18618,7 @@ You can define custom animations using `up.transition()` and
|
|
18164
18618
|
};
|
18165
18619
|
|
18166
18620
|
/***
|
18167
|
-
[Follows](/a-up-follow) this link and opens the result in a new
|
18621
|
+
[Follows](/a-up-follow) this link and opens the result in a new overlay.
|
18168
18622
|
|
18169
18623
|
\#\#\# Example
|
18170
18624
|
|
@@ -18205,12 +18659,12 @@ You can define custom animations using `up.transition()` and
|
|
18205
18659
|
If set to `true` the overlay location and title will be shown in browser UI.
|
18206
18660
|
|
18207
18661
|
If set to `'auto'` history will be visible if the initial overlay
|
18208
|
-
content matches a [main target](/main).
|
18662
|
+
content matches a [main target](/up-main).
|
18209
18663
|
|
18210
18664
|
@param [up-dismissable]
|
18211
18665
|
How the overlay may be [dismissed](/closing-overlays) by the user.
|
18212
18666
|
|
18213
|
-
See [
|
18667
|
+
See [customizing dismiss controls](/closing-overlays#customizing-dismiss-controls)
|
18214
18668
|
for details.
|
18215
18669
|
|
18216
18670
|
You may enable multiple dismiss controls by passing a space-separated string.
|
@@ -18408,12 +18862,33 @@ You can define custom animations using `up.transition()` and
|
|
18408
18862
|
The *current* layer is usually the [frontmost layer](/up.layer.front).
|
18409
18863
|
There are however some cases where the current layer is a layer in the background:
|
18410
18864
|
|
18411
|
-
- While an element in a background layer is [compiled](/up.compiler).
|
18865
|
+
- While an element in a background layer is being [compiled](/up.compiler).
|
18412
18866
|
- While an Unpoly event like `up:request:loaded` is being triggered from a background layer.
|
18413
|
-
- While
|
18867
|
+
- While an event listener bound to a background layer using `up.Layer#on()` is being called.
|
18414
18868
|
|
18415
18869
|
To temporarily change the current layer from your own code, use `up.Layer#asCurrent()`.
|
18416
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
|
+
|
18417
18892
|
@property up.layer.current
|
18418
18893
|
@param {up.Layer} current
|
18419
18894
|
@stable
|
@@ -18457,6 +18932,9 @@ You can define custom animations using `up.transition()` and
|
|
18457
18932
|
/***
|
18458
18933
|
Returns the [root layer](/layer-terminology).
|
18459
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
|
+
|
18460
18938
|
@property up.layer.root
|
18461
18939
|
@param {up.Layer} root
|
18462
18940
|
@stable
|
@@ -18467,7 +18945,10 @@ You can define custom animations using `up.transition()` and
|
|
18467
18945
|
|
18468
18946
|
If no overlay is open, an empty array is returned.
|
18469
18947
|
|
18470
|
-
|
18948
|
+
To get an array of *all* layers including the [root layer](/up.layer.root),
|
18949
|
+
use `up.layer.stack`.
|
18950
|
+
|
18951
|
+
@property up.layer.overlays
|
18471
18952
|
@param {Array<up.Layer>} overlays
|
18472
18953
|
@stable
|
18473
18954
|
*/
|
@@ -18492,9 +18973,9 @@ You can define custom animations using `up.transition()` and
|
|
18492
18973
|
Afterwards the only remaining layer will be the [root layer](/up.layer.root).
|
18493
18974
|
|
18494
18975
|
@function up.layer.dismissOverlays
|
18495
|
-
@param {any} value
|
18976
|
+
@param {any} [value]
|
18496
18977
|
The dismissal value.
|
18497
|
-
@param {Object} options
|
18978
|
+
@param {Object} [options]
|
18498
18979
|
See options for `up.layer.dismiss()`.
|
18499
18980
|
@stable
|
18500
18981
|
*/
|
@@ -18505,13 +18986,13 @@ You can define custom animations using `up.transition()` and
|
|
18505
18986
|
/***
|
18506
18987
|
[Accepts](/closing-overlays) the [current layer](up.layer.current).
|
18507
18988
|
|
18508
|
-
This is a shortcut for `up.layer.current.
|
18509
|
-
See `up.Layer#
|
18989
|
+
This is a shortcut for `up.layer.current.accept()`.
|
18990
|
+
See `up.Layer#accept()` for more documentation.
|
18510
18991
|
|
18511
|
-
@function up.layer.
|
18992
|
+
@function up.layer.accept
|
18512
18993
|
@param {any} [value]
|
18513
18994
|
@param {Object} [options]
|
18514
|
-
@
|
18995
|
+
@stable
|
18515
18996
|
*/
|
18516
18997
|
|
18517
18998
|
/***
|
@@ -18523,7 +19004,7 @@ You can define custom animations using `up.transition()` and
|
|
18523
19004
|
@function up.layer.dismiss
|
18524
19005
|
@param {any} [value]
|
18525
19006
|
@param {Object} [options]
|
18526
|
-
@
|
19007
|
+
@stable
|
18527
19008
|
*/
|
18528
19009
|
|
18529
19010
|
/***
|
@@ -18532,7 +19013,7 @@ You can define custom animations using `up.transition()` and
|
|
18532
19013
|
This is a shortcut for `up.layer.current.isRoot()`.
|
18533
19014
|
See `up.Layer#isRoot()` for more documentation..
|
18534
19015
|
|
18535
|
-
@function up.layer.
|
19016
|
+
@function up.layer.isRoot
|
18536
19017
|
@return {boolean}
|
18537
19018
|
@stable
|
18538
19019
|
*/
|
@@ -18560,7 +19041,7 @@ You can define custom animations using `up.transition()` and
|
|
18560
19041
|
*/
|
18561
19042
|
|
18562
19043
|
/***
|
18563
|
-
Listens to a
|
19044
|
+
Listens to a [DOM event](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Events)
|
18564
19045
|
that originated on an element [contained](/up.Layer.prototype.contains) by the [current layer](/up.layer.current).
|
18565
19046
|
|
18566
19047
|
This is a shortcut for `up.layer.current.on()`.
|
@@ -18569,7 +19050,7 @@ You can define custom animations using `up.transition()` and
|
|
18569
19050
|
@function up.layer.on
|
18570
19051
|
@param {string} types
|
18571
19052
|
A space-separated list of event types to bind to.
|
18572
|
-
@param {string} [selector]
|
19053
|
+
@param {string|Function(): string} [selector]
|
18573
19054
|
The selector of an element on which the event must be triggered.
|
18574
19055
|
@param {Object} [options]
|
18575
19056
|
@param {Function(event, [element], [data])} listener
|
@@ -18586,9 +19067,8 @@ You can define custom animations using `up.transition()` and
|
|
18586
19067
|
See `up.Layer#off()` for more documentation.
|
18587
19068
|
|
18588
19069
|
@function up.layer.off
|
18589
|
-
@param {Element|jQuery} [element=document]
|
18590
19070
|
@param {string} events
|
18591
|
-
@param {string} [selector]
|
19071
|
+
@param {string|Function(): string} [selector]
|
18592
19072
|
@param {Function(event, [element], [data])} listener
|
18593
19073
|
The listener function to unbind.
|
18594
19074
|
@stable
|
@@ -18601,7 +19081,6 @@ You can define custom animations using `up.transition()` and
|
|
18601
19081
|
See `up.Layer#emit()` for more documentation.
|
18602
19082
|
|
18603
19083
|
@function up.layer.emit
|
18604
|
-
@param {Element|jQuery} [target=up.layer.element]
|
18605
19084
|
@param {string} eventType
|
18606
19085
|
@param {Object} [props={}]
|
18607
19086
|
@stable
|
@@ -18631,7 +19110,7 @@ You can define custom animations using `up.transition()` and
|
|
18631
19110
|
*/
|
18632
19111
|
|
18633
19112
|
/***
|
18634
|
-
The location of the [current layer](/up.layer.current).
|
19113
|
+
The location URL of the [current layer](/up.layer.current).
|
18635
19114
|
|
18636
19115
|
This is a shortcut for `up.layer.current.location`.
|
18637
19116
|
See `up.Layer#location` for more documentation.
|
@@ -18640,23 +19119,34 @@ You can define custom animations using `up.transition()` and
|
|
18640
19119
|
@param {string} location
|
18641
19120
|
@stable
|
18642
19121
|
*/
|
19122
|
+
|
19123
|
+
/***
|
19124
|
+
The [current layer](/up.layer.current)'s [mode](/up.layer.mode)
|
19125
|
+
which governs its appearance and behavior.
|
19126
|
+
|
19127
|
+
@property up.layer.mode
|
19128
|
+
@param {string} mode
|
19129
|
+
@stable
|
19130
|
+
*/
|
19131
|
+
|
19132
|
+
/***
|
19133
|
+
The [context](/context) of the [current layer](/up.layer.current).
|
19134
|
+
|
19135
|
+
This is aliased as `up.context`.
|
19136
|
+
|
19137
|
+
@property up.layer.context
|
19138
|
+
@param {string} context
|
19139
|
+
The context object.
|
19140
|
+
|
19141
|
+
If no context has been set an empty object is returned.
|
19142
|
+
@experimental
|
19143
|
+
*/
|
18643
19144
|
u.delegate(api, ['accept', 'dismiss', 'isRoot', 'isOverlay', 'isFront', 'on', 'off', 'emit', 'parent', 'historyVisible', 'location', 'mode', 'context', 'element', 'contains', 'size', 'affix'], function() {
|
18644
19145
|
return stack.current;
|
18645
19146
|
});
|
18646
19147
|
return api;
|
18647
19148
|
})();
|
18648
19149
|
|
18649
|
-
|
18650
|
-
/***
|
18651
|
-
TODO: Docs
|
18652
|
-
@property up.context
|
18653
|
-
@pram {Object} context
|
18654
|
-
*/
|
18655
|
-
|
18656
|
-
u.getter(up, 'context', function() {
|
18657
|
-
return up.layer.context;
|
18658
|
-
});
|
18659
|
-
|
18660
19150
|
}).call(this);
|
18661
19151
|
|
18662
19152
|
/***
|
@@ -18729,6 +19219,11 @@ With these [`up-target`](/a-up-follow#up-target) annotations Unpoly only updates
|
|
18729
19219
|
The JavaScript environment will persist and the user will not see a white flash while the
|
18730
19220
|
new page is loading.
|
18731
19221
|
|
19222
|
+
@see a[up-follow]
|
19223
|
+
@see a[up-instant]
|
19224
|
+
@see a[up-preload]
|
19225
|
+
@see up.follow
|
19226
|
+
|
18732
19227
|
@module up.link
|
18733
19228
|
*/
|
18734
19229
|
|
@@ -18736,7 +19231,7 @@ new page is loading.
|
|
18736
19231
|
var slice = [].slice;
|
18737
19232
|
|
18738
19233
|
up.link = (function() {
|
18739
|
-
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,
|
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;
|
18740
19235
|
u = up.util;
|
18741
19236
|
e = up.element;
|
18742
19237
|
linkPreloader = new up.LinkPreloader();
|
@@ -18753,9 +19248,10 @@ new page is loading.
|
|
18753
19248
|
};
|
18754
19249
|
|
18755
19250
|
/***
|
18756
|
-
|
18757
|
-
|
18758
|
-
|
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.
|
18759
19255
|
|
18760
19256
|
@property up.link.config
|
18761
19257
|
|
@@ -18828,7 +19324,7 @@ new page is loading.
|
|
18828
19324
|
|
18829
19325
|
If set to `false`, Unpoly will never preload links.
|
18830
19326
|
|
18831
|
-
@param {Array<string>} [config.
|
19327
|
+
@param {Array<string>} [config.clickableSelectors]
|
18832
19328
|
A list of CSS selectors matching elements that should behave like links or buttons.
|
18833
19329
|
|
18834
19330
|
@see [up-clickable]
|
@@ -18837,7 +19333,7 @@ new page is loading.
|
|
18837
19333
|
config = new up.Config(function() {
|
18838
19334
|
return {
|
18839
19335
|
followSelectors: combineFollowableSelectors(LINKS_WITH_REMOTE_HTML, ATTRIBUTES_SUGGESTING_FOLLOW).concat(LINKS_WITH_LOCAL_HTML),
|
18840
|
-
noFollowSelectors: ['[up-follow=false]', 'a[
|
19336
|
+
noFollowSelectors: ['[up-follow=false]', 'a[download]', 'a[target]', 'a[href^="#"]:not([up-content]):not([up-fragment]):not([up-document])', 'a[href^="javascript:"]'],
|
18841
19337
|
instantSelectors: ['[up-instant]'],
|
18842
19338
|
noInstantSelectors: ['[up-instant=false]', '[onclick]'],
|
18843
19339
|
preloadSelectors: combineFollowableSelectors(LINKS_WITH_REMOTE_HTML, ['[up-preload]']),
|
@@ -18900,10 +19396,9 @@ new page is loading.
|
|
18900
19396
|
};
|
18901
19397
|
|
18902
19398
|
/***
|
18903
|
-
|
18904
|
-
[current layer](/up.layer.current) with HTML from the response.
|
19399
|
+
Follows the given link with JavaScript and updates a fragment with the server response.
|
18905
19400
|
|
18906
|
-
By default the layer's [main element](/main)
|
19401
|
+
By default the layer's [main element](/up-main)
|
18907
19402
|
will be replaced. Attributes like `a[up-target]`
|
18908
19403
|
or `a[up-layer]` will be honored.
|
18909
19404
|
|
@@ -18965,8 +19460,24 @@ new page is loading.
|
|
18965
19460
|
};
|
18966
19461
|
|
18967
19462
|
/***
|
18968
|
-
Parses the
|
18969
|
-
[`follow`](/up.follow) the given link, but does not
|
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
|
+
```
|
18970
19481
|
|
18971
19482
|
@function up.link.followOptions
|
18972
19483
|
@param {Element|jQuery|string} link
|
@@ -19045,7 +19556,20 @@ new page is loading.
|
|
19045
19556
|
|
19046
19557
|
The event is emitted on the `<a>` element that is being followed.
|
19047
19558
|
|
19048
|
-
|
19559
|
+
\#\#\# Changing render options
|
19560
|
+
|
19561
|
+
Listeners may inspect and manipulate [render options](/up.render) for the coming fragment update.
|
19562
|
+
|
19563
|
+
The code below will open all form-contained links in an overlay, as to not
|
19564
|
+
lose the user's form data:
|
19565
|
+
|
19566
|
+
```js
|
19567
|
+
up.on('up:link:follow', function(event, link) {
|
19568
|
+
if (link.closest('form')) {
|
19569
|
+
event.renderOptions.layer = 'new'
|
19570
|
+
}
|
19571
|
+
})
|
19572
|
+
```
|
19049
19573
|
|
19050
19574
|
@event up:link:follow
|
19051
19575
|
@param {Element} event.target
|
@@ -19071,7 +19595,10 @@ new page is loading.
|
|
19071
19595
|
@param {Object} options
|
19072
19596
|
See options for `up.follow()`.
|
19073
19597
|
@return {Promise}
|
19074
|
-
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`.
|
19075
19602
|
@stable
|
19076
19603
|
*/
|
19077
19604
|
preload = function(link, options) {
|
@@ -19175,7 +19702,7 @@ new page is loading.
|
|
19175
19702
|
@function up.link.makeFollowable
|
19176
19703
|
@param {Element|jQuery|string} link
|
19177
19704
|
The element or selector for the link to make followable.
|
19178
|
-
@
|
19705
|
+
@experimental
|
19179
19706
|
*/
|
19180
19707
|
makeFollowable = function(link) {
|
19181
19708
|
if (!isFollowable(link)) {
|
@@ -19311,6 +19838,13 @@ new page is loading.
|
|
19311
19838
|
If the user activates an element using their keyboard, the `up:click` event will be emitted
|
19312
19839
|
when the key is pressed even if the element has an `[up-instant]` attribute.
|
19313
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
|
+
|
19314
19848
|
@event up:click
|
19315
19849
|
@param {Element} event.target
|
19316
19850
|
The clicked element.
|
@@ -19333,24 +19867,9 @@ new page is loading.
|
|
19333
19867
|
method = followMethod(link);
|
19334
19868
|
return up.network.isSafeMethod(method);
|
19335
19869
|
};
|
19336
|
-
targetMacro = function(queryAttr, fixedResultAttrs, callback) {
|
19337
|
-
return up.macro("[" + queryAttr + "]", function(link) {
|
19338
|
-
var optionalTarget, resultAttrs;
|
19339
|
-
resultAttrs = u.copy(fixedResultAttrs);
|
19340
|
-
if (optionalTarget = link.getAttribute(queryAttr)) {
|
19341
|
-
resultAttrs['up-target'] = optionalTarget;
|
19342
|
-
} else {
|
19343
|
-
resultAttrs['up-follow'] = '';
|
19344
|
-
}
|
19345
|
-
e.setMissingAttrs(link, resultAttrs);
|
19346
|
-
link.removeAttribute(queryAttr);
|
19347
|
-
return typeof callback === "function" ? callback() : void 0;
|
19348
|
-
});
|
19349
|
-
};
|
19350
19870
|
|
19351
19871
|
/***
|
19352
|
-
[Follows](/up.follow) this link with JavaScript and
|
19353
|
-
on the current page with a corresponding element from the response.
|
19872
|
+
[Follows](/up.follow) this link with JavaScript and updates a fragment with the server response.
|
19354
19873
|
|
19355
19874
|
Following a link is considered [navigation](/navigation) by default.
|
19356
19875
|
|
@@ -19363,7 +19882,7 @@ new page is loading.
|
|
19363
19882
|
<a href="/posts/5" up-follow up-target=".content">Read post</a>
|
19364
19883
|
```
|
19365
19884
|
|
19366
|
-
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.
|
19367
19886
|
|
19368
19887
|
\#\#\# Advanced fragment changes
|
19369
19888
|
|
@@ -19379,7 +19898,7 @@ new page is loading.
|
|
19379
19898
|
- `[up-transition]`
|
19380
19899
|
- `[up-content]`
|
19381
19900
|
- `[up-fragment]`
|
19382
|
-
- `[up-document]
|
19901
|
+
- `[up-document]`
|
19383
19902
|
|
19384
19903
|
Such a link will still be followed through Unpoly.
|
19385
19904
|
|
@@ -19400,14 +19919,14 @@ new page is loading.
|
|
19400
19919
|
@param [up-target]
|
19401
19920
|
The CSS selector to update.
|
19402
19921
|
|
19403
|
-
If omitted a [main target](/main) will be rendered.
|
19922
|
+
If omitted a [main target](/up-main) will be rendered.
|
19404
19923
|
|
19405
19924
|
@param [up-fallback]
|
19406
19925
|
Specifies behavior if the [target selector](/up.render#options.target) is missing from the current page or the server response.
|
19407
19926
|
|
19408
19927
|
If set to a CSS selector, Unpoly will attempt to replace that selector instead.
|
19409
19928
|
|
19410
|
-
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.
|
19411
19930
|
|
19412
19931
|
If set to `false` Unpoly will immediately reject the render promise.
|
19413
19932
|
|
@@ -19481,12 +20000,12 @@ new page is loading.
|
|
19481
20000
|
|
19482
20001
|
If set to `auto` history will be updated if the `[up-target]` matches
|
19483
20002
|
a selector in `up.fragment.config.autoHistoryTargets`. By default this contains all
|
19484
|
-
[main targets](/main).
|
20003
|
+
[main targets](/up-main).
|
19485
20004
|
|
19486
20005
|
If set to `false`, the history will remain unchanged.
|
19487
20006
|
|
19488
20007
|
[Overlays](/up.layer) will only change the browser URL and window title if the overlay
|
19489
|
-
has [visible history](/up.layer.historyVisible), even
|
20008
|
+
has [visible history](/up.layer.historyVisible), even when `[up-history=true]` is set.
|
19490
20009
|
|
19491
20010
|
@param [up-title]
|
19492
20011
|
An explicit document title to use after rendering.
|
@@ -19561,7 +20080,7 @@ new page is loading.
|
|
19561
20080
|
This is only relevant when updating a layer that is not the [frontmost layer](/up.layer.front).
|
19562
20081
|
|
19563
20082
|
@param [up-context]
|
19564
|
-
A JSON object that will be merged into the [context](/
|
20083
|
+
A JSON object that will be merged into the [context](/context)
|
19565
20084
|
of the current layer once the fragment is rendered.
|
19566
20085
|
|
19567
20086
|
@param [up-keep='true']
|
@@ -19616,12 +20135,7 @@ new page is loading.
|
|
19616
20135
|
});
|
19617
20136
|
|
19618
20137
|
/***
|
19619
|
-
|
19620
|
-
|
19621
|
-
By adding an `up-instant` attribute to a link, the destination will be
|
19622
|
-
fetched on `mousedown` instead of `click` (`mouseup`).
|
19623
|
-
|
19624
|
-
<a href="/users" up-follow up-instant>User list</a>
|
20138
|
+
Follows this link on `mousedown` instead of `click`.
|
19625
20139
|
|
19626
20140
|
This will save precious milliseconds that otherwise spent
|
19627
20141
|
on waiting for the user to release the mouse button. Since an
|
@@ -19633,6 +20147,10 @@ new page is loading.
|
|
19633
20147
|
navigation actions this isn't needed. E.g. popular operation
|
19634
20148
|
systems switch tabs on `mousedown` instead of `click`.
|
19635
20149
|
|
20150
|
+
\#\#\# Example
|
20151
|
+
|
20152
|
+
<a href="/users" up-follow up-instant>User list</a>
|
20153
|
+
|
19636
20154
|
\#\#\# Accessibility
|
19637
20155
|
|
19638
20156
|
If the user activates an element using their keyboard, the `up:click` event will be emitted
|
@@ -19642,37 +20160,6 @@ new page is loading.
|
|
19642
20160
|
@stable
|
19643
20161
|
*/
|
19644
20162
|
|
19645
|
-
/***
|
19646
|
-
[Follows](/up.follow) this link as fast as possible.
|
19647
|
-
|
19648
|
-
This is done by:
|
19649
|
-
|
19650
|
-
- [Following the link through AJAX](/a-up-follow) instead of a full page load
|
19651
|
-
- [Preloading the link's destination URL](/a-up-preload)
|
19652
|
-
- [Triggering the link on `mousedown`](/a-up-instant) instead of on `click`
|
19653
|
-
|
19654
|
-
\#\#\# Example
|
19655
|
-
|
19656
|
-
Use `[up-dash]` like this:
|
19657
|
-
|
19658
|
-
<a href="/users" up-dash=".main">User list</a>
|
19659
|
-
|
19660
|
-
This is shorthand for:
|
19661
|
-
|
19662
|
-
<a href="/users" up-target=".main" up-instant up-preload>User list</a>
|
19663
|
-
|
19664
|
-
@selector a[up-dash]
|
19665
|
-
@param [up-dash='body']
|
19666
|
-
The CSS selector to replace
|
19667
|
-
|
19668
|
-
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)).
|
19669
|
-
@stable
|
19670
|
-
*/
|
19671
|
-
targetMacro('up-dash', {
|
19672
|
-
'up-preload': '',
|
19673
|
-
'up-instant': ''
|
19674
|
-
});
|
19675
|
-
|
19676
20163
|
/***
|
19677
20164
|
Add an `[up-expand]` attribute to any element to enlarge the click area of a
|
19678
20165
|
descendant link.
|
@@ -19731,11 +20218,9 @@ new page is loading.
|
|
19731
20218
|
});
|
19732
20219
|
|
19733
20220
|
/***
|
19734
|
-
|
19735
|
-
when the user hovers over the click area, or when the user puts her
|
19736
|
-
mouse/finger down (before releasing).
|
20221
|
+
Preloads this link when the user hovers over it.
|
19737
20222
|
|
19738
|
-
When the link is clicked later
|
20223
|
+
When the link is clicked later the response will already be cached,
|
19739
20224
|
making the interaction feel instant.
|
19740
20225
|
|
19741
20226
|
@selector a[up-preload]
|
@@ -19763,7 +20248,6 @@ new page is loading.
|
|
19763
20248
|
isFollowable: isFollowable,
|
19764
20249
|
shouldFollowEvent: shouldFollowEvent,
|
19765
20250
|
followMethod: followMethod,
|
19766
|
-
targetMacro: targetMacro,
|
19767
20251
|
convertClicks: convertClicks,
|
19768
20252
|
config: config,
|
19769
20253
|
combineFollowableSelectors: combineFollowableSelectors
|
@@ -19778,9 +20262,12 @@ new page is loading.
|
|
19778
20262
|
Forms
|
19779
20263
|
=====
|
19780
20264
|
|
19781
|
-
|
19782
|
-
|
19783
|
-
|
20265
|
+
The `up.form` module helps you work with non-trivial forms.
|
20266
|
+
|
20267
|
+
@see form[up-submit]
|
20268
|
+
@see form[up-validate]
|
20269
|
+
@see input[up-switch]
|
20270
|
+
@see form[up-autosubmit]
|
19784
20271
|
|
19785
20272
|
@module up.form
|
19786
20273
|
*/
|
@@ -19789,7 +20276,7 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
19789
20276
|
var slice = [].slice;
|
19790
20277
|
|
19791
20278
|
up.form = (function() {
|
19792
|
-
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;
|
19793
20280
|
u = up.util;
|
19794
20281
|
e = up.element;
|
19795
20282
|
ATTRIBUTES_SUGGESTING_SUBMIT = ['[up-submit]', '[up-target]', '[up-layer]', '[up-transition]'];
|
@@ -19966,8 +20453,26 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
19966
20453
|
});
|
19967
20454
|
|
19968
20455
|
/***
|
19969
|
-
Parses the
|
19970
|
-
[`submit`](/up.submit) the given form, but does not
|
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
|
+
```
|
19971
20476
|
|
19972
20477
|
@param {Element|jQuery|string} form
|
19973
20478
|
The form to submit.
|
@@ -20020,14 +20525,29 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20020
20525
|
/***
|
20021
20526
|
This event is [emitted](/up.emit) when a form is [submitted](/up.submit) through Unpoly.
|
20022
20527
|
|
20023
|
-
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
|
+
```
|
20024
20545
|
|
20025
20546
|
@event up:form:submit
|
20026
20547
|
@param {Element} event.target
|
20027
20548
|
The `<form>` element that will be submitted.
|
20028
20549
|
@param {Object} event.renderOptions
|
20029
20550
|
An object with [render options](/up.render) for the fragment update
|
20030
|
-
that will show the validation results.
|
20031
20551
|
|
20032
20552
|
Listeners may inspect and modify these options.
|
20033
20553
|
@param event.preventDefault()
|
@@ -20035,7 +20555,11 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20035
20555
|
@stable
|
20036
20556
|
*/
|
20037
20557
|
up.on('up:click', submitButtonSelector, function(event, button) {
|
20038
|
-
|
20558
|
+
var form;
|
20559
|
+
form = e.closest(button, 'form');
|
20560
|
+
if (form && isSubmittable(form)) {
|
20561
|
+
return button.focus();
|
20562
|
+
}
|
20039
20563
|
});
|
20040
20564
|
|
20041
20565
|
/***
|
@@ -20120,10 +20644,10 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20120
20644
|
/***
|
20121
20645
|
[Observes](/up.observe) a field or form and submits the form when a value changes.
|
20122
20646
|
|
20123
|
-
Both the form and the changed field will be assigned a CSS class [
|
20647
|
+
Both the form and the changed field will be assigned a CSS class [`.up-active`](/form-up-active)
|
20124
20648
|
while the autosubmitted form is processing.
|
20125
20649
|
|
20126
|
-
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.
|
20127
20651
|
|
20128
20652
|
@function up.autosubmit
|
20129
20653
|
@param {string|Element|jQuery} target
|
@@ -20177,7 +20701,9 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20177
20701
|
|
20178
20702
|
\#\#\# Example
|
20179
20703
|
|
20180
|
-
|
20704
|
+
```js
|
20705
|
+
up.validate('input[name=email]', { target: '.email-errors' })
|
20706
|
+
```
|
20181
20707
|
|
20182
20708
|
@function up.validate
|
20183
20709
|
@param {string|Element|jQuery} field
|
@@ -20221,6 +20747,7 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20221
20747
|
@param event.preventDefault()
|
20222
20748
|
Event listeners may call this method to prevent the validation request
|
20223
20749
|
being sent to the server.
|
20750
|
+
@stable
|
20224
20751
|
*/
|
20225
20752
|
switcherValues = function(field) {
|
20226
20753
|
var checkedButton, form, groupName, meta, value, values;
|
@@ -20333,24 +20860,51 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20333
20860
|
return element;
|
20334
20861
|
}
|
20335
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
|
+
};
|
20336
20887
|
isSubmitDisabled = function(form) {
|
20337
20888
|
return e.matches(form, config.noSubmitSelectors.join(','));
|
20338
20889
|
};
|
20339
20890
|
|
20340
20891
|
/***
|
20341
|
-
|
20342
|
-
instead of triggering a full page reload.
|
20343
|
-
|
20344
|
-
<form method="post" action="/users" up-target=".main">
|
20345
|
-
...
|
20346
|
-
</form>
|
20892
|
+
Submits this form via JavaScript and updates a fragment with the server response.
|
20347
20893
|
|
20348
20894
|
The server response is searched for the selector given in `up-target`.
|
20349
20895
|
The selector content is then [replaced](/up.replace) in the current page.
|
20350
20896
|
|
20351
20897
|
The programmatic variant of this is the [`up.submit()`](/up.submit) function.
|
20352
20898
|
|
20353
|
-
\#\#\#
|
20899
|
+
\#\#\# Example
|
20900
|
+
|
20901
|
+
```html
|
20902
|
+
<form method="post" action="/users" up-submit>
|
20903
|
+
...
|
20904
|
+
</form>
|
20905
|
+
```
|
20906
|
+
|
20907
|
+
\#\#\# Handling validation errors
|
20354
20908
|
|
20355
20909
|
When the server was unable to save the form due to invalid params,
|
20356
20910
|
it will usually re-render an updated copy of the form with
|
@@ -20365,19 +20919,35 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20365
20919
|
[`:status` option to `render`](http://guides.rubyonrails.org/layouts_and_rendering.html#the-status-option)
|
20366
20920
|
for this:
|
20367
20921
|
|
20368
|
-
|
20369
|
-
|
20370
|
-
def create
|
20371
|
-
user_params = params[:user].permit(:email, :password)
|
20372
|
-
@user = User.new(user_params)
|
20373
|
-
if @user.save?
|
20374
|
-
sign_in @user
|
20375
|
-
else
|
20376
|
-
render 'form', status: :bad_request
|
20377
|
-
end
|
20378
|
-
end
|
20922
|
+
```ruby
|
20923
|
+
class UsersController < ApplicationController
|
20379
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
|
20380
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.
|
20381
20951
|
|
20382
20952
|
Note that you can also use
|
20383
20953
|
[`input[up-validate]`](/input-up-validate) to perform server-side
|
@@ -20385,7 +20955,7 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20385
20955
|
|
20386
20956
|
\#\#\# Giving feedback while the form is processing
|
20387
20957
|
|
20388
|
-
The `<form>` element will be assigned a CSS class [
|
20958
|
+
The `<form>` element will be assigned a CSS class [`.up-active`](/form.up-active) while
|
20389
20959
|
the submission is loading.
|
20390
20960
|
|
20391
20961
|
\#\#\# Short notation
|
@@ -20569,11 +21139,13 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20569
21139
|
*/
|
20570
21140
|
|
20571
21141
|
/***
|
20572
|
-
|
21142
|
+
Validates this form on the server when any field changes and shows validation errors.
|
20573
21143
|
|
20574
21144
|
You can configure what Unpoly considers a fieldset by adding CSS selectors to the
|
20575
21145
|
`up.form.config.validateTargets` array.
|
20576
21146
|
|
21147
|
+
See `input[up-validate]` for detailed documentation.
|
21148
|
+
|
20577
21149
|
@selector form[up-validate]
|
20578
21150
|
@param up-validate
|
20579
21151
|
The CSS selector to update with the server response.
|
@@ -20590,7 +21162,7 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20590
21162
|
});
|
20591
21163
|
|
20592
21164
|
/***
|
20593
|
-
Show or hide elements when a
|
21165
|
+
Show or hide elements when a form field is set to a given value.
|
20594
21166
|
|
20595
21167
|
\#\#\# Example: Select options
|
20596
21168
|
|
@@ -20710,6 +21282,15 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20710
21282
|
|
20711
21283
|
<input name="query" up-observe="showSuggestions(value)">
|
20712
21284
|
|
21285
|
+
Note that the parameter name in the markup must be called `value` or it will not work.
|
21286
|
+
The parameter name can be called whatever you want in the JavaScript, however.
|
21287
|
+
|
21288
|
+
Also note that the function must be declared on the `window` object to work, like so:
|
21289
|
+
|
21290
|
+
window.showSuggestions = function(selectedValue) {
|
21291
|
+
console.log(`Called showSuggestions() with ${selectedValue}`);
|
21292
|
+
}
|
21293
|
+
|
20713
21294
|
\#\#\# Callback context
|
20714
21295
|
|
20715
21296
|
The script given to `[up-observe]` runs with the following context:
|
@@ -20784,7 +21365,7 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20784
21365
|
/***
|
20785
21366
|
Submits this field's form when this field changes its values.
|
20786
21367
|
|
20787
|
-
Both the form and the changed field will be assigned a CSS class [
|
21368
|
+
Both the form and the changed field will be assigned a CSS class [`.up-active`](/form-up-active)
|
20788
21369
|
while the autosubmitted form is loading.
|
20789
21370
|
|
20790
21371
|
The programmatic variant of this is the [`up.autosubmit()`](/up.autosubmit) function.
|
@@ -20813,15 +21394,15 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20813
21394
|
</div>
|
20814
21395
|
|
20815
21396
|
@selector input[up-autosubmit]
|
20816
|
-
@param up-delay
|
21397
|
+
@param [up-delay]
|
20817
21398
|
The number of miliseconds to wait after a change before the form is submitted.
|
20818
21399
|
@stable
|
20819
21400
|
*/
|
20820
21401
|
|
20821
21402
|
/***
|
20822
|
-
Submits the form when
|
21403
|
+
Submits the form when any field changes.
|
20823
21404
|
|
20824
|
-
Both the form and the field will be assigned a CSS class [
|
21405
|
+
Both the form and the field will be assigned a CSS class [`.up-active`](/form-up-active)
|
20825
21406
|
while the autosubmitted form is loading.
|
20826
21407
|
|
20827
21408
|
The programmatic variant of this is the [`up.autosubmit()`](/up.autosubmit) function.
|
@@ -20836,7 +21417,7 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20836
21417
|
</form>
|
20837
21418
|
|
20838
21419
|
@selector form[up-autosubmit]
|
20839
|
-
@param up-delay
|
21420
|
+
@param [up-delay]
|
20840
21421
|
The number of miliseconds to wait after a change before the form is submitted.
|
20841
21422
|
@stable
|
20842
21423
|
*/
|
@@ -20848,6 +21429,7 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20848
21429
|
config: config,
|
20849
21430
|
submit: submit,
|
20850
21431
|
submitOptions: submitOptions,
|
21432
|
+
isSubmittable: isSubmittable,
|
20851
21433
|
observe: observe,
|
20852
21434
|
validate: validate,
|
20853
21435
|
autosubmit: autosubmit,
|
@@ -20873,44 +21455,57 @@ Navigation feedback
|
|
20873
21455
|
===================
|
20874
21456
|
|
20875
21457
|
The `up.feedback` module adds useful CSS classes to links while they are loading,
|
20876
|
-
or when they point to the current URL.
|
20877
|
-
|
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.
|
20878
21462
|
|
20879
21463
|
|
20880
21464
|
\#\#\# Example
|
20881
21465
|
|
20882
21466
|
Let's say we have an `<nav>` element with two links, pointing to `/foo` and `/bar` respectively:
|
20883
21467
|
|
20884
|
-
|
20885
|
-
|
20886
|
-
|
20887
|
-
|
21468
|
+
```html
|
21469
|
+
<nav>
|
21470
|
+
<a href="/foo" up-follow>Foo</a>
|
21471
|
+
<a href="/bar" up-follow>Bar</a>
|
21472
|
+
</nav>
|
21473
|
+
```
|
20888
21474
|
|
20889
21475
|
By giving the navigation bar the `[up-nav]` attribute, links pointing to the current browser address are highlighted
|
20890
21476
|
as we navigate through the site.
|
20891
21477
|
|
20892
21478
|
If the current URL is `/foo`, the first link is automatically marked with an [`.up-current`](/a.up-current) class:
|
20893
21479
|
|
20894
|
-
|
20895
|
-
|
20896
|
-
|
20897
|
-
|
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
|
+
```
|
20898
21486
|
|
20899
21487
|
When the user clicks on the `/bar` link, the link will receive the [`up-active`](/a.up-active) class while it is waiting
|
20900
21488
|
for the server to respond:
|
20901
21489
|
|
20902
|
-
|
20903
|
-
|
20904
|
-
|
20905
|
-
|
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
|
+
```
|
20906
21496
|
|
20907
21497
|
Once the response is received the URL will change to `/bar` and the `up-active` class is removed:
|
20908
21498
|
|
20909
|
-
|
20910
|
-
|
20911
|
-
|
20912
|
-
|
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
|
+
```
|
20913
21505
|
|
21506
|
+
@see [up-nav]
|
21507
|
+
@see a.up-current
|
21508
|
+
@see a.up-active
|
20914
21509
|
|
20915
21510
|
@module up.feedback
|
20916
21511
|
*/
|
@@ -21212,7 +21807,7 @@ Once the response is received the URL will change to `/bar` and the `up-active`
|
|
21212
21807
|
*/
|
21213
21808
|
|
21214
21809
|
/***
|
21215
|
-
Links within `[up-nav]` may use the `[up-alias]` attribute to pass
|
21810
|
+
Links within `[up-nav]` may use the `[up-alias]` attribute to pass a [URL pattern](/url-patterns) for which they
|
21216
21811
|
should also be highlighted as [`.up-current`](a.up-current).
|
21217
21812
|
|
21218
21813
|
\#\#\# Example
|
@@ -21225,7 +21820,7 @@ Once the response is received the URL will change to `/bar` and the `up-active`
|
|
21225
21820
|
</div>
|
21226
21821
|
```
|
21227
21822
|
|
21228
|
-
To pass more than one alternative URLs, use
|
21823
|
+
To pass more than one alternative URLs, use a [URL pattern](/url-patterns).
|
21229
21824
|
|
21230
21825
|
@selector a[up-alias]
|
21231
21826
|
@param up-alias
|
@@ -21285,8 +21880,10 @@ Once the response is received the URL will change to `/bar` and the `up-active`
|
|
21285
21880
|
Passive updates
|
21286
21881
|
===============
|
21287
21882
|
|
21288
|
-
This
|
21289
|
-
|
21883
|
+
This package contains functionality to passively receive updates from the server.
|
21884
|
+
|
21885
|
+
@see [up-hungry]
|
21886
|
+
@see [up-poll]
|
21290
21887
|
|
21291
21888
|
@module up.radio
|
21292
21889
|
*/
|
@@ -21301,13 +21898,16 @@ passively receive updates from the server.
|
|
21301
21898
|
Configures defaults for passive updates.
|
21302
21899
|
|
21303
21900
|
@property up.radio.config
|
21901
|
+
|
21304
21902
|
@param {Array<string>} [config.hungrySelectors]
|
21305
21903
|
An array of CSS selectors that is replaced whenever a matching element is found in a response.
|
21306
21904
|
These elements are replaced even when they were not targeted directly.
|
21307
21905
|
|
21308
21906
|
By default this contains the [`[up-hungry]`](/up-hungry) attribute.
|
21907
|
+
|
21309
21908
|
@param {number} [config.pollInterval=30000]
|
21310
21909
|
The default [polling](/up-poll] interval in milliseconds.
|
21910
|
+
|
21311
21911
|
@param {boolean|string|Function(Element)} [config.pollEnabled=true]
|
21312
21912
|
Whether Unpoly will follow instructions to poll fragments, like the `[up-poll]` attribute.
|
21313
21913
|
|
@@ -21322,6 +21922,7 @@ passively receive updates from the server.
|
|
21322
21922
|
When set to `false`, Unpoly will never allow polling.
|
21323
21923
|
|
21324
21924
|
You may also pass a function that accepts the polling fragment and returns `true`, `false` or `'auto'`.
|
21925
|
+
|
21325
21926
|
@stable
|
21326
21927
|
*/
|
21327
21928
|
config = new up.Config(function() {
|
@@ -21344,9 +21945,8 @@ passively receive updates from the server.
|
|
21344
21945
|
};
|
21345
21946
|
|
21346
21947
|
/***
|
21347
|
-
Elements with an `[up-hungry]` attribute are
|
21348
|
-
matching element
|
21349
|
-
when it isn't targeted directly.
|
21948
|
+
Elements with an `[up-hungry]` attribute are updated whenever the server
|
21949
|
+
sends a matching element, even if the element isn't targeted.
|
21350
21950
|
|
21351
21951
|
Use cases for this are unread message counters or notification flashes.
|
21352
21952
|
Such elements often live in the layout, outside of the content area that is
|
@@ -21438,21 +22038,27 @@ passively receive updates from the server.
|
|
21438
22038
|
Assume an application layout with an unread message counter.
|
21439
22039
|
You can use `[up-poll]` to refresh the counter every 30 seconds:
|
21440
22040
|
|
21441
|
-
|
21442
|
-
|
21443
|
-
|
22041
|
+
```html
|
22042
|
+
<div class="unread-count" up-poll>
|
22043
|
+
2 new messages
|
22044
|
+
</div>
|
22045
|
+
```
|
21444
22046
|
|
21445
22047
|
\#\#\# Controlling the reload interval
|
21446
22048
|
|
21447
22049
|
You may set an optional `[up-interval]` attribute to set the reload interval in milliseconds:
|
21448
22050
|
|
21449
|
-
|
21450
|
-
|
21451
|
-
|
22051
|
+
```html
|
22052
|
+
<div class="unread-count" up-poll up-interval="10000">
|
22053
|
+
2 new messages
|
22054
|
+
</div>
|
22055
|
+
```
|
21452
22056
|
|
21453
22057
|
If the value is omitted, a global default is used. You may configure the default like this:
|
21454
22058
|
|
21455
|
-
|
22059
|
+
```js
|
22060
|
+
up.radio.config.pollInterval = 10000
|
22061
|
+
```
|
21456
22062
|
|
21457
22063
|
\#\#\# Controlling the source URL
|
21458
22064
|
|
@@ -21460,13 +22066,20 @@ passively receive updates from the server.
|
|
21460
22066
|
|
21461
22067
|
To reload from another URL, set an `[up-source]` attribute on the polling element:
|
21462
22068
|
|
21463
|
-
|
21464
|
-
|
21465
|
-
|
22069
|
+
```html
|
22070
|
+
<div class="unread-count" up-poll up-source="/unread-count">
|
22071
|
+
2 new messages
|
22072
|
+
</div>
|
22073
|
+
```
|
21466
22074
|
|
21467
22075
|
\#\#\# Skipping updates when nothing changed
|
21468
22076
|
|
21469
|
-
|
22077
|
+
When polling a fragment periodically we want to avoid rendering unchanged content.
|
22078
|
+
This saves <b>CPU time</b> and reduces the <b>bandwidth cost</b> for a
|
22079
|
+
request/response exchange to **~1 KB**.
|
22080
|
+
|
22081
|
+
To achieve this we timestamp your fragments with an `[up-time]` attribute to indicate
|
22082
|
+
when the underlying data was last changed. See `[up-time]` for a detailed example.
|
21470
22083
|
|
21471
22084
|
@selector [up-poll]
|
21472
22085
|
@param [up-interval]
|