unpoly-rails 0.30.1 → 0.31.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 +8 -0
- data/lib/assets/javascripts/unpoly/form.js.coffee +0 -2
- data/lib/assets/javascripts/unpoly/modal.js.coffee +127 -48
- data/lib/assets/javascripts/unpoly/motion.js.coffee +1 -1
- data/lib/assets/javascripts/unpoly/popup.js.coffee +3 -0
- data/lib/assets/javascripts/unpoly/util.js.coffee +50 -15
- data/lib/assets/stylesheets/unpoly-bootstrap3/modal-ext.css.sass +18 -0
- data/lib/assets/stylesheets/unpoly/modal.css.sass +13 -0
- data/lib/unpoly/rails/version.rb +1 -1
- data/spec_app/Gemfile +1 -0
- data/spec_app/Gemfile.lock +7 -1
- data/spec_app/app/assets/javascripts/bootstrap_manifest.coffee +6 -0
- data/spec_app/app/assets/stylesheets/_helpers.sass +5 -0
- data/spec_app/app/assets/stylesheets/bootstrap_manifest.sass +2 -0
- data/spec_app/app/assets/stylesheets/integration_test.sass +11 -2
- data/spec_app/app/views/css_test/modal.erb +10 -0
- data/spec_app/app/views/css_test/modal_contents.erb +3 -3
- data/spec_app/app/views/layouts/integration_test.erb +6 -0
- data/spec_app/app/views/pages/start.erb +12 -3
- data/spec_app/config/initializers/assets.rb +5 -1
- data/spec_app/spec/javascripts/up/form_spec.js.coffee +0 -1
- data/spec_app/spec/javascripts/up/link_spec.js.coffee +24 -0
- data/spec_app/spec/javascripts/up/modal_spec.js.coffee +41 -7
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f141062c454db36ff9fa469178c4980587858770
|
4
|
+
data.tar.gz: cd9474a9ab62e41572b56f731822ef1483f8543a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81d7cf8973a69e968ca7063cc058fbef25403027638d504c2b8fb3919b87e24ea11d1b0f7ca219c8a2a8ca340d13a8cd45474ecab50a6275d1fbae86c8d1def5
|
7
|
+
data.tar.gz: eadfbdd2d046e641e8a93462d2bfb8cdb274086afedff58aa21681d1641a4d501ebc26722195f4d068f7a717e8ec2777ebb316cfda911264775f6e0f57a2d8d1
|
data/CHANGELOG.md
CHANGED
@@ -10,9 +10,17 @@ Unreleased
|
|
10
10
|
|
11
11
|
### Compatible changes
|
12
12
|
|
13
|
+
- Drawers are now a built-in modal flavor! Use the `[up-drawer]` attribute to open page fragements
|
14
|
+
in a modal drawer that slides in from the edge of the screen.
|
15
|
+
|
13
16
|
|
14
17
|
### Breaking changes
|
15
18
|
|
19
|
+
- The [`up.modal.flavor`](/up.modal.flavor) function was deprecated. Set values on the
|
20
|
+
[`up.modal.flavors`](/up.modal.flavors) property instead.
|
21
|
+
|
22
|
+
|
23
|
+
|
16
24
|
|
17
25
|
0.30.1
|
18
26
|
------
|
@@ -249,8 +249,6 @@ up.form = (($) ->
|
|
249
249
|
delay = u.option($fields.attr('up-delay'), options.delay, config.observeDelay)
|
250
250
|
delay = parseInt(delay)
|
251
251
|
|
252
|
-
console.debug("Observing with delay %o", delay)
|
253
|
-
|
254
252
|
destructors = u.map $fields, (field) ->
|
255
253
|
observeField($(field), delay, callback)
|
256
254
|
|
@@ -116,6 +116,8 @@ up.modal = (($) ->
|
|
116
116
|
@param {Boolean} [options.sticky=false]
|
117
117
|
If set to `true`, the modal remains
|
118
118
|
open even it changes the page in the background.
|
119
|
+
@param {String} [options.flavor='default']
|
120
|
+
The default [flavor](/up.modal.flavors).
|
119
121
|
@stable
|
120
122
|
###
|
121
123
|
config = u.config
|
@@ -135,21 +137,62 @@ up.modal = (($) ->
|
|
135
137
|
closeLabel: '×'
|
136
138
|
closable: true
|
137
139
|
sticky: false
|
138
|
-
|
139
|
-
|
140
|
-
template: (
|
140
|
+
flavor: 'default'
|
141
|
+
position: null
|
142
|
+
template: (options) ->
|
141
143
|
"""
|
142
144
|
<div class="up-modal">
|
143
145
|
<div class="up-modal-backdrop"></div>
|
144
146
|
<div class="up-modal-viewport">
|
145
147
|
<div class="up-modal-dialog">
|
146
148
|
<div class="up-modal-content"></div>
|
147
|
-
<div class="up-modal-close" up-close>#{
|
149
|
+
<div class="up-modal-close" up-close>#{options.closeLabel}</div>
|
148
150
|
</div>
|
149
151
|
</div>
|
150
152
|
</div>
|
151
153
|
"""
|
152
154
|
|
155
|
+
###*
|
156
|
+
Define modal variants with their own default configuration, CSS or HTML template.
|
157
|
+
|
158
|
+
\#\#\# Example
|
159
|
+
|
160
|
+
Unpoly's [`[up-drawer]`](/up-drawer) is implemented as a modal flavor:
|
161
|
+
|
162
|
+
up.modal.flavors.drawer = {
|
163
|
+
openAnimation: 'move-from-right',
|
164
|
+
closeAnimation: 'move-to-right'
|
165
|
+
}
|
166
|
+
|
167
|
+
Modals with that flavor will have a container with an `up-flavor` attribute:
|
168
|
+
|
169
|
+
<div class='up-modal' up-flavor='drawer'>
|
170
|
+
...
|
171
|
+
</div>
|
172
|
+
|
173
|
+
We can target the `up-flavor` attribute to override the default dialog styles:
|
174
|
+
|
175
|
+
.up-modal[up-flavor='drawer'] {
|
176
|
+
|
177
|
+
.up-modal-dialog {
|
178
|
+
margin: 0; // Remove margin so drawer starts at the screen edge
|
179
|
+
max-width: 350px; // Set drawer size
|
180
|
+
}
|
181
|
+
|
182
|
+
.up-modal-content {
|
183
|
+
min-height: 100vh; // Stretch background to full window height
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
@property up.modal.flavors
|
188
|
+
@param {Object} flavors
|
189
|
+
An object where the keys are flavor names (e.g. `'drawer') and
|
190
|
+
the values are the respective default configurations.
|
191
|
+
@experimental
|
192
|
+
###
|
193
|
+
flavors = u.openConfig
|
194
|
+
default: {}
|
195
|
+
|
153
196
|
###*
|
154
197
|
Returns the source URL for the fragment displayed in the current modal overlay,
|
155
198
|
or `undefined` if no modal is currently open.
|
@@ -178,6 +221,7 @@ up.modal = (($) ->
|
|
178
221
|
url: null
|
179
222
|
coveredUrl: null
|
180
223
|
coveredTitle: null
|
224
|
+
position: null
|
181
225
|
unshifters: []
|
182
226
|
|
183
227
|
chain = new u.DivertibleChain()
|
@@ -188,13 +232,11 @@ up.modal = (($) ->
|
|
188
232
|
state.reset()
|
189
233
|
chain.reset()
|
190
234
|
config.reset()
|
235
|
+
flavors.reset()
|
191
236
|
|
192
237
|
templateHtml = ->
|
193
238
|
template = flavorDefault('template')
|
194
|
-
|
195
|
-
template(config)
|
196
|
-
else
|
197
|
-
template
|
239
|
+
u.evalOption(template, closeLabel: flavorDefault('closeLabel'))
|
198
240
|
|
199
241
|
discardHistory = ->
|
200
242
|
state.coveredTitle = null
|
@@ -203,6 +245,7 @@ up.modal = (($) ->
|
|
203
245
|
createFrame = (target, options) ->
|
204
246
|
$modal = $(templateHtml())
|
205
247
|
$modal.attr('up-flavor', state.flavor)
|
248
|
+
$modal.attr('up-position', state.position) if u.isPresent(state.position)
|
206
249
|
$dialog = $modal.find('.up-modal-dialog')
|
207
250
|
$dialog.css('width', options.width) if u.isPresent(options.width)
|
208
251
|
$dialog.css('max-width', options.maxWidth) if u.isPresent(options.maxWidth)
|
@@ -389,12 +432,16 @@ up.modal = (($) ->
|
|
389
432
|
url = u.option(u.pluckKey(options, 'url'), $link.attr('up-href'), $link.attr('href'))
|
390
433
|
html = u.option(u.pluckKey(options, 'html'))
|
391
434
|
target = u.option(u.pluckKey(options, 'target'), $link.attr('up-modal'), 'body')
|
392
|
-
options.flavor = u.option(options.flavor, $link.attr('up-flavor'))
|
435
|
+
options.flavor = u.option(options.flavor, $link.attr('up-flavor'), config.flavor)
|
436
|
+
options.position = u.option(options.position, $link.attr('up-position'), flavorDefault('position', options.flavor))
|
437
|
+
options.position = u.evalOption(options.position, $link: $link)
|
393
438
|
options.width = u.option(options.width, $link.attr('up-width'), flavorDefault('width', options.flavor))
|
394
439
|
options.maxWidth = u.option(options.maxWidth, $link.attr('up-max-width'), flavorDefault('maxWidth', options.flavor))
|
395
440
|
options.height = u.option(options.height, $link.attr('up-height'), flavorDefault('height'))
|
396
441
|
options.animation = u.option(options.animation, $link.attr('up-animation'), flavorDefault('openAnimation', options.flavor))
|
442
|
+
options.animation = u.evalOption(options.animation, position: options.position)
|
397
443
|
options.backdropAnimation = u.option(options.backdropAnimation, $link.attr('up-backdrop-animation'), flavorDefault('backdropOpenAnimation', options.flavor))
|
444
|
+
options.backdropAnimation = u.evalOption(options.backdropAnimation, position: options.position)
|
398
445
|
options.sticky = u.option(options.sticky, u.castedAttr($link, 'up-sticky'), flavorDefault('sticky', options.flavor))
|
399
446
|
options.closable = u.option(options.closable, u.castedAttr($link, 'up-closable'), flavorDefault('closable', options.flavor))
|
400
447
|
options.confirm = u.option(options.confirm, $link.attr('up-confirm'))
|
@@ -414,6 +461,7 @@ up.modal = (($) ->
|
|
414
461
|
state.flavor = options.flavor
|
415
462
|
state.sticky = options.sticky
|
416
463
|
state.closable = options.closable
|
464
|
+
state.position = options.position
|
417
465
|
if options.history
|
418
466
|
state.coveredUrl = up.browser.url()
|
419
467
|
state.coveredTitle = document.title
|
@@ -473,7 +521,9 @@ up.modal = (($) ->
|
|
473
521
|
|
474
522
|
options = u.options(options)
|
475
523
|
viewportCloseAnimation = u.option(options.animation, flavorDefault('closeAnimation'))
|
524
|
+
viewportCloseAnimation = u.evalOption(viewportCloseAnimation, position: state.position)
|
476
525
|
backdropCloseAnimation = u.option(options.backdropAnimation, flavorDefault('backdropCloseAnimation'))
|
526
|
+
backdropCloseAnimation = u.evalOption(backdropCloseAnimation, position: state.position)
|
477
527
|
animateOptions = up.motion.animateOptions(options, duration: flavorDefault('closeDuration'), easing: flavorDefault('closeEasing'))
|
478
528
|
|
479
529
|
destroyOptions = u.options(
|
@@ -502,6 +552,7 @@ up.modal = (($) ->
|
|
502
552
|
state.flavor = null
|
503
553
|
state.sticky = null
|
504
554
|
state.closable = null
|
555
|
+
state.position = null
|
505
556
|
up.emit('up:modal:closed', message: 'Modal closed')
|
506
557
|
|
507
558
|
promise
|
@@ -557,42 +608,8 @@ up.modal = (($) ->
|
|
557
608
|
$element = $(elementOrSelector)
|
558
609
|
$element.closest('.up-modal').length > 0
|
559
610
|
|
560
|
-
###*
|
561
|
-
Register a new modal variant with its own default configuration, CSS or HTML template.
|
562
|
-
|
563
|
-
\#\#\# Example
|
564
|
-
|
565
|
-
Let's implement a drawer that slides in from the right:
|
566
|
-
|
567
|
-
up.modal.flavor('drawer', {
|
568
|
-
openAnimation: 'move-from-right',
|
569
|
-
closeAnimation: 'move-to-right',
|
570
|
-
maxWidth: 400
|
571
|
-
}
|
572
|
-
|
573
|
-
Modals with that flavor will have a container `<div class='up-modal' up-flavor='drawer'>...</div>`.
|
574
|
-
We can target the `up-flavor` attribute override the default dialog styles:
|
575
|
-
|
576
|
-
.up-modal[up-flavor='drawer'] {
|
577
|
-
|
578
|
-
// Align drawer on the right
|
579
|
-
.up-modal-viewport { text-align: right; }
|
580
|
-
|
581
|
-
// Remove margin so the drawer starts at the screen edge
|
582
|
-
.up-modal-dialog { margin: 0; }
|
583
|
-
|
584
|
-
// Stretch drawer background to full window height
|
585
|
-
.up-modal-content { min-height: 100vh; }
|
586
|
-
}
|
587
|
-
|
588
|
-
@function up.modal.flavor
|
589
|
-
@param {String} name
|
590
|
-
The name of the new flavor.
|
591
|
-
@param {Object} [overrideConfig]
|
592
|
-
An object whose properties override the defaults in [`/up.modal.config`](/up.modal.config).
|
593
|
-
@experimental
|
594
|
-
###
|
595
611
|
flavor = (name, overrideConfig = {}) ->
|
612
|
+
up.log.warn 'The up.modal.flavor function is deprecated. Use the up.modal.flavors property instead.'
|
596
613
|
u.extend(flavorOverrides(name), overrideConfig)
|
597
614
|
|
598
615
|
###*
|
@@ -604,7 +621,7 @@ up.modal = (($) ->
|
|
604
621
|
@internal
|
605
622
|
###
|
606
623
|
flavorOverrides = (flavor) ->
|
607
|
-
|
624
|
+
flavors[flavor] ||= {}
|
608
625
|
|
609
626
|
###*
|
610
627
|
Returns the config option for the current flavor.
|
@@ -621,16 +638,18 @@ up.modal = (($) ->
|
|
621
638
|
Clicking this link will load the destination via AJAX and open
|
622
639
|
the given selector in a modal dialog.
|
623
640
|
|
624
|
-
Example
|
641
|
+
\#\#\#\# Example
|
625
642
|
|
626
643
|
<a href="/blogs" up-modal=".blog-list">Switch blog</a>
|
627
644
|
|
628
645
|
Clicking would request the path `/blog` and select `.blog-list` from
|
629
|
-
the HTML response. Unpoly will dim the page
|
646
|
+
the HTML response. Unpoly will dim the page
|
630
647
|
and place the matching `.blog-list` tag will be placed in
|
631
648
|
a modal dialog.
|
632
649
|
|
633
650
|
@selector [up-modal]
|
651
|
+
@param {String} up-modal
|
652
|
+
The CSS selector that will be extracted from the response and displayed in a modal dialog.
|
634
653
|
@param {String} [up-confirm]
|
635
654
|
A message that will be displayed in a cancelable confirmation dialog
|
636
655
|
before the modal is opened.
|
@@ -712,6 +731,65 @@ up.modal = (($) ->
|
|
712
731
|
up.bus.consumeAction(event)
|
713
732
|
)
|
714
733
|
|
734
|
+
###*
|
735
|
+
Clicking this link will load the destination via AJAX and open
|
736
|
+
the given selector in a modal drawer that slides in from the edge of the screen.
|
737
|
+
|
738
|
+
You can configure drawers using the [`up.modal.flavors.drawer`](/up.modal.flavors.drawer) property.
|
739
|
+
|
740
|
+
\#\#\#\# Example
|
741
|
+
|
742
|
+
<a href="/blogs" up-drawer=".blog-list">Switch blog</a>
|
743
|
+
|
744
|
+
Clicking would request the path `/blog` and select `.blog-list` from
|
745
|
+
the HTML response. Unpoly will dim the page
|
746
|
+
and place the matching `.blog-list` tag will be placed in
|
747
|
+
a modal drawer.
|
748
|
+
|
749
|
+
@selector [up-drawer]
|
750
|
+
@param {String} up-drawer
|
751
|
+
The CSS selector to extract from the response and open in the drawer.
|
752
|
+
@param {String} [up-position='auto']
|
753
|
+
The side from which the drawer slides in.
|
754
|
+
|
755
|
+
Valid values are `'left'`, `'right'` and `'auto'`. If set to `'auto'`, the
|
756
|
+
drawer will slide in from left if the opening link is on the left half of the screen.
|
757
|
+
Otherwise it will slide in from the right.
|
758
|
+
@experimental
|
759
|
+
###
|
760
|
+
up.macro '[up-drawer]', ($link) ->
|
761
|
+
target = $link.attr('up-drawer')
|
762
|
+
$link.attr
|
763
|
+
'up-modal': target
|
764
|
+
'up-flavor': 'drawer'
|
765
|
+
|
766
|
+
###*
|
767
|
+
Sets default options for future drawers.
|
768
|
+
|
769
|
+
@property up.modal.flavors.drawer
|
770
|
+
@param {Object} config
|
771
|
+
Default options for future drawers.
|
772
|
+
|
773
|
+
See [`up.modal.config`] for available options.
|
774
|
+
@experimental
|
775
|
+
###
|
776
|
+
flavors.drawer =
|
777
|
+
openAnimation: (options) ->
|
778
|
+
switch options.position
|
779
|
+
when 'left' then 'move-from-left'
|
780
|
+
when 'right' then 'move-from-right'
|
781
|
+
closeAnimation: (options) ->
|
782
|
+
switch options.position
|
783
|
+
when 'left' then 'move-to-left'
|
784
|
+
when 'right' then 'move-to-right'
|
785
|
+
position: (options) ->
|
786
|
+
if u.isPresent(options.$link)
|
787
|
+
u.horizontalScreenHalf(options.$link)
|
788
|
+
else
|
789
|
+
# In case the drawer was opened programmatically through `up.modal.open`,
|
790
|
+
# we might now know the link that was clicked on.
|
791
|
+
'left'
|
792
|
+
|
715
793
|
# The framework is reset between tests
|
716
794
|
up.on 'up:framework:reset', reset
|
717
795
|
|
@@ -723,8 +801,9 @@ up.modal = (($) ->
|
|
723
801
|
url: -> state.url
|
724
802
|
coveredUrl: -> state.coveredUrl
|
725
803
|
config: config
|
804
|
+
flavors: flavors
|
726
805
|
contains: contains
|
727
806
|
isOpen: isOpen
|
728
|
-
flavor: flavor
|
807
|
+
flavor: flavor # deprecated
|
729
808
|
|
730
809
|
)(jQuery)
|
@@ -165,7 +165,7 @@ up.motion = (($) ->
|
|
165
165
|
$element = $(elementOrSelector)
|
166
166
|
finish($element)
|
167
167
|
options = animateOptions(options)
|
168
|
-
if animation == 'none' || animation == false
|
168
|
+
if animation == 'none' || animation == false || u.isMissing(animation)
|
169
169
|
none()
|
170
170
|
else if u.isFunction(animation)
|
171
171
|
assertIsDeferred(animation($element, options), animation)
|
@@ -373,6 +373,9 @@ up.popup = (($) ->
|
|
373
373
|
<a href="/settings" up-popup=".options" up-sticky>Settings</a>
|
374
374
|
|
375
375
|
@selector [up-popup]
|
376
|
+
@param {String} up-popup
|
377
|
+
The CSS selector that will be extracted from the response and
|
378
|
+
displayed in a popup overlay.
|
376
379
|
@param [up-position]
|
377
380
|
Defines where the popup is attached to the opening element.
|
378
381
|
|
@@ -1381,6 +1381,19 @@ up.util = (($) ->
|
|
1381
1381
|
|
1382
1382
|
obj
|
1383
1383
|
|
1384
|
+
###*
|
1385
|
+
If the given `value` is a function, calls the function with the given `args`.
|
1386
|
+
Otherwise it just returns `value`.
|
1387
|
+
|
1388
|
+
@function up.util.evalOption
|
1389
|
+
@internal
|
1390
|
+
###
|
1391
|
+
evalOption = (value, args...) ->
|
1392
|
+
if isFunction(value)
|
1393
|
+
value(args...)
|
1394
|
+
else
|
1395
|
+
value
|
1396
|
+
|
1384
1397
|
###*
|
1385
1398
|
@function up.util.cache
|
1386
1399
|
@param {Number|Function} [config.size]
|
@@ -1400,19 +1413,8 @@ up.util = (($) ->
|
|
1400
1413
|
|
1401
1414
|
store = undefined
|
1402
1415
|
|
1403
|
-
|
1404
|
-
|
1405
|
-
value = config[name]
|
1406
|
-
if isNumber(value)
|
1407
|
-
value
|
1408
|
-
else if isFunction(value)
|
1409
|
-
value()
|
1410
|
-
else
|
1411
|
-
undefined
|
1412
|
-
|
1413
|
-
maxKeys = optionEvaluator('size')
|
1414
|
-
|
1415
|
-
expiryMillis = optionEvaluator('expiry')
|
1416
|
+
maxKeys = -> evalOption(config.size)
|
1417
|
+
expiryMillis = -> evalOption(config.expiry)
|
1416
1418
|
|
1417
1419
|
normalizeStoreKey = (key) ->
|
1418
1420
|
if config.key
|
@@ -1501,16 +1503,29 @@ up.util = (($) ->
|
|
1501
1503
|
|
1502
1504
|
###*
|
1503
1505
|
@function up.util.config
|
1506
|
+
@param {Object|Function} blueprint
|
1507
|
+
Default configuration options.
|
1508
|
+
Will be restored by calling `reset` on the returned object.
|
1509
|
+
@return {Object}
|
1510
|
+
An object with a `reset` function.
|
1511
|
+
@internal
|
1512
|
+
###
|
1513
|
+
config = (blueprint) ->
|
1514
|
+
hash = openConfig(blueprint)
|
1515
|
+
Object.preventExtensions(hash)
|
1516
|
+
hash
|
1517
|
+
|
1518
|
+
###*
|
1519
|
+
@function up.util.openConfig
|
1504
1520
|
@internal
|
1505
1521
|
###
|
1506
|
-
|
1522
|
+
openConfig = (blueprint = {}) ->
|
1507
1523
|
hash = {}
|
1508
1524
|
hash.reset = ->
|
1509
1525
|
newOptions = blueprint
|
1510
1526
|
newOptions = newOptions() if isFunction(newOptions)
|
1511
1527
|
extend(hash, newOptions)
|
1512
1528
|
hash.reset()
|
1513
|
-
Object.preventExtensions(hash)
|
1514
1529
|
hash
|
1515
1530
|
|
1516
1531
|
###*
|
@@ -1873,6 +1888,23 @@ up.util = (($) ->
|
|
1873
1888
|
deferred.cancel = -> clearTimeout(timeout)
|
1874
1889
|
deferred
|
1875
1890
|
|
1891
|
+
###*
|
1892
|
+
Returns `'left'` if the center of the given element is in the left 50% of the screen.
|
1893
|
+
Otherwise returns `'right'`.
|
1894
|
+
|
1895
|
+
@function up.util.horizontalScreenHalf
|
1896
|
+
@internal
|
1897
|
+
###
|
1898
|
+
horizontalScreenHalf = ($element) ->
|
1899
|
+
elementDims = measure($element)
|
1900
|
+
screenDims = clientSize()
|
1901
|
+
elementMid = elementDims.left + 0.5 * elementDims.width
|
1902
|
+
screenMid = 0.5 * screenDims.width
|
1903
|
+
if elementMid < screenMid
|
1904
|
+
'left'
|
1905
|
+
else
|
1906
|
+
'right'
|
1907
|
+
|
1876
1908
|
isDetached: isDetached
|
1877
1909
|
requestDataAsArray: requestDataAsArray
|
1878
1910
|
requestDataAsQuery: requestDataAsQuery
|
@@ -1965,6 +1997,7 @@ up.util = (($) ->
|
|
1965
1997
|
scrollbarWidth: scrollbarWidth
|
1966
1998
|
documentHasVerticalScrollbar: documentHasVerticalScrollbar
|
1967
1999
|
config: config
|
2000
|
+
openConfig: openConfig
|
1968
2001
|
cache: cache
|
1969
2002
|
unwrapElement: unwrapElement
|
1970
2003
|
multiSelector: multiSelector
|
@@ -1983,6 +2016,8 @@ up.util = (($) ->
|
|
1983
2016
|
sequence: sequence
|
1984
2017
|
promiseTimer: promiseTimer
|
1985
2018
|
previewable: previewable
|
2019
|
+
evalOption: evalOption
|
2020
|
+
horizontalScreenHalf: horizontalScreenHalf
|
1986
2021
|
|
1987
2022
|
)($)
|
1988
2023
|
|
@@ -2,3 +2,21 @@
|
|
2
2
|
// Unpoly: Gives some default padding
|
3
3
|
// BS: Expects content to set the padding
|
4
4
|
padding: 0
|
5
|
+
|
6
|
+
.up-modal[up-flavor='drawer']
|
7
|
+
|
8
|
+
.up-modal-content
|
9
|
+
// Bootstrap gives its modals round corners, which looks wrong with a
|
10
|
+
// drawer that sits at the end of the screen.
|
11
|
+
border-radius: 0
|
12
|
+
|
13
|
+
// Bootstrap gives its modals a border, which looks wrong
|
14
|
+
// when touching the edge of the screen.
|
15
|
+
border-top: none
|
16
|
+
border-bottom: none
|
17
|
+
|
18
|
+
&[up-position='left'] .up-modal-content
|
19
|
+
border-left: none
|
20
|
+
|
21
|
+
&[up-position='right'] .up-modal-content
|
22
|
+
border-right: none
|
@@ -96,3 +96,16 @@ $close-font-size: 34px
|
|
96
96
|
color: #666
|
97
97
|
cursor: pointer
|
98
98
|
|
99
|
+
.up-modal[up-flavor='drawer']
|
100
|
+
.up-modal-viewport
|
101
|
+
text-align: left
|
102
|
+
&[up-position='right'] .up-modal-viewport
|
103
|
+
text-align: right
|
104
|
+
.up-modal-dialog
|
105
|
+
margin: 0
|
106
|
+
max-width: 350px
|
107
|
+
.up-modal-content
|
108
|
+
min-height: 100vh
|
109
|
+
box-sizing: border-box // since we're setting min-height on an element with padding
|
110
|
+
|
111
|
+
|
data/lib/unpoly/rails/version.rb
CHANGED
data/spec_app/Gemfile
CHANGED
@@ -11,6 +11,7 @@ gem 'therubyracer', platforms: :ruby
|
|
11
11
|
gem 'jquery-rails'
|
12
12
|
gem 'unpoly-rails', path: '..'
|
13
13
|
gem 'bower-rails'
|
14
|
+
gem 'bootstrap-sass', '~> 3.3'
|
14
15
|
|
15
16
|
# Jasmine spec runner won't boot with a more modern version of sprockets.
|
16
17
|
# It crashes with an "asset not precompiled" error.
|
data/spec_app/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
unpoly-rails (0.30.
|
4
|
+
unpoly-rails (0.30.1)
|
5
5
|
rails (>= 3)
|
6
6
|
|
7
7
|
GEM
|
@@ -43,8 +43,13 @@ GEM
|
|
43
43
|
thread_safe (~> 0.3, >= 0.3.4)
|
44
44
|
tzinfo (~> 1.1)
|
45
45
|
arel (6.0.3)
|
46
|
+
autoprefixer-rails (6.5.1.1)
|
47
|
+
execjs
|
46
48
|
binding_of_caller (0.7.2)
|
47
49
|
debug_inspector (>= 0.0.1)
|
50
|
+
bootstrap-sass (3.3.7)
|
51
|
+
autoprefixer-rails (>= 5.2.1)
|
52
|
+
sass (>= 3.3.4)
|
48
53
|
bower-rails (0.9.2)
|
49
54
|
builder (3.2.2)
|
50
55
|
byebug (3.5.1)
|
@@ -195,6 +200,7 @@ PLATFORMS
|
|
195
200
|
ruby
|
196
201
|
|
197
202
|
DEPENDENCIES
|
203
|
+
bootstrap-sass (~> 3.3)
|
198
204
|
bower-rails
|
199
205
|
byebug
|
200
206
|
coffee-rails (~> 4.1.0)
|
@@ -0,0 +1,6 @@
|
|
1
|
+
#= require bootstrap-sprockets
|
2
|
+
|
3
|
+
# From the docs (https://github.com/twbs/bootstrap-sass):
|
4
|
+
# bootstrap-sprockets and bootstrap should not both be included in application.js.
|
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.
|
@@ -1,5 +1,7 @@
|
|
1
1
|
//= require unpoly
|
2
2
|
|
3
|
+
@import helpers
|
4
|
+
|
3
5
|
$block-spacing: 25px
|
4
6
|
|
5
7
|
=block-spacing
|
@@ -14,6 +16,11 @@ body
|
|
14
16
|
h1, h2, h3, h4, p
|
15
17
|
+block-spacing
|
16
18
|
|
19
|
+
a
|
20
|
+
color: #169
|
21
|
+
&:hover
|
22
|
+
color: #e81
|
23
|
+
|
17
24
|
.page
|
18
25
|
min-height: 3000px
|
19
26
|
|
@@ -32,6 +39,7 @@ h1, h2, h3, h4, p
|
|
32
39
|
|
33
40
|
.example
|
34
41
|
margin: 50px
|
42
|
+
+clear-after
|
35
43
|
|
36
44
|
.area
|
37
45
|
+block-spacing
|
@@ -44,13 +52,14 @@ h1, h2, h3, h4, p
|
|
44
52
|
line-height: 50px
|
45
53
|
padding-left: 25px
|
46
54
|
padding-right: 25px
|
47
|
-
background-color: #
|
55
|
+
background-color: #37b
|
48
56
|
color: white
|
49
57
|
text-decoration: none
|
50
58
|
&.up-current
|
51
|
-
background-color: #
|
59
|
+
background-color: #e21
|
52
60
|
&:hover
|
53
61
|
background-color: #fa1
|
62
|
+
color: white
|
54
63
|
&.up-active
|
55
64
|
background-color: #ff0
|
56
65
|
|
@@ -1,3 +1,13 @@
|
|
1
1
|
<div class="example">
|
2
2
|
<a class="button" href="/css_test/modal_contents" up-modal=".contents">Modal</a>
|
3
3
|
</div>
|
4
|
+
|
5
|
+
<div class="example">
|
6
|
+
<a class="button" href="/css_test/modal_contents" up-drawer=".contents" style="float: left">Drawer (auto)</a>
|
7
|
+
<a class="button" href="/css_test/modal_contents" up-drawer=".contents" style="float: right">Drawer (auto)</a>
|
8
|
+
</div>
|
9
|
+
|
10
|
+
<div class="example">
|
11
|
+
<a class="button" href="/css_test/modal_contents" up-drawer=".contents" up-position="left">Drawer (left)</a>
|
12
|
+
<a class="button" href="/css_test/modal_contents" up-drawer=".contents" up-position="right">Drawer (right)</a>
|
13
|
+
</div>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<div class="contents">
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
<% (1..100).each do |i| %>
|
3
|
+
Line <%= i %>: Foo bar baz bam qux foo bar baz bam qux<br>
|
4
|
+
<% end %>
|
5
5
|
</div>
|
@@ -4,6 +4,12 @@
|
|
4
4
|
<title>Integration test - Unpoly</title>
|
5
5
|
<%= stylesheet_link_tag 'integration_test', media: 'all' %>
|
6
6
|
<%= javascript_include_tag 'integration_test' %>
|
7
|
+
<% if params[:bootstrap] == '1' %>
|
8
|
+
<%= stylesheet_link_tag 'bootstrap_manifest', media: 'all' %>
|
9
|
+
<%= javascript_include_tag 'bootstrap_manifest' %>
|
10
|
+
<%= stylesheet_link_tag 'unpoly-bootstrap3', media: 'all' %>
|
11
|
+
<%= javascript_include_tag 'unpoly-bootstrap3' %>
|
12
|
+
<% end %>
|
7
13
|
<%= csrf_meta_tags %>
|
8
14
|
</head>
|
9
15
|
<body>
|
@@ -11,15 +11,24 @@
|
|
11
11
|
<h2>Integration tests</h2>
|
12
12
|
|
13
13
|
<ul>
|
14
|
-
<li
|
14
|
+
<li>
|
15
|
+
<%= link_to 'Tooltip', '/css_test/tooltip' %>
|
16
|
+
(<%= link_to 'with Bootstrap', '/css_test/tooltip?bootstrap=1' %>)
|
17
|
+
</li>
|
15
18
|
</ul>
|
16
19
|
|
17
20
|
<ul>
|
18
|
-
<li
|
21
|
+
<li>
|
22
|
+
<%= link_to 'Popup', '/css_test/popup' %>
|
23
|
+
(<%= link_to 'with Bootstrap', '/css_test/popup?bootstrap=1' %>)
|
24
|
+
</li>
|
19
25
|
</ul>
|
20
26
|
|
21
27
|
<ul>
|
22
|
-
<li
|
28
|
+
<li>
|
29
|
+
<%= link_to 'Modal', '/css_test/modal' %>
|
30
|
+
(<%= link_to 'with Bootstrap', '/css_test/modal?bootstrap=1' %>)
|
31
|
+
</li>
|
23
32
|
</ul>
|
24
33
|
|
25
34
|
<ul>
|
@@ -11,4 +11,8 @@ Rails.application.config.assets.version = '1.0'
|
|
11
11
|
|
12
12
|
|
13
13
|
Rails.application.config.assets.precompile += %w( application.js application.css )
|
14
|
-
Rails.application.config.assets.precompile += %w( jasmine_specs.js jasmine_specs.css
|
14
|
+
Rails.application.config.assets.precompile += %w( jasmine_specs.js jasmine_specs.css )
|
15
|
+
Rails.application.config.assets.precompile += %w( integration_test.js integration_test.css )
|
16
|
+
Rails.application.config.assets.precompile += %w( bootstrap_manifest.js bootstrap_manifest.css )
|
17
|
+
Rails.application.config.assets.precompile += %w( unpoly-bootstrap3.js unpoly-bootstrap3.css )
|
18
|
+
|
@@ -100,7 +100,6 @@ describe 'up.form', ->
|
|
100
100
|
it 'does not run multiple callbacks if a long-running callback has been blocking multiple subsequent callbacks'
|
101
101
|
|
102
102
|
it "runs a callback in the same frame if the delay is 0", ->
|
103
|
-
console.debug('*** next example')
|
104
103
|
$input = affix('input[value="old-value"]')
|
105
104
|
callback = jasmine.createSpy('change callback')
|
106
105
|
up.observe($input, { delay: 0 }, callback)
|
@@ -394,6 +394,30 @@ describe 'up.link', ->
|
|
394
394
|
expect($('.document .target')).toHaveText('new text from document link')
|
395
395
|
done()
|
396
396
|
|
397
|
+
describe 'with [up-fail-target] modifier', ->
|
398
|
+
|
399
|
+
beforeEach ->
|
400
|
+
affix('.success-target').text('old success text')
|
401
|
+
affix('.failure-target').text('old failure text')
|
402
|
+
@$link = affix('a[href="/path"][up-target=".success-target"][up-fail-target=".failure-target"]')
|
403
|
+
|
404
|
+
it 'uses the [up-fail-target] selector for a failed response', (done) ->
|
405
|
+
Trigger.clickSequence(@$link)
|
406
|
+
u.nextFrame =>
|
407
|
+
@respondWith('<div class="failure-target">new failure text</div>', status: 500)
|
408
|
+
u.nextFrame =>
|
409
|
+
expect($('.success-target')).toHaveText('old success text')
|
410
|
+
expect($('.failure-target')).toHaveText('new failure text')
|
411
|
+
done()
|
412
|
+
|
413
|
+
it 'uses the [up-target] selector for a successful response', (done) ->
|
414
|
+
Trigger.clickSequence(@$link)
|
415
|
+
u.nextFrame =>
|
416
|
+
@respondWith('<div class="success-target">new success text</div>', status: 200)
|
417
|
+
u.nextFrame =>
|
418
|
+
expect($('.success-target')).toHaveText('new success text')
|
419
|
+
expect($('.failure-target')).toHaveText('old failure text')
|
420
|
+
done()
|
397
421
|
|
398
422
|
describe 'with [up-transition] modifier', ->
|
399
423
|
|
@@ -225,7 +225,7 @@ describe 'up.modal', ->
|
|
225
225
|
up.modal.config.openDuration = 20
|
226
226
|
up.modal.config.closeAnimation = 'fade-out'
|
227
227
|
up.modal.config.closeDuration = 20
|
228
|
-
up.modal.flavor 'drawer',
|
228
|
+
up.modal.flavor 'custom-drawer',
|
229
229
|
openAnimation: 'move-from-right'
|
230
230
|
closeAnimation: 'move-to-right'
|
231
231
|
|
@@ -252,7 +252,7 @@ describe 'up.modal', ->
|
|
252
252
|
]
|
253
253
|
|
254
254
|
|
255
|
-
up.modal.extract('.target', '<div class="target">response2</div>', flavor: 'drawer')
|
255
|
+
up.modal.extract('.target', '<div class="target">response2</div>', flavor: 'custom-drawer')
|
256
256
|
expect(animations).toEqual [
|
257
257
|
{ animation: 'fade-in', text: 'response1' },
|
258
258
|
{ animation: 'fade-out', text: 'response1' },
|
@@ -266,7 +266,7 @@ describe 'up.modal', ->
|
|
266
266
|
{ animation: 'move-from-right', text: 'response2' }
|
267
267
|
]
|
268
268
|
|
269
|
-
expect($('.up-modal').attr('up-flavor')).toEqual('drawer')
|
269
|
+
expect($('.up-modal').attr('up-flavor')).toEqual('custom-drawer')
|
270
270
|
|
271
271
|
done()
|
272
272
|
|
@@ -293,10 +293,10 @@ describe 'up.modal', ->
|
|
293
293
|
expect(up.modal.coveredUrl()).toBeMissing()
|
294
294
|
done()
|
295
295
|
|
296
|
-
describe 'up.modal.
|
296
|
+
describe 'up.modal.flavors', ->
|
297
297
|
|
298
|
-
it '
|
299
|
-
up.modal.
|
298
|
+
it 'allows to register new modal variants with its own default configuration', ->
|
299
|
+
up.modal.flavors.variant = { maxWidth: 200 }
|
300
300
|
$link = affix('a[href="/path"][up-modal=".target"][up-flavor="variant"]')
|
301
301
|
Trigger.click($link)
|
302
302
|
@respondWith('<div class="target">new text</div>')
|
@@ -307,7 +307,7 @@ describe 'up.modal', ->
|
|
307
307
|
expect($dialog.attr('style')).toContain('max-width: 200px')
|
308
308
|
|
309
309
|
it 'does not change the configuration of non-flavored modals', ->
|
310
|
-
up.modal.
|
310
|
+
up.modal.flavors.variant = { maxWidth: 200 }
|
311
311
|
$link = affix('a[href="/path"][up-modal=".target"]')
|
312
312
|
Trigger.click($link)
|
313
313
|
@respondWith('<div class="target">new text</div>')
|
@@ -417,6 +417,40 @@ describe 'up.modal', ->
|
|
417
417
|
Trigger.click($link)
|
418
418
|
expect(@lastRequest().method).toEqual 'POST'
|
419
419
|
|
420
|
+
describe '[up-drawer]', ->
|
421
|
+
|
422
|
+
beforeEach ->
|
423
|
+
up.motion.config.enabled = false
|
424
|
+
|
425
|
+
it 'slides in a drawer that covers the full height of the screen', (done) ->
|
426
|
+
$link = affix('a[href="/foo"][up-drawer=".target"]').text('label')
|
427
|
+
up.hello($link)
|
428
|
+
Trigger.clickSequence($link)
|
429
|
+
u.nextFrame =>
|
430
|
+
@respondWith '<div class="target">new text</div>'
|
431
|
+
expect(up.modal.isOpen()).toBe(true)
|
432
|
+
expect($('.up-modal').attr('up-flavor')).toEqual('drawer')
|
433
|
+
windowHeight = u.clientSize().height
|
434
|
+
modalHeight = $('.up-modal-content').outerHeight()
|
435
|
+
expect(modalHeight).toEqual(windowHeight)
|
436
|
+
expect($('.up-modal-content').offset()).toEqual(top: 0, left: 0)
|
437
|
+
done()
|
438
|
+
|
439
|
+
it 'puts the drawer on the right if the opening link sits in the right 50% of the screen', (done) ->
|
440
|
+
$link = affix('a[href="/foo"][up-drawer=".target"]').text('label')
|
441
|
+
$link.css
|
442
|
+
position: 'absolute'
|
443
|
+
right: '0'
|
444
|
+
up.hello($link)
|
445
|
+
Trigger.clickSequence($link)
|
446
|
+
u.nextFrame =>
|
447
|
+
@respondWith '<div class="target">new text</div>'
|
448
|
+
expect(up.modal.isOpen()).toBe(true)
|
449
|
+
windowWidth = u.clientSize().width
|
450
|
+
modalWidth = $('.up-modal-content').outerWidth()
|
451
|
+
scrollbarWidth = u.scrollbarWidth()
|
452
|
+
expect($('.up-modal-content').offset().left).toBeAround(windowWidth - modalWidth - scrollbarWidth, 1.0)
|
453
|
+
done()
|
420
454
|
|
421
455
|
describe '[up-close]', ->
|
422
456
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unpoly-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.31.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henning Koch
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-10-
|
11
|
+
date: 2016-10-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -139,8 +139,11 @@ files:
|
|
139
139
|
- spec_app/Rakefile
|
140
140
|
- spec_app/app/assets/images/.keep
|
141
141
|
- spec_app/app/assets/images/grid.png
|
142
|
+
- spec_app/app/assets/javascripts/bootstrap_manifest.coffee
|
142
143
|
- spec_app/app/assets/javascripts/integration_test.coffee
|
143
144
|
- spec_app/app/assets/javascripts/jasmine_specs.coffee
|
145
|
+
- spec_app/app/assets/stylesheets/_helpers.sass
|
146
|
+
- spec_app/app/assets/stylesheets/bootstrap_manifest.sass
|
144
147
|
- spec_app/app/assets/stylesheets/integration_test.sass
|
145
148
|
- spec_app/app/assets/stylesheets/jasmine_specs.sass
|
146
149
|
- spec_app/app/controllers/application_controller.rb
|