effective_bootstrap 0.0.7 → 0.0.8

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: 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