unpoly-rails 0.27.3 → 0.28.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 +22 -1
- data/dist/unpoly.css +29 -21
- data/dist/unpoly.js +291 -134
- data/dist/unpoly.min.css +1 -1
- data/dist/unpoly.min.js +3 -3
- data/lib/assets/javascripts/unpoly.js.coffee +1 -0
- data/lib/assets/javascripts/unpoly/browser.js.coffee +22 -5
- data/lib/assets/javascripts/unpoly/bus.js.coffee +1 -1
- data/lib/assets/javascripts/unpoly/flow.js.coffee +9 -6
- data/lib/assets/javascripts/unpoly/form.js.coffee +46 -49
- data/lib/assets/javascripts/unpoly/history.js.coffee +2 -2
- data/lib/assets/javascripts/unpoly/layout.js.coffee +3 -3
- data/lib/assets/javascripts/unpoly/modal.js.coffee +30 -2
- data/lib/assets/javascripts/unpoly/motion.js.coffee +6 -6
- data/lib/assets/javascripts/unpoly/navigation.js.coffee +1 -1
- data/lib/assets/javascripts/unpoly/popup.js.coffee +2 -2
- data/lib/assets/javascripts/unpoly/proxy.js.coffee +5 -9
- data/lib/assets/javascripts/unpoly/syntax.js.coffee +10 -6
- data/lib/assets/javascripts/unpoly/toast.js.coffee +66 -0
- data/lib/assets/javascripts/unpoly/tooltip.js.coffee +1 -1
- data/lib/assets/javascripts/unpoly/util.js.coffee +47 -21
- data/lib/assets/stylesheets/unpoly/toast.css.sass +33 -0
- data/lib/unpoly/rails/version.rb +1 -1
- data/spec_app/Gemfile.lock +1 -1
- data/spec_app/app/assets/javascripts/integration_test.coffee +1 -0
- data/spec_app/app/assets/stylesheets/integration_test.sass +14 -0
- data/spec_app/app/controllers/application_controller.rb +8 -0
- data/spec_app/app/controllers/error_test_controller.rb +5 -0
- data/spec_app/app/views/error_test/trigger.erb +72 -0
- data/spec_app/app/views/error_test/unexpected_response.erb +3 -0
- data/spec_app/app/views/pages/start.erb +4 -0
- data/spec_app/config/routes.rb +2 -0
- data/spec_app/spec/javascripts/helpers/last_request.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/browser_spec.js.coffee +62 -0
- data/spec_app/spec/javascripts/up/form_spec.js.coffee +116 -3
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +2 -2
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +88 -4
- data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +27 -1
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +12 -0
- metadata +8 -3
- data/lib/assets/stylesheets/unpoly/error.css.sass +0 -21
@@ -182,7 +182,7 @@ up.motion = (($) ->
|
|
182
182
|
$element.css(animation)
|
183
183
|
u.resolvedDeferred()
|
184
184
|
else
|
185
|
-
|
185
|
+
up.fail("Unknown animation type for %o", animation)
|
186
186
|
|
187
187
|
###*
|
188
188
|
Extracts animation-related options from the given options hash.
|
@@ -203,7 +203,7 @@ up.motion = (($) ->
|
|
203
203
|
consolidatedOptions
|
204
204
|
|
205
205
|
findAnimation = (name) ->
|
206
|
-
animations[name] or
|
206
|
+
animations[name] or up.fail("Unknown animation %o", name)
|
207
207
|
|
208
208
|
GHOSTING_DEFERRED_KEY = 'up-ghosting-deferred'
|
209
209
|
GHOSTING_CLASS = 'up-ghosting'
|
@@ -302,7 +302,7 @@ up.motion = (($) ->
|
|
302
302
|
if u.isDeferred(object)
|
303
303
|
object
|
304
304
|
else
|
305
|
-
|
305
|
+
up.fail("Did not return a promise with .then and .resolve methods: %o", source)
|
306
306
|
|
307
307
|
###*
|
308
308
|
Performs an animated transition between two elements.
|
@@ -407,14 +407,14 @@ up.motion = (($) ->
|
|
407
407
|
)
|
408
408
|
return morph($old, $new, transition, parsedOptions)
|
409
409
|
else
|
410
|
-
|
410
|
+
up.fail("Unknown transition %o", transitionOrName)
|
411
411
|
else
|
412
412
|
return skipMorph($old, $new, parsedOptions)
|
413
413
|
|
414
414
|
ensureMorphable = ($element, transition) ->
|
415
415
|
if transition && $element.parents('body').length == 0
|
416
416
|
element = $element.get(0)
|
417
|
-
|
417
|
+
up.fail("Can't morph a <%s> element (%o)", element.tagName, element)
|
418
418
|
|
419
419
|
###*
|
420
420
|
This causes the side effects of a successful transition, but instantly.
|
@@ -724,7 +724,7 @@ up.motion = (($) ->
|
|
724
724
|
animation: animation
|
725
725
|
config: config
|
726
726
|
isEnabled: isEnabled
|
727
|
-
defaults: ->
|
727
|
+
defaults: -> up.fail('up.motion.defaults(...) no longer exists. Set values on he up.motion.config property instead.')
|
728
728
|
none: none
|
729
729
|
when: resolvableWhen
|
730
730
|
prependCopy: prependCopy
|
@@ -221,7 +221,7 @@ up.navigation = (($) ->
|
|
221
221
|
up.on 'up:framework:reset', reset
|
222
222
|
|
223
223
|
config: config
|
224
|
-
defaults: ->
|
224
|
+
defaults: -> up.fail('up.navigation.defaults(...) no longer exists. Set values on he up.navigation.config property instead.')
|
225
225
|
markActive: markActive
|
226
226
|
unmarkActive: unmarkActive
|
227
227
|
withActiveMark: withActiveMark
|
@@ -144,7 +144,7 @@ up.popup = (($) ->
|
|
144
144
|
css['top'] = linkBox.top - popupBox.height
|
145
145
|
css['left'] = linkBox.left
|
146
146
|
else
|
147
|
-
|
147
|
+
up.fail("Unknown position option '%s'", state.position)
|
148
148
|
|
149
149
|
state.$popup.attr('up-position', state.position)
|
150
150
|
state.$popup.css(css)
|
@@ -216,7 +216,7 @@ up.popup = (($) ->
|
|
216
216
|
|
217
217
|
attachNow = (elementOrSelector, options) ->
|
218
218
|
$anchor = $(elementOrSelector)
|
219
|
-
$anchor.length or
|
219
|
+
$anchor.length or up.fail('Cannot attach popup to non-existing element %o', elementOrSelector)
|
220
220
|
|
221
221
|
options = u.options(options)
|
222
222
|
url = u.option(u.pluckKey(options, 'url'), $anchor.attr('up-href'), $anchor.attr('href'))
|
@@ -312,16 +312,12 @@ up.proxy = (($) ->
|
|
312
312
|
show = function() { $element.show() };
|
313
313
|
hide = function() { $element.hide() };
|
314
314
|
|
315
|
-
up.on('up:proxy:slow', show);
|
316
|
-
up.on('up:proxy:recover', hide);
|
317
|
-
|
318
315
|
hide();
|
319
316
|
|
320
|
-
|
321
|
-
|
322
|
-
up.
|
323
|
-
|
324
|
-
};
|
317
|
+
return [
|
318
|
+
up.on('up:proxy:slow', show),
|
319
|
+
up.on('up:proxy:recover', hide)
|
320
|
+
];
|
325
321
|
|
326
322
|
});
|
327
323
|
|
@@ -552,7 +548,7 @@ up.proxy = (($) ->
|
|
552
548
|
isBusy: isBusy
|
553
549
|
isCachable: isCachable
|
554
550
|
config: config
|
555
|
-
defaults: ->
|
551
|
+
defaults: -> up.fail('up.proxy.defaults(...) no longer exists. Set values on he up.proxy.config property instead.')
|
556
552
|
|
557
553
|
)(jQuery)
|
558
554
|
|
@@ -101,7 +101,8 @@ up.syntax = (($) ->
|
|
101
101
|
or event handlers bound to the document root.
|
102
102
|
|
103
103
|
Here is a version of `<clock>` that updates
|
104
|
-
the time every second, and cleans up once it's done
|
104
|
+
the time every second, and cleans up once it's done. Note how it returns
|
105
|
+
a function that calls `clearInterval`:
|
105
106
|
|
106
107
|
up.compiler('clock', function($element) {
|
107
108
|
|
@@ -279,10 +280,16 @@ up.syntax = (($) ->
|
|
279
280
|
if compiler.keep
|
280
281
|
value = if u.isString(compiler.keep) then compiler.keep else ''
|
281
282
|
$jqueryElement.attr('up-keep', value)
|
282
|
-
|
283
|
-
if
|
283
|
+
returnValue = compiler.callback.apply(nativeElement, [$jqueryElement, data($jqueryElement)])
|
284
|
+
if destructor = discoverDestructor(returnValue)
|
284
285
|
addDestructor($jqueryElement, destructor)
|
285
286
|
|
287
|
+
discoverDestructor = (returnValue) ->
|
288
|
+
if u.isFunction(returnValue)
|
289
|
+
returnValue
|
290
|
+
else if u.isArray(returnValue) && u.all(returnValue, u.isFunction)
|
291
|
+
u.sequence(returnValue...)
|
292
|
+
|
286
293
|
addDestructor = ($jqueryElement, destructor) ->
|
287
294
|
$jqueryElement.addClass(DESTRUCTABLE_CLASS)
|
288
295
|
destructors = $jqueryElement.data(DESTRUCTORS_KEY) || []
|
@@ -446,6 +453,3 @@ up.syntax = (($) ->
|
|
446
453
|
|
447
454
|
up.compiler = up.syntax.compiler
|
448
455
|
up.macro = up.syntax.macro
|
449
|
-
|
450
|
-
up.ready = -> up.util.error('up.ready no longer exists. Please use up.hello instead.')
|
451
|
-
up.awaken = -> up.util.error('up.awaken no longer exists. Please use up.compiler instead.')
|
@@ -0,0 +1,66 @@
|
|
1
|
+
###*
|
2
|
+
Toast alerts
|
3
|
+
============
|
4
|
+
|
5
|
+
@class up.toast
|
6
|
+
###
|
7
|
+
up.toast = (($) ->
|
8
|
+
|
9
|
+
u = up.util
|
10
|
+
b = up.browser
|
11
|
+
|
12
|
+
VARIABLE_FORMATTER = (arg) -> "<span class='up-toast-variable'>#{u.escapeHtml(arg)}</span>"
|
13
|
+
|
14
|
+
state = u.config
|
15
|
+
$toast: null
|
16
|
+
|
17
|
+
reset = ->
|
18
|
+
close()
|
19
|
+
state.reset()
|
20
|
+
|
21
|
+
messageToHtml = (message) ->
|
22
|
+
if u.isArray(message)
|
23
|
+
message[0] = u.escapeHtml(message[0])
|
24
|
+
message = b.sprintfWithFormattedArgs(VARIABLE_FORMATTER, message...)
|
25
|
+
else
|
26
|
+
message = u.escapeHtml(message)
|
27
|
+
message
|
28
|
+
|
29
|
+
isOpen = ->
|
30
|
+
!!state.$toast
|
31
|
+
|
32
|
+
addAction = ($actions, label, callback) ->
|
33
|
+
$action = $('<span class="up-toast-action"></span>').text(label)
|
34
|
+
$action.on 'click', callback
|
35
|
+
$action.appendTo($actions)
|
36
|
+
|
37
|
+
open = (message, options = {}) ->
|
38
|
+
close()
|
39
|
+
$toast = $('<div class="up-toast"></div>').prependTo('body')
|
40
|
+
$message = $('<div class="up-toast-message"></div>').appendTo($toast)
|
41
|
+
$actions = $('<div class="up-toast-actions"></div>').appendTo($toast)
|
42
|
+
|
43
|
+
message = messageToHtml(message)
|
44
|
+
$message.html(message)
|
45
|
+
|
46
|
+
if action = (options.action || options.inspect)
|
47
|
+
addAction($actions, action.label, action.callback)
|
48
|
+
|
49
|
+
addAction($actions, 'Close', close)
|
50
|
+
|
51
|
+
state.$toast = $toast
|
52
|
+
|
53
|
+
close = ->
|
54
|
+
if isOpen()
|
55
|
+
state.$toast.remove()
|
56
|
+
state.$toast = null
|
57
|
+
|
58
|
+
# The framework is reset between tests
|
59
|
+
up.on 'up:framework:reset', reset
|
60
|
+
|
61
|
+
open: open
|
62
|
+
close: close
|
63
|
+
reset: reset
|
64
|
+
isOpen: isOpen
|
65
|
+
|
66
|
+
)(jQuery)
|
@@ -102,7 +102,7 @@ up.tooltip = (($) ->
|
|
102
102
|
css['top'] = linkBox.top + linkBox.height
|
103
103
|
css['left'] = linkBox.left + 0.5 * (linkBox.width - tooltipBox.width)
|
104
104
|
else
|
105
|
-
|
105
|
+
up.fail("Unknown position option '%s'", state.position)
|
106
106
|
|
107
107
|
state.$tooltip.attr('up-position', state.position)
|
108
108
|
state.$tooltip.css(css)
|
@@ -545,7 +545,7 @@ up.util = (($) ->
|
|
545
545
|
|
546
546
|
Returns the array.
|
547
547
|
|
548
|
-
@function up.util.
|
548
|
+
@function up.util.toArray
|
549
549
|
@param object
|
550
550
|
@return {Array}
|
551
551
|
@stable
|
@@ -1597,7 +1597,7 @@ up.util = (($) ->
|
|
1597
1597
|
if isFormData(data)
|
1598
1598
|
# Until FormData#entries is implemented in all major browsers
|
1599
1599
|
# we must give up here
|
1600
|
-
up.
|
1600
|
+
up.fail('Cannot convert FormData into an array')
|
1601
1601
|
else
|
1602
1602
|
query = requestDataAsQuery(data)
|
1603
1603
|
array = []
|
@@ -1620,7 +1620,7 @@ up.util = (($) ->
|
|
1620
1620
|
if isFormData(data)
|
1621
1621
|
# Until FormData#entries is implemented in all major browsers
|
1622
1622
|
# we must give up here
|
1623
|
-
up.
|
1623
|
+
up.fail('Cannot convert FormData into a query string')
|
1624
1624
|
else if isPresent(data)
|
1625
1625
|
query = $.param(data)
|
1626
1626
|
query = query.replace(/\+/g, '%20')
|
@@ -1672,28 +1672,34 @@ up.util = (($) ->
|
|
1672
1672
|
data
|
1673
1673
|
|
1674
1674
|
###*
|
1675
|
-
Throws
|
1675
|
+
Throws an [exception](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)
|
1676
|
+
with the given message.
|
1677
|
+
|
1678
|
+
The message will also be printed to the [error log](/up.log.error).
|
1676
1679
|
|
1677
|
-
|
1678
|
-
- An [`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) (exception) will be thrown, unwinding the current call stack
|
1679
|
-
- The error message will be printed in a corner of the screen
|
1680
|
+
Also a notification will be shown at the bottom of the screen.
|
1680
1681
|
|
1681
1682
|
\#\#\#\# Examples
|
1682
1683
|
|
1683
|
-
up.
|
1684
|
-
up.
|
1684
|
+
up.fail('Division by zero')
|
1685
|
+
up.fail('Unexpected result %o', result)
|
1685
1686
|
|
1687
|
+
@function up.fail
|
1686
1688
|
@experimental
|
1687
1689
|
###
|
1688
|
-
|
1689
|
-
|
1690
|
-
|
1691
|
-
|
1692
|
-
|
1693
|
-
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1690
|
+
fail = (args...) ->
|
1691
|
+
if isArray(args[0])
|
1692
|
+
messageArgs = args[0]
|
1693
|
+
toastOptions = args[1] || {}
|
1694
|
+
else
|
1695
|
+
messageArgs = args
|
1696
|
+
toastOptions = {}
|
1697
|
+
|
1698
|
+
up.log.error(messageArgs...)
|
1699
|
+
|
1700
|
+
whenReady().then -> up.toast.open(messageArgs, toastOptions)
|
1701
|
+
|
1702
|
+
asString = up.browser.sprintf(messageArgs...)
|
1697
1703
|
throw new Error(asString)
|
1698
1704
|
|
1699
1705
|
ESCAPE_HTML_ENTITY_MAP =
|
@@ -1816,6 +1822,25 @@ up.util = (($) ->
|
|
1816
1822
|
@queue = map(newTasks, previewable)
|
1817
1823
|
@poke()
|
1818
1824
|
|
1825
|
+
###*
|
1826
|
+
@function up.util.submittedValue
|
1827
|
+
@internal
|
1828
|
+
###
|
1829
|
+
submittedValue = (fieldOrSelector) ->
|
1830
|
+
$field = $(fieldOrSelector)
|
1831
|
+
if $field.is('[type=checkbox], [type=radio]') && !$field.is(':checked')
|
1832
|
+
undefined
|
1833
|
+
else
|
1834
|
+
$field.val()
|
1835
|
+
|
1836
|
+
###*
|
1837
|
+
@function up.util.sequence
|
1838
|
+
@internal
|
1839
|
+
###
|
1840
|
+
sequence: (functions...) ->
|
1841
|
+
->
|
1842
|
+
map functions, (f) -> f()
|
1843
|
+
|
1819
1844
|
isDetached: isDetached
|
1820
1845
|
requestDataAsArray: requestDataAsArray
|
1821
1846
|
requestDataAsQuery: requestDataAsQuery
|
@@ -1838,7 +1863,7 @@ up.util = (($) ->
|
|
1838
1863
|
merge: merge
|
1839
1864
|
options: options
|
1840
1865
|
option: option
|
1841
|
-
|
1866
|
+
fail: fail
|
1842
1867
|
each: each
|
1843
1868
|
map: map
|
1844
1869
|
times: times
|
@@ -1911,7 +1936,7 @@ up.util = (($) ->
|
|
1911
1936
|
cache: cache
|
1912
1937
|
unwrapElement: unwrapElement
|
1913
1938
|
multiSelector: multiSelector
|
1914
|
-
error:
|
1939
|
+
error: fail
|
1915
1940
|
pluckData: pluckData
|
1916
1941
|
pluckKey: pluckKey
|
1917
1942
|
extractOptions: extractOptions
|
@@ -1922,7 +1947,8 @@ up.util = (($) ->
|
|
1922
1947
|
identity: identity
|
1923
1948
|
escapeHtml: escapeHtml
|
1924
1949
|
DivertibleChain: DivertibleChain
|
1950
|
+
submittedValue: submittedValue
|
1925
1951
|
|
1926
1952
|
)($)
|
1927
1953
|
|
1928
|
-
up.
|
1954
|
+
up.fail = up.util.fail
|
@@ -0,0 +1,33 @@
|
|
1
|
+
$highlight-color: #28b
|
2
|
+
$text-color: #333
|
3
|
+
|
4
|
+
.up-toast
|
5
|
+
border-top: 3px solid $highlight-color
|
6
|
+
background-color: white
|
7
|
+
color: $text-color
|
8
|
+
padding: 10px
|
9
|
+
font-family: monospace
|
10
|
+
font-size: 14px
|
11
|
+
line-height: 15px
|
12
|
+
position: fixed
|
13
|
+
left: 0
|
14
|
+
bottom: 0
|
15
|
+
right: 0
|
16
|
+
z-index: 99999999
|
17
|
+
|
18
|
+
.up-toast-variable
|
19
|
+
font-weight: normal
|
20
|
+
color: $text-color + 80
|
21
|
+
|
22
|
+
.up-toast-actions
|
23
|
+
margin-top: 7px
|
24
|
+
|
25
|
+
.up-toast-action
|
26
|
+
display: inline-block
|
27
|
+
word-spacing: -4px
|
28
|
+
text-decoration: underline
|
29
|
+
color: $highlight-color
|
30
|
+
cursor: pointer
|
31
|
+
|
32
|
+
&+.up-toast-action
|
33
|
+
margin-left: 12px
|
data/lib/unpoly/rails/version.rb
CHANGED
data/spec_app/Gemfile.lock
CHANGED
@@ -1,10 +1,19 @@
|
|
1
1
|
//= require unpoly
|
2
2
|
|
3
|
+
$block-spacing: 25px
|
4
|
+
|
5
|
+
=block-spacing
|
6
|
+
margin-top: $block-spacing
|
7
|
+
margin-bottom: $block-spacing
|
8
|
+
|
3
9
|
body
|
4
10
|
margin: 0
|
5
11
|
background: image-url('grid.png') repeat
|
6
12
|
font-family: arial, sans-serif
|
7
13
|
|
14
|
+
h1, h2, h3, h4, p
|
15
|
+
+block-spacing
|
16
|
+
|
8
17
|
.page
|
9
18
|
min-height: 3000px
|
10
19
|
|
@@ -24,6 +33,11 @@ body
|
|
24
33
|
.example
|
25
34
|
margin: 50px
|
26
35
|
|
36
|
+
.area
|
37
|
+
+block-spacing
|
38
|
+
padding: 25px
|
39
|
+
border: 1px dashed #666
|
40
|
+
|
27
41
|
.button
|
28
42
|
display: inline-block
|
29
43
|
height: 50px
|
@@ -3,4 +3,12 @@ class ApplicationController < ActionController::Base
|
|
3
3
|
# For APIs, you may want to use :null_session instead.
|
4
4
|
protect_from_forgery with: :exception
|
5
5
|
|
6
|
+
before_action :print_authenticity_token
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def print_authenticity_token
|
11
|
+
Rails.logger.info "*** Real token is #{send(:real_csrf_token, session)}"
|
12
|
+
end
|
13
|
+
|
6
14
|
end
|