upjs-rails 0.9.1 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +142 -0
- data/README.md +4 -1
- data/design/ghost-debugging.txt +118 -0
- data/design/homepage.txt +236 -0
- data/dist/up-bootstrap.js +7 -3
- data/dist/up-bootstrap.min.js +1 -1
- data/dist/up.js +1611 -1222
- data/dist/up.min.js +2 -2
- data/lib/assets/javascripts/up/bus.js.coffee +1 -1
- data/lib/assets/javascripts/up/flow.js.coffee +21 -20
- data/lib/assets/javascripts/up/form.js.coffee +11 -12
- data/lib/assets/javascripts/up/history.js.coffee +137 -20
- data/lib/assets/javascripts/up/layout.js.coffee +134 -21
- data/lib/assets/javascripts/up/link.js.coffee +40 -17
- data/lib/assets/javascripts/up/modal.js.coffee +2 -2
- data/lib/assets/javascripts/up/motion.js.coffee +3 -1
- data/lib/assets/javascripts/up/navigation.js.coffee +5 -5
- data/lib/assets/javascripts/up/popup.js.coffee +2 -2
- data/lib/assets/javascripts/up/proxy.js.coffee +43 -82
- data/lib/assets/javascripts/up/tooltip.js.coffee +1 -1
- data/lib/assets/javascripts/up/util.js.coffee +145 -14
- data/lib/assets/javascripts/up-bootstrap/layout-ext.js.coffee +2 -2
- data/lib/assets/javascripts/up-bootstrap/navigation-ext.js.coffee +3 -1
- data/lib/assets/javascripts/up.js.coffee +2 -2
- data/lib/upjs/rails/version.rb +1 -1
- data/spec_app/Gemfile.lock +1 -1
- data/spec_app/config/routes.rb +1 -2
- data/spec_app/spec/javascripts/helpers/knife.js.coffee +1 -1
- data/spec_app/spec/javascripts/helpers/last_request.js.coffee +4 -0
- data/spec_app/spec/javascripts/helpers/set_timer.js.coffee +3 -3
- data/spec_app/spec/javascripts/helpers/to_end_with.js.coffee +5 -0
- data/spec_app/spec/javascripts/up/flow_spec.js.coffee +8 -6
- data/spec_app/spec/javascripts/up/form_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/history_spec.js.coffee +80 -1
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +64 -4
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +2 -2
- data/spec_app/spec/javascripts/up/motion_spec.js.coffee +7 -7
- data/spec_app/spec/javascripts/up/navigation_spec.js.coffee +6 -6
- data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +2 -2
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +22 -4
- metadata +7 -2
@@ -11,26 +11,44 @@ up.layout = (->
|
|
11
11
|
u = up.util
|
12
12
|
|
13
13
|
###*
|
14
|
-
|
14
|
+
Configures the application layout.
|
15
15
|
|
16
16
|
@method up.layout.defaults
|
17
|
-
@param {String} [options.
|
18
|
-
|
19
|
-
|
17
|
+
@param {Array<String>} [options.viewports]
|
18
|
+
An array of CSS selectors that find viewports
|
19
|
+
(containers that scroll their contents).
|
20
|
+
@param {Array<String>} [options.fixedTop]
|
21
|
+
An array of CSS selectors that find elements fixed to the
|
22
|
+
top edge of the screen (using `position: fixed`).
|
23
|
+
@param {Array<String>} [options.fixedBottom]
|
24
|
+
An array of CSS selectors that find elements fixed to the
|
25
|
+
bottom edge of the screen (using `position: fixed`).
|
20
26
|
@param {Number} [options.duration]
|
27
|
+
The duration of the scrolling animation in milliseconds.
|
28
|
+
Setting this to `0` will disable scrolling animations.
|
21
29
|
@param {String} [options.easing]
|
30
|
+
The timing function that controls the animation's acceleration.
|
31
|
+
See [W3C documentation](http://www.w3.org/TR/css3-transitions/#transition-timing-function)
|
32
|
+
for a list of pre-defined timing functions.
|
22
33
|
@param {Number} [options.snap]
|
34
|
+
When [revealing](#up.reveal) elements, Up.js will scroll an viewport
|
35
|
+
to the top when the revealed element is closer to the top than `options.snap`.
|
23
36
|
###
|
24
37
|
config = u.config
|
25
38
|
duration: 0
|
26
|
-
|
27
|
-
fixedTop: '[up-fixed~=top]'
|
28
|
-
fixedBottom: '[up-fixed~=bottom]'
|
39
|
+
viewports: ['body', '.up-modal', '[up-viewport]']
|
40
|
+
fixedTop: ['[up-fixed~=top]']
|
41
|
+
fixedBottom: ['[up-fixed~=bottom]']
|
29
42
|
snap: 50
|
30
43
|
easing: 'swing'
|
31
44
|
|
45
|
+
lastScrollTops = u.cache
|
46
|
+
size: 30,
|
47
|
+
key: up.history.normalizeUrl
|
48
|
+
|
32
49
|
reset = ->
|
33
50
|
config.reset()
|
51
|
+
lastScrollTops.clear()
|
34
52
|
|
35
53
|
SCROLL_PROMISE_KEY = 'up-scroll-promise'
|
36
54
|
|
@@ -73,35 +91,35 @@ up.layout = (->
|
|
73
91
|
A promise that will be resolved when the scrolling ends.
|
74
92
|
###
|
75
93
|
scroll = (viewport, scrollTop, options) ->
|
76
|
-
$
|
94
|
+
$viewport = $(viewport)
|
77
95
|
options = u.options(options)
|
78
96
|
duration = u.option(options.duration, config.duration)
|
79
97
|
easing = u.option(options.easing, config.easing)
|
80
98
|
|
81
|
-
finishScrolling($
|
99
|
+
finishScrolling($viewport)
|
82
100
|
|
83
101
|
if duration > 0
|
84
102
|
deferred = $.Deferred()
|
85
103
|
|
86
|
-
$
|
104
|
+
$viewport.data(SCROLL_PROMISE_KEY, deferred)
|
87
105
|
deferred.then ->
|
88
|
-
$
|
106
|
+
$viewport.removeData(SCROLL_PROMISE_KEY)
|
89
107
|
# Since we're scrolling using #animate, #finish can be
|
90
108
|
# used to jump to the last frame:
|
91
109
|
# https://api.jquery.com/finish/
|
92
|
-
$
|
110
|
+
$viewport.finish()
|
93
111
|
|
94
112
|
targetProps =
|
95
113
|
scrollTop: scrollTop
|
96
114
|
|
97
|
-
$
|
115
|
+
$viewport.animate targetProps,
|
98
116
|
duration: duration,
|
99
117
|
easing: easing,
|
100
118
|
complete: -> deferred.resolve()
|
101
119
|
|
102
120
|
deferred
|
103
121
|
else
|
104
|
-
$
|
122
|
+
$viewport.scrollTop(scrollTop)
|
105
123
|
u.resolvedDeferred()
|
106
124
|
|
107
125
|
###*
|
@@ -122,10 +140,10 @@ up.layout = (->
|
|
122
140
|
u.error("Fixed element %o must have a CSS attribute %o", $obstructor, cssAttr)
|
123
141
|
parseInt(anchorPosition) + $obstructor.height()
|
124
142
|
|
125
|
-
fixedTopBottoms = for obstructor in $(config.fixedTop)
|
143
|
+
fixedTopBottoms = for obstructor in $(config.fixedTop.join(', '))
|
126
144
|
measurePosition(obstructor, 'top')
|
127
145
|
|
128
|
-
fixedBottomTops = for obstructor in $(config.fixedBottom)
|
146
|
+
fixedBottomTops = for obstructor in $(config.fixedBottom.join(', '))
|
129
147
|
measurePosition(obstructor, 'bottom')
|
130
148
|
|
131
149
|
top: Math.max(0, fixedTopBottoms...)
|
@@ -171,7 +189,7 @@ up.layout = (->
|
|
171
189
|
reveal = (elementOrSelector, options) ->
|
172
190
|
options = u.options(options)
|
173
191
|
$element = $(elementOrSelector)
|
174
|
-
$viewport =
|
192
|
+
$viewport = viewportOf($element, options.viewport)
|
175
193
|
|
176
194
|
snap = u.option(options.snap, config.snap)
|
177
195
|
|
@@ -220,23 +238,112 @@ up.layout = (->
|
|
220
238
|
else
|
221
239
|
u.resolvedDeferred()
|
222
240
|
|
241
|
+
viewportSelector = ->
|
242
|
+
config.viewports.join(', ')
|
243
|
+
|
223
244
|
###*
|
224
|
-
|
225
|
-
|
245
|
+
Returns the viewport for the given element.
|
246
|
+
|
247
|
+
Throws an error if no viewport could be found.
|
248
|
+
|
249
|
+
@protected
|
250
|
+
@method up.layout.viewportOf
|
251
|
+
@param {String|Element|jQuery} selectorOrElement
|
226
252
|
###
|
227
|
-
|
253
|
+
viewportOf = (selectorOrElement, viewportSelectorOrElement) ->
|
254
|
+
$element = $(selectorOrElement)
|
228
255
|
$viewport = undefined
|
229
256
|
# If someone has handed as a jQuery element, that's the
|
230
257
|
# view period.
|
231
258
|
if u.isJQuery(viewportSelectorOrElement)
|
232
259
|
$viewport = viewportSelectorOrElement
|
233
260
|
else
|
234
|
-
vieportSelector = u.presence(viewportSelectorOrElement) ||
|
261
|
+
vieportSelector = u.presence(viewportSelectorOrElement) || viewportSelector()
|
235
262
|
$viewport = $element.closest(vieportSelector)
|
236
263
|
|
237
264
|
$viewport.length or u.error("Could not find viewport for %o", $element)
|
238
265
|
$viewport
|
239
266
|
|
267
|
+
###*
|
268
|
+
Returns a jQuery collection of all the viewports contained within the
|
269
|
+
given selector or element.
|
270
|
+
|
271
|
+
@protected
|
272
|
+
@method up.layout.viewportsIn
|
273
|
+
@param {String|Element|jQuery} selectorOrElement
|
274
|
+
@return jQuery
|
275
|
+
###
|
276
|
+
viewportsIn = (selectorOrElement) ->
|
277
|
+
$element = $(selectorOrElement)
|
278
|
+
u.findWithSelf($element, viewportSelector())
|
279
|
+
|
280
|
+
###*
|
281
|
+
Returns a jQuery collection of all the viewports on the screen.
|
282
|
+
|
283
|
+
@protected
|
284
|
+
@method up.layout.viewports
|
285
|
+
###
|
286
|
+
viewports = ->
|
287
|
+
$(viewportSelector())
|
288
|
+
|
289
|
+
###*
|
290
|
+
Returns a hash with scroll positions.
|
291
|
+
|
292
|
+
Each key in the hash is a viewport selector. The corresponding
|
293
|
+
value is the viewport's top scroll position:
|
294
|
+
|
295
|
+
up.layout.scrollTops()
|
296
|
+
=> { '.main': 0, '.sidebar': 73 }
|
297
|
+
|
298
|
+
@protected
|
299
|
+
@method up.layout.scrollTops
|
300
|
+
@return Object<String, Number>
|
301
|
+
###
|
302
|
+
scrollTops = ->
|
303
|
+
topsBySelector = {}
|
304
|
+
for viewport in config.viewports
|
305
|
+
$viewport = $(viewport)
|
306
|
+
if $viewport.length
|
307
|
+
topsBySelector[viewport] = $viewport.scrollTop()
|
308
|
+
topsBySelector
|
309
|
+
|
310
|
+
###*
|
311
|
+
Saves the top scroll positions of all the
|
312
|
+
viewports configured in `up.layout.defaults('viewports').
|
313
|
+
The saved scroll positions can be restored by calling
|
314
|
+
[`up.layout.restoreScroll()`](#up.layout.restoreScroll).
|
315
|
+
|
316
|
+
@method up.layout.saveScroll
|
317
|
+
@param {String} [options.url]
|
318
|
+
@param {Object<String, Number>} [options.tops]
|
319
|
+
@protected
|
320
|
+
###
|
321
|
+
saveScroll = (options = {}) ->
|
322
|
+
url = u.option(options.url, up.history.url())
|
323
|
+
tops = u.option(options.tops, scrollTops())
|
324
|
+
lastScrollTops.set(url, tops)
|
325
|
+
|
326
|
+
###*
|
327
|
+
Restores the top scroll positions of all the
|
328
|
+
viewports configured in `up.layout.defaults('viewports')`.
|
329
|
+
|
330
|
+
@method up.layout.restoreScroll
|
331
|
+
@param {String} [options.within]
|
332
|
+
@protected
|
333
|
+
###
|
334
|
+
restoreScroll = (options = {}) ->
|
335
|
+
|
336
|
+
$viewports = if options.within
|
337
|
+
viewportsIn(options.within)
|
338
|
+
else
|
339
|
+
viewports()
|
340
|
+
|
341
|
+
tops = lastScrollTops.get(up.history.url())
|
342
|
+
|
343
|
+
for selector, scrollTop of tops
|
344
|
+
$matchingViewport = $viewports.filter(selector)
|
345
|
+
up.scroll($matchingViewport, scrollTop, duration: 0)
|
346
|
+
|
240
347
|
###*
|
241
348
|
Marks this element as a scrolling container. Apply this ttribute if your app uses
|
242
349
|
a custom panel layout with fixed positioning instead of scrolling `<body>`.
|
@@ -323,6 +430,12 @@ up.layout = (->
|
|
323
430
|
scroll: scroll
|
324
431
|
finishScrolling: finishScrolling
|
325
432
|
defaults: config.update
|
433
|
+
viewportOf: viewportOf
|
434
|
+
viewportsIn: viewportsIn
|
435
|
+
viewports: viewports
|
436
|
+
scrollTops: scrollTops
|
437
|
+
saveScroll: saveScroll
|
438
|
+
restoreScroll: restoreScroll
|
326
439
|
|
327
440
|
)()
|
328
441
|
|
@@ -132,9 +132,8 @@ up.link = (->
|
|
132
132
|
or to `body` if such an attribute does not exist.
|
133
133
|
@param {Function|String} [options.transition]
|
134
134
|
A transition function or name.
|
135
|
-
@param {Element|jQuery|String} [options.
|
136
|
-
|
137
|
-
case the replaced element is not visible in the viewport.
|
135
|
+
@param {Element|jQuery|String} [options.reveal]
|
136
|
+
Whether to reveal the followed element within its viewport.
|
138
137
|
@param {Number} [options.duration]
|
139
138
|
The duration of the transition. See [`up.morph`](/up.motion#up.morph).
|
140
139
|
@param {Number} [options.delay]
|
@@ -148,10 +147,11 @@ up.link = (->
|
|
148
147
|
options = u.options(options)
|
149
148
|
url = u.option($link.attr('up-href'), $link.attr('href'))
|
150
149
|
selector = u.option(options.target, $link.attr('up-target'), 'body')
|
151
|
-
options.transition = u.option(options.transition, $link
|
152
|
-
options.history = u.option(options.history, $link
|
153
|
-
options.
|
154
|
-
options.cache = u.option(options.cache, $link
|
150
|
+
options.transition = u.option(options.transition, u.castedAttr($link, 'up-transition'), u.castedAttr($link, 'up-animation'))
|
151
|
+
options.history = u.option(options.history, u.castedAttr($link, 'up-history'))
|
152
|
+
options.reveal = u.option(options.reveal, u.castedAttr($link, 'up-reveal'))
|
153
|
+
options.cache = u.option(options.cache, u.castedAttr($link, 'up-cache'))
|
154
|
+
options.restoreScroll = u.option(options.restoreScroll, u.castedAttr($link, 'up-restore-scroll'))
|
155
155
|
options.method = followMethod($link, options)
|
156
156
|
options = u.merge(options, up.motion.animateOptions(options, $link))
|
157
157
|
|
@@ -219,6 +219,9 @@ up.link = (->
|
|
219
219
|
@param [up-href]
|
220
220
|
The destination URL to follow.
|
221
221
|
If omitted, the the link's `href` attribute will be used.
|
222
|
+
@param [up-restore-scroll='false']
|
223
|
+
Whether to restore the scroll position of all viewports
|
224
|
+
within the target selector.
|
222
225
|
###
|
223
226
|
up.on 'click', 'a[up-target], [up-href][up-target]', (event, $link) ->
|
224
227
|
if shouldProcessLinkEvent(event, $link)
|
@@ -265,7 +268,21 @@ up.link = (->
|
|
265
268
|
|
266
269
|
shouldProcessLinkEvent = (event, $link) ->
|
267
270
|
u.isUnmodifiedMouseEvent(event) && !childClicked(event, $link)
|
268
|
-
|
271
|
+
|
272
|
+
###*
|
273
|
+
Makes sure that the given link is handled by Up.js.
|
274
|
+
|
275
|
+
This is done by giving the link an `up-follow` attribute
|
276
|
+
if it doesn't already have it an `up-target` or `up-follow` attribute.
|
277
|
+
|
278
|
+
@method up.link.makeFollowable
|
279
|
+
@protected
|
280
|
+
###
|
281
|
+
makeFollowable = (link) ->
|
282
|
+
$link = $(link)
|
283
|
+
if u.isMissing($link.attr('up-target')) && u.isMissing($link.attr('up-follow'))
|
284
|
+
$link.attr('up-follow', '')
|
285
|
+
|
269
286
|
###*
|
270
287
|
If applied on a link, Follows this link via AJAX and replaces the
|
271
288
|
current `<body>` element with the response's `<body>` element.
|
@@ -292,6 +309,9 @@ up.link = (->
|
|
292
309
|
@param [up-href]
|
293
310
|
The destination URL to follow.
|
294
311
|
If omitted, the the link's `href` attribute will be used.
|
312
|
+
@param [up-restore-scroll='false']
|
313
|
+
Whether to restore the scroll position of all viewports
|
314
|
+
within the response.
|
295
315
|
###
|
296
316
|
up.on 'click', 'a[up-follow], [up-href][up-follow]', (event, $link) ->
|
297
317
|
if shouldProcessLinkEvent(event, $link)
|
@@ -321,9 +341,9 @@ up.link = (->
|
|
321
341
|
@ujs
|
322
342
|
@method [up-expand]
|
323
343
|
###
|
324
|
-
up.compiler '[up-expand]', ($
|
325
|
-
link = $
|
326
|
-
link or u.error('No link to expand within %o', $
|
344
|
+
up.compiler '[up-expand]', ($area) ->
|
345
|
+
link = $area.find('a, [up-href]').get(0)
|
346
|
+
link or u.error('No link to expand within %o', $area)
|
327
347
|
upAttributePattern = /^up-/
|
328
348
|
newAttrs = {}
|
329
349
|
newAttrs['up-href'] = $(link).attr('href')
|
@@ -331,10 +351,10 @@ up.link = (->
|
|
331
351
|
name = attribute.name
|
332
352
|
if name.match(upAttributePattern)
|
333
353
|
newAttrs[name] = attribute.value
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
354
|
+
u.setMissingAttrs($area, newAttrs)
|
355
|
+
$area.removeAttr('up-expand')
|
356
|
+
makeFollowable($area)
|
357
|
+
|
338
358
|
|
339
359
|
###*
|
340
360
|
Marks up the current link to be followed *as fast as possible*.
|
@@ -356,12 +376,14 @@ up.link = (->
|
|
356
376
|
@ujs
|
357
377
|
###
|
358
378
|
up.compiler '[up-dash]', ($element) ->
|
359
|
-
target = $element
|
379
|
+
target = u.castedAttr($element, 'up-dash')
|
360
380
|
newAttrs = {
|
361
381
|
'up-preload': 'true',
|
362
382
|
'up-instant': 'true'
|
363
383
|
}
|
364
|
-
if
|
384
|
+
if target is true
|
385
|
+
# If it's literally `true` then we don't have a target selector.
|
386
|
+
# Just follow the link by replacing `<body>`.
|
365
387
|
newAttrs['up-follow'] = ''
|
366
388
|
else
|
367
389
|
newAttrs['up-target'] = target
|
@@ -371,6 +393,7 @@ up.link = (->
|
|
371
393
|
knife: eval(Knife?.point)
|
372
394
|
visit: visit
|
373
395
|
follow: follow
|
396
|
+
makeFollowable: makeFollowable
|
374
397
|
childClicked: childClicked
|
375
398
|
followMethod: followMethod
|
376
399
|
|
@@ -207,8 +207,8 @@ up.modal = (->
|
|
207
207
|
maxWidth = u.option(options.maxWidth, $link.attr('up-max-width'), config.maxWidth)
|
208
208
|
height = u.option(options.height, $link.attr('up-height'), config.height)
|
209
209
|
animation = u.option(options.animation, $link.attr('up-animation'), config.openAnimation)
|
210
|
-
sticky = u.option(options.sticky, $link
|
211
|
-
history = if up.browser.canPushState() then u.option(options.history, $link
|
210
|
+
sticky = u.option(options.sticky, u.castedAttr($link, 'up-sticky'))
|
211
|
+
history = if up.browser.canPushState() then u.option(options.history, u.castedAttr($link, 'up-history'), true) else false
|
212
212
|
animateOptions = up.motion.animateOptions(options, $link)
|
213
213
|
|
214
214
|
close()
|
@@ -123,6 +123,8 @@ up.motion = (->
|
|
123
123
|
$element = $(elementOrSelector)
|
124
124
|
finish($element)
|
125
125
|
options = animateOptions(options)
|
126
|
+
if animation == 'none' || animation == false
|
127
|
+
none()
|
126
128
|
if u.isFunction(animation)
|
127
129
|
assertIsDeferred(animation($element, options), animation)
|
128
130
|
else if u.isString(animation)
|
@@ -260,7 +262,7 @@ up.motion = (->
|
|
260
262
|
$new = $(target)
|
261
263
|
finish($old)
|
262
264
|
finish($new)
|
263
|
-
if transitionOrName == 'none'
|
265
|
+
if transitionOrName == 'none' or transitionOrName == false
|
264
266
|
# don't create ghosts if we aren't really transitioning
|
265
267
|
none()
|
266
268
|
else if transition = u.presence(transitionOrName, u.isFunction) || transitions[transitionOrName]
|
@@ -23,16 +23,16 @@ up.navigation = (->
|
|
23
23
|
The class to set on [links that point the current location](#up-current).
|
24
24
|
###
|
25
25
|
config = u.config
|
26
|
-
|
26
|
+
currentClasses: ['up-current']
|
27
27
|
|
28
28
|
reset = ->
|
29
29
|
config.reset()
|
30
30
|
|
31
31
|
currentClass = ->
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
classes = config.currentClasses
|
33
|
+
classes = classes.concat(['up-current'])
|
34
|
+
classes = u.uniq(classes)
|
35
|
+
classes.join(' ')
|
36
36
|
|
37
37
|
CLASS_ACTIVE = 'up-active'
|
38
38
|
SELECTORS_SECTION = ['a', '[up-href]', '[up-alias]']
|
@@ -141,8 +141,8 @@ up.popup = (->
|
|
141
141
|
selector = u.option(options.target, $link.attr('up-popup'), 'body')
|
142
142
|
position = u.option(options.position, $link.attr('up-position'), config.position)
|
143
143
|
animation = u.option(options.animation, $link.attr('up-animation'), config.openAnimation)
|
144
|
-
sticky = u.option(options.sticky, $link
|
145
|
-
history = if up.browser.canPushState() then u.option(options.history, $link
|
144
|
+
sticky = u.option(options.sticky, u.castedAttr($link, 'up-sticky'))
|
145
|
+
history = if up.browser.canPushState() then u.option(options.history, u.castedAttr($link, 'up-history'), false) else false
|
146
146
|
animateOptions = up.motion.animateOptions(options, $link)
|
147
147
|
|
148
148
|
close()
|
@@ -53,7 +53,6 @@ up.proxy = (->
|
|
53
53
|
|
54
54
|
u = up.util
|
55
55
|
|
56
|
-
cache = undefined
|
57
56
|
$waitingLink = undefined
|
58
57
|
preloadDelayTimer = undefined
|
59
58
|
busyDelayTimer = undefined
|
@@ -81,6 +80,44 @@ up.proxy = (->
|
|
81
80
|
cacheSize: 70
|
82
81
|
cacheExpiry: 1000 * 60 * 5
|
83
82
|
|
83
|
+
cacheKey = (request) ->
|
84
|
+
normalizeRequest(request)
|
85
|
+
[ request.url,
|
86
|
+
request.method,
|
87
|
+
request.data,
|
88
|
+
request.selector
|
89
|
+
].join('|')
|
90
|
+
|
91
|
+
cache = u.cache
|
92
|
+
size: -> config.cacheSize
|
93
|
+
expiry: -> config.cacheExpiry
|
94
|
+
key: cacheKey
|
95
|
+
log: 'up.proxy'
|
96
|
+
|
97
|
+
###*
|
98
|
+
@protected
|
99
|
+
@method up.proxy.get
|
100
|
+
###
|
101
|
+
get = cache.get
|
102
|
+
|
103
|
+
###*
|
104
|
+
@protected
|
105
|
+
@method up.proxy.set
|
106
|
+
###
|
107
|
+
set = cache.set
|
108
|
+
|
109
|
+
###*
|
110
|
+
@protected
|
111
|
+
@method up.proxy.remove
|
112
|
+
###
|
113
|
+
remove = cache.remove
|
114
|
+
|
115
|
+
###*
|
116
|
+
@protected
|
117
|
+
@method up.proxy.clear
|
118
|
+
###
|
119
|
+
clear = cache.clear
|
120
|
+
|
84
121
|
cancelPreloadDelay = ->
|
85
122
|
clearTimeout(preloadDelayTimer)
|
86
123
|
preloadDelayTimer = null
|
@@ -90,40 +127,18 @@ up.proxy = (->
|
|
90
127
|
busyDelayTimer = null
|
91
128
|
|
92
129
|
reset = ->
|
93
|
-
cache = {}
|
94
130
|
$waitingLink = null
|
95
131
|
cancelPreloadDelay()
|
96
132
|
cancelBusyDelay()
|
97
133
|
pendingCount = 0
|
98
134
|
config.reset()
|
99
135
|
busyEventEmitted = false
|
136
|
+
cache.clear()
|
100
137
|
|
101
138
|
reset()
|
102
139
|
|
103
|
-
|
104
|
-
|
105
|
-
[ request.url,
|
106
|
-
request.method,
|
107
|
-
request.data,
|
108
|
-
request.selector
|
109
|
-
].join('|')
|
110
|
-
|
111
|
-
trim = ->
|
112
|
-
keys = u.keys(cache)
|
113
|
-
if keys.length > config.cacheSize
|
114
|
-
oldestKey = null
|
115
|
-
oldestTimestamp = null
|
116
|
-
u.each keys, (key) ->
|
117
|
-
promise = cache[key] # we don't need to call cacheKey here
|
118
|
-
timestamp = promise.timestamp
|
119
|
-
if !oldestTimestamp || oldestTimestamp > timestamp
|
120
|
-
oldestKey = key
|
121
|
-
oldestTimestamp = timestamp
|
122
|
-
delete cache[oldestKey] if oldestKey
|
123
|
-
|
124
|
-
timestamp = ->
|
125
|
-
(new Date()).valueOf()
|
126
|
-
|
140
|
+
alias = cache.alias
|
141
|
+
|
127
142
|
normalizeRequest = (request) ->
|
128
143
|
unless request._normalized
|
129
144
|
request.method = u.normalizeMethod(request.method)
|
@@ -131,11 +146,6 @@ up.proxy = (->
|
|
131
146
|
request.selector ||= 'body'
|
132
147
|
request._normalized = true
|
133
148
|
request
|
134
|
-
|
135
|
-
alias = (oldRequest, newRequest) ->
|
136
|
-
u.debug("Aliasing %o to %o", oldRequest, newRequest)
|
137
|
-
if promise = get(oldRequest)
|
138
|
-
set(newRequest, promise)
|
139
149
|
|
140
150
|
###*
|
141
151
|
Makes a request to the given URL and caches the response.
|
@@ -160,8 +170,8 @@ up.proxy = (->
|
|
160
170
|
If set to `false` a network connection will always be attempted.
|
161
171
|
###
|
162
172
|
ajax = (options) ->
|
163
|
-
forceCache =
|
164
|
-
ignoreCache =
|
173
|
+
forceCache = (options.cache == true)
|
174
|
+
ignoreCache = (options.cache == false)
|
165
175
|
|
166
176
|
request = u.only(options, 'url', 'method', 'data', 'selector', '_normalized')
|
167
177
|
|
@@ -254,55 +264,6 @@ up.proxy = (->
|
|
254
264
|
normalizeRequest(request)
|
255
265
|
u.contains(SAFE_HTTP_METHODS, request.method)
|
256
266
|
|
257
|
-
isFresh = (promise) ->
|
258
|
-
timeSinceTouch = timestamp() - promise.timestamp
|
259
|
-
timeSinceTouch < config.cacheExpiry
|
260
|
-
|
261
|
-
###*
|
262
|
-
@protected
|
263
|
-
@method up.proxy.get
|
264
|
-
###
|
265
|
-
get = (request) ->
|
266
|
-
key = cacheKey(request)
|
267
|
-
if promise = cache[key]
|
268
|
-
if !isFresh(promise)
|
269
|
-
u.debug("Discarding stale cache entry for %o (%o)", request.url, request)
|
270
|
-
remove(request)
|
271
|
-
undefined
|
272
|
-
else
|
273
|
-
u.debug("Cache hit for %o (%o)", request.url, request)
|
274
|
-
# $('body').css('background-color': 'green')
|
275
|
-
promise
|
276
|
-
else
|
277
|
-
u.debug("Cache miss for %o (%o)", request.url, request)
|
278
|
-
undefined
|
279
|
-
|
280
|
-
###*
|
281
|
-
@protected
|
282
|
-
@method up.proxy.set
|
283
|
-
###
|
284
|
-
set = (request, promise) ->
|
285
|
-
trim()
|
286
|
-
key = cacheKey(request)
|
287
|
-
promise.timestamp = timestamp()
|
288
|
-
cache[key] = promise
|
289
|
-
promise
|
290
|
-
|
291
|
-
###*
|
292
|
-
@protected
|
293
|
-
@method up.proxy.remove
|
294
|
-
###
|
295
|
-
remove = (request) ->
|
296
|
-
key = cacheKey(request)
|
297
|
-
delete cache[key]
|
298
|
-
|
299
|
-
###*
|
300
|
-
@protected
|
301
|
-
@method up.proxy.clear
|
302
|
-
###
|
303
|
-
clear = ->
|
304
|
-
cache = {}
|
305
|
-
|
306
267
|
checkPreload = ($link) ->
|
307
268
|
delay = parseInt(u.presentAttr($link, 'up-delay')) || config.preloadDelay
|
308
269
|
unless $link.is($waitingLink)
|
@@ -60,7 +60,7 @@ up.tooltip = (->
|
|
60
60
|
$link = $(linkOrSelector)
|
61
61
|
html = u.option(options.html, $link.attr('up-tooltip'), $link.attr('title'))
|
62
62
|
position = u.option(options.position, $link.attr('up-position'), 'top')
|
63
|
-
animation = u.option(options.animation, $link
|
63
|
+
animation = u.option(options.animation, u.castedAttr($link, 'up-animation'), 'fade-in')
|
64
64
|
animateOptions = up.motion.animateOptions(options, $link)
|
65
65
|
close()
|
66
66
|
$tooltip = createElement(html)
|