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
@@ -27,16 +27,10 @@ class up.Request extends up.Record
|
|
27
27
|
###
|
28
28
|
|
29
29
|
###**
|
30
|
-
Parameters that should be sent as the request's payload.
|
30
|
+
[Parameters](/up.params) that should be sent as the request's payload.
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
1. An object where keys are param names and the values are param values
|
35
|
-
2. An array of `{ name: 'param-name', value: 'param-value' }` objects
|
36
|
-
3. A [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) object
|
37
|
-
|
38
|
-
@property up.Request#data
|
39
|
-
@param {String} data
|
32
|
+
@property up.Request#params
|
33
|
+
@param {object|FormData|string|Array} params
|
40
34
|
@stable
|
41
35
|
###
|
42
36
|
|
@@ -78,11 +72,14 @@ class up.Request extends up.Record
|
|
78
72
|
[
|
79
73
|
'method',
|
80
74
|
'url',
|
81
|
-
'
|
75
|
+
'params',
|
76
|
+
'data', # deprecated. use #params.
|
82
77
|
'target',
|
83
78
|
'failTarget',
|
84
79
|
'headers',
|
85
|
-
'timeout'
|
80
|
+
'timeout',
|
81
|
+
'preload' # since up.proxy.request() options are sometimes wrapped in this class
|
82
|
+
'cache' # since up.proxy.request() options are sometimes wrapped in this class
|
86
83
|
]
|
87
84
|
|
88
85
|
###**
|
@@ -94,37 +91,34 @@ class up.Request extends up.Record
|
|
94
91
|
@normalize()
|
95
92
|
|
96
93
|
normalize: =>
|
94
|
+
u.deprecateRenamedKey(@, 'data', 'params')
|
97
95
|
@method = u.normalizeMethod(@method)
|
98
96
|
@headers ||= {}
|
99
97
|
@extractHashFromUrl()
|
100
98
|
|
101
99
|
if u.methodAllowsPayload(@method)
|
102
|
-
@
|
100
|
+
@transferSearchToParams()
|
103
101
|
else
|
104
|
-
@
|
102
|
+
@transferParamsToUrl()
|
105
103
|
|
106
104
|
extractHashFromUrl: =>
|
107
105
|
urlParts = u.parseUrl(@url)
|
108
106
|
# Remember the #hash for later revealing.
|
109
107
|
# It will be lost during normalization.
|
110
|
-
@hash = urlParts.hash
|
108
|
+
@hash = u.presence(urlParts.hash)
|
111
109
|
@url = u.normalizeUrl(urlParts, hash: false)
|
112
110
|
|
113
|
-
|
114
|
-
if @
|
115
|
-
# GET methods are not allowed to have a payload, so we transfer {
|
116
|
-
|
117
|
-
|
118
|
-
@
|
119
|
-
# Now that we have transfered the params into the URL, we delete them from the { data } option.
|
120
|
-
@data = undefined
|
111
|
+
transferParamsToUrl: =>
|
112
|
+
if @params && !u.isFormData(@params)
|
113
|
+
# GET methods are not allowed to have a payload, so we transfer { params } params to the URL.
|
114
|
+
@url = up.params.buildURL(@url, @params)
|
115
|
+
# Now that we have transfered the params into the URL, we delete them from the { params } option.
|
116
|
+
@params = undefined
|
121
117
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
@data = u.mergeRequestData(@data, query)
|
127
|
-
@url = u.normalizeUrl(urlParts, search: false)
|
118
|
+
transferSearchToParams: =>
|
119
|
+
if query = up.params.fromURL(@url)
|
120
|
+
@params = up.params.merge(@params, query)
|
121
|
+
@url = u.normalizeUrl(@url, search: false)
|
128
122
|
|
129
123
|
isSafe: =>
|
130
124
|
up.proxy.isSafeMethod(@method)
|
@@ -136,27 +130,25 @@ class up.Request extends up.Record
|
|
136
130
|
xhr = new XMLHttpRequest()
|
137
131
|
|
138
132
|
xhrHeaders = u.copy(@headers)
|
139
|
-
|
133
|
+
xhrPayload = @params
|
140
134
|
xhrMethod = @method
|
141
135
|
xhrUrl = @url
|
142
136
|
|
143
|
-
[xhrMethod,
|
137
|
+
[xhrMethod, xhrPayload] = up.proxy.wrapMethod(xhrMethod, xhrPayload)
|
144
138
|
|
145
|
-
if
|
139
|
+
if xhrPayload
|
146
140
|
delete xhrHeaders['Content-Type'] # let the browser set the content type
|
147
|
-
|
148
|
-
xhrData = u.requestDataAsQuery(xhrData, purpose: 'form')
|
149
|
-
xhrHeaders['Content-Type'] = 'application/x-www-form-urlencoded'
|
141
|
+
xhrPayload = up.params.toFormData(xhrPayload)
|
150
142
|
else
|
151
143
|
# XMLHttpRequest expects null for an empty body
|
152
|
-
|
144
|
+
xhrPayload = null
|
153
145
|
|
154
|
-
|
155
|
-
xhrHeaders[
|
146
|
+
pc = up.protocol.config
|
147
|
+
xhrHeaders[pc.targetHeader] = @target if @target
|
148
|
+
xhrHeaders[pc.failTargetHeader] = @failTarget if @failTarget
|
156
149
|
xhrHeaders['X-Requested-With'] ||= 'XMLHttpRequest' unless @isCrossDomain()
|
157
|
-
|
158
150
|
if csrfToken = @csrfToken()
|
159
|
-
xhrHeaders[
|
151
|
+
xhrHeaders[pc.csrfHeader] = csrfToken
|
160
152
|
|
161
153
|
xhr.open(xhrMethod, xhrUrl)
|
162
154
|
|
@@ -177,12 +169,12 @@ class up.Request extends up.Record
|
|
177
169
|
|
178
170
|
xhr.timeout = @timeout if @timeout
|
179
171
|
|
180
|
-
xhr.send(
|
172
|
+
xhr.send(xhrPayload)
|
181
173
|
|
182
174
|
navigate: =>
|
183
175
|
# GET forms cannot have an URL with a query section in their [action] attribute.
|
184
176
|
# The query section would be overridden by the serialized input values on submission.
|
185
|
-
@
|
177
|
+
@transferSearchToParams()
|
186
178
|
|
187
179
|
$form = $('<form class="up-page-loader"></form>')
|
188
180
|
|
@@ -202,9 +194,9 @@ class up.Request extends up.Record
|
|
202
194
|
if (csrfParam = up.protocol.csrfParam()) && (csrfToken = @csrfToken())
|
203
195
|
addField(name: csrfParam, value: csrfToken)
|
204
196
|
|
205
|
-
# @
|
197
|
+
# @params will be undefined for GET requests, since we have already
|
206
198
|
# transfered all params to the URL during normalize().
|
207
|
-
u.each
|
199
|
+
u.each(up.params.toArray(@params), addField)
|
208
200
|
|
209
201
|
$form.hide().appendTo('body')
|
210
202
|
up.browser.submitForm($form)
|
@@ -236,10 +228,11 @@ class up.Request extends up.Record
|
|
236
228
|
new up.Response(responseAttrs)
|
237
229
|
|
238
230
|
isCachable: =>
|
239
|
-
@isSafe() && !u.isFormData(@
|
231
|
+
@isSafe() && !u.isFormData(@params)
|
240
232
|
|
241
233
|
cacheKey: =>
|
242
|
-
|
234
|
+
query = up.params.toQuery(@params)
|
235
|
+
[@url, @method, query, @target].join('|')
|
243
236
|
|
244
237
|
@wrap: (object) ->
|
245
238
|
if object instanceof @
|
@@ -94,7 +94,7 @@ class up.Response extends up.Record
|
|
94
94
|
'status',
|
95
95
|
'request',
|
96
96
|
'xhr',
|
97
|
-
'title'
|
97
|
+
'title',
|
98
98
|
]
|
99
99
|
|
100
100
|
constructor: (options) ->
|
@@ -136,3 +136,18 @@ class up.Response extends up.Record
|
|
136
136
|
###
|
137
137
|
isFatalError: =>
|
138
138
|
@isError() && u.isBlank(@text)
|
139
|
+
|
140
|
+
###**
|
141
|
+
Returns the HTTP header value with the given name.
|
142
|
+
|
143
|
+
The search for the header name is case-insensitive.
|
144
|
+
|
145
|
+
Returns `undefined` if the given header name was not included in the response.
|
146
|
+
|
147
|
+
@function up.Response#getHeader
|
148
|
+
@param {string} name
|
149
|
+
@return {string|undefined} value
|
150
|
+
@experimental
|
151
|
+
###
|
152
|
+
getHeader: (name) =>
|
153
|
+
@xhr.getResponseHeader(name)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
up.store ||= {}
|
2
|
+
|
3
|
+
u = up.util
|
4
|
+
|
5
|
+
class up.store.Memory
|
6
|
+
|
7
|
+
constructor: ->
|
8
|
+
@clear()
|
9
|
+
|
10
|
+
clear: =>
|
11
|
+
@data = {}
|
12
|
+
|
13
|
+
get: (key) =>
|
14
|
+
@data[key]
|
15
|
+
|
16
|
+
set: (key, value) =>
|
17
|
+
@data[key] = value
|
18
|
+
|
19
|
+
remove: (key) =>
|
20
|
+
delete @data[key]
|
21
|
+
|
22
|
+
keys: =>
|
23
|
+
Object.keys(@data)
|
24
|
+
|
25
|
+
values: =>
|
26
|
+
u.values(@data)
|
@@ -0,0 +1,59 @@
|
|
1
|
+
u = up.util
|
2
|
+
|
3
|
+
##
|
4
|
+
# Store implementation backed by window.sessionStorage
|
5
|
+
# ====================================================
|
6
|
+
#
|
7
|
+
# This improves plain sessionStorage access in several ways:
|
8
|
+
#
|
9
|
+
# - Falls back to in-memory storage if window.sessionStorage is not available (see below).
|
10
|
+
# - Allows to store other types of values than just strings.
|
11
|
+
# - Allows to store structured values.
|
12
|
+
# - Allows to invalidate existing data by incrementing a version number on the server.
|
13
|
+
#
|
14
|
+
# On sessionStorage availability
|
15
|
+
# ------------------------------
|
16
|
+
#
|
17
|
+
# All supported browsers have sessionStorage, but the property is `null`
|
18
|
+
# in private browsing mode in Safari and the default Android webkit browser.
|
19
|
+
# See https://makandracards.com/makandra/32865-sessionstorage-per-window-browser-storage
|
20
|
+
#
|
21
|
+
# Also Chrome explodes upon access of window.sessionStorage when
|
22
|
+
# user blocks third-party cookies and site data and this page is embedded
|
23
|
+
# as an <iframe>. See https://bugs.chromium.org/p/chromium/issues/detail?id=357625
|
24
|
+
#
|
25
|
+
class up.store.Session extends up.store.Memory
|
26
|
+
|
27
|
+
constructor: (rootKey) ->
|
28
|
+
@rootKey = rootKey
|
29
|
+
@loadFromSessionStorage()
|
30
|
+
|
31
|
+
clear: =>
|
32
|
+
super()
|
33
|
+
@saveToSessionStorage()
|
34
|
+
|
35
|
+
set: (key, value) =>
|
36
|
+
super(key, value)
|
37
|
+
@saveToSessionStorage()
|
38
|
+
|
39
|
+
remove: (key) =>
|
40
|
+
super(key)
|
41
|
+
@saveToSessionStorage()
|
42
|
+
|
43
|
+
loadFromSessionStorage: =>
|
44
|
+
try
|
45
|
+
if raw = sessionStorage?.getItem(@rootKey)
|
46
|
+
@data = JSON.parse(raw)
|
47
|
+
catch
|
48
|
+
# window.sessionStorage not supported (see class comment)
|
49
|
+
# or JSON syntax error. We start with a blank object instead.
|
50
|
+
|
51
|
+
@data ||= {}
|
52
|
+
|
53
|
+
saveToSessionStorage: =>
|
54
|
+
json = JSON.stringify(@data)
|
55
|
+
try
|
56
|
+
sessionStorage?.setItem(@rootKey, json)
|
57
|
+
catch
|
58
|
+
# window.sessionStorage not supported (see class comment).
|
59
|
+
# We do nothing and only keep data in-memory.
|
@@ -0,0 +1,56 @@
|
|
1
|
+
####**
|
2
|
+
#Cookies
|
3
|
+
#=======
|
4
|
+
#
|
5
|
+
#class up.cookies
|
6
|
+
####
|
7
|
+
#up.cookie = (->
|
8
|
+
# u = up.util
|
9
|
+
#
|
10
|
+
# escape = encodeURIComponent
|
11
|
+
# unescape = decodeURIComponent
|
12
|
+
#
|
13
|
+
# lastRaw = undefined
|
14
|
+
# lastParsed = {}
|
15
|
+
#
|
16
|
+
# all = ->
|
17
|
+
# currentRaw = document.cookie
|
18
|
+
# if u.isUndefined(lastRaw) || lastRaw != currentRaw
|
19
|
+
# lastParsed = parse()
|
20
|
+
# lastRaw = currentRaw
|
21
|
+
# lastParsed
|
22
|
+
#
|
23
|
+
# parse = ->
|
24
|
+
# hash = {}
|
25
|
+
# pairs = u.splitValues(document.cookie, ';')
|
26
|
+
# for pair in pairs
|
27
|
+
# parts = u.splitValues(pair, '=')
|
28
|
+
# name = unescape(parts[0])
|
29
|
+
# value = unescape(parts[1])
|
30
|
+
# hash[name] = value
|
31
|
+
# hash
|
32
|
+
#
|
33
|
+
# remove = (name) ->
|
34
|
+
# set(name, '', 'expires=Thu, 01-Jan-70 00:00:01 GMT; path=/')
|
35
|
+
#
|
36
|
+
# get = (name) ->
|
37
|
+
# all()[name]
|
38
|
+
#
|
39
|
+
# set = (name, value, meta) ->
|
40
|
+
# str = escape(name) + '=' + escape(value)
|
41
|
+
# str += ';' + meta if meta
|
42
|
+
# document.cookie = str
|
43
|
+
# lastRaw = undefined
|
44
|
+
#
|
45
|
+
# pop = (name) ->
|
46
|
+
# value = get(name)
|
47
|
+
# if u.isPresent(value)
|
48
|
+
# remove(name)
|
49
|
+
# value
|
50
|
+
#
|
51
|
+
# all: all
|
52
|
+
# get: get
|
53
|
+
# set: set
|
54
|
+
# remove: remove
|
55
|
+
# pop: pop
|
56
|
+
#)()
|
@@ -70,6 +70,7 @@ up.dom = (($) ->
|
|
70
70
|
@param {string|Element|jQuery} origin
|
71
71
|
The element that this selector resolution is relative to.
|
72
72
|
That element's selector will be substituted for `&` ([like in Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector)).
|
73
|
+
@return {string}
|
73
74
|
@internal
|
74
75
|
###
|
75
76
|
resolveSelector = (selectorOrElement, origin) ->
|
@@ -179,13 +180,8 @@ up.dom = (($) ->
|
|
179
180
|
You can also pass `false` to explicitly prevent the title from being updated.
|
180
181
|
@param {string} [options.method='get']
|
181
182
|
The HTTP method to use for the request.
|
182
|
-
@param {Object|Array
|
183
|
-
Parameters that should be sent as the request's payload.
|
184
|
-
|
185
|
-
Parameters can either be passed as an object (where the property names become
|
186
|
-
the param names and the property values become the param values) or as
|
187
|
-
an array of `{ name: 'param-name', value: 'param-value' }` objects
|
188
|
-
|
183
|
+
@param {Object|FormData|string|Array} [options.params]
|
184
|
+
[Parameters](/up.params) that should be sent as the request's payload.
|
189
185
|
@param {string} [options.transition='none']
|
190
186
|
@param {string|boolean} [options.history=true]
|
191
187
|
If a string is given, it is used as the URL the browser's location bar and history.
|
@@ -211,18 +207,15 @@ up.dom = (($) ->
|
|
211
207
|
@param {Object} [options.headers={}]
|
212
208
|
An object of additional header key/value pairs to send along
|
213
209
|
with the request.
|
214
|
-
@param {boolean} [options.requireMatch=true]
|
215
|
-
Whether to raise an error if the given selector is missing in
|
216
|
-
either the current page or in the response.
|
217
210
|
@param {Element|jQuery} [options.origin]
|
218
211
|
The element that triggered the replacement.
|
219
212
|
|
220
213
|
The element's selector will be substituted for the `&` shorthand in the target selector ([like in Sass](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector)).
|
221
214
|
@param {string} [options.layer='auto']
|
222
215
|
The name of the layer that ought to be updated. Valid values are
|
223
|
-
`auto`, `page`, `modal` and `popup`.
|
216
|
+
`'auto'`, `'page'`, `'modal'` and `'popup'`.
|
224
217
|
|
225
|
-
If set to `auto` (default), Unpoly will try to find a match in the
|
218
|
+
If set to `'auto'` (default), Unpoly will try to find a match in the
|
226
219
|
same layer as the element that triggered the replacement (see `options.origin`).
|
227
220
|
If that element is not known, or no match was found in that layer,
|
228
221
|
Unpoly will search in other layers, starting from the topmost layer.
|
@@ -240,7 +233,7 @@ up.dom = (($) ->
|
|
240
233
|
replace = (selectorOrElement, url, options) ->
|
241
234
|
options = u.options(options)
|
242
235
|
|
243
|
-
options.inspectResponse = fullLoad = -> up.browser.navigate(url, u.only(options, 'method', '
|
236
|
+
options.inspectResponse = fullLoad = -> up.browser.navigate(url, u.only(options, 'method', 'params'))
|
244
237
|
|
245
238
|
if !up.browser.canPushState() && options.history != false
|
246
239
|
fullLoad() unless options.preload
|
@@ -266,26 +259,28 @@ up.dom = (($) ->
|
|
266
259
|
# http://2ality.com/2016/03/promise-rejections-vs-exceptions.html
|
267
260
|
return Promise.reject(e)
|
268
261
|
|
269
|
-
request =
|
262
|
+
request = new up.Request(
|
270
263
|
url: url
|
271
264
|
method: options.method
|
272
|
-
data: options.data
|
265
|
+
data: options.data # deprecated, use { params }
|
266
|
+
params: options.params
|
273
267
|
target: improvedTarget
|
274
268
|
failTarget: improvedFailTarget
|
275
269
|
cache: options.cache
|
276
270
|
preload: options.preload
|
277
271
|
headers: options.headers
|
278
272
|
timeout: options.timeout
|
273
|
+
)
|
279
274
|
|
280
275
|
onSuccess = (response) ->
|
281
|
-
processResponse(true, improvedTarget, response, successOptions)
|
276
|
+
processResponse(true, improvedTarget, request, response, successOptions)
|
282
277
|
|
283
278
|
onFailure = (response) ->
|
284
279
|
rejection = -> Promise.reject(response)
|
285
280
|
if response.isFatalError()
|
286
281
|
rejection()
|
287
282
|
else
|
288
|
-
promise = processResponse(false, improvedFailTarget, response, failureOptions)
|
283
|
+
promise = processResponse(false, improvedFailTarget, request, response, failureOptions)
|
289
284
|
# Although processResponse() we will perform a successful replacement of options.failTarget,
|
290
285
|
# we still want to reject the promise that's returned to our API client.
|
291
286
|
u.always(promise, rejection)
|
@@ -297,15 +292,12 @@ up.dom = (($) ->
|
|
297
292
|
###**
|
298
293
|
@internal
|
299
294
|
###
|
300
|
-
processResponse = (isSuccess, selector, response, options) ->
|
301
|
-
request = response.request
|
295
|
+
processResponse = (isSuccess, selector, request, response, options) ->
|
302
296
|
sourceUrl = response.url
|
303
297
|
historyUrl = sourceUrl
|
304
|
-
hash = request.hash
|
305
298
|
|
306
|
-
if
|
307
|
-
|
308
|
-
options.reveal = hash
|
299
|
+
if hash = request.hash
|
300
|
+
options.hash = hash
|
309
301
|
historyUrl += hash
|
310
302
|
|
311
303
|
isReloadable = (response.method == 'GET')
|
@@ -376,7 +368,6 @@ up.dom = (($) ->
|
|
376
368
|
up.log.group 'Extracting %s from %d bytes of HTML', selectorOrElement, html?.length, ->
|
377
369
|
options = u.options options,
|
378
370
|
historyMethod: 'push'
|
379
|
-
requireMatch: true
|
380
371
|
keep: true
|
381
372
|
layer: 'auto'
|
382
373
|
|
@@ -452,7 +443,7 @@ up.dom = (($) ->
|
|
452
443
|
# Reveal element that was being prepended/appended.
|
453
444
|
# Since we will animate (not morph) it's OK to allow animation of scrolling
|
454
445
|
# if the user has configured up.layout.config.duration.
|
455
|
-
promise = up.layout.
|
446
|
+
promise = up.layout.scrollAfterInsertFragment($wrapper, options)
|
456
447
|
|
457
448
|
# Since we're adding content instead of replacing, we'll only
|
458
449
|
# animate $new instead of morphing between $old and $new
|
@@ -490,6 +481,7 @@ up.dom = (($) ->
|
|
490
481
|
|
491
482
|
return up.morph($old, $new, transition, morphOptions)
|
492
483
|
|
484
|
+
|
493
485
|
# This will find all [up-keep] descendants in $old an, overwrite their partner
|
494
486
|
# element in $new and leave a visually identical clone in $old for a later transition.
|
495
487
|
# Returns an array of keepPlans.
|
@@ -512,6 +504,7 @@ up.dom = (($) ->
|
|
512
504
|
keepPlans.push(plan)
|
513
505
|
keepPlans
|
514
506
|
|
507
|
+
|
515
508
|
findKeepPlan = ($element, $new, options) ->
|
516
509
|
if options.keep
|
517
510
|
$keepable = $element
|
@@ -525,8 +518,8 @@ up.dom = (($) ->
|
|
525
518
|
$partner = $partner.first()
|
526
519
|
if $partner.length && $partner.is('[up-keep]')
|
527
520
|
plan =
|
528
|
-
$element: $keepable
|
529
|
-
$newElement: $partner
|
521
|
+
$element: $keepable # the element that should be kept
|
522
|
+
$newElement: $partner # the element that would have replaced it but now does not
|
530
523
|
newData: up.syntax.data($partner) # the parsed up-data attribute of the element we will discard
|
531
524
|
keepEventArgs = u.merge(plan, message: ['Keeping element %o', $keepable.get(0)])
|
532
525
|
if up.bus.nobodyPrevents('up:fragment:keep', keepEventArgs)
|
@@ -652,7 +645,7 @@ up.dom = (($) ->
|
|
652
645
|
keptElements = []
|
653
646
|
for plan in options.keepPlans
|
654
647
|
emitFragmentKept(plan)
|
655
|
-
keptElements.push(plan.$element)
|
648
|
+
keptElements.push(plan.$element[0])
|
656
649
|
up.syntax.compile($element, skip: keptElements)
|
657
650
|
emitFragmentInserted($element, options)
|
658
651
|
$element
|
@@ -718,9 +711,10 @@ up.dom = (($) ->
|
|
718
711
|
|
719
712
|
@function up.first
|
720
713
|
@param {string|Element|jQuery|Array<Element>} selectorOrElement
|
721
|
-
@param {string} options.layer
|
722
|
-
The name of the layer in which to find the element.
|
723
|
-
|
714
|
+
@param {string} [options.layer='auto']
|
715
|
+
The name of the layer in which to find the element.
|
716
|
+
|
717
|
+
Valid values are `'auto'`, `'page'`, `'modal'` and `'popup'`.
|
724
718
|
@param {string|Element|jQuery} [options.origin]
|
725
719
|
An second element or selector that can be referenced as `&` in the first selector:
|
726
720
|
|
@@ -762,17 +756,48 @@ up.dom = (($) ->
|
|
762
756
|
break
|
763
757
|
$match
|
764
758
|
|
759
|
+
###**
|
760
|
+
@function up.dom.layerOf
|
761
|
+
@internal
|
762
|
+
###
|
765
763
|
layerOf = (selectorOrElement) ->
|
766
764
|
$element = $(selectorOrElement)
|
767
|
-
if
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
765
|
+
if $element.length
|
766
|
+
if up.popup.contains($element)
|
767
|
+
'popup'
|
768
|
+
else if up.modal.contains($element)
|
769
|
+
'modal'
|
770
|
+
else
|
771
|
+
'page'
|
773
772
|
|
774
773
|
matchesLayer = (selectorOrElement, layer) ->
|
775
|
-
layerOf(selectorOrElement) == layer
|
774
|
+
!layer || layerOf(selectorOrElement) == layer
|
775
|
+
|
776
|
+
###**
|
777
|
+
Returns all elements matching the given selector, but
|
778
|
+
ignores elements that are being [destroyed](/up.destroy) or [transitioned](/up.morph).
|
779
|
+
|
780
|
+
If the given argument is already a jQuery collection (or an array
|
781
|
+
of DOM elements), returns the subset of the given list that is matching these conditions.
|
782
|
+
|
783
|
+
@function up.all
|
784
|
+
@param {string|jQuery|Array<Element>} selectorOrElements
|
785
|
+
@param {string|Element|jQuery} [options.origin]
|
786
|
+
An second element or selector that can be referenced as `&` in the first selector.
|
787
|
+
@param {string} [options.layer]
|
788
|
+
The name of the layer in which to find the element. Valid values are
|
789
|
+
`'page'`, `'modal'` and `'popup'`.
|
790
|
+
@return {jQuery}
|
791
|
+
A jQuery collection of matching elements.
|
792
|
+
@experimental
|
793
|
+
###
|
794
|
+
all = (selectorOrElements, options) ->
|
795
|
+
options = u.options(options)
|
796
|
+
resolved = resolveSelector(selectorOrElements, options.origin)
|
797
|
+
$root = $(u.option(options.root, document))
|
798
|
+
$root.find(resolved).filter (index, element) ->
|
799
|
+
$element = $(element)
|
800
|
+
isRealElement($element) && matchesLayer($element, options.layer)
|
776
801
|
|
777
802
|
###**
|
778
803
|
Destroys the given element or selector.
|
@@ -912,10 +937,12 @@ up.dom = (($) ->
|
|
912
937
|
destroy: destroy
|
913
938
|
extract: extract
|
914
939
|
first: first
|
940
|
+
all: all
|
915
941
|
source: source
|
916
942
|
resolveSelector: resolveSelector
|
917
943
|
hello: hello
|
918
944
|
config: config
|
945
|
+
layerOf: layerOf
|
919
946
|
|
920
947
|
)(jQuery)
|
921
948
|
|
@@ -924,6 +951,7 @@ up.extract = up.dom.extract
|
|
924
951
|
up.reload = up.dom.reload
|
925
952
|
up.destroy = up.dom.destroy
|
926
953
|
up.first = up.dom.first
|
954
|
+
up.all = up.dom.all
|
927
955
|
up.hello = up.dom.hello
|
928
956
|
|
929
|
-
up.
|
957
|
+
up.deprecateRenamedModule 'flow', 'dom'
|