unpoly-rails 0.60.2 → 0.62.1
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/.ruby-version +1 -2
- data/CHANGELOG.md +105 -0
- data/Rakefile +5 -1
- data/dist/unpoly.js +199 -80
- data/dist/unpoly.min.js +4 -4
- data/lib/assets/javascripts/unpoly/browser.coffee.erb +10 -5
- data/lib/assets/javascripts/unpoly/classes/body_shifter.coffee +21 -12
- data/lib/assets/javascripts/unpoly/classes/compile_pass.coffee +2 -2
- data/lib/assets/javascripts/unpoly/classes/event_listener.coffee +1 -1
- data/lib/assets/javascripts/unpoly/classes/follow_variant.coffee +11 -3
- data/lib/assets/javascripts/unpoly/classes/params.coffee.erb +2 -1
- data/lib/assets/javascripts/unpoly/element.coffee.erb +4 -4
- data/lib/assets/javascripts/unpoly/event.coffee.erb +12 -4
- data/lib/assets/javascripts/unpoly/form.coffee.erb +77 -15
- data/lib/assets/javascripts/unpoly/fragment.coffee.erb +7 -3
- data/lib/assets/javascripts/unpoly/link.coffee.erb +1 -1
- data/lib/assets/javascripts/unpoly/modal.coffee.erb +4 -2
- data/lib/assets/javascripts/unpoly/motion.coffee.erb +1 -1
- data/lib/assets/javascripts/unpoly/protocol.coffee +1 -1
- data/lib/assets/javascripts/unpoly/syntax.coffee.erb +3 -4
- data/lib/assets/javascripts/unpoly/util.coffee.erb +2 -1
- data/lib/assets/javascripts/unpoly/viewport.coffee.erb +26 -2
- data/lib/unpoly/rails/version.rb +1 -1
- data/package.json +1 -1
- data/spec_app/Gemfile +2 -4
- data/spec_app/Gemfile.lock +23 -27
- data/spec_app/app/views/css_test/modal.erb +1 -1
- data/spec_app/app/views/css_test/popup.erb +1 -1
- data/spec_app/app/views/pages/start.erb +2 -1
- data/spec_app/app/views/replace_test/table.erb +16 -0
- data/spec_app/spec/javascripts/up/event_spec.js.coffee +34 -0
- data/spec_app/spec/javascripts/up/form_spec.js.coffee +137 -9
- data/spec_app/spec/javascripts/up/fragment_spec.js.coffee +36 -1
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +7 -2
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +23 -1
- data/spec_app/spec/javascripts/up/popup_spec.js.coffee +2 -1
- data/spec_app/spec/javascripts/up/util_spec.js.coffee +14 -0
- metadata +4 -4
@@ -250,6 +250,7 @@ up.modal = do ->
|
|
250
250
|
createHiddenFrame = (target, options) ->
|
251
251
|
html = templateHtml()
|
252
252
|
state.modalElement = modalElement = e.createFromHtml(html)
|
253
|
+
modalElement.setAttribute('aria-modal', 'true') # tell modern screen readers to make all other elements inert
|
253
254
|
modalElement.setAttribute('up-flavor', state.flavor)
|
254
255
|
modalElement.setAttribute('up-position', state.position) if u.isPresent(state.position)
|
255
256
|
|
@@ -288,7 +289,7 @@ up.modal = do ->
|
|
288
289
|
var link = document.querySelector('a')
|
289
290
|
up.modal.follow(link)
|
290
291
|
|
291
|
-
Any option attributes for [`a[up-modal]`](/a
|
292
|
+
Any option attributes for [`a[up-modal]`](/a-up-modal) will be honored.
|
292
293
|
|
293
294
|
Emits events [`up:modal:open`](/up:modal:open) and [`up:modal:opened`](/up:modal:opened).
|
294
295
|
|
@@ -436,6 +437,7 @@ up.modal = do ->
|
|
436
437
|
options.layer = 'modal'
|
437
438
|
options.failTarget ?= link.getAttribute('up-fail-target')
|
438
439
|
options.failLayer ?= link.getAttribute('up-fail-layer') ? 'auto'
|
440
|
+
options.cache ?= e.booleanAttr(link, 'up-cache')
|
439
441
|
|
440
442
|
animateOptions = up.motion.animateOptions(options, link, duration: flavorDefault('openDuration', options.flavor), easing: flavorDefault('openEasing', options.flavor))
|
441
443
|
|
@@ -650,7 +652,7 @@ up.modal = do ->
|
|
650
652
|
|
651
653
|
Clicking would request the path `/blog` and select `.blog-list` from
|
652
654
|
the HTML response. Unpoly will dim the page
|
653
|
-
and place the matching `.blog-list` tag
|
655
|
+
and place the matching `.blog-list` tag in
|
654
656
|
a modal dialog.
|
655
657
|
|
656
658
|
@selector a[up-modal]
|
@@ -246,7 +246,7 @@ up.protocol = do ->
|
|
246
246
|
The parameter name can be configured as a string or as function that returns the parameter name.
|
247
247
|
If no name is set, no token will be sent.
|
248
248
|
|
249
|
-
Defaults to the `content` attribute of a `<meta>` tag named `csrf-
|
249
|
+
Defaults to the `content` attribute of a `<meta>` tag named `csrf-param`:
|
250
250
|
|
251
251
|
<meta name="csrf-param" content="authenticity_token" />
|
252
252
|
|
@@ -215,7 +215,7 @@ up.syntax = do ->
|
|
215
215
|
###**
|
216
216
|
Registers a [compiler](/up.compiler) that is run before all other compilers.
|
217
217
|
|
218
|
-
Use `up.macro()` to register a compiler that sets
|
218
|
+
Use `up.macro()` to register a compiler that sets multiple Unpoly attributes.
|
219
219
|
|
220
220
|
\#\#\# Example
|
221
221
|
|
@@ -373,10 +373,9 @@ up.syntax = do ->
|
|
373
373
|
clean = (fragment) ->
|
374
374
|
cleanables = e.subtree(fragment, '.up-can-clean')
|
375
375
|
u.each cleanables, (cleanable) ->
|
376
|
-
if destructors = cleanable
|
376
|
+
if destructors = u.pluckKey(cleanable, 'upDestructors')
|
377
377
|
destructor() for destructor in destructors
|
378
|
-
|
379
|
-
# The element we just cleaned is about to be removed from the DOM.
|
378
|
+
cleanable.classList.remove('up-can-clean')
|
380
379
|
|
381
380
|
###**
|
382
381
|
Checks if the given element has an [`up-data`](/up-data) attribute.
|
@@ -499,7 +499,8 @@ up.util = do ->
|
|
499
499
|
@stable
|
500
500
|
###
|
501
501
|
isJQuery = (object) ->
|
502
|
-
|
502
|
+
# We cannot do `object instanceof jQuery` since window.jQuery might not be set
|
503
|
+
!!object?.jquery
|
503
504
|
|
504
505
|
###**
|
505
506
|
Returns whether the given argument is an object with a `then` method.
|
@@ -506,13 +506,37 @@ up.viewport = do ->
|
|
506
506
|
|
507
507
|
The scroll positions will be associated with the current URL.
|
508
508
|
They can later be restored by calling [`up.viewport.restoreScroll()`](/up.viewport.restoreScroll)
|
509
|
-
at the same URL
|
509
|
+
at the same URL, or by following a link with an [`[up-restore-scroll]`](/a-up-follow#up-restore-scroll)
|
510
|
+
attribute.
|
510
511
|
|
511
|
-
Unpoly automatically saves scroll positions
|
512
|
+
Unpoly automatically saves scroll positions before a [fragment update](/up.replace)
|
513
|
+
you will rarely need to call this function yourself.
|
514
|
+
|
515
|
+
\#\#\# Examples
|
516
|
+
|
517
|
+
Should you need to save the current scroll positions outside of a [fragment update](/up.replace),
|
518
|
+
you may call:
|
519
|
+
|
520
|
+
up.viewport.saveScroll()
|
521
|
+
|
522
|
+
Instead of saving the current scroll positions for the current URL, you may also pass another
|
523
|
+
url or vertical scroll positionsfor each viewport:
|
524
|
+
|
525
|
+
up.viewport.saveScroll({
|
526
|
+
url: '/inbox',
|
527
|
+
tops: {
|
528
|
+
'body': 0,
|
529
|
+
'.sidebar', 100,
|
530
|
+
'.main', 320
|
531
|
+
}
|
532
|
+
})
|
512
533
|
|
513
534
|
@function up.viewport.saveScroll
|
514
535
|
@param {string} [options.url]
|
536
|
+
The URL for which to save scroll positions.
|
537
|
+
If omitted, the current browser location is used.
|
515
538
|
@param {Object<string, number>} [options.tops]
|
539
|
+
An object mapping viewport selectors to vertical scroll positions in pixels.
|
516
540
|
@experimental
|
517
541
|
###
|
518
542
|
saveScroll = (options = {}) ->
|
data/lib/unpoly/rails/version.rb
CHANGED
data/package.json
CHANGED
data/spec_app/Gemfile
CHANGED
@@ -14,11 +14,9 @@ gem 'bower-rails'
|
|
14
14
|
gem 'bootstrap-sass', '~> 3.3'
|
15
15
|
gem 'rake', '< 11'
|
16
16
|
|
17
|
-
# Jasmine spec runner won't boot with a more modern version of sprockets.
|
18
|
-
# It crashes with an "asset not precompiled" error.
|
19
17
|
gem 'tilt', '=1.4.1'
|
20
|
-
gem 'sprockets-rails', '
|
21
|
-
gem 'sprockets', '
|
18
|
+
gem 'sprockets-rails', '~> 3.2.1'
|
19
|
+
gem 'sprockets', '~> 3.7.2'
|
22
20
|
|
23
21
|
group :development, :test do
|
24
22
|
gem 'byebug'
|
data/spec_app/Gemfile.lock
CHANGED
@@ -12,7 +12,7 @@ GIT
|
|
12
12
|
PATH
|
13
13
|
remote: ..
|
14
14
|
specs:
|
15
|
-
unpoly-rails (0.
|
15
|
+
unpoly-rails (0.62.0)
|
16
16
|
rails (>= 3)
|
17
17
|
|
18
18
|
GEM
|
@@ -62,7 +62,7 @@ GEM
|
|
62
62
|
autoprefixer-rails (>= 5.2.1)
|
63
63
|
sass (>= 3.3.4)
|
64
64
|
bower-rails (0.9.2)
|
65
|
-
builder (3.2.
|
65
|
+
builder (3.2.4)
|
66
66
|
byebug (3.5.1)
|
67
67
|
columnize (~> 0.8)
|
68
68
|
debugger-linecache (~> 1.2)
|
@@ -75,8 +75,8 @@ GEM
|
|
75
75
|
execjs
|
76
76
|
coffee-script-source (1.12.2)
|
77
77
|
columnize (0.9.0)
|
78
|
-
concurrent-ruby (1.1.
|
79
|
-
crass (1.0.
|
78
|
+
concurrent-ruby (1.1.6)
|
79
|
+
crass (1.0.6)
|
80
80
|
debug_inspector (0.0.2)
|
81
81
|
debugger-linecache (1.2.0)
|
82
82
|
diff-lcs (1.2.5)
|
@@ -92,7 +92,6 @@ GEM
|
|
92
92
|
haml (>= 3.1, < 5.0)
|
93
93
|
html2haml (>= 1.0.1)
|
94
94
|
railties (>= 4.0.1)
|
95
|
-
hike (1.2.3)
|
96
95
|
hpricot (0.8.6)
|
97
96
|
html2haml (1.0.1)
|
98
97
|
erubis (~> 2.7.0)
|
@@ -102,25 +101,24 @@ GEM
|
|
102
101
|
i18n (0.9.5)
|
103
102
|
concurrent-ruby (~> 1.0)
|
104
103
|
jasmine-core (2.99.2)
|
105
|
-
jquery-rails (4.3.
|
104
|
+
jquery-rails (4.3.5)
|
106
105
|
rails-dom-testing (>= 1, < 3)
|
107
106
|
railties (>= 4.2.0)
|
108
107
|
thor (>= 0.14, < 2.0)
|
109
108
|
json (1.8.6)
|
110
109
|
libv8 (3.16.14.3)
|
111
|
-
loofah (2.
|
110
|
+
loofah (2.4.0)
|
112
111
|
crass (~> 1.0.2)
|
113
112
|
nokogiri (>= 1.5.9)
|
114
113
|
mail (2.6.3)
|
115
114
|
mime-types (>= 1.16, < 3)
|
116
115
|
mime-types (2.99)
|
117
116
|
mini_portile2 (2.4.0)
|
118
|
-
minitest (5.
|
119
|
-
|
120
|
-
nokogiri (1.9.1)
|
117
|
+
minitest (5.14.0)
|
118
|
+
nokogiri (1.10.9)
|
121
119
|
mini_portile2 (~> 2.4.0)
|
122
120
|
phantomjs (2.1.1.0)
|
123
|
-
rack (1.6.
|
121
|
+
rack (1.6.13)
|
124
122
|
rack-test (0.6.3)
|
125
123
|
rack (>= 1.0)
|
126
124
|
rails (4.2.0)
|
@@ -140,8 +138,8 @@ GEM
|
|
140
138
|
activesupport (>= 4.2.0, < 5.0)
|
141
139
|
nokogiri (~> 1.6)
|
142
140
|
rails-deprecated_sanitizer (>= 1.0.1)
|
143
|
-
rails-html-sanitizer (1.0
|
144
|
-
loofah (~> 2.
|
141
|
+
rails-html-sanitizer (1.3.0)
|
142
|
+
loofah (~> 2.3)
|
145
143
|
railties (4.2.0)
|
146
144
|
actionpack (= 4.2.0)
|
147
145
|
activesupport (= 4.2.0)
|
@@ -177,23 +175,21 @@ GEM
|
|
177
175
|
tilt (>= 1.1, < 3)
|
178
176
|
sexp_processor (4.4.4)
|
179
177
|
slop (3.6.0)
|
180
|
-
sprockets (
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
activesupport (>= 3.0)
|
188
|
-
sprockets (>= 2.8, < 4.0)
|
178
|
+
sprockets (3.7.2)
|
179
|
+
concurrent-ruby (~> 1.0)
|
180
|
+
rack (> 1, < 3)
|
181
|
+
sprockets-rails (3.2.1)
|
182
|
+
actionpack (>= 4.0)
|
183
|
+
activesupport (>= 4.0)
|
184
|
+
sprockets (>= 3.0.0)
|
189
185
|
sqlite3 (1.3.10)
|
190
186
|
therubyracer (0.12.1)
|
191
187
|
libv8 (~> 3.16.14.0)
|
192
188
|
ref
|
193
|
-
thor (0.
|
189
|
+
thor (1.0.1)
|
194
190
|
thread_safe (0.3.6)
|
195
191
|
tilt (1.4.1)
|
196
|
-
tzinfo (1.2.
|
192
|
+
tzinfo (1.2.7)
|
197
193
|
thread_safe (~> 0.1)
|
198
194
|
uglifier (2.6.0)
|
199
195
|
execjs (>= 0.3.0)
|
@@ -220,8 +216,8 @@ DEPENDENCIES
|
|
220
216
|
rake (< 11)
|
221
217
|
rspec-rails
|
222
218
|
sass-rails (~> 5.0)
|
223
|
-
sprockets (
|
224
|
-
sprockets-rails (
|
219
|
+
sprockets (~> 3.7.2)
|
220
|
+
sprockets-rails (~> 3.2.1)
|
225
221
|
sqlite3
|
226
222
|
therubyracer
|
227
223
|
tilt (= 1.4.1)
|
@@ -230,4 +226,4 @@ DEPENDENCIES
|
|
230
226
|
web-console (~> 2.0)
|
231
227
|
|
232
228
|
BUNDLED WITH
|
233
|
-
1.
|
229
|
+
1.17.3
|
@@ -63,7 +63,8 @@
|
|
63
63
|
<li><%= link_to 'Form (redirect)', '/form_test/redirect/new' %></li>
|
64
64
|
<li><%= link_to 'Error', '/error_test/trigger' %></li>
|
65
65
|
<li><%= link_to 'Booting with non-GET method', '/method_test/page1' %></li>
|
66
|
-
<li><%= link_to 'Fragment update', '/replace_test/page1' %></li>
|
66
|
+
<li><%= link_to 'Fragment update (basic)', '/replace_test/page1' %></li>
|
67
|
+
<li><%= link_to 'Fragment update (table)', '/replace_test/table' %></li>
|
67
68
|
<li><%= link_to 'Hash links (without Unpoly)', '/hash_test/vanilla#one' %></li>
|
68
69
|
<li><%= link_to 'Hash links (with Unpoly)', '/hash_test/unpoly#one' %></li>
|
69
70
|
<li><%= link_to 'Revealing content in an overflowing <div> ', '/reveal_test/within_overflowing_div_viewport' %></li>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<table>
|
2
|
+
<tbody>
|
3
|
+
<tr id="one">
|
4
|
+
<td><%= Time.now %></td>
|
5
|
+
<td><a href="table" up-target="#one">Replace this row</a></td>
|
6
|
+
</tr>
|
7
|
+
<tr id="two">
|
8
|
+
<td><%= Time.now %></td>
|
9
|
+
<td><a href="table" up-target="#two">Replace this row</a></td>
|
10
|
+
</tr>
|
11
|
+
<tr id="three">
|
12
|
+
<td><%= Time.now %></td>
|
13
|
+
<td><a href="table" up-target="#three">Replace this row</a></td>
|
14
|
+
</tr>
|
15
|
+
</tbody>
|
16
|
+
</table>
|
@@ -494,3 +494,37 @@ describe 'up.event', ->
|
|
494
494
|
promiseState(promise).then (result) ->
|
495
495
|
expect(result.state).toEqual('rejected')
|
496
496
|
done()
|
497
|
+
|
498
|
+
describe 'up.event.halt', ->
|
499
|
+
|
500
|
+
it 'stops propagation of the given event to other event listeners on the same element', ->
|
501
|
+
otherListenerBefore = jasmine.createSpy()
|
502
|
+
otherListenerAfter = jasmine.createSpy()
|
503
|
+
element = fixture('div')
|
504
|
+
|
505
|
+
element.addEventListener('foo', otherListenerBefore)
|
506
|
+
element.addEventListener('foo', up.event.halt)
|
507
|
+
element.addEventListener('foo', otherListenerAfter)
|
508
|
+
|
509
|
+
up.emit(element, 'foo')
|
510
|
+
|
511
|
+
expect(otherListenerBefore).toHaveBeenCalled()
|
512
|
+
expect(otherListenerAfter).not.toHaveBeenCalled()
|
513
|
+
|
514
|
+
it 'stops the event from bubbling up the document tree', ->
|
515
|
+
parent = fixture('div')
|
516
|
+
element = e.affix(parent, 'div')
|
517
|
+
parentListener = jasmine.createSpy()
|
518
|
+
parent.addEventListener('foo', parentListener)
|
519
|
+
element.addEventListener('foo', up.event.halt)
|
520
|
+
|
521
|
+
up.emit(element, 'foo')
|
522
|
+
|
523
|
+
expect(parentListener).not.toHaveBeenCalled()
|
524
|
+
|
525
|
+
it 'prevents default on the event', ->
|
526
|
+
element = fixture('div')
|
527
|
+
element.addEventListener('foo', up.event.halt)
|
528
|
+
event = up.emit(element, 'foo')
|
529
|
+
expect(event.defaultPrevented).toBe(true)
|
530
|
+
|
@@ -6,6 +6,47 @@ describe 'up.form', ->
|
|
6
6
|
|
7
7
|
describe 'JavaScript functions', ->
|
8
8
|
|
9
|
+
describe 'up.form.fields', ->
|
10
|
+
|
11
|
+
it 'returns a list of form fields within the given element', ->
|
12
|
+
form = fixture('form')
|
13
|
+
textField = e.affix(form, 'input[type=text]')
|
14
|
+
select = e.affix(form, 'select')
|
15
|
+
results = up.form.fields(form)
|
16
|
+
expect(results).toMatchList([textField, select])
|
17
|
+
|
18
|
+
it 'returns an empty list if the given element contains no form fields', ->
|
19
|
+
form = fixture('form')
|
20
|
+
results = up.form.fields(form)
|
21
|
+
expect(results).toMatchList([])
|
22
|
+
|
23
|
+
it 'returns a list of the given element if the element is itself a form field', ->
|
24
|
+
textArea = fixture('textarea')
|
25
|
+
results = up.form.fields(textArea)
|
26
|
+
expect(results).toMatchList([textArea])
|
27
|
+
|
28
|
+
it 'ignores fields outside the given form', ->
|
29
|
+
form1 = fixture('form')
|
30
|
+
form1Field = e.affix(form1, 'input[type=text]')
|
31
|
+
form2 = fixture('form')
|
32
|
+
form2Field = e.affix(form2, 'input[type=text]')
|
33
|
+
results = up.form.fields(form1)
|
34
|
+
expect(results).toMatchList([form1Field])
|
35
|
+
|
36
|
+
it "includes fields outside the form with a [form] attribute matching the given form's ID", ->
|
37
|
+
form = fixture('form#form-id')
|
38
|
+
insideField = e.affix(form, 'input[type=text]')
|
39
|
+
outsideField = fixture('input[type=text][form=form-id]')
|
40
|
+
results = up.form.fields(form)
|
41
|
+
expect(results).toMatchList([insideField, outsideField])
|
42
|
+
|
43
|
+
it "does not return duplicate fields if a field with a matching [form] attribute is also a child of the form", ->
|
44
|
+
form = fixture('form#form-id')
|
45
|
+
field = e.affix(form, 'input[type=text][form=form-id]')
|
46
|
+
results = up.form.fields(form)
|
47
|
+
expect(results).toMatchList([field])
|
48
|
+
|
49
|
+
|
9
50
|
describe 'up.observe', ->
|
10
51
|
|
11
52
|
beforeEach ->
|
@@ -858,6 +899,23 @@ describe 'up.form', ->
|
|
858
899
|
Trigger.change($field)
|
859
900
|
next => expect(submitSpy).toHaveBeenCalled()
|
860
901
|
|
902
|
+
it 'submits the form when a change is observed on a container for a radio button group', asyncSpec (next) ->
|
903
|
+
form = fixture('form')
|
904
|
+
group = e.affix(form, '.group[up-autosubmit][up-delay=0]')
|
905
|
+
radio1 = e.affix(group, 'input[type=radio][name=foo][value=1]')
|
906
|
+
radio2 = e.affix(group, 'input[type=radio][name=foo][value=2]')
|
907
|
+
up.hello(form)
|
908
|
+
submitSpy = up.form.knife.mock('submit').and.returnValue(Promise.reject())
|
909
|
+
Trigger.clickSequence(radio1)
|
910
|
+
next =>
|
911
|
+
expect(submitSpy.calls.count()).toBe(1)
|
912
|
+
Trigger.clickSequence(radio2)
|
913
|
+
next =>
|
914
|
+
expect(submitSpy.calls.count()).toBe(2)
|
915
|
+
Trigger.clickSequence(radio1)
|
916
|
+
next =>
|
917
|
+
expect(submitSpy.calls.count()).toBe(3)
|
918
|
+
|
861
919
|
describe 'form[up-autosubmit]', ->
|
862
920
|
|
863
921
|
it 'submits the form when a change is observed in any of its fields', asyncSpec (next) ->
|
@@ -1013,16 +1071,17 @@ describe 'up.form', ->
|
|
1013
1071
|
container.innerHTML = """
|
1014
1072
|
<form action="/users" id="registration">
|
1015
1073
|
|
1016
|
-
<
|
1074
|
+
<div up-fieldset>
|
1017
1075
|
<input type="text" name="email" up-validate />
|
1018
|
-
</
|
1076
|
+
</div>
|
1019
1077
|
|
1020
|
-
<
|
1078
|
+
<div up-fieldset>
|
1021
1079
|
<input type="password" name="password" up-validate />
|
1022
|
-
</
|
1080
|
+
</div>
|
1023
1081
|
|
1024
1082
|
</form>
|
1025
1083
|
"""
|
1084
|
+
up.hello(container)
|
1026
1085
|
|
1027
1086
|
Trigger.change $('#registration input[name=password]')
|
1028
1087
|
|
@@ -1030,24 +1089,93 @@ describe 'up.form', ->
|
|
1030
1089
|
@respondWith """
|
1031
1090
|
<form action="/users" id="registration">
|
1032
1091
|
|
1033
|
-
<
|
1092
|
+
<div up-fieldset>
|
1034
1093
|
Validation message
|
1035
1094
|
<input type="text" name="email" up-validate />
|
1036
|
-
</
|
1095
|
+
</div>
|
1037
1096
|
|
1038
|
-
<
|
1097
|
+
<div up-fieldset>
|
1039
1098
|
Validation message
|
1040
1099
|
<input type="password" name="password" up-validate />
|
1041
|
-
</
|
1100
|
+
</div>
|
1042
1101
|
|
1043
1102
|
</form>
|
1044
1103
|
"""
|
1045
1104
|
|
1046
1105
|
next =>
|
1047
|
-
$labels = $('#registration
|
1106
|
+
$labels = $('#registration [up-fieldset]')
|
1048
1107
|
expect($labels[0]).not.toHaveText('Validation message')
|
1049
1108
|
expect($labels[1]).toHaveText('Validation message')
|
1050
1109
|
|
1110
|
+
describe 'form[up-validate]', ->
|
1111
|
+
|
1112
|
+
# it 'prints an error saying that this form is not yet supported', ->
|
1113
|
+
|
1114
|
+
it 'performs server-side validation for all fieldsets contained within the form', asyncSpec (next) ->
|
1115
|
+
container = fixture('.container')
|
1116
|
+
container.innerHTML = """
|
1117
|
+
<form action="/users" id="registration" up-validate>
|
1118
|
+
|
1119
|
+
<div up-fieldset>
|
1120
|
+
<input type="text" name="email">
|
1121
|
+
</div>
|
1122
|
+
|
1123
|
+
<div up-fieldset>
|
1124
|
+
<input type="password" name="password">
|
1125
|
+
</div>
|
1126
|
+
|
1127
|
+
</form>
|
1128
|
+
"""
|
1129
|
+
up.hello(container)
|
1130
|
+
|
1131
|
+
Trigger.change $('#registration input[name=password]')
|
1132
|
+
|
1133
|
+
next =>
|
1134
|
+
expect(jasmine.Ajax.requests.count()).toEqual(1)
|
1135
|
+
expect(@lastRequest().requestHeaders['X-Up-Validate']).toEqual('password')
|
1136
|
+
expect(@lastRequest().requestHeaders['X-Up-Target']).toEqual('[up-fieldset]:has(input[name="password"])')
|
1137
|
+
|
1138
|
+
|
1139
|
+
@respondWith """
|
1140
|
+
<form action="/users" id="registration" up-validate>
|
1141
|
+
|
1142
|
+
<div up-fieldset>
|
1143
|
+
Validation message
|
1144
|
+
<input type="text" name="email">
|
1145
|
+
</div>
|
1146
|
+
|
1147
|
+
<div up-fieldset>
|
1148
|
+
Validation message
|
1149
|
+
<input type="password" name="password">
|
1150
|
+
</div>
|
1151
|
+
|
1152
|
+
</form>
|
1153
|
+
"""
|
1154
|
+
|
1155
|
+
next =>
|
1156
|
+
$labels = $('#registration [up-fieldset]')
|
1157
|
+
expect($labels[0]).not.toHaveText('Validation message')
|
1158
|
+
expect($labels[1]).toHaveText('Validation message')
|
1159
|
+
|
1160
|
+
it 'only sends a single request when a radio button group changes', asyncSpec (next) ->
|
1161
|
+
container = fixture('.container')
|
1162
|
+
container.innerHTML = """
|
1163
|
+
<form action="/users" id="registration" up-validate>
|
1164
|
+
|
1165
|
+
<div up-fieldset>
|
1166
|
+
<input type="radio" name="foo" value="1" checked>
|
1167
|
+
<input type="radio" name="foo" value="2">
|
1168
|
+
</div>
|
1169
|
+
|
1170
|
+
</form>
|
1171
|
+
"""
|
1172
|
+
up.hello(container)
|
1173
|
+
|
1174
|
+
Trigger.change $('#registration input[value="2"]')
|
1175
|
+
|
1176
|
+
next =>
|
1177
|
+
expect(jasmine.Ajax.requests.count()).toEqual(1)
|
1178
|
+
|
1051
1179
|
describe '[up-switch]', ->
|
1052
1180
|
|
1053
1181
|
describe 'on a select', ->
|