upjs-rails 0.3.3 → 0.4.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.
- 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">
|