unpoly-rails 0.37.0 → 0.50.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 +127 -25
- data/LICENSE +1 -1
- data/README_RAILS.md +4 -2
- data/Rakefile +6 -1
- data/dist/unpoly.js +3192 -2198
- data/dist/unpoly.min.js +4 -3
- data/lib/assets/javascripts/unpoly/browser.coffee +51 -63
- data/lib/assets/javascripts/unpoly/bus.coffee +58 -33
- data/lib/assets/javascripts/unpoly/classes/cache.coffee +117 -0
- data/lib/assets/javascripts/unpoly/{dom → classes}/extract_cascade.coffee +3 -3
- data/lib/assets/javascripts/unpoly/{dom → classes}/extract_plan.coffee +1 -1
- data/lib/assets/javascripts/unpoly/classes/field_observer.coffee +57 -0
- data/lib/assets/javascripts/unpoly/classes/follow_variant.coffee +52 -0
- data/lib/assets/javascripts/unpoly/classes/motion_tracker.coffee +95 -0
- data/lib/assets/javascripts/unpoly/classes/record.coffee +16 -0
- data/lib/assets/javascripts/unpoly/classes/request.coffee +228 -0
- data/lib/assets/javascripts/unpoly/classes/response.coffee +138 -0
- data/lib/assets/javascripts/unpoly/dom.coffee +151 -142
- data/lib/assets/javascripts/unpoly/feedback.coffee +67 -38
- data/lib/assets/javascripts/unpoly/form.coffee +156 -139
- data/lib/assets/javascripts/unpoly/history.coffee +22 -19
- data/lib/assets/javascripts/unpoly/layout.coffee +108 -90
- data/lib/assets/javascripts/unpoly/link.coffee +159 -158
- data/lib/assets/javascripts/unpoly/log.coffee +5 -5
- data/lib/assets/javascripts/unpoly/modal.coffee +93 -81
- data/lib/assets/javascripts/unpoly/motion.coffee +291 -250
- data/lib/assets/javascripts/unpoly/popup.coffee +67 -53
- data/lib/assets/javascripts/unpoly/protocol.coffee +67 -16
- data/lib/assets/javascripts/unpoly/proxy.coffee +282 -211
- data/lib/assets/javascripts/unpoly/rails.coffee +3 -14
- data/lib/assets/javascripts/unpoly/syntax.coffee +54 -49
- data/lib/assets/javascripts/unpoly/tooltip.coffee +18 -25
- data/lib/assets/javascripts/unpoly/util.coffee +236 -477
- data/lib/assets/javascripts/unpoly.coffee +1 -1
- data/lib/unpoly/rails/inspector.rb +67 -22
- data/lib/unpoly/rails/version.rb +1 -1
- data/package.json +1 -1
- data/spec_app/Gemfile.lock +13 -13
- data/spec_app/app/assets/javascripts/integration_test.coffee +1 -0
- data/spec_app/app/assets/javascripts/jasmine_specs.coffee +1 -1
- data/spec_app/app/assets/stylesheets/jasmine_specs.sass +10 -0
- data/spec_app/app/controllers/binding_test_controller.rb +19 -2
- data/spec_app/app/controllers/method_test_controller.rb +16 -0
- data/spec_app/app/views/layouts/jasmine_rails/spec_runner.html.erb +20 -0
- data/spec_app/app/views/method_test/form_target.erb +17 -0
- data/spec_app/app/views/method_test/page1.erb +11 -0
- data/spec_app/app/views/method_test/page2.erb +6 -0
- data/spec_app/app/views/pages/start.erb +33 -19
- data/spec_app/config/initializers/assets.rb +5 -0
- data/spec_app/config/routes.rb +3 -0
- data/spec_app/spec/controllers/binding_test_controller_spec.rb +82 -27
- data/spec_app/spec/javascripts/helpers/agent_detector.coffee +17 -0
- data/spec_app/spec/javascripts/helpers/async_sequence.js.coffee +102 -0
- data/spec_app/spec/javascripts/helpers/last_request.js.coffee +1 -1
- data/spec_app/spec/javascripts/helpers/mock_ajax.js.coffee +5 -2
- data/spec_app/spec/javascripts/helpers/promise_state.js +18 -0
- data/spec_app/spec/javascripts/helpers/protect_jasmine_runner.coffee +9 -0
- data/spec_app/spec/javascripts/helpers/reset_history.js.coffee +22 -0
- data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +11 -3
- data/spec_app/spec/javascripts/helpers/show_lib_versions.coffee +10 -0
- data/spec_app/spec/javascripts/helpers/to_be_error.coffee +5 -0
- data/spec_app/spec/javascripts/helpers/to_match_url.coffee +13 -0
- data/spec_app/spec/javascripts/helpers/trigger.js.coffee +13 -6
- data/spec_app/spec/javascripts/up/browser_spec.js.coffee +92 -33
- data/spec_app/spec/javascripts/up/bus_spec.js.coffee +64 -15
- data/spec_app/spec/javascripts/up/classes/.keep +0 -0
- data/spec_app/spec/javascripts/up/classes/cache_spec.js.coffee +1 -0
- data/spec_app/spec/javascripts/up/dom_spec.js.coffee +759 -551
- data/spec_app/spec/javascripts/up/feedback_spec.js.coffee +155 -82
- data/spec_app/spec/javascripts/up/form_spec.js.coffee +490 -349
- data/spec_app/spec/javascripts/up/history_spec.js.coffee +226 -179
- data/spec_app/spec/javascripts/up/layout_spec.js.coffee +253 -185
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +416 -270
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +459 -330
- data/spec_app/spec/javascripts/up/motion_spec.js.coffee +198 -153
- data/spec_app/spec/javascripts/up/namespace_spec.js.coffee +9 -0
- data/spec_app/spec/javascripts/up/popup_spec.js.coffee +240 -175
- data/spec_app/spec/javascripts/up/protocol_spec.js.coffee +38 -0
- data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +777 -303
- data/spec_app/spec/javascripts/up/rails_spec.js.coffee +24 -8
- data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +40 -23
- data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +80 -66
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +227 -201
- data/spec_app/vendor/asset-libs/es6-promise-4.1.6/es6-promise.auto.js +1159 -0
- metadata +30 -7
- data/spec_app/spec/javascripts/helpers/reset_path.js.coffee +0 -7
- data/spec_app/spec/javascripts/helpers/to_equal_url.coffee +0 -11
@@ -1,14 +1,11 @@
|
|
1
1
|
###*
|
2
|
-
|
3
|
-
|
2
|
+
History
|
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.
|
8
8
|
|
9
|
-
|
10
|
-
Going back behavior .... configure.
|
11
|
-
|
12
9
|
@class up.history
|
13
10
|
###
|
14
11
|
up.history = (($) ->
|
@@ -22,12 +19,13 @@ up.history = (($) ->
|
|
22
19
|
@param {Array} [config.popTargets=['body']]
|
23
20
|
An array of CSS selectors to replace when the user goes
|
24
21
|
back in history.
|
25
|
-
@param {
|
22
|
+
@param {boolean} [config.restoreScroll=true]
|
26
23
|
Whether to restore the known scroll positions
|
27
24
|
when the user goes back or forward in history.
|
28
25
|
@stable
|
29
26
|
###
|
30
27
|
config = u.config
|
28
|
+
enabled: true
|
31
29
|
popTargets: ['body']
|
32
30
|
restoreScroll: true
|
33
31
|
|
@@ -92,8 +90,8 @@ up.history = (($) ->
|
|
92
90
|
browser's location bar for you.
|
93
91
|
|
94
92
|
@function up.history.replace
|
95
|
-
@param {
|
96
|
-
@
|
93
|
+
@param {string} url
|
94
|
+
@internal
|
97
95
|
###
|
98
96
|
replace = (url) ->
|
99
97
|
manipulate('replaceState', url)
|
@@ -113,7 +111,7 @@ up.history = (($) ->
|
|
113
111
|
Emits events [`up:history:push`](/up:history:push) and [`up:history:pushed`](/up:history:pushed).
|
114
112
|
|
115
113
|
@function up.history.push
|
116
|
-
@param {
|
114
|
+
@param {string} url
|
117
115
|
The URL for the history entry to be added.
|
118
116
|
@experimental
|
119
117
|
###
|
@@ -121,14 +119,16 @@ up.history = (($) ->
|
|
121
119
|
options = u.options(options, force: false)
|
122
120
|
url = normalizeUrl(url)
|
123
121
|
if (options.force || !isCurrentUrl(url)) && up.bus.nobodyPrevents('up:history:push', url: url, message: "Adding history entry for #{url}")
|
124
|
-
manipulate('pushState', url)
|
125
|
-
|
122
|
+
if manipulate('pushState', url)
|
123
|
+
up.emit('up:history:pushed', url: url, message: "Advanced to location #{url}")
|
124
|
+
else
|
125
|
+
up.emit('up:history:muted', url: url, message: "Did not advance to #{url} (history is unavailable)")
|
126
126
|
|
127
127
|
###*
|
128
128
|
This event is [emitted](/up.emit) before a new history entry is added.
|
129
129
|
|
130
130
|
@event up:history:push
|
131
|
-
@param {
|
131
|
+
@param {string} event.url
|
132
132
|
The URL for the history entry that is going to be added.
|
133
133
|
@param event.preventDefault()
|
134
134
|
Event listeners may call this method to prevent the history entry from being added.
|
@@ -139,18 +139,19 @@ up.history = (($) ->
|
|
139
139
|
This event is [emitted](/up.emit) after a new history entry has been added.
|
140
140
|
|
141
141
|
@event up:history:pushed
|
142
|
-
@param {
|
142
|
+
@param {string} event.url
|
143
143
|
The URL for the history entry that has been added.
|
144
144
|
@experimental
|
145
145
|
###
|
146
146
|
|
147
147
|
manipulate = (method, url) ->
|
148
|
-
if up.browser.canPushState()
|
148
|
+
if up.browser.canPushState() && config.enabled
|
149
149
|
state = buildState()
|
150
150
|
window.history[method](state, '', url)
|
151
151
|
observeNewUrl(currentUrl())
|
152
|
+
true
|
152
153
|
else
|
153
|
-
|
154
|
+
false
|
154
155
|
|
155
156
|
buildState = ->
|
156
157
|
fromUp: true
|
@@ -189,7 +190,7 @@ up.history = (($) ->
|
|
189
190
|
History entries are restored when the user uses the *Back* or *Forward* button.
|
190
191
|
|
191
192
|
@event up:history:restore
|
192
|
-
@param {
|
193
|
+
@param {string} event.url
|
193
194
|
The URL for the history entry that has been restored.
|
194
195
|
@internal
|
195
196
|
###
|
@@ -200,7 +201,7 @@ up.history = (($) ->
|
|
200
201
|
History entries are restored when the user uses the *Back* or *Forward* button.
|
201
202
|
|
202
203
|
@event up:history:restored
|
203
|
-
@param {
|
204
|
+
@param {string} event.url
|
204
205
|
The URL for the history entry that has been restored.
|
205
206
|
@experimental
|
206
207
|
###
|
@@ -225,6 +226,8 @@ up.history = (($) ->
|
|
225
226
|
Note that this will *not* call `location.back()`, but will set
|
226
227
|
the link's `up-href` attribute to the actual, previous URL.
|
227
228
|
|
229
|
+
If no previous URL is known, the link will not be changed.
|
230
|
+
|
228
231
|
\#\#\# Example
|
229
232
|
|
230
233
|
This link ...
|
@@ -239,10 +242,10 @@ up.history = (($) ->
|
|
239
242
|
Go back
|
240
243
|
</a>
|
241
244
|
|
242
|
-
@selector [up-back]
|
245
|
+
@selector a[up-back]
|
243
246
|
@stable
|
244
247
|
###
|
245
|
-
up.
|
248
|
+
up.macro 'a[up-back], [up-href][up-back]', ($link) ->
|
246
249
|
if u.isPresent(previousUrl)
|
247
250
|
u.setMissingAttrs $link,
|
248
251
|
'up-href': previousUrl,
|
@@ -4,7 +4,7 @@ Application layout
|
|
4
4
|
|
5
5
|
You can [make Unpoly aware](/up.layout.config) of fixed elements in your
|
6
6
|
layout, such as navigation bars or headers. Unpoly will respect these sticky
|
7
|
-
elements when [revealing elements](/up.reveal) or [opening a modal dialog](/up-modal).
|
7
|
+
elements when [revealing elements](/up.reveal) or [opening a modal dialog](/a-up-modal).
|
8
8
|
|
9
9
|
This modules also contains functions to programmatically [scroll a viewport](/up.scroll)
|
10
10
|
or [reveal an element within its viewport](/up.reveal).
|
@@ -41,17 +41,17 @@ up.layout = (($) ->
|
|
41
41
|
An array of CSS selectors that find elements anchored to the
|
42
42
|
right edge of the screen (using `right:0` with `position: fixed` or `position: absolute`).
|
43
43
|
See [`[up-anchored="right"]`](/up-anchored-right) for details.
|
44
|
-
@param {
|
44
|
+
@param {number} [config.duration=0]
|
45
45
|
The duration of the scrolling animation in milliseconds.
|
46
46
|
Setting this to `0` will disable scrolling animations.
|
47
|
-
@param {
|
47
|
+
@param {string} [config.easing='swing']
|
48
48
|
The timing function that controls the animation's acceleration.
|
49
49
|
See [W3C documentation](http://www.w3.org/TR/css3-transitions/#transition-timing-function)
|
50
50
|
for a list of pre-defined timing functions.
|
51
|
-
@param {
|
51
|
+
@param {number} [config.snap=50]
|
52
52
|
When [revealing](/up.reveal) elements, Unpoly will scroll an viewport
|
53
53
|
to the top when the revealed element is closer to the top than `config.snap`.
|
54
|
-
@param {
|
54
|
+
@param {number} [config.substance=150]
|
55
55
|
A number indicating how many top pixel rows of an element to [reveal](/up.reveal).
|
56
56
|
@stable
|
57
57
|
###
|
@@ -65,15 +65,16 @@ up.layout = (($) ->
|
|
65
65
|
substance: 150
|
66
66
|
easing: 'swing'
|
67
67
|
|
68
|
-
lastScrollTops =
|
68
|
+
lastScrollTops = new up.Cache
|
69
69
|
size: 30,
|
70
70
|
key: up.history.normalizeUrl
|
71
71
|
|
72
|
+
scrollingTracker = new up.MotionTracker('scrolling')
|
73
|
+
|
72
74
|
reset = ->
|
73
75
|
config.reset()
|
74
76
|
lastScrollTops.clear()
|
75
|
-
|
76
|
-
SCROLL_PROMISE_KEY = 'up-scroll-promise'
|
77
|
+
scrollingTracker.finish()
|
77
78
|
|
78
79
|
###*
|
79
80
|
Scrolls the given viewport to the given Y-position.
|
@@ -101,63 +102,67 @@ up.layout = (($) ->
|
|
101
102
|
last frame before the next animation is started.
|
102
103
|
|
103
104
|
@function up.scroll
|
104
|
-
@param {
|
105
|
+
@param {string|Element|jQuery} viewport
|
105
106
|
The container element to scroll.
|
106
|
-
@param {
|
107
|
+
@param {number} scrollPos
|
107
108
|
The absolute number of pixels to set the scroll position to.
|
108
|
-
@param {
|
109
|
+
@param {number}[options.duration]
|
109
110
|
The number of miliseconds for the scrolling's animation.
|
110
|
-
@param {
|
111
|
+
@param {string}[options.easing]
|
111
112
|
The timing function that controls the acceleration for the scrolling's animation.
|
112
|
-
@return {
|
113
|
-
A promise that will be
|
113
|
+
@return {Promise}
|
114
|
+
A promise that will be fulfilled when the scrolling ends.
|
114
115
|
@experimental
|
115
116
|
###
|
116
117
|
scroll = (viewport, scrollTop, options) ->
|
117
|
-
$
|
118
|
+
$scrollable = scrollableElementForViewport(viewport)
|
118
119
|
options = u.options(options)
|
119
|
-
duration = u.option(options.duration, config.duration)
|
120
|
-
easing = u.option(options.easing, config.easing)
|
120
|
+
options.duration = u.option(options.duration, config.duration)
|
121
|
+
options.easing = u.option(options.easing, config.easing)
|
121
122
|
|
122
|
-
finishScrolling($
|
123
|
-
|
124
|
-
|
125
|
-
|
123
|
+
finishScrolling($scrollable).then ->
|
124
|
+
if up.motion.isEnabled() && options.duration > 0
|
125
|
+
scrollWithAnimateNow($scrollable, scrollTop, options)
|
126
|
+
else
|
127
|
+
scrollAbruptlyNow($scrollable, scrollTop)
|
126
128
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
$viewport.finish()
|
129
|
+
scrollableElementForViewport = (viewport) ->
|
130
|
+
$viewport = $(viewport)
|
131
|
+
if $viewport.get(0) == document
|
132
|
+
$('html, body') # FML
|
133
|
+
else
|
134
|
+
$viewport
|
134
135
|
|
135
|
-
|
136
|
-
|
136
|
+
scrollWithAnimateNow = ($scrollable, scrollTop, animateOptions) ->
|
137
|
+
start = ->
|
138
|
+
finish = ->
|
139
|
+
# jQuery exposes a finish() method that completes all animations orchestrated through jQuery.
|
140
|
+
# This will also resolve the promise returned by $element.animate(..).promise().
|
141
|
+
$scrollable.finish()
|
137
142
|
|
138
|
-
|
139
|
-
|
143
|
+
$scrollable.on(scrollingTracker.eventName, finish)
|
144
|
+
scrollDone = $scrollable.animate({ scrollTop }, animateOptions).promise()
|
145
|
+
scrollDone.then -> $scrollable.off(scrollingTracker.eventName)
|
146
|
+
scrollDone
|
140
147
|
|
141
|
-
|
142
|
-
|
143
|
-
easing: easing,
|
144
|
-
complete: -> deferred.resolve()
|
148
|
+
# Tracker will either finish or wait for previous scrolling animations before starting the next
|
149
|
+
scrollingTracker.claim($scrollable, start)
|
145
150
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
u.resolvedDeferred()
|
151
|
+
scrollAbruptlyNow = ($scrollable, scrollTop) ->
|
152
|
+
$scrollable.scrollTop(scrollTop)
|
153
|
+
Promise.resolve()
|
150
154
|
|
151
155
|
###*
|
156
|
+
Finishes scrolling animations in the given element, its ancestors or its descendants.
|
157
|
+
|
152
158
|
@function up.layout.finishScrolling
|
153
|
-
@param {
|
154
|
-
|
159
|
+
@param {string|Element|jQuery}
|
160
|
+
@return {Promise}
|
155
161
|
@internal
|
156
162
|
###
|
157
|
-
finishScrolling = (
|
158
|
-
$(
|
159
|
-
|
160
|
-
existingScrolling.resolve()
|
163
|
+
finishScrolling = (element) ->
|
164
|
+
$scrollable = scrollableElementForViewport(element)
|
165
|
+
scrollingTracker.finish($scrollable)
|
161
166
|
|
162
167
|
###*
|
163
168
|
@function up.layout.anchoredRight
|
@@ -166,8 +171,12 @@ up.layout = (($) ->
|
|
166
171
|
anchoredRight = ->
|
167
172
|
u.multiSelector(config.anchoredRight).select()
|
168
173
|
|
174
|
+
###*
|
175
|
+
@function measureObstruction
|
176
|
+
@return {Object}
|
177
|
+
@internal
|
178
|
+
###
|
169
179
|
measureObstruction = ->
|
170
|
-
|
171
180
|
measurePosition = (obstructor, cssAttr) ->
|
172
181
|
$obstructor = $(obstructor)
|
173
182
|
anchorPosition = $obstructor.css(cssAttr)
|
@@ -215,16 +224,16 @@ up.layout = (($) ->
|
|
215
224
|
- [configure default options](/up.layout.config) for `fixedTop` or `fixedBottom`
|
216
225
|
|
217
226
|
@function up.reveal
|
218
|
-
@param {
|
219
|
-
@param {
|
220
|
-
@param {
|
221
|
-
@param {
|
222
|
-
@param {
|
223
|
-
@param {
|
227
|
+
@param {string|Element|jQuery} element
|
228
|
+
@param {number} [options.duration]
|
229
|
+
@param {string} [options.easing]
|
230
|
+
@param {string} [options.snap]
|
231
|
+
@param {string|Element|jQuery} [options.viewport]
|
232
|
+
@param {boolean} [options.top=false]
|
224
233
|
Whether to scroll the viewport so that the first element row aligns
|
225
234
|
with the top edge of the viewport.
|
226
|
-
@return {
|
227
|
-
A promise that
|
235
|
+
@return {Promise}
|
236
|
+
A promise that fulfills when the element is revealed.
|
228
237
|
@stable
|
229
238
|
###
|
230
239
|
reveal = (elementOrSelector, options) ->
|
@@ -279,7 +288,7 @@ up.layout = (($) ->
|
|
279
288
|
if newScrollPos != originalScrollPos
|
280
289
|
scroll($viewport, newScrollPos, options)
|
281
290
|
else
|
282
|
-
|
291
|
+
Promise.resolve()
|
283
292
|
|
284
293
|
###*
|
285
294
|
[Reveals](/up.reveal) an element matching the `#hash` in the current URL.
|
@@ -291,16 +300,15 @@ up.layout = (($) ->
|
|
291
300
|
This is called automatically when the page loads initially.
|
292
301
|
|
293
302
|
@function up.layout.revealHash
|
303
|
+
@return {Promise}
|
304
|
+
A promise that is fulfilled when scroll position has changed to match the location hash.
|
294
305
|
@experimental
|
295
306
|
###
|
296
307
|
revealHash = ->
|
297
|
-
if hash = up.browser.hash()
|
298
|
-
|
299
|
-
reveal($match)
|
300
|
-
else
|
301
|
-
u.rejectedPromise()
|
308
|
+
if (hash = up.browser.hash()) && ($match = firstHashTarget(hash))
|
309
|
+
reveal($match)
|
302
310
|
else
|
303
|
-
|
311
|
+
Promise.resolve()
|
304
312
|
|
305
313
|
viewportSelector = ->
|
306
314
|
u.multiSelector(config.viewports)
|
@@ -311,7 +319,7 @@ up.layout = (($) ->
|
|
311
319
|
Throws an error if no viewport could be found.
|
312
320
|
|
313
321
|
@function up.layout.viewportOf
|
314
|
-
@param {
|
322
|
+
@param {string|Element|jQuery} selectorOrElement
|
315
323
|
@internal
|
316
324
|
###
|
317
325
|
viewportOf = (selectorOrElement, options = {}) ->
|
@@ -326,13 +334,13 @@ up.layout = (($) ->
|
|
326
334
|
given selector or element.
|
327
335
|
|
328
336
|
@function up.layout.viewportsWithin
|
329
|
-
@param {
|
337
|
+
@param {string|Element|jQuery} selectorOrElement
|
330
338
|
@return jQuery
|
331
339
|
@internal
|
332
340
|
###
|
333
341
|
viewportsWithin = (selectorOrElement) ->
|
334
342
|
$element = $(selectorOrElement)
|
335
|
-
viewportSelector().
|
343
|
+
viewportSelector().selectInSubtree($element)
|
336
344
|
|
337
345
|
###*
|
338
346
|
Returns a jQuery collection of all the viewports on the screen.
|
@@ -360,7 +368,7 @@ up.layout = (($) ->
|
|
360
368
|
=> { '.main': 0, '.sidebar': 73 }
|
361
369
|
|
362
370
|
@function up.layout.scrollTops
|
363
|
-
@return Object<
|
371
|
+
@return Object<string, number>
|
364
372
|
@internal
|
365
373
|
###
|
366
374
|
scrollTops = ->
|
@@ -396,14 +404,13 @@ up.layout = (($) ->
|
|
396
404
|
Unpoly automatically saves scroll positions whenever a fragment was updated on the page.
|
397
405
|
|
398
406
|
@function up.layout.saveScroll
|
399
|
-
@param {
|
400
|
-
@param {Object<
|
407
|
+
@param {string} [options.url]
|
408
|
+
@param {Object<string, number>} [options.tops]
|
401
409
|
@experimental
|
402
410
|
###
|
403
411
|
saveScroll = (options = {}) ->
|
404
412
|
url = u.option(options.url, up.history.url())
|
405
413
|
tops = u.option(options.tops, scrollTops())
|
406
|
-
up.puts('Saving scroll positions for URL %s (%o)', url, tops)
|
407
414
|
lastScrollTops.set(url, tops)
|
408
415
|
|
409
416
|
###*
|
@@ -417,10 +424,11 @@ up.layout = (($) ->
|
|
417
424
|
@param {jQuery} [options.around]
|
418
425
|
If set, only restores viewports that are either an ancestor
|
419
426
|
or descendant of the given element.
|
427
|
+
@return {Promise}
|
428
|
+
A promise that will be fulfilled once scroll positions have been restored.
|
420
429
|
@experimental
|
421
430
|
###
|
422
431
|
restoreScroll = (options = {}) ->
|
423
|
-
|
424
432
|
url = up.history.url()
|
425
433
|
|
426
434
|
$viewports = undefined
|
@@ -435,37 +443,48 @@ up.layout = (($) ->
|
|
435
443
|
scrollTopsForUrl = lastScrollTops.get(url) || {}
|
436
444
|
|
437
445
|
up.log.group 'Restoring scroll positions for URL %s to %o', url, scrollTopsForUrl, ->
|
438
|
-
$viewports
|
439
|
-
|
440
|
-
key = scrollTopKey($viewport)
|
446
|
+
allScrollPromises = u.map $viewports, (viewport) ->
|
447
|
+
key = scrollTopKey(viewport)
|
441
448
|
scrollTop = scrollTopsForUrl[key] || 0
|
442
|
-
scroll(
|
449
|
+
scroll(viewport, scrollTop, duration: 0)
|
443
450
|
|
444
|
-
|
445
|
-
# join promises from the up.scroll call above
|
446
|
-
u.resolvedDeferred()
|
451
|
+
Promise.all(allScrollPromises)
|
447
452
|
|
448
453
|
###*
|
449
454
|
@function up.layout.revealOrRestoreScroll
|
450
|
-
@
|
451
|
-
|
455
|
+
@param {boolean} [options.restoreScroll]
|
456
|
+
@param {boolean|string} [options.reveal]
|
457
|
+
@return {Promise}
|
458
|
+
A promise that is fulfilled when the element is revealed or
|
459
|
+
the scroll position is restored.
|
452
460
|
@internal
|
453
461
|
###
|
454
462
|
revealOrRestoreScroll = (selectorOrElement, options) ->
|
455
463
|
$element = $(selectorOrElement)
|
464
|
+
|
456
465
|
if options.restoreScroll
|
457
|
-
restoreScroll(around: $element)
|
458
|
-
|
466
|
+
return restoreScroll(around: $element)
|
467
|
+
|
468
|
+
if options.reveal
|
459
469
|
revealOptions = {}
|
460
|
-
if options.
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
470
|
+
if u.isString(options.reveal)
|
471
|
+
selector = revealSelector(options.reveal)
|
472
|
+
$element = up.first(selector) || $element
|
473
|
+
revealOptions.top = true
|
474
|
+
return reveal($element, revealOptions)
|
475
|
+
|
476
|
+
# If we didn't need to scroll above, just return a resolved promise
|
477
|
+
# to fulfill this function's signature.
|
478
|
+
return Promise.resolve()
|
468
479
|
|
480
|
+
###*
|
481
|
+
@internal
|
482
|
+
###
|
483
|
+
revealSelector = (selector, options) ->
|
484
|
+
selector = up.dom.resolveSelector(selector, options)
|
485
|
+
if selector[0] == '#'
|
486
|
+
selector += ", a[name='#{selector}']"
|
487
|
+
selector
|
469
488
|
|
470
489
|
###*
|
471
490
|
Marks this element as a scrolling container ("viewport").
|
@@ -613,7 +632,6 @@ up.layout = (($) ->
|
|
613
632
|
revealHash: revealHash
|
614
633
|
firstHashTarget: firstHashTarget
|
615
634
|
scroll: scroll
|
616
|
-
finishScrolling: finishScrolling
|
617
635
|
config: config
|
618
636
|
viewportOf: viewportOf
|
619
637
|
viewportsWithin: viewportsWithin
|