effective_form_inputs 1.0.9 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +355 -207
- data/app/assets/javascripts/effective_form_inputs.js +1 -0
- data/app/assets/javascripts/effective_panel_select/effective_panel_select.js.coffee +211 -0
- data/app/assets/javascripts/effective_panel_select/initialize.js.coffee +12 -0
- data/app/assets/javascripts/effective_panel_select/input.js +2 -0
- data/app/assets/stylesheets/effective_form_inputs.scss +1 -0
- data/app/assets/stylesheets/effective_panel_select/input.scss +86 -0
- data/app/models/effective/form_builder_inputs.rb +5 -0
- data/app/models/inputs/effective_panel_select/input.rb +107 -0
- data/app/models/inputs/effective_panel_select_input.rb +18 -0
- data/app/views/effective/effective_panel_select/_input.html.haml +52 -0
- data/lib/effective_form_inputs/version.rb +1 -1
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a75831223cd401c30495c973058cfc192ba3fced
|
4
|
+
data.tar.gz: b8fd17c7f18fbb59b3392d96277c50177948c432
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 712f1cd5a0063b6be125c10fef55cc494bc27b379a6e9169c0e2d49bead07a44e86fb1ecbd488b0c4a54c5564ee81711688670be814738142f3a9892a910c267
|
7
|
+
data.tar.gz: 56a35b5d732b3401a44f5a61d85a2bcb6b2ee34b62c633637b12e4e47f2a768786c16448c579a03b91836dba34730196bdf3de480fb6bb633c586616cfd90048
|
data/README.md
CHANGED
@@ -71,6 +71,99 @@ $('input.effective_date_time_picker').datetimepicker
|
|
71
71
|
Any options passed in this way will be used to initialize the underlying javascript libraries.
|
72
72
|
|
73
73
|
|
74
|
+
## Effective CKEditor Text Area
|
75
|
+
|
76
|
+
This custom form input replaces a standard textarea with a CKEditor html rich text area.
|
77
|
+
|
78
|
+
It is based on the widely used:
|
79
|
+
|
80
|
+
CKEditor (http://ckeditor.com/)
|
81
|
+
|
82
|
+
and built ontop of
|
83
|
+
|
84
|
+
effective_ckeditor (https://github.com/code-and-effect/effective_ckeditor/)
|
85
|
+
|
86
|
+
### Installation
|
87
|
+
|
88
|
+
You must first install [effective_ckeditor](https://github.com/code-and-effect/effective_ckeditor/)
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
gem 'effective_ckeditor'
|
92
|
+
```
|
93
|
+
|
94
|
+
Depending on how often you're going to display this form input, you now have two options:
|
95
|
+
|
96
|
+
- You can do nothing, and when this form input is displayed it will use javascript to load the ckeditor .js and .css file on $(ready). It will make 2 additional requests, slowing down your page load by a moment.
|
97
|
+
|
98
|
+
- Or, when you intend to use the input quite a bit, it's faster to add the effective_ckeditor resources to the asset pipeline. However, it will increase the asset payload by around 200kb.
|
99
|
+
|
100
|
+
To add it to the asset pipeline, put the following to your application.js:
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
//= require effective_ckeditor
|
104
|
+
```
|
105
|
+
|
106
|
+
and in your application.css, add:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
*= require effective_ckeditor
|
110
|
+
```
|
111
|
+
|
112
|
+
There are no additional effective_ckeditor installation steps.
|
113
|
+
|
114
|
+
|
115
|
+
If you've already installed the 'All Form Inputs' assets (see above), there are no additional installation steps.
|
116
|
+
|
117
|
+
To install this form input individually, add the following to your application.js:
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
//= require effective_ckeditor_text_area/input
|
121
|
+
```
|
122
|
+
|
123
|
+
### Usage
|
124
|
+
|
125
|
+
As a Rails Form Helper input:
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
= form_for @post do |f|
|
129
|
+
= f.effective_ckeditor_text_area :body
|
130
|
+
```
|
131
|
+
|
132
|
+
As a SimpleForm input:
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
= simple_form_for @post do |f|
|
136
|
+
= f.input :body, :as => :effective_ckeditor_text_area
|
137
|
+
```
|
138
|
+
|
139
|
+
### Options
|
140
|
+
|
141
|
+
You can specify the `toolbar` as `'full'` or `'simple'`:
|
142
|
+
|
143
|
+
The full toolbar includes Image, oEmbed and Assets, wheras simple does not.
|
144
|
+
|
145
|
+
```ruby
|
146
|
+
= f.input :body, :as => :effective_ckeditor_text_area, :toolbar => 'full'
|
147
|
+
= f.input :body, :as => :effective_ckeditor_text_area, :toolbar => 'simple'
|
148
|
+
```
|
149
|
+
|
150
|
+
You can specify the `height` and `width`:
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
= f.input :body, :as => :effective_ckeditor_text_area, :height => '400px;', :width => '200px;'
|
154
|
+
```
|
155
|
+
|
156
|
+
And you can specify a `contentsCss` stylesheet:
|
157
|
+
|
158
|
+
By default, this loads the `asset_path('application.css')` file, you can also specify `:bootstrap`, `false`, a string url, or an array of urls.
|
159
|
+
|
160
|
+
When `:bootstrap`, this loads a CDN hosted bootstrap 3.3.7 stylesheet.
|
161
|
+
|
162
|
+
```ruby
|
163
|
+
= f.input :body, :as => :effective_ckeditor_text_area, :contentsCss => :bootstrap
|
164
|
+
```
|
165
|
+
|
166
|
+
|
74
167
|
## Effective Date Time Picker
|
75
168
|
|
76
169
|
This custom form input is based on the following awesome project:
|
@@ -244,15 +337,28 @@ validates :email, effective_email: true # Enforces same format as above
|
|
244
337
|
|
245
338
|
There are no javascript options for this input.
|
246
339
|
|
247
|
-
## Effective Static Control
|
248
340
|
|
249
|
-
|
341
|
+
## Effective Panel Select
|
250
342
|
|
251
|
-
|
343
|
+
A totally new way to do grouped collection selects.
|
344
|
+
|
345
|
+
Looks like a select field, but when expanded, the usual popup is replaced with a slidedown tabbed panel.
|
252
346
|
|
253
347
|
### Installation
|
254
348
|
|
255
|
-
|
349
|
+
If you've already installed the 'All Form Inputs' assets (see above), there are no additional installation steps.
|
350
|
+
|
351
|
+
To install this form input individually, add the following to your application.js:
|
352
|
+
|
353
|
+
```ruby
|
354
|
+
//= require effective_panel_select/input
|
355
|
+
```
|
356
|
+
|
357
|
+
and add the following to your application.css:
|
358
|
+
|
359
|
+
```ruby
|
360
|
+
*= require effective_panel_select/input
|
361
|
+
```
|
256
362
|
|
257
363
|
### Usage
|
258
364
|
|
@@ -260,19 +366,237 @@ As a Rails Form Helper input:
|
|
260
366
|
|
261
367
|
```ruby
|
262
368
|
= form_for @user do |f|
|
263
|
-
= f.
|
369
|
+
= f.effective_panel_select :category, categories_collection
|
264
370
|
```
|
265
371
|
|
266
|
-
|
372
|
+
and as a SimpleForm input:
|
267
373
|
|
268
374
|
```ruby
|
269
375
|
= simple_form_for @user do |f|
|
270
|
-
= f.input :
|
376
|
+
= f.input :category, as: :effective_panel_select, collection: categories_collection
|
377
|
+
```
|
378
|
+
|
379
|
+
### Collection
|
380
|
+
|
381
|
+
The collection is the same as a grouped select collection:
|
382
|
+
|
383
|
+
```ruby
|
384
|
+
collection: {'Active' => Post.active, 'Past' => Post.past}
|
385
|
+
collection: {'Active' => [['Post A', 1], ['Post B', 2]], 'Past' => [['Post C', 3], ['Post D', 4]]}
|
386
|
+
```
|
387
|
+
|
388
|
+
Each group, 'Active' and 'Past', will have its own tab. And its options selectable inside it.
|
389
|
+
|
390
|
+
### Options
|
391
|
+
|
392
|
+
The default `input_js: options` used to initialize this form input are as follows:
|
393
|
+
|
394
|
+
```ruby
|
395
|
+
{
|
396
|
+
placeholder: 'Please choose',
|
397
|
+
invade: '.row',
|
398
|
+
collapseOnSelect: true, # Close the panel when an item is selected
|
399
|
+
resetOnCollapse: true, # Reset the panel to its selected value when collapsed
|
400
|
+
keepFetched: false # Keep fetched pages instead of clearing them from the DOM on reset
|
401
|
+
showCount: false # Show number of categories in each group on the tab pane
|
402
|
+
}
|
403
|
+
```
|
404
|
+
|
405
|
+
and there are also options that control the collection behaviour:
|
406
|
+
|
407
|
+
```ruby
|
408
|
+
{
|
409
|
+
label_method: :to_s,
|
410
|
+
value_method: :to_s,
|
411
|
+
group_label_method: :first,
|
412
|
+
group_method: :second,
|
413
|
+
option_value_method: :first,
|
414
|
+
option_key_method: :second
|
415
|
+
}
|
416
|
+
```
|
417
|
+
|
418
|
+
### AJAX
|
419
|
+
|
420
|
+
Initialize the input with ajax options to display inline each resource's show page.
|
421
|
+
|
422
|
+
HTML is fetched from the server using `$.load`.
|
423
|
+
|
424
|
+
Initialize your input as follows:
|
425
|
+
|
426
|
+
```ruby
|
427
|
+
= f.input :category_id, as: :effective_panel_select, collection: categories_collection,
|
428
|
+
input_js: { ajax: { url: category_path(':id') } }
|
429
|
+
```
|
430
|
+
|
431
|
+
Here the url should be `/categories/:id`. The string `:id` (including the :) will be replaced by the selected value.
|
432
|
+
|
433
|
+
A controller action to handle this ajax request looks like:
|
434
|
+
|
435
|
+
```ruby
|
436
|
+
def show
|
437
|
+
@category = Category.find(params[:id])
|
438
|
+
|
439
|
+
# An effective panel select GET request will have effective_panel_select: true
|
440
|
+
if params[:effective_panel_select]
|
441
|
+
render layout: false
|
442
|
+
end
|
443
|
+
end
|
444
|
+
```
|
445
|
+
|
446
|
+
Or, you can render the normal show page, with layout, and use `$.load` target.
|
447
|
+
|
448
|
+
```ruby
|
449
|
+
= f.input :category_id, as: :effective_panel_select, collection: categories_collection,
|
450
|
+
input_js: { ajax: { url: category_path(':id'), target: '#category' } }
|
451
|
+
```
|
452
|
+
|
453
|
+
By default, any fetched pages are `remove()` from the DOM when the panel is reset (on collapse).
|
454
|
+
|
455
|
+
You can change this behaviour with `resetOnCollapse` and `keepFetched`.
|
456
|
+
|
457
|
+
### Invade
|
458
|
+
|
459
|
+
By default, when expanded, the panel will invade -- that is `detach()` and `attach()` itself -- to its closest `$('.row')`.
|
460
|
+
|
461
|
+
The invaded parent DOM node has its children hidden, and just the panel is displayed.
|
462
|
+
|
463
|
+
Disable this behaviour by passing `invade: false` or tweak it with a different selector `invade: '.container'`.
|
464
|
+
|
465
|
+
### Programatic access
|
466
|
+
|
467
|
+
An event is fired when the panel's value changes:
|
468
|
+
|
469
|
+
```coffeescript
|
470
|
+
$(document).on 'change', '.effective-panel-select', (event) ->
|
471
|
+
console.log $(event.currentTarget).effectivePanelSelect('val')
|
472
|
+
```
|
473
|
+
|
474
|
+
and you can manually do the following:
|
475
|
+
|
476
|
+
```javascript
|
477
|
+
$('.effective-panel-select').effectivePanelSelect('toggle')
|
478
|
+
$('.effective-panel-select').effectivePanelSelect('expand')
|
479
|
+
$('.effective-panel-select').effectivePanelSelect('collapse')
|
480
|
+
```
|
481
|
+
|
482
|
+
```javascript
|
483
|
+
$('.effective-panel-select').effectivePanelSelect('val')
|
484
|
+
$('.effective-panel-select').effectivePanelSelect('val', 123) # setVal
|
485
|
+
$('.effective-panel-select').effectivePanelSelect('title')
|
486
|
+
$('.effective-panel-select').effectivePanelSelect('clear')
|
487
|
+
```
|
488
|
+
|
489
|
+
|
490
|
+
## Effective Price
|
491
|
+
|
492
|
+
This custom form input uses no 3rd party jQuery plugins.
|
493
|
+
|
494
|
+
It displays a currency formatted value `100.00` but posts the "price as integer" value of `10000` to the server.
|
495
|
+
|
496
|
+
Think about this value as "the number of cents".
|
497
|
+
|
498
|
+
|
499
|
+
### Installation
|
500
|
+
|
501
|
+
If you've already installed the 'All Form Inputs' assets (see above), there are no additional installation steps.
|
502
|
+
|
503
|
+
To install this form input individually, add the following to your application.js:
|
504
|
+
|
505
|
+
```ruby
|
506
|
+
//= require effective_price/input
|
507
|
+
```
|
508
|
+
|
509
|
+
### Usage
|
510
|
+
|
511
|
+
As a Rails Form Helper input:
|
512
|
+
|
513
|
+
```ruby
|
514
|
+
= form_for @product do |f|
|
515
|
+
= f.effective_price :price
|
516
|
+
```
|
517
|
+
|
518
|
+
As a SimpleForm input:
|
519
|
+
|
520
|
+
```ruby
|
521
|
+
= simple_form_for @product do |f|
|
522
|
+
= f.input :price, :as => :effective_price
|
523
|
+
```
|
524
|
+
|
525
|
+
As a SimpleForm input without the input group (glyphicon-usd glyphicon)
|
526
|
+
|
527
|
+
```ruby
|
528
|
+
= simple_form_for @product do |f|
|
529
|
+
= f.input :price, :as => :effective_price, :input_group => false
|
271
530
|
```
|
272
531
|
|
273
532
|
### Options
|
274
533
|
|
275
|
-
|
534
|
+
You can pass `include_blank: true` to allow `nil`. By default `nil`s are convereted, displayed and submitted as `$0.00`.
|
535
|
+
|
536
|
+
```ruby
|
537
|
+
= f.input :price, :as => :effective_price, :include_blank => true
|
538
|
+
```
|
539
|
+
|
540
|
+
### Rails Helper
|
541
|
+
|
542
|
+
This input also installs a rails view helper `price_to_currency` that takes a value like `10000` and displays it as `$100.00`
|
543
|
+
|
544
|
+
|
545
|
+
## Effective Radio Buttons
|
546
|
+
|
547
|
+
This custom form input adds image support to the SimpleForm radio buttons. It doesn't really work as a regular rails form helper.
|
548
|
+
|
549
|
+
### Installation
|
550
|
+
|
551
|
+
If you've already installed the 'All Form Inputs' assets (see above), there are no additional installation steps.
|
552
|
+
|
553
|
+
To install this form input individually, add the following to your application.css:
|
554
|
+
|
555
|
+
```ruby
|
556
|
+
*= require effective_radio_buttons/input
|
557
|
+
```
|
558
|
+
|
559
|
+
There is no javascript.
|
560
|
+
|
561
|
+
### Bootstrap button group
|
562
|
+
|
563
|
+
Pass `buttons: true` to the input options to render as a bootstrap button group.
|
564
|
+
|
565
|
+
As a SimpleForm input:
|
566
|
+
|
567
|
+
```ruby
|
568
|
+
= simple_form_for @user do |f|
|
569
|
+
= f.input :breakfast,
|
570
|
+
:as => :effective_radio_buttons,
|
571
|
+
:collection => ['eggs', 'toast', 'bacon'],
|
572
|
+
:buttons => true
|
573
|
+
```
|
574
|
+
|
575
|
+
### Inline
|
576
|
+
|
577
|
+
Pass `inline: true` to the input options to render the radio buttons inline.
|
578
|
+
|
579
|
+
As a SimpleForm input:
|
580
|
+
|
581
|
+
```ruby
|
582
|
+
= simple_form_for @user do |f|
|
583
|
+
= f.input :breakfast,
|
584
|
+
:as => :effective_radio_buttons,
|
585
|
+
:collection => ['eggs', 'toast', 'bacon'],
|
586
|
+
:inline => true
|
587
|
+
```
|
588
|
+
|
589
|
+
### Images
|
590
|
+
|
591
|
+
Pass `images: []` as an array of strings with the same length as the collection to render image buttons.
|
592
|
+
|
593
|
+
```ruby
|
594
|
+
= simple_form_for @user do |f|
|
595
|
+
= f.input :breakfast,
|
596
|
+
:as => :effective_radio_buttons,
|
597
|
+
:collection => ['eggs', 'toast', 'bacon'],
|
598
|
+
:images => [asset_path('eggs.png'), asset_path('toast.png'), asset_path('bacon.png')]
|
599
|
+
```
|
276
600
|
|
277
601
|
|
278
602
|
## Effective Select
|
@@ -434,22 +758,15 @@ $(document).on 'change', '.something', (event) ->
|
|
434
758
|
There is currently no support for using AJAX to load remote data. This feature is supported by the underlying select2 library and will be implemented here at a future point.
|
435
759
|
|
436
760
|
|
437
|
-
## Effective
|
438
|
-
|
439
|
-
This custom form input uses a jQuery maskedInput plugin from the following awesome project:
|
761
|
+
## Effective Static Control
|
440
762
|
|
441
|
-
|
763
|
+
A bootstrap3 Static control input.
|
442
764
|
|
765
|
+
Renders `<p class='form-control-static'>value</p>` with the appropriate SimpleForm wrappings.
|
443
766
|
|
444
767
|
### Installation
|
445
768
|
|
446
|
-
|
447
|
-
|
448
|
-
To install this form input individually, add the following to your application.js:
|
449
|
-
|
450
|
-
```ruby
|
451
|
-
//= require effective_tel/input
|
452
|
-
```
|
769
|
+
There are no installation steps required for this form input
|
453
770
|
|
454
771
|
### Usage
|
455
772
|
|
@@ -457,37 +774,26 @@ As a Rails Form Helper input:
|
|
457
774
|
|
458
775
|
```ruby
|
459
776
|
= form_for @user do |f|
|
460
|
-
= f.
|
777
|
+
= f.effective_static_control :category
|
461
778
|
```
|
462
779
|
|
463
780
|
As a SimpleForm input:
|
464
781
|
|
465
782
|
```ruby
|
466
783
|
= simple_form_for @user do |f|
|
467
|
-
= f.input :
|
784
|
+
= f.input :category, as: :effective_static_control
|
785
|
+
= f.input :category, as: :effective_static_control
|
468
786
|
```
|
469
787
|
|
470
|
-
|
471
|
-
|
472
|
-
```ruby
|
473
|
-
= simple_form_for @user do |f|
|
474
|
-
= f.input :phone, :as => :effective_tel, :input_group => false
|
475
|
-
```
|
476
|
-
|
477
|
-
You should add a server side validation to enforce the default "(123) 555-1234" with optional "x123" extension format:
|
478
|
-
|
479
|
-
```ruby
|
480
|
-
validates :phone, format: { with: /\A\(\d{3}\) \d{3}-\d{4}( x\d+)?\Z/ }
|
481
|
-
validates :phone, effective_tel: true # Enforces same format as above
|
482
|
-
```
|
788
|
+
### Options
|
483
789
|
|
484
|
-
|
790
|
+
There are no default options for this form input.
|
485
791
|
|
486
|
-
|
792
|
+
## Effective Tel(ephone)
|
487
793
|
|
488
|
-
|
794
|
+
This custom form input uses a jQuery maskedInput plugin from the following awesome project:
|
489
795
|
|
490
|
-
|
796
|
+
jQuery Masked Input Plugin (https://github.com/digitalBush/jquery.maskedinput)
|
491
797
|
|
492
798
|
|
493
799
|
### Installation
|
@@ -497,7 +803,7 @@ If you've already installed the 'All Form Inputs' assets (see above), there are
|
|
497
803
|
To install this form input individually, add the following to your application.js:
|
498
804
|
|
499
805
|
```ruby
|
500
|
-
//= require
|
806
|
+
//= require effective_tel/input
|
501
807
|
```
|
502
808
|
|
503
809
|
### Usage
|
@@ -505,38 +811,31 @@ To install this form input individually, add the following to your application.j
|
|
505
811
|
As a Rails Form Helper input:
|
506
812
|
|
507
813
|
```ruby
|
508
|
-
= form_for @
|
509
|
-
= f.
|
814
|
+
= form_for @user do |f|
|
815
|
+
= f.effective_tel :phone
|
510
816
|
```
|
511
817
|
|
512
818
|
As a SimpleForm input:
|
513
819
|
|
514
820
|
```ruby
|
515
|
-
= simple_form_for @
|
516
|
-
= f.input :
|
821
|
+
= simple_form_for @user do |f|
|
822
|
+
= f.input :phone, :as => :effective_tel
|
517
823
|
```
|
518
824
|
|
519
|
-
As a SimpleForm input without the input group (
|
825
|
+
As a SimpleForm input without the input group (phone glyphicon)
|
520
826
|
|
521
827
|
```ruby
|
522
|
-
= simple_form_for @
|
523
|
-
= f.input :
|
828
|
+
= simple_form_for @user do |f|
|
829
|
+
= f.input :phone, :as => :effective_tel, :input_group => false
|
524
830
|
```
|
525
831
|
|
526
|
-
|
527
|
-
|
528
|
-
You can pass `include_blank: true` to allow `nil`. By default `nil`s are convereted, displayed and submitted as `$0.00`.
|
832
|
+
You should add a server side validation to enforce the default "(123) 555-1234" with optional "x123" extension format:
|
529
833
|
|
530
834
|
```ruby
|
531
|
-
|
835
|
+
validates :phone, format: { with: /\A\(\d{3}\) \d{3}-\d{4}( x\d+)?\Z/ }
|
836
|
+
validates :phone, effective_tel: true # Enforces same format as above
|
532
837
|
```
|
533
838
|
|
534
|
-
|
535
|
-
### Rails Helper
|
536
|
-
|
537
|
-
This input also installs a rails view helper `price_to_currency` that takes a value like `10000` and displays it as `$100.00`
|
538
|
-
|
539
|
-
|
540
839
|
## Effective URL
|
541
840
|
|
542
841
|
This custom form input enforces the url starts with http:// or https://
|
@@ -587,156 +886,6 @@ validates :website, effective_url: true # Enforced same format as above
|
|
587
886
|
|
588
887
|
You can pass `fontawesome: false` and `glyphicon: false` to tweak the automatic social icon display behaviour.
|
589
888
|
|
590
|
-
|
591
|
-
## Effective CKEditor Text Area
|
592
|
-
|
593
|
-
This custom form input replaces a standard textarea with a CKEditor html rich text area.
|
594
|
-
|
595
|
-
It is based on the widely used:
|
596
|
-
|
597
|
-
CKEditor (http://ckeditor.com/)
|
598
|
-
|
599
|
-
and built ontop of
|
600
|
-
|
601
|
-
effective_ckeditor (https://github.com/code-and-effect/effective_ckeditor/)
|
602
|
-
|
603
|
-
### Installation
|
604
|
-
|
605
|
-
You must first install [effective_ckeditor](https://github.com/code-and-effect/effective_ckeditor/)
|
606
|
-
|
607
|
-
```ruby
|
608
|
-
gem 'effective_ckeditor'
|
609
|
-
```
|
610
|
-
|
611
|
-
Depending on how often you're going to display this form input, you now have two options:
|
612
|
-
|
613
|
-
- You can do nothing, and when this form input is displayed it will use javascript to load the ckeditor .js and .css file on $(ready). It will make 2 additional requests, slowing down your page load by a moment.
|
614
|
-
|
615
|
-
- Or, when you intend to use the input quite a bit, it's faster to add the effective_ckeditor resources to the asset pipeline. However, it will increase the asset payload by around 200kb.
|
616
|
-
|
617
|
-
To add it to the asset pipeline, put the following to your application.js:
|
618
|
-
|
619
|
-
```ruby
|
620
|
-
//= require effective_ckeditor
|
621
|
-
```
|
622
|
-
|
623
|
-
and in your application.css, add:
|
624
|
-
|
625
|
-
```ruby
|
626
|
-
*= require effective_ckeditor
|
627
|
-
```
|
628
|
-
|
629
|
-
There are no additional effective_ckeditor installation steps.
|
630
|
-
|
631
|
-
|
632
|
-
If you've already installed the 'All Form Inputs' assets (see above), there are no additional installation steps.
|
633
|
-
|
634
|
-
To install this form input individually, add the following to your application.js:
|
635
|
-
|
636
|
-
```ruby
|
637
|
-
//= require effective_ckeditor_text_area/input
|
638
|
-
```
|
639
|
-
|
640
|
-
### Usage
|
641
|
-
|
642
|
-
As a Rails Form Helper input:
|
643
|
-
|
644
|
-
```ruby
|
645
|
-
= form_for @post do |f|
|
646
|
-
= f.effective_ckeditor_text_area :body
|
647
|
-
```
|
648
|
-
|
649
|
-
As a SimpleForm input:
|
650
|
-
|
651
|
-
```ruby
|
652
|
-
= simple_form_for @post do |f|
|
653
|
-
= f.input :body, :as => :effective_ckeditor_text_area
|
654
|
-
```
|
655
|
-
|
656
|
-
### Options
|
657
|
-
|
658
|
-
You can specify the `toolbar` as `'full'` or `'simple'`:
|
659
|
-
|
660
|
-
The full toolbar includes Image, oEmbed and Assets, wheras simple does not.
|
661
|
-
|
662
|
-
```ruby
|
663
|
-
= f.input :body, :as => :effective_ckeditor_text_area, :toolbar => 'full'
|
664
|
-
= f.input :body, :as => :effective_ckeditor_text_area, :toolbar => 'simple'
|
665
|
-
```
|
666
|
-
|
667
|
-
You can specify the `height` and `width`:
|
668
|
-
|
669
|
-
```ruby
|
670
|
-
= f.input :body, :as => :effective_ckeditor_text_area, :height => '400px;', :width => '200px;'
|
671
|
-
```
|
672
|
-
|
673
|
-
And you can specify a `contentsCss` stylesheet:
|
674
|
-
|
675
|
-
By default, this loads the `asset_path('application.css')` file, you can also specify `:bootstrap`, `false`, a string url, or an array of urls.
|
676
|
-
|
677
|
-
When `:bootstrap`, this loads a CDN hosted bootstrap 3.3.7 stylesheet.
|
678
|
-
|
679
|
-
```ruby
|
680
|
-
= f.input :body, :as => :effective_ckeditor_text_area, :contentsCss => :bootstrap
|
681
|
-
```
|
682
|
-
|
683
|
-
|
684
|
-
## Effective Radio Buttons
|
685
|
-
|
686
|
-
This custom form input adds image support to the SimpleForm radio buttons. It doesn't really work as a regular rails form helper.
|
687
|
-
|
688
|
-
### Installation
|
689
|
-
|
690
|
-
If you've already installed the 'All Form Inputs' assets (see above), there are no additional installation steps.
|
691
|
-
|
692
|
-
To install this form input individually, add the following to your application.css:
|
693
|
-
|
694
|
-
```ruby
|
695
|
-
*= require effective_radio_buttons/input
|
696
|
-
```
|
697
|
-
|
698
|
-
There is no javascript.
|
699
|
-
|
700
|
-
### Bootstrap button group
|
701
|
-
|
702
|
-
Pass `buttons: true` to the input options to render as a bootstrap button group.
|
703
|
-
|
704
|
-
As a SimpleForm input:
|
705
|
-
|
706
|
-
```ruby
|
707
|
-
= simple_form_for @user do |f|
|
708
|
-
= f.input :breakfast,
|
709
|
-
:as => :effective_radio_buttons,
|
710
|
-
:collection => ['eggs', 'toast', 'bacon'],
|
711
|
-
:buttons => true
|
712
|
-
```
|
713
|
-
|
714
|
-
### Inline
|
715
|
-
|
716
|
-
Pass `inline: true` to the input options to render the radio buttons inline.
|
717
|
-
|
718
|
-
As a SimpleForm input:
|
719
|
-
|
720
|
-
```ruby
|
721
|
-
= simple_form_for @user do |f|
|
722
|
-
= f.input :breakfast,
|
723
|
-
:as => :effective_radio_buttons,
|
724
|
-
:collection => ['eggs', 'toast', 'bacon'],
|
725
|
-
:inline => true
|
726
|
-
```
|
727
|
-
|
728
|
-
### Images
|
729
|
-
|
730
|
-
Pass `images: []` as an array of strings with the same length as the collection to render image buttons.
|
731
|
-
|
732
|
-
```ruby
|
733
|
-
= simple_form_for @user do |f|
|
734
|
-
= f.input :breakfast,
|
735
|
-
:as => :effective_radio_buttons,
|
736
|
-
:collection => ['eggs', 'toast', 'bacon'],
|
737
|
-
:images => [asset_path('eggs.png'), asset_path('toast.png'), asset_path('bacon.png')]
|
738
|
-
```
|
739
|
-
|
740
889
|
## License
|
741
890
|
|
742
891
|
MIT License. Copyright [Code and Effect Inc.](http://www.codeandeffect.com/)
|
@@ -747,7 +896,6 @@ The authors of this gem are not associated with any of the awesome projects used
|
|
747
896
|
|
748
897
|
We are just extending these existing community projects for ease of use with Rails Form Helper and SimpleForm.
|
749
898
|
|
750
|
-
|
751
899
|
## Contributing
|
752
900
|
|
753
901
|
1. Fork it
|
@@ -1,6 +1,7 @@
|
|
1
1
|
//= require ./effective_ckeditor_text_area/input
|
2
2
|
//= require ./effective_date_time_picker/input
|
3
3
|
//= require ./effective_date_picker/input
|
4
|
+
//= require ./effective_panel_select/input
|
4
5
|
//= require ./effective_price/input
|
5
6
|
//= require ./effective_select/input
|
6
7
|
//= require ./effective_tel/input
|
@@ -0,0 +1,211 @@
|
|
1
|
+
# We initialize this on the .panel
|
2
|
+
|
3
|
+
(($, window) ->
|
4
|
+
class EffectivePanelSelect
|
5
|
+
defaults:
|
6
|
+
placeholder: 'Please choose'
|
7
|
+
invade: '.row'
|
8
|
+
collapseOnSelect: true
|
9
|
+
resetOnCollapse: true
|
10
|
+
keepFetched: false # Keep any fetched ajax pages in the dom. Otherwise they're freed on reset()
|
11
|
+
ajax:
|
12
|
+
url: '' # /exercises/:id The string ':id' will be replaced with the viewed item value
|
13
|
+
target: '' # #container The string to pass to load
|
14
|
+
|
15
|
+
panel: null # Our root node. the .panel element
|
16
|
+
input: null # The input[type=hidden] field where we keep the selected value
|
17
|
+
label: null # Contains either a %span.selection-placeholder, or a %span.selection-clear and %span.selection-label
|
18
|
+
selector: null # Root node of the container
|
19
|
+
invading: false # If we're currently invading the closest @options.invade selector
|
20
|
+
|
21
|
+
constructor: (el, options) ->
|
22
|
+
@panel = $(el)
|
23
|
+
@input = @panel.find("input[type='hidden']")
|
24
|
+
@label = @panel.find('.selection-title')
|
25
|
+
@selector = @panel.children('.selector')
|
26
|
+
@tabList = @selector.find('ul.nav').first()
|
27
|
+
@tabContent = @selector.find('.tab-content').first()
|
28
|
+
|
29
|
+
@options = $.extend({}, @defaults, options)
|
30
|
+
|
31
|
+
@initTabs()
|
32
|
+
@initEvents()
|
33
|
+
@initInvade()
|
34
|
+
@initAjax()
|
35
|
+
true
|
36
|
+
|
37
|
+
# So we need to assign unique IDs to all the group tabs so we can have multiple selectors per page
|
38
|
+
# This should also handle cocoon gem
|
39
|
+
|
40
|
+
initTabs: ->
|
41
|
+
unique = new Date().getTime()
|
42
|
+
|
43
|
+
@tabList.find("a[data-toggle='tab']").each (index, item) =>
|
44
|
+
item = $(item)
|
45
|
+
href = item.attr('href')
|
46
|
+
tab = @tabContent.children(href)
|
47
|
+
|
48
|
+
href = href + '-' + unique + index
|
49
|
+
|
50
|
+
item.attr('href', href)
|
51
|
+
tab.attr('id', href.substring(1))
|
52
|
+
|
53
|
+
initEvents: ->
|
54
|
+
@panel.on 'click', '.selection', (event) => @toggle()
|
55
|
+
@panel.on 'click', '.selection-clear', (event) => @clear() and false
|
56
|
+
@panel.on 'click', '[data-item-value]', (event) => @val($(event.currentTarget).data('item-value')) and false
|
57
|
+
@panel.on 'click', '[data-fetch-item]', (event) => @fetch($(event.currentTarget).closest('[data-item-value]').data('item-value')) and false
|
58
|
+
@panel.on 'click', '.fetched-clear', (event) => @reset() and false
|
59
|
+
@panel.on 'click', '.fetched-select', (event) => @setVal($(event.currentTarget).data('item-value')) and false
|
60
|
+
|
61
|
+
initInvade: ->
|
62
|
+
return if @options.invade == false || @options.invade == 'false'
|
63
|
+
@home = @panel.parent()
|
64
|
+
@away = $("<div class='col-xs-12 effective_panel_select'></div>")
|
65
|
+
|
66
|
+
initAjax: ->
|
67
|
+
return unless @options.ajax && @options.ajax.url.length
|
68
|
+
@fetched = @selector.find('.fetched')
|
69
|
+
|
70
|
+
# Rest of these are commands
|
71
|
+
|
72
|
+
# Expand / Collapse
|
73
|
+
# $('.effective-panel-select').effectivePanelSelect('toggle')
|
74
|
+
toggle: ->
|
75
|
+
if @panel.hasClass('expanded') then @collapse() else @expand()
|
76
|
+
|
77
|
+
expand: ->
|
78
|
+
@invade() if @options.invade
|
79
|
+
@selector.slideDown 'fast', => @panel.addClass('expanded')
|
80
|
+
|
81
|
+
collapse: ->
|
82
|
+
@selector.slideUp 'fast', =>
|
83
|
+
@panel.removeClass('expanded')
|
84
|
+
@reset() if @options.resetOnCollapse
|
85
|
+
@retreat() if @options.invade
|
86
|
+
|
87
|
+
# Invade the nearest '.row'
|
88
|
+
invade: ->
|
89
|
+
target = @home.closest(@options.invade)
|
90
|
+
return unless target.length && !@invading
|
91
|
+
|
92
|
+
@panel.detach()
|
93
|
+
target.children().hide()
|
94
|
+
@away.append(@panel).show()
|
95
|
+
|
96
|
+
target.append(@away)
|
97
|
+
|
98
|
+
@invading = true
|
99
|
+
|
100
|
+
# Reset to default position
|
101
|
+
retreat: ->
|
102
|
+
target = @away.closest(@options.invade)
|
103
|
+
return unless target.length && @invading
|
104
|
+
|
105
|
+
@panel.detach()
|
106
|
+
target.children().show()
|
107
|
+
@away.hide()
|
108
|
+
|
109
|
+
hint = @home.children(':not(label)')
|
110
|
+
if hint.length then @panel.insertBefore(hint) else @home.append(@panel)
|
111
|
+
|
112
|
+
@invading = false
|
113
|
+
|
114
|
+
# Get / Set / Clear selection
|
115
|
+
val: (args...) ->
|
116
|
+
if args.length == 0 then @input.val() else @setVal(args[0])
|
117
|
+
|
118
|
+
title: (item) ->
|
119
|
+
(item || @label).find('a').clone().children().remove().end().text()
|
120
|
+
|
121
|
+
# Sets the input value, and the selected value text
|
122
|
+
setVal: (value) ->
|
123
|
+
@input.val(value)
|
124
|
+
|
125
|
+
if value == null || value == undefined || value == ''
|
126
|
+
@label.html("<span class='selection-placeholder'>#{@options.placeholder}</span>")
|
127
|
+
@reset()
|
128
|
+
else
|
129
|
+
$item = @selector.find("li[data-item-value='#{value}']").first()
|
130
|
+
label = @title($item)
|
131
|
+
|
132
|
+
@label.html("<span class='selection-clear'>x</span> <span class='selection-label'>#{label}</span>")
|
133
|
+
if @options.collapseOnSelect then @collapse() else @reset()
|
134
|
+
|
135
|
+
@panel.trigger 'change'
|
136
|
+
true
|
137
|
+
|
138
|
+
# Syncs the tabs to the current value
|
139
|
+
reset: ->
|
140
|
+
value = @val()
|
141
|
+
|
142
|
+
@fetched.children(':not(.top)').remove() if @fetched && @fetched.length && !@options.keepFetched
|
143
|
+
|
144
|
+
@selector.find("li.selected").removeClass('selected')
|
145
|
+
@selector.find('.active').removeClass('active')
|
146
|
+
|
147
|
+
if (value == null || value == undefined || value == '') == false
|
148
|
+
$item = @selector.find("li[data-item-value='#{value}']")
|
149
|
+
$item.addClass('selected').addClass('active')
|
150
|
+
|
151
|
+
$tab_pane = $item.closest('.tab-pane')
|
152
|
+
|
153
|
+
if $tab_pane.length
|
154
|
+
$tab = @selector.find("a[href='##{$tab_pane.attr('id')}']").parent('li')
|
155
|
+
$tab.addClass('selected').addClass('active')
|
156
|
+
$tab_pane.addClass('active')
|
157
|
+
|
158
|
+
clear: -> @val(null)
|
159
|
+
|
160
|
+
# Ajax fetch and view page
|
161
|
+
fetch: (value) ->
|
162
|
+
return unless @options.ajax && @options.ajax.url.length
|
163
|
+
|
164
|
+
fetched = @fetched.children("div[data-fetch='#{value}']")
|
165
|
+
|
166
|
+
if fetched.length == 0
|
167
|
+
fetched = $("<div data-fetch='#{value}'></div>")
|
168
|
+
|
169
|
+
fetched = fetched.load(@url(value), (response, status, xhr) =>
|
170
|
+
fetched.append('<p>This item is unavailable (ajax error)</p>') if status == 'error'
|
171
|
+
)
|
172
|
+
|
173
|
+
@fetched.append(fetched)
|
174
|
+
|
175
|
+
@fetched.parent().find('.active').removeClass('active')
|
176
|
+
@fetched.addClass('active').children(':not(.top)').hide()
|
177
|
+
fetched.show()
|
178
|
+
@fetched.children('.top').find('.fetched-select').data('item-value', value)
|
179
|
+
|
180
|
+
url: (value) ->
|
181
|
+
return unless @options.ajax && @options.ajax.url.length
|
182
|
+
|
183
|
+
url = @options.ajax.url.replace(':id', value)
|
184
|
+
|
185
|
+
# Add a data param
|
186
|
+
url = url + (if url.indexOf('?') == -1 then '?' else '&') + $.param(effective_panel_select: true)
|
187
|
+
|
188
|
+
# Add target
|
189
|
+
url = url + " #{@options.ajax.target}" if @options.ajax.target # jQuery .load('/things/13 #thing')
|
190
|
+
|
191
|
+
url
|
192
|
+
|
193
|
+
$.fn.extend effectivePanelSelect: (option, args...) ->
|
194
|
+
retval = @each
|
195
|
+
|
196
|
+
@each ->
|
197
|
+
$this = $(this)
|
198
|
+
data = $this.data('effectivePanelSelect')
|
199
|
+
|
200
|
+
$this.data('effectivePanelSelect', (data = new EffectivePanelSelect(this, option))) if !data
|
201
|
+
|
202
|
+
retval = data[option].apply(data, args) if typeof option == 'string'
|
203
|
+
$this
|
204
|
+
|
205
|
+
retval
|
206
|
+
|
207
|
+
) window.jQuery, window
|
208
|
+
|
209
|
+
$(document).on 'click', (event) ->
|
210
|
+
if !$(event.target).closest('.effective-panel-select').length
|
211
|
+
$('.effective-panel-select.initialized').effectivePanelSelect('collapse')
|
@@ -0,0 +1,12 @@
|
|
1
|
+
initialize = ->
|
2
|
+
$('div.effective-panel-select:not(.initialized)').each (i, element) ->
|
3
|
+
element = $(element)
|
4
|
+
options = element.data('input-js-options') || {}
|
5
|
+
|
6
|
+
$select = element.addClass('initialized').effectivePanelSelect(options)
|
7
|
+
|
8
|
+
$ -> initialize()
|
9
|
+
$(document).on 'page:change', -> initialize()
|
10
|
+
$(document).on 'turbolinks:load', -> initialize()
|
11
|
+
$(document).on 'turbolinks:render', -> initialize()
|
12
|
+
$(document).on 'cocoon:after-insert', -> initialize()
|
@@ -0,0 +1,86 @@
|
|
1
|
+
// The .effective-panel-select top level container is a div
|
2
|
+
// That is also a .panel and .panel-default
|
3
|
+
// Oftentimes, this will be inside a simple_form wrapper, so a div of .effective_panel_select will be above this.
|
4
|
+
|
5
|
+
.effective-panel-select { // This will also have the classes panel and .panel-default
|
6
|
+
margin-bottom: 0px;
|
7
|
+
|
8
|
+
li.selected {
|
9
|
+
font-weight: bold;
|
10
|
+
}
|
11
|
+
|
12
|
+
.selector {
|
13
|
+
display: none;
|
14
|
+
|
15
|
+
.tab-content { padding-top: 0px; }
|
16
|
+
}
|
17
|
+
|
18
|
+
.tab-pane.fetched { padding-right: 15px; }
|
19
|
+
|
20
|
+
.selection {
|
21
|
+
width: 100%;
|
22
|
+
font-family: "Open Sans", sans-serif;
|
23
|
+
font-size: 14px;
|
24
|
+
cursor: pointer;
|
25
|
+
}
|
26
|
+
|
27
|
+
.selection-title {
|
28
|
+
display: block;
|
29
|
+
height: 32px;
|
30
|
+
padding: 6px 24px 6px 12px;
|
31
|
+
overflow: hidden;
|
32
|
+
text-overflow: ellipsis;
|
33
|
+
white-space: nowrap;
|
34
|
+
}
|
35
|
+
|
36
|
+
.selection-clear {
|
37
|
+
width: 10px;
|
38
|
+
color: #999;
|
39
|
+
font-weight: bold;
|
40
|
+
&:hover { color: #333; }
|
41
|
+
}
|
42
|
+
|
43
|
+
.selection-placeholder {
|
44
|
+
color: #999;
|
45
|
+
white-space: nowrap;
|
46
|
+
}
|
47
|
+
|
48
|
+
.selection-arrow {
|
49
|
+
float: right;
|
50
|
+
|
51
|
+
width: 4px;
|
52
|
+
height: 4px;
|
53
|
+
margin-top: -14px;
|
54
|
+
margin-right: 18px;
|
55
|
+
|
56
|
+
b {
|
57
|
+
border-color: #999 transparent transparent transparent;
|
58
|
+
border-style: solid;
|
59
|
+
border-width: 4px 4px 0 4px;
|
60
|
+
margin-left: 4px;
|
61
|
+
margin-top: -2px;
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
.effective-panel-select.expanded {
|
67
|
+
margin-bottom: 15px;
|
68
|
+
|
69
|
+
border-color: #55afe9;
|
70
|
+
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
71
|
+
|
72
|
+
.selector { display: block; }
|
73
|
+
|
74
|
+
.selection-arrow {
|
75
|
+
margin-top: -38px;
|
76
|
+
|
77
|
+
b {
|
78
|
+
border-color: transparent transparent #999 transparent;
|
79
|
+
border-width: 0 4px 4px 4px;
|
80
|
+
}
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
.has-error {
|
85
|
+
.effective-panel-select { border-color: #a94442; }
|
86
|
+
}
|
@@ -12,6 +12,11 @@ module Effective
|
|
12
12
|
Inputs::EffectiveDatePicker::Input.new(@object, @object_name, @template, method, options, options).to_html
|
13
13
|
end
|
14
14
|
|
15
|
+
def effective_panel_select(method, options_tag = nil, options = {}, html_options = {})
|
16
|
+
options[:collection] = options_tag
|
17
|
+
Inputs::EffectivePanelSelect::Input.new(@object, @object_name, @template, method, options, html_options).to_html
|
18
|
+
end
|
19
|
+
|
15
20
|
def effective_price(method, options = {})
|
16
21
|
Inputs::EffectivePrice::Input.new(@object, @object_name, @template, method, options, options).to_html
|
17
22
|
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# This is a unique form input
|
2
|
+
# Takes in the same collection as a grouped select
|
3
|
+
# Displays the groups on the left, and each of the items on the right panel
|
4
|
+
# Only supports one category, and one kind of objects
|
5
|
+
# No polymorphic stuff
|
6
|
+
|
7
|
+
module Inputs
|
8
|
+
module EffectivePanelSelect
|
9
|
+
class Input < Effective::FormInput
|
10
|
+
delegate :grouped_collection_select, :hidden_field_tag, :text_field_tag, :render, to: :@template
|
11
|
+
|
12
|
+
def default_options
|
13
|
+
{ label_method: :to_s, value_method: :to_s, group_label_method: :first, group_method: :second, option_value_method: :first, option_key_method: :second }
|
14
|
+
end
|
15
|
+
|
16
|
+
def default_input_js
|
17
|
+
{ placeholder: 'Please choose', invade: '.row', collapseOnSelect: true, resetOnCollapse: true, showCount: false }
|
18
|
+
end
|
19
|
+
|
20
|
+
def default_input_html
|
21
|
+
{ class: 'effective_panel_select' }
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_html
|
25
|
+
render('effective/effective_panel_select/input', input: self)
|
26
|
+
end
|
27
|
+
|
28
|
+
def method_name
|
29
|
+
@method_name ||= @method.to_s.titleize.downcase
|
30
|
+
end
|
31
|
+
|
32
|
+
def ajax?
|
33
|
+
return true if js_options[:ajax]
|
34
|
+
end
|
35
|
+
|
36
|
+
def show_count?
|
37
|
+
return true if js_options[:showCount]
|
38
|
+
end
|
39
|
+
|
40
|
+
# option_value 1
|
41
|
+
# option_label Post A
|
42
|
+
# group_label Active
|
43
|
+
|
44
|
+
# 163
|
45
|
+
def option_value
|
46
|
+
value
|
47
|
+
end
|
48
|
+
|
49
|
+
# Post A
|
50
|
+
def option_label
|
51
|
+
return nil unless value.present?
|
52
|
+
@option_label || (_initialize_group_and_option; @option_label)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Active
|
56
|
+
def group_label
|
57
|
+
return nil unless value.present?
|
58
|
+
@group_label || (_initialize_group_and_option; @group_label)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Active
|
62
|
+
def group_value
|
63
|
+
return nil unless value.present?
|
64
|
+
@group_value || (_initialize_group_and_option; @group_value)
|
65
|
+
end
|
66
|
+
|
67
|
+
def _initialize_group_and_option
|
68
|
+
collection.each do |group, items|
|
69
|
+
items.each do |item|
|
70
|
+
if item.send(options[:option_key_method]) == value
|
71
|
+
@group_label = group.send(options[:group_label_method])
|
72
|
+
@group_value = group.send(options[:group_method])
|
73
|
+
@option_label = item.send(options[:option_value_method])
|
74
|
+
return
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
# This is a grouped polymorphic collection
|
82
|
+
# [['Active', [['Post A', 1], ['Post B', 2]]], ['Past', [['Post C', 3], ['Post D', 4]]]
|
83
|
+
def collection
|
84
|
+
@collection ||= begin
|
85
|
+
collection = options.delete(:collection) || []
|
86
|
+
grouped = collection[0].kind_of?(Array) && collection[0][1].respond_to?(:to_a) && (collection[0][1] != nil) # Array or ActiveRecord_Relation
|
87
|
+
|
88
|
+
if !grouped && collection.present?
|
89
|
+
raise "Grouped collection expecting a Hash {'Posts' => Post.all, 'Events' => Event.all} or a Hash {'Posts' => [['Post A', 1], ['Post B', 2]], 'Events' => [['Event A', 1], ['Event B', 2]]}"
|
90
|
+
end
|
91
|
+
|
92
|
+
collection.each_with_index do |(name, group), index|
|
93
|
+
collection[index][1] = group.respond_to?(:call) ? group.call : group.to_a
|
94
|
+
end
|
95
|
+
|
96
|
+
if collection[0][0].kind_of?(String)
|
97
|
+
options[:group_label_method] = :to_s
|
98
|
+
options[:group_method] = :to_s
|
99
|
+
end
|
100
|
+
|
101
|
+
collection.respond_to?(:call) ? collection.call : collection.to_a
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# = simple_form_for @thing do |f|
|
2
|
+
# = f.input :category, :as => :effective_panel_select
|
3
|
+
|
4
|
+
if defined?(SimpleForm)
|
5
|
+
|
6
|
+
class EffectivePanelSelectInput < SimpleForm::Inputs::CollectionSelectInput
|
7
|
+
def input(wrapper_options = nil)
|
8
|
+
label_method, value_method = (detect_collection_methods rescue [:to_s, :to_s])
|
9
|
+
|
10
|
+
options[:collection] = collection
|
11
|
+
options[:label_method] = label_method unless options[:polymorphic]
|
12
|
+
options[:value_method] = value_method unless options[:polymorphic]
|
13
|
+
|
14
|
+
Inputs::EffectivePanelSelect::Input.new(object, object_name, template, attribute_name, input_options, (merge_wrapper_options(input_html_options, wrapper_options) || {})).to_html
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
.panel.panel-default.effective-panel-select{'data-input-js-options' => input.js_options.to_json }
|
2
|
+
= hidden_field_tag(input.field_name, input.value)
|
3
|
+
|
4
|
+
.selection
|
5
|
+
%span.selection-title
|
6
|
+
- if input.option_label.present?
|
7
|
+
%span.selection-clear x
|
8
|
+
%span.selection-label= input.option_label
|
9
|
+
- else
|
10
|
+
%span.selection-placeholder Please Choose
|
11
|
+
%span.selection-arrow
|
12
|
+
%b
|
13
|
+
|
14
|
+
.selector
|
15
|
+
.row
|
16
|
+
.col-sm-4
|
17
|
+
%ul.nav.nav-pills.nav-stacked{role: 'tablist'}
|
18
|
+
- input.collection.each do |group, items|
|
19
|
+
- group_label = group.send(input.options[:group_label_method])
|
20
|
+
- group_value = group.send(input.options[:group_method])
|
21
|
+
|
22
|
+
%li{class: ('active selected' if group_value == input.group_value) }
|
23
|
+
%a{'data-toggle': 'tab', role: 'tab', href: "##{group_value.parameterize}"}
|
24
|
+
= group_label
|
25
|
+
- if input.show_count?
|
26
|
+
%span.badge= items.length
|
27
|
+
.col-sm-8
|
28
|
+
.tab-content
|
29
|
+
- input.collection.each do |group, items|
|
30
|
+
- group_label = group.send(input.options[:group_label_method])
|
31
|
+
- group_value = group.send(input.options[:group_method])
|
32
|
+
|
33
|
+
.tab-pane{id: group_value.parameterize, class: ('active' if group_value == input.group_value) }
|
34
|
+
%p #{group_label}:
|
35
|
+
|
36
|
+
%ul.nav.nav-pills.nav-stacked
|
37
|
+
- Array(items).each do |item|
|
38
|
+
- item_value = item.send(input.options[:option_key_method])
|
39
|
+
|
40
|
+
%li{class: ('active selected' if item_value == input.value), 'data-item-value' => item_value}
|
41
|
+
%a{href: '#'}
|
42
|
+
= item.send(input.options[:option_value_method])
|
43
|
+
- if input.ajax?
|
44
|
+
%span.badge.pull-right{'data-fetch-item' => true} View
|
45
|
+
|
46
|
+
- if input.ajax?
|
47
|
+
.tab-pane.fetched
|
48
|
+
.top.row
|
49
|
+
.col-xs-6
|
50
|
+
.btn.btn-default.fetched-clear Back
|
51
|
+
.col-xs-6.text-right
|
52
|
+
.btn.btn-primary.fetched-select Select
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: effective_form_inputs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code and Effect
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-05-
|
11
|
+
date: 2017-05-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -60,6 +60,9 @@ files:
|
|
60
60
|
- app/assets/javascripts/effective_email/initialize.js.coffee
|
61
61
|
- app/assets/javascripts/effective_email/input.js
|
62
62
|
- app/assets/javascripts/effective_form_inputs.js
|
63
|
+
- app/assets/javascripts/effective_panel_select/effective_panel_select.js.coffee
|
64
|
+
- app/assets/javascripts/effective_panel_select/initialize.js.coffee
|
65
|
+
- app/assets/javascripts/effective_panel_select/input.js
|
63
66
|
- app/assets/javascripts/effective_price/initialize.js.coffee
|
64
67
|
- app/assets/javascripts/effective_price/input.js
|
65
68
|
- app/assets/javascripts/effective_select/initialize.js.coffee
|
@@ -76,6 +79,7 @@ files:
|
|
76
79
|
- app/assets/stylesheets/effective_date_time_picker/input.scss
|
77
80
|
- app/assets/stylesheets/effective_date_time_picker/overrides.scss
|
78
81
|
- app/assets/stylesheets/effective_form_inputs.scss
|
82
|
+
- app/assets/stylesheets/effective_panel_select/input.scss
|
79
83
|
- app/assets/stylesheets/effective_radio_buttons/input.scss
|
80
84
|
- app/assets/stylesheets/effective_select/bootstrap-theme.css
|
81
85
|
- app/assets/stylesheets/effective_select/input.scss
|
@@ -92,6 +96,8 @@ files:
|
|
92
96
|
- app/models/inputs/effective_date_time_picker_input.rb
|
93
97
|
- app/models/inputs/effective_email/input.rb
|
94
98
|
- app/models/inputs/effective_email_input.rb
|
99
|
+
- app/models/inputs/effective_panel_select/input.rb
|
100
|
+
- app/models/inputs/effective_panel_select_input.rb
|
95
101
|
- app/models/inputs/effective_price/input.rb
|
96
102
|
- app/models/inputs/effective_price_input.rb
|
97
103
|
- app/models/inputs/effective_radio_buttons/input.rb
|
@@ -107,6 +113,7 @@ files:
|
|
107
113
|
- app/validators/effective_email_validator.rb
|
108
114
|
- app/validators/effective_tel_validator.rb
|
109
115
|
- app/validators/effective_url_validator.rb
|
116
|
+
- app/views/effective/effective_panel_select/_input.html.haml
|
110
117
|
- app/views/effective/style_guide/_effective_form_inputs.html.haml
|
111
118
|
- lib/effective_form_inputs.rb
|
112
119
|
- lib/effective_form_inputs/engine.rb
|