unpoly-rails 2.0.0.pre.rc8 → 2.0.1
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 +127 -49
- data/README.md +2 -3
- data/dist/unpoly-migrate.js +102 -19
- data/dist/unpoly-migrate.min.js +1 -1
- data/dist/unpoly.js +1405 -808
- 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: ca1b97c24b080cd0a84254cb393b9118772b416f4383f1a4389e9c161ce6e843
|
4
|
+
data.tar.gz: cd31715c151bcb4f1966ef479b5752134ac3ae9c7245fe65054e1f78cae69d1f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f38f09fa8cdfa73f24885e406907766f1a7698361d815a5969d870c70ac02de0b660266f5c36ba4f56121ee4daadde2b54103e233fbe41b255290fea25a04d38
|
7
|
+
data.tar.gz: 0c784690fb34f37c51a6fe090b2669c49b6d3f1b6076ec50caacc6fdc3254163b59d6a80cfc62970280e3ea254709822d61ab5c3c9880a7f80d56f3cc5a4bc81
|
data/CHANGELOG.md
CHANGED
@@ -3,67 +3,145 @@ 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
|
|
11
|
+
2.0.1
|
12
|
+
-----
|
13
|
+
|
14
|
+
This bugfix release addresses some issues user reported when upgrading to Unpoly 2:
|
15
|
+
|
16
|
+
- Fix a bug where [`unpoly-migrate.js`](https://unpoly.com/changes/upgrading) would crash when loaded.
|
17
|
+
- Fix a bug where transitions would crash when some { scroll } options were also used (#187)
|
18
|
+
- Users can now now change the spacing between a popup overlay and the opening link by giving `<up-popup>` a CSS margin.
|
19
|
+
|
20
|
+
|
9
21
|
2.0.0
|
10
22
|
-----
|
11
23
|
|
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
|
-
-
|
24
|
+
Unpoly 2 ships with many new features and API improvements, unlocking many use cases that were not possible with Unpoly 1.
|
25
|
+
|
26
|
+
For an in-depth guide to all changes, see our [Unpoly 2 presentation](http://triskweline.de/unpoly2-slides/) (150 slides).
|
27
|
+
|
28
|
+
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).
|
29
|
+
|
30
|
+
### Change overview
|
31
|
+
|
32
|
+
#### Less need for boilerplate configuration
|
33
|
+
|
34
|
+
- 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.
|
35
|
+
- Unpoly can be configured to [handle all links and forms](/handling-everything), without any `[up-...]` attributes.
|
36
|
+
- We have examined many real-world Unpoly apps for repetitive configuration and made these options the new default.
|
37
|
+
|
38
|
+
#### New Layer API
|
39
|
+
|
40
|
+
- A new [layer API](/up.layer) replaces modals and popups.
|
41
|
+
- Layers can be stacked infinitely.
|
42
|
+
- 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).
|
43
|
+
- 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).
|
44
|
+
|
45
|
+
#### Subinteractions
|
46
|
+
|
47
|
+
- Overlays allow you to break up a complex screen into [subinteractions](/subinteractions).
|
48
|
+
- Subinteractions take place in overlays and may span one or many pages. The original screen remains open in the background.
|
49
|
+
- Once the subinteraction is *done*, the overlay is [closed](/closing-overlays) and a result value is communicated back to the parent layer.
|
50
|
+
|
51
|
+
#### Navigation intent
|
52
|
+
|
53
|
+
- You can now define whether a framgent update constitutes a user navigation. Switching screens needs other defaults than updating a tiny box.
|
54
|
+
- User navigation aborts earlier requests, fixing race conditions on slow connections.
|
55
|
+
|
56
|
+
#### Accessibility
|
57
|
+
|
58
|
+
- New overlays are focused automatically and trap focus in a cycle. Closing the overlay re-focuses the link that opened it.
|
59
|
+
- Focus is automatically managed when rendering major new content. A new [`[up-focus]` attribute](/focus-option) allows
|
60
|
+
you to explicitely move the user's focus as you update fragments.
|
61
|
+
- Keyboard navigation is supported everywhere.
|
62
|
+
- Focus, selection and scroll positions are preserved within an updated fragment.
|
63
|
+
|
64
|
+
#### Reworked Bootstrap integration
|
65
|
+
|
66
|
+
- The Bootstrap integration is now minimal and as unopinionated as possible. Little to no Bootstrap CSS is overridden.
|
67
|
+
- Bootstrap versions 3, 4 and 5 are now supported.
|
68
|
+
|
69
|
+
#### Quality of live improvements
|
70
|
+
|
71
|
+
- Unpoly now ships with a bandwidth-friendly [polling implementation](/up-poll) that handles many edge cases.
|
72
|
+
- 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.
|
73
|
+
- The [log](/up.log) output is more much more compact and has a calmer formatting.
|
74
|
+
- 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.
|
75
|
+
- History is no longer changed by default. Instead Unpoly updates history only when a [main target](/up-main) has changed.
|
76
|
+
- All scroll-related options have been unified in a single [`[up-scroll]` attribute](/scroll-option).
|
77
|
+
- 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.
|
78
|
+
- The client-side cache can be carefully managed by both the client and server.
|
79
|
+
- 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()`.
|
80
|
+
- Event handlers to `up:link:follow`, `up:form:submit` etc. may change the render options for the coming fragment update.
|
81
|
+
- Added more options to handle [unexpected server responses](/server-errors), including the new `up:fragment:loaded` event.
|
82
|
+
|
83
|
+
#### Extended server protocol
|
84
|
+
|
85
|
+
The optional server protocol has been extended with additional headers that the server may use to interact with the frontend. For example:
|
86
|
+
|
87
|
+
- The server may [emit events on the frontend](/X-Up-Events).
|
88
|
+
- The server may [close overlays](/X-Up-Accept).
|
89
|
+
- The server may [change the render target](/X-Up-Target) for a fragment update.
|
90
|
+
|
91
|
+
See `up.protocol` for a full list of features.
|
92
|
+
|
93
|
+
If you are using Ruby on Rails, the new protocol is already implemented by the [`unpoly-rails`](https://rubygems.org/gems/unpoly-rails) gem.
|
94
|
+
|
95
|
+
If you are using Elixir / Phoenix, the new protocol is already implemented by the [`ex_unpoly`](https://hex.pm/packages/ex_unpoly) package.
|
96
|
+
|
97
|
+
|
98
|
+
### Overview of breaking changes
|
99
|
+
|
100
|
+
Please use [`unpoly-migrate.js`](/changes/upgrading) for a very smooth upgrade process from Unpoly 0.x or 1.x to Unpoly 2.0.
|
101
|
+
|
102
|
+
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.
|
103
|
+
|
104
|
+
There's a short list of changes that we cannot fix with aliases.
|
105
|
+
|
106
|
+
#### Overlays (modals, popups) have different HTML
|
107
|
+
|
108
|
+
But it's similar. E.g. `<div class="modal">` becomes `<up-modal>`.
|
109
|
+
|
110
|
+
#### Unpoly only sees the current layer
|
111
|
+
|
112
|
+
You can target other layers with `{ layer: 'any' }`.
|
113
|
+
|
114
|
+
#### Async functions no longer wait for animations
|
115
|
+
|
116
|
+
You might or might not notice. In cases where you absolutely do need to wait, an `{ onFinished }` callback can be used.
|
117
|
+
|
118
|
+
#### Tooltips are no longer built-in
|
119
|
+
|
120
|
+
But there are a million better libraries.
|
121
|
+
|
122
|
+
|
123
|
+
### Unpoly 1 maintenance
|
124
|
+
|
125
|
+
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.
|
126
|
+
|
127
|
+
The legacy documentation for Unpoly 1.x has been archived to <https://v1.unpoly.com>.
|
128
|
+
|
60
129
|
|
61
130
|
|
62
131
|
1.0.0
|
63
132
|
-----
|
64
133
|
|
65
|
-
|
134
|
+
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.
|
135
|
+
|
136
|
+
There are only three changes from 0.62.1:
|
137
|
+
|
138
|
+
- Fix a bug where `up.util.escapeHTML()`` would not escape single quotes.
|
139
|
+
- 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.
|
140
|
+
- You may now disable the Unpoly banner in the development console with `up.log.config.banner = false`. (change by @hfjallemark).
|
141
|
+
|
142
|
+
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
143
|
|
144
|
+
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
145
|
|
68
146
|
|
69
147
|
0.62.1
|
data/README.md
CHANGED
@@ -35,6 +35,7 @@ Install dependencies for tests:
|
|
35
35
|
|
36
36
|
- Install Ruby 2.3.8
|
37
37
|
- Install Bundler by running `gem install bundler`
|
38
|
+
- Install Node.js (required for building the library)
|
38
39
|
- `cd` into `spec_app`
|
39
40
|
- Install dependencies by running `bundle install`
|
40
41
|
|
@@ -52,11 +53,9 @@ To run RSpec tests for the `unpoly-rails` gem:
|
|
52
53
|
|
53
54
|
### Making a new release
|
54
55
|
|
55
|
-
We are currently feeding
|
56
|
+
We are currently feeding two release channels:
|
56
57
|
|
57
|
-
- Manual download from GitHub
|
58
58
|
- npm
|
59
|
-
- Bower (which is based on Git and version tags)
|
60
59
|
- Rubygems (as the `unpoly-rails` gem)
|
61
60
|
|
62
61
|
We always release to all channel simultaneously.
|
data/dist/unpoly-migrate.js
CHANGED
@@ -300,6 +300,43 @@ 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 e, u;
|
306
|
+
|
307
|
+
u = up.util;
|
308
|
+
|
309
|
+
e = up.element;
|
310
|
+
|
311
|
+
up.migrate.postCompile = function(elements, compiler) {
|
312
|
+
var element, i, keepValue, len, results, value;
|
313
|
+
if (keepValue = compiler.keep) {
|
314
|
+
up.migrate.warn('The { keep: true } option for up.compiler() has been removed. Have the compiler set [up-keep] attribute instead.');
|
315
|
+
value = u.isString(keepValue) ? keepValue : '';
|
316
|
+
results = [];
|
317
|
+
for (i = 0, len = elements.length; i < len; i++) {
|
318
|
+
element = elements[i];
|
319
|
+
results.push(element.setAttribute('up-keep', value));
|
320
|
+
}
|
321
|
+
return results;
|
322
|
+
}
|
323
|
+
};
|
324
|
+
|
325
|
+
up.migrate.targetMacro = function(queryAttr, fixedResultAttrs, callback) {
|
326
|
+
return up.macro("[" + queryAttr + "]", function(link) {
|
327
|
+
var optionalTarget, resultAttrs;
|
328
|
+
resultAttrs = u.copy(fixedResultAttrs);
|
329
|
+
if (optionalTarget = link.getAttribute(queryAttr)) {
|
330
|
+
resultAttrs['up-target'] = optionalTarget;
|
331
|
+
} else {
|
332
|
+
resultAttrs['up-follow'] = '';
|
333
|
+
}
|
334
|
+
e.setMissingAttrs(link, resultAttrs);
|
335
|
+
link.removeAttribute(queryAttr);
|
336
|
+
return typeof callback === "function" ? callback() : void 0;
|
337
|
+
});
|
338
|
+
};
|
339
|
+
|
303
340
|
}).call(this);
|
304
341
|
|
305
342
|
/***
|
@@ -538,6 +575,11 @@ Returns the first descendant element matching the given selector.
|
|
538
575
|
up.migrate.renamedProperty(up.feedback.config, 'navs', 'navSelectors');
|
539
576
|
|
540
577
|
}).call(this);
|
578
|
+
|
579
|
+
/***
|
580
|
+
@module up.link
|
581
|
+
*/
|
582
|
+
|
541
583
|
(function() {
|
542
584
|
up.migrate.parseFollowOptions = function(parser) {
|
543
585
|
parser.string('flavor');
|
@@ -549,6 +591,42 @@ Returns the first descendant element matching the given selector.
|
|
549
591
|
return parser.boolean('restoreScroll');
|
550
592
|
};
|
551
593
|
|
594
|
+
|
595
|
+
/***
|
596
|
+
[Follows](/up.follow) this link as fast as possible.
|
597
|
+
|
598
|
+
This is done by:
|
599
|
+
|
600
|
+
- [Following the link through AJAX](/a-up-follow) instead of a full page load
|
601
|
+
- [Preloading the link's destination URL](/a-up-preload)
|
602
|
+
- [Triggering the link on `mousedown`](/a-up-instant) instead of on `click`
|
603
|
+
|
604
|
+
\#\#\# Example
|
605
|
+
|
606
|
+
Use `[up-dash]` like this:
|
607
|
+
|
608
|
+
<a href="/users" up-dash=".main">User list</a>
|
609
|
+
|
610
|
+
This is shorthand for:
|
611
|
+
|
612
|
+
<a href="/users" up-target=".main" up-instant up-preload>User list</a>
|
613
|
+
|
614
|
+
@selector a[up-dash]
|
615
|
+
@param [up-dash='body']
|
616
|
+
The CSS selector to replace
|
617
|
+
|
618
|
+
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)).
|
619
|
+
@deprecated
|
620
|
+
To accelerate all links use `up.link.config.instantSelectors` and `up.link.config.preloadSelectors`.
|
621
|
+
*/
|
622
|
+
|
623
|
+
up.migrate.targetMacro('up-dash', {
|
624
|
+
'up-preload': '',
|
625
|
+
'up-instant': ''
|
626
|
+
}, function() {
|
627
|
+
return up.migrate.deprecated('a[up-dash]', 'up.link.config.instantSelectors or up.link.config.preloadSelectors');
|
628
|
+
});
|
629
|
+
|
552
630
|
}).call(this);
|
553
631
|
|
554
632
|
/***
|
@@ -826,10 +904,10 @@ Returns the first descendant element matching the given selector.
|
|
826
904
|
@param {string} up-modal
|
827
905
|
The CSS selector that will be extracted from the response and displayed in a modal dialog.
|
828
906
|
@deprecated
|
829
|
-
Use `a[up-layer=modal]` instead.
|
907
|
+
Use `a[up-layer="new modal"]` instead.
|
830
908
|
*/
|
831
909
|
|
832
|
-
up.
|
910
|
+
up.migrate.targetMacro('up-modal', {
|
833
911
|
'up-layer': 'new modal'
|
834
912
|
}, function() {
|
835
913
|
return up.migrate.deprecated('a[up-modal]', 'a[up-layer="new modal"]');
|
@@ -846,16 +924,21 @@ Returns the first descendant element matching the given selector.
|
|
846
924
|
@param {string} up-drawer
|
847
925
|
The CSS selector that will be extracted from the response and displayed in a modal dialog.
|
848
926
|
@deprecated
|
849
|
-
Use `a[up-layer=drawer]` instead.
|
927
|
+
Use `a[up-layer="new drawer"]` instead.
|
850
928
|
*/
|
851
929
|
|
852
|
-
up.
|
930
|
+
up.migrate.targetMacro('up-drawer', {
|
853
931
|
'up-layer': 'new drawer'
|
854
932
|
}, function() {
|
855
933
|
return up.migrate.deprecated('a[up-drawer]', 'a[up-layer="new drawer"]');
|
856
934
|
});
|
857
935
|
|
858
936
|
}).call(this);
|
937
|
+
|
938
|
+
/***
|
939
|
+
@module up.layer
|
940
|
+
*/
|
941
|
+
|
859
942
|
(function() {
|
860
943
|
var e, u;
|
861
944
|
|
@@ -987,7 +1070,7 @@ Returns the first descendant element matching the given selector.
|
|
987
1070
|
|
988
1071
|
up.migrate.renamedEvent('up:popup:closed', 'up:layer:dismissed');
|
989
1072
|
|
990
|
-
up.
|
1073
|
+
up.migrate.targetMacro('up-popup', {
|
991
1074
|
'up-layer': 'new popup'
|
992
1075
|
}, function() {
|
993
1076
|
return up.migrate.deprecated('[up-popup]', '[up-layer="new popup"]');
|
@@ -1060,15 +1143,6 @@ This feature is now deprecated.
|
|
1060
1143
|
|
1061
1144
|
up.migrate.renamedProperty(up.network.config, 'slowDelay', 'badResponseTime');
|
1062
1145
|
|
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
1146
|
up.migrate.handleRequestOptions = function(options) {
|
1073
1147
|
return up.migrate.fixKey(options, 'data', 'params');
|
1074
1148
|
};
|
@@ -1081,11 +1155,13 @@ This feature is now deprecated.
|
|
1081
1155
|
|
1082
1156
|
\#\#\# Example
|
1083
1157
|
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1158
|
+
```
|
1159
|
+
up.ajax('/search', { params: { query: 'sunshine' } }).then(function(text) {
|
1160
|
+
console.log('The response text is %o', text)
|
1161
|
+
}).catch(function() {
|
1162
|
+
console.error('The request failed')
|
1163
|
+
})
|
1164
|
+
```
|
1089
1165
|
|
1090
1166
|
@function up.ajax
|
1091
1167
|
@param {string} [url]
|
@@ -1124,6 +1200,13 @@ This feature is now deprecated.
|
|
1124
1200
|
return up.cache.clear();
|
1125
1201
|
};
|
1126
1202
|
|
1203
|
+
up.network.preload = function() {
|
1204
|
+
var args, ref;
|
1205
|
+
args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
|
1206
|
+
up.migrate.deprecated('up.proxy.preload(link)', 'up.link.preload(link)');
|
1207
|
+
return (ref = up.link).preload.apply(ref, args);
|
1208
|
+
};
|
1209
|
+
|
1127
1210
|
|
1128
1211
|
/***
|
1129
1212
|
@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 p,o;o=up.util,p=up.element,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(a,n,u){return up.macro("["+a+"]",function(e){var t,r;return r=o.copy(n),(t=e.getAttribute(a))?r["up-target"]=t:r["up-follow"]="",p.setMissingAttrs(e,r),e.removeAttribute(a),"function"==typeof u?u():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.migrate.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.
|
8
|
+
version: "2.0.1"
|
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,12 +2590,8 @@ 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
|
2524
|
-
<<<<<<< HEAD:lib/assets/javascripts/unpoly/element.coffee
|
2525
|
-
@stable
|
2526
|
-
=======
|
2527
2593
|
@param {Element} element
|
2528
|
-
@
|
2529
|
-
>>>>>>> 0d20e224... Adjust docs:lib/assets/javascripts/unpoly/element.coffee.erb
|
2594
|
+
@stable
|
2530
2595
|
*/
|
2531
2596
|
show = function(element) {
|
2532
2597
|
return element.style.display = '';
|
@@ -2563,7 +2628,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
2563
2628
|
@function up.element.toggleClass
|
2564
2629
|
@param {Element} element
|
2565
2630
|
The element for which to add or remove the class.
|
2566
|
-
@param {
|
2631
|
+
@param {string} className
|
2567
2632
|
The class which should be added or removed.
|
2568
2633
|
@param {Boolean} [newPresent]
|
2569
2634
|
Pass `true` to add the class to the element or `false` to remove it.
|
@@ -2916,6 +2981,15 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
2916
2981
|
}
|
2917
2982
|
};
|
2918
2983
|
|
2984
|
+
/***
|
2985
|
+
@function up.element.classSelector
|
2986
|
+
@internal
|
2987
|
+
*/
|
2988
|
+
classSelector = function(klass) {
|
2989
|
+
klass = klass.replace(/:/g, '\\:');
|
2990
|
+
return "." + klass;
|
2991
|
+
};
|
2992
|
+
|
2919
2993
|
/***
|
2920
2994
|
Always creates a full document with a <html> root, even if the given `html`
|
2921
2995
|
is only a fragment.
|
@@ -3449,6 +3523,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
3449
3523
|
affix: affix,
|
3450
3524
|
toSelector: toSelector,
|
3451
3525
|
idSelector: idSelector,
|
3526
|
+
classSelector: classSelector,
|
3452
3527
|
isSingleton: isSingleton,
|
3453
3528
|
isSingletonSelector: isSingletonSelector,
|
3454
3529
|
attributeSelector: attributeSelector,
|
@@ -4993,7 +5068,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
4993
5068
|
};
|
4994
5069
|
|
4995
5070
|
CompilerPass.prototype.runCompiler = function(compiler) {
|
4996
|
-
var
|
5071
|
+
var base, i, len, match, matches;
|
4997
5072
|
matches = this.select(compiler.selector);
|
4998
5073
|
if (!matches.length) {
|
4999
5074
|
return;
|
@@ -5009,15 +5084,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
5009
5084
|
this.compileOneElement(compiler, match);
|
5010
5085
|
}
|
5011
5086
|
}
|
5012
|
-
|
5013
|
-
value = u.isString(keepValue) ? keepValue : '';
|
5014
|
-
results = [];
|
5015
|
-
for (j = 0, len1 = matches.length; j < len1; j++) {
|
5016
|
-
match = matches[j];
|
5017
|
-
results.push(match.setAttribute('up-keep', value));
|
5018
|
-
}
|
5019
|
-
return results;
|
5020
|
-
}
|
5087
|
+
return typeof (base = up.migrate).postCompile === "function" ? base.postCompile(matches, compiler) : void 0;
|
5021
5088
|
};
|
5022
5089
|
|
5023
5090
|
CompilerPass.prototype.compileOneElement = function(compiler, element) {
|
@@ -6238,8 +6305,12 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6238
6305
|
/***
|
6239
6306
|
Each layer has an `up.Layer` instance.
|
6240
6307
|
|
6241
|
-
Most functions in the `up.layer`
|
6242
|
-
|
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.
|
6243
6314
|
|
6244
6315
|
@class up.Layer
|
6245
6316
|
*/
|
@@ -6266,66 +6337,46 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6266
6337
|
|
6267
6338
|
|
6268
6339
|
/***
|
6269
|
-
|
6270
|
-
|
6271
|
-
Available layer modes are:
|
6340
|
+
Whether fragment updates within this layer can affect browser history and window title.
|
6272
6341
|
|
6273
|
-
|
6274
|
-
- `'modal'`
|
6275
|
-
- `'popup'`
|
6276
|
-
- `'drawer'`
|
6277
|
-
- `'cover'`
|
6342
|
+
If a layer does not have visible history, its desendant layers cannot have history either.
|
6278
6343
|
|
6279
|
-
@property up.Layer#
|
6280
|
-
@param {
|
6344
|
+
@property up.Layer#historyVisible
|
6345
|
+
@param {boolean} historyVisible
|
6281
6346
|
@stable
|
6282
6347
|
*/
|
6283
6348
|
|
6284
6349
|
|
6285
6350
|
/***
|
6286
|
-
|
6351
|
+
This layer's mode which governs its appearance and behavior.
|
6287
6352
|
|
6288
|
-
@
|
6289
|
-
|
6353
|
+
@see layer-terminology
|
6354
|
+
|
6355
|
+
@property up.Layer#mode
|
6356
|
+
@param {string} mode
|
6357
|
+
@stable
|
6290
6358
|
*/
|
6291
6359
|
|
6292
6360
|
|
6293
6361
|
/***
|
6294
|
-
This layer's context
|
6295
|
-
|
6296
|
-
Think of *context* as [session storage](/https://makandracards.com/makandra/32865), but specific to a [layer](/up.layer)
|
6297
|
-
rather than specific to an entire browser tab.
|
6298
|
-
|
6299
|
-
You may access the context object's properties like a regular JavaScript object.
|
6362
|
+
This layer's [context](/context).
|
6300
6363
|
|
6301
6364
|
\#\#\# Example
|
6302
6365
|
|
6366
|
+
You may access the context properties like a regular JavaScript object.
|
6367
|
+
|
6303
6368
|
```js
|
6304
6369
|
let layer = up.layer.current
|
6305
6370
|
layer.context.message = 'Please select a contact'
|
6306
6371
|
console.log(layer.context) // logs "{ message: 'Please select a contact' }"
|
6307
6372
|
```
|
6308
6373
|
|
6309
|
-
\#\#\# Accessing the context from the server
|
6310
|
-
|
6311
|
-
The context is is sent as an `X-Up-Context` header along with every
|
6312
|
-
[request](/up.request) to the server. The server may also update the updating
|
6313
|
-
layer's context by including an `X-Up-Context` header in its response.
|
6314
|
-
|
6315
6374
|
@property up.Layer#context
|
6316
6375
|
@param {Object} context
|
6317
|
-
|
6318
|
-
*/
|
6319
|
-
|
6320
|
-
|
6321
|
-
/***
|
6322
|
-
Whether fragment updates within this layer will affect [browser history](/up.history).
|
6323
|
-
|
6324
|
-
If a layer does not have visible history, its desendant layers cannot have history either.
|
6376
|
+
The context object.
|
6325
6377
|
|
6326
|
-
|
6327
|
-
@
|
6328
|
-
@stable
|
6378
|
+
If no context has been set an empty object is returned.
|
6379
|
+
@experimental
|
6329
6380
|
*/
|
6330
6381
|
|
6331
6382
|
Layer.prototype.keys = function() {
|
@@ -6384,7 +6435,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6384
6435
|
[Closes this overlay](/closing-overlays) with an accepting intent,
|
6385
6436
|
e.g. when a change was confirmed or when a value was selected.
|
6386
6437
|
|
6387
|
-
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.
|
6388
6439
|
|
6389
6440
|
@function up.Layer#accept
|
6390
6441
|
@param {any} [value]
|
@@ -6422,7 +6473,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6422
6473
|
|
6423
6474
|
|
6424
6475
|
/***
|
6425
|
-
[Closes this overlay](/closing-overlays) without an accepting intent,
|
6476
|
+
[Closes this overlay](/closing-overlays) *without* an accepting intent,
|
6426
6477
|
e.g. when a "Cancel" button was clicked.
|
6427
6478
|
|
6428
6479
|
To close an overlay with an accepting intent, use `up.Layer#accept()` instead.
|
@@ -6497,7 +6548,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6497
6548
|
/***
|
6498
6549
|
Returns whether this layer is the [root layer](/up.layer.root).
|
6499
6550
|
|
6500
|
-
@function up.Layer#
|
6551
|
+
@function up.Layer#isRoot
|
6501
6552
|
@return {boolean}
|
6502
6553
|
@stable
|
6503
6554
|
*/
|
@@ -6578,7 +6629,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6578
6629
|
|
6579
6630
|
Returns `undefined` if this layer has not opened a child layer.
|
6580
6631
|
|
6581
|
-
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
|
6582
6633
|
first dismiss the existing child before replacing it with the new child.
|
6583
6634
|
|
6584
6635
|
@property up.Layer#child
|
@@ -6594,6 +6645,10 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6594
6645
|
/***
|
6595
6646
|
Returns an array of this layer's ancestor layers.
|
6596
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
|
+
|
6597
6652
|
@property up.Layer#ancestors
|
6598
6653
|
@return {Array<up.Layer>} ancestors
|
6599
6654
|
@stable
|
@@ -6609,6 +6664,10 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6609
6664
|
|
6610
6665
|
Descendant layers are all layers that visually overlay this layer.
|
6611
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
|
+
|
6612
6671
|
@property up.Layer#descendants
|
6613
6672
|
@return {Array<up.Layer>} descendants
|
6614
6673
|
@stable
|
@@ -6668,7 +6727,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6668
6727
|
|
6669
6728
|
|
6670
6729
|
/***
|
6671
|
-
Listens to a
|
6730
|
+
Listens to a [DOM event](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Events) that originated
|
6672
6731
|
on an element [contained](/up.Layer.prototype.contains) by this layer.
|
6673
6732
|
|
6674
6733
|
This will ignore events emitted on elements in [descendant](/up.Layer.prototype.descendants) overlays,
|
@@ -6705,27 +6764,43 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6705
6764
|
up.follow(overlayLink) // listener is not called
|
6706
6765
|
|
6707
6766
|
@function up.Layer#on
|
6767
|
+
|
6708
6768
|
@param {string} types
|
6709
6769
|
A space-separated list of event types to bind to.
|
6710
|
-
|
6770
|
+
|
6771
|
+
@param {string|Function(): string} [selector]
|
6711
6772
|
The selector of an element on which the event must be triggered.
|
6712
6773
|
|
6713
6774
|
Omit the selector to listen to all events of the given type, regardless
|
6714
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
|
+
|
6715
6781
|
@param {boolean} [options.passive=false]
|
6716
6782
|
Whether to register a [passive event listener](https://developers.google.com/web/updates/2016/06/passive-event-listeners).
|
6717
6783
|
|
6718
6784
|
A passive event listener may not call `event.preventDefault()`.
|
6719
6785
|
This in particular may improve the frame rate when registering
|
6720
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
|
+
|
6721
6794
|
@param {Function(event, [element], [data])} listener
|
6722
6795
|
The listener function that should be called.
|
6723
6796
|
|
6724
6797
|
The function takes the affected element as the second argument.
|
6725
6798
|
If the element has an [`up-data`](/up-data) attribute, its value is parsed as JSON
|
6726
6799
|
and passed as a third argument.
|
6800
|
+
|
6727
6801
|
@return {Function()}
|
6728
6802
|
A function that unbinds the event listeners when called.
|
6803
|
+
|
6729
6804
|
@stable
|
6730
6805
|
*/
|
6731
6806
|
|
@@ -6740,13 +6815,12 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6740
6815
|
Unbinds an event listener previously bound with `up.Layer#on()`.
|
6741
6816
|
|
6742
6817
|
@function up.Layer#off
|
6743
|
-
@param {Element|jQuery} [element=document]
|
6744
6818
|
@param {string} events
|
6745
|
-
@param {string} [selector]
|
6819
|
+
@param {string|Function(): string} [selector]
|
6746
6820
|
@param {Function(event, [element], [data])} listener
|
6747
6821
|
The listener function to unbind.
|
6748
6822
|
|
6749
|
-
Note that you must pass a reference to the
|
6823
|
+
Note that you must pass a reference to the same function reference
|
6750
6824
|
that was passed to `up.Layer#on()` earlier.
|
6751
6825
|
@stable
|
6752
6826
|
*/
|
@@ -6918,9 +6992,9 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
6918
6992
|
/***
|
6919
6993
|
This layer's location URL.
|
6920
6994
|
|
6921
|
-
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
|
6922
6997
|
the browser's address bar will show the location of an ancestor layer.
|
6923
|
-
This property will return the URL the layer would use if it had visible history.
|
6924
6998
|
|
6925
6999
|
When this layer opens a child layer with visible history, the browser URL will change to the child
|
6926
7000
|
layer's location. When the child layer is closed, this layer's location will be restored.
|
@@ -7243,7 +7317,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
7243
7317
|
If the destruction is animated, the callback will run after the animation has finished.
|
7244
7318
|
@return {Promise}
|
7245
7319
|
A resolved promise.
|
7246
|
-
@
|
7320
|
+
@internal
|
7247
7321
|
*/
|
7248
7322
|
|
7249
7323
|
Overlay.prototype.destroyElements = function(options) {
|
@@ -7382,6 +7456,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
7382
7456
|
/***
|
7383
7457
|
@function up.Layer.OverlayWithViewport#openNow
|
7384
7458
|
@param {Element} options.content
|
7459
|
+
@internal
|
7385
7460
|
*/
|
7386
7461
|
|
7387
7462
|
OverlayWithViewport.prototype.createElements = function(content) {
|
@@ -8895,6 +8970,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
8895
8970
|
@param {string} name
|
8896
8971
|
@return {any}
|
8897
8972
|
The value of the param with the given name.
|
8973
|
+
@internal
|
8898
8974
|
*/
|
8899
8975
|
|
8900
8976
|
Params.prototype.getFirst = function(name) {
|
@@ -8913,6 +8989,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
8913
8989
|
@param {string} name
|
8914
8990
|
@return {Array}
|
8915
8991
|
An array of all values with the given name.
|
8992
|
+
@internal
|
8916
8993
|
*/
|
8917
8994
|
|
8918
8995
|
Params.prototype.getAll = function(name) {
|
@@ -9260,7 +9337,15 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9260
9337
|
|
9261
9338
|
|
9262
9339
|
/***
|
9263
|
-
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
|
+
```
|
9264
9349
|
|
9265
9350
|
@class up.RenderResult
|
9266
9351
|
*/
|
@@ -9311,17 +9396,18 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9311
9396
|
|
9312
9397
|
|
9313
9398
|
/***
|
9314
|
-
|
9315
|
-
such as the requested URL, form parameters and HTTP method.
|
9399
|
+
A normalized description of an [HTTP request](`up.request()`).
|
9316
9400
|
|
9317
9401
|
You can queue a request using the `up.request()` method:
|
9318
9402
|
|
9319
|
-
|
9320
|
-
|
9403
|
+
```js
|
9404
|
+
let request = up.request('/foo')
|
9405
|
+
console.log(request.url)
|
9321
9406
|
|
9322
|
-
|
9323
|
-
|
9324
|
-
|
9407
|
+
// A request object is also a promise for its response
|
9408
|
+
let response = await request
|
9409
|
+
console.log(response.text)
|
9410
|
+
```
|
9325
9411
|
|
9326
9412
|
@class up.Request
|
9327
9413
|
*/
|
@@ -9348,6 +9434,23 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9348
9434
|
*/
|
9349
9435
|
|
9350
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
|
+
|
9351
9454
|
/***
|
9352
9455
|
[Parameters](/up.Params) that should be sent as the request's payload.
|
9353
9456
|
|
@@ -9358,7 +9461,9 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9358
9461
|
|
9359
9462
|
|
9360
9463
|
/***
|
9361
|
-
The CSS selector
|
9464
|
+
The CSS selector targeted by this request.
|
9465
|
+
|
9466
|
+
The selector will be sent as an `X-Up-Target` header.
|
9362
9467
|
|
9363
9468
|
@property up.Request#target
|
9364
9469
|
@param {string} target
|
@@ -9367,7 +9472,10 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9367
9472
|
|
9368
9473
|
|
9369
9474
|
/***
|
9370
|
-
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.
|
9371
9479
|
|
9372
9480
|
@property up.Request#failTarget
|
9373
9481
|
@param {string} failTarget
|
@@ -9378,7 +9486,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9378
9486
|
/***
|
9379
9487
|
An object of additional HTTP headers.
|
9380
9488
|
|
9381
|
-
|
9489
|
+
Unpoly will by default send a number of custom request headers.
|
9382
9490
|
See `up.protocol` and `up.network.config.metaKeys` for details.
|
9383
9491
|
|
9384
9492
|
@property up.Request#headers
|
@@ -9414,25 +9522,71 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9414
9522
|
|
9415
9523
|
|
9416
9524
|
/***
|
9417
|
-
|
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.
|
9418
9528
|
|
9419
9529
|
@property up.Request#context
|
9420
9530
|
@param {Object} context
|
9421
|
-
@
|
9531
|
+
@experimental
|
9422
9532
|
*/
|
9423
9533
|
|
9424
9534
|
|
9425
9535
|
/***
|
9426
|
-
|
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.
|
9427
9539
|
|
9428
9540
|
@property up.Request#failContext
|
9429
9541
|
@param {Object} failContext
|
9430
|
-
@
|
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
|
9431
9583
|
*/
|
9432
9584
|
|
9433
9585
|
|
9434
9586
|
/***
|
9435
|
-
|
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.
|
9436
9590
|
|
9437
9591
|
@property up.Request#mode
|
9438
9592
|
@param {string} mode
|
@@ -9441,7 +9595,9 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9441
9595
|
|
9442
9596
|
|
9443
9597
|
/***
|
9444
|
-
|
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.
|
9445
9601
|
|
9446
9602
|
@property up.Request#failMode
|
9447
9603
|
@param {string} failMode
|
@@ -9450,7 +9606,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9450
9606
|
|
9451
9607
|
|
9452
9608
|
/***
|
9453
|
-
|
9609
|
+
The format in which the [request params](/up.Layer.prototype.params) will be encoded.
|
9454
9610
|
|
9455
9611
|
@property up.Request#contentType
|
9456
9612
|
@param {string} contentType
|
@@ -9459,13 +9615,22 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9459
9615
|
|
9460
9616
|
|
9461
9617
|
/***
|
9462
|
-
|
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.
|
9463
9621
|
|
9464
9622
|
@property up.Request#payload
|
9465
9623
|
@param {string} payload
|
9466
9624
|
@stable
|
9467
9625
|
*/
|
9468
9626
|
|
9627
|
+
|
9628
|
+
/***
|
9629
|
+
@property up.Request#preload
|
9630
|
+
@param {boolean} preload
|
9631
|
+
@experimental
|
9632
|
+
*/
|
9633
|
+
|
9469
9634
|
Request.prototype.keys = function() {
|
9470
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'];
|
9471
9636
|
};
|
@@ -9521,7 +9686,8 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9521
9686
|
Request.prototype.normalizeForCaching = function() {
|
9522
9687
|
this.method = u.normalizeMethod(this.method);
|
9523
9688
|
this.extractHashFromURL();
|
9524
|
-
|
9689
|
+
this.transferParamsToURL();
|
9690
|
+
return this.url = u.normalizeURL(this.url);
|
9525
9691
|
};
|
9526
9692
|
|
9527
9693
|
Request.prototype.evictExpensiveAttrs = function() {
|
@@ -9608,6 +9774,37 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
9608
9774
|
});
|
9609
9775
|
};
|
9610
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
|
+
|
9611
9808
|
Request.prototype.loadPage = function() {
|
9612
9809
|
up.network.abort();
|
9613
9810
|
return new up.Request.FormRenderer(this).buildAndSubmit();
|
@@ -10187,7 +10384,7 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
10187
10384
|
|
10188
10385
|
|
10189
10386
|
/***
|
10190
|
-
|
10387
|
+
A response to an [HTTP request](`up.request()`).
|
10191
10388
|
|
10192
10389
|
\#\#\# Example
|
10193
10390
|
|
@@ -10299,6 +10496,14 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
10299
10496
|
@experimental
|
10300
10497
|
*/
|
10301
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
|
+
|
10302
10507
|
Response.prototype.keys = function() {
|
10303
10508
|
return ['method', 'url', 'text', 'status', 'request', 'xhr', 'target', 'title', 'acceptLayer', 'dismissLayer', 'eventPlans', 'context', 'clearCache', 'headers'];
|
10304
10509
|
};
|
@@ -10845,7 +11050,8 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
10845
11050
|
|
10846
11051
|
}).call(this);
|
10847
11052
|
(function() {
|
10848
|
-
var e, u
|
11053
|
+
var e, u,
|
11054
|
+
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
10849
11055
|
|
10850
11056
|
u = up.util;
|
10851
11057
|
|
@@ -10853,6 +11059,8 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
10853
11059
|
|
10854
11060
|
up.Tether = (function() {
|
10855
11061
|
function Tether(options) {
|
11062
|
+
this.sync = bind(this.sync, this);
|
11063
|
+
this.scheduleSync = bind(this.scheduleSync, this);
|
10856
11064
|
var base;
|
10857
11065
|
if (typeof (base = up.migrate).handleTetherOptions === "function") {
|
10858
11066
|
base.handleTetherOptions(options);
|
@@ -10895,8 +11103,14 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
10895
11103
|
};
|
10896
11104
|
|
10897
11105
|
Tether.prototype.sync = function() {
|
10898
|
-
var anchorBox, elementBox, left, top;
|
11106
|
+
var anchorBox, elementBox, elementMargin, left, top;
|
10899
11107
|
elementBox = this.element.getBoundingClientRect();
|
11108
|
+
elementMargin = {
|
11109
|
+
top: e.styleNumber(this.element, 'marginTop'),
|
11110
|
+
right: e.styleNumber(this.element, 'marginRight'),
|
11111
|
+
bottom: e.styleNumber(this.element, 'marginBottom'),
|
11112
|
+
left: e.styleNumber(this.element, 'marginLeft')
|
11113
|
+
};
|
10900
11114
|
anchorBox = this.anchor.getBoundingClientRect();
|
10901
11115
|
left = void 0;
|
10902
11116
|
top = void 0;
|
@@ -10905,19 +11119,19 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
10905
11119
|
top = (function() {
|
10906
11120
|
switch (this.position) {
|
10907
11121
|
case 'top':
|
10908
|
-
return anchorBox.top - elementBox.height;
|
11122
|
+
return anchorBox.top - elementMargin.bottom - elementBox.height;
|
10909
11123
|
case 'bottom':
|
10910
|
-
return anchorBox.top + anchorBox.height;
|
11124
|
+
return anchorBox.top + anchorBox.height + elementMargin.top;
|
10911
11125
|
}
|
10912
11126
|
}).call(this);
|
10913
11127
|
left = (function() {
|
10914
11128
|
switch (this.align) {
|
10915
11129
|
case 'left':
|
10916
|
-
return anchorBox.left;
|
11130
|
+
return anchorBox.left + elementMargin.left;
|
10917
11131
|
case 'center':
|
10918
11132
|
return anchorBox.left + 0.5 * (anchorBox.width - elementBox.width);
|
10919
11133
|
case 'right':
|
10920
|
-
return anchorBox.left + anchorBox.width - elementBox.width;
|
11134
|
+
return anchorBox.left + anchorBox.width - elementBox.width - elementMargin.right;
|
10921
11135
|
}
|
10922
11136
|
}).call(this);
|
10923
11137
|
break;
|
@@ -10925,19 +11139,19 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
10925
11139
|
top = (function() {
|
10926
11140
|
switch (this.align) {
|
10927
11141
|
case 'top':
|
10928
|
-
return anchorBox.top;
|
11142
|
+
return anchorBox.top + elementMargin.top;
|
10929
11143
|
case 'center':
|
10930
11144
|
return anchorBox.top + 0.5 * (anchorBox.height - elementBox.height);
|
10931
11145
|
case 'bottom':
|
10932
|
-
return anchorBox.top + anchorBox.height - elementBox.height;
|
11146
|
+
return anchorBox.top + anchorBox.height - elementBox.height - elementMargin.bottom;
|
10933
11147
|
}
|
10934
11148
|
}).call(this);
|
10935
11149
|
left = (function() {
|
10936
11150
|
switch (this.position) {
|
10937
11151
|
case 'left':
|
10938
|
-
return anchorBox.left - elementBox.width;
|
11152
|
+
return anchorBox.left - elementMargin.right - elementBox.width;
|
10939
11153
|
case 'right':
|
10940
|
-
return anchorBox.left + anchorBox.width;
|
11154
|
+
return anchorBox.left + anchorBox.width + elementMargin.left;
|
10941
11155
|
}
|
10942
11156
|
}).call(this);
|
10943
11157
|
}
|
@@ -11154,37 +11368,26 @@ It complements [native `Element` methods](https://www.w3schools.com/jsref/dom_ob
|
|
11154
11368
|
Events
|
11155
11369
|
======
|
11156
11370
|
|
11157
|
-
This module contains functions to [
|
11371
|
+
This module contains functions to [emit](/up.emit) and [observe](/up.on) DOM events.
|
11158
11372
|
|
11159
|
-
While the browser also
|
11160
|
-
and
|
11161
|
-
work with DOM events, you will find the functions in this module to be more convenient and feature-rich.
|
11373
|
+
While the browser also has built-in functions to work with events,
|
11374
|
+
you will find Unpoly's functions to be very concise and feature-rich.
|
11162
11375
|
|
11163
11376
|
## Events emitted by Unpoly
|
11164
11377
|
|
11165
|
-
Most Unpoly
|
11166
|
-
|
11167
|
-
```javascript
|
11168
|
-
document.addEventListener('up:modal:opened', (event) => {
|
11169
|
-
console.log('A new modal has just opened!')
|
11170
|
-
})
|
11171
|
-
```
|
11172
|
-
|
11173
|
-
Events often have both present and past forms. For example, `up:layer:open` is emitted before an overlay starts to open.
|
11174
|
-
`up:layer:opened` is emitted when the overlay has appeared in the DOM tree.
|
11378
|
+
Most Unpoly features emit events that are prefixed with `up:`.
|
11175
11379
|
|
11176
|
-
|
11380
|
+
Unpoly's own events are documented in their respective modules, for example:
|
11177
11381
|
|
11178
|
-
|
11382
|
+
| Event | Module |
|
11383
|
+
|-----------------------|--------------------|
|
11384
|
+
| `up:link:follow` | `up.link` |
|
11385
|
+
| `up:form:submit` | `up.form` |
|
11386
|
+
| `up:layer:open` | `up.layer` |
|
11387
|
+
| `up:request:late` | `up.network` |
|
11179
11388
|
|
11180
|
-
|
11181
|
-
|
11182
|
-
if (event.url == '/evil') {
|
11183
|
-
// Prevent the modal from opening
|
11184
|
-
event.preventDefault()
|
11185
|
-
}
|
11186
|
-
})
|
11187
|
-
```
|
11389
|
+
@see up.on
|
11390
|
+
@see up.emit
|
11188
11391
|
|
11189
11392
|
@module up.event
|
11190
11393
|
*/
|
@@ -11324,12 +11527,16 @@ document.addEventListener('up:modal:open', (event) => {
|
|
11324
11527
|
Multiple event types may be passed as either a space-separated string
|
11325
11528
|
or as an array of types.
|
11326
11529
|
|
11327
|
-
@param {string} [selector]
|
11530
|
+
@param {string|Function():string} [selector]
|
11328
11531
|
The selector of an element on which the event must be triggered.
|
11329
11532
|
|
11330
11533
|
Omit the selector to listen to all events of the given type, regardless
|
11331
11534
|
of the event target.
|
11332
11535
|
|
11536
|
+
If the selector is not known in advance you may also pass a function
|
11537
|
+
that returns the selector. The function is evaluated every time
|
11538
|
+
an event with the given type is observed.
|
11539
|
+
|
11333
11540
|
@param {boolean} [options.passive=false]
|
11334
11541
|
Whether to register a [passive event listener](https://developers.google.com/web/updates/2016/06/passive-event-listeners).
|
11335
11542
|
|
@@ -11340,7 +11547,7 @@ document.addEventListener('up:modal:open', (event) => {
|
|
11340
11547
|
@param {boolean} [options.once=true]
|
11341
11548
|
Whether the listener should run at most once.
|
11342
11549
|
|
11343
|
-
If `true` the listener will automatically be
|
11550
|
+
If `true` the listener will automatically be unbound
|
11344
11551
|
after the first invocation.
|
11345
11552
|
|
11346
11553
|
@param {Function(event, [element], [data])} listener
|
@@ -11431,12 +11638,12 @@ document.addEventListener('up:modal:open', (event) => {
|
|
11431
11638
|
|
11432
11639
|
@function up.off
|
11433
11640
|
@param {Element|jQuery} [element=document]
|
11434
|
-
@param {string} events
|
11641
|
+
@param {string|Function(): string} events
|
11435
11642
|
@param {string} [selector]
|
11436
11643
|
@param {Function(event, [element], [data])} listener
|
11437
11644
|
The listener function to unbind.
|
11438
11645
|
|
11439
|
-
Note that you must pass a reference to the
|
11646
|
+
Note that you must pass a reference to the same function reference
|
11440
11647
|
that was passed to `up.on()` earlier.
|
11441
11648
|
@stable
|
11442
11649
|
*/
|
@@ -11687,8 +11894,12 @@ document.addEventListener('up:modal:open', (event) => {
|
|
11687
11894
|
|
11688
11895
|
This hyperlink will emit an `user:select` event when clicked:
|
11689
11896
|
|
11690
|
-
```
|
11691
|
-
<a href='/users/5
|
11897
|
+
```html
|
11898
|
+
<a href='/users/5'
|
11899
|
+
up-emit='user:select'
|
11900
|
+
up-emit-props='{ "id": 5, "firstName": "Alice" }'>
|
11901
|
+
Alice
|
11902
|
+
</a>
|
11692
11903
|
|
11693
11904
|
<script>
|
11694
11905
|
up.on('a', 'user:select', function(event) {
|
@@ -11703,6 +11914,7 @@ document.addEventListener('up:modal:open', (event) => {
|
|
11703
11914
|
The type of the event to be emitted.
|
11704
11915
|
@param [up-emit-props='{}']
|
11705
11916
|
The event properties, serialized as JSON.
|
11917
|
+
@stable
|
11706
11918
|
*/
|
11707
11919
|
executeEmitAttr = function(event, element) {
|
11708
11920
|
var eventProps, eventType, forkedEvent;
|
@@ -11771,7 +11983,7 @@ There are existing implementations for various web frameworks:
|
|
11771
11983
|
- [Roda](https://github.com/adam12/roda-unpoly)
|
11772
11984
|
- [Rack](https://github.com/adam12/rack-unpoly) (Sinatra, Padrino, Hanami, Cuba, ...)
|
11773
11985
|
- [Phoenix](https://elixirforum.com/t/unpoly-a-framework-like-turbolinks/3614/15) (Elixir)
|
11774
|
-
- [PHP](https://github.com/
|
11986
|
+
- [PHP](https://github.com/webstronauts/php-unpoly) (Symfony, Laravel, Stack)
|
11775
11987
|
|
11776
11988
|
@module up.protocol
|
11777
11989
|
*/
|
@@ -11994,68 +12206,35 @@ There are existing implementations for various web frameworks:
|
|
11994
12206
|
The timestamp must be explicitely set by the user as an `[up-time]` attribute on the fragment.
|
11995
12207
|
It should indicate the time when the fragment's underlying data was last changed.
|
11996
12208
|
|
11997
|
-
|
12209
|
+
See `[up-time]` for a detailed example.
|
11998
12210
|
|
11999
|
-
|
12000
|
-
|
12001
|
-
\#\#\# Example
|
12002
|
-
|
12003
|
-
You may timestamp your fragments with an `[up-time]` attribute to indicate when the underlying data
|
12004
|
-
was last changed. For instance, when the last message in a list was received from December 24th, 1:51:46 PM UTC:
|
12211
|
+
\#\#\# Format
|
12005
12212
|
|
12006
|
-
|
12007
|
-
<div class="messages" up-time="1608730818">
|
12008
|
-
...
|
12009
|
-
</div>
|
12010
|
-
```
|
12213
|
+
The time is encoded is the number of seconds elapsed since the [Unix epoch](https://en.wikipedia.org/wiki/Unix_time).
|
12011
12214
|
|
12012
|
-
|
12215
|
+
For instance, a modification date of December 23th, 1:40:18 PM UTC would produce the following header:
|
12013
12216
|
|
12014
12217
|
```http
|
12218
|
+
X-Up-Target: .unread-count
|
12015
12219
|
X-Up-Reload-From-Time: 1608730818
|
12016
12220
|
```
|
12017
12221
|
|
12018
|
-
|
12222
|
+
If no timestamp is known, Unpoly will send a value of zero (`X-Up-Reload-From-Time: 0`).
|
12019
12223
|
|
12020
|
-
|
12021
|
-
|
12224
|
+
@header X-Up-Reload-From-Time
|
12225
|
+
@stable
|
12226
|
+
*/
|
12227
|
+
contextFromXHR = function(xhr) {
|
12228
|
+
return extractHeader(xhr, 'context', JSON.parse);
|
12229
|
+
};
|
12230
|
+
|
12231
|
+
/***
|
12232
|
+
This request header contains the targeted layer's [context](/context), serialized as JSON.
|
12022
12233
|
|
12023
|
-
The
|
12024
|
-
|
12234
|
+
The user may choose to not send this header by configuring
|
12235
|
+
`up.network.config.requestMetaKeys`.
|
12025
12236
|
|
12026
|
-
|
12027
|
-
class MessagesController < ApplicationController
|
12028
|
-
|
12029
|
-
def index
|
12030
|
-
if up.reload_from_time == current_user.last_message_at
|
12031
|
-
up.render_nothing
|
12032
|
-
else
|
12033
|
-
@messages = current_user.messages.order(time: :desc).to_a
|
12034
|
-
render 'index'
|
12035
|
-
end
|
12036
|
-
end
|
12037
|
-
|
12038
|
-
end
|
12039
|
-
```
|
12040
|
-
|
12041
|
-
Only rendering when needed saves <b>CPU time</b> on your server, which spends most of its response time rendering HTML.
|
12042
|
-
|
12043
|
-
This also reduces the <b>bandwidth cost</b> for a request/response exchange to **~1 KB**.
|
12044
|
-
|
12045
|
-
@header X-Up-Reload-From-Time
|
12046
|
-
@stable
|
12047
|
-
*/
|
12048
|
-
contextFromXHR = function(xhr) {
|
12049
|
-
return extractHeader(xhr, 'context', JSON.parse);
|
12050
|
-
};
|
12051
|
-
|
12052
|
-
/***
|
12053
|
-
This request header contains the targeted layer's [context](/up.context), serialized as JSON.
|
12054
|
-
|
12055
|
-
The user may choose to not send this header by configuring
|
12056
|
-
`up.network.config.requestMetaKeys`.
|
12057
|
-
|
12058
|
-
\#\#\# Example
|
12237
|
+
\#\#\# Example
|
12059
12238
|
|
12060
12239
|
```http
|
12061
12240
|
X-Up-Context: { "lives": 3 }
|
@@ -12091,11 +12270,11 @@ There are existing implementations for various web frameworks:
|
|
12091
12270
|
the request was in flight will get overridden by the server-provided context.
|
12092
12271
|
|
12093
12272
|
@header X-Up-Context
|
12094
|
-
@
|
12273
|
+
@experimental
|
12095
12274
|
*/
|
12096
12275
|
|
12097
12276
|
/***
|
12098
|
-
This request header contains the [context](/
|
12277
|
+
This request header contains the [context](/context) of the layer
|
12099
12278
|
targeted for a failed fragment update, serialized as JSON.
|
12100
12279
|
|
12101
12280
|
A fragment update is considered *failed* if the server responds with a
|
@@ -12114,7 +12293,7 @@ There are existing implementations for various web frameworks:
|
|
12114
12293
|
```
|
12115
12294
|
|
12116
12295
|
@header X-Up-Fail-Context
|
12117
|
-
@
|
12296
|
+
@experimental
|
12118
12297
|
*/
|
12119
12298
|
|
12120
12299
|
/***
|
@@ -12274,7 +12453,7 @@ There are existing implementations for various web frameworks:
|
|
12274
12453
|
the response's HTML content.
|
12275
12454
|
|
12276
12455
|
The header value is the acceptance value serialized as a JSON object.
|
12277
|
-
To accept an overlay without value, set the header value to `null`.
|
12456
|
+
To accept an overlay without value, set the header value to the string `null`.
|
12278
12457
|
|
12279
12458
|
\#\#\# Example
|
12280
12459
|
|
@@ -12320,7 +12499,7 @@ There are existing implementations for various web frameworks:
|
|
12320
12499
|
the response's HTML content.
|
12321
12500
|
|
12322
12501
|
The header value is the dismissal value serialized as a JSON object.
|
12323
|
-
To accept an overlay without value, set the header value to `null`.
|
12502
|
+
To accept an overlay without value, set the header value to the string `null`.
|
12324
12503
|
|
12325
12504
|
\#\#\# Example
|
12326
12505
|
|
@@ -12432,10 +12611,12 @@ There are existing implementations for various web frameworks:
|
|
12432
12611
|
Configures strings used in the optional [server protocol](/up.protocol).
|
12433
12612
|
|
12434
12613
|
@property up.protocol.config
|
12614
|
+
|
12435
12615
|
@param {string} [config.csrfHeader='X-CSRF-Token']
|
12436
12616
|
The name of the HTTP header that will include the
|
12437
12617
|
[CSRF token](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Synchronizer_token_pattern)
|
12438
12618
|
for AJAX requests.
|
12619
|
+
|
12439
12620
|
@param {string|Function(): string} [config.csrfParam]
|
12440
12621
|
The `name` of the hidden `<input>` used for sending a
|
12441
12622
|
[CSRF token](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Synchronizer_token_pattern) when
|
@@ -12447,7 +12628,10 @@ There are existing implementations for various web frameworks:
|
|
12447
12628
|
|
12448
12629
|
Defaults to the `content` attribute of a `<meta>` tag named `csrf-param`:
|
12449
12630
|
|
12450
|
-
|
12631
|
+
```html
|
12632
|
+
<meta name="csrf-param" content="authenticity_token" />
|
12633
|
+
```
|
12634
|
+
|
12451
12635
|
@param {string|Function(): string} [config.csrfToken]
|
12452
12636
|
The [CSRF token](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Synchronizer_token_pattern)
|
12453
12637
|
to send for unsafe requests. The token will be sent as either a HTTP header (for AJAX requests)
|
@@ -12458,7 +12642,10 @@ There are existing implementations for various web frameworks:
|
|
12458
12642
|
|
12459
12643
|
Defaults to the `content` attribute of a `<meta>` tag named `csrf-token`:
|
12460
12644
|
|
12461
|
-
|
12645
|
+
```
|
12646
|
+
<meta name='csrf-token' content='secret12345'>
|
12647
|
+
```
|
12648
|
+
|
12462
12649
|
@param {string} [config.methodParam='_method']
|
12463
12650
|
The name of request parameter containing the original request method when Unpoly needs to wrap
|
12464
12651
|
the method.
|
@@ -12537,13 +12724,14 @@ There are existing implementations for various web frameworks:
|
|
12537
12724
|
Logging
|
12538
12725
|
=======
|
12539
12726
|
|
12540
|
-
Unpoly can print debugging information to the
|
12727
|
+
Unpoly can print debugging information to the [browser console](https://developer.chrome.com/docs/devtools/console/), e.g.:
|
12541
12728
|
|
12542
12729
|
- Which [events](/up.event) are called
|
12543
12730
|
- When we're [making requests to the network](/up.request)
|
12544
12731
|
- Which [compilers](/up.syntax) are applied to which elements
|
12545
12732
|
|
12546
|
-
|
12733
|
+
@see up.log.enable
|
12734
|
+
@see up.log.disable
|
12547
12735
|
|
12548
12736
|
@module up.log
|
12549
12737
|
*/
|
@@ -12651,7 +12839,7 @@ You can activate logging by calling [`up.log.enable()`](/up.log.enable).
|
|
12651
12839
|
return console.log(logo + text);
|
12652
12840
|
}
|
12653
12841
|
};
|
12654
|
-
up.on('up:
|
12842
|
+
up.on('up:app:boot', printBanner);
|
12655
12843
|
up.on('up:framework:reset', reset);
|
12656
12844
|
setEnabled = function(value) {
|
12657
12845
|
sessionStore.set('enabled', value);
|
@@ -12659,7 +12847,7 @@ You can activate logging by calling [`up.log.enable()`](/up.log.enable).
|
|
12659
12847
|
};
|
12660
12848
|
|
12661
12849
|
/***
|
12662
|
-
|
12850
|
+
Starts printing debugging information to the developer console.
|
12663
12851
|
|
12664
12852
|
Debugging information includes which elements are being [compiled](/up.syntax)
|
12665
12853
|
and which [events](/up.event) are being emitted.
|
@@ -12674,7 +12862,7 @@ You can activate logging by calling [`up.log.enable()`](/up.log.enable).
|
|
12674
12862
|
};
|
12675
12863
|
|
12676
12864
|
/***
|
12677
|
-
|
12865
|
+
Stops printing debugging information to the developer console.
|
12678
12866
|
|
12679
12867
|
Errors will still be printed, even with logging disabled.
|
12680
12868
|
|
@@ -12716,24 +12904,26 @@ You can activate logging by calling [`up.log.enable()`](/up.log.enable).
|
|
12716
12904
|
};
|
12717
12905
|
|
12718
12906
|
/***
|
12719
|
-
|
12720
|
-
|
12721
|
-
|
12722
|
-
|
12723
|
-
|
12724
|
-
|
12725
|
-
|
12726
|
-
|
12727
|
-
|
12728
|
-
|
12729
|
-
|
12730
|
-
|
12731
|
-
|
12732
|
-
|
12733
|
-
|
12734
|
-
|
12735
|
-
|
12736
|
-
|
12907
|
+
Registers an empty rejection handler in case the given promise
|
12908
|
+
rejects with an AbortError or a failed up.Response.
|
12909
|
+
|
12910
|
+
This prevents browsers from printing "Uncaught (in promise)" to the error
|
12911
|
+
console when the promise is rejected.
|
12912
|
+
|
12913
|
+
This is helpful for event handlers where it is clear that no rejection
|
12914
|
+
handler will be registered:
|
12915
|
+
|
12916
|
+
```js
|
12917
|
+
up.on('submit', 'form[up-target]', (event, form) => {
|
12918
|
+
promise = up.submit(form)
|
12919
|
+
up.util.muteRejection(promise)
|
12920
|
+
})
|
12921
|
+
```
|
12922
|
+
|
12923
|
+
@function up.log.muteUncriticalRejection
|
12924
|
+
@param {Promise} promise
|
12925
|
+
@return {Promise}
|
12926
|
+
@internal
|
12737
12927
|
*/
|
12738
12928
|
muteUncriticalRejection = function(promise) {
|
12739
12929
|
return promise["catch"](function(error) {
|
@@ -12769,20 +12959,11 @@ You can activate logging by calling [`up.log.enable()`](/up.log.enable).
|
|
12769
12959
|
Custom JavaScript
|
12770
12960
|
=================
|
12771
12961
|
|
12772
|
-
|
12773
|
-
in order to integrate libraries or implement custom behavior.
|
12774
|
-
|
12775
|
-
Unpoly lets you organize your JavaScript snippets using [compilers](/up.compiler).
|
12962
|
+
The `up.syntax` package lets you pair HTML elements with JavaScript behavior.
|
12776
12963
|
|
12777
|
-
|
12778
|
-
|
12779
|
-
|
12780
|
-
up.compiler('.grid', function(element) {
|
12781
|
-
new Masonry(element, { itemSelector: '.grid--item' })
|
12782
|
-
})
|
12783
|
-
|
12784
|
-
The compiler function will be called on matching elements when the page loads
|
12785
|
-
or when a matching fragment is [inserted via AJAX](/up.link) later.
|
12964
|
+
@see up.compiler
|
12965
|
+
@see [up-data]
|
12966
|
+
@see up.macro
|
12786
12967
|
|
12787
12968
|
@module up.syntax
|
12788
12969
|
*/
|
@@ -12817,14 +12998,17 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
12817
12998
|
Use compilers to activate your custom Javascript behavior on matching
|
12818
12999
|
elements.
|
12819
13000
|
|
12820
|
-
You should migrate your [`DOMContentLoaded`](https://
|
13001
|
+
You should migrate your [`DOMContentLoaded`](https://developer.mozilla.org/en-US/docs/Web/API/Window/DOMContentLoaded_event)
|
12821
13002
|
callbacks to compilers. This will make sure they run both at page load and
|
12822
13003
|
when a new fragment is inserted later.
|
12823
|
-
|
13004
|
+
See [Making JavaScripts work with fragment updates](/legacy-scripts) for advice
|
13005
|
+
on migrating legacy scripts.
|
13006
|
+
|
13007
|
+
It will also organize your JavaScript snippets by selector.
|
12824
13008
|
|
12825
13009
|
\#\#\# Example
|
12826
13010
|
|
12827
|
-
This
|
13011
|
+
This compiler will insert the current time into a
|
12828
13012
|
`<div class='current-time'></div>`:
|
12829
13013
|
|
12830
13014
|
```js
|
@@ -12885,55 +13069,34 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
12885
13069
|
|
12886
13070
|
An alternative way to register a destructor function is `up.destructor()`.
|
12887
13071
|
|
12888
|
-
\#\#\#
|
13072
|
+
\#\#\# Passing parameters to a compiler
|
12889
13073
|
|
12890
|
-
|
12891
|
-
|
12892
|
-
For instance, a container for a [Google Map](https://developers.google.com/maps/documentation/javascript/tutorial)
|
12893
|
-
might attach the location and names of its marker pins:
|
13074
|
+
Use the `[up-data]` attribute to attach structured data to a DOM element.
|
13075
|
+
The data will be parsed and passed to your compiler function.
|
12894
13076
|
|
12895
|
-
|
12896
|
-
|
12897
|
-
|
12898
|
-
{ "lat": 48.75, "lng": 11.45, "title": "Ingolstadt" }
|
12899
|
-
]'></div>
|
12900
|
-
```
|
13077
|
+
Alternatively your compiler may access attributes for the compiled element
|
13078
|
+
via the standard [`Element#getAttribute()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute)
|
13079
|
+
method.
|
12901
13080
|
|
12902
|
-
|
13081
|
+
Unpoly also provides utility functions to read an element attribute and
|
13082
|
+
cast it to a given type:
|
12903
13083
|
|
12904
|
-
|
12905
|
-
up.
|
12906
|
-
|
12907
|
-
|
12908
|
-
pins.forEach(function(pin) {
|
12909
|
-
var position = new google.maps.LatLng(pin.lat, pin.lng)
|
12910
|
-
new google.maps.Marker({
|
12911
|
-
position: position,
|
12912
|
-
map: map,
|
12913
|
-
title: pin.title
|
12914
|
-
})
|
12915
|
-
})
|
12916
|
-
})
|
12917
|
-
```
|
12918
|
-
|
12919
|
-
@see legacy-scripts
|
13084
|
+
- `up.element.booleanAttr(element, attr)`
|
13085
|
+
- `up.element.numberAttr(element, attr)`
|
13086
|
+
- `up.element.jsonAttr(element, attr)`
|
12920
13087
|
|
12921
13088
|
@function up.compiler
|
12922
13089
|
@param {string} selector
|
12923
13090
|
The selector to match.
|
12924
13091
|
@param {number} [options.priority=0]
|
12925
13092
|
The priority of this compiler.
|
13093
|
+
|
12926
13094
|
Compilers with a higher priority are run first.
|
12927
13095
|
Two compilers with the same priority are run in the order they were registered.
|
12928
13096
|
@param {boolean} [options.batch=false]
|
12929
13097
|
If set to `true` and a fragment insertion contains multiple
|
12930
|
-
elements matching the
|
12931
|
-
with
|
12932
|
-
@param {boolean} [options.keep=false]
|
12933
|
-
If set to `true` compiled fragment will be [persisted](/up-keep) during
|
12934
|
-
fragment updates.
|
12935
|
-
|
12936
|
-
This has the same effect as setting an `up-keep` attribute on the element.
|
13098
|
+
elements matching `selector`, the `compiler` function is only called once
|
13099
|
+
with all these elements.
|
12937
13100
|
@param {Function(element, data)} compiler
|
12938
13101
|
The function to call when a matching element is inserted.
|
12939
13102
|
|
@@ -12970,10 +13133,12 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
12970
13133
|
This jQuery compiler will insert the current time into a
|
12971
13134
|
`<div class='current-time'></div>`:
|
12972
13135
|
|
12973
|
-
|
12974
|
-
|
12975
|
-
|
12976
|
-
|
13136
|
+
```js
|
13137
|
+
up.$compiler('.current-time', function($element) {
|
13138
|
+
var now = new Date()
|
13139
|
+
$element.text(now.toString())
|
13140
|
+
})
|
13141
|
+
```
|
12977
13142
|
|
12978
13143
|
@function up.$compiler
|
12979
13144
|
@param {string} selector
|
@@ -12997,33 +13162,40 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
12997
13162
|
/***
|
12998
13163
|
Registers a [compiler](/up.compiler) that is run before all other compilers.
|
12999
13164
|
|
13000
|
-
|
13165
|
+
A macro lets you set UJS attributes that will be compiled afterwards.
|
13166
|
+
|
13167
|
+
If you want default attributes for *every* link and form, consider customizing your
|
13168
|
+
[navigation options](/navigation).
|
13001
13169
|
|
13002
13170
|
\#\#\# Example
|
13003
13171
|
|
13004
13172
|
You will sometimes find yourself setting the same combination of UJS attributes again and again:
|
13005
13173
|
|
13006
|
-
|
13007
|
-
|
13008
|
-
|
13174
|
+
```html
|
13175
|
+
<a href="/page1" up-layer="new modal" up-class="warning" up-animation="shake">Page 1</a>
|
13176
|
+
<a href="/page1" up-layer="new modal" up-class="warning" up-animation="shake">Page 1</a>
|
13177
|
+
<a href="/page1" up-layer="new modal" up-class="warning" up-animation="shake">Page 1</a>
|
13178
|
+
```
|
13009
13179
|
|
13010
|
-
We would much rather define a new `[
|
13180
|
+
We would much rather define a new `[smooth-link]` attribute that let's us
|
13011
13181
|
write the same links like this:
|
13012
13182
|
|
13013
|
-
|
13014
|
-
|
13015
|
-
|
13183
|
+
```html
|
13184
|
+
<a href="/page1" smooth-link>Page 1</a>
|
13185
|
+
<a href="/page2" smooth-link>Page 2</a>
|
13186
|
+
<a href="/page3" smooth-link>Page 3</a>
|
13187
|
+
```
|
13016
13188
|
|
13017
13189
|
We can define the `[content-link]` attribute by registering a macro that
|
13018
13190
|
sets the `[up-target]`, `[up-transition]` and `[up-duration]` attributes for us:
|
13019
13191
|
|
13020
|
-
|
13021
|
-
|
13022
|
-
|
13023
|
-
|
13024
|
-
|
13025
|
-
|
13026
|
-
|
13192
|
+
```
|
13193
|
+
up.macro('[smooth-link]', function(link) {
|
13194
|
+
link.setAttribute('up-target', '.content')
|
13195
|
+
link.setAttribute('up-transition', 'cross-fade')
|
13196
|
+
link.setAttribute('up-duration', '300')
|
13197
|
+
})
|
13198
|
+
```
|
13027
13199
|
|
13028
13200
|
@function up.macro
|
13029
13201
|
@param {string} selector
|
@@ -13056,13 +13228,15 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
13056
13228
|
|
13057
13229
|
\#\#\# Example
|
13058
13230
|
|
13059
|
-
|
13060
|
-
|
13061
|
-
|
13062
|
-
|
13063
|
-
|
13064
|
-
|
13065
|
-
|
13231
|
+
```js
|
13232
|
+
up.$macro('[content-link]', function($link) {
|
13233
|
+
$link.attr(
|
13234
|
+
'up-target': '.content',
|
13235
|
+
'up-transition': 'cross-fade',
|
13236
|
+
'up-duration':'300'
|
13237
|
+
)
|
13238
|
+
})
|
13239
|
+
```
|
13066
13240
|
|
13067
13241
|
@function up.$macro
|
13068
13242
|
@param {string} selector
|
@@ -13124,6 +13298,7 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
13124
13298
|
|
13125
13299
|
/***
|
13126
13300
|
Applies all compilers on the given element and its descendants.
|
13301
|
+
|
13127
13302
|
Unlike [`up.hello()`](/up.hello), this doesn't emit any events.
|
13128
13303
|
|
13129
13304
|
@function up.syntax.compile
|
@@ -13152,8 +13327,8 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
13152
13327
|
})
|
13153
13328
|
```
|
13154
13329
|
|
13155
|
-
An alternative way to register a destructor function is to
|
13156
|
-
it from your compiler function.
|
13330
|
+
An alternative way to register a destructor function is to
|
13331
|
+
[`return` it from your compiler function](/up.compiler#cleaning-up-after-yourself).
|
13157
13332
|
|
13158
13333
|
@function up.destructor
|
13159
13334
|
@param {Element} element
|
@@ -13177,6 +13352,7 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
13177
13352
|
|
13178
13353
|
/***
|
13179
13354
|
Runs any destructor on the given fragment and its descendants in the same layer.
|
13355
|
+
|
13180
13356
|
Unlike [`up.destroy()`](/up.destroy), this does not emit any events
|
13181
13357
|
and does not remove the element from the DOM.
|
13182
13358
|
|
@@ -13195,20 +13371,23 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
13195
13371
|
};
|
13196
13372
|
|
13197
13373
|
/***
|
13198
|
-
|
13199
|
-
If yes, parses the attribute value as JSON and returns the parsed object.
|
13374
|
+
Returns the given element's `[up-data]`, parsed as a JavaScript object.
|
13200
13375
|
|
13201
|
-
Returns `undefined` if the element has no `up-data` attribute.
|
13376
|
+
Returns `undefined` if the element has no `[up-data]` attribute.
|
13202
13377
|
|
13203
13378
|
\#\#\# Example
|
13204
13379
|
|
13205
13380
|
You have an element with JSON data serialized into an `up-data` attribute:
|
13206
13381
|
|
13207
|
-
|
13382
|
+
```html
|
13383
|
+
<span class='person' up-data='{ "age": 18, "name": "Bob" }'>Bob</span>
|
13384
|
+
```
|
13208
13385
|
|
13209
13386
|
Calling `up.syntax.data()` will deserialize the JSON string into a JavaScript object:
|
13210
13387
|
|
13211
|
-
|
13388
|
+
```js
|
13389
|
+
up.syntax.data('.person') // returns { age: 18, name: 'Bob' }
|
13390
|
+
```
|
13212
13391
|
|
13213
13392
|
@function up.data
|
13214
13393
|
@param {string|Element|jQuery} element
|
@@ -13221,39 +13400,49 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
13221
13400
|
*/
|
13222
13401
|
|
13223
13402
|
/***
|
13224
|
-
|
13403
|
+
Attaches structured data to an element, to be consumed by a compiler.
|
13404
|
+
|
13405
|
+
If an element with an `[up-data]` attribute enters the DOM,
|
13225
13406
|
Unpoly will parse the JSON and pass the resulting object to any matching
|
13226
|
-
[`up.compiler()`](/up.compiler)
|
13407
|
+
[`up.compiler()`](/up.compiler) functions.
|
13408
|
+
|
13409
|
+
\#\#\# Example
|
13227
13410
|
|
13228
13411
|
For instance, a container for a [Google Map](https://developers.google.com/maps/documentation/javascript/tutorial)
|
13229
13412
|
might attach the location and names of its marker pins:
|
13230
13413
|
|
13231
|
-
|
13232
|
-
|
13233
|
-
|
13234
|
-
|
13414
|
+
```html
|
13415
|
+
<div class='google-map' up-data='[
|
13416
|
+
{ "lat": 48.36, "lng": 10.99, "title": "Friedberg" },
|
13417
|
+
{ "lat": 48.75, "lng": 11.45, "title": "Ingolstadt" }
|
13418
|
+
]'></div>
|
13419
|
+
```
|
13235
13420
|
|
13236
13421
|
The JSON will be parsed and handed to your compiler as a second argument:
|
13237
13422
|
|
13238
|
-
|
13239
|
-
|
13240
|
-
|
13241
|
-
|
13242
|
-
|
13243
|
-
|
13244
|
-
|
13245
|
-
|
13246
|
-
|
13247
|
-
})
|
13423
|
+
```js
|
13424
|
+
up.compiler('.google-map', function(element, pins) {
|
13425
|
+
var map = new google.maps.Map(element)
|
13426
|
+
pins.forEach(function(pin) {
|
13427
|
+
var position = new google.maps.LatLng(pin.lat, pin.lng)
|
13428
|
+
new google.maps.Marker({
|
13429
|
+
position: position,
|
13430
|
+
map: map,
|
13431
|
+
title: pin.title
|
13248
13432
|
})
|
13433
|
+
})
|
13434
|
+
})
|
13435
|
+
```
|
13249
13436
|
|
13250
13437
|
Similarly, when an event is triggered on an element annotated with
|
13251
13438
|
[`up-data`], the parsed object will be passed to any matching
|
13252
13439
|
[`up.on()`](/up.on) handlers.
|
13253
13440
|
|
13254
|
-
|
13255
|
-
|
13256
|
-
|
13441
|
+
```js
|
13442
|
+
up.on('click', '.google-map', function(event, element, pins) {
|
13443
|
+
console.log("There are %d pins on the clicked map", pins.length)
|
13444
|
+
})
|
13445
|
+
```
|
13257
13446
|
|
13258
13447
|
@selector [up-data]
|
13259
13448
|
@param up-data
|
@@ -13306,9 +13495,10 @@ or when a matching fragment is [inserted via AJAX](/up.link) later.
|
|
13306
13495
|
History
|
13307
13496
|
========
|
13308
13497
|
|
13309
|
-
|
13498
|
+
The `up.history` module helps you work with the browser history.
|
13310
13499
|
|
13311
|
-
|
13500
|
+
@see up.history.location
|
13501
|
+
@see up:location:changed
|
13312
13502
|
|
13313
13503
|
@module up.history
|
13314
13504
|
*/
|
@@ -13333,7 +13523,7 @@ In an Unpoly app, every page has an URL.
|
|
13333
13523
|
Defines whether [fragment updates](/up.render) will update the browser's current URL.
|
13334
13524
|
|
13335
13525
|
If set to `false` Unpoly will never change the browser URL.
|
13336
|
-
@param {boolean} [config.
|
13526
|
+
@param {boolean} [config.enabled=true]
|
13337
13527
|
Whether to restore the known scroll positions
|
13338
13528
|
when the user goes back or forward in history.
|
13339
13529
|
@stable
|
@@ -13442,7 +13632,7 @@ In an Unpoly app, every page has an URL.
|
|
13442
13632
|
address bar with the given URL.
|
13443
13633
|
|
13444
13634
|
When the user restores the new history entry later,
|
13445
|
-
Unpoly will replace
|
13635
|
+
Unpoly will replace a selector from `up.history.config.restoreTargets` with the body from that URL.
|
13446
13636
|
|
13447
13637
|
Note that [fragment navigation](/navigation) will automatically update the
|
13448
13638
|
browser's location bar for you.
|
@@ -13476,7 +13666,7 @@ In an Unpoly app, every page has an URL.
|
|
13476
13666
|
|
13477
13667
|
When a [layer](/up.layer) has no [visible history](/up.Layer.prototype.historyVisible), following a link
|
13478
13668
|
will not cause the browser's address bar to be updated. In this case no `up:location:changed` event will be emitted.
|
13479
|
-
|
13669
|
+
However, a `up:layer:location:changed` will be emitted even if the address bar did not change.
|
13480
13670
|
|
13481
13671
|
@event up:location:changed
|
13482
13672
|
@param {string} event.url
|
@@ -13549,9 +13739,11 @@ In an Unpoly app, every page has an URL.
|
|
13549
13739
|
register = function() {
|
13550
13740
|
window.history.scrollRestoration = 'manual';
|
13551
13741
|
window.addEventListener('popstate', pop);
|
13552
|
-
|
13553
|
-
|
13554
|
-
|
13742
|
+
if (up.protocol.initialRequestMethod() === 'GET') {
|
13743
|
+
return replace(currentLocation(), {
|
13744
|
+
event: false
|
13745
|
+
});
|
13746
|
+
}
|
13555
13747
|
};
|
13556
13748
|
if (typeof jasmine !== "undefined" && jasmine !== null) {
|
13557
13749
|
return register();
|
@@ -13614,31 +13806,48 @@ In an Unpoly app, every page has an URL.
|
|
13614
13806
|
})();
|
13615
13807
|
|
13616
13808
|
}).call(this);
|
13809
|
+
(function() {
|
13810
|
+
var e, u,
|
13811
|
+
slice = [].slice;
|
13617
13812
|
|
13618
|
-
|
13619
|
-
Fragment update API
|
13620
|
-
===================
|
13621
|
-
|
13622
|
-
The `up.fragment` module exposes a high-level Javascript API to [update](/up.replace) or
|
13623
|
-
[destroy](/up.destroy) page fragments.
|
13813
|
+
u = up.util;
|
13624
13814
|
|
13625
|
-
|
13626
|
-
They also exist on a layer (page, modal, popup).
|
13815
|
+
e = up.element;
|
13627
13816
|
|
13628
|
-
Most of Unpoly's functionality (like [fragment links](/up.link) or [modals](/up.modal))
|
13629
|
-
is built from `up.fragment` functions. You may use them to extend Unpoly from your
|
13630
|
-
[custom Javascript](/up.syntax).
|
13631
13817
|
|
13632
|
-
|
13633
|
-
|
13634
|
-
|
13635
|
-
|
13636
|
-
|
13818
|
+
/***
|
13819
|
+
Fragment API
|
13820
|
+
===========
|
13821
|
+
|
13822
|
+
The `up.fragment` module offers a high-level JavaScript API to work with DOM elements.
|
13823
|
+
|
13824
|
+
A fragment is an element with some additional properties that are useful in the context of
|
13825
|
+
a server-rendered web application:
|
13826
|
+
|
13827
|
+
- Fragments are [identified by a CSS selector](/up.fragment.toTarget), like a `.class` or `#id`.
|
13828
|
+
- Fragments are usually updated by a [link](/a-up-follow) for [form](/form-up-submits) that targets their selector.
|
13829
|
+
When the server renders HTML with a matching element, the fragment is swapped with a new version.
|
13830
|
+
- As fragments enter the page they are automatically [compiled](/up.compiler) to activate JavaScript behavior.
|
13831
|
+
- Fragment changes may be [animated](/up.motion).
|
13832
|
+
- Fragments are placed on a [layer](/up.layer) that is isolated from other layers.
|
13833
|
+
Unpoly features will only see or change fragments from the [current layer](/up.layer.current)
|
13834
|
+
unless you [explicitly target another layer](/layer-option).
|
13835
|
+
- Fragments [know the URL from where they were loaded](/up.source).
|
13836
|
+
They can be [reloaded](/up.reload) or [polled periodically](/up-polled).
|
13837
|
+
|
13838
|
+
For low-level DOM utilities that complement the browser's native API, see `up.element`.
|
13839
|
+
|
13840
|
+
@see up.render
|
13841
|
+
@see up.navigate
|
13842
|
+
@see up.destroy
|
13843
|
+
@see up.reload
|
13844
|
+
@see up.fragment.get
|
13845
|
+
@see up.hello
|
13846
|
+
|
13847
|
+
@module up.fragment
|
13848
|
+
*/
|
13637
13849
|
|
13638
13850
|
up.fragment = (function() {
|
13639
|
-
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;
|
13640
|
-
u = up.util;
|
13641
|
-
e = up.element;
|
13642
13851
|
|
13643
13852
|
/***
|
13644
13853
|
Configures defaults for fragment updates.
|
@@ -13684,7 +13893,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13684
13893
|
The default configuration tries, in this order:
|
13685
13894
|
|
13686
13895
|
- If the URL has a `#hash`, scroll to the hash.
|
13687
|
-
- If updating a [main target](/main), reset scroll positions.
|
13896
|
+
- If updating a [main target](/up-main), reset scroll positions.
|
13688
13897
|
|
13689
13898
|
@param {boolean|string|Function(Element)} [config.autoFocus]
|
13690
13899
|
How to focus when updating a fragment with `{ focus: 'auto' }`.
|
@@ -13696,7 +13905,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13696
13905
|
- Focus a `#hash` in the URL.
|
13697
13906
|
- Focus an `[autofocus]` element in the new fragment.
|
13698
13907
|
- If focus was lost with the old fragment, focus the new fragment.
|
13699
|
-
- If updating a [main target](/main), focus the new fragment.
|
13908
|
+
- If updating a [main target](/up-main), focus the new fragment.
|
13700
13909
|
|
13701
13910
|
@param {boolean} [config.runScripts=false]
|
13702
13911
|
Whether to execute `<script>` tags in updated fragments.
|
@@ -13704,7 +13913,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13704
13913
|
Scripts will load asynchronously, with no guarantee of execution order.
|
13705
13914
|
|
13706
13915
|
If you set this to `true`, mind that the `<body>` element is a default
|
13707
|
-
[main target](/main). If you are including your global application scripts
|
13916
|
+
[main target](/up-main). If you are including your global application scripts
|
13708
13917
|
at the end of your `<body>`
|
13709
13918
|
for performance reasons, swapping the `<body>` will re-execute these scripts.
|
13710
13919
|
In that case you must configure a different main target that does not include
|
@@ -13712,6 +13921,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13712
13921
|
|
13713
13922
|
@stable
|
13714
13923
|
*/
|
13924
|
+
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;
|
13715
13925
|
config = new up.Config(function() {
|
13716
13926
|
return {
|
13717
13927
|
badTargetClasses: [/^up-/],
|
@@ -13732,13 +13942,8 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13732
13942
|
autoScroll: ['hash', 'layer-if-main']
|
13733
13943
|
};
|
13734
13944
|
});
|
13735
|
-
|
13736
|
-
|
13737
|
-
return up.layer.config.any.mainTargets;
|
13738
|
-
},
|
13739
|
-
set: function(value) {
|
13740
|
-
return up.layer.config.any.mainTargets = value;
|
13741
|
-
}
|
13945
|
+
u.delegate(config, 'mainTargets', function() {
|
13946
|
+
return up.layer.config.any;
|
13742
13947
|
});
|
13743
13948
|
reset = function() {
|
13744
13949
|
return config.reset();
|
@@ -13792,6 +13997,74 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13792
13997
|
return e.closestAttr(element, 'up-time') || '0';
|
13793
13998
|
};
|
13794
13999
|
|
14000
|
+
/***
|
14001
|
+
Sets the time when the fragment's underlying data was last changed.
|
14002
|
+
|
14003
|
+
This can be used to avoid rendering unchanged HTML when [reloading](/up.reload)
|
14004
|
+
a fragment. This saves <b>CPU time</b> and reduces the <b>bandwidth cost</b> for a
|
14005
|
+
request/response exchange to **~1 KB**.
|
14006
|
+
|
14007
|
+
\#\# Example
|
14008
|
+
|
14009
|
+
Let's say we display a list of recent messages.
|
14010
|
+
We use the `[up-poll]` attribute to reload the `.messages` fragment every 30 seconds:
|
14011
|
+
|
14012
|
+
```html
|
14013
|
+
<div class="messages" up-poll>
|
14014
|
+
...
|
14015
|
+
</div>
|
14016
|
+
```
|
14017
|
+
|
14018
|
+
The list is now always up to date. But most of the time there will not be new messages,
|
14019
|
+
and we waste resources sending the same unchanged HTML from the server.
|
14020
|
+
|
14021
|
+
We can improve this by setting an `[up-time]` attribute and the message list.
|
14022
|
+
The attribute value is the time of the most recent message.
|
14023
|
+
|
14024
|
+
The time is encoded as the number of seconds since [Unix epoch](https://en.wikipedia.org/wiki/Unix_time).
|
14025
|
+
When, for instance, the last message in a list was received from December 24th, 1:51:46 PM UTC,
|
14026
|
+
we use the following HTML:
|
14027
|
+
|
14028
|
+
```html
|
14029
|
+
<div class="messages" up-time="1608730818" up-poll>
|
14030
|
+
...
|
14031
|
+
</div>
|
14032
|
+
```
|
14033
|
+
|
14034
|
+
When reloading Unpoly will echo the `[up-time]` timestamp in an `X-Up-Reload-From-Time` header:
|
14035
|
+
|
14036
|
+
```http
|
14037
|
+
X-Up-Reload-From-Time: 1608730818
|
14038
|
+
```
|
14039
|
+
|
14040
|
+
The server can compare the time from the request with the time of the last data update.
|
14041
|
+
If no more recent data is available, the server can render nothing and respond with
|
14042
|
+
an [`X-Up-Target: :none`](/X-Up-Target) header.
|
14043
|
+
|
14044
|
+
Here is an example with [unpoly-rails](https://unpoly.com/install/rails):
|
14045
|
+
|
14046
|
+
```ruby
|
14047
|
+
class MessagesController < ApplicationController
|
14048
|
+
|
14049
|
+
def index
|
14050
|
+
if up.reload_from_time == current_user.last_message_at
|
14051
|
+
up.render_nothing
|
14052
|
+
else
|
14053
|
+
@messages = current_user.messages.order(time: :desc).to_a
|
14054
|
+
render 'index'
|
14055
|
+
end
|
14056
|
+
end
|
14057
|
+
|
14058
|
+
end
|
14059
|
+
```
|
14060
|
+
|
14061
|
+
@selector [up-time]
|
14062
|
+
@param {string} up-time
|
14063
|
+
The number of seconds between the [Unix epoch](https://en.wikipedia.org/wiki/Unix_time).
|
14064
|
+
and the time when the element's underlying data was last changed.
|
14065
|
+
@experimental
|
14066
|
+
*/
|
14067
|
+
|
13795
14068
|
/***
|
13796
14069
|
Sets this element's source URL for [reloading](/up.reload) and [polling](/up-poll)
|
13797
14070
|
|
@@ -13813,7 +14086,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13813
14086
|
</div>
|
13814
14087
|
|
13815
14088
|
@selector [up-source]
|
13816
|
-
@param {
|
14089
|
+
@param {string} up-source
|
13817
14090
|
The URL from which to reload this element.
|
13818
14091
|
@stable
|
13819
14092
|
*/
|
@@ -13823,7 +14096,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13823
14096
|
|
13824
14097
|
The current and new elements must both match the same CSS selector.
|
13825
14098
|
The selector is either given as `{ target }` option,
|
13826
|
-
or a [main target](/main) is used as default.
|
14099
|
+
or a [main target](/up-main) is used as default.
|
13827
14100
|
|
13828
14101
|
See the [fragment placement](/fragment-placement) selector for many examples for how you can target content.
|
13829
14102
|
|
@@ -13884,29 +14157,32 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13884
14157
|
|
13885
14158
|
@function up.render
|
13886
14159
|
|
13887
|
-
@param {string|Element|jQuery} [target]
|
14160
|
+
@param {string|Element|jQuery|Array<string>} [target]
|
13888
14161
|
The CSS selector to update.
|
13889
14162
|
|
13890
|
-
If omitted a [main target](/main) will be rendered.
|
14163
|
+
If omitted a [main target](/up-main) will be rendered.
|
13891
14164
|
|
13892
|
-
You
|
14165
|
+
You may also pass a DOM element or jQuery element here, in which case a selector
|
13893
14166
|
will be [inferred from the element attributes](/up.fragment.toTarget). The given element
|
13894
14167
|
will also be used as [`{ origin }`](#options.origin) for the fragment update.
|
13895
14168
|
|
14169
|
+
You may also pass an array of selector alternatives. The first selector
|
14170
|
+
matching in both old and new content will be used.
|
14171
|
+
|
13896
14172
|
Instead of passing the target as the first argument, you may also pass it as
|
13897
14173
|
a [´{ target }`](#options.target) option..
|
13898
14174
|
|
13899
|
-
@param {string|Element|jQuery} [options.target]
|
14175
|
+
@param {string|Element|jQuery|Array<string>} [options.target]
|
13900
14176
|
The CSS selector to update.
|
13901
14177
|
|
13902
|
-
|
14178
|
+
See documentation for the [`target`](#target) parameter.
|
13903
14179
|
|
13904
14180
|
@param {string|boolean} [options.fallback=false]
|
13905
14181
|
Specifies behavior if the [target selector](/up.render#options.target) is missing from the current page or the server response.
|
13906
14182
|
|
13907
14183
|
If set to a CSS selector string, Unpoly will attempt to replace that selector instead.
|
13908
14184
|
|
13909
|
-
If set to `true` Unpoly will attempt to replace a [main target](/main) instead.
|
14185
|
+
If set to `true` Unpoly will attempt to replace a [main target](/up-main) instead.
|
13910
14186
|
|
13911
14187
|
If set to `false` Unpoly will immediately reject the render promise.
|
13912
14188
|
|
@@ -13986,12 +14262,12 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
13986
14262
|
|
13987
14263
|
If set to `'auto'` history will be updated if the `{ target }` matches
|
13988
14264
|
a selector in `up.fragment.config.autoHistoryTargets`. By default this contains all
|
13989
|
-
[main targets](/main).
|
14265
|
+
[main targets](/up-main).
|
13990
14266
|
|
13991
14267
|
If set to `false`, the history will remain unchanged.
|
13992
14268
|
|
13993
14269
|
[Overlays](/up.layer) will only change the browser URL and window title if the overlay
|
13994
|
-
has [visible history](/up.layer.historyVisible), even
|
14270
|
+
has [visible history](/up.layer.historyVisible), even when `{ history: true }` is passed.
|
13995
14271
|
|
13996
14272
|
@param {string} [options.title]
|
13997
14273
|
An explicit document title to use after rendering.
|
@@ -14042,11 +14318,12 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
14042
14318
|
Also see [`up.request({ cache })`](/up.request#options.cache).
|
14043
14319
|
|
14044
14320
|
@param {boolean|string} [options.clearCache]
|
14045
|
-
Whether existing [cache](/up.cache) entries will be cleared with this request.
|
14321
|
+
Whether existing [cache](/up.cache) entries will be [cleared](/up.cache.clear) with this request.
|
14046
14322
|
|
14047
|
-
By default a non-GET request will clear the entire cache.
|
14048
14323
|
You may also pass a [URL pattern](/url-patterns) to only clear matching requests.
|
14049
14324
|
|
14325
|
+
By default a non-GET request will clear the entire cache.
|
14326
|
+
|
14050
14327
|
Also see [`up.request({ clearCache })`](/up.request#options.clearCache) and `up.network.config.clearCache`.
|
14051
14328
|
|
14052
14329
|
@param {Element|jQuery} [options.origin]
|
@@ -14071,7 +14348,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
14071
14348
|
This is only relevant when updating a layer that is not the [frontmost layer](/up.layer.front).
|
14072
14349
|
|
14073
14350
|
@param {Object} [options.context]
|
14074
|
-
An object that will be merged into the [context](/
|
14351
|
+
An object that will be merged into the [context](/context) of the current layer once the fragment is rendered.
|
14075
14352
|
|
14076
14353
|
@param {boolean} [options.keep=true]
|
14077
14354
|
Whether [`[up-keep]`](/up-keep) elements will be preserved in the updated fragment.
|
@@ -14175,7 +14452,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
14175
14452
|
@param {string|Element|jQuery} [target]
|
14176
14453
|
The CSS selector to update.
|
14177
14454
|
|
14178
|
-
If omitted a [main target](/main) will be rendered.
|
14455
|
+
If omitted a [main target](/up-main) will be rendered.
|
14179
14456
|
|
14180
14457
|
You can also pass a DOM element or jQuery element here, in which case a selector
|
14181
14458
|
will be [inferred from the element attributes](/up.fragment.target). The given element
|
@@ -14205,17 +14482,19 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
14205
14482
|
an entirely different page layout (like a maintenance page or fatal server error)
|
14206
14483
|
which should be open with a full page load:
|
14207
14484
|
|
14208
|
-
|
14209
|
-
|
14485
|
+
```js
|
14486
|
+
up.on('up:fragment:loaded', (event) => {
|
14487
|
+
let isMaintenancePage = event.response.getHeader('X-Maintenance')
|
14210
14488
|
|
14211
|
-
|
14212
|
-
|
14213
|
-
|
14489
|
+
if (isMaintenancePage) {
|
14490
|
+
// Prevent the fragment update and don't update browser history
|
14491
|
+
event.preventDefault()
|
14214
14492
|
|
14215
|
-
|
14216
|
-
|
14217
|
-
|
14218
|
-
|
14493
|
+
// Make a full page load for the same request.
|
14494
|
+
event.request.loadPage()
|
14495
|
+
}
|
14496
|
+
})
|
14497
|
+
```
|
14219
14498
|
|
14220
14499
|
Instead of preventing the update, listeners may also access the `event.renderOptions` object
|
14221
14500
|
to mutate options to the `up.render()` call that will process the server response.
|
@@ -14229,6 +14508,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
14229
14508
|
The server response.
|
14230
14509
|
@param {Object} event.renderOptions
|
14231
14510
|
Options for the `up.render()` call that will process the server response.
|
14511
|
+
@stable
|
14232
14512
|
*/
|
14233
14513
|
|
14234
14514
|
/***
|
@@ -14614,7 +14894,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
14614
14894
|
- The [`up.element.all()`](/up.element.get) function simply returns the all elements matching a selector
|
14615
14895
|
without further filtering.
|
14616
14896
|
|
14617
|
-
@function up.fragment.
|
14897
|
+
@function up.fragment.all
|
14618
14898
|
|
14619
14899
|
@param {Element|jQuery} [root=document]
|
14620
14900
|
The root element for the search. Only the root's children will be matched.
|
@@ -14849,7 +15129,8 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
14849
15129
|
|
14850
15130
|
\#\#\# Skipping updates when nothing changed
|
14851
15131
|
|
14852
|
-
|
15132
|
+
You may use the `[up-time]` attribute to avoid rendering unchanged HTML when reloading
|
15133
|
+
a fragment. See `[up-time]` for a detailed example.
|
14853
15134
|
|
14854
15135
|
@function up.reload
|
14855
15136
|
@param {string|Element|jQuery} [target]
|
@@ -14927,11 +15208,12 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
14927
15208
|
|
14928
15209
|
\#\#\# Example
|
14929
15210
|
|
14930
|
-
|
14931
|
-
|
14932
|
-
|
15211
|
+
```js
|
15212
|
+
element = up.element.createFromHTML('<span class="klass">...</span>')
|
15213
|
+
selector = up.fragment.toTarget(element) // returns '.klass'
|
15214
|
+
```
|
14933
15215
|
|
14934
|
-
@function up.
|
15216
|
+
@function up.fragment.toTarget
|
14935
15217
|
@param {string|Element|jQuery}
|
14936
15218
|
The element for which to create a selector.
|
14937
15219
|
@stable
|
@@ -14954,7 +15236,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
14954
15236
|
selector = '';
|
14955
15237
|
for (i = 0, len = goodClasses.length; i < len; i++) {
|
14956
15238
|
klass = goodClasses[i];
|
14957
|
-
selector +=
|
15239
|
+
selector += e.classSelector(klass);
|
14958
15240
|
}
|
14959
15241
|
return selector;
|
14960
15242
|
} else {
|
@@ -15104,10 +15386,13 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
15104
15386
|
When no other render target is given, Unpoly will try to find and replace a main target.
|
15105
15387
|
|
15106
15388
|
In most app layouts the main target should match the primary content area.
|
15107
|
-
The default main targets are
|
15108
|
-
|
15109
|
-
|
15110
|
-
|
15389
|
+
The default main targets are:
|
15390
|
+
|
15391
|
+
- any element with an `[up-main]` attribute
|
15392
|
+
- the HTML5 [`<main>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main) element
|
15393
|
+
- the current layer's [topmost swappable element](/layer)
|
15394
|
+
|
15395
|
+
You may configure main target selectors in `up.fragment.config.mainTargets`.
|
15111
15396
|
|
15112
15397
|
\#\#\# Example
|
15113
15398
|
|
@@ -15119,6 +15404,86 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
15119
15404
|
@experimental
|
15120
15405
|
*/
|
15121
15406
|
|
15407
|
+
/***
|
15408
|
+
Updates this element when no other render target is given.
|
15409
|
+
|
15410
|
+
\#\#\# Example
|
15411
|
+
|
15412
|
+
Many links simply replace the main content element in your application layout.
|
15413
|
+
|
15414
|
+
Unpoly lets you mark this elements as a default target using the `[up-main]` attribute:
|
15415
|
+
|
15416
|
+
```html
|
15417
|
+
<body>
|
15418
|
+
<div class="layout">
|
15419
|
+
<div class="layout--side">
|
15420
|
+
...
|
15421
|
+
</div>
|
15422
|
+
<div class="layout--content" up-main>
|
15423
|
+
...
|
15424
|
+
</div>
|
15425
|
+
</div>
|
15426
|
+
</body>
|
15427
|
+
```
|
15428
|
+
|
15429
|
+
Once a main target is configured, you no longer need `[up-target]` in a link.\
|
15430
|
+
Use `[up-follow]` and the `[up-main]` element will be replaced:
|
15431
|
+
|
15432
|
+
```html
|
15433
|
+
<a href="/foo" up-follow>...</a>
|
15434
|
+
```
|
15435
|
+
|
15436
|
+
If you want to update something more specific, you can still use `[up-target]`:
|
15437
|
+
|
15438
|
+
```html
|
15439
|
+
<a href="/foo" up-target=".profile">...</a>
|
15440
|
+
```
|
15441
|
+
|
15442
|
+
Instead of assigning `[up-main]` you may also configure an existing selector in `up.fragment.config.mainTargets`:
|
15443
|
+
|
15444
|
+
```js
|
15445
|
+
up.fragment.config.mainTargets.push('.layout--content')
|
15446
|
+
```
|
15447
|
+
|
15448
|
+
Overlays can use different main targets
|
15449
|
+
---------------------------------------
|
15450
|
+
|
15451
|
+
Overlays often use a different default selector, e.g. to exclude a navigation bar.
|
15452
|
+
|
15453
|
+
To define a different main target for an overlay, set the [layer mode](/layer-terminology) as the
|
15454
|
+
value of the `[up-main]` attribute:
|
15455
|
+
|
15456
|
+
```html
|
15457
|
+
<body>
|
15458
|
+
<div class="layout" up-main="root">
|
15459
|
+
<div class="layout--side">
|
15460
|
+
...
|
15461
|
+
</div>
|
15462
|
+
<div class="layout--content" up-main="modal">
|
15463
|
+
...
|
15464
|
+
</div>
|
15465
|
+
</div>
|
15466
|
+
</body>
|
15467
|
+
```
|
15468
|
+
|
15469
|
+
Instead of assigning `[up-main]` you may also configure layer-specific targets in `up.layer.config`:
|
15470
|
+
|
15471
|
+
```js
|
15472
|
+
up.layer.config.popup.mainTargets.push('.menu') // for popup overlays
|
15473
|
+
up.layer.config.drawer.mainTargets.push('.menu') // for drawer overlays
|
15474
|
+
up.layer.config.overlay.mainTargets.push('.layout--content') // for all overlay modes
|
15475
|
+
```
|
15476
|
+
|
15477
|
+
@selector [up-main]
|
15478
|
+
@param [up-main]
|
15479
|
+
A space-separated list of [layer modes](/layer-terminology) for which to use this main target.
|
15480
|
+
|
15481
|
+
Omit the attribute value to define a main target for *all* layer modes.
|
15482
|
+
|
15483
|
+
To use a different main target for all overlays (but not the root layer), set `[up-main=overlay]`.
|
15484
|
+
@stable
|
15485
|
+
*/
|
15486
|
+
|
15122
15487
|
/***
|
15123
15488
|
To make a server request without changing a fragment, use the `:none` selector.
|
15124
15489
|
|
@@ -15163,7 +15528,7 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
15163
15528
|
For the [root layer](/up.layer.root) it is the `<body>` element. For an overlay
|
15164
15529
|
it is the target with which the overlay was opened with.
|
15165
15530
|
|
15166
|
-
In canonical usage the topmost swappable element is often a [main element](/main).
|
15531
|
+
In canonical usage the topmost swappable element is often a [main element](/up-main).
|
15167
15532
|
|
15168
15533
|
\#\#\# Example
|
15169
15534
|
|
@@ -15260,36 +15625,39 @@ is built from `up.fragment` functions. You may use them to extend Unpoly from yo
|
|
15260
15625
|
|
15261
15626
|
up.visit = up.fragment.visit;
|
15262
15627
|
|
15628
|
+
|
15629
|
+
/***
|
15630
|
+
Returns the current [context](/context).
|
15631
|
+
|
15632
|
+
This is aliased as `up.layer.context`.
|
15633
|
+
|
15634
|
+
@property up.context
|
15635
|
+
@param {Object} context
|
15636
|
+
The context object.
|
15637
|
+
|
15638
|
+
If no context has been set an empty object is returned.
|
15639
|
+
@experimental
|
15640
|
+
*/
|
15641
|
+
|
15642
|
+
u.delegate(up, 'context', function() {
|
15643
|
+
return up.layer.current;
|
15644
|
+
});
|
15645
|
+
|
15263
15646
|
}).call(this);
|
15264
15647
|
|
15265
15648
|
/***
|
15266
15649
|
Scrolling viewports
|
15267
15650
|
===================
|
15268
15651
|
|
15269
|
-
The `up.viewport` module controls the scroll position
|
15652
|
+
The `up.viewport` module controls the scroll position and focus within scrollable containers ("viewports").
|
15270
15653
|
|
15271
15654
|
The default viewport for any web application is the main document. An application may
|
15272
15655
|
define additional viewports by giving the CSS property `{ overflow-y: scroll }` to any `<div>`.
|
15273
15656
|
|
15657
|
+
Also see documentation for the [scroll option](/scroll-option) and [focus option](focus-option).
|
15274
15658
|
|
15275
|
-
|
15276
|
-
|
15277
|
-
When following a [link to a fragment](/a-up-follow) Unpoly will automatically
|
15278
|
-
scroll the document's viewport to [reveal](/up.viewport) the updated content.
|
15279
|
-
|
15280
|
-
You should [make Unpoly aware](/up.viewport.config#config.fixedTop) of fixed elements in your
|
15281
|
-
layout, such as navigation bars or headers. Unpoly will respect these sticky
|
15282
|
-
elements when [revealing updated fragments](/up.reveal).
|
15283
|
-
|
15284
|
-
You should also [tell Unpoly](/up.viewport.config#config.viewportSelectors) when your application has more than one viewport,
|
15285
|
-
so Unpoly can pick the right viewport to scroll for each fragment update.
|
15286
|
-
|
15287
|
-
|
15288
|
-
\#\#\# Bootstrap integration
|
15289
|
-
|
15290
|
-
When using Bootstrap integration (`unpoly-bootstrap3.js` and `unpoly-bootstrap3.css`)
|
15291
|
-
Unpoly will automatically be aware of sticky Bootstrap components such as
|
15292
|
-
[fixed navbar](https://getbootstrap.com/examples/navbar-fixed-top/).
|
15659
|
+
@see up.reveal
|
15660
|
+
@see [up-fixed=top]
|
15293
15661
|
|
15294
15662
|
@module up.viewport
|
15295
15663
|
*/
|
@@ -15298,29 +15666,31 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15298
15666
|
var slice = [].slice;
|
15299
15667
|
|
15300
15668
|
up.viewport = (function() {
|
15301
|
-
var absolutize, allSelector, anchoredRight,
|
15669
|
+
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;
|
15302
15670
|
u = up.util;
|
15303
15671
|
e = up.element;
|
15304
15672
|
f = up.fragment;
|
15305
15673
|
|
15306
15674
|
/***
|
15307
|
-
Configures
|
15675
|
+
Configures defaults for scrolling.
|
15308
15676
|
|
15309
15677
|
@property up.viewport.config
|
15310
15678
|
@param {Array} [config.viewportSelectors]
|
15311
|
-
An array of CSS selectors that
|
15312
|
-
(containers that scroll their contents).
|
15679
|
+
An array of CSS selectors that match viewports.
|
15313
15680
|
@param {Array} [config.fixedTop]
|
15314
15681
|
An array of CSS selectors that find elements fixed to the
|
15315
15682
|
top edge of the screen (using `position: fixed`).
|
15683
|
+
|
15316
15684
|
See [`[up-fixed="top"]`](/up-fixed-top) for details.
|
15317
15685
|
@param {Array} [config.fixedBottom]
|
15318
|
-
An array of CSS selectors that
|
15686
|
+
An array of CSS selectors that match elements fixed to the
|
15319
15687
|
bottom edge of the screen (using `position: fixed`).
|
15688
|
+
|
15320
15689
|
See [`[up-fixed="bottom"]`](/up-fixed-bottom) for details.
|
15321
15690
|
@param {Array} [config.anchoredRight]
|
15322
15691
|
An array of CSS selectors that find elements anchored to the
|
15323
15692
|
right edge of the screen (using `right:0` with `position: fixed` or `position: absolute`).
|
15693
|
+
|
15324
15694
|
See [`[up-anchored="right"]`](/up-anchored-right) for details.
|
15325
15695
|
@param {number} [config.revealSnap]
|
15326
15696
|
When [revealing](/up.reveal) elements, Unpoly will scroll an viewport
|
@@ -15434,19 +15804,9 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15434
15804
|
};
|
15435
15805
|
|
15436
15806
|
/***
|
15437
|
-
|
15807
|
+
Scrolls the given element's viewport so the first rows of the
|
15438
15808
|
element are visible for the user.
|
15439
15809
|
|
15440
|
-
\#\#\# How Unpoly finds the viewport
|
15441
|
-
|
15442
|
-
The viewport (the container that is going to be scrolled)
|
15443
|
-
is the closest parent of the element that is either:
|
15444
|
-
|
15445
|
-
- the currently open [modal](/up.modal)
|
15446
|
-
- an element with the attribute `[up-viewport]`
|
15447
|
-
- the `<body>` element
|
15448
|
-
- an element matching the selector you have configured using `up.viewport.config.viewportSelectors.push('my-custom-selector')`
|
15449
|
-
|
15450
15810
|
\#\#\# Fixed elements obstructing the viewport
|
15451
15811
|
|
15452
15812
|
Many applications have a navigation bar fixed to the top or bottom,
|
@@ -15454,14 +15814,16 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15454
15814
|
|
15455
15815
|
You can make `up.reveal()` aware of these fixed elements
|
15456
15816
|
so it can scroll the viewport far enough so the revealed element is fully visible.
|
15457
|
-
To make `up.reveal()` aware fixed elements you can either:
|
15817
|
+
To make `up.reveal()` aware of fixed elements you can either:
|
15458
15818
|
|
15459
15819
|
- give the element an attribute [`up-fixed="top"`](/up-fixed-top) or [`up-fixed="bottom"`](up-fixed-bottom)
|
15460
15820
|
- [configure default options](/up.viewport.config) for `fixedTop` or `fixedBottom`
|
15461
15821
|
|
15462
15822
|
@function up.reveal
|
15823
|
+
|
15463
15824
|
@param {string|Element|jQuery} element
|
15464
15825
|
The element to reveal.
|
15826
|
+
|
15465
15827
|
@param {number} [options.scrollSpeed=1]
|
15466
15828
|
The speed of the scrolling motion when scrolling with `{ behavior: 'smooth' }`.
|
15467
15829
|
|
@@ -15469,6 +15831,7 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15469
15831
|
[native smooth scrolling](https://developer.mozilla.org/en-US/docs/Web/API/ScrollToOptions/behavior).
|
15470
15832
|
|
15471
15833
|
Defaults to `up.viewport.config.scrollSpeed`.
|
15834
|
+
|
15472
15835
|
@param {string} [options.revealSnap]
|
15473
15836
|
When the the revealed element would be closer to the viewport's top edge
|
15474
15837
|
than this value, Unpoly will scroll the viewport to the top.
|
@@ -15476,35 +15839,40 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15476
15839
|
Set to `0` to disable snapping.
|
15477
15840
|
|
15478
15841
|
Defaults to `up.viewport.config.revealSnap`.
|
15842
|
+
|
15479
15843
|
@param {string|Element|jQuery} [options.viewport]
|
15480
15844
|
The scrolling element to scroll.
|
15481
15845
|
|
15482
15846
|
Defaults to the [given element's viewport](/up.viewport.closest).
|
15847
|
+
|
15483
15848
|
@param {boolean} [options.top]
|
15484
15849
|
Whether to scroll the viewport so that the first element row aligns
|
15485
15850
|
with the top edge of the viewport.
|
15486
15851
|
|
15487
15852
|
Defaults to `up.viewport.config.revealTop`.
|
15853
|
+
|
15488
15854
|
@param {string}[options.behavior='auto']
|
15489
15855
|
When set to `'auto'`, this will immediately scroll to the new position.
|
15490
15856
|
|
15491
15857
|
When set to `'smooth'`, this will scroll smoothly to the new position.
|
15858
|
+
|
15492
15859
|
@param {number}[options.speed]
|
15493
15860
|
The speed of the scrolling motion when scrolling with `{ behavior: 'smooth' }`.
|
15494
15861
|
|
15495
15862
|
Defaults to `up.viewport.config.scrollSpeed`.
|
15863
|
+
|
15496
15864
|
@param {number} [options.padding]
|
15497
15865
|
The desired padding between the revealed element and the
|
15498
15866
|
closest [viewport](/up.viewport) edge (in pixels).
|
15499
15867
|
|
15500
15868
|
Defaults to `up.viewport.config.revealPadding`.
|
15869
|
+
|
15501
15870
|
@param {number|boolean} [options.snap]
|
15502
15871
|
Whether to snap to the top of the viewport if the new scroll position
|
15503
15872
|
after revealing the element is close to the top edge.
|
15504
15873
|
|
15505
15874
|
Defaults to `up.viewport.config.revealSnap`.
|
15506
|
-
|
15507
|
-
Whether to close overlays obscuring the layer of `element`.
|
15875
|
+
|
15508
15876
|
@return {Promise}
|
15509
15877
|
A promise that fulfills when the element is revealed.
|
15510
15878
|
|
@@ -15513,13 +15881,12 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15513
15881
|
|
15514
15882
|
When the scrolling is not animated, the promise will fulfill
|
15515
15883
|
in the next [microtask](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/).
|
15884
|
+
|
15516
15885
|
@stable
|
15517
15886
|
*/
|
15518
15887
|
reveal = function(element, options) {
|
15519
15888
|
var motion;
|
15520
|
-
options = u.options(options
|
15521
|
-
peel: true
|
15522
|
-
});
|
15889
|
+
options = u.options(options);
|
15523
15890
|
element = f.get(element, options);
|
15524
15891
|
if (!(options.layer = up.layer.get(element))) {
|
15525
15892
|
return up.error.failed.async('Cannot reveal a detached element');
|
@@ -15532,7 +15899,19 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15532
15899
|
};
|
15533
15900
|
|
15534
15901
|
/***
|
15535
|
-
|
15902
|
+
Focuses the given element.
|
15903
|
+
|
15904
|
+
Focusing an element will also [reveal](/up.reveal) it, unless `{ preventScroll: true }` is passed.
|
15905
|
+
|
15906
|
+
@function up.focus
|
15907
|
+
|
15908
|
+
@param {string|Element|jQuery} element
|
15909
|
+
The element to focus.
|
15910
|
+
|
15911
|
+
@param {[options.preventScroll=false]}
|
15912
|
+
Whether to prevent changes to the acroll position.
|
15913
|
+
|
15914
|
+
@experimental
|
15536
15915
|
*/
|
15537
15916
|
doFocus = function(element, options) {
|
15538
15917
|
var oldScrollTop, viewport;
|
@@ -15557,13 +15936,6 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15557
15936
|
doFocus(element, options);
|
15558
15937
|
return element === document.activeElement;
|
15559
15938
|
};
|
15560
|
-
autofocus = function(element, options) {
|
15561
|
-
var autofocusElement;
|
15562
|
-
if (autofocusElement = e.subtree(element, '[autofocus]')[0]) {
|
15563
|
-
doDocus(autofocusElement, options);
|
15564
|
-
return true;
|
15565
|
-
}
|
15566
|
-
};
|
15567
15939
|
isNativelyFocusable = function(element) {
|
15568
15940
|
return e.matches(element, 'a[href], button, textarea, input, select');
|
15569
15941
|
};
|
@@ -15633,6 +16005,9 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15633
16005
|
Returns a list of all the viewports contained within the
|
15634
16006
|
given selector or element.
|
15635
16007
|
|
16008
|
+
If the given element is itself a viewport, the element is included
|
16009
|
+
in the returned list.
|
16010
|
+
|
15636
16011
|
@function up.viewport.subtree
|
15637
16012
|
@param {string|Element|jQuery} target
|
15638
16013
|
@param {Object} options
|
@@ -15825,30 +16200,11 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
15825
16200
|
|
15826
16201
|
The scroll positions will be associated with the current URL.
|
15827
16202
|
They can later be restored by calling [`up.viewport.restoreScroll()`](/up.viewport.restoreScroll)
|
15828
|
-
at the same URL, or by following a link with an [`[
|
16203
|
+
at the same URL, or by following a link with an [`[scroll="restore"]`](/a-up-follow#up-restore-scroll)
|
15829
16204
|
attribute.
|
15830
16205
|
|
15831
|
-
Unpoly automatically saves scroll positions before
|
15832
|
-
|
15833
|
-
|
15834
|
-
\#\#\# Examples
|
15835
|
-
|
15836
|
-
Should you need to save the current scroll positions outside of a [fragment update](/up.replace),
|
15837
|
-
you may call:
|
15838
|
-
|
15839
|
-
up.viewport.saveScroll()
|
15840
|
-
|
15841
|
-
Instead of saving the current scroll positions for the current URL, you may also pass another
|
15842
|
-
url or vertical scroll positionsfor each viewport:
|
15843
|
-
|
15844
|
-
up.viewport.saveScroll({
|
15845
|
-
url: '/inbox',
|
15846
|
-
tops: {
|
15847
|
-
'body': 0,
|
15848
|
-
'.sidebar', 100,
|
15849
|
-
'.main', 320
|
15850
|
-
}
|
15851
|
-
})
|
16206
|
+
Unpoly automatically saves scroll positions before [navigating](/navigation).
|
16207
|
+
You will rarely need to call this function yourself.
|
15852
16208
|
|
15853
16209
|
@function up.viewport.saveScroll
|
15854
16210
|
@param {string} [options.location]
|
@@ -16175,7 +16531,6 @@ Unpoly will automatically be aware of sticky Bootstrap components such as
|
|
16175
16531
|
absolutize: absolutize,
|
16176
16532
|
focus: doFocus,
|
16177
16533
|
tryFocus: tryFocus,
|
16178
|
-
autofocus: autofocus,
|
16179
16534
|
makeFocusable: makeFocusable
|
16180
16535
|
});
|
16181
16536
|
})();
|
@@ -16194,11 +16549,16 @@ Animation
|
|
16194
16549
|
|
16195
16550
|
When you [update a page fragment](/up.link) you can animate the change.
|
16196
16551
|
|
16197
|
-
|
16198
|
-
|
16199
|
-
to smoothly fade out the old element while fading in the new element:
|
16552
|
+
You can add an attribute [`[up-transition]`](/a-up-transition) to your
|
16553
|
+
links or forms to smoothly fade out the old element while fading in the new element:
|
16200
16554
|
|
16201
|
-
|
16555
|
+
```html
|
16556
|
+
<a href="/users"
|
16557
|
+
up-target=".list"
|
16558
|
+
up-transition="cross-fade">
|
16559
|
+
Show users
|
16560
|
+
</a>
|
16561
|
+
```
|
16202
16562
|
|
16203
16563
|
\#\#\# Transitions vs. animations
|
16204
16564
|
|
@@ -16206,10 +16566,17 @@ When we morph between an old and a new element, we call it a *transition*.
|
|
16206
16566
|
In contrast, when we animate a new element without simultaneously removing an
|
16207
16567
|
old element, we call it an *animation*.
|
16208
16568
|
|
16209
|
-
An example for an animation is opening a new
|
16210
|
-
of the dialog by adding an [`[up-animation]`](/a-up-
|
16569
|
+
An example for an animation is opening a new overlay. We can animate the appearance
|
16570
|
+
of the dialog by adding an [`[up-animation]`](/a-up-animation) attribute to the opening link:
|
16211
16571
|
|
16212
|
-
|
16572
|
+
```html
|
16573
|
+
<a href="/users"
|
16574
|
+
up-target=".list"
|
16575
|
+
up-layer="new"
|
16576
|
+
up-animation="move-from-top">
|
16577
|
+
Show users
|
16578
|
+
</a>
|
16579
|
+
```
|
16213
16580
|
|
16214
16581
|
\#\#\# Which animations are available?
|
16215
16582
|
|
@@ -16219,12 +16586,16 @@ and [predefined animations](/up.animate#named-animations).
|
|
16219
16586
|
You can define custom animations using `up.transition()` and
|
16220
16587
|
`up.animation()`.
|
16221
16588
|
|
16589
|
+
@see a[up-transition]
|
16590
|
+
@see up.animation
|
16591
|
+
@see up.transition
|
16592
|
+
|
16222
16593
|
@module up.motion
|
16223
16594
|
*/
|
16224
16595
|
|
16225
16596
|
(function() {
|
16226
16597
|
up.motion = (function() {
|
16227
|
-
var
|
16598
|
+
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;
|
16228
16599
|
u = up.util;
|
16229
16600
|
e = up.element;
|
16230
16601
|
namedAnimations = {};
|
@@ -16242,9 +16613,12 @@ You can define custom animations using `up.transition()` and
|
|
16242
16613
|
|
16243
16614
|
See [W3C documentation](http://www.w3.org/TR/css3-transitions/#transition-timing-function)
|
16244
16615
|
for a list of pre-defined timing functions.
|
16245
|
-
@param {boolean} [config.enabled
|
16616
|
+
@param {boolean} [config.enabled]
|
16246
16617
|
Whether animation is enabled.
|
16247
16618
|
|
16619
|
+
By default animations are enabled, unless the user has configured their
|
16620
|
+
system to [minimize non-essential motion](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion).
|
16621
|
+
|
16248
16622
|
Set this to `false` to disable animation globally.
|
16249
16623
|
This can be useful in full-stack integration tests.
|
16250
16624
|
@stable
|
@@ -16286,15 +16660,19 @@ You can define custom animations using `up.transition()` and
|
|
16286
16660
|
|
16287
16661
|
\#\#\# Example
|
16288
16662
|
|
16289
|
-
|
16663
|
+
```js
|
16664
|
+
up.animate('.warning', 'fade-in')
|
16665
|
+
```
|
16290
16666
|
|
16291
16667
|
You can pass additional options:
|
16292
16668
|
|
16293
|
-
|
16294
|
-
|
16295
|
-
|
16296
|
-
|
16297
|
-
|
16669
|
+
```
|
16670
|
+
up.animate('.warning', 'fade-in', {
|
16671
|
+
delay: 1000,
|
16672
|
+
duration: 250,
|
16673
|
+
easing: 'linear'
|
16674
|
+
})
|
16675
|
+
```
|
16298
16676
|
|
16299
16677
|
\#\#\# Named animations
|
16300
16678
|
|
@@ -16319,9 +16697,11 @@ You can define custom animations using `up.transition()` and
|
|
16319
16697
|
By passing an object instead of an animation name, you can animate
|
16320
16698
|
the CSS properties of the given element:
|
16321
16699
|
|
16322
|
-
|
16323
|
-
|
16324
|
-
|
16700
|
+
```
|
16701
|
+
var warning = document.querySelector('.warning')
|
16702
|
+
warning.style.opacity = 0
|
16703
|
+
up.animate(warning, { opacity: 1 })
|
16704
|
+
```
|
16325
16705
|
|
16326
16706
|
CSS properties must be given in `kebab-case`, not `camelCase`.
|
16327
16707
|
|
@@ -16357,7 +16737,6 @@ You can define custom animations using `up.transition()` and
|
|
16357
16737
|
var animationFn, runNow, willRun;
|
16358
16738
|
element = up.fragment.get(element);
|
16359
16739
|
options = u.options(options);
|
16360
|
-
applyConfig(options);
|
16361
16740
|
animationFn = findAnimationFn(animation);
|
16362
16741
|
willRun = willAnimate(element, animation, options);
|
16363
16742
|
if (willRun) {
|
@@ -16370,6 +16749,7 @@ You can define custom animations using `up.transition()` and
|
|
16370
16749
|
}
|
16371
16750
|
};
|
16372
16751
|
willAnimate = function(element, animationOrTransition, options) {
|
16752
|
+
applyConfig(options);
|
16373
16753
|
return isEnabled() && !isNone(animationOrTransition) && options.duration > 0 && !e.isSingleton(element);
|
16374
16754
|
};
|
16375
16755
|
skipAnimate = function(element, animation) {
|
@@ -16378,7 +16758,6 @@ You can define custom animations using `up.transition()` and
|
|
16378
16758
|
}
|
16379
16759
|
return Promise.resolve();
|
16380
16760
|
};
|
16381
|
-
animCount = 0;
|
16382
16761
|
|
16383
16762
|
/***
|
16384
16763
|
Animates the given element's CSS properties using CSS transitions.
|
@@ -16428,7 +16807,7 @@ You can define custom animations using `up.transition()` and
|
|
16428
16807
|
Animations are completed by jumping to the last animation frame instantly.
|
16429
16808
|
Promises returned by animation and transition functions instantly settle.
|
16430
16809
|
|
16431
|
-
Emits the `up:motion:finish` event that is
|
16810
|
+
Emits the `up:motion:finish` event that is handled by `up.animate()`.
|
16432
16811
|
|
16433
16812
|
Does nothing if there are no animation to complete.
|
16434
16813
|
|
@@ -16552,7 +16931,7 @@ You can define custom animations using `up.transition()` and
|
|
16552
16931
|
});
|
16553
16932
|
trackable = function() {
|
16554
16933
|
var promise;
|
16555
|
-
promise = scrollNew();
|
16934
|
+
promise = Promise.resolve(scrollNew());
|
16556
16935
|
promise = promise.then(function() {
|
16557
16936
|
var scrollTopAfterReveal;
|
16558
16937
|
scrollTopAfterReveal = viewport.scrollTop;
|
@@ -16626,18 +17005,20 @@ You can define custom animations using `up.transition()` and
|
|
16626
17005
|
});
|
16627
17006
|
|
16628
17007
|
/***
|
16629
|
-
Defines a named transition that [morphs](/up.
|
17008
|
+
Defines a named transition that [morphs](/up.morph) from one element to another.
|
16630
17009
|
|
16631
17010
|
\#\#\# Example
|
16632
17011
|
|
16633
17012
|
Here is the definition of the pre-defined `cross-fade` animation:
|
16634
17013
|
|
16635
|
-
|
16636
|
-
|
16637
|
-
|
16638
|
-
|
16639
|
-
|
16640
|
-
|
17014
|
+
```js
|
17015
|
+
up.transition('cross-fade', (oldElement, newElement, options) ->
|
17016
|
+
Promise.all([
|
17017
|
+
up.animate(oldElement, 'fade-out', options),
|
17018
|
+
up.animate(newElement, 'fade-in', options)
|
17019
|
+
])
|
17020
|
+
)
|
17021
|
+
```
|
16641
17022
|
|
16642
17023
|
It is recommended that your transitions use [`up.animate()`](/up.animate),
|
16643
17024
|
passing along the `options` that were passed to you.
|
@@ -16672,10 +17053,12 @@ You can define custom animations using `up.transition()` and
|
|
16672
17053
|
|
16673
17054
|
Here is the definition of the pre-defined `fade-in` animation:
|
16674
17055
|
|
16675
|
-
|
16676
|
-
|
16677
|
-
|
16678
|
-
|
17056
|
+
```js
|
17057
|
+
up.animation('fade-in', function(element, options) {
|
17058
|
+
element.style.opacity = 0
|
17059
|
+
up.animate(element, { opacity: 1 }, options)
|
17060
|
+
})
|
17061
|
+
```
|
16679
17062
|
|
16680
17063
|
It is recommended that your definitions always end by calling
|
16681
17064
|
calling [`up.animate()`](/up.animate) with an object argument, passing along
|
@@ -16684,7 +17067,7 @@ You can define custom animations using `up.transition()` and
|
|
16684
17067
|
If you choose to *not* use `up.animate()` and roll your own
|
16685
17068
|
animation code instead, your code must honor the following contract:
|
16686
17069
|
|
16687
|
-
1. It must honor the options `{ duration, easing }
|
17070
|
+
1. It must honor the options `{ duration, easing }`, if given.
|
16688
17071
|
2. It must *not* remove any of the given elements from the DOM.
|
16689
17072
|
3. It returns a promise that is fulfilled when the transition has ended
|
16690
17073
|
4. If during the animation an event `up:motion:finish` is emitted on
|
@@ -16743,7 +17126,7 @@ You can define custom animations using `up.transition()` and
|
|
16743
17126
|
e.setStyle(element, translateCSS(0, 0));
|
16744
17127
|
return element.getBoundingClientRect();
|
16745
17128
|
};
|
16746
|
-
|
17129
|
+
registerMoveAnimations = function(direction, boxToTransform) {
|
16747
17130
|
var animationFromName, animationToName;
|
16748
17131
|
animationToName = "move-to-" + direction;
|
16749
17132
|
animationFromName = "move-from-" + direction;
|
@@ -16761,22 +17144,22 @@ You can define custom animations using `up.transition()` and
|
|
16761
17144
|
return animateNow(element, translateCSS(0, 0), options);
|
16762
17145
|
});
|
16763
17146
|
};
|
16764
|
-
|
17147
|
+
registerMoveAnimations('top', function(box) {
|
16765
17148
|
var travelDistance;
|
16766
17149
|
travelDistance = box.top + box.height;
|
16767
17150
|
return translateCSS(0, -travelDistance);
|
16768
17151
|
});
|
16769
|
-
|
17152
|
+
registerMoveAnimations('bottom', function(box) {
|
16770
17153
|
var travelDistance;
|
16771
17154
|
travelDistance = up.viewport.rootHeight() - box.top;
|
16772
17155
|
return translateCSS(0, travelDistance);
|
16773
17156
|
});
|
16774
|
-
|
17157
|
+
registerMoveAnimations('left', function(box) {
|
16775
17158
|
var travelDistance;
|
16776
17159
|
travelDistance = box.left + box.width;
|
16777
17160
|
return translateCSS(-travelDistance, 0);
|
16778
17161
|
});
|
16779
|
-
|
17162
|
+
registerMoveAnimations('right', function(box) {
|
16780
17163
|
var travelDistance;
|
16781
17164
|
travelDistance = up.viewport.rootWidth() - box.left;
|
16782
17165
|
return translateCSS(travelDistance, 0);
|
@@ -16791,10 +17174,17 @@ You can define custom animations using `up.transition()` and
|
|
16791
17174
|
[Follows](/a-up-follow) this link and swaps in the new fragment
|
16792
17175
|
with an animated transition.
|
16793
17176
|
|
17177
|
+
Note that transitions are not possible when replacing the `body`
|
17178
|
+
element.
|
17179
|
+
|
16794
17180
|
\#\#\# Example
|
16795
17181
|
|
16796
17182
|
```html
|
16797
|
-
<a href="/page2"
|
17183
|
+
<a href="/page2"
|
17184
|
+
up-target=".story"
|
17185
|
+
up-transition="move-left">
|
17186
|
+
Next page
|
17187
|
+
</a>
|
16798
17188
|
```
|
16799
17189
|
|
16800
17190
|
@selector a[up-transition]
|
@@ -16806,6 +17196,7 @@ You can define custom animations using `up.transition()` and
|
|
16806
17196
|
The transition to use when the server responds with an error code.
|
16807
17197
|
|
16808
17198
|
@see server-errors
|
17199
|
+
@stable
|
16809
17200
|
*/
|
16810
17201
|
|
16811
17202
|
/***
|
@@ -16815,7 +17206,9 @@ You can define custom animations using `up.transition()` and
|
|
16815
17206
|
\#\#\# Example
|
16816
17207
|
|
16817
17208
|
```html
|
16818
|
-
<form action="/tasks"
|
17209
|
+
<form action="/tasks"
|
17210
|
+
up-target=".content"
|
17211
|
+
up-transition="cross-fade">
|
16819
17212
|
...
|
16820
17213
|
</form>
|
16821
17214
|
```
|
@@ -16829,6 +17222,7 @@ You can define custom animations using `up.transition()` and
|
|
16829
17222
|
The transition to use when the server responds with an error code.
|
16830
17223
|
|
16831
17224
|
@see server-errors
|
17225
|
+
@stable
|
16832
17226
|
*/
|
16833
17227
|
up.on('up:framework:boot', warnIfDisabled);
|
16834
17228
|
up.on('up:framework:reset', reset);
|
@@ -16869,43 +17263,25 @@ You can define custom animations using `up.transition()` and
|
|
16869
17263
|
Network requests
|
16870
17264
|
================
|
16871
17265
|
|
16872
|
-
|
17266
|
+
Unpoly ships with an optimized HTTP client for fast and effective
|
17267
|
+
communication with your server-side app.
|
16873
17268
|
|
16874
|
-
|
17269
|
+
While you can use the browser's native `fetch()` function,
|
17270
|
+
Unpoly's `up.request()` has a number of convenience features:
|
16875
17271
|
|
16876
|
-
|
17272
|
+
- Requests may be [cached](/up.request#options.cache) to reuse responses and enable [preloading](/a-up-preload).
|
17273
|
+
- Requests send [additional HTTP headers](/up.protocol) that the server may use to optimize its response.
|
17274
|
+
For example, when updating a [fragment](/up.fragment), the fragment's selector is automatically sent
|
17275
|
+
as an `X-Up-Target` header. The server may choose to only render the targeted fragment.
|
17276
|
+
- Useful events like `up:request:loaded` or `up:request:late` are emitted throughout the request/response
|
17277
|
+
lifecycle.
|
17278
|
+
- When too many requests are sent concurrently, excessive requests are [queued](/up.network.config#config.concurrency).
|
17279
|
+
This prevents exhausting the user's bandwidth and limits race conditions in end-to-end tests.
|
17280
|
+
- A very concise API requiring zero boilerplate code.
|
16877
17281
|
|
16878
|
-
|
16879
|
-
|
16880
|
-
|
16881
|
-
you explicitly pass a `{ cache: false }` option or set an `up-cache="false"` attribute.
|
16882
|
-
|
16883
|
-
The cache holds up to 50 responses for 5 minutes. You can configure the cache size and expiry using
|
16884
|
-
[`up.network.config`](/up.network.config), or clear the cache manually using [`up.cache.clear()`](/up.cache.clear).
|
16885
|
-
|
16886
|
-
Also the entire cache is cleared with every non-`GET` request (like `POST` or `PUT`).
|
16887
|
-
|
16888
|
-
If you need to make cache-aware requests from your [custom JavaScript](/up.syntax),
|
16889
|
-
use [`up.request()`](/up.request).
|
16890
|
-
|
16891
|
-
\#\#\# Preloading links
|
16892
|
-
|
16893
|
-
Unpoly also lets you speed up reaction times by [preloading
|
16894
|
-
links](/a-up-preload) when the user hovers over the click area (or puts the mouse/finger
|
16895
|
-
down). This way the response will already be cached when
|
16896
|
-
the user releases the mouse/finger.
|
16897
|
-
|
16898
|
-
\#\#\# Spinners
|
16899
|
-
|
16900
|
-
You can listen to the [`up:request:late`](/up:request:late) event to implement a spinner
|
16901
|
-
that appears during a long-running request.
|
16902
|
-
|
16903
|
-
\#\#\# More acceleration
|
16904
|
-
|
16905
|
-
Other Unpoly modules contain even more tricks to outsmart network latency:
|
16906
|
-
|
16907
|
-
- [Instantaneous feedback for links that are currently loading](/a.up-active)
|
16908
|
-
- [Follow links on `mousedown` instead of `click`](/a-up-instant)
|
17282
|
+
@see up.request
|
17283
|
+
@see up.Response
|
17284
|
+
@see up:request:late
|
16909
17285
|
|
16910
17286
|
@module up.network
|
16911
17287
|
*/
|
@@ -16923,8 +17299,8 @@ You can define custom animations using `up.transition()` and
|
|
16923
17299
|
Additional requests are queued. [Preload](/a-up-preload) requests are
|
16924
17300
|
always queued behind non-preload requests.
|
16925
17301
|
|
16926
|
-
You might find it useful to set the request concurrency `1` in
|
16927
|
-
|
17302
|
+
You might find it useful to set the request concurrency `1` in end-to-end tests
|
17303
|
+
to prevent race conditions.
|
16928
17304
|
|
16929
17305
|
Note that your browser might [impose its own request limit](http://www.browserscope.org/?category=network)
|
16930
17306
|
regardless of what you configure here.
|
@@ -17026,7 +17402,7 @@ You can define custom animations using `up.transition()` and
|
|
17026
17402
|
|
17027
17403
|
@stable
|
17028
17404
|
*/
|
17029
|
-
var abortRequests, cache, config, handleCaching, isBusy, isIdle, isSafeMethod, makeRequest, mimicLocalRequest, parseRequestOptions,
|
17405
|
+
var abortRequests, cache, config, handleCaching, isBusy, isIdle, isSafeMethod, makeRequest, mimicLocalRequest, parseRequestOptions, queue, queueRequest, registerAliasForRedirect, reset, shouldReduceRequests, useCachedRequest;
|
17030
17406
|
config = new up.Config(function() {
|
17031
17407
|
return {
|
17032
17408
|
concurrency: 4,
|
@@ -17084,13 +17460,24 @@ You can define custom animations using `up.transition()` and
|
|
17084
17460
|
/***
|
17085
17461
|
Removes all [cache](/up.cache.get) entries.
|
17086
17462
|
|
17087
|
-
|
17088
|
-
|
17089
|
-
|
17463
|
+
To only remove some cache entries, pass a [URL pattern](/url-patterns):
|
17464
|
+
|
17465
|
+
```js
|
17466
|
+
up.cache.clear('/users/*')
|
17467
|
+
```
|
17468
|
+
|
17469
|
+
\#\#\# Other reasons the cache may clear
|
17470
|
+
|
17471
|
+
By default Unpoly automatically clears the entire cache whenever it processes
|
17472
|
+
a request with an non-GET HTTP method. To customize this rule, use `up.network.config.clearCache`.
|
17090
17473
|
|
17091
17474
|
The server may also clear the cache by sending an [`X-Up-Cache: clear`](/X-Up-Cache) header.
|
17092
17475
|
|
17093
17476
|
@function up.cache.clear
|
17477
|
+
@param {string} [pattern]
|
17478
|
+
A [URL pattern](/url-patterns) matching cache entries that should be cleared.
|
17479
|
+
|
17480
|
+
If omitted, the entire cache is cleared.
|
17094
17481
|
@stable
|
17095
17482
|
*/
|
17096
17483
|
|
@@ -17148,39 +17535,45 @@ You can define custom animations using `up.transition()` and
|
|
17148
17535
|
Makes an AJAX request to the given URL.
|
17149
17536
|
|
17150
17537
|
Returns an `up.Request` object which contains information about the request.
|
17151
|
-
|
17538
|
+
This request object is also a promise for an `up.Response` that contains
|
17539
|
+
the response text, headers, etc.
|
17152
17540
|
|
17153
17541
|
\#\#\# Example
|
17154
17542
|
|
17155
|
-
|
17156
|
-
|
17543
|
+
```js
|
17544
|
+
let request = up.request('/search', { params: { query: 'sunshine' } })
|
17545
|
+
console.log('We made a request to', request.url)
|
17157
17546
|
|
17158
|
-
|
17159
|
-
|
17547
|
+
let response = await request
|
17548
|
+
console.log('The response text is', response.text)
|
17549
|
+
```
|
17160
17550
|
|
17161
17551
|
\#\#\# Error handling
|
17162
17552
|
|
17163
17553
|
The returned promise will fulfill with an `up.Response` when the server
|
17164
17554
|
responds with an HTTP status of 2xx (like `200`).
|
17165
17555
|
|
17166
|
-
When the server responds with an error code (like `422` or `500`), the promise
|
17556
|
+
When the server responds with an HTTP error code (like `422` or `500`), the promise
|
17167
17557
|
will *reject* with `up.Response`.
|
17168
17558
|
|
17169
17559
|
When the request fails from a fatal error (like a timeout or loss of connectivity),
|
17170
17560
|
the promise will reject with an [`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) object.
|
17171
17561
|
|
17172
|
-
Here is an example for a complete control flow that
|
17562
|
+
Here is an example for a complete control flow that handles both HTTP error codes
|
17563
|
+
and fatal errors:
|
17173
17564
|
|
17174
|
-
|
17175
|
-
|
17176
|
-
|
17177
|
-
|
17178
|
-
|
17179
|
-
|
17180
|
-
|
17181
|
-
|
17182
|
-
|
17183
|
-
|
17565
|
+
```js
|
17566
|
+
try {
|
17567
|
+
let response = await up.request('/search', { params: { query: 'sunshine' } })
|
17568
|
+
console.log('Successful response with text:', response.text)
|
17569
|
+
} catch (e) {
|
17570
|
+
if (e instanceof up.Response) {
|
17571
|
+
console.log('Server responded with HTTP status %s and text %s', e.status, e.text)
|
17572
|
+
} else {
|
17573
|
+
console.log('Fatal error during request:', e.message)
|
17574
|
+
}
|
17575
|
+
}
|
17576
|
+
```
|
17184
17577
|
|
17185
17578
|
\#\#\# Caching
|
17186
17579
|
|
@@ -17223,10 +17616,13 @@ You can define custom animations using `up.transition()` and
|
|
17223
17616
|
|
17224
17617
|
With `{ cache: false }` (the default) Unpoly will always make a network request.
|
17225
17618
|
|
17226
|
-
@param {boolean} [options.clearCache]
|
17227
|
-
Whether to clear the cache after this request.
|
17619
|
+
@param {boolean|string} [options.clearCache]
|
17620
|
+
Whether to [clear](/up.cache.clear) the [cache](/up.cache.get) after this request.
|
17621
|
+
|
17622
|
+
You may also pass a [URL pattern](/url-patterns) to only clear matching requests.
|
17228
17623
|
|
17229
|
-
Defaults to the result of `up.network.config.clearCache
|
17624
|
+
Defaults to the result of `up.network.config.clearCache`, which
|
17625
|
+
defaults to clearing the entire cache after a non-GET request.
|
17230
17626
|
|
17231
17627
|
@param {Object} [options.headers={}]
|
17232
17628
|
An object of additional HTTP headers.
|
@@ -17251,13 +17647,13 @@ You can define custom animations using `up.transition()` and
|
|
17251
17647
|
@param {string} [options.target='body']
|
17252
17648
|
The CSS selector that will be sent as an `X-Up-Target` header.
|
17253
17649
|
|
17254
|
-
@param {string} [options.layer='current']
|
17255
|
-
The [layer](/up.layer) this request is associated with.
|
17256
|
-
|
17257
17650
|
@param {string} [options.failTarget='body']
|
17258
17651
|
The CSS selector that will be sent as an `X-Up-Fail-Target` header.
|
17259
17652
|
|
17260
17653
|
@param {string} [options.layer='current']
|
17654
|
+
The [layer](/up.layer) this request is associated with.
|
17655
|
+
|
17656
|
+
@param {string} [options.failLayer='current']
|
17261
17657
|
The [layer](/up.layer) this request is associated with if the server [sends a HTTP status code](/server-errors).
|
17262
17658
|
|
17263
17659
|
@param {Element} [options.origin]
|
@@ -17309,16 +17705,6 @@ You can define custom animations using `up.transition()` and
|
|
17309
17705
|
return cache.clear(clearCache);
|
17310
17706
|
}
|
17311
17707
|
};
|
17312
|
-
preload = function() {
|
17313
|
-
var args, base, options;
|
17314
|
-
args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
|
17315
|
-
if (typeof (base = up.migrate).handleNetworkPreloadArgs === "function") {
|
17316
|
-
base.handleNetworkPreloadArgs.apply(base, args);
|
17317
|
-
}
|
17318
|
-
options = parseRequestOptions(args);
|
17319
|
-
options.preload = true;
|
17320
|
-
return makeRequest(options);
|
17321
|
-
};
|
17322
17708
|
parseRequestOptions = function(args) {
|
17323
17709
|
var base, options;
|
17324
17710
|
options = u.extractOptions(args);
|
@@ -17430,18 +17816,24 @@ You can define custom animations using `up.transition()` and
|
|
17430
17816
|
|
17431
17817
|
Without arguments, this will abort all pending requests:
|
17432
17818
|
|
17433
|
-
|
17819
|
+
```js
|
17820
|
+
up.network.abort()
|
17821
|
+
```
|
17434
17822
|
|
17435
17823
|
To abort a given `up.Request` object, pass it as the first argument:
|
17436
17824
|
|
17437
|
-
|
17438
|
-
|
17825
|
+
```js
|
17826
|
+
let request = up.request('/path')
|
17827
|
+
up.network.abort(request)
|
17828
|
+
```
|
17439
17829
|
|
17440
17830
|
To abort all requests matching a condition, pass a function that takes a request
|
17441
17831
|
and returns a boolean value. Unpoly will abort all request for which the given
|
17442
17832
|
function returns `true`. E.g. to abort all requests with a HTTP method as `GET`:
|
17443
17833
|
|
17444
|
-
|
17834
|
+
```js
|
17835
|
+
up.network.abort((request) => request.method == 'GET')
|
17836
|
+
```
|
17445
17837
|
|
17446
17838
|
@function up.network.abort
|
17447
17839
|
@param {up.Request|boolean|Function(up.Request): boolean} [matcher=true]
|
@@ -17603,7 +17995,6 @@ You can define custom animations using `up.transition()` and
|
|
17603
17995
|
up.on('up:framework:reset', reset);
|
17604
17996
|
return {
|
17605
17997
|
request: makeRequest,
|
17606
|
-
preload: preload,
|
17607
17998
|
cache: cache,
|
17608
17999
|
isIdle: isIdle,
|
17609
18000
|
isBusy: isBusy,
|
@@ -17635,15 +18026,30 @@ You can define custom animations using `up.transition()` and
|
|
17635
18026
|
Layers
|
17636
18027
|
======
|
17637
18028
|
|
17638
|
-
|
18029
|
+
Unpoly allows you to [open page fragments in an overlay](/opening-overlays). Overlays may be stacked infinitely.
|
18030
|
+
|
18031
|
+
A variety of [overlay modes](/layer-terminology) are supported,
|
18032
|
+
such as modal dialogs, popup overlays or drawers. You may [customize their appearance and behavior](/customizing-overlays).
|
18033
|
+
|
18034
|
+
Layers are isolated, meaning a screen in one layer will not accidentally see elements
|
18035
|
+
or events from another layer. For instance, [fragment links](/up.link) will only update elements from the [current layer](/up.layer.current)
|
18036
|
+
unless you [explicitly target another layer](/layer-option).
|
18037
|
+
|
18038
|
+
Overlays allow you to break up a complex screen into [subinteractions](/subinteractions).
|
18039
|
+
Subinteractions take place in overlays and may span one or many pages. The original screen remains open in the background.
|
18040
|
+
Once the subinteraction is *done*, the overlay is closed and a result value is communicated back to the parent layer.
|
18041
|
+
|
18042
|
+
@see a[up-layer=new]
|
18043
|
+
@see up.layer.current
|
18044
|
+
@see up.layer.on
|
18045
|
+
@see up.layer.ask
|
17639
18046
|
|
17640
18047
|
@module up.layer
|
17641
18048
|
*/
|
17642
18049
|
|
17643
18050
|
up.layer = (function() {
|
17644
|
-
var LAYER_CLASSES, OVERLAY_CLASSES,
|
18051
|
+
var LAYER_CLASSES, OVERLAY_CLASSES, anySelector, api, ask, build, closeCallbackAttr, config, handlers, mainTargets, modeConfigs, normalizeOptions, open, openCallbackAttr, optionToString, reset, stack;
|
17645
18052
|
OVERLAY_CLASSES = [up.Layer.Modal, up.Layer.Popup, up.Layer.Drawer, up.Layer.Cover];
|
17646
|
-
OVERLAY_MODES = u.map(OVERLAY_CLASSES, 'mode');
|
17647
18053
|
LAYER_CLASSES = [up.Layer.Root].concat(OVERLAY_CLASSES);
|
17648
18054
|
|
17649
18055
|
/***
|
@@ -17682,7 +18088,7 @@ You can define custom animations using `up.transition()` and
|
|
17682
18088
|
up.layer.config.modal.openAnimation = 'move-from-top'
|
17683
18089
|
```
|
17684
18090
|
|
17685
|
-
To configure an additional [main target](/main)
|
18091
|
+
To configure an additional [main target](/up-main)
|
17686
18092
|
for overlay of any mode:
|
17687
18093
|
|
17688
18094
|
```js
|
@@ -17841,16 +18247,17 @@ You can define custom animations using `up.transition()` and
|
|
17841
18247
|
});
|
17842
18248
|
|
17843
18249
|
/***
|
17844
|
-
|
18250
|
+
A list of layers that are currently open.
|
18251
|
+
|
18252
|
+
The first element in the list is the [root layer](/up.layer.root).
|
18253
|
+
The last element is the [frontmost layer](/up.layer.front).
|
17845
18254
|
|
17846
|
-
@
|
18255
|
+
@property up.layer.stack
|
18256
|
+
@param {List<up.Layer>} stack
|
17847
18257
|
@stable
|
17848
18258
|
*/
|
17849
18259
|
stack = null;
|
17850
18260
|
handlers = [];
|
17851
|
-
isOverlayMode = function(mode) {
|
17852
|
-
return u.contains(OVERLAY_MODES, mode);
|
17853
|
-
};
|
17854
18261
|
mainTargets = function(mode) {
|
17855
18262
|
return u.flatMap(modeConfigs(mode), 'mainTargets');
|
17856
18263
|
};
|
@@ -17974,7 +18381,7 @@ You can define custom animations using `up.transition()` and
|
|
17974
18381
|
How the overlay may be [dismissed](/closing-overlays) by the user.
|
17975
18382
|
|
17976
18383
|
Supported values are `'key'`, `'outside'` and `'button'`.
|
17977
|
-
See [
|
18384
|
+
See [customizing dismiss controls](/closing-overlays#customizing-dismiss-controls)
|
17978
18385
|
for details.
|
17979
18386
|
|
17980
18387
|
You may enable multiple dismiss controls by passing an array or
|
@@ -17988,7 +18395,7 @@ You can define custom animations using `up.transition()` and
|
|
17988
18395
|
If set to `true` the overlay location and title will be shown in browser UI.
|
17989
18396
|
|
17990
18397
|
If set to `'auto'` history will be visible if the initial overlay
|
17991
|
-
content matches a [main target](/main).
|
18398
|
+
content matches a [main target](/up-main).
|
17992
18399
|
|
17993
18400
|
@param {string|Function} [options.animation]
|
17994
18401
|
The opening animation.
|
@@ -18087,22 +18494,61 @@ You can define custom animations using `up.transition()` and
|
|
18087
18494
|
};
|
18088
18495
|
|
18089
18496
|
/***
|
18090
|
-
|
18091
|
-
|
18092
|
-
|
18497
|
+
This event is emitted before an overlay is opened.
|
18498
|
+
|
18499
|
+
The overlay is not yet part of the [layer stack](/up.layer.stack) and has not yet been placed
|
18500
|
+
in the DOM. Listeners may prevent this event to prevent the overlay from opening.
|
18501
|
+
|
18502
|
+
The event is emitted on the `document`.
|
18503
|
+
|
18504
|
+
\#\#\# Changing layer options
|
18505
|
+
|
18506
|
+
Listeners may inspect and manipulate options for the overlay that is about to open.
|
18507
|
+
|
18508
|
+
For example, to give overlays the CSS class `.warning` if the initial URL contains
|
18509
|
+
the word `"confirm"`:
|
18510
|
+
|
18511
|
+
```js
|
18512
|
+
up.on('up:layer:open', function(event) {
|
18513
|
+
if (event.layerOptions.url.includes('confirm')) {
|
18514
|
+
event.layerOptions.class = 'warning'
|
18515
|
+
}
|
18516
|
+
})
|
18517
|
+
```
|
18093
18518
|
|
18094
18519
|
@event up:layer:open
|
18095
18520
|
@param {Object} event.layerOptions
|
18521
|
+
Options for the overlay that is about to open.
|
18522
|
+
|
18523
|
+
Listeners may inspect and change the options.
|
18524
|
+
All options for `up.layer.open()` may be used.
|
18096
18525
|
@param {Element} event.origin
|
18526
|
+
The link element that is opening the overlay.
|
18527
|
+
@param event.preventDefault()
|
18528
|
+
Event listeners may call this method to prevent the overlay from opening.
|
18097
18529
|
@stable
|
18098
18530
|
*/
|
18099
18531
|
|
18100
18532
|
/***
|
18101
|
-
|
18533
|
+
This event is emitted after a new overlay has been placed into the DOM.
|
18534
|
+
|
18535
|
+
The event is emitted right before the opening animation starts. Because the overlay
|
18536
|
+
has not been rendered by the browser, this makes it a good occasion to
|
18537
|
+
[customize overlay elements](/customizing-overlays#customizing-overlay-elements):
|
18538
|
+
|
18539
|
+
```js
|
18540
|
+
up.on('up:layer:opened', function(event) {
|
18541
|
+
if (isChristmas()) {
|
18542
|
+
up.element.affix(event.layer.element, '.santa-hat', text: 'Merry Christmas!')
|
18543
|
+
}
|
18544
|
+
})
|
18545
|
+
```
|
18102
18546
|
|
18103
18547
|
@event up:layer:opened
|
18104
18548
|
@param {Element} event.origin
|
18549
|
+
The link element that is opening the overlay.
|
18105
18550
|
@param {up.Layer} event.layer
|
18551
|
+
The [layer object](/up.Layer) that is opening.
|
18106
18552
|
@stable
|
18107
18553
|
*/
|
18108
18554
|
|
@@ -18110,7 +18556,7 @@ You can define custom animations using `up.transition()` and
|
|
18110
18556
|
This event is emitted after a layer's [location property](/up.Layer.prototype.location)
|
18111
18557
|
has changed value.
|
18112
18558
|
|
18113
|
-
This event is also emitted when a layer [without history](/up.Layer.prototype.historyVisible)
|
18559
|
+
This event is also emitted when a layer [without visible history](/up.Layer.prototype.historyVisible)
|
18114
18560
|
has reached a new location.
|
18115
18561
|
|
18116
18562
|
@param {string} event.location
|
@@ -18146,6 +18592,7 @@ You can define custom animations using `up.transition()` and
|
|
18146
18592
|
A promise that will settle when the overlay closes.
|
18147
18593
|
|
18148
18594
|
When the overlay was accepted, the promise will fulfill with the overlay's acceptance value.
|
18595
|
+
|
18149
18596
|
When the overlay was dismissed, the promise will reject with the overlay's dismissal value.
|
18150
18597
|
|
18151
18598
|
@stable
|
@@ -18177,7 +18624,7 @@ You can define custom animations using `up.transition()` and
|
|
18177
18624
|
};
|
18178
18625
|
|
18179
18626
|
/***
|
18180
|
-
[Follows](/a-up-follow) this link and opens the result in a new
|
18627
|
+
[Follows](/a-up-follow) this link and opens the result in a new overlay.
|
18181
18628
|
|
18182
18629
|
\#\#\# Example
|
18183
18630
|
|
@@ -18218,12 +18665,12 @@ You can define custom animations using `up.transition()` and
|
|
18218
18665
|
If set to `true` the overlay location and title will be shown in browser UI.
|
18219
18666
|
|
18220
18667
|
If set to `'auto'` history will be visible if the initial overlay
|
18221
|
-
content matches a [main target](/main).
|
18668
|
+
content matches a [main target](/up-main).
|
18222
18669
|
|
18223
18670
|
@param [up-dismissable]
|
18224
18671
|
How the overlay may be [dismissed](/closing-overlays) by the user.
|
18225
18672
|
|
18226
|
-
See [
|
18673
|
+
See [customizing dismiss controls](/closing-overlays#customizing-dismiss-controls)
|
18227
18674
|
for details.
|
18228
18675
|
|
18229
18676
|
You may enable multiple dismiss controls by passing a space-separated string.
|
@@ -18421,12 +18868,33 @@ You can define custom animations using `up.transition()` and
|
|
18421
18868
|
The *current* layer is usually the [frontmost layer](/up.layer.front).
|
18422
18869
|
There are however some cases where the current layer is a layer in the background:
|
18423
18870
|
|
18424
|
-
- While an element in a background layer is [compiled](/up.compiler).
|
18871
|
+
- While an element in a background layer is being [compiled](/up.compiler).
|
18425
18872
|
- While an Unpoly event like `up:request:loaded` is being triggered from a background layer.
|
18426
|
-
- While
|
18873
|
+
- While an event listener bound to a background layer using `up.Layer#on()` is being called.
|
18427
18874
|
|
18428
18875
|
To temporarily change the current layer from your own code, use `up.Layer#asCurrent()`.
|
18429
18876
|
|
18877
|
+
\#\#\# Remembering the current layer
|
18878
|
+
|
18879
|
+
Most functions in the `up.layer` package affect the current layer. E.g. `up.layer.dismiss()`
|
18880
|
+
is shorthand for `up.layer.current.dismiss()`.
|
18881
|
+
|
18882
|
+
As described above `up.layer.current` is set to the right layer in compilers and most events,
|
18883
|
+
even if that layer is not the frontmost layer.
|
18884
|
+
|
18885
|
+
If you have async code, the current layer may change when your callback is called.
|
18886
|
+
To address this you may retrieve the current layer for later reference:
|
18887
|
+
|
18888
|
+
```js
|
18889
|
+
function dismissCurrentLayerIn(seconds) {
|
18890
|
+
let savedLayer = up.layer.current // returns an up.Layer object
|
18891
|
+
let dismiss = () => savedLayer.dismiss()
|
18892
|
+
setTimeout(dismiss, seconds * 1000)
|
18893
|
+
}
|
18894
|
+
|
18895
|
+
dismissCurrentLayerIn(10) //
|
18896
|
+
```
|
18897
|
+
|
18430
18898
|
@property up.layer.current
|
18431
18899
|
@param {up.Layer} current
|
18432
18900
|
@stable
|
@@ -18470,6 +18938,9 @@ You can define custom animations using `up.transition()` and
|
|
18470
18938
|
/***
|
18471
18939
|
Returns the [root layer](/layer-terminology).
|
18472
18940
|
|
18941
|
+
The root layer represents the initial page before any overlay was [opened](/opening-overlays).
|
18942
|
+
The root layer always exists and cannot be closed.
|
18943
|
+
|
18473
18944
|
@property up.layer.root
|
18474
18945
|
@param {up.Layer} root
|
18475
18946
|
@stable
|
@@ -18480,7 +18951,10 @@ You can define custom animations using `up.transition()` and
|
|
18480
18951
|
|
18481
18952
|
If no overlay is open, an empty array is returned.
|
18482
18953
|
|
18483
|
-
|
18954
|
+
To get an array of *all* layers including the [root layer](/up.layer.root),
|
18955
|
+
use `up.layer.stack`.
|
18956
|
+
|
18957
|
+
@property up.layer.overlays
|
18484
18958
|
@param {Array<up.Layer>} overlays
|
18485
18959
|
@stable
|
18486
18960
|
*/
|
@@ -18505,9 +18979,9 @@ You can define custom animations using `up.transition()` and
|
|
18505
18979
|
Afterwards the only remaining layer will be the [root layer](/up.layer.root).
|
18506
18980
|
|
18507
18981
|
@function up.layer.dismissOverlays
|
18508
|
-
@param {any} value
|
18982
|
+
@param {any} [value]
|
18509
18983
|
The dismissal value.
|
18510
|
-
@param {Object} options
|
18984
|
+
@param {Object} [options]
|
18511
18985
|
See options for `up.layer.dismiss()`.
|
18512
18986
|
@stable
|
18513
18987
|
*/
|
@@ -18518,13 +18992,13 @@ You can define custom animations using `up.transition()` and
|
|
18518
18992
|
/***
|
18519
18993
|
[Accepts](/closing-overlays) the [current layer](up.layer.current).
|
18520
18994
|
|
18521
|
-
This is a shortcut for `up.layer.current.
|
18522
|
-
See `up.Layer#
|
18995
|
+
This is a shortcut for `up.layer.current.accept()`.
|
18996
|
+
See `up.Layer#accept()` for more documentation.
|
18523
18997
|
|
18524
|
-
@function up.layer.
|
18998
|
+
@function up.layer.accept
|
18525
18999
|
@param {any} [value]
|
18526
19000
|
@param {Object} [options]
|
18527
|
-
@
|
19001
|
+
@stable
|
18528
19002
|
*/
|
18529
19003
|
|
18530
19004
|
/***
|
@@ -18536,7 +19010,7 @@ You can define custom animations using `up.transition()` and
|
|
18536
19010
|
@function up.layer.dismiss
|
18537
19011
|
@param {any} [value]
|
18538
19012
|
@param {Object} [options]
|
18539
|
-
@
|
19013
|
+
@stable
|
18540
19014
|
*/
|
18541
19015
|
|
18542
19016
|
/***
|
@@ -18545,7 +19019,7 @@ You can define custom animations using `up.transition()` and
|
|
18545
19019
|
This is a shortcut for `up.layer.current.isRoot()`.
|
18546
19020
|
See `up.Layer#isRoot()` for more documentation..
|
18547
19021
|
|
18548
|
-
@function up.layer.
|
19022
|
+
@function up.layer.isRoot
|
18549
19023
|
@return {boolean}
|
18550
19024
|
@stable
|
18551
19025
|
*/
|
@@ -18573,7 +19047,7 @@ You can define custom animations using `up.transition()` and
|
|
18573
19047
|
*/
|
18574
19048
|
|
18575
19049
|
/***
|
18576
|
-
Listens to a
|
19050
|
+
Listens to a [DOM event](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Events)
|
18577
19051
|
that originated on an element [contained](/up.Layer.prototype.contains) by the [current layer](/up.layer.current).
|
18578
19052
|
|
18579
19053
|
This is a shortcut for `up.layer.current.on()`.
|
@@ -18582,7 +19056,7 @@ You can define custom animations using `up.transition()` and
|
|
18582
19056
|
@function up.layer.on
|
18583
19057
|
@param {string} types
|
18584
19058
|
A space-separated list of event types to bind to.
|
18585
|
-
@param {string} [selector]
|
19059
|
+
@param {string|Function(): string} [selector]
|
18586
19060
|
The selector of an element on which the event must be triggered.
|
18587
19061
|
@param {Object} [options]
|
18588
19062
|
@param {Function(event, [element], [data])} listener
|
@@ -18599,9 +19073,8 @@ You can define custom animations using `up.transition()` and
|
|
18599
19073
|
See `up.Layer#off()` for more documentation.
|
18600
19074
|
|
18601
19075
|
@function up.layer.off
|
18602
|
-
@param {Element|jQuery} [element=document]
|
18603
19076
|
@param {string} events
|
18604
|
-
@param {string} [selector]
|
19077
|
+
@param {string|Function(): string} [selector]
|
18605
19078
|
@param {Function(event, [element], [data])} listener
|
18606
19079
|
The listener function to unbind.
|
18607
19080
|
@stable
|
@@ -18614,7 +19087,6 @@ You can define custom animations using `up.transition()` and
|
|
18614
19087
|
See `up.Layer#emit()` for more documentation.
|
18615
19088
|
|
18616
19089
|
@function up.layer.emit
|
18617
|
-
@param {Element|jQuery} [target=up.layer.element]
|
18618
19090
|
@param {string} eventType
|
18619
19091
|
@param {Object} [props={}]
|
18620
19092
|
@stable
|
@@ -18644,7 +19116,7 @@ You can define custom animations using `up.transition()` and
|
|
18644
19116
|
*/
|
18645
19117
|
|
18646
19118
|
/***
|
18647
|
-
The location of the [current layer](/up.layer.current).
|
19119
|
+
The location URL of the [current layer](/up.layer.current).
|
18648
19120
|
|
18649
19121
|
This is a shortcut for `up.layer.current.location`.
|
18650
19122
|
See `up.Layer#location` for more documentation.
|
@@ -18653,23 +19125,34 @@ You can define custom animations using `up.transition()` and
|
|
18653
19125
|
@param {string} location
|
18654
19126
|
@stable
|
18655
19127
|
*/
|
19128
|
+
|
19129
|
+
/***
|
19130
|
+
The [current layer](/up.layer.current)'s [mode](/up.layer.mode)
|
19131
|
+
which governs its appearance and behavior.
|
19132
|
+
|
19133
|
+
@property up.layer.mode
|
19134
|
+
@param {string} mode
|
19135
|
+
@stable
|
19136
|
+
*/
|
19137
|
+
|
19138
|
+
/***
|
19139
|
+
The [context](/context) of the [current layer](/up.layer.current).
|
19140
|
+
|
19141
|
+
This is aliased as `up.context`.
|
19142
|
+
|
19143
|
+
@property up.layer.context
|
19144
|
+
@param {string} context
|
19145
|
+
The context object.
|
19146
|
+
|
19147
|
+
If no context has been set an empty object is returned.
|
19148
|
+
@experimental
|
19149
|
+
*/
|
18656
19150
|
u.delegate(api, ['accept', 'dismiss', 'isRoot', 'isOverlay', 'isFront', 'on', 'off', 'emit', 'parent', 'historyVisible', 'location', 'mode', 'context', 'element', 'contains', 'size', 'affix'], function() {
|
18657
19151
|
return stack.current;
|
18658
19152
|
});
|
18659
19153
|
return api;
|
18660
19154
|
})();
|
18661
19155
|
|
18662
|
-
|
18663
|
-
/***
|
18664
|
-
TODO: Docs
|
18665
|
-
@property up.context
|
18666
|
-
@pram {Object} context
|
18667
|
-
*/
|
18668
|
-
|
18669
|
-
u.getter(up, 'context', function() {
|
18670
|
-
return up.layer.context;
|
18671
|
-
});
|
18672
|
-
|
18673
19156
|
}).call(this);
|
18674
19157
|
|
18675
19158
|
/***
|
@@ -18742,6 +19225,11 @@ With these [`up-target`](/a-up-follow#up-target) annotations Unpoly only updates
|
|
18742
19225
|
The JavaScript environment will persist and the user will not see a white flash while the
|
18743
19226
|
new page is loading.
|
18744
19227
|
|
19228
|
+
@see a[up-follow]
|
19229
|
+
@see a[up-instant]
|
19230
|
+
@see a[up-preload]
|
19231
|
+
@see up.follow
|
19232
|
+
|
18745
19233
|
@module up.link
|
18746
19234
|
*/
|
18747
19235
|
|
@@ -18749,7 +19237,7 @@ new page is loading.
|
|
18749
19237
|
var slice = [].slice;
|
18750
19238
|
|
18751
19239
|
up.link = (function() {
|
18752
|
-
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,
|
19240
|
+
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;
|
18753
19241
|
u = up.util;
|
18754
19242
|
e = up.element;
|
18755
19243
|
linkPreloader = new up.LinkPreloader();
|
@@ -18766,9 +19254,10 @@ new page is loading.
|
|
18766
19254
|
};
|
18767
19255
|
|
18768
19256
|
/***
|
18769
|
-
|
18770
|
-
|
18771
|
-
|
19257
|
+
Configures defaults for link handling.
|
19258
|
+
|
19259
|
+
In particular you can configure Unpoly to handle [all links on the page](/handling-everything)
|
19260
|
+
without requiring developers to set `[up-...]` attributes.
|
18772
19261
|
|
18773
19262
|
@property up.link.config
|
18774
19263
|
|
@@ -18841,7 +19330,7 @@ new page is loading.
|
|
18841
19330
|
|
18842
19331
|
If set to `false`, Unpoly will never preload links.
|
18843
19332
|
|
18844
|
-
@param {Array<string>} [config.
|
19333
|
+
@param {Array<string>} [config.clickableSelectors]
|
18845
19334
|
A list of CSS selectors matching elements that should behave like links or buttons.
|
18846
19335
|
|
18847
19336
|
@see [up-clickable]
|
@@ -18913,10 +19402,9 @@ new page is loading.
|
|
18913
19402
|
};
|
18914
19403
|
|
18915
19404
|
/***
|
18916
|
-
|
18917
|
-
[current layer](/up.layer.current) with HTML from the response.
|
19405
|
+
Follows the given link with JavaScript and updates a fragment with the server response.
|
18918
19406
|
|
18919
|
-
By default the layer's [main element](/main)
|
19407
|
+
By default the layer's [main element](/up-main)
|
18920
19408
|
will be replaced. Attributes like `a[up-target]`
|
18921
19409
|
or `a[up-layer]` will be honored.
|
18922
19410
|
|
@@ -18978,8 +19466,24 @@ new page is loading.
|
|
18978
19466
|
};
|
18979
19467
|
|
18980
19468
|
/***
|
18981
|
-
Parses the
|
18982
|
-
[`follow`](/up.follow) the given link, but does not
|
19469
|
+
Parses the [render](/up.render) options that would be used to
|
19470
|
+
[`follow`](/up.follow) the given link, but does not render.
|
19471
|
+
|
19472
|
+
\#\#\# Example
|
19473
|
+
|
19474
|
+
Given a link with some `[up-...]` attributes:
|
19475
|
+
|
19476
|
+
```html
|
19477
|
+
<a href="/foo" up-target=".content" up-layer="new">...</a>
|
19478
|
+
```
|
19479
|
+
|
19480
|
+
We can parse the link's render options like this:
|
19481
|
+
|
19482
|
+
```js
|
19483
|
+
let link = document.querySelector('a[href="/foo"]')
|
19484
|
+
let options = up.link.followOptions(link)
|
19485
|
+
// => { url: '/foo', method: 'GET', target: '.content', layer: 'new', ... }
|
19486
|
+
```
|
18983
19487
|
|
18984
19488
|
@function up.link.followOptions
|
18985
19489
|
@param {Element|jQuery|string} link
|
@@ -19058,7 +19562,20 @@ new page is loading.
|
|
19058
19562
|
|
19059
19563
|
The event is emitted on the `<a>` element that is being followed.
|
19060
19564
|
|
19061
|
-
|
19565
|
+
\#\#\# Changing render options
|
19566
|
+
|
19567
|
+
Listeners may inspect and manipulate [render options](/up.render) for the coming fragment update.
|
19568
|
+
|
19569
|
+
The code below will open all form-contained links in an overlay, as to not
|
19570
|
+
lose the user's form data:
|
19571
|
+
|
19572
|
+
```js
|
19573
|
+
up.on('up:link:follow', function(event, link) {
|
19574
|
+
if (link.closest('form')) {
|
19575
|
+
event.renderOptions.layer = 'new'
|
19576
|
+
}
|
19577
|
+
})
|
19578
|
+
```
|
19062
19579
|
|
19063
19580
|
@event up:link:follow
|
19064
19581
|
@param {Element} event.target
|
@@ -19084,7 +19601,10 @@ new page is loading.
|
|
19084
19601
|
@param {Object} options
|
19085
19602
|
See options for `up.follow()`.
|
19086
19603
|
@return {Promise}
|
19087
|
-
A promise that will be fulfilled when the request was loaded and cached
|
19604
|
+
A promise that will be fulfilled when the request was loaded and cached.
|
19605
|
+
|
19606
|
+
When preloading is [disabled](/up.link.config#config.preloadEnabled) the promise
|
19607
|
+
rejects with an `AbortError`.
|
19088
19608
|
@stable
|
19089
19609
|
*/
|
19090
19610
|
preload = function(link, options) {
|
@@ -19188,7 +19708,7 @@ new page is loading.
|
|
19188
19708
|
@function up.link.makeFollowable
|
19189
19709
|
@param {Element|jQuery|string} link
|
19190
19710
|
The element or selector for the link to make followable.
|
19191
|
-
@
|
19711
|
+
@experimental
|
19192
19712
|
*/
|
19193
19713
|
makeFollowable = function(link) {
|
19194
19714
|
if (!isFollowable(link)) {
|
@@ -19324,6 +19844,13 @@ new page is loading.
|
|
19324
19844
|
If the user activates an element using their keyboard, the `up:click` event will be emitted
|
19325
19845
|
when the key is pressed even if the element has an `[up-instant]` attribute.
|
19326
19846
|
|
19847
|
+
\#\#\# Only unmodified clicks are considered
|
19848
|
+
|
19849
|
+
To prevent overriding native browser behavior, the `up:click` is only emitted for unmodified clicks.
|
19850
|
+
|
19851
|
+
In particular, it is not emitted when the user holds `Shift`, `CTRL` or `Meta` while clicking.
|
19852
|
+
Neither it is emitted when the user clicks with a secondary mouse button.
|
19853
|
+
|
19327
19854
|
@event up:click
|
19328
19855
|
@param {Element} event.target
|
19329
19856
|
The clicked element.
|
@@ -19346,24 +19873,9 @@ new page is loading.
|
|
19346
19873
|
method = followMethod(link);
|
19347
19874
|
return up.network.isSafeMethod(method);
|
19348
19875
|
};
|
19349
|
-
targetMacro = function(queryAttr, fixedResultAttrs, callback) {
|
19350
|
-
return up.macro("[" + queryAttr + "]", function(link) {
|
19351
|
-
var optionalTarget, resultAttrs;
|
19352
|
-
resultAttrs = u.copy(fixedResultAttrs);
|
19353
|
-
if (optionalTarget = link.getAttribute(queryAttr)) {
|
19354
|
-
resultAttrs['up-target'] = optionalTarget;
|
19355
|
-
} else {
|
19356
|
-
resultAttrs['up-follow'] = '';
|
19357
|
-
}
|
19358
|
-
e.setMissingAttrs(link, resultAttrs);
|
19359
|
-
link.removeAttribute(queryAttr);
|
19360
|
-
return typeof callback === "function" ? callback() : void 0;
|
19361
|
-
});
|
19362
|
-
};
|
19363
19876
|
|
19364
19877
|
/***
|
19365
|
-
[Follows](/up.follow) this link with JavaScript and
|
19366
|
-
on the current page with a corresponding element from the response.
|
19878
|
+
[Follows](/up.follow) this link with JavaScript and updates a fragment with the server response.
|
19367
19879
|
|
19368
19880
|
Following a link is considered [navigation](/navigation) by default.
|
19369
19881
|
|
@@ -19376,7 +19888,7 @@ new page is loading.
|
|
19376
19888
|
<a href="/posts/5" up-follow up-target=".content">Read post</a>
|
19377
19889
|
```
|
19378
19890
|
|
19379
|
-
If no `[up-target]` attribute is set, the [main target](/main) is updated.
|
19891
|
+
If no `[up-target]` attribute is set, the [main target](/up-main) is updated.
|
19380
19892
|
|
19381
19893
|
\#\#\# Advanced fragment changes
|
19382
19894
|
|
@@ -19413,14 +19925,14 @@ new page is loading.
|
|
19413
19925
|
@param [up-target]
|
19414
19926
|
The CSS selector to update.
|
19415
19927
|
|
19416
|
-
If omitted a [main target](/main) will be rendered.
|
19928
|
+
If omitted a [main target](/up-main) will be rendered.
|
19417
19929
|
|
19418
19930
|
@param [up-fallback]
|
19419
19931
|
Specifies behavior if the [target selector](/up.render#options.target) is missing from the current page or the server response.
|
19420
19932
|
|
19421
19933
|
If set to a CSS selector, Unpoly will attempt to replace that selector instead.
|
19422
19934
|
|
19423
|
-
If set to `true` Unpoly will attempt to replace a [main target](/main) instead.
|
19935
|
+
If set to `true` Unpoly will attempt to replace a [main target](/up-main) instead.
|
19424
19936
|
|
19425
19937
|
If set to `false` Unpoly will immediately reject the render promise.
|
19426
19938
|
|
@@ -19494,12 +20006,12 @@ new page is loading.
|
|
19494
20006
|
|
19495
20007
|
If set to `auto` history will be updated if the `[up-target]` matches
|
19496
20008
|
a selector in `up.fragment.config.autoHistoryTargets`. By default this contains all
|
19497
|
-
[main targets](/main).
|
20009
|
+
[main targets](/up-main).
|
19498
20010
|
|
19499
20011
|
If set to `false`, the history will remain unchanged.
|
19500
20012
|
|
19501
20013
|
[Overlays](/up.layer) will only change the browser URL and window title if the overlay
|
19502
|
-
has [visible history](/up.layer.historyVisible), even
|
20014
|
+
has [visible history](/up.layer.historyVisible), even when `[up-history=true]` is set.
|
19503
20015
|
|
19504
20016
|
@param [up-title]
|
19505
20017
|
An explicit document title to use after rendering.
|
@@ -19574,7 +20086,7 @@ new page is loading.
|
|
19574
20086
|
This is only relevant when updating a layer that is not the [frontmost layer](/up.layer.front).
|
19575
20087
|
|
19576
20088
|
@param [up-context]
|
19577
|
-
A JSON object that will be merged into the [context](/
|
20089
|
+
A JSON object that will be merged into the [context](/context)
|
19578
20090
|
of the current layer once the fragment is rendered.
|
19579
20091
|
|
19580
20092
|
@param [up-keep='true']
|
@@ -19629,12 +20141,7 @@ new page is loading.
|
|
19629
20141
|
});
|
19630
20142
|
|
19631
20143
|
/***
|
19632
|
-
|
19633
|
-
|
19634
|
-
By adding an `up-instant` attribute to a link, the destination will be
|
19635
|
-
fetched on `mousedown` instead of `click` (`mouseup`).
|
19636
|
-
|
19637
|
-
<a href="/users" up-follow up-instant>User list</a>
|
20144
|
+
Follows this link on `mousedown` instead of `click`.
|
19638
20145
|
|
19639
20146
|
This will save precious milliseconds that otherwise spent
|
19640
20147
|
on waiting for the user to release the mouse button. Since an
|
@@ -19646,6 +20153,10 @@ new page is loading.
|
|
19646
20153
|
navigation actions this isn't needed. E.g. popular operation
|
19647
20154
|
systems switch tabs on `mousedown` instead of `click`.
|
19648
20155
|
|
20156
|
+
\#\#\# Example
|
20157
|
+
|
20158
|
+
<a href="/users" up-follow up-instant>User list</a>
|
20159
|
+
|
19649
20160
|
\#\#\# Accessibility
|
19650
20161
|
|
19651
20162
|
If the user activates an element using their keyboard, the `up:click` event will be emitted
|
@@ -19655,37 +20166,6 @@ new page is loading.
|
|
19655
20166
|
@stable
|
19656
20167
|
*/
|
19657
20168
|
|
19658
|
-
/***
|
19659
|
-
[Follows](/up.follow) this link as fast as possible.
|
19660
|
-
|
19661
|
-
This is done by:
|
19662
|
-
|
19663
|
-
- [Following the link through AJAX](/a-up-follow) instead of a full page load
|
19664
|
-
- [Preloading the link's destination URL](/a-up-preload)
|
19665
|
-
- [Triggering the link on `mousedown`](/a-up-instant) instead of on `click`
|
19666
|
-
|
19667
|
-
\#\#\# Example
|
19668
|
-
|
19669
|
-
Use `[up-dash]` like this:
|
19670
|
-
|
19671
|
-
<a href="/users" up-dash=".main">User list</a>
|
19672
|
-
|
19673
|
-
This is shorthand for:
|
19674
|
-
|
19675
|
-
<a href="/users" up-target=".main" up-instant up-preload>User list</a>
|
19676
|
-
|
19677
|
-
@selector a[up-dash]
|
19678
|
-
@param [up-dash='body']
|
19679
|
-
The CSS selector to replace
|
19680
|
-
|
19681
|
-
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)).
|
19682
|
-
@stable
|
19683
|
-
*/
|
19684
|
-
targetMacro('up-dash', {
|
19685
|
-
'up-preload': '',
|
19686
|
-
'up-instant': ''
|
19687
|
-
});
|
19688
|
-
|
19689
20169
|
/***
|
19690
20170
|
Add an `[up-expand]` attribute to any element to enlarge the click area of a
|
19691
20171
|
descendant link.
|
@@ -19744,11 +20224,9 @@ new page is loading.
|
|
19744
20224
|
});
|
19745
20225
|
|
19746
20226
|
/***
|
19747
|
-
|
19748
|
-
when the user hovers over the click area, or when the user puts her
|
19749
|
-
mouse/finger down (before releasing).
|
20227
|
+
Preloads this link when the user hovers over it.
|
19750
20228
|
|
19751
|
-
When the link is clicked later
|
20229
|
+
When the link is clicked later the response will already be cached,
|
19752
20230
|
making the interaction feel instant.
|
19753
20231
|
|
19754
20232
|
@selector a[up-preload]
|
@@ -19776,7 +20254,6 @@ new page is loading.
|
|
19776
20254
|
isFollowable: isFollowable,
|
19777
20255
|
shouldFollowEvent: shouldFollowEvent,
|
19778
20256
|
followMethod: followMethod,
|
19779
|
-
targetMacro: targetMacro,
|
19780
20257
|
convertClicks: convertClicks,
|
19781
20258
|
config: config,
|
19782
20259
|
combineFollowableSelectors: combineFollowableSelectors
|
@@ -19791,9 +20268,12 @@ new page is loading.
|
|
19791
20268
|
Forms
|
19792
20269
|
=====
|
19793
20270
|
|
19794
|
-
|
19795
|
-
|
19796
|
-
|
20271
|
+
The `up.form` module helps you work with non-trivial forms.
|
20272
|
+
|
20273
|
+
@see form[up-submit]
|
20274
|
+
@see form[up-validate]
|
20275
|
+
@see input[up-switch]
|
20276
|
+
@see form[up-autosubmit]
|
19797
20277
|
|
19798
20278
|
@module up.form
|
19799
20279
|
*/
|
@@ -19802,7 +20282,7 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
19802
20282
|
var slice = [].slice;
|
19803
20283
|
|
19804
20284
|
up.form = (function() {
|
19805
|
-
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;
|
20285
|
+
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;
|
19806
20286
|
u = up.util;
|
19807
20287
|
e = up.element;
|
19808
20288
|
ATTRIBUTES_SUGGESTING_SUBMIT = ['[up-submit]', '[up-target]', '[up-layer]', '[up-transition]'];
|
@@ -19979,8 +20459,26 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
19979
20459
|
});
|
19980
20460
|
|
19981
20461
|
/***
|
19982
|
-
Parses the
|
19983
|
-
[`submit`](/up.submit) the given form, but does not
|
20462
|
+
Parses the [render](/up.render) options that would be used to
|
20463
|
+
[`submit`](/up.submit) the given form, but does not render.
|
20464
|
+
|
20465
|
+
\#\#\# Example
|
20466
|
+
|
20467
|
+
Given a form element:
|
20468
|
+
|
20469
|
+
```html
|
20470
|
+
<form action="/foo" method="post" up-target=".content">
|
20471
|
+
...
|
20472
|
+
</form>
|
20473
|
+
```
|
20474
|
+
|
20475
|
+
We can parse the link's render options like this:
|
20476
|
+
|
20477
|
+
```js
|
20478
|
+
let form = document.querySelector('form')
|
20479
|
+
let options = up.form.submitOptions(form)
|
20480
|
+
// => { url: '/foo', method: 'POST', target: '.content', ... }
|
20481
|
+
```
|
19984
20482
|
|
19985
20483
|
@param {Element|jQuery|string} form
|
19986
20484
|
The form to submit.
|
@@ -20033,14 +20531,29 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20033
20531
|
/***
|
20034
20532
|
This event is [emitted](/up.emit) when a form is [submitted](/up.submit) through Unpoly.
|
20035
20533
|
|
20036
|
-
The event is emitted on the`<form>` element.
|
20534
|
+
The event is emitted on the `<form>` element.
|
20535
|
+
|
20536
|
+
When the form is being [validated](/input-up-validate), this event is not emitted.
|
20537
|
+
Instead an `up:form:validate` event is emitted.
|
20538
|
+
|
20539
|
+
\#\#\# Changing render options
|
20540
|
+
|
20541
|
+
Listeners may inspect and manipulate [render options](/up.render) for the coming fragment update.
|
20542
|
+
|
20543
|
+
The code below will use a custom [transition](/up-transition)
|
20544
|
+
when a form submission [fails](/server-errors):
|
20545
|
+
|
20546
|
+
```js
|
20547
|
+
up.on('up:form:submit', function(event, form) {
|
20548
|
+
event.renderOptions.failTransition = 'shake'
|
20549
|
+
})
|
20550
|
+
```
|
20037
20551
|
|
20038
20552
|
@event up:form:submit
|
20039
20553
|
@param {Element} event.target
|
20040
20554
|
The `<form>` element that will be submitted.
|
20041
20555
|
@param {Object} event.renderOptions
|
20042
20556
|
An object with [render options](/up.render) for the fragment update
|
20043
|
-
that will show the validation results.
|
20044
20557
|
|
20045
20558
|
Listeners may inspect and modify these options.
|
20046
20559
|
@param event.preventDefault()
|
@@ -20048,7 +20561,11 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20048
20561
|
@stable
|
20049
20562
|
*/
|
20050
20563
|
up.on('up:click', submitButtonSelector, function(event, button) {
|
20051
|
-
|
20564
|
+
var form;
|
20565
|
+
form = e.closest(button, 'form');
|
20566
|
+
if (form && isSubmittable(form)) {
|
20567
|
+
return button.focus();
|
20568
|
+
}
|
20052
20569
|
});
|
20053
20570
|
|
20054
20571
|
/***
|
@@ -20133,10 +20650,10 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20133
20650
|
/***
|
20134
20651
|
[Observes](/up.observe) a field or form and submits the form when a value changes.
|
20135
20652
|
|
20136
|
-
Both the form and the changed field will be assigned a CSS class [
|
20653
|
+
Both the form and the changed field will be assigned a CSS class [`.up-active`](/form-up-active)
|
20137
20654
|
while the autosubmitted form is processing.
|
20138
20655
|
|
20139
|
-
The unobtrusive variant of this is the [`up-autosubmit`](/form-up-autosubmit) attribute.
|
20656
|
+
The unobtrusive variant of this is the [`[up-autosubmit]`](/form-up-autosubmit) attribute.
|
20140
20657
|
|
20141
20658
|
@function up.autosubmit
|
20142
20659
|
@param {string|Element|jQuery} target
|
@@ -20190,7 +20707,9 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20190
20707
|
|
20191
20708
|
\#\#\# Example
|
20192
20709
|
|
20193
|
-
|
20710
|
+
```js
|
20711
|
+
up.validate('input[name=email]', { target: '.email-errors' })
|
20712
|
+
```
|
20194
20713
|
|
20195
20714
|
@function up.validate
|
20196
20715
|
@param {string|Element|jQuery} field
|
@@ -20234,6 +20753,7 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20234
20753
|
@param event.preventDefault()
|
20235
20754
|
Event listeners may call this method to prevent the validation request
|
20236
20755
|
being sent to the server.
|
20756
|
+
@stable
|
20237
20757
|
*/
|
20238
20758
|
switcherValues = function(field) {
|
20239
20759
|
var checkedButton, form, groupName, meta, value, values;
|
@@ -20346,24 +20866,51 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20346
20866
|
return element;
|
20347
20867
|
}
|
20348
20868
|
};
|
20869
|
+
|
20870
|
+
/***
|
20871
|
+
Returns whether the given form will be [submitted](/up.follow) through Unpoly
|
20872
|
+
instead of making a full page load.
|
20873
|
+
|
20874
|
+
By default Unpoly will follow forms if the element has
|
20875
|
+
one of the following attributes:
|
20876
|
+
|
20877
|
+
- `[up-submit]`
|
20878
|
+
- `[up-target]`
|
20879
|
+
- `[up-layer]`
|
20880
|
+
- `[up-transition]`
|
20881
|
+
|
20882
|
+
To consider other selectors to be submittable, see `up.form.config.submitSelectors`.
|
20883
|
+
|
20884
|
+
@function up.form.isSubmittable
|
20885
|
+
@param {Element|jQuery|string} form
|
20886
|
+
The form to check.
|
20887
|
+
@stable
|
20888
|
+
*/
|
20889
|
+
isSubmittable = function(form) {
|
20890
|
+
form = up.fragment.get(form);
|
20891
|
+
return e.matches(form, fullSubmitSelector()) && !isSubmitDisabled(form);
|
20892
|
+
};
|
20349
20893
|
isSubmitDisabled = function(form) {
|
20350
20894
|
return e.matches(form, config.noSubmitSelectors.join(','));
|
20351
20895
|
};
|
20352
20896
|
|
20353
20897
|
/***
|
20354
|
-
|
20355
|
-
instead of triggering a full page reload.
|
20356
|
-
|
20357
|
-
<form method="post" action="/users" up-target=".main">
|
20358
|
-
...
|
20359
|
-
</form>
|
20898
|
+
Submits this form via JavaScript and updates a fragment with the server response.
|
20360
20899
|
|
20361
20900
|
The server response is searched for the selector given in `up-target`.
|
20362
20901
|
The selector content is then [replaced](/up.replace) in the current page.
|
20363
20902
|
|
20364
20903
|
The programmatic variant of this is the [`up.submit()`](/up.submit) function.
|
20365
20904
|
|
20366
|
-
\#\#\#
|
20905
|
+
\#\#\# Example
|
20906
|
+
|
20907
|
+
```html
|
20908
|
+
<form method="post" action="/users" up-submit>
|
20909
|
+
...
|
20910
|
+
</form>
|
20911
|
+
```
|
20912
|
+
|
20913
|
+
\#\#\# Handling validation errors
|
20367
20914
|
|
20368
20915
|
When the server was unable to save the form due to invalid params,
|
20369
20916
|
it will usually re-render an updated copy of the form with
|
@@ -20378,19 +20925,35 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20378
20925
|
[`:status` option to `render`](http://guides.rubyonrails.org/layouts_and_rendering.html#the-status-option)
|
20379
20926
|
for this:
|
20380
20927
|
|
20381
|
-
|
20382
|
-
|
20383
|
-
def create
|
20384
|
-
user_params = params[:user].permit(:email, :password)
|
20385
|
-
@user = User.new(user_params)
|
20386
|
-
if @user.save?
|
20387
|
-
sign_in @user
|
20388
|
-
else
|
20389
|
-
render 'form', status: :bad_request
|
20390
|
-
end
|
20391
|
-
end
|
20928
|
+
```ruby
|
20929
|
+
class UsersController < ApplicationController
|
20392
20930
|
|
20931
|
+
def create
|
20932
|
+
user_params = params[:user].permit(:email, :password)
|
20933
|
+
@user = User.new(user_params)
|
20934
|
+
if @user.save?
|
20935
|
+
sign_in @user
|
20936
|
+
else
|
20937
|
+
render 'form', status: :bad_request
|
20393
20938
|
end
|
20939
|
+
end
|
20940
|
+
|
20941
|
+
end
|
20942
|
+
```
|
20943
|
+
|
20944
|
+
You may define different option for the failure case by infixing an attribute with `fail`:
|
20945
|
+
|
20946
|
+
```html
|
20947
|
+
<form method="post" action="/action"
|
20948
|
+
up-target=".content"
|
20949
|
+
up-fail-target="form"
|
20950
|
+
up-scroll="auto"
|
20951
|
+
up-fail-scroll=".errors">
|
20952
|
+
...
|
20953
|
+
</form>
|
20954
|
+
```
|
20955
|
+
|
20956
|
+
See [handling server errors](/server-errors) for details.
|
20394
20957
|
|
20395
20958
|
Note that you can also use
|
20396
20959
|
[`input[up-validate]`](/input-up-validate) to perform server-side
|
@@ -20398,7 +20961,7 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20398
20961
|
|
20399
20962
|
\#\#\# Giving feedback while the form is processing
|
20400
20963
|
|
20401
|
-
The `<form>` element will be assigned a CSS class [
|
20964
|
+
The `<form>` element will be assigned a CSS class [`.up-active`](/form.up-active) while
|
20402
20965
|
the submission is loading.
|
20403
20966
|
|
20404
20967
|
\#\#\# Short notation
|
@@ -20582,11 +21145,13 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20582
21145
|
*/
|
20583
21146
|
|
20584
21147
|
/***
|
20585
|
-
|
21148
|
+
Validates this form on the server when any field changes and shows validation errors.
|
20586
21149
|
|
20587
21150
|
You can configure what Unpoly considers a fieldset by adding CSS selectors to the
|
20588
21151
|
`up.form.config.validateTargets` array.
|
20589
21152
|
|
21153
|
+
See `input[up-validate]` for detailed documentation.
|
21154
|
+
|
20590
21155
|
@selector form[up-validate]
|
20591
21156
|
@param up-validate
|
20592
21157
|
The CSS selector to update with the server response.
|
@@ -20603,7 +21168,7 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20603
21168
|
});
|
20604
21169
|
|
20605
21170
|
/***
|
20606
|
-
Show or hide elements when a
|
21171
|
+
Show or hide elements when a form field is set to a given value.
|
20607
21172
|
|
20608
21173
|
\#\#\# Example: Select options
|
20609
21174
|
|
@@ -20806,7 +21371,7 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20806
21371
|
/***
|
20807
21372
|
Submits this field's form when this field changes its values.
|
20808
21373
|
|
20809
|
-
Both the form and the changed field will be assigned a CSS class [
|
21374
|
+
Both the form and the changed field will be assigned a CSS class [`.up-active`](/form-up-active)
|
20810
21375
|
while the autosubmitted form is loading.
|
20811
21376
|
|
20812
21377
|
The programmatic variant of this is the [`up.autosubmit()`](/up.autosubmit) function.
|
@@ -20835,15 +21400,15 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20835
21400
|
</div>
|
20836
21401
|
|
20837
21402
|
@selector input[up-autosubmit]
|
20838
|
-
@param up-delay
|
21403
|
+
@param [up-delay]
|
20839
21404
|
The number of miliseconds to wait after a change before the form is submitted.
|
20840
21405
|
@stable
|
20841
21406
|
*/
|
20842
21407
|
|
20843
21408
|
/***
|
20844
|
-
Submits the form when
|
21409
|
+
Submits the form when any field changes.
|
20845
21410
|
|
20846
|
-
Both the form and the field will be assigned a CSS class [
|
21411
|
+
Both the form and the field will be assigned a CSS class [`.up-active`](/form-up-active)
|
20847
21412
|
while the autosubmitted form is loading.
|
20848
21413
|
|
20849
21414
|
The programmatic variant of this is the [`up.autosubmit()`](/up.autosubmit) function.
|
@@ -20858,7 +21423,7 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20858
21423
|
</form>
|
20859
21424
|
|
20860
21425
|
@selector form[up-autosubmit]
|
20861
|
-
@param up-delay
|
21426
|
+
@param [up-delay]
|
20862
21427
|
The number of miliseconds to wait after a change before the form is submitted.
|
20863
21428
|
@stable
|
20864
21429
|
*/
|
@@ -20870,6 +21435,7 @@ open dialogs with sub-forms, etc. all without losing form state.
|
|
20870
21435
|
config: config,
|
20871
21436
|
submit: submit,
|
20872
21437
|
submitOptions: submitOptions,
|
21438
|
+
isSubmittable: isSubmittable,
|
20873
21439
|
observe: observe,
|
20874
21440
|
validate: validate,
|
20875
21441
|
autosubmit: autosubmit,
|
@@ -20895,44 +21461,57 @@ Navigation feedback
|
|
20895
21461
|
===================
|
20896
21462
|
|
20897
21463
|
The `up.feedback` module adds useful CSS classes to links while they are loading,
|
20898
|
-
or when they point to the current URL.
|
20899
|
-
|
21464
|
+
or when they point to the current URL.
|
21465
|
+
|
21466
|
+
By styling these classes you may provide instant feedback to user interactions,
|
21467
|
+
improving the perceived speed of your interface.
|
20900
21468
|
|
20901
21469
|
|
20902
21470
|
\#\#\# Example
|
20903
21471
|
|
20904
21472
|
Let's say we have an `<nav>` element with two links, pointing to `/foo` and `/bar` respectively:
|
20905
21473
|
|
20906
|
-
|
20907
|
-
|
20908
|
-
|
20909
|
-
|
21474
|
+
```html
|
21475
|
+
<nav>
|
21476
|
+
<a href="/foo" up-follow>Foo</a>
|
21477
|
+
<a href="/bar" up-follow>Bar</a>
|
21478
|
+
</nav>
|
21479
|
+
```
|
20910
21480
|
|
20911
21481
|
By giving the navigation bar the `[up-nav]` attribute, links pointing to the current browser address are highlighted
|
20912
21482
|
as we navigate through the site.
|
20913
21483
|
|
20914
21484
|
If the current URL is `/foo`, the first link is automatically marked with an [`.up-current`](/a.up-current) class:
|
20915
21485
|
|
20916
|
-
|
20917
|
-
|
20918
|
-
|
20919
|
-
|
21486
|
+
```html
|
21487
|
+
<nav up-nav>
|
21488
|
+
<a href="/foo" up-follow class="up-current">Foo</a>
|
21489
|
+
<a href="/bar" up-follow>Bar</a>
|
21490
|
+
</nav>
|
21491
|
+
```
|
20920
21492
|
|
20921
21493
|
When the user clicks on the `/bar` link, the link will receive the [`up-active`](/a.up-active) class while it is waiting
|
20922
21494
|
for the server to respond:
|
20923
21495
|
|
20924
|
-
|
20925
|
-
|
20926
|
-
|
20927
|
-
|
21496
|
+
```
|
21497
|
+
<nav up-nav>
|
21498
|
+
<a href="/foo" up-follow class="up-current">Foo</a>
|
21499
|
+
<a href="/bar" up-follow class="up-active">Bar</a>
|
21500
|
+
</div>
|
21501
|
+
```
|
20928
21502
|
|
20929
21503
|
Once the response is received the URL will change to `/bar` and the `up-active` class is removed:
|
20930
21504
|
|
20931
|
-
|
20932
|
-
|
20933
|
-
|
20934
|
-
|
21505
|
+
```html
|
21506
|
+
<nav up-nav>
|
21507
|
+
<a href="/foo" up-follow>Foo</a>
|
21508
|
+
<a href="/bar" up-follow class="up-current">Bar</a>
|
21509
|
+
</nav>
|
21510
|
+
```
|
20935
21511
|
|
21512
|
+
@see [up-nav]
|
21513
|
+
@see a.up-current
|
21514
|
+
@see a.up-active
|
20936
21515
|
|
20937
21516
|
@module up.feedback
|
20938
21517
|
*/
|
@@ -21234,7 +21813,7 @@ Once the response is received the URL will change to `/bar` and the `up-active`
|
|
21234
21813
|
*/
|
21235
21814
|
|
21236
21815
|
/***
|
21237
|
-
Links within `[up-nav]` may use the `[up-alias]` attribute to pass
|
21816
|
+
Links within `[up-nav]` may use the `[up-alias]` attribute to pass a [URL pattern](/url-patterns) for which they
|
21238
21817
|
should also be highlighted as [`.up-current`](a.up-current).
|
21239
21818
|
|
21240
21819
|
\#\#\# Example
|
@@ -21247,7 +21826,7 @@ Once the response is received the URL will change to `/bar` and the `up-active`
|
|
21247
21826
|
</div>
|
21248
21827
|
```
|
21249
21828
|
|
21250
|
-
To pass more than one alternative URLs, use
|
21829
|
+
To pass more than one alternative URLs, use a [URL pattern](/url-patterns).
|
21251
21830
|
|
21252
21831
|
@selector a[up-alias]
|
21253
21832
|
@param up-alias
|
@@ -21307,8 +21886,10 @@ Once the response is received the URL will change to `/bar` and the `up-active`
|
|
21307
21886
|
Passive updates
|
21308
21887
|
===============
|
21309
21888
|
|
21310
|
-
This
|
21311
|
-
|
21889
|
+
This package contains functionality to passively receive updates from the server.
|
21890
|
+
|
21891
|
+
@see [up-hungry]
|
21892
|
+
@see [up-poll]
|
21312
21893
|
|
21313
21894
|
@module up.radio
|
21314
21895
|
*/
|
@@ -21323,13 +21904,16 @@ passively receive updates from the server.
|
|
21323
21904
|
Configures defaults for passive updates.
|
21324
21905
|
|
21325
21906
|
@property up.radio.config
|
21907
|
+
|
21326
21908
|
@param {Array<string>} [config.hungrySelectors]
|
21327
21909
|
An array of CSS selectors that is replaced whenever a matching element is found in a response.
|
21328
21910
|
These elements are replaced even when they were not targeted directly.
|
21329
21911
|
|
21330
21912
|
By default this contains the [`[up-hungry]`](/up-hungry) attribute.
|
21913
|
+
|
21331
21914
|
@param {number} [config.pollInterval=30000]
|
21332
21915
|
The default [polling](/up-poll] interval in milliseconds.
|
21916
|
+
|
21333
21917
|
@param {boolean|string|Function(Element)} [config.pollEnabled=true]
|
21334
21918
|
Whether Unpoly will follow instructions to poll fragments, like the `[up-poll]` attribute.
|
21335
21919
|
|
@@ -21344,6 +21928,7 @@ passively receive updates from the server.
|
|
21344
21928
|
When set to `false`, Unpoly will never allow polling.
|
21345
21929
|
|
21346
21930
|
You may also pass a function that accepts the polling fragment and returns `true`, `false` or `'auto'`.
|
21931
|
+
|
21347
21932
|
@stable
|
21348
21933
|
*/
|
21349
21934
|
config = new up.Config(function() {
|
@@ -21366,9 +21951,8 @@ passively receive updates from the server.
|
|
21366
21951
|
};
|
21367
21952
|
|
21368
21953
|
/***
|
21369
|
-
Elements with an `[up-hungry]` attribute are
|
21370
|
-
matching element
|
21371
|
-
when it isn't targeted directly.
|
21954
|
+
Elements with an `[up-hungry]` attribute are updated whenever the server
|
21955
|
+
sends a matching element, even if the element isn't targeted.
|
21372
21956
|
|
21373
21957
|
Use cases for this are unread message counters or notification flashes.
|
21374
21958
|
Such elements often live in the layout, outside of the content area that is
|
@@ -21460,21 +22044,27 @@ passively receive updates from the server.
|
|
21460
22044
|
Assume an application layout with an unread message counter.
|
21461
22045
|
You can use `[up-poll]` to refresh the counter every 30 seconds:
|
21462
22046
|
|
21463
|
-
|
21464
|
-
|
21465
|
-
|
22047
|
+
```html
|
22048
|
+
<div class="unread-count" up-poll>
|
22049
|
+
2 new messages
|
22050
|
+
</div>
|
22051
|
+
```
|
21466
22052
|
|
21467
22053
|
\#\#\# Controlling the reload interval
|
21468
22054
|
|
21469
22055
|
You may set an optional `[up-interval]` attribute to set the reload interval in milliseconds:
|
21470
22056
|
|
21471
|
-
|
21472
|
-
|
21473
|
-
|
22057
|
+
```html
|
22058
|
+
<div class="unread-count" up-poll up-interval="10000">
|
22059
|
+
2 new messages
|
22060
|
+
</div>
|
22061
|
+
```
|
21474
22062
|
|
21475
22063
|
If the value is omitted, a global default is used. You may configure the default like this:
|
21476
22064
|
|
21477
|
-
|
22065
|
+
```js
|
22066
|
+
up.radio.config.pollInterval = 10000
|
22067
|
+
```
|
21478
22068
|
|
21479
22069
|
\#\#\# Controlling the source URL
|
21480
22070
|
|
@@ -21482,13 +22072,20 @@ passively receive updates from the server.
|
|
21482
22072
|
|
21483
22073
|
To reload from another URL, set an `[up-source]` attribute on the polling element:
|
21484
22074
|
|
21485
|
-
|
21486
|
-
|
21487
|
-
|
22075
|
+
```html
|
22076
|
+
<div class="unread-count" up-poll up-source="/unread-count">
|
22077
|
+
2 new messages
|
22078
|
+
</div>
|
22079
|
+
```
|
21488
22080
|
|
21489
22081
|
\#\#\# Skipping updates when nothing changed
|
21490
22082
|
|
21491
|
-
|
22083
|
+
When polling a fragment periodically we want to avoid rendering unchanged content.
|
22084
|
+
This saves <b>CPU time</b> and reduces the <b>bandwidth cost</b> for a
|
22085
|
+
request/response exchange to **~1 KB**.
|
22086
|
+
|
22087
|
+
To achieve this we timestamp your fragments with an `[up-time]` attribute to indicate
|
22088
|
+
when the underlying data was last changed. See `[up-time]` for a detailed example.
|
21492
22089
|
|
21493
22090
|
@selector [up-poll]
|
21494
22091
|
@param [up-interval]
|