upjs-rails 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/dist/up.css +16 -1
- data/dist/up.js +499 -88
- data/dist/up.min.css +1 -1
- data/dist/up.min.js +2 -1
- data/lib/assets/javascripts/up/browser.js.coffee +17 -1
- data/lib/assets/javascripts/up/bus.js.coffee +6 -4
- data/lib/assets/javascripts/up/flow.js.coffee +25 -16
- data/lib/assets/javascripts/up/form.js.coffee +11 -3
- data/lib/assets/javascripts/up/history.js.coffee +3 -4
- data/lib/assets/javascripts/up/link.js.coffee +47 -17
- data/lib/assets/javascripts/up/magic.js.coffee +36 -8
- data/lib/assets/javascripts/up/modal.js.coffee +6 -8
- data/lib/assets/javascripts/up/motion.js.coffee +9 -7
- data/lib/assets/javascripts/up/navigation.js.coffee +17 -7
- data/lib/assets/javascripts/up/popup.js.coffee +2 -4
- data/lib/assets/javascripts/up/proxy.js.coffee +179 -0
- data/lib/assets/javascripts/up/tooltip.js.coffee +6 -2
- data/lib/assets/javascripts/up/util.js.coffee +92 -6
- data/lib/assets/javascripts/up.js.coffee +4 -1
- data/lib/assets/stylesheets/up/error.css.sass +15 -0
- data/lib/assets/stylesheets/up/tooltip.css.sass +1 -0
- data/lib/upjs/rails/current_location.rb +2 -1
- data/lib/upjs/rails/version.rb +1 -1
- data/spec_app/Gemfile.lock +1 -1
- data/spec_app/spec/javascripts/up/flow_spec.js.coffee +38 -9
- data/spec_app/spec/javascripts/up/form_spec.js.coffee +2 -2
- data/spec_app/spec/javascripts/up/magic_spec.js.coffee +25 -1
- data/spec_app/spec/javascripts/up/navigation_spec.js.coffee +2 -2
- metadata +4 -2
@@ -82,10 +82,10 @@ up.motion = (->
|
|
82
82
|
else if u.isHash(animation)
|
83
83
|
u.cssAnimate($element, animation, options)
|
84
84
|
else
|
85
|
-
u.error("Unknown animation type", animation)
|
85
|
+
u.error("Unknown animation type %o", animation)
|
86
86
|
|
87
87
|
findAnimation = (name) ->
|
88
|
-
animations[name] or u.error("Unknown animation", animation)
|
88
|
+
animations[name] or u.error("Unknown animation %o", animation)
|
89
89
|
|
90
90
|
GHOSTING_PROMISE_KEY = 'up-ghosting-promise'
|
91
91
|
|
@@ -134,14 +134,14 @@ up.motion = (->
|
|
134
134
|
|
135
135
|
finishGhosting = ($element) ->
|
136
136
|
if existingGhosting = $element.data(GHOSTING_PROMISE_KEY)
|
137
|
-
|
137
|
+
u.debug('Canceling existing ghosting on %o', $element)
|
138
138
|
existingGhosting.resolve?()
|
139
139
|
|
140
140
|
assertIsDeferred = (object, origin) ->
|
141
141
|
if u.isDeferred(object)
|
142
142
|
object
|
143
143
|
else
|
144
|
-
u.error("Did not return a promise with .then and .resolve methods: ", origin)
|
144
|
+
u.error("Did not return a promise with .then and .resolve methods: %o", origin)
|
145
145
|
|
146
146
|
###*
|
147
147
|
Performs a transition between two elements.
|
@@ -178,8 +178,10 @@ up.motion = (->
|
|
178
178
|
$new = $(target)
|
179
179
|
finish($old)
|
180
180
|
finish($new)
|
181
|
-
|
182
|
-
|
181
|
+
if transitionOrName == 'none'
|
182
|
+
# don't create ghosts if we aren't really transitioning
|
183
|
+
none()
|
184
|
+
else if transition = u.presence(transitionOrName, u.isFunction) || transitions[transitionOrName]
|
183
185
|
withGhosts $old, $new, ($oldGhost, $newGhost) ->
|
184
186
|
assertIsDeferred(transition($oldGhost, $newGhost, options), transitionOrName)
|
185
187
|
else if animation = animations[transitionOrName]
|
@@ -194,7 +196,7 @@ up.motion = (->
|
|
194
196
|
)
|
195
197
|
morph($old, $new, transition, options)
|
196
198
|
else
|
197
|
-
u.error("Unknown transition
|
199
|
+
u.error("Unknown transition %o", transitionOrName)
|
198
200
|
else
|
199
201
|
# Skip ghosting and all the other stuff that can go wrong
|
200
202
|
# in ancient browsers
|
@@ -29,7 +29,7 @@ up.navigation = (->
|
|
29
29
|
|
30
30
|
CLASS_ACTIVE = 'up-active'
|
31
31
|
CLASS_CURRENT = 'up-current'
|
32
|
-
SELECTOR_SECTION = 'a[href], a[up-target], [up-follow], [up-modal], [up-popup]'
|
32
|
+
SELECTOR_SECTION = 'a[href], a[up-target], [up-follow], [up-modal], [up-popup], [up-source]'
|
33
33
|
SELECTOR_ACTIVE = ".#{CLASS_ACTIVE}"
|
34
34
|
|
35
35
|
normalizeUrl = (url) ->
|
@@ -38,19 +38,29 @@ up.navigation = (->
|
|
38
38
|
search: false
|
39
39
|
stripTrailingSlash: true
|
40
40
|
)
|
41
|
+
|
42
|
+
sectionUrls = ($section) ->
|
43
|
+
urls = []
|
44
|
+
if $link = up.link.resolve($section)
|
45
|
+
for attr in ['href', 'up-follow', 'up-source']
|
46
|
+
if url = u.presentAttr($link, attr)
|
47
|
+
url = normalizeUrl(url)
|
48
|
+
urls.push(url)
|
49
|
+
urls
|
41
50
|
|
42
51
|
locationChanged = ->
|
43
|
-
|
44
|
-
|
45
|
-
|
52
|
+
currentUrls = u.stringSet [
|
53
|
+
normalizeUrl(up.browser.url()),
|
54
|
+
normalizeUrl(up.modal.source()),
|
55
|
+
normalizeUrl(up.popup.source())
|
56
|
+
]
|
46
57
|
|
47
58
|
u.each $(SELECTOR_SECTION), (section) ->
|
48
59
|
$section = $(section)
|
49
60
|
# if $section is marked up with up-follow,
|
50
61
|
# the actual link might be a child element.
|
51
|
-
|
52
|
-
|
53
|
-
if url == windowLocation || url == modalLocation || url == popupLocation
|
62
|
+
urls = sectionUrls($section)
|
63
|
+
if currentUrls.includesAny(urls)
|
54
64
|
$section.addClass(CLASS_CURRENT)
|
55
65
|
else
|
56
66
|
$section.removeClass(CLASS_CURRENT)
|
@@ -54,7 +54,7 @@ up.popup = (->
|
|
54
54
|
left: linkBox.left
|
55
55
|
bottom: linkBox.top
|
56
56
|
else
|
57
|
-
u.error("Unknown origin", origin)
|
57
|
+
u.error("Unknown origin %o", origin)
|
58
58
|
$popup.attr('up-origin', origin)
|
59
59
|
$popup.css(css)
|
60
60
|
ensureInViewport($popup)
|
@@ -116,7 +116,7 @@ up.popup = (->
|
|
116
116
|
###
|
117
117
|
open = (linkOrSelector, options) ->
|
118
118
|
$link = $(linkOrSelector)
|
119
|
-
|
119
|
+
|
120
120
|
options = u.options(options)
|
121
121
|
url = u.option($link.attr('href'))
|
122
122
|
selector = u.option(options.target, $link.attr('up-popup'), 'body')
|
@@ -128,8 +128,6 @@ up.popup = (->
|
|
128
128
|
close()
|
129
129
|
$popup = createHiddenPopup($link, selector, sticky)
|
130
130
|
|
131
|
-
# console.log("before replace", $link, $popup)
|
132
|
-
|
133
131
|
up.replace(selector, url,
|
134
132
|
history: history
|
135
133
|
# source: true
|
@@ -0,0 +1,179 @@
|
|
1
|
+
###*
|
2
|
+
Caching and preloading
|
3
|
+
======================
|
4
|
+
|
5
|
+
Document me.
|
6
|
+
|
7
|
+
@class up.proxy
|
8
|
+
###
|
9
|
+
up.proxy = (->
|
10
|
+
|
11
|
+
config =
|
12
|
+
preloadDelay: 50
|
13
|
+
cacheSize: 70
|
14
|
+
cacheExpiry: 1000 * 60 * 5
|
15
|
+
|
16
|
+
###*
|
17
|
+
@method up.proxy.defaults
|
18
|
+
@param {Number} [preloadDelay]
|
19
|
+
@param {Number} [cacheSize]
|
20
|
+
@param {Number} [cacheExpiry]
|
21
|
+
The number of milliseconds until a cache entry expires.
|
22
|
+
###
|
23
|
+
defaults = (options) ->
|
24
|
+
u.extend(config, options)
|
25
|
+
|
26
|
+
cache = {}
|
27
|
+
|
28
|
+
u = up.util
|
29
|
+
|
30
|
+
$waitingLink = null
|
31
|
+
delayTimer = null
|
32
|
+
|
33
|
+
cacheKey = (request) ->
|
34
|
+
normalizeRequest(request)
|
35
|
+
[ request.url,
|
36
|
+
request.method,
|
37
|
+
request.selector
|
38
|
+
].join('|')
|
39
|
+
|
40
|
+
trim = ->
|
41
|
+
keys = u.keys(cache)
|
42
|
+
if keys.length > config.cacheSize
|
43
|
+
oldestKey = null
|
44
|
+
oldestTimestamp = null
|
45
|
+
u.each keys, (key) ->
|
46
|
+
promise = cache[key] # we don't need to call cacheKey here
|
47
|
+
timestamp = promise.timestamp
|
48
|
+
if !oldestTimestamp || oldestTimestamp > timestamp
|
49
|
+
oldestKey = key
|
50
|
+
oldestTimestamp = timestamp
|
51
|
+
delete cache[oldestKey] if oldestKey
|
52
|
+
|
53
|
+
timestamp = ->
|
54
|
+
(new Date()).valueOf()
|
55
|
+
|
56
|
+
normalizeRequest = (request) ->
|
57
|
+
debugger unless u.isHash(request)
|
58
|
+
unless request._requestNormalized
|
59
|
+
request.method = u.normalizeMethod(request.method)
|
60
|
+
request.url = u.normalizeUrl(request.url) if request.url
|
61
|
+
request.selector ||= 'body'
|
62
|
+
request._requestNormalized = true
|
63
|
+
request
|
64
|
+
|
65
|
+
alias = (oldRequest, newRequest) ->
|
66
|
+
u.debug("Aliasing %o to %o", oldRequest, newRequest)
|
67
|
+
if promise = get(oldRequest)
|
68
|
+
set(newRequest, promise)
|
69
|
+
|
70
|
+
###
|
71
|
+
@method up.proxy.ajax
|
72
|
+
@param {String} options.url
|
73
|
+
@param {String} [options.method='GET']
|
74
|
+
@param {String} [options.selector]
|
75
|
+
###
|
76
|
+
ajax = (request) ->
|
77
|
+
if !isIdempotent(request)
|
78
|
+
clear()
|
79
|
+
# We don't cache non-GET responses
|
80
|
+
promise = u.ajax(request)
|
81
|
+
else if promise = get(request)
|
82
|
+
touch(promise)
|
83
|
+
else
|
84
|
+
promise = u.ajax(request)
|
85
|
+
set(request, promise)
|
86
|
+
promise
|
87
|
+
|
88
|
+
isIdempotent = (request) ->
|
89
|
+
normalizeRequest(request)
|
90
|
+
request.method == 'GET'
|
91
|
+
|
92
|
+
ensureIsIdempotent = (request) ->
|
93
|
+
isIdempotent(request) or u.error("Won't preload non-GET request %o", request)
|
94
|
+
|
95
|
+
isFresh = (promise) ->
|
96
|
+
timeSinceTouch = timestamp() - promise.timestamp
|
97
|
+
timeSinceTouch < config.cacheExpiry
|
98
|
+
|
99
|
+
touch = (promise) ->
|
100
|
+
promise.timestamp = timestamp()
|
101
|
+
|
102
|
+
get = (request) ->
|
103
|
+
key = cacheKey(request)
|
104
|
+
if promise = cache[key]
|
105
|
+
if !isFresh(promise)
|
106
|
+
u.debug("Discarding stale cache entry for %o (%o)", request.url, request)
|
107
|
+
remove(request)
|
108
|
+
undefined
|
109
|
+
else
|
110
|
+
u.debug("Cache hit for %o (%o)", request.url, request)
|
111
|
+
# $('body').css('background-color': 'green')
|
112
|
+
promise
|
113
|
+
else
|
114
|
+
u.debug("Cache miss for %o (%o)", request.url, request)
|
115
|
+
# $('body').css('background-color': 'yellow')
|
116
|
+
undefined
|
117
|
+
|
118
|
+
set = (request, promise) ->
|
119
|
+
trim()
|
120
|
+
key = cacheKey(request)
|
121
|
+
cache[key] = promise
|
122
|
+
touch(promise)
|
123
|
+
promise
|
124
|
+
|
125
|
+
remove = (request) ->
|
126
|
+
key = cacheKey(request)
|
127
|
+
delete cache[key]
|
128
|
+
|
129
|
+
clear = ->
|
130
|
+
cache = {}
|
131
|
+
|
132
|
+
checkPreload = ($link) ->
|
133
|
+
delay = parseInt(u.presentAttr($link, 'up-delay')) || config.preloadDelay
|
134
|
+
unless $link.is($waitingLink)
|
135
|
+
$waitingLink = $link
|
136
|
+
cancelDelay()
|
137
|
+
curriedPreload = -> preload($link)
|
138
|
+
startDelay(curriedPreload, delay)
|
139
|
+
|
140
|
+
startDelay = (block, delay) ->
|
141
|
+
delayTimer = setTimeout(block, delay)
|
142
|
+
|
143
|
+
cancelDelay = ->
|
144
|
+
clearTimeout(delayTimer)
|
145
|
+
delayTimer = null
|
146
|
+
|
147
|
+
preload = (link, options) ->
|
148
|
+
options = u.options()
|
149
|
+
ensureIsIdempotent(options)
|
150
|
+
u.debug("Preloading %o", link)
|
151
|
+
options.preload = true
|
152
|
+
up.link.follow(link, options)
|
153
|
+
|
154
|
+
reset = ->
|
155
|
+
cancelDelay()
|
156
|
+
cache = {}
|
157
|
+
|
158
|
+
up.bus.on 'framework:reset', reset
|
159
|
+
|
160
|
+
###
|
161
|
+
@method [up-preload]
|
162
|
+
@ujs
|
163
|
+
###
|
164
|
+
up.on 'mouseover mousedown touchstart', '[up-preload]', (event, $element) ->
|
165
|
+
# Don't do anything if we are hovering over the child
|
166
|
+
# of a link. The actual link will receive the event
|
167
|
+
# and bubble in a second.
|
168
|
+
unless up.link.childClicked(event, $element)
|
169
|
+
checkPreload(up.link.resolve($element))
|
170
|
+
|
171
|
+
preload: preload
|
172
|
+
ajax: ajax
|
173
|
+
get: get
|
174
|
+
set: set
|
175
|
+
alias: alias
|
176
|
+
clear: clear
|
177
|
+
defaults: defaults
|
178
|
+
|
179
|
+
)()
|
@@ -31,7 +31,7 @@ up.tooltip = (->
|
|
31
31
|
left: linkBox.left + 0.5 * (linkBox.width - tooltipBox.width)
|
32
32
|
top: linkBox.top + linkBox.height
|
33
33
|
else
|
34
|
-
u.error("Unknown origin", origin)
|
34
|
+
u.error("Unknown origin %o", origin)
|
35
35
|
$tooltip.attr('up-origin', origin)
|
36
36
|
$tooltip.css(css)
|
37
37
|
|
@@ -51,7 +51,7 @@ up.tooltip = (->
|
|
51
51
|
###
|
52
52
|
open = (linkOrSelector, options = {}) ->
|
53
53
|
$link = $(linkOrSelector)
|
54
|
-
html = u.option(options.html, $link.attr('up-tooltip'))
|
54
|
+
html = u.option(options.html, $link.attr('up-tooltip'), $link.attr('title'))
|
55
55
|
origin = u.option(options.origin, $link.attr('up-origin'), 'top')
|
56
56
|
animation = u.option(options.animation, $link.attr('up-animation'), 'fade-in')
|
57
57
|
close()
|
@@ -78,6 +78,10 @@ up.tooltip = (->
|
|
78
78
|
Displays a tooltip when hovering the mouse over this element:
|
79
79
|
|
80
80
|
<a href="/decks" up-tooltip="Show all decks">Decks</a>
|
81
|
+
|
82
|
+
You can also make an existing `title` attribute appear as a tooltip:
|
83
|
+
|
84
|
+
<a href="/decks" title="Show all decks" up-tooltip>Decks</a>
|
81
85
|
|
82
86
|
@method [up-tooltip]
|
83
87
|
@ujs
|
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
###*
|
2
3
|
Utility functions
|
3
4
|
=================
|
@@ -57,6 +58,16 @@ up.util = (->
|
|
57
58
|
normalized += anchor.search unless options?.search == false
|
58
59
|
normalized
|
59
60
|
|
61
|
+
###
|
62
|
+
@method up.util.normalizeMethod
|
63
|
+
@protected
|
64
|
+
###
|
65
|
+
normalizeMethod = (method) ->
|
66
|
+
if method
|
67
|
+
method.toUpperCase()
|
68
|
+
else
|
69
|
+
'GET'
|
70
|
+
|
60
71
|
$createElementFromSelector = (selector) ->
|
61
72
|
path = selector.split(/[ >]/)
|
62
73
|
$root = null
|
@@ -87,15 +98,55 @@ up.util = (->
|
|
87
98
|
element = document.createElement(tagName)
|
88
99
|
element.innerHTML = html if isPresent(html)
|
89
100
|
element
|
101
|
+
|
102
|
+
debug = (args...) ->
|
103
|
+
args = toArray(args)
|
104
|
+
message = args.shift()
|
105
|
+
message = "[UP] #{message}"
|
106
|
+
placeHolderCount = message.match(CONSOLE_PLACEHOLDERS)?.length || 0
|
107
|
+
if isFunction(last(args)) && placeHolderCount < args.length
|
108
|
+
group = args.pop()
|
109
|
+
value = console.debug(message, args...)
|
110
|
+
if group
|
111
|
+
console.groupCollapsed()
|
112
|
+
try
|
113
|
+
value = group()
|
114
|
+
finally
|
115
|
+
console.groupEnd()
|
116
|
+
value
|
90
117
|
|
91
118
|
error = (args...) ->
|
92
|
-
|
93
|
-
|
94
|
-
|
119
|
+
args[0] = "[UP] #{args[0]}"
|
120
|
+
console.error(args...)
|
121
|
+
asString = stringifyConsoleArgs(args)
|
122
|
+
$error = presence($('.up-error')) || $('<div class="up-error"></div>').prependTo('body')
|
123
|
+
# $error = $('body')
|
124
|
+
$error.addClass('up-error')
|
125
|
+
$error.text(asString)
|
126
|
+
# alert "#{asString}\n\nOpen the developer console for details."
|
95
127
|
throw asString
|
128
|
+
|
129
|
+
CONSOLE_PLACEHOLDERS = /\%[odisf]/g
|
130
|
+
|
131
|
+
stringifyConsoleArgs = (args) ->
|
132
|
+
message = args[0]
|
133
|
+
i = 0
|
134
|
+
maxLength = 30
|
135
|
+
message.replace CONSOLE_PLACEHOLDERS, ->
|
136
|
+
i += 1
|
137
|
+
arg = args[i]
|
138
|
+
argType = (typeof arg)
|
139
|
+
if argType == 'string'
|
140
|
+
arg = arg.replace(/\s+/g, ' ')
|
141
|
+
arg = "#{arg.substr(0, maxLength)}…" if arg.length > maxLength
|
142
|
+
"\"#{arg}\""
|
143
|
+
else if argType == 'number'
|
144
|
+
arg.toString()
|
145
|
+
else
|
146
|
+
"(#{argType})"
|
96
147
|
|
97
148
|
createSelectorFromElement = ($element) ->
|
98
|
-
|
149
|
+
debug("Creating selector from element %o", $element)
|
99
150
|
classes = if classString = $element.attr("class") then classString.split(" ") else []
|
100
151
|
id = $element.attr("id")
|
101
152
|
selector = $element.prop("tagName").toLowerCase()
|
@@ -216,6 +267,9 @@ up.util = (->
|
|
216
267
|
# https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
|
217
268
|
isArray = Array.isArray ||
|
218
269
|
(object) -> Object.prototype.toString.call(object) == '[object Array]'
|
270
|
+
|
271
|
+
toArray = (object) ->
|
272
|
+
Array.prototype.slice.call(object)
|
219
273
|
|
220
274
|
copy = (object) ->
|
221
275
|
if isArray(object)
|
@@ -298,8 +352,11 @@ up.util = (->
|
|
298
352
|
|
299
353
|
temporaryCss = ($element, css, block) ->
|
300
354
|
oldCss = $element.css(keys(css))
|
355
|
+
# debug("Stored old CSS", oldCss)
|
301
356
|
$element.css(css)
|
302
|
-
memo = ->
|
357
|
+
memo = ->
|
358
|
+
# debug("Restoring CSS %o on %o", oldCss, $element)
|
359
|
+
$element.css(oldCss)
|
303
360
|
if block
|
304
361
|
block()
|
305
362
|
memo()
|
@@ -451,7 +508,10 @@ up.util = (->
|
|
451
508
|
String(object) == "false"
|
452
509
|
|
453
510
|
locationFromXhr = (xhr) ->
|
454
|
-
xhr.getResponseHeader('X-Up-
|
511
|
+
xhr.getResponseHeader('X-Up-Location')
|
512
|
+
|
513
|
+
methodFromXhr = (xhr) ->
|
514
|
+
xhr.getResponseHeader('X-Up-Method')
|
455
515
|
|
456
516
|
# willChangeHistory = (historyOption) ->
|
457
517
|
# isPresent(historyOption) && !castsToFalse(historyOption)
|
@@ -477,6 +537,27 @@ up.util = (->
|
|
477
537
|
each deferreds, (deferred) -> deferred.resolve?()
|
478
538
|
joined
|
479
539
|
|
540
|
+
stringSet = (array) ->
|
541
|
+
set = {}
|
542
|
+
|
543
|
+
includes = (string) ->
|
544
|
+
set[key(string)]
|
545
|
+
|
546
|
+
includesAny = (strings) ->
|
547
|
+
detect strings, includes
|
548
|
+
|
549
|
+
put = (string) ->
|
550
|
+
set[key(string)] = true
|
551
|
+
|
552
|
+
key = (string) ->
|
553
|
+
"_#{string}"
|
554
|
+
|
555
|
+
put(string) for string in array
|
556
|
+
|
557
|
+
put: put
|
558
|
+
includes: includes
|
559
|
+
includesAny: includesAny
|
560
|
+
|
480
561
|
# memoArray = ->
|
481
562
|
# array = []
|
482
563
|
# defaults = []
|
@@ -496,6 +577,7 @@ up.util = (->
|
|
496
577
|
presentAttr: presentAttr
|
497
578
|
createElement: createElement
|
498
579
|
normalizeUrl: normalizeUrl
|
580
|
+
normalizeMethod: normalizeMethod
|
499
581
|
createElementFromHtml: createElementFromHtml
|
500
582
|
$createElementFromSelector: $createElementFromSelector
|
501
583
|
createSelectorFromElement: createSelectorFromElement
|
@@ -507,6 +589,7 @@ up.util = (->
|
|
507
589
|
options: options
|
508
590
|
option: option
|
509
591
|
error: error
|
592
|
+
debug: debug
|
510
593
|
each: each
|
511
594
|
detect: detect
|
512
595
|
select: select
|
@@ -540,9 +623,11 @@ up.util = (->
|
|
540
623
|
findWithSelf: findWithSelf
|
541
624
|
contains: contains
|
542
625
|
isArray: isArray
|
626
|
+
toArray: toArray
|
543
627
|
castsToTrue: castsToTrue
|
544
628
|
castsToFalse: castsToFalse
|
545
629
|
locationFromXhr: locationFromXhr
|
630
|
+
methodFromXhr: methodFromXhr
|
546
631
|
clientSize: clientSize
|
547
632
|
only: only
|
548
633
|
trim: trim
|
@@ -550,5 +635,6 @@ up.util = (->
|
|
550
635
|
resolvedPromise: resolvedPromise
|
551
636
|
resolvedDeferred: resolvedDeferred
|
552
637
|
resolvableWhen: resolvableWhen
|
638
|
+
stringSet: stringSet
|
553
639
|
|
554
640
|
)()
|
@@ -6,6 +6,7 @@
|
|
6
6
|
#= require up/magic
|
7
7
|
#= require up/history
|
8
8
|
#= require up/motion
|
9
|
+
#= require up/proxy
|
9
10
|
#= require up/link
|
10
11
|
#= require up/form
|
11
12
|
#= require up/popup
|
@@ -15,8 +16,10 @@
|
|
15
16
|
#= require up/marker
|
16
17
|
#= require_self
|
17
18
|
|
18
|
-
|
19
|
+
up.browser.ensureRecentJquery()
|
19
20
|
|
21
|
+
if up.browser.isSupported()
|
22
|
+
|
20
23
|
up.browser.ensureConsoleExists()
|
21
24
|
|
22
25
|
up.bus.emit('framework:ready')
|
@@ -0,0 +1,15 @@
|
|
1
|
+
.up-error
|
2
|
+
background-color: #e10
|
3
|
+
color: white
|
4
|
+
padding: 5px
|
5
|
+
font-family: arial, helvetica, sans-serif
|
6
|
+
font-weight: bold
|
7
|
+
font-size: 14px
|
8
|
+
line-height: 18px
|
9
|
+
position: fixed
|
10
|
+
left: 0
|
11
|
+
top: 0
|
12
|
+
max-width: 100%
|
13
|
+
box-sizing: border-box
|
14
|
+
z-index: 99999999
|
15
|
+
|
@@ -9,7 +9,8 @@ module Upjs
|
|
9
9
|
private
|
10
10
|
|
11
11
|
def set_header_for_current_location
|
12
|
-
headers['X-Up-
|
12
|
+
headers['X-Up-Location'] = request.original_url
|
13
|
+
headers['X-Up-Method'] = request.method
|
13
14
|
end
|
14
15
|
|
15
16
|
ActionController::Base.include(self)
|
data/lib/upjs/rails/version.rb
CHANGED
data/spec_app/Gemfile.lock
CHANGED
@@ -14,18 +14,20 @@ describe 'up.flow', ->
|
|
14
14
|
affix('.before').text('old-before')
|
15
15
|
affix('.middle').text('old-middle')
|
16
16
|
affix('.after').text('old-after')
|
17
|
-
|
17
|
+
|
18
|
+
@responseText =
|
19
|
+
"""
|
20
|
+
<div class="before">new-before</div>
|
21
|
+
<div class="middle">new-middle</div>
|
22
|
+
<div class="after">new-after</div>
|
23
|
+
"""
|
24
|
+
|
18
25
|
@respond = ->
|
19
26
|
jasmine.Ajax.requests.mostRecent().respondWith
|
20
27
|
status: 200
|
21
28
|
contentType: 'text/html'
|
22
|
-
responseText:
|
23
|
-
|
24
|
-
<div class="before">new-before</div>
|
25
|
-
<div class="middle">new-middle</div>
|
26
|
-
<div class="after">new-after</div>
|
27
|
-
"""
|
28
|
-
|
29
|
+
responseText: @responseText
|
30
|
+
|
29
31
|
it 'replaces the given selector with the same selector from a freshly fetched page', (done) ->
|
30
32
|
@request = up.replace('.middle', '/path')
|
31
33
|
@respond()
|
@@ -57,7 +59,34 @@ describe 'up.flow', ->
|
|
57
59
|
expect($('.middle')).toHaveText('new-middle')
|
58
60
|
expect($('.after')).toHaveText('new-after')
|
59
61
|
done()
|
60
|
-
|
62
|
+
|
63
|
+
it 'executes those script-tags in the response that get inserted into the DOM', (done) ->
|
64
|
+
window.scriptTagExecuted = jasmine.createSpy('scriptTagExecuted')
|
65
|
+
|
66
|
+
@responseText =
|
67
|
+
"""
|
68
|
+
<div class="before">
|
69
|
+
new-before
|
70
|
+
<script type="text/javascript">
|
71
|
+
window.scriptTagExecuted('before')
|
72
|
+
</script>
|
73
|
+
</div>
|
74
|
+
<div class="middle">
|
75
|
+
new-middle
|
76
|
+
<script type="text/javascript">
|
77
|
+
window.scriptTagExecuted('middle')
|
78
|
+
</script>
|
79
|
+
</div>
|
80
|
+
"""
|
81
|
+
|
82
|
+
@request = up.replace('.middle', '/path')
|
83
|
+
@respond()
|
84
|
+
|
85
|
+
@request.then ->
|
86
|
+
expect(window.scriptTagExecuted).not.toHaveBeenCalledWith('before')
|
87
|
+
expect(window.scriptTagExecuted).toHaveBeenCalledWith('middle')
|
88
|
+
done()
|
89
|
+
|
61
90
|
else
|
62
91
|
|
63
92
|
it 'makes a full page load', ->
|
@@ -72,12 +72,12 @@ describe 'up.form', ->
|
|
72
72
|
expect($('body')).not.toHaveText('text-after')
|
73
73
|
done()
|
74
74
|
|
75
|
-
it 'respects a X-Up-
|
75
|
+
it 'respects a X-Up-Location header that the server sends in case of a redirect', (done) ->
|
76
76
|
|
77
77
|
@request.respondWith
|
78
78
|
status: 200
|
79
79
|
contentType: 'text/html'
|
80
|
-
responseHeaders: { 'X-Up-
|
80
|
+
responseHeaders: { 'X-Up-Location': '/other/path' }
|
81
81
|
responseText:
|
82
82
|
"""
|
83
83
|
<div class="response">
|