effective_form_inputs 1.0.9 → 1.1.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.
- 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
|