unpoly-rails 0.31.2 → 0.32.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of unpoly-rails might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +49 -5
- data/README.md +21 -15
- data/README_RAILS.md +2 -2
- data/Rakefile +1 -1
- data/bower.json +4 -3
- data/design/homepage.txt +2 -2
- data/dist/unpoly-bootstrap3.css +3 -0
- data/dist/unpoly-bootstrap3.min.css +1 -1
- data/dist/unpoly.css +4 -4
- data/dist/unpoly.js +114 -80
- data/dist/unpoly.min.css +1 -1
- data/dist/unpoly.min.js +3 -3
- data/lib/assets/javascripts/unpoly/browser.js.coffee +1 -1
- data/lib/assets/javascripts/unpoly/bus.js.coffee +3 -3
- data/lib/assets/javascripts/unpoly/flow.js.coffee +15 -11
- data/lib/assets/javascripts/unpoly/form.js.coffee +1 -1
- data/lib/assets/javascripts/unpoly/layout.js.coffee +12 -9
- data/lib/assets/javascripts/unpoly/link.js.coffee +22 -7
- data/lib/assets/javascripts/unpoly/log.js.coffee +3 -2
- data/lib/assets/javascripts/unpoly/modal.js.coffee +11 -13
- data/lib/assets/javascripts/unpoly/motion.js.coffee +1 -1
- data/lib/assets/javascripts/unpoly/navigation.js.coffee +5 -5
- data/lib/assets/javascripts/unpoly/popup.js.coffee +8 -9
- data/lib/assets/javascripts/unpoly/proxy.js.coffee +2 -2
- data/lib/assets/javascripts/unpoly/syntax.js.coffee +19 -15
- data/lib/assets/javascripts/unpoly/util.js.coffee +19 -3
- data/lib/assets/stylesheets/unpoly-bootstrap3/modal-ext.css.sass +6 -1
- data/lib/assets/stylesheets/unpoly/modal.css.sass +7 -2
- data/lib/unpoly/rails/version.rb +1 -1
- data/package.json +2 -2
- data/spec_app/Gemfile.lock +1 -1
- data/spec_app/app/assets/javascripts/bootstrap_manifest.coffee +2 -2
- data/spec_app/app/views/css_test/modal.erb +4 -0
- data/spec_app/app/views/css_test/modal_contents_wide.erb +5 -0
- data/spec_app/app/views/layouts/integration_test.erb +1 -0
- data/spec_app/spec/javascripts/helpers/knife.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/browser_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/bus_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/flow_spec.js.coffee +63 -5
- data/spec_app/spec/javascripts/up/form_spec.js.coffee +2 -2
- data/spec_app/spec/javascripts/up/history_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/layout_spec.js.coffee +27 -1
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +3 -3
- data/spec_app/spec/javascripts/up/log_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +3 -3
- data/spec_app/spec/javascripts/up/motion_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/popup_spec.js.coffee +21 -3
- data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +1 -1
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +2 -2
- data/spec_app/vendor/assets/bower_components/jasmine-jquery/README.md +2 -2
- data/unpoly-rails.gemspec +1 -1
- metadata +5 -4
@@ -456,7 +456,7 @@ up.util = (($) ->
|
|
456
456
|
###*
|
457
457
|
Returns whether the given argument is an object.
|
458
458
|
|
459
|
-
This also returns `true` for functions, which may behave like objects in
|
459
|
+
This also returns `true` for functions, which may behave like objects in JavaScript.
|
460
460
|
For an alternative that returns `false` for functions, see [`up.util.isHash`](/up.util.isHash).
|
461
461
|
|
462
462
|
@function up.util.isObject
|
@@ -783,7 +783,7 @@ up.util = (($) ->
|
|
783
783
|
|
784
784
|
###*
|
785
785
|
Schedules the given function to be called in the
|
786
|
-
next
|
786
|
+
next JavaScript execution frame.
|
787
787
|
|
788
788
|
@function up.util.nextFrame
|
789
789
|
@param {Function} block
|
@@ -1684,7 +1684,7 @@ up.util = (($) ->
|
|
1684
1684
|
data
|
1685
1685
|
|
1686
1686
|
###*
|
1687
|
-
Throws a [
|
1687
|
+
Throws a [JavaScript error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)
|
1688
1688
|
with the given message.
|
1689
1689
|
|
1690
1690
|
The message will also be printed to the [error log](/up.log.error). Also a notification will be shown at the bottom of the screen.
|
@@ -1905,6 +1905,21 @@ up.util = (($) ->
|
|
1905
1905
|
else
|
1906
1906
|
'right'
|
1907
1907
|
|
1908
|
+
###*
|
1909
|
+
Like `$old.replaceWith($new)`, but keeps event handlers bound to `$old`.
|
1910
|
+
|
1911
|
+
Note that this is a memory leak unless you re-attach `$new` to the DOM aferwards.
|
1912
|
+
|
1913
|
+
@function up.util.detachWith
|
1914
|
+
@internal
|
1915
|
+
###
|
1916
|
+
detachWith = ($old, $new) ->
|
1917
|
+
$insertion = $('<div></div>')
|
1918
|
+
$insertion.insertAfter($old)
|
1919
|
+
$old.detach()
|
1920
|
+
$insertion.replaceWith($new)
|
1921
|
+
$old
|
1922
|
+
|
1908
1923
|
isDetached: isDetached
|
1909
1924
|
requestDataAsArray: requestDataAsArray
|
1910
1925
|
requestDataAsQuery: requestDataAsQuery
|
@@ -2018,6 +2033,7 @@ up.util = (($) ->
|
|
2018
2033
|
previewable: previewable
|
2019
2034
|
evalOption: evalOption
|
2020
2035
|
horizontalScreenHalf: horizontalScreenHalf
|
2036
|
+
detachWith: detachWith
|
2021
2037
|
|
2022
2038
|
)($)
|
2023
2039
|
|
@@ -1,8 +1,13 @@
|
|
1
1
|
.up-modal-content
|
2
2
|
// Unpoly: Gives some default padding
|
3
|
-
//
|
3
|
+
// Bootstrap: Expects content to set the padding
|
4
4
|
padding: 0
|
5
5
|
|
6
|
+
.up-modal-dialog
|
7
|
+
// Unpoly: Dialog margin is a padding of .up-modal-viewport so we can give .up-modal-dialog a max-width of 100%
|
8
|
+
// Bootstrap: Dialog margin is a margin of .modal-dialog
|
9
|
+
margin: 0
|
10
|
+
|
6
11
|
.up-modal[up-flavor='drawer']
|
7
12
|
|
8
13
|
.up-modal-content
|
@@ -50,6 +50,12 @@ $close-font-size: 34px
|
|
50
50
|
// contents of `.up-modal-content`.
|
51
51
|
text-align: center
|
52
52
|
|
53
|
+
// Implement the margin around the dialog box with a padding of the viewport.
|
54
|
+
// This way we can give .up-modal-dialog a max-width of 100%, (1) preventing people
|
55
|
+
// from setting withs larger than the viewport, and (2) sizing approproately
|
56
|
+
// if the modal contents are very wide and cannot wrap (e.g. code blocks).
|
57
|
+
padding: 30px 10px
|
58
|
+
|
53
59
|
.up-modal.up-modal-animating
|
54
60
|
// During opening/closing animations we let the .up-modal container take over
|
55
61
|
// the scrollbars that would usually be owned by .up-modal-viewport.
|
@@ -68,7 +74,6 @@ $close-font-size: 34px
|
|
68
74
|
// the width and height attributes set by up.modal
|
69
75
|
// should be honored exactly.
|
70
76
|
box-sizing: border-box
|
71
|
-
margin: 30px 10px
|
72
77
|
|
73
78
|
// In case someone sets a huge width on the dialog.
|
74
79
|
max-width: 100%
|
@@ -99,10 +104,10 @@ $close-font-size: 34px
|
|
99
104
|
.up-modal[up-flavor='drawer']
|
100
105
|
.up-modal-viewport
|
101
106
|
text-align: left
|
107
|
+
padding: 0
|
102
108
|
&[up-position='right'] .up-modal-viewport
|
103
109
|
text-align: right
|
104
110
|
.up-modal-dialog
|
105
|
-
margin: 0
|
106
111
|
max-width: 350px
|
107
112
|
.up-modal-content
|
108
113
|
min-height: 100vh
|
data/lib/unpoly/rails/version.rb
CHANGED
data/package.json
CHANGED
data/spec_app/Gemfile.lock
CHANGED
@@ -2,5 +2,5 @@
|
|
2
2
|
|
3
3
|
# From the docs (https://github.com/twbs/bootstrap-sass):
|
4
4
|
# bootstrap-sprockets and bootstrap should not both be included in application.js.
|
5
|
-
# bootstrap-sprockets provides individual Bootstrap
|
6
|
-
# while bootstrap provides a concatenated file containing all Bootstrap
|
5
|
+
# bootstrap-sprockets provides individual Bootstrap JavaScript files (alert.js or dropdown.js, for example),
|
6
|
+
# while bootstrap provides a concatenated file containing all Bootstrap JavaScripts.
|
@@ -2,6 +2,10 @@
|
|
2
2
|
<a class="button" href="/css_test/modal_contents" up-modal=".contents">Modal</a>
|
3
3
|
</div>
|
4
4
|
|
5
|
+
<div class="example">
|
6
|
+
<a class="button" href="/css_test/modal_contents_wide" up-modal=".contents">Modal (wide contents)</a>
|
7
|
+
</div>
|
8
|
+
|
5
9
|
<div class="example">
|
6
10
|
<a class="button" href="/css_test/modal_contents" up-drawer=".contents" style="float: left">Drawer (auto)</a>
|
7
11
|
<a class="button" href="/css_test/modal_contents" up-drawer=".contents" style="float: right">Drawer (auto)</a>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
##
|
2
|
-
# Knife: Get, set or mock inaccessible variables in a
|
2
|
+
# Knife: Get, set or mock inaccessible variables in a JavaScript closure
|
3
3
|
# ======================================================================
|
4
4
|
#
|
5
5
|
# Requires [Jasmine](http://jasmine.github.io/) 2+.
|
@@ -2,7 +2,7 @@ describe 'up.flow', ->
|
|
2
2
|
|
3
3
|
u = up.util
|
4
4
|
|
5
|
-
describe '
|
5
|
+
describe 'JavaScript functions', ->
|
6
6
|
|
7
7
|
describe 'up.replace', ->
|
8
8
|
|
@@ -493,10 +493,12 @@ describe 'up.flow', ->
|
|
493
493
|
beforeEach ->
|
494
494
|
@revealedHTML = []
|
495
495
|
@revealedText = []
|
496
|
+
@revealOptions = {}
|
496
497
|
|
497
|
-
@revealMock = up.layout.knife.mock('reveal').and.callFake ($
|
498
|
-
@revealedHTML.push $
|
499
|
-
@revealedText.push $
|
498
|
+
@revealMock = up.layout.knife.mock('reveal').and.callFake ($element, options) =>
|
499
|
+
@revealedHTML.push $element.get(0).outerHTML
|
500
|
+
@revealedText.push $element.text().trim()
|
501
|
+
@revealOptions = options
|
500
502
|
u.resolvedDeferred()
|
501
503
|
|
502
504
|
it 'reveals a new element before it is being replaced', (done) ->
|
@@ -519,7 +521,7 @@ describe 'up.flow', ->
|
|
519
521
|
|
520
522
|
describe 'when there is an anchor #hash in the URL', ->
|
521
523
|
|
522
|
-
it '
|
524
|
+
it 'scrolls to the top of a child with the ID of that #hash', (done) ->
|
523
525
|
promise = up.replace('.middle', '/path#three', reveal: true)
|
524
526
|
@responseText =
|
525
527
|
"""
|
@@ -532,6 +534,7 @@ describe 'up.flow', ->
|
|
532
534
|
@respond()
|
533
535
|
promise.then =>
|
534
536
|
expect(@revealedHTML).toEqual ['<div id="three">three</div>']
|
537
|
+
expect(@revealOptions).toEqual { top: true }
|
535
538
|
done()
|
536
539
|
|
537
540
|
it "reveals the entire element if it has no child with the ID of that #hash", (done) ->
|
@@ -794,34 +797,67 @@ describe 'up.flow', ->
|
|
794
797
|
expect(keptListener).toHaveBeenCalledWith(jasmine.anything(), $('.keeper'), jasmine.anything())
|
795
798
|
|
796
799
|
it "removes an [up-keep] element if no matching element is found in the response", ->
|
800
|
+
barCompiler = jasmine.createSpy()
|
801
|
+
barDestructor = jasmine.createSpy()
|
802
|
+
up.compiler '.bar', ($bar) ->
|
803
|
+
text = $bar.text()
|
804
|
+
barCompiler(text)
|
805
|
+
return -> barDestructor(text)
|
806
|
+
|
797
807
|
$container = affix('.container')
|
798
808
|
$container.html """
|
799
809
|
<div class='foo'>old-foo</div>
|
800
810
|
<div class='bar' up-keep>old-bar</div>
|
801
811
|
"""
|
812
|
+
up.hello($container)
|
813
|
+
|
814
|
+
expect(barCompiler.calls.allArgs()).toEqual [['old-bar']]
|
815
|
+
expect(barDestructor.calls.allArgs()).toEqual []
|
816
|
+
|
802
817
|
up.extract '.container', """
|
803
818
|
<div class='container'>
|
804
819
|
<div class='foo'>new-foo</div>
|
805
820
|
</div>
|
806
821
|
"""
|
822
|
+
|
807
823
|
expect($('.container .foo')).toExist()
|
808
824
|
expect($('.container .bar')).not.toExist()
|
809
825
|
|
826
|
+
expect(barCompiler.calls.allArgs()).toEqual [['old-bar']]
|
827
|
+
expect(barDestructor.calls.allArgs()).toEqual [['old-bar']]
|
828
|
+
|
810
829
|
it "updates an element if a matching element is found in the response, but that other element is no longer [up-keep]", ->
|
830
|
+
barCompiler = jasmine.createSpy()
|
831
|
+
barDestructor = jasmine.createSpy()
|
832
|
+
up.compiler '.bar', ($bar) ->
|
833
|
+
text = $bar.text()
|
834
|
+
console.info('Compiling %o', text)
|
835
|
+
barCompiler(text)
|
836
|
+
return -> barDestructor(text)
|
837
|
+
|
811
838
|
$container = affix('.container')
|
812
839
|
$container.html """
|
813
840
|
<div class='foo'>old-foo</div>
|
814
841
|
<div class='bar' up-keep>old-bar</div>
|
815
842
|
"""
|
843
|
+
up.hello($container)
|
844
|
+
|
845
|
+
expect(barCompiler.calls.allArgs()).toEqual [['old-bar']]
|
846
|
+
expect(barDestructor.calls.allArgs()).toEqual []
|
847
|
+
|
816
848
|
up.extract '.container', """
|
817
849
|
<div class='container'>
|
818
850
|
<div class='foo'>new-foo</div>
|
819
851
|
<div class='bar'>new-bar</div>
|
820
852
|
</div>
|
821
853
|
"""
|
854
|
+
|
822
855
|
expect($('.container .foo')).toHaveText('new-foo')
|
823
856
|
expect($('.container .bar')).toHaveText('new-bar')
|
824
857
|
|
858
|
+
expect(barCompiler.calls.allArgs()).toEqual [['old-bar'], ['new-bar']]
|
859
|
+
expect(barDestructor.calls.allArgs()).toEqual [['old-bar']]
|
860
|
+
|
825
861
|
it 'moves a kept element to the ancestry position of the matching element in the response', ->
|
826
862
|
$container = affix('.container')
|
827
863
|
$container.html """
|
@@ -874,6 +910,28 @@ describe 'up.flow', ->
|
|
874
910
|
expect(compiler.calls.count()).toEqual(1)
|
875
911
|
expect('.keeper').toExist()
|
876
912
|
|
913
|
+
it 'does not lose jQuery event handlers on a kept element (bugfix)', ->
|
914
|
+
handler = jasmine.createSpy('event handler')
|
915
|
+
up.compiler '.keeper', ($keeper) ->
|
916
|
+
$keeper.on 'click', handler
|
917
|
+
|
918
|
+
$container = affix('.container')
|
919
|
+
$container.html """
|
920
|
+
<div class="keeper" up-keep>old-text</div>
|
921
|
+
"""
|
922
|
+
up.hello($container)
|
923
|
+
|
924
|
+
up.extract '.container', """
|
925
|
+
<div class='container'>
|
926
|
+
<div class="keeper" up-keep>new-text</div>
|
927
|
+
</div>
|
928
|
+
"""
|
929
|
+
|
930
|
+
$keeper = $('.keeper')
|
931
|
+
expect($keeper).toHaveText('old-text')
|
932
|
+
Trigger.click($keeper)
|
933
|
+
expect(handler).toHaveBeenCalled()
|
934
|
+
|
877
935
|
it 'lets listeners cancel the keeping by preventing default on an up:fragment:keep event', ->
|
878
936
|
$keeper = affix('.keeper[up-keep]').text('old-inside')
|
879
937
|
$keeper.on 'up:fragment:keep', (event) -> event.preventDefault()
|
@@ -2,7 +2,7 @@ describe 'up.form', ->
|
|
2
2
|
|
3
3
|
u = up.util
|
4
4
|
|
5
|
-
describe '
|
5
|
+
describe 'JavaScript functions', ->
|
6
6
|
|
7
7
|
describe 'up.observe', ->
|
8
8
|
|
@@ -419,7 +419,7 @@ describe 'up.form', ->
|
|
419
419
|
afterEach ->
|
420
420
|
window.observeCallbackSpy = undefined
|
421
421
|
|
422
|
-
it 'runs the
|
422
|
+
it 'runs the JavaScript code in the attribute value when a change is observed in the field', (done) ->
|
423
423
|
$form = affix('form')
|
424
424
|
window.observeCallbackSpy = jasmine.createSpy('observe callback')
|
425
425
|
$field = $form.affix('input[val="old-value"][up-observe="window.observeCallbackSpy(value, $field.get(0))"]')
|
@@ -2,7 +2,7 @@ describe 'up.layout', ->
|
|
2
2
|
|
3
3
|
u = up.util
|
4
4
|
|
5
|
-
describe '
|
5
|
+
describe 'JavaScript functions', ->
|
6
6
|
|
7
7
|
describe 'up.reveal', ->
|
8
8
|
|
@@ -78,6 +78,18 @@ describe 'up.layout', ->
|
|
78
78
|
# [2] 70 ......... 5069
|
79
79
|
expect($(document).scrollTop()).toBe(0)
|
80
80
|
|
81
|
+
it 'does not snap to the top if it would un-reveal an element at the bottom edge of the screen (bugfix)', ->
|
82
|
+
up.layout.config.snap = 100
|
83
|
+
|
84
|
+
up.reveal(@$elements[1])
|
85
|
+
# ---------------------
|
86
|
+
# [0] 0 .......... ch-1
|
87
|
+
# [1] ch+0 ...... ch+49
|
88
|
+
# ---------------------
|
89
|
+
# [2] ch+50 ... ch+5049
|
90
|
+
expect($(document).scrollTop()).toBe(50)
|
91
|
+
|
92
|
+
|
81
93
|
it 'scrolls far enough so the element is not obstructed by an element fixed to the top', ->
|
82
94
|
$topNav = affix('[up-fixed=top]').css(
|
83
95
|
position: 'fixed',
|
@@ -161,6 +173,20 @@ describe 'up.layout', ->
|
|
161
173
|
# [F] 0 ............ 99
|
162
174
|
expect($(document).scrollTop()).toBe(@clientHeight + 50)
|
163
175
|
|
176
|
+
describe 'with { top: true } option', ->
|
177
|
+
|
178
|
+
it 'scrolls the viewport to the first row of the element, even if that element is already fully revealed', ->
|
179
|
+
|
180
|
+
@$elements[0].css(height: '20px')
|
181
|
+
|
182
|
+
up.reveal(@$elements[1], { top: true })
|
183
|
+
# [0] 0 ............ 19
|
184
|
+
# [1] 20 ........... 69
|
185
|
+
# ---------------------
|
186
|
+
# [2] 70 ......... 5069
|
187
|
+
# ---------------------
|
188
|
+
expect($(document).scrollTop()).toBe(20)
|
189
|
+
|
164
190
|
|
165
191
|
describe 'when the viewport is a container with overflow-y: scroll', ->
|
166
192
|
|
@@ -2,7 +2,7 @@ describe 'up.link', ->
|
|
2
2
|
|
3
3
|
u = up.util
|
4
4
|
|
5
|
-
describe '
|
5
|
+
describe 'JavaScript functions', ->
|
6
6
|
|
7
7
|
describe 'up.follow', ->
|
8
8
|
|
@@ -462,7 +462,7 @@ describe 'up.link', ->
|
|
462
462
|
Trigger.click(@$link)
|
463
463
|
expect(@followSpy).toHaveBeenCalledWith(@$link)
|
464
464
|
|
465
|
-
# IE does not call
|
465
|
+
# IE does not call JavaScript and always performs the default action on right clicks
|
466
466
|
unless navigator.userAgent.match(/Trident/)
|
467
467
|
it 'does nothing if the right mouse button is used', ->
|
468
468
|
Trigger.click(@$link, button: 2)
|
@@ -497,7 +497,7 @@ describe 'up.link', ->
|
|
497
497
|
Trigger.click(@$link)
|
498
498
|
expect(@followSpy).not.toHaveBeenCalled()
|
499
499
|
|
500
|
-
# IE does not call
|
500
|
+
# IE does not call JavaScript and always performs the default action on right clicks
|
501
501
|
unless navigator.userAgent.match(/Trident/)
|
502
502
|
it 'does nothing if the right mouse button is pressed down', ->
|
503
503
|
Trigger.mousedown(@$link, button: 2)
|