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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4366d401ed983ede60b16c9e82fbb76e393975be
4
- data.tar.gz: e33da495ac5d246d803444c8ed3726250ad45416
3
+ metadata.gz: 6159bfe9bf5e58af814e2d446ee907d3a456a54b
4
+ data.tar.gz: 2b232d59b9e6904c6b6358e07631294673a0fa78
5
5
  SHA512:
6
- metadata.gz: 1983cdb4104022d4dc1f24987b418222fcf12688f7c6cf6c1e4553b09f0071e16ef75bc7d98506eb85d1c299183259bf75ec6caf9e6b633327f1ee087c454b22
7
- data.tar.gz: 413e36f0d728563fe5eb845fc236dd086c3dc6581bd51729e57b2d62f160ce73d13ec671d80f63e358583f2b0ea78745a040708682dcd9506a22717499e04ee7
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
- # Clear any server side validation on individual inputs
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').removeClass('form-is-invalid')
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').removeClass('form-is-valid')
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
- enable: ($form) ->
49
- $form.removeClass('form-is-valid').find('[type=submit]').removeAttr('disabled')
53
+ reset: ($form) ->
54
+ $form.removeClass('was-validated').removeClass('form-is-invalid').removeClass('form-is-valid')
50
55
 
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)
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
- @remote_form_payload = ''; @remote_form_flash = ''; @remote_form_flash_payload = '';
61
+ $form.find('[type=submit]').removeAttr('disabled')
60
62
 
61
- flash: ($form, status, $alert) ->
62
- $submit = $form.children('.form-actions')
63
+ flash: ($form, status, message, skip_success = false) ->
64
+ $actions = $form.children('.form-actions')
63
65
 
64
66
  if status == 'danger' || status == 'error'
65
- $submit.find('.eb-icon-x').show().delay(1000).fadeOut('slow')
67
+ $actions.find('.eb-icon-x').show().delay(1000).fadeOut('slow')
66
68
  else
67
- $submit.find('.eb-icon-check').show().delay(1000).fadeOut('slow')
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
- $submit.prepend($alert) if $alert.length > 0
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'>&times;</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 }
@@ -16,3 +16,11 @@ div.btn-group > .btn.first-button {
16
16
  .visible-when-unselected { display: none; }
17
17
  }
18
18
  }
19
+
20
+ .effective-radios.is-valid {
21
+ label { border-color: #28a745; }
22
+ }
23
+
24
+ .effective-radios.is-invalid {
25
+ label { border-color: #dc3545; }
26
+ }
@@ -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, :template
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
- name ? object.errors[name].present? : object.errors.present?
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
- options[:input][:class] = options[:input][:class].to_s.sub('form-control', 'form-control-plaintext')
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: "form-group #{tag_id}" }
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', style: ('display: block;' if has_error? && !has_error?(name)) }.compact,
26
- invalid: { class: 'invalid-feedback', style: ('display: block;' if has_error?(name)) }.compact
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
@@ -10,6 +10,11 @@ module Effective
10
10
  { input_group: { class: 'input-group' }, prepend: content_tag(:span, icon('at-sign'), class: 'input-group-text') }
11
11
  end
12
12
 
13
+ # This has gotta be a valid pattern
14
+ def validated?(name)
15
+ true
16
+ end
17
+
13
18
  end
14
19
  end
15
20
  end
@@ -17,6 +17,11 @@ module Effective
17
17
  { input_group: { class: 'input-group' }, prepend: content_tag(:span, icon('phone'), class: 'input-group-text') }
18
18
  end
19
19
 
20
+ # This has gotta be a valid pattern
21
+ def validated?(name)
22
+ true
23
+ end
24
+
20
25
  private
21
26
 
22
27
  def fax?
@@ -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: 'btn-group btn-group-toggle effective-radios', 'data-toggle': 'buttons')
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: 'card-deck effective-radios', 'data-toggle': 'cards')
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', style: ('display: block;' if has_error? && !has_error?(name)) }.compact,
46
- invalid: { class: 'invalid-feedback', style: ('display: block;' if has_error?(name)) }.compact
56
+ valid: { class: 'valid-feedback' }.compact,
57
+ invalid: { class: 'invalid-feedback' }.compact
47
58
  }
48
59
  end
49
60
 
@@ -2,6 +2,10 @@ module Effective
2
2
  module FormInputs
3
3
  class Submit < Effective::FormInput
4
4
 
5
+ def to_html(&block)
6
+ return super unless (form_readonly? || form_disabled?)
7
+ end
8
+
5
9
  def build_input(&block)
6
10
  tags = [
7
11
  icon('check', style: 'display: none;'),
@@ -10,6 +10,11 @@ module Effective
10
10
  { input_group: { class: 'input-group' }, prepend: content_tag(:span, icon('link'), class: 'input-group-text') }
11
11
  end
12
12
 
13
+ # This has gotta be a valid pattern
14
+ def validated?(name)
15
+ true
16
+ end
17
+
13
18
  end
14
19
  end
15
20
  end
@@ -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
@@ -1,3 +1,3 @@
1
1
  module EffectiveBootstrap
2
- VERSION = '0.0.7'.freeze
2
+ VERSION = '0.0.8'.freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_bootstrap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect