unpoly-rails 0.23.0 → 0.24.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 +68 -0
- data/dist/unpoly-bootstrap3.js +1 -1
- data/dist/unpoly-bootstrap3.min.js +1 -1
- data/dist/unpoly.css +18 -8
- data/dist/unpoly.js +498 -265
- data/dist/unpoly.min.css +1 -1
- data/dist/unpoly.min.js +3 -3
- data/lib/assets/javascripts/unpoly-bootstrap3/modal-ext.js.coffee +5 -2
- data/lib/assets/javascripts/unpoly/flow.js.coffee +3 -1
- data/lib/assets/javascripts/unpoly/form.js.coffee +3 -6
- data/lib/assets/javascripts/unpoly/layout.js.coffee +1 -1
- data/lib/assets/javascripts/unpoly/link.js.coffee +4 -2
- data/lib/assets/javascripts/unpoly/log.js.coffee +2 -2
- data/lib/assets/javascripts/unpoly/modal.js.coffee +125 -36
- data/lib/assets/javascripts/unpoly/motion.js.coffee +75 -37
- data/lib/assets/javascripts/unpoly/navigation.js.coffee +38 -26
- data/lib/assets/javascripts/unpoly/proxy.js.coffee +77 -52
- data/lib/assets/javascripts/unpoly/syntax.js.coffee +1 -0
- data/lib/assets/javascripts/unpoly/tooltip.js.coffee +2 -0
- data/lib/assets/javascripts/unpoly/util.js.coffee +138 -46
- data/lib/assets/stylesheets/unpoly/link.css.sass +1 -1
- data/lib/assets/stylesheets/unpoly/modal.css.sass +28 -15
- data/lib/unpoly/rails/version.rb +1 -1
- data/spec_app/Gemfile.lock +7 -7
- data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +2 -0
- data/spec_app/spec/javascripts/helpers/to_contain.js.coffee +5 -0
- data/spec_app/spec/javascripts/up/flow_spec.js.coffee +2 -2
- data/spec_app/spec/javascripts/up/history_spec.js.coffee +6 -4
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +114 -5
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +28 -18
- data/spec_app/spec/javascripts/up/motion_spec.js.coffee +112 -7
- data/spec_app/spec/javascripts/up/navigation_spec.js.coffee +157 -121
- data/spec_app/spec/javascripts/up/popup_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +42 -3
- data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +1 -2
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +26 -1
- data/spec_app/vendor/assets/bower_components/jquery/.bower.json +1 -1
- metadata +3 -3
- data/spec_app/spec/javascripts/helpers/set_timer.js.coffee +0 -3
@@ -36,11 +36,8 @@ up.navigation = (($) ->
|
|
36
36
|
classes.join(' ')
|
37
37
|
|
38
38
|
CLASS_ACTIVE = 'up-active'
|
39
|
-
|
40
|
-
|
41
|
-
SELECTOR_SECTION_INSTANT = ("#{selector}[up-instant]" for selector in SELECTORS_SECTION).join(', ')
|
42
|
-
SELECTOR_ACTIVE = ".#{CLASS_ACTIVE}"
|
43
|
-
|
39
|
+
SELECTOR_SECTION = 'a, [up-href]'
|
40
|
+
|
44
41
|
normalizeUrl = (url) ->
|
45
42
|
if u.isPresent(url)
|
46
43
|
u.normalizeUrl(url,
|
@@ -102,6 +99,22 @@ up.navigation = (($) ->
|
|
102
99
|
else if $section.hasClass(klass) && $section.closest('.up-destroying').length == 0
|
103
100
|
$section.removeClass(klass)
|
104
101
|
|
102
|
+
###*
|
103
|
+
@function findClickArea
|
104
|
+
@param {String|Element|jQuery} elementOrSelector
|
105
|
+
@param {Boolean} options.enlarge
|
106
|
+
If `true`, tries to find a containing link that has expanded the link's click area.
|
107
|
+
If we find one, we prefer to mark the larger area as active.
|
108
|
+
@internal
|
109
|
+
###
|
110
|
+
findClickArea = (elementOrSelector, options) ->
|
111
|
+
$area = $(elementOrSelector)
|
112
|
+
options = u.options(options, enlarge: false)
|
113
|
+
if options.enlarge
|
114
|
+
u.presence($area.parent(SELECTOR_SECTION)) || $area
|
115
|
+
else
|
116
|
+
$area
|
117
|
+
|
105
118
|
###*
|
106
119
|
Links that are currently loading are assigned the `up-active`
|
107
120
|
class automatically. Style `.up-active` in your CSS to improve the
|
@@ -129,24 +142,23 @@ up.navigation = (($) ->
|
|
129
142
|
@selector .up-active
|
130
143
|
@stable
|
131
144
|
###
|
132
|
-
|
133
|
-
|
134
|
-
$
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
$(
|
142
|
-
|
143
|
-
|
144
|
-
if u.
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
sectionClicked($section)
|
145
|
+
markActive = (elementOrSelector, options) ->
|
146
|
+
$element = findClickArea(elementOrSelector, options)
|
147
|
+
$element.addClass(CLASS_ACTIVE)
|
148
|
+
|
149
|
+
unmarkActive = (elementOrSelector, options) ->
|
150
|
+
$element = findClickArea(elementOrSelector, options)
|
151
|
+
$element.removeClass(CLASS_ACTIVE)
|
152
|
+
|
153
|
+
withActiveMark = (elementOrSelector, options, block) ->
|
154
|
+
$element = $(elementOrSelector)
|
155
|
+
markActive($element, options)
|
156
|
+
promise = block()
|
157
|
+
if u.isPromise(promise)
|
158
|
+
promise.always -> unmarkActive($element, options)
|
159
|
+
else
|
160
|
+
up.warn('Expected block to return a promise, but got %o', promise)
|
161
|
+
promise
|
150
162
|
|
151
163
|
###*
|
152
164
|
Links that point to the current location are assigned
|
@@ -193,9 +205,6 @@ up.navigation = (($) ->
|
|
193
205
|
@stable
|
194
206
|
###
|
195
207
|
up.on 'up:fragment:inserted', ->
|
196
|
-
# If a new fragment is inserted, it's likely to be the result
|
197
|
-
# of the active action. So we can remove the active marker.
|
198
|
-
unmarkActive()
|
199
208
|
# When a fragment is inserted it might either have brought a location change
|
200
209
|
# with it, or it might have opened a modal / popup which we consider
|
201
210
|
# to be secondary location sources (the primary being the browser's
|
@@ -215,5 +224,8 @@ up.navigation = (($) ->
|
|
215
224
|
|
216
225
|
config: config
|
217
226
|
defaults: -> u.error('up.navigation.defaults(...) no longer exists. Set values on he up.navigation.config property instead.')
|
227
|
+
markActive: markActive
|
228
|
+
unmarkActive: unmarkActive
|
229
|
+
withActiveMark: withActiveMark
|
218
230
|
|
219
231
|
)(jQuery)
|
@@ -112,67 +112,26 @@ up.proxy = (($) ->
|
|
112
112
|
if response = cache.get(candidate)
|
113
113
|
return response
|
114
114
|
|
115
|
-
###*
|
116
|
-
Manually stores a promise for the response to the given request.
|
117
|
-
|
118
|
-
@function up.proxy.set
|
119
|
-
@param {String} request.url
|
120
|
-
@param {String} [request.method='GET']
|
121
|
-
@param {String} [request.target='body']
|
122
|
-
@param {Promise} response
|
123
|
-
A promise for the response that is API-compatible with the
|
124
|
-
promise returned by [`jQuery.ajax`](http://api.jquery.com/jquery.ajax/).
|
125
|
-
@experimental
|
126
|
-
###
|
127
|
-
set = cache.set
|
128
|
-
|
129
|
-
###*
|
130
|
-
Manually removes the given request from the cache.
|
131
|
-
|
132
|
-
You can also [configure](/up.proxy.config) when the proxy
|
133
|
-
automatically removes cache entries.
|
134
|
-
|
135
|
-
@function up.proxy.remove
|
136
|
-
@param {String} request.url
|
137
|
-
@param {String} [request.method='GET']
|
138
|
-
@param {String} [request.target='body']
|
139
|
-
@experimental
|
140
|
-
###
|
141
|
-
remove = cache.remove
|
142
|
-
|
143
|
-
###*
|
144
|
-
Removes all cache entries.
|
145
|
-
|
146
|
-
Unpoly also automatically clears the cache whenever it processes
|
147
|
-
a request with a non-GET HTTP method.
|
148
|
-
|
149
|
-
@function up.proxy.clear
|
150
|
-
@stable
|
151
|
-
###
|
152
|
-
clear = cache.clear
|
153
|
-
|
154
115
|
cancelPreloadDelay = ->
|
155
116
|
clearTimeout(preloadDelayTimer)
|
156
117
|
preloadDelayTimer = null
|
157
118
|
|
158
|
-
|
119
|
+
cancelSlowDelay = ->
|
159
120
|
clearTimeout(slowDelayTimer)
|
160
121
|
slowDelayTimer = null
|
161
122
|
|
162
123
|
reset = ->
|
163
124
|
$waitingLink = null
|
164
125
|
cancelPreloadDelay()
|
165
|
-
|
126
|
+
cancelSlowDelay()
|
166
127
|
pendingCount = 0
|
167
128
|
config.reset()
|
168
|
-
slowEventEmitted = false
|
169
129
|
cache.clear()
|
130
|
+
slowEventEmitted = false
|
170
131
|
queuedRequests = []
|
171
132
|
|
172
133
|
reset()
|
173
134
|
|
174
|
-
alias = cache.alias
|
175
|
-
|
176
135
|
normalizeRequest = (request) ->
|
177
136
|
unless request._normalized
|
178
137
|
request.method = u.normalizeMethod(request.method)
|
@@ -190,13 +149,23 @@ up.proxy = (($) ->
|
|
190
149
|
Only requests with a method of `GET`, `OPTIONS` and `HEAD`
|
191
150
|
are considered to be read-only.
|
192
151
|
|
152
|
+
\#\#\#\# Example
|
153
|
+
|
154
|
+
up.ajax('/search', data: { query: 'sunshine' }).then(function(data, status, xhr) {
|
155
|
+
console.log('The response body is %o', data);
|
156
|
+
}).fail(function(xhr, status, error) {
|
157
|
+
console.error('The request failed');
|
158
|
+
});
|
159
|
+
|
160
|
+
\#\#\#\# Events
|
161
|
+
|
193
162
|
If a network connection is attempted, the proxy will emit
|
194
|
-
a `up:proxy:load` event with the `request` as its argument.
|
195
|
-
Once the response is received, a `up:proxy:receive` event will
|
163
|
+
a [`up:proxy:load`](/up:proxy:load) event with the `request` as its argument.
|
164
|
+
Once the response is received, a [`up:proxy:receive`](/up:proxy:receive) event will
|
196
165
|
be emitted.
|
197
166
|
|
198
167
|
@function up.ajax
|
199
|
-
@param {String}
|
168
|
+
@param {String} url
|
200
169
|
@param {String} [request.method='GET']
|
201
170
|
@param {String} [request.target='body']
|
202
171
|
@param {Boolean} [request.cache]
|
@@ -207,12 +176,18 @@ up.proxy = (($) ->
|
|
207
176
|
with the request.
|
208
177
|
@param {Object} [request.data={}]
|
209
178
|
An object of request parameters.
|
179
|
+
@param {String} [request.url]
|
180
|
+
You can omit the first string argument and pass the URL as
|
181
|
+
a `request` property instead.
|
210
182
|
@return
|
211
183
|
A promise for the response that is API-compatible with the
|
212
184
|
promise returned by [`jQuery.ajax`](http://api.jquery.com/jquery.ajax/).
|
213
185
|
@stable
|
214
186
|
###
|
215
|
-
ajax = (
|
187
|
+
ajax = (args...) ->
|
188
|
+
|
189
|
+
options = u.extractOptions(args)
|
190
|
+
options.url = args[0] if u.isGiven(args[0])
|
216
191
|
|
217
192
|
forceCache = (options.cache == true)
|
218
193
|
ignoreCache = (options.cache == false)
|
@@ -293,10 +268,7 @@ up.proxy = (($) ->
|
|
293
268
|
if isBusy() # a fast response might have beaten the delay
|
294
269
|
up.emit('up:proxy:slow', message: 'Proxy is busy')
|
295
270
|
slowEventEmitted = true
|
296
|
-
|
297
|
-
slowDelayTimer = setTimeout(emission, config.slowDelay)
|
298
|
-
else
|
299
|
-
emission()
|
271
|
+
slowDelayTimer = u.setTimer(config.slowDelay, emission)
|
300
272
|
|
301
273
|
###*
|
302
274
|
This event is [emitted]/(up.emit) when [AJAX requests](/up.ajax)
|
@@ -423,6 +395,59 @@ up.proxy = (($) ->
|
|
423
395
|
promise.done (args...) -> entry.deferred.resolve(args...)
|
424
396
|
promise.fail (args...) -> entry.deferred.reject(args...)
|
425
397
|
|
398
|
+
###*
|
399
|
+
Makes the proxy assume that `newRequest` has the same response as the
|
400
|
+
already cached `oldRequest`.
|
401
|
+
|
402
|
+
Unpoly uses this internally when the user redirects from `/old` to `/new`.
|
403
|
+
In that case, both `/old` and `/new` will cache the same response from `/new`.
|
404
|
+
|
405
|
+
@function up.proxy.alias
|
406
|
+
@param {Object} oldRequest
|
407
|
+
@param {Object} newRequest
|
408
|
+
@experimental
|
409
|
+
###
|
410
|
+
alias = cache.alias
|
411
|
+
|
412
|
+
###*
|
413
|
+
Manually stores a promise for the response to the given request.
|
414
|
+
|
415
|
+
@function up.proxy.set
|
416
|
+
@param {String} request.url
|
417
|
+
@param {String} [request.method='GET']
|
418
|
+
@param {String} [request.target='body']
|
419
|
+
@param {Promise} response
|
420
|
+
A promise for the response that is API-compatible with the
|
421
|
+
promise returned by [`jQuery.ajax`](http://api.jquery.com/jquery.ajax/).
|
422
|
+
@experimental
|
423
|
+
###
|
424
|
+
set = cache.set
|
425
|
+
|
426
|
+
###*
|
427
|
+
Manually removes the given request from the cache.
|
428
|
+
|
429
|
+
You can also [configure](/up.proxy.config) when the proxy
|
430
|
+
automatically removes cache entries.
|
431
|
+
|
432
|
+
@function up.proxy.remove
|
433
|
+
@param {String} request.url
|
434
|
+
@param {String} [request.method='GET']
|
435
|
+
@param {String} [request.target='body']
|
436
|
+
@experimental
|
437
|
+
###
|
438
|
+
remove = cache.remove
|
439
|
+
|
440
|
+
###*
|
441
|
+
Removes all cache entries.
|
442
|
+
|
443
|
+
Unpoly also automatically clears the cache whenever it processes
|
444
|
+
a request with a non-GET HTTP method.
|
445
|
+
|
446
|
+
@function up.proxy.clear
|
447
|
+
@stable
|
448
|
+
###
|
449
|
+
clear = cache.clear
|
450
|
+
|
426
451
|
###*
|
427
452
|
This event is [emitted]/(up.emit) before an [AJAX request](/up.ajax)
|
428
453
|
is starting to load.
|
@@ -9,6 +9,14 @@ that might save you from loading something like [Underscore.js](http://underscor
|
|
9
9
|
###
|
10
10
|
up.util = (($) ->
|
11
11
|
|
12
|
+
###*
|
13
|
+
A function that does nothing.
|
14
|
+
|
15
|
+
@function up.util.noop
|
16
|
+
@experimental
|
17
|
+
###
|
18
|
+
noop = $.noop
|
19
|
+
|
12
20
|
###*
|
13
21
|
@function up.util.memoize
|
14
22
|
@internal
|
@@ -755,6 +763,24 @@ up.util = (($) ->
|
|
755
763
|
values = ($element.attr(attrName) for attrName in attrNames)
|
756
764
|
detect(values, isPresent)
|
757
765
|
|
766
|
+
###*
|
767
|
+
Waits for the given number of milliseconds, the nruns the given callback.
|
768
|
+
|
769
|
+
If the number of milliseconds is zero, the callback is run in the current execution frame.
|
770
|
+
See [`up.util.nextFrame`] for running a function in the next executation frame.
|
771
|
+
|
772
|
+
@function up.util.setTimer
|
773
|
+
@param {Number} millis
|
774
|
+
@param {Function} callback
|
775
|
+
@experimental
|
776
|
+
###
|
777
|
+
setTimer = (millis, callback) ->
|
778
|
+
if millis > 0
|
779
|
+
setTimeout(callback, millis)
|
780
|
+
else
|
781
|
+
callback()
|
782
|
+
|
783
|
+
|
758
784
|
###*
|
759
785
|
Schedules the given function to be called in the
|
760
786
|
next Javascript execution frame.
|
@@ -868,6 +894,16 @@ up.util = (($) ->
|
|
868
894
|
memo = ->
|
869
895
|
memo
|
870
896
|
|
897
|
+
###*
|
898
|
+
Forces a repaint of the given element.
|
899
|
+
|
900
|
+
@function up.util.forceRepaint
|
901
|
+
@internal
|
902
|
+
###
|
903
|
+
forceRepaint = (element) ->
|
904
|
+
element = unJQuery(element)
|
905
|
+
element.offsetHeight
|
906
|
+
|
871
907
|
###*
|
872
908
|
Animates the given element's CSS properties using CSS transitions.
|
873
909
|
|
@@ -901,23 +937,49 @@ up.util = (($) ->
|
|
901
937
|
delay: 0,
|
902
938
|
easing: 'ease'
|
903
939
|
)
|
904
|
-
|
905
|
-
#
|
940
|
+
|
941
|
+
# We don't finish an existing animation here, since the public API
|
942
|
+
# we expose as `up.motion.animate` already does this.
|
906
943
|
deferred = $.Deferred()
|
907
944
|
transition =
|
908
945
|
'transition-property': Object.keys(lastFrame).join(', ')
|
909
946
|
'transition-duration': "#{opts.duration}ms"
|
910
947
|
'transition-delay': "#{opts.delay}ms"
|
911
948
|
'transition-timing-function': opts.easing
|
949
|
+
oldTransition = $element.css(Object.keys(transition))
|
950
|
+
|
951
|
+
$element.addClass('up-animating')
|
912
952
|
withoutCompositing = forceCompositing($element)
|
913
|
-
|
953
|
+
$element.css(transition)
|
914
954
|
$element.css(lastFrame)
|
915
|
-
deferred.then(withoutCompositing)
|
916
|
-
deferred.then(withoutTransition)
|
917
955
|
$element.data(ANIMATION_DEFERRED_KEY, deferred)
|
918
|
-
|
919
|
-
|
920
|
-
|
956
|
+
|
957
|
+
deferred.then ->
|
958
|
+
$element.removeData(ANIMATION_DEFERRED_KEY)
|
959
|
+
withoutCompositing()
|
960
|
+
|
961
|
+
# To interrupt the running transition we *must* set it to 'none' exactly.
|
962
|
+
# We cannot simply restore the old transition properties because browsers
|
963
|
+
# would simply keep transitioning the old properties.
|
964
|
+
$element.css('transition': 'none')
|
965
|
+
|
966
|
+
# Restoring a previous transition involves some work, so we only do it if
|
967
|
+
# we know the element was transitioning before.
|
968
|
+
hadTransitionBefore = !(oldTransition['transition-property'] == 'none' || (oldTransition['transition-property'] == 'all' && oldTransition['transition-duration'][0] == '0'))
|
969
|
+
if hadTransitionBefore
|
970
|
+
forceRepaint($element) # :(
|
971
|
+
$element.css(oldTransition)
|
972
|
+
|
973
|
+
# Since listening to transitionEnd events is painful, we wait for a timeout
|
974
|
+
# and then resolve our deferred. Maybe revisit that decision some day.
|
975
|
+
animationEnd = opts.duration + opts.delay
|
976
|
+
endTimeout = setTimer animationEnd, ->
|
977
|
+
$element.removeClass('up-animating')
|
978
|
+
deferred.resolve() unless isDetached($element)
|
979
|
+
# Clean up in case we're canceled through some other code that
|
980
|
+
# resolves our deferred.
|
981
|
+
deferred.then(-> clearTimeout(endTimeout))
|
982
|
+
|
921
983
|
# Return the whole deferred and not just return a thenable.
|
922
984
|
# Other code will need the possibility to cancel the animation
|
923
985
|
# by resolving the deferred.
|
@@ -1299,49 +1361,46 @@ up.util = (($) ->
|
|
1299
1361
|
|
1300
1362
|
store = undefined
|
1301
1363
|
|
1364
|
+
optionEvaluator = (name) ->
|
1365
|
+
->
|
1366
|
+
value = config[name]
|
1367
|
+
if isNumber(value)
|
1368
|
+
value
|
1369
|
+
else if isFunction(value)
|
1370
|
+
value()
|
1371
|
+
else
|
1372
|
+
undefined
|
1373
|
+
|
1374
|
+
maxKeys = optionEvaluator('size')
|
1375
|
+
|
1376
|
+
expiryMillis = optionEvaluator('expiry')
|
1377
|
+
|
1378
|
+
normalizeStoreKey = (key) ->
|
1379
|
+
if config.key
|
1380
|
+
config.key(key)
|
1381
|
+
else
|
1382
|
+
key.toString()
|
1383
|
+
|
1384
|
+
isEnabled = ->
|
1385
|
+
maxKeys() isnt 0 && expiryMillis() isnt 0
|
1386
|
+
|
1302
1387
|
clear = ->
|
1303
1388
|
store = {}
|
1304
1389
|
|
1305
1390
|
clear()
|
1306
1391
|
|
1307
1392
|
log = (args...) ->
|
1308
|
-
if config.
|
1309
|
-
args[0] = "[#{config.
|
1393
|
+
if config.logPrefix
|
1394
|
+
args[0] = "[#{config.logPrefix}] #{args[0]}"
|
1310
1395
|
up.puts(args...)
|
1311
1396
|
|
1312
1397
|
keys = ->
|
1313
1398
|
Object.keys(store)
|
1314
1399
|
|
1315
|
-
|
1316
|
-
if isMissing(config.size)
|
1317
|
-
undefined
|
1318
|
-
else if isFunction(config.size)
|
1319
|
-
config.size()
|
1320
|
-
else if isNumber(config.size)
|
1321
|
-
config.size
|
1322
|
-
else
|
1323
|
-
error("Invalid size config: %o", config.size)
|
1324
|
-
|
1325
|
-
expiryMilis = ->
|
1326
|
-
if isMissing(config.expiry)
|
1327
|
-
undefined
|
1328
|
-
else if isFunction(config.expiry)
|
1329
|
-
config.expiry()
|
1330
|
-
else if isNumber(config.expiry)
|
1331
|
-
config.expiry
|
1332
|
-
else
|
1333
|
-
error("Invalid expiry config: %o", config.expiry)
|
1334
|
-
|
1335
|
-
normalizeStoreKey = (key) ->
|
1336
|
-
if config.key
|
1337
|
-
config.key(key)
|
1338
|
-
else
|
1339
|
-
key.toString()
|
1340
|
-
|
1341
|
-
trim = ->
|
1400
|
+
makeRoomForAnotherKey = ->
|
1342
1401
|
storeKeys = copy(keys())
|
1343
|
-
|
1344
|
-
if
|
1402
|
+
max = maxKeys()
|
1403
|
+
if max && storeKeys.length >= max
|
1345
1404
|
oldestKey = null
|
1346
1405
|
oldestTimestamp = null
|
1347
1406
|
each storeKeys, (key) ->
|
@@ -1361,20 +1420,22 @@ up.util = (($) ->
|
|
1361
1420
|
(new Date()).valueOf()
|
1362
1421
|
|
1363
1422
|
set = (key, value) ->
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1423
|
+
if isEnabled()
|
1424
|
+
makeRoomForAnotherKey()
|
1425
|
+
storeKey = normalizeStoreKey(key)
|
1426
|
+
store[storeKey] =
|
1427
|
+
timestamp: timestamp()
|
1428
|
+
value: value
|
1368
1429
|
|
1369
1430
|
remove = (key) ->
|
1370
1431
|
storeKey = normalizeStoreKey(key)
|
1371
1432
|
delete store[storeKey]
|
1372
1433
|
|
1373
1434
|
isFresh = (entry) ->
|
1374
|
-
|
1375
|
-
if
|
1435
|
+
millis = expiryMillis()
|
1436
|
+
if millis
|
1376
1437
|
timeSinceTouch = timestamp() - entry.timestamp
|
1377
|
-
timeSinceTouch <
|
1438
|
+
timeSinceTouch < millis
|
1378
1439
|
else
|
1379
1440
|
true
|
1380
1441
|
|
@@ -1570,12 +1631,37 @@ up.util = (($) ->
|
|
1570
1631
|
$error.text(asString)
|
1571
1632
|
throw new Error(asString)
|
1572
1633
|
|
1634
|
+
pluckKey = (object, key) ->
|
1635
|
+
value = object[key]
|
1636
|
+
delete object[key]
|
1637
|
+
value
|
1638
|
+
|
1573
1639
|
pluckData = (elementOrSelector, key) ->
|
1574
1640
|
$element = $(elementOrSelector)
|
1575
1641
|
value = $element.data(key)
|
1576
1642
|
$element.removeData(key)
|
1577
1643
|
value
|
1578
1644
|
|
1645
|
+
extractOptions = (args) ->
|
1646
|
+
lastArg = last(args)
|
1647
|
+
if isObject(lastArg)
|
1648
|
+
args.pop()
|
1649
|
+
else
|
1650
|
+
{}
|
1651
|
+
|
1652
|
+
###*
|
1653
|
+
Returns whether the given element has been detached from the DOM
|
1654
|
+
(or whether it was never attached).
|
1655
|
+
|
1656
|
+
@function up.util.isDetached
|
1657
|
+
@internal
|
1658
|
+
###
|
1659
|
+
isDetached = (element) ->
|
1660
|
+
element = unJQuery(element)
|
1661
|
+
# This is by far the fastest way to do this
|
1662
|
+
not jQuery.contains(document.documentElement, element)
|
1663
|
+
|
1664
|
+
isDetached: isDetached
|
1579
1665
|
requestDataAsArray: requestDataAsArray
|
1580
1666
|
requestDataAsQuery: requestDataAsQuery
|
1581
1667
|
appendRequestData: appendRequestData
|
@@ -1631,12 +1717,14 @@ up.util = (($) ->
|
|
1631
1717
|
isUnmodifiedMouseEvent: isUnmodifiedMouseEvent
|
1632
1718
|
nullJQuery: nullJQuery
|
1633
1719
|
unJQuery: unJQuery
|
1720
|
+
setTimer: setTimer
|
1634
1721
|
nextFrame: nextFrame
|
1635
1722
|
measure: measure
|
1636
1723
|
temporaryCss: temporaryCss
|
1637
1724
|
cssAnimate: cssAnimate
|
1638
1725
|
finishCssAnimate: finishCssAnimate
|
1639
1726
|
forceCompositing: forceCompositing
|
1727
|
+
forceRepaint: forceRepaint
|
1640
1728
|
escapePressed: escapePressed
|
1641
1729
|
copyAttributes: copyAttributes
|
1642
1730
|
findWithSelf: findWithSelf
|
@@ -1667,6 +1755,10 @@ up.util = (($) ->
|
|
1667
1755
|
multiSelector: multiSelector
|
1668
1756
|
error: error
|
1669
1757
|
pluckData: pluckData
|
1758
|
+
pluckKey: pluckKey
|
1759
|
+
extractOptions: extractOptions
|
1760
|
+
isDetached: isDetached
|
1761
|
+
noop: noop
|
1670
1762
|
|
1671
1763
|
)($)
|
1672
1764
|
|