effective_bootstrap 0.0.6 → 0.0.7

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: ec5621959449ff4c414d797e5b635b197ad481cb
4
- data.tar.gz: 98044a2f5c6167489ea5a1ef2b192322faae2726
3
+ metadata.gz: 4366d401ed983ede60b16c9e82fbb76e393975be
4
+ data.tar.gz: e33da495ac5d246d803444c8ed3726250ad45416
5
5
  SHA512:
6
- metadata.gz: 55cf5551994328a7458abe296c1d1e73a02520f9a415a25a2d3437c9bb8f0abbc3cfa8ae0f9716ead00f0889b3b48ffda78824f4558ad7da46b4778e339774be
7
- data.tar.gz: 9835d86a4c956040965e0cfd54c85c15ef8a3a7d8a559f972e1de883a11a105378c1d337ded67f4a9b2fa050e4076ce67429b10b5c6bf3cd3526ba5871d61e30
6
+ metadata.gz: 1983cdb4104022d4dc1f24987b418222fcf12688f7c6cf6c1e4553b09f0071e16ef75bc7d98506eb85d1c299183259bf75ec6caf9e6b633327f1ee087c454b22
7
+ data.tar.gz: 413e36f0d728563fe5eb845fc236dd086c3dc6581bd51729e57b2d62f160ce73d13ec671d80f63e358583f2b0ea78745a040708682dcd9506a22717499e04ee7
data/README.md CHANGED
@@ -1,11 +1,10 @@
1
1
  # Effective Bootstrap
2
2
 
3
- Everything you need to get set up with bootstrap 4.
3
+ Everything your Ruby on Rails 5.1+ application needs to get working with [Twitter Bootstrap 4](https://getbootstrap.com/).
4
4
 
5
- Bootstrap 4 component helpers and form building replacement.
6
-
7
- Bootstrap >= 4.0
8
- Rails >= 5.1
5
+ - Bootstrap4 component view helpers.
6
+ - SVG icons based on [Inline SVG](https://github.com/jamesmartin/inline_svg), with [Feather Icons](https://feathericons.com) and [FontAwesome](https://fontawesome.com) svg icons to replace the old glyphicons.
7
+ - An html-exact form builder that builds on top of Rails' new `form_with` with numerous custom form inputs.
9
8
 
10
9
  ## Getting Started
11
10
 
@@ -27,85 +26,435 @@ rails generate effective_bootstrap:install
27
26
 
28
27
  The generator will install an initializer which describes all configuration options.
29
28
 
30
- Make sure you have Bootstrap 4 installed:
31
-
32
- Your `application.js` should include
29
+ Add the following to your `application.js`:
33
30
 
34
31
  ```ruby
35
32
  //= require jquery3
36
33
  //= require popper
37
34
  //= require bootstrap
35
+ //= require effective_bootstrap
38
36
  ```
39
37
 
40
- And `application.scss` should include
38
+ And to your `application.scss`:
41
39
 
42
40
  ```sass
43
41
  @import 'bootstrap';
42
+ @import 'effective_bootstrap';
43
+ ```
44
+
45
+ ## View Helpers
46
+
47
+ ### Dropdown
48
+
49
+ https://getbootstrap.com/docs/4.0/components/dropdowns/
50
+
51
+ ```haml
52
+ = dropdown do
53
+ = dropdown_link_to 'Something', root_path
54
+ = dropdown_divider
55
+ = dropdown_link_to 'Another', root_path
56
+ ```
57
+
58
+ Options include: `dropdown(variation: :dropup|:dropleft|:dropright, split: true|false, right: true|false, btn: 'btn-secondary')`
59
+
60
+ ### ListGroup
61
+
62
+ https://getbootstrap.com/docs/4.0/components/list-group/
63
+
64
+ ```haml
65
+ = list_group do
66
+ = list_group_link_to 'Something', root_path
67
+ ```
68
+
69
+ `list_group_link_to` will automatically insert the the `.active` class based on the request path.
70
+
71
+ ### Navbar
72
+
73
+ https://getbootstrap.com/docs/4.0/components/navbar/
74
+
75
+ ```haml
76
+ %nav.navbar.navbar-expand-lg.navbar-light.bg-light
77
+ %a.navbar-brand{href: '/'} Home
78
+
79
+ %button.navbar-toggler{type: 'button', data: {toggle: 'collapse', target: '#navContent', 'aria-controls': 'navContent', 'aria-label': 'Toggle navigation'}}
80
+ %span.navbar-toggler-icon
81
+
82
+ #navContent.collapse.navbar-collapse
83
+ %ul.navbar-nav.mr-auto
84
+ = nav_link_to 'About', '/about'
85
+ = nav_link_to 'Contact', '/conact'
86
+
87
+ %ul.navbar-nav
88
+ - if current_user.present?
89
+ = nav_dropdown('Account', right: true) do
90
+ = nav_link_to 'Settings', user_settings_path
91
+
92
+ - if can?(:access, :admin)
93
+ = nav_divider
94
+ = nav_link_to 'Site Admin', '/admin'
95
+
96
+ = nav_divider
97
+ = nav_link_to 'Sign Out', destroy_user_session_path, method: :delete
98
+ - else
99
+ = nav_link_to 'Sign In', new_user_session_path
44
100
  ```
45
101
 
46
- ### Install All Form Inputs
102
+ `nav_link_to` will automatically insert the `.active` class based on the request path.
103
+
104
+ ## Icon Helpers
105
+
106
+ Unfortunately, Bootstrap 4 dropped support for glyphicons, so we use a combination of [Inline SVG](https://github.com/jamesmartin/inline_svg), with [Feather Icons](https://feathericons.com) and [FontAwesome](https://fontawesome.com) .svg images (no webfonts) to get back this functionality, even better than it was before.
107
+
108
+ ```haml
109
+ = icon('ok') # <svg class='eb-icon eb-icon-ok' ...>
110
+ ```
111
+
112
+ ```haml
113
+ = icon_to('ok', root_path) # <a href='/'><svg class='eb-icon eb-icon-ok' ...></a>
114
+ ```
115
+
116
+ A full list of icons can be found here: [All effective_bootstrap icons](https://github.com/code-and-effect/effective_bootstrap/tree/master/app/assets/images/icons)
117
+
118
+ To overwrite or add an icon, just drop the `.svg` file into your application's `app/assets/images/icons/` directory.
47
119
 
48
- This gem packages the javascript/css assets for numerous form inputs.
120
+ There are also a few helpers for commonly used icons, they all take the form of `x_icon_to(new_thing_path)`:
49
121
 
50
- The assets for these inputs may be included all at once or individually.
122
+ - `new_icon_to`
123
+ - `show_icon_to`
124
+ - `edit_icon_to`
125
+ - `destroy_icon_to`
126
+ - `settings_icon_to`
127
+ - `ok_icon_to`
128
+ - `approve_icon_to`
129
+ - `remove_icon_to`
51
130
 
52
- To install all available inputs, add the following to your application.js:
131
+ ## Form Builder
132
+
133
+ Rails 5.1 has introduced a new `form_with` syntax, and soft-deprecated `form_tag` and `form_for`.
134
+
135
+ This gem includes a [Bootstrap4 Forms](https://getbootstrap.com/docs/4.0/components/forms/) html-exact form builder built on top of `form_with`.
136
+
137
+ The goal of this form builder is to output beautiful forms while matching the rails form syntax -- you should be able to change an existing `form_with` form to `effective_form_with` with no other changes.
138
+
139
+ Of course, just the regular form inputs are boring, and this gem extends numerous jQuery/Javascript libraries to level up some inputs.
140
+
141
+ This is an opinionated Bootstrap4 form builder.
142
+
143
+ ## effective_form_with
144
+
145
+ Matches the Rails `form_with` tag syntax, with all its `:model`, `:scope`, `:url`, `:method`, etc.
146
+
147
+ As well, you can specify `layout: :vertical`, `layout: :horizontal`, or `layout: :inline` as per the different Bootstrap form layouts.
148
+
149
+ ```haml
150
+ = effective_form_with(model: @user, layout: :horizontal) do |f|
151
+ = f.text_field :name
152
+ = f.submit
153
+ ```
154
+
155
+ The default is `layout: :vertical`.
156
+
157
+ All standard form fields have been implemented as per [Rails 5.1 FormHelper](http://api.rubyonrails.org/v5.1/classes/ActionView/Helpers/FormHelper.html)
158
+
159
+ ### Options
160
+
161
+ There are three sets of options hashes that you can pass into any form input:
162
+
163
+ - `wrapper: { class: 'something' }` are applied to the wrapping div tag.
164
+ - `input_html: { class: 'something' }` are applied to the input, select or textarea tag itself.
165
+ - `input_js: { key: value}` are passed to any custom form input will be used to initialize the Javascript library. For example:
53
166
 
54
167
  ```ruby
55
- //= require effective_bootstrap
168
+ = effective_form_with(model: @user) do |f|
169
+ = f.date_field :updated_at, input_js: { useCurrent: 'day', showTodayButton: true }
170
+ ```
171
+
172
+ will result in the following call to the Javascript library:
173
+
174
+ ```javascript
175
+ $('input').datetimepicker(useCurrent: 'day', showTodayButton: true);
176
+ ```
177
+ Any options passed in this way will be used to initialize the underlying javascript libraries.
178
+
179
+ ## Basic form inputs
180
+
181
+ The following form inputs are supported, but don't have any kind of custom JavaScript
182
+
183
+ ```haml
184
+ = f.check_box
185
+ = f.email_field
186
+ = f.error_field
187
+ = f.number_field
188
+ = f.password_field
189
+ = f.static_field
190
+ = f.text_area
191
+ = f.text_field
192
+ = f.url_field
193
+ ```
194
+
195
+ ## Custom date_field, datetime_field, time_field
196
+
197
+ These custom form inputs are all based on the following awesome project:
198
+
199
+ Bootstrap 3 Datepicker (https://github.com/Eonasdan/bootstrap-datetimepicker)
200
+
201
+ ```haml
202
+ = f.date_field :updated_at
203
+ = f.datetime_field :updated_at
204
+ = f.time_field :updated_at
56
205
  ```
57
206
 
58
- and add the following to your application.css:
207
+ ### Options
208
+
209
+ The default options used to initialize this form input are as follows:
59
210
 
60
211
  ```ruby
61
- @import 'effective_bootstrap';
212
+ input_js: { showTodayButton: true, showClear: true, useCurrent: 'hour' }
62
213
  ```
63
214
 
64
- All of the included form inputs will now be available with no additional installation tasks.
215
+ For a full list of options, please refer to:
216
+
217
+ http://eonasdan.github.io/bootstrap-datetimepicker/Options/
218
+
219
+ ### Set Date
220
+
221
+ Use the following JavaScript to set the date:
65
222
 
66
- ### Options Passing to JavaScript
223
+ ```javascript
224
+ $('#start_at').data('DateTimePicker').date('2016-05-08')
225
+ ```
67
226
 
68
- All `:input_js => options` passed to any effective_form_input will be used to initialize the Javascript library
227
+ ### Disabled Dates
69
228
 
70
- For example:
229
+ Provide a String, Date, or Range to set the disabled dates.
71
230
 
72
231
  ```ruby
73
- = form_for @user do |f|
74
- = f.effective_date_time_picker :updated_at, :input_js => {:format => 'dddd, MMMM Do YYYY', :showTodayButton => true}
232
+ input_js: { disabledDates: '2020-01-01' }
233
+ input_js: { disabledDates: Time.zone.now }
234
+ input_js: { disabledDates: Time.zone.now.beginning_of_month..Time.zone.now.end_of_month }
235
+ input_js: { disabledDates: [Time.zone.now, Time.zone.now + 1.day] }
75
236
  ```
76
237
 
77
- or
238
+ ### Linked Dates
239
+
240
+ By default, when two matching date inputs named `start_*` and `end_*` are present on the same form, they will become linked.
241
+
242
+ The end date selector will have its date <= start_date disabled.
243
+
244
+ To disable this behaviour, call with `date_linked: false`.
78
245
 
79
246
  ```ruby
80
- = simple_form_for @user do |f|
81
- = f.input :updated_at, :as => :effective_date_time_picker, :input_js => {:format => 'dddd, MMMM Do YYYY', :showTodayButton => true}
247
+ = f.input :end_at, date_linked: false
82
248
  ```
83
249
 
84
- will result in the following call to the Javascript library:
250
+ ### Events
85
251
 
86
- ```coffee
87
- $('input.effective_date_time_picker').datetimepicker
88
- format: 'dddd, MMMM Do YYYY',
89
- showTodayButton: true
252
+ The date picker library doesn't trigger a regular `change`. Instead you must watch for the `dp.change` event.
253
+
254
+ More info is available here:
255
+
256
+ http://eonasdan.github.io/bootstrap-datetimepicker/Events/
257
+
258
+ ## Custom price_field
259
+
260
+ This custom form input uses no 3rd party jQuery plugins.
261
+
262
+ It displays a currency formatted value `100.00` but posts the "price as integer" value of `10000` to the server.
263
+
264
+ Think about this value as "the number of cents".
265
+
266
+ ```haml
267
+ = f.price_field :price
90
268
  ```
91
269
 
92
- Any options passed in this way will be used to initialize the underlying javascript libraries.
270
+ This gem also includes a rails view helper `price_to_currency` that takes a value like `10000` and displays it as `$100.00`
271
+
272
+ ## Custom select
273
+
274
+ This custom form input is based on the following awesome project:
93
275
 
276
+ Select2 (https://select2.github.io/)
94
277
 
278
+ ### Usage
279
+
280
+ As a Rails Form Helper input:
281
+
282
+ ```ruby
283
+ = f.select :category, 10.times.map { |x| "Category #{x}"}
284
+ = f.select :categories, 10.times.map { |x| "Category #{x}"}, multiple: true
285
+ = f.select :categories, 10.times.map { |x| "Category #{x}"}, tags: true
286
+ = f.select :categories, {'Active': [['Post A', 1], ['Post B', 2]], 'Past': ['Post C', 3], ['Post D', 4]}, grouped: true
287
+ ```
288
+
289
+ ### Modes
290
+
291
+ The standard mode is a replacement for the default single select box.
292
+
293
+ Passing `multiple: true` will allow multiple selections to be made.
294
+
295
+ Passing `multiple: true, tags: true` will allow multiple selections to be made, and new value options to be created. This will allow you to both select existing tags and create new tags in the same form control.
296
+
297
+ Passing `grouped: true` will enable optgroup support. When in this mode, the collection should be a Hash of ActiveRecord Relations or Array of Arrays
298
+
299
+ ```ruby
300
+ {'Active' => Post.active, 'Past' => Post.past}
301
+ {'Active' => [['Post A', 1], ['Post B', 2]], 'Past' => [['Post C', 3], ['Post D', 4]]}
302
+ ```
303
+
304
+ Passing `polymorphic: true` will enable polymorphic support. In this mode, an additional 2 hidden input fields are created alongside the select field.
305
+
306
+ So calling
307
+
308
+ ```ruby
309
+ = f.input :primary_contact, User.all.to_a + Member.all.to_a, polymorphic: true
310
+ ```
311
+
312
+ will internally translate the collection into:
313
+
314
+ ```ruby
315
+ [['User 1', 'User_1'], ['User 2', 'User_2'], ['Member 100', 'Member_100']]
95
316
  ```
96
- = f.submit
97
- = f.submit 'Save 2'
98
317
 
99
- = f.submit 'Save', left: true
100
- = f.submit 'Save', center: true
101
- = f.submit 'Save', right: true
318
+ and instead of posting to the server with the parameter `:primary_contact`, it will instead post `{:primary_contact_id => 2, :primary_contact_type => 'User'}`.
102
319
 
103
- = f.submit 'Save', border: false
104
- = f.submit 'Save', center: true, border: false
105
- = f.submit 'Save', left: true, border: false
320
+ Using both `polymorphic: true` and `grouped: true` is recommended. In this case the expected collection is as follows:
106
321
 
107
- = f.submit('Save', border: false) do
108
- = f.save 'Okay'
109
- = f.save 'Mom'
322
+ ```ruby
323
+ = f.input :primary_contact, {'Users' => User.all, 'Members' => 'Member.all'}, polymorphic: true, grouped: true
324
+ ```
325
+
326
+ ### Options
327
+
328
+ The default options used to initialize this form input are as follows:
329
+
330
+ ```ruby
331
+ {
332
+ :theme => 'bootstrap',
333
+ :minimumResultsForSearch => 6,
334
+ :tokenSeparators => [',', ' '],
335
+ :width => 'style',
336
+ :placeholder => 'Please choose',
337
+ :allowClear => !(options[:multiple]) # Only display the Clear 'x' on a single selection box
338
+ }
339
+ ```
340
+
341
+ ### Interesting Available Options
342
+
343
+ To limit the number of items that can be selected in a multiple select box:
344
+
345
+ ```ruby
346
+ :maximumSelectionLength => 2
110
347
  ```
111
348
 
349
+ To hide the search box entirely:
350
+
351
+ ```ruby
352
+ :minimumResultsForSearch => 'Infinity'
353
+ ```
354
+
355
+ For a full list of options, please refer to: https://select2.github.io/options.html
356
+
357
+
358
+ The following `input_js: options` are not part of the standard select2 API, and are custom `effective_select` functionality only:
359
+
360
+ To add a css class to the select2 container or dropdown:
361
+
362
+ ```ruby
363
+ :containerClass => 'custom-container-class'
364
+ :dropdownClass => 'custom-dropdown-class'
365
+ ```
366
+
367
+ to display a glyphicon infront of each option value:
368
+
369
+ ```ruby
370
+ f.input :user, User.all.map { |user| [user.to_s, user.to_param, { class: 'glyphicon-flag' }] }, template: :glyphicon
371
+ ```
372
+
373
+
374
+ ### Additional
375
+
376
+ Call with `single_selected: true` to ensure only the first selected option tag will be `<option selected="selected">`.
377
+
378
+ This can be useful when displaying multiple options with an identical value.
379
+
380
+ ### Clear value
381
+
382
+ It's a bit tricky to clear the selected value
383
+
384
+ ```coffeescript
385
+ $('select').val('').trigger('change.select2')
386
+ ```
387
+
388
+ ### Working with dynamic options
389
+
390
+ The following information applies to `effective_select` only, and is not part of the standard select2 API.
391
+
392
+ To totally hide (instead of just grey out) any disabled options from the select2 dropdown, initialize the input with:
393
+
394
+ ```ruby
395
+ = f.input :category, User.all, hide_disabled: true
396
+ ```
397
+
398
+ If you want to dynamically add/remove options from the select field after page load, you must use the `select2:reinitialize` event:
399
+
400
+ ```coffeescript
401
+ # When something on my page changes
402
+ $(document).on 'change', '.something', (event) ->
403
+ $select = $(event.target).closest('form').find('select.i-want-to-change') # Find the select2 input to be updated
404
+
405
+ # Go through its options, and modify some of them.
406
+ # Using the above 'hide_disabled true' functionality, the following code hides the options from being displayed,
407
+ # but you could actually remove the options, add new ones, or update the values/texts. whatever.
408
+ $select.find('option').each (index, option) ->
409
+ $(option).prop('disabled', true) if index > 10
410
+
411
+ # Whenever the underlying options change, you need to manually trigger the following event:
412
+ $select.select2().trigger('select2:reinitialize')
413
+ ```
414
+
415
+ ### AJAX Support
416
+
417
+ 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.
418
+
419
+ ## Custom submit and save
420
+
421
+ The `f.submit` puts in a wrapper and a default save button, and does the whole icon spin when submit thing.
422
+
423
+ The `f.save` is purely a input submit button.
424
+
425
+ ```haml
426
+ = f.submit
427
+ = f.submit 'Save 2'
428
+
429
+ = f.submit 'Save', left: true
430
+ = f.submit 'Save', center: true
431
+ = f.submit 'Save', right: true
432
+
433
+ = f.submit 'Save', border: false
434
+ = f.submit 'Save', center: true, border: false
435
+ = f.submit 'Save', left: true, border: false
436
+
437
+ = f.submit(border: false) do
438
+ = f.save 'Save 1'
439
+ = f.save 'Save 2'
440
+ ```
441
+
442
+
443
+ ## License
444
+
445
+ MIT License. Copyright [Code and Effect Inc.](http://www.codeandeffect.com/)
446
+
447
+ ## Credits
448
+
449
+ The authors of this gem are not associated with any of the awesome projects used by this gem.
450
+
451
+ We are just extending these existing community projects for ease of use with Rails Form Helper and SimpleForm.
452
+
453
+ ## Contributing
454
+
455
+ 1. Fork it
456
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
457
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
458
+ 4. Push to the branch (`git push origin my-new-feature`)
459
+ 5. Bonus points for test coverage
460
+ 6. Create new Pull Request
@@ -7,5 +7,5 @@
7
7
  //= require ./effective_file/input
8
8
  //= require ./effective_phone/input
9
9
  //= require ./effective_price/input
10
+ //= require ./effective_radio/input
10
11
  //= require ./effective_select/input
11
-
@@ -1,4 +1,8 @@
1
1
  this.EffectiveBootstrap ||= new class
2
+ remote_form_payload: '' # A fresh form
3
+ remote_form_flash: '' # Array of Arrays
4
+ remote_form_flash_payload: '' # $('<div alert>...</div>')
5
+
2
6
  initialize: (target) ->
3
7
  $(target || document).find('[data-input-js-options]:not(.initialized)').each (i, element) ->
4
8
  $element = $(element)
@@ -29,14 +33,41 @@ this.EffectiveBootstrap ||= new class
29
33
  else
30
34
  $form.addClass('was-validated').addClass('form-is-invalid').removeClass('form-is-valid')
31
35
 
36
+ if valid and $form.data('remote')
37
+ $form.one 'ajax:success', (event) -> EffectiveBootstrap.loadRemoteForm($(event.target))
38
+
32
39
  valid
33
40
 
41
+ submitting: ($form) ->
42
+ $form.addClass('form-is-valid').removeClass('form-is-invalid')
43
+ @disable($form)
44
+
34
45
  disable: ($form) ->
35
46
  $form.find('[type=submit]').prop('disabled', true)
36
47
 
37
48
  enable: ($form) ->
38
49
  $form.removeClass('form-is-valid').find('[type=submit]').removeAttr('disabled')
39
50
 
51
+ # Loads remote for payload that was placed here by effective_resources create.js.erb and update.js.erb
52
+ loadRemoteForm: ($target) ->
53
+ $form = @remote_form_payload.find('form')
54
+ $target.replaceWith($form)
55
+
56
+ for flash in @remote_form_flash
57
+ @flash($form, flash[0], @remote_form_flash_payload)
58
+
59
+ @remote_form_payload = ''; @remote_form_flash = ''; @remote_form_flash_payload = '';
60
+
61
+ flash: ($form, status, $alert) ->
62
+ $submit = $form.children('.form-actions')
63
+
64
+ if status == 'danger' || status == 'error'
65
+ $submit.find('.eb-icon-x').show().delay(1000).fadeOut('slow')
66
+ else
67
+ $submit.find('.eb-icon-check').show().delay(1000).fadeOut('slow')
68
+
69
+ $submit.prepend($alert) if $alert.length > 0
70
+
40
71
  $ -> EffectiveBootstrap.initialize()
41
72
  $(document).on 'turbolinks:load', -> EffectiveBootstrap.initialize()
42
73
  $(document).on 'cocoon:after-insert', -> EffectiveBootstrap.initialize()
@@ -0,0 +1 @@
1
+ //= require ./initialize
@@ -0,0 +1,24 @@
1
+ $(document).on 'change', '[data-toggle=cards] input[type=radio]', (event) ->
2
+ $input = $(event.currentTarget)
3
+ return unless $input.is(':checked')
4
+
5
+ $card = $input.closest('.card')
6
+ return unless $card.length > 0
7
+
8
+ $cards = $input.closest('.card-deck').children('.card')
9
+ return unless $cards.length > 0
10
+
11
+ $cards.removeClass('active').removeClass('border-secondary')
12
+ $cards.find('.card-header').removeClass('bg-secondary text-white')
13
+
14
+ $card.addClass('active').addClass('border-secondary')
15
+ $card.find('.card-header').addClass('bg-secondary text-white')
16
+ true
17
+
18
+ $(document).on 'click', '[data-toggle=cards] [data-toggle=card]', (event) ->
19
+ $card = $(event.currentTarget).closest('.card')
20
+ return unless $card.length > 0
21
+
22
+ val = $card.find('input:radio').val()
23
+ $card.find('input:radio').val([val]).trigger('change')
24
+ false
@@ -0,0 +1 @@
1
+ //= require ./initialize
@@ -2,6 +2,12 @@
2
2
  .form-actions {
3
3
  display: flex;
4
4
  align-items: center;
5
+ position: relative;
6
+
7
+ .alert {
8
+ position: absolute;
9
+ top: -4.0em;
10
+ }
5
11
  }
6
12
 
7
13
  .form-actions-bordered {
@@ -2,3 +2,17 @@ div.btn-group > .btn.first-button {
2
2
  border-top-left-radius: 0.25rem;
3
3
  border-bottom-left-radius: 0.25rem;
4
4
  }
5
+
6
+ .effective-radios.card-deck {
7
+ .card-header { cursor: pointer; }
8
+
9
+ input[type=radio] { display: none; }
10
+
11
+ .visible-when-selected { display: none; }
12
+ .visible-when-unselected { display: block; }
13
+
14
+ .active {
15
+ .visible-when-selected { display: block; }
16
+ .visible-when-unselected { display: none; }
17
+ }
18
+ }
@@ -112,7 +112,7 @@ module EffectiveBootstrapHelper
112
112
  # = nav_link_to 'Sign In', new_user_session_path
113
113
  # = nav_dropdown 'Settings' do
114
114
  # = nav_link_to 'Account Settings', user_settings_path
115
- # = nav_dropdown_divider
115
+ # = nav_divider
116
116
  # = nav_link_to 'Sign In', new_user_session_path, method: :delete
117
117
  def nav_link_to(label, path, opts = {})
118
118
  if @_nav_mode == :dropdown # We insert dropdown-items
@@ -47,4 +47,3 @@ module EffectiveIconsHelper
47
47
  end
48
48
 
49
49
  end
50
-
@@ -1,10 +1,15 @@
1
1
  # http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-select
2
+
3
+ # buttons: true
4
+ # cards: true
5
+ # custom: false
6
+
2
7
  module Effective
3
8
  module FormInputs
4
9
  class Radios < CollectionInput
5
10
 
6
11
  def build_wrapper(&block)
7
- tag = buttons? ? :div : :fieldset
12
+ tag = (buttons? || cards?) ? :div : :fieldset
8
13
 
9
14
  if layout == :horizontal
10
15
  content_tag(tag, content_tag(:div, yield, class: 'row'), options[:wrapper])
@@ -22,6 +27,8 @@ module Effective
22
27
  def build_button_group(&block)
23
28
  if buttons?
24
29
  content_tag(:div, yield, id: button_group_id, class: 'btn-group btn-group-toggle effective-radios', 'data-toggle': 'buttons')
30
+ elsif cards?
31
+ content_tag(:div, yield, id: button_group_id, class: 'card-deck effective-radios', 'data-toggle': 'cards')
25
32
  else
26
33
  yield
27
34
  end
@@ -43,6 +50,8 @@ module Effective
43
50
  def input_html_options
44
51
  if buttons?
45
52
  { autocomplete: 'off' }
53
+ elsif cards?
54
+ { autocomplete: 'off' }
46
55
  elsif custom?
47
56
  { class: 'custom-control-input' }
48
57
  else
@@ -59,6 +68,8 @@ module Effective
59
68
 
60
69
  if buttons?
61
70
  content_tag(:label, text, options[:label].merge(for: button_group_id))
71
+ elsif cards?
72
+ content_tag(:label, text, options[:label].merge(for: button_group_id))
62
73
  elsif inline?
63
74
  content_tag(:label, text, options[:label])
64
75
  else
@@ -74,13 +85,24 @@ module Effective
74
85
  opts[:class] = [opts[:class], ('active' if active_item?(builder)), ('first-button' if first_item?) ].compact.join(' ')
75
86
 
76
87
  builder.label(opts) { builder.radio_button(id: item_id) + builder.text }
88
+ elsif cards?
89
+ opts = item_label_options.merge(for: item_id)
90
+ opts[:class] = [opts[:class], ('active border-secondary' if active_item?(builder)), ('first-card' if first_item?) ].compact.join(' ')
91
+
92
+ if active_item?(builder)
93
+ builder.label(opts) { builder.radio_button(id: item_id) + builder.text.sub('card-header', 'card-header bg-secondary text-white').html_safe }
94
+ else
95
+ builder.label(opts) { builder.radio_button(id: item_id) + builder.text }
96
+ end
77
97
  else
78
98
  build_item_wrap { builder.radio_button(id: item_id) + builder.label(item_label_options.merge(for: item_id)) }
79
99
  end
80
100
  end
81
101
 
82
102
  def build_item_wrap(&block)
83
- if custom?
103
+ if cards?
104
+ content_tag(:div, yield, class: 'card')
105
+ elsif custom?
84
106
  content_tag(:div, yield, class: 'custom-control custom-radio ' + (inline? ? 'custom-control-inline' : 'form-group'))
85
107
  else
86
108
  content_tag(:div, yield, class: 'form-check' + (inline? ? ' form-check-inline' : ''))
@@ -94,6 +116,8 @@ module Effective
94
116
  def item_label_options
95
117
  if buttons?
96
118
  { class: 'btn btn-outline-secondary' }
119
+ elsif cards?
120
+ { class: 'card' }
97
121
  elsif custom?
98
122
  { class: 'custom-control-label' }
99
123
  else
@@ -106,6 +130,11 @@ module Effective
106
130
  @buttons = (options.delete(:buttons) || false)
107
131
  end
108
132
 
133
+ def cards? # default false
134
+ return @cards unless @cards.nil?
135
+ @cards= (options.delete(:cards) || false)
136
+ end
137
+
109
138
  def button_group_id
110
139
  "#{tag_id}_btn_group"
111
140
  end
@@ -3,23 +3,26 @@ module Effective
3
3
  class Submit < Effective::FormInput
4
4
 
5
5
  def build_input(&block)
6
- icon('spinner') + (block_given? ? capture(&block) : content_tag(:button, name, options[:input]))
6
+ tags = [
7
+ icon('check', style: 'display: none;'),
8
+ icon('x', style: 'display: none;'),
9
+ icon('spinner'),
10
+ (block_given? ? capture(&block) : content_tag(:button, name, options[:input]))
11
+ ]
12
+
13
+ (left? ? tags.reverse.join : tags.join).html_safe
7
14
  end
8
15
 
9
16
  def wrapper_options
10
- border = options.key?(:border) ? options.delete(:border) : true
11
- left = options.delete(:left) || false
12
- center = options.delete(:center) || false
13
- right = options.delete(:right) || false
14
- right = true unless (left || center)
17
+ @right = true unless (left? || center? || right?)
15
18
 
16
19
  classes = [
17
20
  ('row' if layout == :horizontal),
18
21
  'form-group form-actions',
19
- ('form-actions-bordered' if border),
20
- ('justify-content-start' if left && layout == :vertical),
21
- ('justify-content-center' if center && layout == :vertical),
22
- ('justify-content-end' if right && layout == :vertical)
22
+ ('form-actions-bordered' if border?),
23
+ ('justify-content-start' if left? && layout == :vertical),
24
+ ('justify-content-center' if center? && layout == :vertical),
25
+ ('justify-content-end' if right? && layout == :vertical)
23
26
  ].compact.join(' ')
24
27
 
25
28
  { class: classes }
@@ -33,6 +36,28 @@ module Effective
33
36
  false
34
37
  end
35
38
 
39
+ private
40
+
41
+ def border?
42
+ return @border unless @border.nil?
43
+ @border = options.key?(:border) ? options.delete(:border) : true
44
+ end
45
+
46
+ def left?
47
+ return @left unless @left.nil?
48
+ @left = (options.delete(:left) || false)
49
+ end
50
+
51
+ def center?
52
+ return @center unless @center.nil?
53
+ @center = (options.delete(:center) || false)
54
+ end
55
+
56
+ def right?
57
+ return @right unless @right.nil?
58
+ @right = (options.delete(:right) || false)
59
+ end
60
+
36
61
  def feedback_options
37
62
  # case layout
38
63
  # when :inline
@@ -1,7 +1,7 @@
1
1
  %p These icons are a combination of #{link_to 'Feather', 'https://feathericons.com/'} and #{link_to 'FontAwesome', 'https://fontawesome.com/'} icons.
2
2
 
3
3
  .row.text-center
4
- - Dir["#{__dir__}/../../../assets/icons/*.svg"].map { |path| path.split('/').last.chomp('.svg') }.each do |name|
4
+ - Dir["#{__dir__}/../../../assets/images/icons/*.svg"].map { |path| path.split('/').last.chomp('.svg') }.each do |name|
5
5
  .col-sm-2.my-3
6
6
  = icon(name)
7
7
  %br
@@ -1,3 +1,3 @@
1
1
  module EffectiveBootstrap
2
- VERSION = '0.0.6'.freeze
2
+ VERSION = '0.0.7'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_bootstrap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
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: 2018-03-29 00:00:00.000000000 Z
11
+ date: 2018-04-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: jquery-rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: coffee-rails
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -368,7 +382,10 @@ files:
368
382
  - app/assets/javascripts/effective_phone/initialize.js.coffee
369
383
  - app/assets/javascripts/effective_phone/input.js
370
384
  - app/assets/javascripts/effective_phone/jquery.maskedInput.js
371
- - app/assets/javascripts/effective_price/input.js.coffee
385
+ - app/assets/javascripts/effective_price/initialize.js.coffee
386
+ - app/assets/javascripts/effective_price/input.js
387
+ - app/assets/javascripts/effective_radio/initialize.js.coffee
388
+ - app/assets/javascripts/effective_radio/input.js
372
389
  - app/assets/javascripts/effective_select/initialize.js.coffee
373
390
  - app/assets/javascripts/effective_select/input.js
374
391
  - app/assets/javascripts/effective_select/overrides.js.coffee