unpoly-rails 0.56.7 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of unpoly-rails might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +74 -1
- data/dist/unpoly.js +1569 -793
- data/dist/unpoly.min.js +4 -4
- data/lib/assets/javascripts/unpoly.coffee +2 -0
- data/lib/assets/javascripts/unpoly/browser.coffee.erb +25 -41
- data/lib/assets/javascripts/unpoly/bus.coffee.erb +20 -6
- data/lib/assets/javascripts/unpoly/classes/cache.coffee +23 -13
- data/lib/assets/javascripts/unpoly/classes/compile_pass.coffee +87 -0
- data/lib/assets/javascripts/unpoly/classes/focus_tracker.coffee +29 -0
- data/lib/assets/javascripts/unpoly/classes/follow_variant.coffee +7 -4
- data/lib/assets/javascripts/unpoly/classes/record.coffee +1 -1
- data/lib/assets/javascripts/unpoly/classes/request.coffee +38 -45
- data/lib/assets/javascripts/unpoly/classes/response.coffee +16 -1
- data/lib/assets/javascripts/unpoly/classes/store/memory.coffee +26 -0
- data/lib/assets/javascripts/unpoly/classes/store/session.coffee +59 -0
- data/lib/assets/javascripts/unpoly/cookie.coffee +56 -0
- data/lib/assets/javascripts/unpoly/dom.coffee.erb +67 -39
- data/lib/assets/javascripts/unpoly/feedback.coffee +2 -2
- data/lib/assets/javascripts/unpoly/form.coffee.erb +23 -12
- data/lib/assets/javascripts/unpoly/history.coffee +2 -2
- data/lib/assets/javascripts/unpoly/layout.coffee.erb +118 -99
- data/lib/assets/javascripts/unpoly/link.coffee.erb +12 -5
- data/lib/assets/javascripts/unpoly/log.coffee +6 -5
- data/lib/assets/javascripts/unpoly/modal.coffee.erb +9 -2
- data/lib/assets/javascripts/unpoly/motion.coffee.erb +2 -6
- data/lib/assets/javascripts/unpoly/namespace.coffee.erb +2 -2
- data/lib/assets/javascripts/unpoly/params.coffee.erb +522 -0
- data/lib/assets/javascripts/unpoly/popup.coffee.erb +3 -3
- data/lib/assets/javascripts/unpoly/proxy.coffee +42 -34
- data/lib/assets/javascripts/unpoly/{syntax.coffee → syntax.coffee.erb} +59 -117
- data/lib/assets/javascripts/unpoly/{util.coffee → util.coffee.erb} +206 -171
- data/lib/unpoly/rails/version.rb +1 -1
- data/package.json +1 -1
- data/spec_app/Gemfile.lock +1 -1
- data/spec_app/app/assets/javascripts/integration_test.coffee +0 -4
- data/spec_app/app/assets/stylesheets/integration_test.sass +7 -1
- data/spec_app/app/controllers/pages_controller.rb +4 -0
- data/spec_app/app/views/form_test/basics/new.erb +34 -5
- data/spec_app/app/views/form_test/submission_result.erb +2 -2
- data/spec_app/app/views/form_test/uploads/new.erb +15 -2
- data/spec_app/app/views/hash_test/unpoly.erb +30 -0
- data/spec_app/app/views/pages/start.erb +2 -1
- data/spec_app/spec/javascripts/helpers/parse_form_data.js.coffee +17 -2
- data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +5 -0
- data/spec_app/spec/javascripts/helpers/to_be_error.coffee +1 -1
- data/spec_app/spec/javascripts/helpers/to_match_selector.coffee +5 -0
- data/spec_app/spec/javascripts/up/browser_spec.js.coffee +8 -8
- data/spec_app/spec/javascripts/up/bus_spec.js.coffee +58 -20
- data/spec_app/spec/javascripts/up/classes/cache_spec.js.coffee +78 -0
- data/spec_app/spec/javascripts/up/classes/focus_tracker_spec.coffee +31 -0
- data/spec_app/spec/javascripts/up/classes/request_spec.coffee +50 -0
- data/spec_app/spec/javascripts/up/classes/store/memory_spec.js.coffee +67 -0
- data/spec_app/spec/javascripts/up/classes/store/session_spec.js.coffee +113 -0
- data/spec_app/spec/javascripts/up/dom_spec.js.coffee +133 -45
- data/spec_app/spec/javascripts/up/form_spec.js.coffee +13 -13
- data/spec_app/spec/javascripts/up/layout_spec.js.coffee +110 -26
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +1 -0
- data/spec_app/spec/javascripts/up/motion_spec.js.coffee +52 -51
- data/spec_app/spec/javascripts/up/namespace_spec.js.coffee +2 -2
- data/spec_app/spec/javascripts/up/params_spec.coffee +768 -0
- data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +75 -36
- data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +48 -15
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +148 -131
- metadata +17 -5
- data/spec_app/spec/javascripts/up/classes/.keep +0 -0
@@ -92,7 +92,7 @@ up.feedback = (($) ->
|
|
92
92
|
for attr in ['href', 'up-href', 'up-alias']
|
93
93
|
if value = u.presentAttr($section, attr)
|
94
94
|
# Allow to include multiple space-separated URLs in [up-alias]
|
95
|
-
for url in
|
95
|
+
for url in u.splitValues(value)
|
96
96
|
unless url == '#'
|
97
97
|
url = normalizeUrl(url)
|
98
98
|
urls.push(url)
|
@@ -371,4 +371,4 @@ up.feedback = (($) ->
|
|
371
371
|
|
372
372
|
)(jQuery)
|
373
373
|
|
374
|
-
up.
|
374
|
+
up.deprecateRenamedModule 'navigation', 'feedback'
|
@@ -28,13 +28,16 @@ up.form = (($) ->
|
|
28
28
|
By default this looks for a `<fieldset>`, `<label>` or `<form>`
|
29
29
|
around the validating input field, or any element with an
|
30
30
|
`up-fieldset` attribute.
|
31
|
-
@param {string} [config.fields
|
31
|
+
@param {string} [config.fields]
|
32
32
|
An array of CSS selectors that represent form fields, such as `input` or `select`.
|
33
|
+
@param {string} [config.submitButtons]
|
34
|
+
An array of CSS selectors that represent submit buttons, such as `input[type=submit]`.
|
33
35
|
@stable
|
34
36
|
###
|
35
37
|
config = u.config
|
36
38
|
validateTargets: ['[up-fieldset]:has(&)', 'fieldset:has(&)', 'label:has(&)', 'form:has(&)']
|
37
|
-
fields: [':
|
39
|
+
fields: ['select', 'input:not([type=submit]):not([type=image])', 'button[type]:not([type=submit])', 'textarea'],
|
40
|
+
submitButtons: ['input[type=submit]', 'input[type=image]', 'button[type=submit]', 'button:not([type])']
|
38
41
|
observeDelay: 0
|
39
42
|
|
40
43
|
reset = ->
|
@@ -47,6 +50,13 @@ up.form = (($) ->
|
|
47
50
|
fieldSelector = ->
|
48
51
|
config.fields.join(',')
|
49
52
|
|
53
|
+
###**
|
54
|
+
@function up.form.submitButtonSelector
|
55
|
+
@internal
|
56
|
+
###
|
57
|
+
submitButtonSelector = ->
|
58
|
+
config.submitButtons.join(',')
|
59
|
+
|
50
60
|
###**
|
51
61
|
Submits a form via AJAX and updates a page fragment with the response.
|
52
62
|
|
@@ -129,9 +139,9 @@ up.form = (($) ->
|
|
129
139
|
with the request.
|
130
140
|
@param {string} [options.layer='auto']
|
131
141
|
The name of the layer that ought to be updated. Valid values are
|
132
|
-
`auto`, `page`, `modal` and `popup`.
|
142
|
+
`'auto'`, `'page'`, `'modal'` and `'popup'`.
|
133
143
|
|
134
|
-
If set to `auto` (default), Unpoly will try to find a match in the form's layer.
|
144
|
+
If set to `'auto'` (default), Unpoly will try to find a match in the form's layer.
|
135
145
|
@param {string} [options.failLayer='auto']
|
136
146
|
The name of the layer that ought to be updated if the server sends a non-200 status code.
|
137
147
|
@return {Promise}
|
@@ -158,7 +168,7 @@ up.form = (($) ->
|
|
158
168
|
options.origin = u.option(options.origin, $form)
|
159
169
|
options.layer = u.option(options.layer, $form.attr('up-layer'), 'auto')
|
160
170
|
options.failLayer = u.option(options.failLayer, $form.attr('up-fail-layer'), 'auto')
|
161
|
-
options.
|
171
|
+
options.params = up.params.fromForm($form)
|
162
172
|
options = u.merge(options, up.motion.animateOptions(options, $form))
|
163
173
|
|
164
174
|
if options.validate
|
@@ -167,7 +177,7 @@ up.form = (($) ->
|
|
167
177
|
options.failTransition = false
|
168
178
|
options.headers[up.protocol.config.validateHeader] = options.validate
|
169
179
|
|
170
|
-
up.bus.whenEmitted('up:form:submit', $element: $form).then ->
|
180
|
+
up.bus.whenEmitted('up:form:submit', message: 'Submitting form', $form: $form, $element: $form).then ->
|
171
181
|
up.feedback.start($form)
|
172
182
|
|
173
183
|
# If we can't update the location URL, fall back to a vanilla form submission.
|
@@ -184,7 +194,7 @@ up.form = (($) ->
|
|
184
194
|
This event is [emitted](/up.emit) when a form is [submitted](/up.submit) through Unpoly.
|
185
195
|
|
186
196
|
@event up:form:submit
|
187
|
-
@param {jQuery} event.$
|
197
|
+
@param {jQuery} event.$form
|
188
198
|
The `<form>` element that will be submitted.
|
189
199
|
@param event.preventDefault()
|
190
200
|
Event listeners may call this method to prevent the form from being submitted.
|
@@ -430,11 +440,11 @@ up.form = (($) ->
|
|
430
440
|
$target = $(target)
|
431
441
|
fieldValues ||= switcherValues(findSwitcherForTarget($target))
|
432
442
|
if hideValues = $target.attr('up-hide-for')
|
433
|
-
hideValues =
|
443
|
+
hideValues = u.splitValues(hideValues)
|
434
444
|
show = u.intersect(fieldValues, hideValues).length == 0
|
435
445
|
else
|
436
446
|
if showValues = $target.attr('up-show-for')
|
437
|
-
showValues =
|
447
|
+
showValues = u.splitValues(showValues)
|
438
448
|
else
|
439
449
|
# If the target has neither up-show-for or up-hide-for attributes,
|
440
450
|
# assume the user wants the target to be visible whenever anything
|
@@ -472,7 +482,7 @@ up.form = (($) ->
|
|
472
482
|
|
473
483
|
\#\#\# Failed submission
|
474
484
|
|
475
|
-
When the server was unable to save the form due to invalid
|
485
|
+
When the server was unable to save the form due to invalid params,
|
476
486
|
it will usually re-render an updated copy of the form with
|
477
487
|
validation messages.
|
478
488
|
|
@@ -555,9 +565,9 @@ up.form = (($) ->
|
|
555
565
|
or `method` (vanilla HTML) for the same purpose.
|
556
566
|
@param {string} [up-layer='auto']
|
557
567
|
The name of the layer that ought to be updated. Valid values are
|
558
|
-
`auto`, `page`, `modal` and `popup`.
|
568
|
+
`'auto'`, `'page'`, `'modal'` and `'popup'`.
|
559
569
|
|
560
|
-
If set to `auto` (default), Unpoly will try to find a match in the form's layer.
|
570
|
+
If set to `'auto'` (default), Unpoly will try to find a match in the form's layer.
|
561
571
|
If no match was found in that layer,
|
562
572
|
Unpoly will search in other layers, starting from the topmost layer.
|
563
573
|
@param {string} [up-fail-layer='auto']
|
@@ -978,6 +988,7 @@ up.form = (($) ->
|
|
978
988
|
switchTargets: switchTargets
|
979
989
|
autosubmit: autosubmit
|
980
990
|
fieldSelector: fieldSelector
|
991
|
+
submitButtonSelector: submitButtonSelector
|
981
992
|
|
982
993
|
)(jQuery)
|
983
994
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
###**
|
2
2
|
History
|
3
3
|
========
|
4
|
-
|
4
|
+
|
5
5
|
In an Unpoly app, every page has an URL.
|
6
6
|
|
7
7
|
[Fragment updates](/up.link) automatically update the URL.
|
@@ -60,7 +60,7 @@ up.history = (($) ->
|
|
60
60
|
###
|
61
61
|
currentUrl = (normalizeOptions) ->
|
62
62
|
normalizeUrl(up.browser.url(), normalizeOptions)
|
63
|
-
|
63
|
+
|
64
64
|
isCurrentUrl = (url) ->
|
65
65
|
normalizeOptions = { stripTrailingSlash: true }
|
66
66
|
normalizeUrl(url, normalizeOptions) == currentUrl(normalizeOptions)
|
@@ -115,23 +115,16 @@ up.layout = (($) ->
|
|
115
115
|
@experimental
|
116
116
|
###
|
117
117
|
scroll = (viewport, scrollTop, options) ->
|
118
|
-
$
|
118
|
+
$viewport = $(viewport)
|
119
119
|
options = u.options(options)
|
120
120
|
options.duration = u.option(options.duration, config.duration)
|
121
121
|
options.easing = u.option(options.easing, config.easing)
|
122
122
|
|
123
|
-
finishScrolling($
|
123
|
+
finishScrolling($viewport).then ->
|
124
124
|
if up.motion.isEnabled() && options.duration > 0
|
125
|
-
scrollWithAnimateNow($
|
125
|
+
scrollWithAnimateNow($viewport, scrollTop, options)
|
126
126
|
else
|
127
|
-
scrollAbruptlyNow($
|
128
|
-
|
129
|
-
scrollableElementForViewport = (viewport) ->
|
130
|
-
$viewport = $(viewport)
|
131
|
-
if $viewport.get(0) == document
|
132
|
-
$('html, body') # FML
|
133
|
-
else
|
134
|
-
$viewport
|
127
|
+
scrollAbruptlyNow($viewport, scrollTop)
|
135
128
|
|
136
129
|
scrollWithAnimateNow = ($scrollable, scrollTop, animateOptions) ->
|
137
130
|
start = ->
|
@@ -164,7 +157,7 @@ up.layout = (($) ->
|
|
164
157
|
# Don't emit expensive events if no animation can be running anyway
|
165
158
|
return Promise.resolve() unless up.motion.isEnabled()
|
166
159
|
|
167
|
-
$scrollable =
|
160
|
+
$scrollable = viewportOf(element)
|
168
161
|
scrollingTracker.finish($scrollable)
|
169
162
|
|
170
163
|
###**
|
@@ -180,22 +173,25 @@ up.layout = (($) ->
|
|
180
173
|
@return {Object}
|
181
174
|
@internal
|
182
175
|
###
|
183
|
-
measureObstruction = ->
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
176
|
+
measureObstruction = (viewportHeight) ->
|
177
|
+
composeHeight = (obstructor, distanceFromEdgeProps) ->
|
178
|
+
distanceFromEdge = u.sum(distanceFromEdgeProps, (prop) -> u.readComputedStyleNumber(obstructor, prop)) || 0
|
179
|
+
distanceFromEdge + obstructor.offsetHeight
|
180
|
+
|
181
|
+
measureTopObstructor = (obstructor) ->
|
182
|
+
composeHeight(obstructor, ['top', 'margin-top'])
|
183
|
+
|
184
|
+
measureBottomObstructor = (obstructor) ->
|
185
|
+
composeHeight(obstructor, ['bottom', 'margin-bottom'])
|
186
|
+
|
187
|
+
$topObstructors = $(config.fixedTop.join(', '))
|
188
|
+
$bottomObstructors = $(config.fixedBottom.join(', '))
|
189
|
+
|
190
|
+
topObstructions = u.map($topObstructors, measureTopObstructor)
|
191
|
+
bottomObstructions = u.map($bottomObstructors, measureBottomObstructor)
|
192
|
+
|
193
|
+
top: Math.max(0, topObstructions...)
|
194
|
+
bottom: Math.max(0, bottomObstructions...)
|
199
195
|
|
200
196
|
###**
|
201
197
|
Scroll's the given element's viewport so the first rows of the
|
@@ -250,7 +246,7 @@ up.layout = (($) ->
|
|
250
246
|
|
251
247
|
snap = u.option(options.snap, config.snap)
|
252
248
|
|
253
|
-
viewportIsDocument = $viewport.is(
|
249
|
+
viewportIsDocument = $viewport.is(up.browser.documentViewportSelector())
|
254
250
|
viewportHeight = if viewportIsDocument then u.clientSize().height else $viewport.outerHeight()
|
255
251
|
originalScrollPos = $viewport.scrollTop()
|
256
252
|
newScrollPos = originalScrollPos
|
@@ -259,7 +255,7 @@ up.layout = (($) ->
|
|
259
255
|
obstruction = undefined
|
260
256
|
|
261
257
|
if viewportIsDocument
|
262
|
-
obstruction = measureObstruction()
|
258
|
+
obstruction = measureObstruction(viewportHeight)
|
263
259
|
# Within the body, $.position will always return the distance
|
264
260
|
# from the document top and *not* the distance of the viewport
|
265
261
|
# top. This is what the calculations below expect, so don't shift.
|
@@ -274,11 +270,11 @@ up.layout = (($) ->
|
|
274
270
|
offsetShift = originalScrollPos
|
275
271
|
|
276
272
|
predictFirstVisibleRow = -> newScrollPos + obstruction.top
|
277
|
-
predictLastVisibleRow = -> newScrollPos + viewportHeight - obstruction.bottom
|
273
|
+
predictLastVisibleRow = -> newScrollPos + viewportHeight - obstruction.bottom
|
278
274
|
|
279
275
|
elementDims = u.measure($element, relative: $viewport, includeMargin: true)
|
280
276
|
firstElementRow = elementDims.top + offsetShift
|
281
|
-
lastElementRow = firstElementRow + Math.min(elementDims.height, config.substance)
|
277
|
+
lastElementRow = firstElementRow + Math.min(elementDims.height, config.substance)
|
282
278
|
|
283
279
|
if lastElementRow > predictLastVisibleRow()
|
284
280
|
# Try to show the full height of the element
|
@@ -297,32 +293,91 @@ up.layout = (($) ->
|
|
297
293
|
Promise.resolve()
|
298
294
|
|
299
295
|
###**
|
300
|
-
|
296
|
+
@function up.layout.scrollAfterInsertFragment
|
297
|
+
@param {boolean|object} [options.restoreScroll]
|
298
|
+
@param {boolean|string|jQuery|Element} [options.reveal]
|
299
|
+
@param {boolean|string} [options.reveal]
|
300
|
+
@return {Promise}
|
301
|
+
A promise that is fulfilled when the scrolling has finished.
|
302
|
+
@internal
|
303
|
+
###
|
304
|
+
scrollAfterInsertFragment = (selectorOrElement, options) ->
|
305
|
+
options = u.options(options)
|
306
|
+
$element = $(selectorOrElement)
|
307
|
+
|
308
|
+
hashOpt = options.hash
|
309
|
+
revealOpt = options.reveal
|
310
|
+
restoreScrollOpt = options.restoreScroll
|
311
|
+
|
312
|
+
durationOptions = u.only(options, 'duration')
|
313
|
+
|
314
|
+
if restoreScrollOpt
|
315
|
+
# If options.restoreScroll is an object, its keys map viewport selectors
|
316
|
+
# to scroll positions. If it is just true, we leave the scrollTops option
|
317
|
+
# undefined and let restoreScroll() retrieve previous scrollTops from cache.
|
318
|
+
givenTops = u.presence(restoreScrollOpt, u.isObject)
|
319
|
+
return restoreScroll(around: $element, scrollTops: givenTops)
|
320
|
+
|
321
|
+
else if hashOpt && revealOpt == true # hash revealing can be disabled with { reveal: false }
|
322
|
+
return revealHash(hashOpt, durationOptions)
|
323
|
+
|
324
|
+
else if revealOpt
|
325
|
+
# We allow to pass another element as { reveal } option
|
326
|
+
if u.isElement(revealOpt) || u.isJQuery(revealOpt)
|
327
|
+
$element = $(revealOpt)
|
328
|
+
|
329
|
+
# We allow to pass a selector as { reveal } option
|
330
|
+
else if u.isString(revealOpt)
|
331
|
+
selector = up.dom.resolveSelector(revealOpt, options.origin)
|
332
|
+
$element = up.first(selector)
|
333
|
+
|
334
|
+
else
|
335
|
+
# We reveal the given $element
|
336
|
+
|
337
|
+
# If selectorOrElement was a CSS selector, don't blow up by calling reveal()
|
338
|
+
# with an empty jQuery collection. This might happen if a failed form submission
|
339
|
+
# reveals the first validation error message, but the error is shown in an
|
340
|
+
# unexpected element.
|
341
|
+
if $element.length
|
342
|
+
return reveal($element, durationOptions)
|
343
|
+
|
344
|
+
else
|
345
|
+
# If we didn't need to scroll above, just return a resolved promise
|
346
|
+
# to fulfill this function's signature.
|
347
|
+
return Promise.resolve()
|
348
|
+
|
349
|
+
###**
|
350
|
+
[Reveals](/up.reveal) an element matching the given `#hash` anchor.
|
301
351
|
|
302
352
|
Other than the default behavior found in browsers, `up.revealHash` works with
|
303
353
|
[multiple viewports](/up-viewport) and honors [fixed elements](/up-fixed-top) obstructing the user's
|
304
354
|
view of the viewport.
|
305
355
|
|
306
|
-
|
356
|
+
When the page loads initially, this function is automatically called with the hash from
|
357
|
+
the current URL.
|
358
|
+
|
359
|
+
If no element matches the given `#hash` anchor, a resolved promise is returned.
|
307
360
|
|
308
361
|
@function up.layout.revealHash
|
309
362
|
@return {Promise}
|
310
363
|
A promise that is fulfilled when scroll position has changed to match the location hash.
|
311
364
|
@experimental
|
312
365
|
###
|
313
|
-
revealHash = ->
|
314
|
-
if (hash
|
315
|
-
reveal($match)
|
366
|
+
revealHash = (hash) ->
|
367
|
+
if (hash) && ($match = firstHashTarget(hash))
|
368
|
+
reveal($match, top: true)
|
316
369
|
else
|
317
370
|
Promise.resolve()
|
318
371
|
|
319
372
|
viewportSelector = ->
|
320
|
-
|
373
|
+
# On Edge the document viewport can be changed from CSS
|
374
|
+
[up.browser.documentViewportSelector(), config.viewports...].join(',')
|
321
375
|
|
322
376
|
###**
|
323
377
|
Returns the viewport for the given element.
|
324
378
|
|
325
|
-
Returns
|
379
|
+
Returns the [document's scrolling element](https://developer.mozilla.org/en-US/docs/Web/API/Document/scrollingElement)
|
380
|
+
if no closer viewpoint exists.
|
326
381
|
|
327
382
|
@function up.layout.viewportOf
|
328
383
|
@param {string|Element|jQuery} selectorOrElement
|
@@ -331,10 +386,7 @@ up.layout = (($) ->
|
|
331
386
|
###
|
332
387
|
viewportOf = (selectorOrElement, options = {}) ->
|
333
388
|
$element = $(selectorOrElement)
|
334
|
-
$
|
335
|
-
if $viewport.length == 0
|
336
|
-
$viewport = $(document)
|
337
|
-
$viewport
|
389
|
+
$element.closest(viewportSelector())
|
338
390
|
|
339
391
|
###**
|
340
392
|
Returns a jQuery collection of all the viewports contained within the
|
@@ -356,14 +408,10 @@ up.layout = (($) ->
|
|
356
408
|
@internal
|
357
409
|
###
|
358
410
|
viewports = ->
|
359
|
-
$(
|
411
|
+
$(viewportSelector())
|
360
412
|
|
361
413
|
scrollTopKey = (viewport) ->
|
362
|
-
|
363
|
-
if $viewport.is(document)
|
364
|
-
'document'
|
365
|
-
else
|
366
|
-
u.selectorForElement($viewport)
|
414
|
+
u.selectorForElement(viewport)
|
367
415
|
|
368
416
|
###**
|
369
417
|
Returns a hash with scroll positions.
|
@@ -447,7 +495,7 @@ up.layout = (($) ->
|
|
447
495
|
else
|
448
496
|
$viewports = viewports()
|
449
497
|
|
450
|
-
scrollTopsForUrl = lastScrollTops.get(url) || {}
|
498
|
+
scrollTopsForUrl = options.scrollTops || lastScrollTops.get(url) || {}
|
451
499
|
|
452
500
|
up.log.group 'Restoring scroll positions for URL %s to %o', url, scrollTopsForUrl, ->
|
453
501
|
allScrollPromises = u.map $viewports, (viewport) ->
|
@@ -457,51 +505,6 @@ up.layout = (($) ->
|
|
457
505
|
|
458
506
|
Promise.all(allScrollPromises)
|
459
507
|
|
460
|
-
###**
|
461
|
-
@function up.layout.revealOrRestoreScroll
|
462
|
-
@param {boolean} [options.restoreScroll]
|
463
|
-
@param {boolean|string} [options.reveal]
|
464
|
-
@return {Promise}
|
465
|
-
A promise that is fulfilled when the element is revealed or
|
466
|
-
the scroll position is restored.
|
467
|
-
@internal
|
468
|
-
###
|
469
|
-
revealOrRestoreScroll = (selectorOrElement, options) ->
|
470
|
-
options = u.options(options)
|
471
|
-
$element = $(selectorOrElement)
|
472
|
-
|
473
|
-
if options.restoreScroll
|
474
|
-
return restoreScroll(around: $element)
|
475
|
-
|
476
|
-
if options.reveal
|
477
|
-
revealOptions = { duration: options.duration }
|
478
|
-
if u.isString(options.reveal)
|
479
|
-
selector = revealSelector(options.reveal, options)
|
480
|
-
$element = up.first(selector) || $element
|
481
|
-
revealOptions.top = true
|
482
|
-
|
483
|
-
# If selectorOrElement was a CSS selector, don't blow up by calling reveal()
|
484
|
-
# with an empty jQuery collection. This might happen if a failed form submission
|
485
|
-
# reveals the first validation error message, but the error is shown in an
|
486
|
-
# unexpected element.
|
487
|
-
if $element.length
|
488
|
-
return reveal($element, revealOptions)
|
489
|
-
|
490
|
-
# If we didn't need to scroll above, just return a resolved promise
|
491
|
-
# to fulfill this function's signature.
|
492
|
-
return Promise.resolve()
|
493
|
-
|
494
|
-
###**
|
495
|
-
@internal
|
496
|
-
###
|
497
|
-
revealSelector = (selector, options) ->
|
498
|
-
# up.dom.resolveSelector() will (1) substitute any "&" shorthands with an selector
|
499
|
-
# for options.origin and (2) convert selector into a string, if it is an Element.
|
500
|
-
selector = up.dom.resolveSelector(selector, options.origin)
|
501
|
-
if selector[0] == '#'
|
502
|
-
selector += ", a[name='#{selector}']"
|
503
|
-
selector
|
504
|
-
|
505
508
|
###**
|
506
509
|
@internal
|
507
510
|
###
|
@@ -686,10 +689,26 @@ up.layout = (($) ->
|
|
686
689
|
@internal
|
687
690
|
###
|
688
691
|
firstHashTarget = (hash) ->
|
689
|
-
if hash =
|
690
|
-
|
692
|
+
if hash = pureHash(hash)
|
693
|
+
byID = u.attributeSelector('id', hash)
|
694
|
+
byName = 'a' + u.attributeSelector('name', hash)
|
695
|
+
up.first("#{byID},#{byName}")
|
696
|
+
|
697
|
+
|
698
|
+
###**
|
699
|
+
Returns `'foo'` if the hash is `'#foo'`.
|
700
|
+
|
701
|
+
Returns undefined if the hash is `'#'`, `''` or `undefined`.
|
702
|
+
|
703
|
+
@function up.browser.hash
|
704
|
+
@internal
|
705
|
+
###
|
706
|
+
pureHash = (value) ->
|
707
|
+
if value && value[0] == '#'
|
708
|
+
value = value.substr(1)
|
709
|
+
u.presence(value)
|
691
710
|
|
692
|
-
up.on 'up:app:booted', revealHash
|
711
|
+
up.on 'up:app:booted', -> revealHash(location.hash)
|
693
712
|
|
694
713
|
up.on 'up:framework:reset', reset
|
695
714
|
|
@@ -705,7 +724,7 @@ up.layout = (($) ->
|
|
705
724
|
scrollTops: scrollTops
|
706
725
|
saveScroll: saveScroll
|
707
726
|
restoreScroll: restoreScroll
|
708
|
-
|
727
|
+
scrollAfterInsertFragment: scrollAfterInsertFragment
|
709
728
|
anchoredRight: anchoredRight
|
710
729
|
fixedChildren: fixedChildren
|
711
730
|
absolutize: absolutize
|