unpoly-rails 2.3.0 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of unpoly-rails might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/assets/unpoly/unpoly.es5.js +151 -66
- data/assets/unpoly/unpoly.es5.min.js +1 -1
- data/assets/unpoly/unpoly.js +151 -65
- data/assets/unpoly/unpoly.min.js +1 -1
- data/lib/unpoly/rails/version.rb +1 -1
- metadata +2 -2
data/assets/unpoly/unpoly.js
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
@module up
|
9
9
|
*/
|
10
10
|
window.up = {
|
11
|
-
version: '2.
|
11
|
+
version: '2.4.0'
|
12
12
|
};
|
13
13
|
|
14
14
|
|
@@ -96,27 +96,63 @@ up.util = (function () {
|
|
96
96
|
}
|
97
97
|
const NORMALIZE_URL_DEFAULTS = {
|
98
98
|
host: 'cross-domain',
|
99
|
-
stripTrailingSlash: false,
|
100
|
-
search: true,
|
101
|
-
hash: false
|
102
99
|
};
|
103
100
|
/*-
|
104
|
-
|
101
|
+
Returns a normalized version of the given URL string.
|
102
|
+
|
103
|
+
Two URLs that point to the same resource should normalize to the same string.
|
104
|
+
|
105
|
+
### Comparing normalized URLs
|
106
|
+
|
107
|
+
The main purpose of this function is to normalize two URLs for string comparison:
|
108
|
+
|
109
|
+
```js
|
110
|
+
up.util.normalizeURL('http://current-host/path') === up.util.normalizeURL('/path') // => true
|
111
|
+
```
|
112
|
+
|
113
|
+
By default the hostname is only included if it points to a different origin:
|
114
|
+
|
115
|
+
```js
|
116
|
+
up.util.normalizeURL('http://current-host/path') // => '/path'
|
117
|
+
up.util.normalizeURL('http://other-host/path') // => 'http://other-host/path'
|
118
|
+
```
|
119
|
+
|
120
|
+
Relative paths are normalized to absolute paths:
|
121
|
+
|
122
|
+
```js
|
123
|
+
up.util.normalizeURL('index.html') // => '/path/index.html'
|
124
|
+
```
|
125
|
+
|
126
|
+
### Excluding URL components
|
127
|
+
|
128
|
+
You may pass options to exclude URL components from the normalized string:
|
129
|
+
|
130
|
+
```js
|
131
|
+
up.util.normalizeURL('/foo?query=bar', { query: false }) => '/foo'
|
132
|
+
up.util.normalizeURL('/bar#hash', { hash: false }) => '/bar'
|
133
|
+
```
|
134
|
+
|
135
|
+
### Limitations
|
136
|
+
|
137
|
+
- Username and password are always omitted from the normalized URL.
|
138
|
+
- Only `http` and `https` schemes are supported.
|
105
139
|
|
106
140
|
@function up.util.normalizeURL
|
107
141
|
@param {boolean} [options.host='cross-domain']
|
108
142
|
Whether to include protocol, hostname and port in the normalized URL.
|
109
143
|
|
110
|
-
|
111
|
-
|
112
|
-
|
144
|
+
When set to `'cross-domain'` (the default), the host is only included if it differ's from the page's hostname.
|
145
|
+
|
146
|
+
The port is omitted if the port is the standard port for the given protocol, e.g. `:443` for `https://`.
|
147
|
+
@param {boolean} [options.hash=true]
|
148
|
+
Whether to include an `#hash` anchor in the normalized URL.
|
113
149
|
@param {boolean} [options.search=true]
|
114
|
-
Whether to include a `?query` string in the normalized URL
|
115
|
-
@param {boolean} [options.
|
116
|
-
Whether to
|
150
|
+
Whether to include a `?query` string in the normalized URL.
|
151
|
+
@param {boolean} [options.trailingSlash=true]
|
152
|
+
Whether to include a trailing slash from the pathname.
|
117
153
|
@return {string}
|
118
154
|
The normalized URL.
|
119
|
-
@
|
155
|
+
@experimental
|
120
156
|
*/
|
121
157
|
function normalizeURL(urlOrAnchor, options) {
|
122
158
|
options = newOptions(options, NORMALIZE_URL_DEFAULTS);
|
@@ -135,21 +171,18 @@ up.util = (function () {
|
|
135
171
|
}
|
136
172
|
}
|
137
173
|
let { pathname } = parts;
|
138
|
-
if (options.
|
174
|
+
if (options.trailingSlash === false && pathname !== '/') {
|
139
175
|
pathname = pathname.replace(/\/$/, '');
|
140
176
|
}
|
141
177
|
normalized += pathname;
|
142
|
-
if (options.search) {
|
178
|
+
if (options.search !== false) {
|
143
179
|
normalized += parts.search;
|
144
180
|
}
|
145
|
-
if (options.hash) {
|
181
|
+
if (options.hash !== false) {
|
146
182
|
normalized += parts.hash;
|
147
183
|
}
|
148
184
|
return normalized;
|
149
185
|
}
|
150
|
-
function urlWithoutHost(url) {
|
151
|
-
return normalizeURL(url, { host: false });
|
152
|
-
}
|
153
186
|
function matchURLs(leftURL, rightURL) {
|
154
187
|
return normalizeURL(leftURL) === normalizeURL(rightURL);
|
155
188
|
}
|
@@ -1911,7 +1944,6 @@ up.util = (function () {
|
|
1911
1944
|
return {
|
1912
1945
|
parseURL,
|
1913
1946
|
normalizeURL,
|
1914
|
-
urlWithoutHost,
|
1915
1947
|
matchURLs,
|
1916
1948
|
normalizeMethod,
|
1917
1949
|
methodAllowsPayload,
|
@@ -3858,7 +3890,7 @@ up.Change.Addition = class Addition extends up.Change {
|
|
3858
3890
|
// (1) Don't set a source if { false } is passed.
|
3859
3891
|
// (2) Don't set a source if the element HTML already has an [up-source] attribute.
|
3860
3892
|
if (source) {
|
3861
|
-
e.setMissingAttr(newElement, 'up-source', u.normalizeURL(source));
|
3893
|
+
e.setMissingAttr(newElement, 'up-source', u.normalizeURL(source, { hash: false }));
|
3862
3894
|
}
|
3863
3895
|
}
|
3864
3896
|
};
|
@@ -12962,7 +12994,7 @@ up.history = (function () {
|
|
12962
12994
|
/*-
|
12963
12995
|
Returns a normalized URL for the previous history entry.
|
12964
12996
|
|
12965
|
-
Only history entries
|
12997
|
+
Only history entries added by Unpoly functions will be considered.
|
12966
12998
|
|
12967
12999
|
@property up.history.previousLocation
|
12968
13000
|
@param {string} previousLocation
|
@@ -12976,13 +13008,20 @@ up.history = (function () {
|
|
12976
13008
|
nextPreviousLocation = undefined;
|
12977
13009
|
trackCurrentLocation();
|
12978
13010
|
}
|
12979
|
-
|
12980
|
-
|
12981
|
-
|
13011
|
+
const DEFAULT_NORMALIZE_OPTIONS = { hash: true };
|
13012
|
+
function normalizeURL(url, options) {
|
13013
|
+
// The reason why we this takes an { options } object is that
|
13014
|
+
// isCurrentLocation() ignores a trailing slash. This is used to check whether
|
13015
|
+
// we're already at the given URL before pushing a history state.
|
13016
|
+
options = u.merge(DEFAULT_NORMALIZE_OPTIONS, options);
|
13017
|
+
return u.normalizeURL(url, options);
|
12982
13018
|
}
|
12983
13019
|
/*-
|
12984
13020
|
Returns a normalized URL for the current browser location.
|
12985
13021
|
|
13022
|
+
The returned URL is an absolute pathname like `"/path"` without a hostname or port.
|
13023
|
+
It will include a `#hash` fragment and query string, if present.
|
13024
|
+
|
12986
13025
|
Note that if the current [layer](/up.layer) does not have [visible history](/up.Layer.prototype.history),
|
12987
13026
|
the browser's address bar will show the location of an ancestor layer.
|
12988
13027
|
To get the location of the current layer, use `up.layer.location`.
|
@@ -13008,11 +13047,51 @@ up.history = (function () {
|
|
13008
13047
|
}
|
13009
13048
|
}
|
13010
13049
|
trackCurrentLocation();
|
13011
|
-
|
13012
|
-
|
13013
|
-
|
13014
|
-
|
13015
|
-
|
13050
|
+
// Some web frameworks care about a trailing slash, some consider it optional.
|
13051
|
+
// Only for the equality test ("is this the current URL?") we consider it optional.
|
13052
|
+
// Note that we inherit { hash: true } from DEFAULT_NORMALIZE_OPTIONS.
|
13053
|
+
const ADDITIONAL_NORMALIZE_OPTIONS_FOR_COMPARISON = { trailingSlash: false };
|
13054
|
+
/*-
|
13055
|
+
Returns whether the given URL matches the [current browser location](/up.history.location).
|
13056
|
+
|
13057
|
+
### Examples
|
13058
|
+
|
13059
|
+
```js
|
13060
|
+
location.hostname // => '/path'
|
13061
|
+
|
13062
|
+
up.history.isLocation('/path') // => true
|
13063
|
+
up.history.isLocation('/path?query') // => false
|
13064
|
+
up.history.isLocation('/path#hash') // => false
|
13065
|
+
up.history.isLocation('/other') // => false
|
13066
|
+
```
|
13067
|
+
|
13068
|
+
The given URL is [normalized](/up.util.normalizeURL), so any URL string pointing to the browser location
|
13069
|
+
will match:
|
13070
|
+
|
13071
|
+
```js
|
13072
|
+
location.hostname // => '/current-host'
|
13073
|
+
location.pathname // => '/foo'
|
13074
|
+
|
13075
|
+
up.history.isLocation('/foo') // => true
|
13076
|
+
up.history.isLocation('http://current-host/foo') // => true
|
13077
|
+
up.history.isLocation('http://otgher-host/foo') // => false
|
13078
|
+
```
|
13079
|
+
|
13080
|
+
@function up.history.isLocation
|
13081
|
+
@param {string} url
|
13082
|
+
The URL to compare against the current browser location.
|
13083
|
+
|
13084
|
+
This can be a either an absolute pathname (`/path`), a relative filename (`index.html`) or a fully qualified URL (`https://...`).
|
13085
|
+
@param {boolean} [options.hash=true]
|
13086
|
+
Whether to consider `#hash` fragments in the given or current URLs.
|
13087
|
+
|
13088
|
+
When set to `false` this function will consider the URLs `/foo#one` and `/foo#two` to be equal.
|
13089
|
+
@return {boolean}
|
13090
|
+
@experimental
|
13091
|
+
*/
|
13092
|
+
function isLocation(url, options) {
|
13093
|
+
options = u.merge(ADDITIONAL_NORMALIZE_OPTIONS_FOR_COMPARISON, options);
|
13094
|
+
return normalizeURL(url, options) === currentLocation(options);
|
13016
13095
|
}
|
13017
13096
|
/*-
|
13018
13097
|
Replaces the current history entry and updates the
|
@@ -13031,8 +13110,9 @@ up.history = (function () {
|
|
13031
13110
|
@internal
|
13032
13111
|
*/
|
13033
13112
|
function replace(url, options = {}) {
|
13113
|
+
url = normalizeURL(url);
|
13034
13114
|
if (manipulate('replaceState', url) && (options.event !== false)) {
|
13035
|
-
emit('up:location:changed', { url, reason: 'replace', log: `Replaced state for ${
|
13115
|
+
emit('up:location:changed', { url, reason: 'replace', log: `Replaced state for ${url}` });
|
13036
13116
|
}
|
13037
13117
|
}
|
13038
13118
|
/*-
|
@@ -13045,6 +13125,8 @@ up.history = (function () {
|
|
13045
13125
|
Note that [fragment navigation](/navigation) will automatically update the
|
13046
13126
|
browser's location bar for you.
|
13047
13127
|
|
13128
|
+
Does not add a history entry if the the given URL is already the current browser location.
|
13129
|
+
|
13048
13130
|
Emits event `up:location:changed`.
|
13049
13131
|
|
13050
13132
|
@function up.history.push
|
@@ -13054,8 +13136,8 @@ up.history = (function () {
|
|
13054
13136
|
*/
|
13055
13137
|
function push(url) {
|
13056
13138
|
url = normalizeURL(url);
|
13057
|
-
if (!
|
13058
|
-
up.emit('up:location:changed', { url, reason: 'push', log: `Advanced to location ${
|
13139
|
+
if (!isLocation(url) && manipulate('pushState', url)) {
|
13140
|
+
up.emit('up:location:changed', { url, reason: 'push', log: `Advanced to location ${url}` });
|
13059
13141
|
}
|
13060
13142
|
}
|
13061
13143
|
/*-
|
@@ -13204,8 +13286,8 @@ up.history = (function () {
|
|
13204
13286
|
replace,
|
13205
13287
|
get location() { return currentLocation(); },
|
13206
13288
|
get previousLocation() { return previousLocation; },
|
13207
|
-
|
13208
|
-
|
13289
|
+
normalizeURL,
|
13290
|
+
isLocation
|
13209
13291
|
};
|
13210
13292
|
})();
|
13211
13293
|
|
@@ -14957,7 +15039,7 @@ up.fragment = (function () {
|
|
14957
15039
|
}
|
14958
15040
|
up.on('up:framework:boot', function () {
|
14959
15041
|
const { body } = document;
|
14960
|
-
body.setAttribute('up-source',
|
15042
|
+
body.setAttribute('up-source', u.normalizeURL(location.href, { hash: false }));
|
14961
15043
|
hello(body);
|
14962
15044
|
if (!up.browser.canPushState()) {
|
14963
15045
|
return up.warn('Cannot push history changes. Next fragment update will load in a new page.');
|
@@ -15585,7 +15667,7 @@ up.viewport = (function () {
|
|
15585
15667
|
const [viewports, options] = parseOptions(args);
|
15586
15668
|
const url = options.layer.location;
|
15587
15669
|
const scrollTopsForURL = options.layer.lastScrollTops.get(url) || {};
|
15588
|
-
up.puts('up.viewport.restoreScroll()', 'Restoring scroll positions for URL %s to %o',
|
15670
|
+
up.puts('up.viewport.restoreScroll()', 'Restoring scroll positions for URL %s to %o', url, scrollTopsForURL);
|
15589
15671
|
return setScrollTops(viewports, scrollTopsForURL);
|
15590
15672
|
}
|
15591
15673
|
function parseOptions(args) {
|
@@ -17031,20 +17113,11 @@ up.network = (function () {
|
|
17031
17113
|
function makeRequest(...args) {
|
17032
17114
|
const request = new up.Request(parseRequestOptions(args));
|
17033
17115
|
useCachedRequest(request) || queueRequest(request);
|
17034
|
-
|
17035
|
-
if (solo) {
|
17036
|
-
// The { solo } option may also contain a function.
|
17037
|
-
// This way users can excempt some requests from being solo-aborted
|
17038
|
-
// by configuring up.fragment.config.navigateOptions.
|
17039
|
-
queue.abortExcept(request, solo);
|
17040
|
-
}
|
17116
|
+
handleSolo(request);
|
17041
17117
|
return request;
|
17042
17118
|
}
|
17043
17119
|
function mimicLocalRequest(options) {
|
17044
|
-
|
17045
|
-
if (solo) {
|
17046
|
-
abortRequests(solo);
|
17047
|
-
}
|
17120
|
+
handleSolo(options);
|
17048
17121
|
// We cannot consult config.clearCache since there is no up.Request
|
17049
17122
|
// for a local update.
|
17050
17123
|
let clearCache = options.clearCache;
|
@@ -17052,6 +17125,21 @@ up.network = (function () {
|
|
17052
17125
|
cache.clear(clearCache);
|
17053
17126
|
}
|
17054
17127
|
}
|
17128
|
+
function handleSolo(requestOrOptions) {
|
17129
|
+
let solo = requestOrOptions.solo;
|
17130
|
+
if (solo && isBusy()) {
|
17131
|
+
up.puts('up.request()', 'Change with { solo } option will abort other requests');
|
17132
|
+
// The { solo } option may also contain a function.
|
17133
|
+
// This way users can excempt some requests from being solo-aborted
|
17134
|
+
// by configuring up.fragment.config.navigateOptions.
|
17135
|
+
if (requestOrOptions instanceof up.Request) {
|
17136
|
+
queue.abortExcept(requestOrOptions, solo);
|
17137
|
+
}
|
17138
|
+
else {
|
17139
|
+
abortRequests(solo);
|
17140
|
+
}
|
17141
|
+
}
|
17142
|
+
}
|
17055
17143
|
function parseRequestOptions(args) {
|
17056
17144
|
const options = u.extractOptions(args);
|
17057
17145
|
if (!options.url) {
|
@@ -21156,10 +21244,11 @@ up.feedback = (function () {
|
|
21156
21244
|
*/
|
21157
21245
|
const config = new up.Config(() => ({
|
21158
21246
|
currentClasses: ['up-current'],
|
21159
|
-
navSelectors: ['[up-nav]', 'nav']
|
21247
|
+
navSelectors: ['[up-nav]', 'nav'],
|
21160
21248
|
}));
|
21161
21249
|
function reset() {
|
21162
21250
|
config.reset();
|
21251
|
+
up.layer.root.feedbackLocation = null;
|
21163
21252
|
}
|
21164
21253
|
const CLASS_ACTIVE = 'up-active';
|
21165
21254
|
const SELECTOR_LINK = 'a, [up-href]';
|
@@ -21168,7 +21257,7 @@ up.feedback = (function () {
|
|
21168
21257
|
}
|
21169
21258
|
function normalizeURL(url) {
|
21170
21259
|
if (url) {
|
21171
|
-
return u.normalizeURL(url, {
|
21260
|
+
return u.normalizeURL(url, { trailingSlash: false, hash: false });
|
21172
21261
|
}
|
21173
21262
|
}
|
21174
21263
|
function linkURLs(link) {
|
@@ -21203,17 +21292,11 @@ up.feedback = (function () {
|
|
21203
21292
|
const links = u.flatMap(navs, nav => e.subtree(nav, SELECTOR_LINK));
|
21204
21293
|
updateLinks(links, options);
|
21205
21294
|
}
|
21206
|
-
|
21207
|
-
|
21208
|
-
|
21209
|
-
|
21210
|
-
|
21211
|
-
// The { feedbackLocation } property may be nil if:
|
21212
|
-
// (1) The layer was opened without a location, e.g. if it was created from local HTML.
|
21213
|
-
// (2) The layer is the root layer and the location was never changed.
|
21214
|
-
// The initial page load does not emit an up:layer:location:changed event for
|
21215
|
-
// the root layer to be consistent with up:location:changed.
|
21216
|
-
layer.feedbackLocation || layer.location;
|
21295
|
+
function getNormalizedLayerLocation(layer) {
|
21296
|
+
// Don't re-use layer.feedbackLocation since the current layer returns
|
21297
|
+
// location.href in case someone changed the history using the pushState API.
|
21298
|
+
return layer.feedbackLocation || normalizeURL(layer.location);
|
21299
|
+
}
|
21217
21300
|
function updateLinks(links, options = {}) {
|
21218
21301
|
if (!links.length) {
|
21219
21302
|
return;
|
@@ -21221,7 +21304,7 @@ up.feedback = (function () {
|
|
21221
21304
|
const layer = options.layer || up.layer.get(links[0]);
|
21222
21305
|
// An overlay might not have a { location } property, e.g. if it was created
|
21223
21306
|
// from local { content }. In this case we do not set .up-current.
|
21224
|
-
let layerLocation =
|
21307
|
+
let layerLocation = getNormalizedLayerLocation(layer);
|
21225
21308
|
if (layerLocation) {
|
21226
21309
|
for (let link of links) {
|
21227
21310
|
const isCurrent = linkURLs(link).isCurrent(layerLocation);
|
@@ -21436,6 +21519,8 @@ up.feedback = (function () {
|
|
21436
21519
|
- the link's `[up-href]` attribute
|
21437
21520
|
- the URL pattern in the link's [`[up-alias]`](/a-up-alias) attribute
|
21438
21521
|
|
21522
|
+
Any `#hash` fragments in the link's or current URLs will be ignored.
|
21523
|
+
|
21439
21524
|
@selector [up-nav]
|
21440
21525
|
@stable
|
21441
21526
|
*/
|
@@ -21470,13 +21555,14 @@ up.feedback = (function () {
|
|
21470
21555
|
*/
|
21471
21556
|
function updateLayerIfLocationChanged(layer) {
|
21472
21557
|
const processedLocation = layer.feedbackLocation;
|
21473
|
-
const
|
21558
|
+
const layerLocation = getNormalizedLayerLocation(layer.location);
|
21474
21559
|
// A history change might call this function multiple times,
|
21475
21560
|
// since we listen to both up:location:changed and up:layer:location:changed.
|
21561
|
+
// We also don't want to unnecessarily reprocess nav links, which is expensive.
|
21476
21562
|
// For this reason we check whether the current location differs from
|
21477
21563
|
// the last processed location.
|
21478
|
-
if (!processedLocation || (processedLocation !==
|
21479
|
-
layer.feedbackLocation =
|
21564
|
+
if (!processedLocation || (processedLocation !== layerLocation)) {
|
21565
|
+
layer.feedbackLocation = layerLocation;
|
21480
21566
|
updateLinksWithinNavs(layer.element, { layer });
|
21481
21567
|
}
|
21482
21568
|
}
|
@@ -21506,7 +21592,7 @@ up.feedback = (function () {
|
|
21506
21592
|
stop,
|
21507
21593
|
around,
|
21508
21594
|
aroundForOptions,
|
21509
|
-
normalizeURL
|
21595
|
+
normalizeURL,
|
21510
21596
|
};
|
21511
21597
|
})();
|
21512
21598
|
|