effective_bootstrap 0.0.7 → 0.0.8
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/app/assets/javascripts/effective_bootstrap/base.js.coffee +48 -22
- data/app/assets/javascripts/effective_radio/initialize.js.coffee +12 -0
- data/app/assets/stylesheets/effective_bootstrap/forms.scss +6 -9
- data/app/assets/stylesheets/effective_radio/input.scss +8 -0
- data/app/helpers/effective_form_builder_helper.rb +4 -0
- data/app/models/effective/form_builder.rb +7 -1
- data/app/models/effective/form_input.rb +31 -3
- data/app/models/effective/form_inputs/checks.rb +11 -4
- data/app/models/effective/form_inputs/email_field.rb +5 -0
- data/app/models/effective/form_inputs/phone_field.rb +5 -0
- data/app/models/effective/form_inputs/radios.rb +15 -4
- data/app/models/effective/form_inputs/submit.rb +4 -0
- data/app/models/effective/form_inputs/url_field.rb +5 -0
- data/app/views/effective/style_guide/_effective_form_with.html.haml +3 -0
- data/lib/effective_bootstrap/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6159bfe9bf5e58af814e2d446ee907d3a456a54b
|
4
|
+
data.tar.gz: 2b232d59b9e6904c6b6358e07631294673a0fa78
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9111638ac3d4eb19d1ed5b2abd43404300f88af4925460c6fca5980b66e2337d6cdf9c245a6378207fa6c3d809509134c9d264b58f3b40d3c5cec7f65ed16a53
|
7
|
+
data.tar.gz: ade79312e2e0c17f9eabbeff7a2ce2f954b068e0cab86e2d63b9b478f6b97fda4ab96019f47504b17ea0814ba9476a52a732f74947ccab56a164b7c870f02e64
|
@@ -1,7 +1,6 @@
|
|
1
1
|
this.EffectiveBootstrap ||= new class
|
2
2
|
remote_form_payload: '' # A fresh form
|
3
3
|
remote_form_flash: '' # Array of Arrays
|
4
|
-
remote_form_flash_payload: '' # $('<div alert>...</div>')
|
5
4
|
|
6
5
|
initialize: (target) ->
|
7
6
|
$(target || document).find('[data-input-js-options]:not(.initialized)').each (i, element) ->
|
@@ -20,22 +19,28 @@ this.EffectiveBootstrap ||= new class
|
|
20
19
|
validate: (form) ->
|
21
20
|
$form = $(form)
|
22
21
|
|
23
|
-
|
24
|
-
$form.find('.alert.is-invalid').remove()
|
25
|
-
$form.find('.is-invalid').removeClass('is-invalid')
|
26
|
-
$form.find('.is-valid').removeClass('is-valid')
|
22
|
+
@reset($form)
|
27
23
|
|
28
24
|
valid = form.checkValidity()
|
29
25
|
|
30
26
|
if valid
|
31
|
-
$form.addClass('form-is-valid')
|
27
|
+
$form.addClass('form-is-valid')
|
32
28
|
setTimeout((-> EffectiveBootstrap.disable($form)), 0)
|
33
29
|
else
|
34
|
-
$form.addClass('was-validated').addClass('form-is-invalid')
|
30
|
+
$form.addClass('was-validated').addClass('form-is-invalid')
|
31
|
+
|
32
|
+
$('.effective-radios:not(.no-feedback),.effective-checks:not(.no-feedback)').each -> # These controls need a little bit of help with client side validations
|
33
|
+
$(@).addClass(if $(@).find('input:invalid').length > 0 then 'is-invalid' else 'is-valid')
|
34
|
+
|
35
|
+
@flash($form, 'danger')
|
35
36
|
|
36
37
|
if valid and $form.data('remote')
|
37
38
|
$form.one 'ajax:success', (event) -> EffectiveBootstrap.loadRemoteForm($(event.target))
|
38
39
|
|
40
|
+
$form.one 'ajax:error', (event, _, status, message) ->
|
41
|
+
EffectiveBootstrap.reset($(event.target))
|
42
|
+
EffectiveBootstrap.flash($(event.target), 'danger', "Ajax #{status}: #{message}")
|
43
|
+
|
39
44
|
valid
|
40
45
|
|
41
46
|
submitting: ($form) ->
|
@@ -45,28 +50,49 @@ this.EffectiveBootstrap ||= new class
|
|
45
50
|
disable: ($form) ->
|
46
51
|
$form.find('[type=submit]').prop('disabled', true)
|
47
52
|
|
48
|
-
|
49
|
-
$form.removeClass('
|
53
|
+
reset: ($form) ->
|
54
|
+
$form.removeClass('was-validated').removeClass('form-is-invalid').removeClass('form-is-valid')
|
50
55
|
|
51
|
-
|
52
|
-
|
53
|
-
$form
|
54
|
-
$
|
55
|
-
|
56
|
-
for flash in @remote_form_flash
|
57
|
-
@flash($form, flash[0], @remote_form_flash_payload)
|
56
|
+
# Clear any server side validation on individual inputs
|
57
|
+
$form.find('.alert.is-invalid').remove()
|
58
|
+
$form.find('.is-invalid').removeClass('is-invalid')
|
59
|
+
$form.find('.is-valid').removeClass('is-valid')
|
58
60
|
|
59
|
-
|
61
|
+
$form.find('[type=submit]').removeAttr('disabled')
|
60
62
|
|
61
|
-
flash: ($form, status,
|
62
|
-
$
|
63
|
+
flash: ($form, status, message, skip_success = false) ->
|
64
|
+
$actions = $form.children('.form-actions')
|
63
65
|
|
64
66
|
if status == 'danger' || status == 'error'
|
65
|
-
$
|
67
|
+
$actions.find('.eb-icon-x').show().delay(1000).fadeOut('slow')
|
66
68
|
else
|
67
|
-
$
|
69
|
+
$actions.find('.eb-icon-check').show().delay(1000).fadeOut('slow')
|
70
|
+
|
71
|
+
if message? && !(status == 'success' && skip_success)
|
72
|
+
$actions.prepend(@buildFlash(status, message))
|
68
73
|
|
69
|
-
|
74
|
+
# Loads remote for payload that was placed here by effective_resources create.js.erb and update.js.erb
|
75
|
+
loadRemoteForm: ($target) ->
|
76
|
+
if @remote_form_payload?
|
77
|
+
$form = @remote_form_payload.find("form[data-remote-index='#{$target.data('remote-index')}']")
|
78
|
+
$form = @remote_form_payload.find('form') if $form.length == 0
|
79
|
+
$target.replaceWith($form)
|
80
|
+
|
81
|
+
if @remote_form_flash?
|
82
|
+
for flash in @remote_form_flash
|
83
|
+
@flash($form, flash[0], flash[1], true)
|
84
|
+
|
85
|
+
@remote_form_payload = ''; @remote_form_flash = '';
|
86
|
+
|
87
|
+
buildFlash: (status, message) ->
|
88
|
+
$("
|
89
|
+
<div class='alert alert-dismissable alert-#{status} fade show' role='alert'>
|
90
|
+
#{message}
|
91
|
+
<button class='close' type='button' aria-label='Close' data-dismiss='alert'>
|
92
|
+
<span aria-hidden='true'>×</span>
|
93
|
+
</button>
|
94
|
+
</div>
|
95
|
+
")
|
70
96
|
|
71
97
|
$ -> EffectiveBootstrap.initialize()
|
72
98
|
$(document).on 'turbolinks:load', -> EffectiveBootstrap.initialize()
|
@@ -22,3 +22,15 @@ $(document).on 'click', '[data-toggle=cards] [data-toggle=card]', (event) ->
|
|
22
22
|
val = $card.find('input:radio').val()
|
23
23
|
$card.find('input:radio').val([val]).trigger('change')
|
24
24
|
false
|
25
|
+
|
26
|
+
$(document).on 'change', '.effective-radios input', (event) ->
|
27
|
+
$input = $(event.currentTarget)
|
28
|
+
$group = $input.closest('.effective-radios')
|
29
|
+
|
30
|
+
return unless ($group.hasClass('is-valid') || $group.hasClass('is-invalid'))
|
31
|
+
|
32
|
+
if $input.is(':valid')
|
33
|
+
$group.addClass('is-valid').removeClass('is-invalid')
|
34
|
+
else
|
35
|
+
$group.addClass('is-invalid').removeClass('is-valid')
|
36
|
+
|
@@ -33,15 +33,6 @@
|
|
33
33
|
.form-actions .eb-icon-spinner { display: none; }
|
34
34
|
.form-is-valid .form-actions .eb-icon-spinner { display: inline; }
|
35
35
|
|
36
|
-
// Custom submit button feedback
|
37
|
-
.was-validated.form-is-valid .form-actions {
|
38
|
-
.valid-feedback { display: block; }
|
39
|
-
}
|
40
|
-
|
41
|
-
.was-validated.form-is-invalid .form-actions {
|
42
|
-
.invalid-feedback { display: block; }
|
43
|
-
}
|
44
|
-
|
45
36
|
// Radio and Checkbox fieldsets
|
46
37
|
fieldset.form-group > label {
|
47
38
|
display: block;
|
@@ -50,3 +41,9 @@ fieldset.form-group > label {
|
|
50
41
|
div.form-group > label + .btn-group {
|
51
42
|
display: block;
|
52
43
|
}
|
44
|
+
|
45
|
+
.effective-radios.is-invalid ~ .invalid-feedback { display: block }
|
46
|
+
.effective-radios.is-valid ~ .valid-feedback { display: block }
|
47
|
+
|
48
|
+
.effective-checks.is-invalid .invalid-feedback { display: block }
|
49
|
+
.effective-checks.is-valid .valid-feedback { display: block }
|
@@ -4,10 +4,14 @@ module EffectiveFormBuilderHelper
|
|
4
4
|
options[:html] = (options[:html] || {}).merge(novalidate: true, onsubmit: 'return EffectiveBootstrap.validate(this);')
|
5
5
|
|
6
6
|
if options.delete(:remote) == true
|
7
|
+
@_effective_remote_index ||= 0
|
8
|
+
|
7
9
|
if options[:html][:data].kind_of?(Hash)
|
8
10
|
options[:html][:data][:remote] = true
|
11
|
+
options[:html][:data]['data-remote-index'] = (@_effective_remote_index += 1)
|
9
12
|
else
|
10
13
|
options[:html]['data-remote'] = true
|
14
|
+
options[:html]['data-remote-index'] = (@_effective_remote_index += 1)
|
11
15
|
end
|
12
16
|
end
|
13
17
|
|
@@ -1,13 +1,19 @@
|
|
1
1
|
module Effective
|
2
2
|
class FormBuilder < ActionView::Helpers::FormBuilder
|
3
3
|
|
4
|
-
attr_accessor :layout, :
|
4
|
+
attr_accessor :template, :layout, :action, :readonly, :disabled, :remote
|
5
5
|
|
6
6
|
delegate :content_tag, to: :template
|
7
7
|
|
8
8
|
def initialize(object_name, object, template, options)
|
9
9
|
@template = template
|
10
|
+
|
10
11
|
@layout = (options.delete(:layout) || :vertical).to_sym
|
12
|
+
@action = options.delete(:action)
|
13
|
+
@readonly = options.delete(:readonly)
|
14
|
+
@disabled = options.delete(:disabled)
|
15
|
+
@remote = options[:remote]
|
16
|
+
|
11
17
|
super
|
12
18
|
end
|
13
19
|
|
@@ -164,7 +164,12 @@ module Effective
|
|
164
164
|
|
165
165
|
def has_error?(name = nil)
|
166
166
|
return false unless object.respond_to?(:errors)
|
167
|
-
|
167
|
+
|
168
|
+
if name
|
169
|
+
object.errors[name].present? || (parent_object && parent_object.errors[name].present?)
|
170
|
+
else
|
171
|
+
object.errors.present? || parent_object&.errors&.present?
|
172
|
+
end
|
168
173
|
end
|
169
174
|
|
170
175
|
def required?(name)
|
@@ -265,9 +270,16 @@ module Effective
|
|
265
270
|
options[:input][:required] = 'required'
|
266
271
|
end
|
267
272
|
|
268
|
-
if options[:input][:readonly]
|
273
|
+
if options[:input][:readonly] || form_readonly?
|
269
274
|
options[:input][:readonly] = 'readonly'
|
270
|
-
|
275
|
+
|
276
|
+
unless options[:input][:class].to_s.include?('form-control-plaintext')
|
277
|
+
options[:input][:class] = options[:input][:class].to_s.sub('form-control', 'form-control-plaintext')
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
if options[:input][:disabled] || form_disabled?
|
282
|
+
options[:input][:disabled] = 'disabled'
|
271
283
|
end
|
272
284
|
|
273
285
|
if options[:hint] && options[:hint][:text] && options[:hint][:id]
|
@@ -311,6 +323,22 @@ module Effective
|
|
311
323
|
options[:layout] || @builder.layout
|
312
324
|
end
|
313
325
|
|
326
|
+
def form_readonly?
|
327
|
+
@builder.readonly
|
328
|
+
end
|
329
|
+
|
330
|
+
def form_disabled?
|
331
|
+
@builder.disabled
|
332
|
+
end
|
333
|
+
|
334
|
+
def form_remote?
|
335
|
+
@builder.remote
|
336
|
+
end
|
337
|
+
|
338
|
+
def parent_object
|
339
|
+
@builder.options[:parent_builder]&.object
|
340
|
+
end
|
341
|
+
|
314
342
|
# https://github.com/rails/rails/blob/master/actionview/lib/action_view/helpers/tags/base.rb#L120
|
315
343
|
def tag_id(index = nil)
|
316
344
|
case
|
@@ -15,15 +15,22 @@ module Effective
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def wrapper_options
|
18
|
-
{ class:
|
18
|
+
{ class: [
|
19
|
+
'form-group effective-checks',
|
20
|
+
('no-feedback' unless feedback_options),
|
21
|
+
tag_id,
|
22
|
+
('is-invalid' if feedback_options && has_error?(name)),
|
23
|
+
('is-valid' if feedback_options && has_error? && !has_error?(name))
|
24
|
+
].compact.join(' ')
|
25
|
+
}
|
19
26
|
end
|
20
27
|
|
21
28
|
def feedback_options
|
22
29
|
return false if layout == :inline
|
23
30
|
|
24
31
|
{
|
25
|
-
valid: { class: 'valid-feedback'
|
26
|
-
invalid: { class: 'invalid-feedback'
|
32
|
+
valid: { class: 'valid-feedback' }.compact,
|
33
|
+
invalid: { class: 'invalid-feedback' }.compact
|
27
34
|
}
|
28
35
|
end
|
29
36
|
|
@@ -58,7 +65,7 @@ module Effective
|
|
58
65
|
end
|
59
66
|
|
60
67
|
def item_input_options
|
61
|
-
options[:input].except(:inline, :custom)
|
68
|
+
options[:input].except(:inline, :custom, :required)
|
62
69
|
end
|
63
70
|
|
64
71
|
def item_label_options
|
@@ -26,9 +26,9 @@ module Effective
|
|
26
26
|
|
27
27
|
def build_button_group(&block)
|
28
28
|
if buttons?
|
29
|
-
content_tag(:div, yield, id: button_group_id, class:
|
29
|
+
content_tag(:div, yield, id: button_group_id, class: button_group_class, 'data-toggle': 'buttons')
|
30
30
|
elsif cards?
|
31
|
-
content_tag(:div, yield, id: button_group_id, class:
|
31
|
+
content_tag(:div, yield, id: button_group_id, class: button_group_class, 'data-toggle': 'cards')
|
32
32
|
else
|
33
33
|
yield
|
34
34
|
end
|
@@ -38,12 +38,23 @@ module Effective
|
|
38
38
|
{ class: "form-group #{tag_id}" }
|
39
39
|
end
|
40
40
|
|
41
|
+
def button_group_class
|
42
|
+
[
|
43
|
+
'effective-radios',
|
44
|
+
('no-feedback' if options[:feedback] == false),
|
45
|
+
('btn-group btn-group-toggle' if buttons?),
|
46
|
+
('card-deck' if cards?),
|
47
|
+
('is-invalid' if options[:feedback] && has_error?(name)),
|
48
|
+
('is-valid' if options[:feedback] && has_error? && !has_error?(name))
|
49
|
+
].compact.join(' ')
|
50
|
+
end
|
51
|
+
|
41
52
|
def feedback_options
|
42
53
|
return false if layout == :inline
|
43
54
|
|
44
55
|
{
|
45
|
-
valid: { class: 'valid-feedback'
|
46
|
-
invalid: { class: 'invalid-feedback'
|
56
|
+
valid: { class: 'valid-feedback' }.compact,
|
57
|
+
invalid: { class: 'invalid-feedback' }.compact
|
47
58
|
}
|
48
59
|
end
|
49
60
|
|
@@ -4,6 +4,9 @@
|
|
4
4
|
= effective_form_with model: Effective::StyleGuide.new, url: url do |f|
|
5
5
|
= render '_fields', f: f, uid: 1
|
6
6
|
%hr
|
7
|
+
= effective_form_with model: Effective::StyleGuide.new, url: url, readonly: true do |f|
|
8
|
+
= render '_fields', f: f, uid: 1
|
9
|
+
%hr
|
7
10
|
= effective_form_with model: Effective::StyleGuide.new.tap { |s| s.valid? }, url: url do |f|
|
8
11
|
= render '_fields', f: f, uid: 2
|
9
12
|
%hr
|