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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 13b591cf464ffa57c1fd4ccca0c5db7d12fab6eb
4
- data.tar.gz: 1d2dbad66015c45d3cb8d23cc8dda8a028cd11c3
3
+ metadata.gz: a75831223cd401c30495c973058cfc192ba3fced
4
+ data.tar.gz: b8fd17c7f18fbb59b3392d96277c50177948c432
5
5
  SHA512:
6
- metadata.gz: 5f01b4d46479410ff658d3c4ef0edb8443a57d1a725db90fad8e30d6bda89ab68789666d955646deaed809c80852fe652712b4a6ce6c5bba55f60ca131732cf4
7
- data.tar.gz: f27ae101cd5e9233224f78c450b4dad04de18a4624eb35d86cb3a7be3328a88a62c66c8c50b6173330d4910077b7f8e1931f4e4007e0542e8202316b4e57f4f0
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
- A bootstrap3 Static control input
341
+ ## Effective Panel Select
250
342
 
251
- Renders `<p class='form-control-static'>value</p>` with the appropriate SimpleForm wrappings.
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
- There are no installation steps required for this form input
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.effective_static_control :member_id
369
+ = f.effective_panel_select :category, categories_collection
264
370
  ```
265
371
 
266
- As a SimpleForm input:
372
+ and as a SimpleForm input:
267
373
 
268
374
  ```ruby
269
375
  = simple_form_for @user do |f|
270
- = f.input :member_id, :as => :effective_static_control
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
- There are no default options for this form input
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 Tel(ephone)
438
-
439
- This custom form input uses a jQuery maskedInput plugin from the following awesome project:
761
+ ## Effective Static Control
440
762
 
441
- jQuery Masked Input Plugin (https://github.com/digitalBush/jquery.maskedinput)
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
- If you've already installed the 'All Form Inputs' assets (see above), there are no additional installation steps.
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.effective_tel :phone
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 :phone, :as => :effective_tel
784
+ = f.input :category, as: :effective_static_control
785
+ = f.input :category, as: :effective_static_control
468
786
  ```
469
787
 
470
- As a SimpleForm input without the input group (phone glyphicon)
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
- ## Effective Price
790
+ There are no default options for this form input.
485
791
 
486
- This custom form input uses no 3rd party jQuery plugins.
792
+ ## Effective Tel(ephone)
487
793
 
488
- It displays a currency formatted value `100.00` but posts the "price as integer" value of `10000` to the server.
794
+ This custom form input uses a jQuery maskedInput plugin from the following awesome project:
489
795
 
490
- Think about this value as "the number of cents".
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 effective_price/input
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 @product do |f|
509
- = f.effective_price :price
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 @product do |f|
516
- = f.input :price, :as => :effective_price
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 (glyphicon-usd glyphicon)
825
+ As a SimpleForm input without the input group (phone glyphicon)
520
826
 
521
827
  ```ruby
522
- = simple_form_for @product do |f|
523
- = f.input :price, :as => :effective_price, :input_group => false
828
+ = simple_form_for @user do |f|
829
+ = f.input :phone, :as => :effective_tel, :input_group => false
524
830
  ```
525
831
 
526
- ### Options
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
- = f.input :price, :as => :effective_price, :include_blank => true
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,2 @@
1
+ //= require ./effective_panel_select
2
+ //= require ./initialize
@@ -1,3 +1,4 @@
1
1
  @import 'effective_date_time_picker/input';
2
2
  @import 'effective_radio_buttons/input';
3
+ @import 'effective_panel_select/input';
3
4
  @import 'effective_select/input';
@@ -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
@@ -1,3 +1,3 @@
1
1
  module EffectiveFormInputs
2
- VERSION = '1.0.9'.freeze
2
+ VERSION = '1.1.0'.freeze
3
3
  end
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.9
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-08 00:00:00.000000000 Z
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