unpoly-rails 0.56.7 → 0.57.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of unpoly-rails might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +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
|