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
@@ -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'
|