unpoly-rails 0.30.1 → 0.31.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 +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
|