simple_form-bootstrap 1.0.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 01f4677d60eb55516edfce94662be7be2694a9b0
4
+ data.tar.gz: 5c486b494860f4460812723074f387019713ab2a
5
+ SHA512:
6
+ metadata.gz: eac1e6ee3e50a2b2f8d580c1f915f3b3b92d8da2ba09f92122f314c374562c30d7e00297e7ab01671bad49cd9ef15c22207dd8b7858473c2dd91f4d06950ca89
7
+ data.tar.gz: 468837005159acccbe5e73ce8bac474432e3511cf7dddf3af9fcb8f53d03a14d66c86dd561e9a291fc3a17d4b8008fb3346a6e126c7d5040cafaf39d05bc6e9e
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
@@ -0,0 +1,20 @@
1
+ //= require simple_form-bootstrap/date_time_input
2
+
3
+ (function($) {
4
+ 'use strict';
5
+ function initializeComponents(node) {
6
+ // Enable our date/time pickers
7
+ var datePickers = $('input.bootstrap-datepicker', node);
8
+ datePickers.datetimepicker();
9
+ }
10
+
11
+ $(document).on('ready', function(e) {
12
+ initializeComponents(document);
13
+ })
14
+ $(document).on('DOMNodeInserted', function(e) {
15
+ initializeComponents(e.target);
16
+ });
17
+ $(document).on('nested:fieldAdded', function(e) {
18
+ initializeComponents(e.field);
19
+ });
20
+ })(jQuery);
@@ -0,0 +1,76 @@
1
+ // Hijacks the default Bootstrap date-time picker to always format dates in the specified format
2
+ // through the use of a hidden field.
3
+ (function($) {
4
+ 'use strict';
5
+ /* global moment */
6
+
7
+ // Machine-readable formats used to store dates in hidden fields
8
+ var DATE_FORMAT = 'YYYY-MM-DD';
9
+ var DATETIME_FORMAT = 'YYYY-MM-DDTHH:mm:ssZZ';
10
+ var DATETIME_FORMAT_RAILS = 'YYYY-MM-DD HH:mm:ss ZZ';
11
+
12
+ var oldDateTimePicker = $.fn.datetimepicker;
13
+ if (!oldDateTimePicker) {
14
+ return;
15
+ }
16
+
17
+ var methods = {
18
+ initialise: function(arg) {
19
+ // Synchronise the proper display format
20
+ this.each(methods.initialiseFormat);
21
+
22
+ // Create the controls
23
+ arg = arg || {};
24
+ oldDateTimePicker.call(
25
+ this.filter(':not(input.bootstrap-timepicker)').parent(),
26
+ $.extend({}, arg, { pickTime: false }));
27
+ oldDateTimePicker.call(
28
+ this.filter('input.bootstrap-timepicker').parent(),
29
+ arg);
30
+
31
+ // Hide the backing date picker and show the actual date picker.
32
+ this.attr('type', 'text');
33
+ this.parent().css('display', '');
34
+ this.parent().next('input[type=text]').attr('type', 'hidden');
35
+
36
+ return this;
37
+ },
38
+
39
+ initialiseFormat: function() {
40
+ var $textField = $(this);
41
+ var displayFormat = $textField.data('dateFormat');
42
+
43
+ // Parse date in field (if provided)
44
+ var thisDate = moment($textField.val(), [DATETIME_FORMAT_RAILS, displayFormat]);
45
+ if (thisDate.isValid()) {
46
+ // Set displayed text field
47
+ $textField.val(thisDate.format(displayFormat));
48
+
49
+ // Set hidden field
50
+ var hiddenFormat = $textField.hasClass('bootstrap-timepicker') ? DATETIME_FORMAT :
51
+ DATE_FORMAT;
52
+ $textField.parent().next('input').val(thisDate.format(hiddenFormat));
53
+ }
54
+ }
55
+ };
56
+
57
+ // Replace the datetimepicker prototypes
58
+ $.fn.datetimepicker = function(arg) {
59
+ return methods.initialise.call(this, arg);
60
+ };
61
+ $.fn.datetimepicker.defaults = oldDateTimePicker.defaults;
62
+
63
+ // Ensure that the dates are properly formatted in the text field.
64
+ $(document).on('dp.change dp.show', '.bootstrap-datepicker:' +
65
+ 'not(.bootstrap-timepicker)', function (e) {
66
+ var date = e.date;
67
+ var rails_date_format = date.format(DATE_FORMAT);
68
+ $(this).next('input[type=hidden]').val(rails_date_format);
69
+ });
70
+
71
+ $(document).on('dp.change dp.show', '.bootstrap-timepicker', function (e) {
72
+ var date = e.date;
73
+ var rails_date_format = date.format(DATETIME_FORMAT);
74
+ $(this).next('input[type=hidden]').val(rails_date_format);
75
+ });
76
+ }(jQuery));
@@ -0,0 +1,26 @@
1
+ module SimpleForm::Bootstrap
2
+ extend ActiveSupport::Autoload
3
+
4
+ autoload :Setup
5
+ autoload :FormBuilders
6
+
7
+ eager_autoload do
8
+ autoload :Inputs
9
+ end
10
+
11
+ # Because we are augmenting Simple Form with our input fields, we need to load even when eager
12
+ # loading is not enabled
13
+ SimpleForm::Bootstrap::FormBuilders.load!
14
+
15
+ # Configuration options
16
+ extend SimpleForm::Bootstrap::Setup
17
+
18
+ # Method used to tidy up errors.
19
+ mattr_accessor :error_method
20
+ @@error_method = :first
21
+ end
22
+
23
+ if defined?(Rails)
24
+ require 'simple_form/bootstrap/railtie'
25
+ require 'simple_form/bootstrap/engine'
26
+ end
@@ -0,0 +1,2 @@
1
+ class SimpleForm::Bootstrap::Engine < Rails::Engine
2
+ end
@@ -0,0 +1,9 @@
1
+ module SimpleForm::Bootstrap::FormBuilders
2
+ extend ActiveSupport::Autoload
3
+
4
+ def self.load!
5
+ Dir.glob("#{__dir__}/form_builders/*") do |path|
6
+ require path
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,27 @@
1
+ module SimpleForm::Bootstrap::FormBuilders::DateTime
2
+ DATE_TIME_COLUMN_TYPES = [
3
+ 'datetime',
4
+ 'timestamp',
5
+ 'timestamp without time zone'
6
+ ].freeze
7
+
8
+ DATE_COLUMN_TYPES = [
9
+ 'date'
10
+ ].freeze
11
+
12
+ def default_input_type_with_bootstrap_date_time(attribute_name, column, options, *args, &block)
13
+ if (options.is_a?(Hash) ? options[:as] : @options[:as]).nil? && !column.nil?
14
+ return :bootstrap_date_time if DATE_TIME_COLUMN_TYPES.include?(column.sql_type)
15
+ return :bootstrap_date if DATE_COLUMN_TYPES.include?(column.sql_type)
16
+ end
17
+
18
+ default_input_type_without_bootstrap_date_time(attribute_name, column, options, *args, &block)
19
+ end
20
+ end
21
+
22
+ SimpleForm::FormBuilder.class_eval do
23
+ include SimpleForm::Bootstrap::FormBuilders::DateTime
24
+
25
+ map_type :bootstrap_date_time, :bootstrap_date, to: SimpleForm::Bootstrap::Inputs::DateTimeInput
26
+ alias_method_chain :default_input_type, :bootstrap_date_time
27
+ end
@@ -0,0 +1,7 @@
1
+ module SimpleForm::Bootstrap::Inputs
2
+ extend ActiveSupport::Autoload
3
+
4
+ eager_autoload do
5
+ autoload :DateTimeInput
6
+ end
7
+ end
@@ -0,0 +1,134 @@
1
+ # Inspired by this StackOverflow answer: http://stackoverflow.com/a/19018501
2
+ # I have modified this to work with dates AND times, and also to work better
3
+ # with browsers with JavaScript disabled.
4
+ class SimpleForm::Bootstrap::Inputs::DateTimeInput < SimpleForm::Inputs::Base
5
+ def input(_ = nil)
6
+ text_field_options = input_html_options.with_indifferent_access
7
+ format = text_field_options.delete(:format) || default_format
8
+
9
+ # Integrate with Bootstrap's styling
10
+ text_field_options[:class] << 'form-control'
11
+
12
+ hidden_field_options = text_field_options.dup
13
+ hidden_field_options[:class] = text_field_options[:class].dup # so they won't work with same array object
14
+ hidden_field_options[:id] = "#{attribute_name}_hidden"
15
+ hidden_field_options[:value] ||= value(object).try(:to_s)
16
+ text_field_options[:class] << 'bootstrap-datepicker'
17
+ text_field_options[:class] << 'bootstrap-timepicker' if input_type == :bootstrap_date_time
18
+ text_field_options[:value] ||= format_date(value(object), format)
19
+ text_field_options[:data] = { 'date-format' => strftime_to_momentjs_format(format) }
20
+
21
+ text_field_group_classes = text_field_options[:class].dup
22
+ text_field_group_classes.delete('form-control')
23
+
24
+ return_string = <<-END_INPUT
25
+ <div class="input-group #{text_field_group_classes.join(' ')}" style="display: none">
26
+ #{@builder.hidden_field(attribute_name, text_field_options.to_hash)}
27
+ <span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
28
+ </div>
29
+ #{@builder.text_field(attribute_name, hidden_field_options.to_hash)}
30
+ END_INPUT
31
+ return_string.html_safe
32
+ end
33
+
34
+ protected
35
+
36
+ # Gets the format suitable for this field.
37
+ def default_format
38
+ case input_type
39
+ when :bootstrap_date
40
+ I18n.t('date.formats.default')
41
+ when :bootstrap_date_time
42
+ I18n.t('time.formats.default')
43
+ end
44
+ end
45
+
46
+ def value(object)
47
+ object.send @attribute_name if object
48
+ end
49
+
50
+ def format_date(value, format)
51
+ value.try(:strftime, format)
52
+ end
53
+
54
+ private
55
+
56
+ # rubocop:disable Style/CyclomaticComplexity, Style/MethodLength
57
+ def strftime_to_momentjs_format(format)
58
+ format.gsub(/([^%]%|^%)([_\-\^][a-zA-Z]|[a-zA-Z])/i) do |match|
59
+ last_match = Regexp.last_match(2)
60
+
61
+ # Preprocess the last match:
62
+ # - %_m is blank-padding
63
+ # - %-m is no padding
64
+ # - %^B is uppercase
65
+ padding = 0 # zero padding; 1 = blank, 2 = none
66
+ case last_match[0]
67
+ when '_'
68
+ padding = 1
69
+ last_match = last_match[1]
70
+ when '-'
71
+ padding = 2
72
+ last_match = last_match[1]
73
+ when '^'
74
+ last_match = last_match[1]
75
+ end
76
+
77
+ specifier =
78
+ case last_match
79
+ when 'a' # Abbreviated day
80
+ 'ddd'
81
+ when 'A' # Full day
82
+ 'dddd'
83
+ when 'd' # Day of month, with leading 0
84
+ padding == 2 ? 'D' : 'DD'
85
+ when 'u' # Day of year, with leading 0's (3 digits)
86
+ 'DDDD'
87
+ when 'w' # Day of week, Sunday = 0
88
+ 'd'
89
+
90
+ when 'b', 'h' # Abbreviated month
91
+ 'MMM'
92
+ when 'B' # Full month
93
+ 'MMMM'
94
+ when 'm' # Two digit representation of month (01 = Jan)
95
+ padding == 2 ? 'M' : 'MM'
96
+
97
+ when 'y' # Two digit representation of the year
98
+ 'YY'
99
+ when 'Y' # Four digit representation of the year
100
+ 'YYYY'
101
+
102
+ when 'H' # Two digit representation of the hour in 24-hour format
103
+ 'HH'
104
+ when 'k' # Two digit representation of the hour in 24-hour format, padded with space
105
+ 'H'
106
+ when 'I' # Two digit representation of the hour in 12-hour format
107
+ 'hh'
108
+ when 'l' # Two digit representation of the hour in 12-hour format, padded with space
109
+ 'h'
110
+
111
+ when 'M' # Two digit representation of minute
112
+ 'mm'
113
+ when 'p' # Uppercase AM or PM
114
+ 'A'
115
+ when 'P' # Lowercase AM or PM
116
+ 'a'
117
+ when 'S' # Two digit representation of seconds
118
+ 'ss'
119
+
120
+ when 'z' # The time zone offset. e.g. -0500
121
+ 'ZZ'
122
+ when 'Z' # The time zone offset. e.g. EST
123
+ 'z'
124
+ else
125
+ match
126
+ end
127
+
128
+ # Strip the % and return the new specifier
129
+ match = Regexp.last_match(1)
130
+ (match.slice(0, match.length - 1) || '') + specifier
131
+ end
132
+ end
133
+ # rubocop:enable Style/CyclomaticComplexity, Style/MethodLength
134
+ end
@@ -0,0 +1,5 @@
1
+ require 'rails/railtie'
2
+
3
+ class SimpleForm::Bootstrap::Railtie < Rails::Railtie
4
+ config.eager_load_namespaces << SimpleForm::Bootstrap
5
+ end
@@ -0,0 +1,155 @@
1
+ # Handles configuration Simple Form with Bootstrap defaults.
2
+ module SimpleForm::Bootstrap::Setup
3
+ def setup
4
+ yield self
5
+ configure_simple_form
6
+ end
7
+
8
+ private
9
+
10
+ def configure_simple_form
11
+ SimpleForm.setup do |config|
12
+ config.error_notification_class = 'alert alert-danger'
13
+ config.button_class = 'btn btn-default'
14
+ config.boolean_label_class = nil
15
+
16
+ config.wrappers :vertical_form, tag: 'div', class: 'form-group',
17
+ error_class: 'has-error' do |b|
18
+ b.use :html5
19
+ b.use :placeholder
20
+ b.optional :maxlength
21
+ b.optional :pattern
22
+ b.optional :min_max
23
+ b.optional :readonly
24
+ b.use :label, class: 'control-label'
25
+
26
+ b.use :input, class: 'form-control'
27
+ b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
28
+ b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
29
+ end
30
+
31
+ config.wrappers :vertical_file_input, tag: 'div', class: 'form-group',
32
+ error_class: 'has-error' do |b|
33
+ b.use :html5
34
+ b.use :placeholder
35
+ b.optional :maxlength
36
+ b.optional :readonly
37
+ b.use :label, class: 'control-label'
38
+
39
+ b.use :input
40
+ b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
41
+ b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
42
+ end
43
+
44
+ config.wrappers :vertical_boolean, tag: 'div', class: 'form-group',
45
+ error_class: 'has-error' do |b|
46
+ b.use :html5
47
+ b.optional :readonly
48
+
49
+ b.wrapper tag: 'div', class: 'checkbox' do |ba|
50
+ ba.use :label_input
51
+ end
52
+
53
+ b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
54
+ b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
55
+ end
56
+
57
+ config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group',
58
+ error_class: 'has-error' do |b|
59
+ b.use :html5
60
+ b.optional :readonly
61
+ b.use :label, class: 'control-label'
62
+ b.use :input
63
+ b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
64
+ b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
65
+ end
66
+
67
+ config.wrappers :horizontal_form, tag: 'div', class: 'form-group',
68
+ error_class: 'has-error' do |b|
69
+ b.use :html5
70
+ b.use :placeholder
71
+ b.optional :maxlength
72
+ b.optional :pattern
73
+ b.optional :min_max
74
+ b.optional :readonly
75
+ b.use :label, class: 'col-sm-3 control-label'
76
+
77
+ b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
78
+ ba.use :input, class: 'form-control'
79
+ ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
80
+ ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
81
+ end
82
+ end
83
+
84
+ config.wrappers :horizontal_file_input, tag: 'div', class: 'form-group',
85
+ error_class: 'has-error' do |b|
86
+ b.use :html5
87
+ b.use :placeholder
88
+ b.optional :maxlength
89
+ b.optional :readonly
90
+ b.use :label, class: 'col-sm-3 control-label'
91
+
92
+ b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
93
+ ba.use :input
94
+ ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
95
+ ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
96
+ end
97
+ end
98
+
99
+ config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group',
100
+ error_class: 'has-error' do |b|
101
+ b.use :html5
102
+ b.optional :readonly
103
+
104
+ b.wrapper tag: 'div', class: 'col-sm-offset-3 col-sm-9' do |wr|
105
+ wr.wrapper tag: 'div', class: 'checkbox' do |ba|
106
+ ba.use :label_input, class: 'col-sm-9'
107
+ end
108
+
109
+ wr.use :error, wrap_with: { tag: 'span', class: 'help-block' }
110
+ wr.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
111
+ end
112
+ end
113
+
114
+ config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'form-group',
115
+ error_class: 'has-error' do |b|
116
+ b.use :html5
117
+ b.optional :readonly
118
+
119
+ b.use :label, class: 'col-sm-3 control-label'
120
+
121
+ b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
122
+ ba.use :input
123
+ ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
124
+ ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
125
+ end
126
+ end
127
+
128
+ config.wrappers :inline_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
129
+ b.use :html5
130
+ b.use :placeholder
131
+ b.optional :maxlength
132
+ b.optional :pattern
133
+ b.optional :min_max
134
+ b.optional :readonly
135
+ b.use :label, class: 'sr-only'
136
+
137
+ b.use :input, class: 'form-control'
138
+ b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
139
+ b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
140
+ end
141
+
142
+ # Wrappers for forms and inputs using the Bootstrap toolkit.
143
+ # Check the Bootstrap docs (http://getbootstrap.com)
144
+ # to learn about the different styles for forms and inputs,
145
+ # buttons and other elements.
146
+ config.default_wrapper = :vertical_form
147
+ config.wrapper_mappings = {
148
+ check_boxes: :vertical_radio_and_checkboxes,
149
+ radio_buttons: :vertical_radio_and_checkboxes,
150
+ file: :vertical_file_input,
151
+ boolean: :vertical_boolean,
152
+ }
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,4 @@
1
+ module SimpleForm; end
2
+ module SimpleForm::Bootstrap
3
+ VERSION = '1.0.0'
4
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_form-bootstrap
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Joel Low
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bootstrap-sass
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: simple_form
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 3.1.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 3.1.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: activemodel
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '4.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: actionpack
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '4.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '4.0'
69
+ description: Initialises Simple Form to automatically produce Bootstrap 3-friendly
70
+ markup
71
+ email: joel@joelsplace.sg
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - Rakefile
77
+ - app/assets/javascripts/simple_form-bootstrap.js
78
+ - app/assets/javascripts/simple_form-bootstrap/date_time_input.js
79
+ - lib/simple_form/bootstrap.rb
80
+ - lib/simple_form/bootstrap/engine.rb
81
+ - lib/simple_form/bootstrap/form_builders.rb
82
+ - lib/simple_form/bootstrap/form_builders/date_time.rb
83
+ - lib/simple_form/bootstrap/inputs.rb
84
+ - lib/simple_form/bootstrap/inputs/date_time_input.rb
85
+ - lib/simple_form/bootstrap/railtie.rb
86
+ - lib/simple_form/bootstrap/setup.rb
87
+ - lib/simple_form/bootstrap/version.rb
88
+ homepage: https://github.com/lowjoel/simple_form-bootstrap
89
+ licenses:
90
+ - MIT
91
+ metadata: {}
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project:
108
+ rubygems_version: 2.2.2
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: Initialises Simple Form to automatically produce Bootstrap 3-friendly markup.
112
+ Also adds date and time pickers.
113
+ test_files: []