bootstrap_form_extensions 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 +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +34 -0
- data/app/assets/javascripts/bootstrap_form_extensions/arrayed_field.js +70 -0
- data/app/assets/javascripts/bootstrap_form_extensions/bootstrap-timepicker.min.js +5 -0
- data/app/assets/javascripts/bootstrap_form_extensions/index.js +2 -0
- data/app/assets/javascripts/bootstrap_form_extensions/jquery.html5data.min.js +7 -0
- data/app/assets/javascripts/bootstrap_form_extensions/scheduler.js +226 -0
- data/app/assets/javascripts/bootstrap_form_extensions/select_or_new.js +76 -0
- data/app/assets/javascripts/bootstrap_form_extensions/time_picker.js +61 -0
- data/app/assets/javascripts/bootstrap_form_extensions/timespan.js +60 -0
- data/app/assets/stylesheets/bootstrap_form_extensions/bootstrap-timepicker.min.css +10 -0
- data/app/assets/stylesheets/bootstrap_form_extensions/common.css +11 -0
- data/app/assets/stylesheets/bootstrap_form_extensions/index.css +4 -0
- data/app/assets/stylesheets/bootstrap_form_extensions/scheduler.css +31 -0
- data/app/assets/stylesheets/bootstrap_form_extensions/submit_bar.css +4 -0
- data/app/views/bootstrap_form_extensions/_submit_bar.html.erb +36 -0
- data/lib/bootstrap_form_extensions.rb +22 -0
- data/lib/bootstrap_form_extensions/arrayed_field.rb +107 -0
- data/lib/bootstrap_form_extensions/date_time_pickers.rb +71 -0
- data/lib/bootstrap_form_extensions/helpers.rb +18 -0
- data/lib/bootstrap_form_extensions/scheduler.rb +72 -0
- data/lib/bootstrap_form_extensions/select_or_new.rb +36 -0
- data/lib/bootstrap_form_extensions/submit_bar.rb +65 -0
- data/lib/bootstrap_form_extensions/timespan.rb +55 -0
- data/lib/bootstrap_form_extensions/version.rb +3 -0
- data/lib/tasks/rails_bootstrap_form_extensions_tasks.rake +4 -0
- data/test/arrayed_field_test.rb +63 -0
- data/test/bootstrap_form_extensions_test.rb +7 -0
- data/test/date_time_pickers_test.rb +50 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/models/category.rb +7 -0
- data/test/dummy/app/models/thing.rb +46 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +29 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +26 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +41 -0
- data/test/dummy/config/environments/production.rb +79 -0
- data/test/dummy/config/environments/test.rb +42 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +3 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/db/migrate/20150918185031_create_things.rb +9 -0
- data/test/dummy/db/migrate/20150924203053_add_timespan.rb +7 -0
- data/test/dummy/db/migrate/20150929213249_add_arrayed_field.rb +7 -0
- data/test/dummy/db/migrate/20151006171627_add_another_arrayed_field.rb +7 -0
- data/test/dummy/db/migrate/20151006181943_add_json_field.rb +7 -0
- data/test/dummy/db/migrate/20151007213131_add_scheduler_field.rb +7 -0
- data/test/dummy/db/migrate/20151030194330_add_date_time.rb +7 -0
- data/test/dummy/db/migrate/20151106165522_add_category.rb +10 -0
- data/test/dummy/db/schema.rb +31 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +0 -0
- data/test/dummy/log/test.log +1997 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/test/fixtures/things.yml +8 -0
- data/test/javascripts/arrayed_field_spec.js +101 -0
- data/test/javascripts/helpers/function_bind_polyfill_for_phantomjs.js +32 -0
- data/test/javascripts/helpers/jasmine-jquery.js +838 -0
- data/test/javascripts/scheduler_spec.js +354 -0
- data/test/javascripts/select_or_new_spec.js +113 -0
- data/test/javascripts/support/jasmine.yml +127 -0
- data/test/javascripts/support/jasmine_helper.rb +19 -0
- data/test/javascripts/time_picker_spec.js +42 -0
- data/test/javascripts/timespan_spec.js +81 -0
- data/test/javascripts/vendor/bootstrap.min.js +7 -0
- data/test/javascripts/vendor/jquery-2.1.4.min.js +4 -0
- data/test/scheduler_serializer_test.rb +200 -0
- data/test/scheduler_test.rb +15 -0
- data/test/select_or_new_test.rb +37 -0
- data/test/submit_bar_test.rb +112 -0
- data/test/test_helper.rb +37 -0
- data/test/timespan_test.rb +47 -0
- metadata +291 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
module BootstrapFormExtensions
|
|
2
|
+
|
|
3
|
+
module Scheduler
|
|
4
|
+
|
|
5
|
+
include BootstrapFormExtensions::Helpers
|
|
6
|
+
|
|
7
|
+
def self.serializer to: :yaml, default_selection: true
|
|
8
|
+
BootstrapFormExtensions::Scheduler::Serializer.new to, default_selection
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def scheduler method, **options
|
|
12
|
+
schedule = object.send method
|
|
13
|
+
hidden = hidden_field method, value: JSON.dump(schedule), class: 'scheduler-hidden-field'
|
|
14
|
+
options[:wrapper] ||= {}
|
|
15
|
+
options[:wrapper][:data] ||= {}
|
|
16
|
+
options[:wrapper][:data][:scheduler] = true
|
|
17
|
+
form_group_builder(method, options) { hidden + schedule_to_table(schedule) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def schedule_to_table schedule
|
|
23
|
+
content_tag :table, class: 'scheduler-badge' do
|
|
24
|
+
content_tag :tbody do
|
|
25
|
+
schedule.each.with_index.inject(''.html_safe) do |rows, (day_array, day_index)|
|
|
26
|
+
rows << content_tag(:tr) do
|
|
27
|
+
day_array.each.with_index.inject(''.html_safe) do |columns, (value, hour_index)|
|
|
28
|
+
columns << content_tag(:td, ' '.html_safe, class: (true?(value) ? 'on' : 'off'), data: { day: day_index, hour: hour_index })
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class Serializer
|
|
37
|
+
|
|
38
|
+
include BootstrapFormExtensions::Helpers
|
|
39
|
+
|
|
40
|
+
attr_reader :to_format, :default_selection
|
|
41
|
+
|
|
42
|
+
def initialize to_format, default_selection
|
|
43
|
+
@to_format = to_format
|
|
44
|
+
@default_selection = default_selection
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def load value_from_db
|
|
48
|
+
value_from_db = YAML.load(value_from_db.to_s || '') if to_format == :yaml
|
|
49
|
+
value_from_db = [] if value_from_db.blank?
|
|
50
|
+
value_from_db = parse_schedule_array value_from_db unless value_from_db[6].try(:[], 23).present?
|
|
51
|
+
value_from_db
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def dump value_from_user
|
|
55
|
+
value_from_user = JSON.parse value_from_user rescue [] if value_from_user.is_a? String
|
|
56
|
+
value_from_user = [] unless value_from_user.is_a? Array
|
|
57
|
+
value_from_user = parse_schedule_array value_from_user
|
|
58
|
+
value_from_user = value_from_user.to_yaml if to_format == :yaml
|
|
59
|
+
value_from_user
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def parse_schedule_array value
|
|
65
|
+
Array.new(7) { |i| Array.new(24) { |j| (value[i][j].nil? && default_selection) || true?(value[i][j]) rescue default_selection } }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module BootstrapFormExtensions
|
|
2
|
+
|
|
3
|
+
module SelectOrNew
|
|
4
|
+
|
|
5
|
+
include BootstrapFormExtensions::Helpers
|
|
6
|
+
|
|
7
|
+
def select_or_new method, choices = [], options = {}, html_options = {}
|
|
8
|
+
new_is_selected = object.send(method) == 0
|
|
9
|
+
|
|
10
|
+
# select...
|
|
11
|
+
options.delete :prompt
|
|
12
|
+
options.delete :include_blank
|
|
13
|
+
choices.unshift [ "Please select", nil ]
|
|
14
|
+
choices.push [ "New...", 0 ]
|
|
15
|
+
html_options[:class] = [ "form-control", html_options[:class] ].compact.join(' ')
|
|
16
|
+
html_options[:style] = 'display: none;' if new_is_selected
|
|
17
|
+
select = self.select_without_bootstrap method, choices, options, html_options
|
|
18
|
+
|
|
19
|
+
# ... or new
|
|
20
|
+
icon = @template.glyphicon_tag 'remove', class: 'text-danger'
|
|
21
|
+
icon = content_tag :div, icon, class: 'input-group-addon select-or-new-cancel'
|
|
22
|
+
new_method = "new_#{method.to_s.sub(/_id$/, '')}"
|
|
23
|
+
new_field_name = "#{object_name}[#{new_method}]"
|
|
24
|
+
text = @template.text_field_tag new_field_name, object.try(new_method), class: 'form-control', placeholder: 'New...'
|
|
25
|
+
text = content_tag :div, text + icon, class: 'input-group', style: (new_is_selected ? '' : 'display: none;')
|
|
26
|
+
|
|
27
|
+
# form group to put them together
|
|
28
|
+
html_options[:wrapper] ||= {}
|
|
29
|
+
html_options[:wrapper][:data] ||= {}
|
|
30
|
+
html_options[:wrapper][:data][:select_or_new] = true
|
|
31
|
+
form_group_builder(method, options, html_options) { select + text }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module BootstrapFormExtensions
|
|
2
|
+
|
|
3
|
+
module SubmitBar
|
|
4
|
+
|
|
5
|
+
mattr_accessor :partial
|
|
6
|
+
@@partial = 'bootstrap_form_extensions/submit_bar'
|
|
7
|
+
|
|
8
|
+
mattr_accessor :show_submit_button
|
|
9
|
+
@@show_submit_button = true
|
|
10
|
+
|
|
11
|
+
mattr_accessor :submit_button_text
|
|
12
|
+
@@submit_button_text = 'Save'
|
|
13
|
+
|
|
14
|
+
mattr_accessor :show_submit_menu
|
|
15
|
+
@@show_submit_menu = true
|
|
16
|
+
|
|
17
|
+
mattr_accessor :show_submit_and_dup_button
|
|
18
|
+
@@show_submit_and_dup_button = true
|
|
19
|
+
|
|
20
|
+
mattr_accessor :show_submit_and_new_button
|
|
21
|
+
@@show_submit_and_new_button = true
|
|
22
|
+
|
|
23
|
+
mattr_accessor :show_cancel_button
|
|
24
|
+
@@show_cancel_button = true
|
|
25
|
+
|
|
26
|
+
mattr_accessor :cancel_button_text
|
|
27
|
+
@@cancel_button_text = 'Cancel'
|
|
28
|
+
|
|
29
|
+
mattr_accessor :back_button_text
|
|
30
|
+
@@back_button_text = 'Back'
|
|
31
|
+
|
|
32
|
+
def submit_bar show_submit_button: @@show_submit_button, submit_button_text: @@submit_button_text,
|
|
33
|
+
show_submit_menu: @@show_submit_menu, show_submit_and_dup_button: @@show_submit_and_dup_button, show_submit_and_new_button: @@show_submit_and_new_button,
|
|
34
|
+
show_cancel_button: @@show_cancel_button, cancel_button_text: nil, cancel_button_url: nil,
|
|
35
|
+
extra_buttons: [], right_buttons: [],
|
|
36
|
+
partial: @@partial
|
|
37
|
+
|
|
38
|
+
show_submit_menu &&= @template.current_ability.can? :new, object if @template.respond_to? :current_ability
|
|
39
|
+
cancel_button_url ||= @template.url_for(object.persisted? ? object : @template.controller_name.to_sym) rescue 'javascript:history.back();'
|
|
40
|
+
cancel_button_text ||= show_submit_button ? @@cancel_button_text : @@back_button_text
|
|
41
|
+
|
|
42
|
+
@template.render partial, {
|
|
43
|
+
show_submit_button: show_submit_button, submit_button_text: submit_button_text,
|
|
44
|
+
show_submit_menu: show_submit_menu, show_submit_and_dup_button: show_submit_and_dup_button, show_submit_and_new_button: show_submit_and_new_button,
|
|
45
|
+
show_cancel_button: show_cancel_button, cancel_button_text: cancel_button_text, cancel_button_url: cancel_button_url,
|
|
46
|
+
extra_buttons: parse_extra_buttons_for_submit_bar(extra_buttons, :extra),
|
|
47
|
+
right_buttons: parse_extra_buttons_for_submit_bar(right_buttons, :right),
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def parse_extra_buttons_for_submit_bar buttons, type
|
|
54
|
+
buttons.map do |options|
|
|
55
|
+
text = options.delete :text
|
|
56
|
+
url = options.delete :url
|
|
57
|
+
options[:class] = [ 'btn', 'btn-default', "submitbar-#{type}-button", options[:class] ].compact.join(' ')
|
|
58
|
+
options[:rel] ||= "nofollow"
|
|
59
|
+
{ text: text, url: url, options: options }
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module BootstrapFormExtensions
|
|
2
|
+
|
|
3
|
+
module Timespan
|
|
4
|
+
|
|
5
|
+
UNITS_IN_SECONDS = ActiveSupport::OrderedHash[ :seconds, 1, :minutes, 60, :hours, 3600, :days, 86400, :weeks, 604800, :months, 18144000 ]
|
|
6
|
+
|
|
7
|
+
mattr_accessor :units
|
|
8
|
+
@@units = UNITS_IN_SECONDS.keys
|
|
9
|
+
|
|
10
|
+
def timespan method, units: @@units, quantity_options: {}, unit_options: {}
|
|
11
|
+
quantity, selected, units = quantity_and_units_for_timespan method, units
|
|
12
|
+
hidden = hidden_field method, class: 'timespan-seconds'
|
|
13
|
+
field = text_field_for_timespan method, quantity, quantity_options
|
|
14
|
+
select = select_for_timespan method, selected, units, unit_options
|
|
15
|
+
content_tag :span, hidden + field + ' '.html_safe + select, data: { timespan: true }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def quantity_and_units_for_timespan method, units
|
|
21
|
+
units = units.map { |unit| [ unit, UNITS_IN_SECONDS[unit] ] }
|
|
22
|
+
|
|
23
|
+
time_in_seconds = object.send method
|
|
24
|
+
return [ '', units.first.last, units ] if time_in_seconds.blank?
|
|
25
|
+
|
|
26
|
+
selected = UNITS_IN_SECONDS.values.reverse.find(proc { 1 }) { |seconds| time_in_seconds % seconds == 0 }
|
|
27
|
+
quantity = time_in_seconds / selected
|
|
28
|
+
[ quantity, selected, units ]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def text_field_for_timespan method, quantity, quantity_options
|
|
32
|
+
text_field_name = method.to_s.sub(/(_in_seconds)?$/, '_quantity').to_sym
|
|
33
|
+
|
|
34
|
+
quantity_options[:size] ||= 5
|
|
35
|
+
quantity_options[:class] = [ "form-control", "timespan-quantity", quantity_options[:class] ].compact.join(' ')
|
|
36
|
+
|
|
37
|
+
field = @template.text_field_tag text_field_name, quantity, quantity_options
|
|
38
|
+
field << generate_help(method, nil)
|
|
39
|
+
|
|
40
|
+
css_class = 'form-group'
|
|
41
|
+
css_class << " #{error_class}" if has_error?(method)
|
|
42
|
+
|
|
43
|
+
content_tag :div, field, class: css_class
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def select_for_timespan method, selected, units, unit_options
|
|
47
|
+
select_field_name = method.to_s.sub(/(_in_seconds)?$/, '_unit').to_sym
|
|
48
|
+
unit_options[:class] = [ "form-control", "timespan-unit", unit_options[:class] ].compact.join(' ')
|
|
49
|
+
select = @template.select_tag select_field_name, @template.options_for_select(units, selected), unit_options
|
|
50
|
+
content_tag :div, select, class: 'form-group'
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class ArrayedFieldTest < ActionView::TestCase
|
|
4
|
+
include BootstrapFormExtensions::ArrayedField
|
|
5
|
+
|
|
6
|
+
def setup
|
|
7
|
+
setup_test_fixture
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
test "arrayed_text_field with default values" do
|
|
11
|
+
expected = '<div class="form-group"><label class="control-label col-sm-2" for="thing_list">List</label><div class="col-sm-10"><div data-arrayed-field="true"><div class="blueprint-for-arrayed-field" style="display:none;"><div class="row voffset1"><div class="col-sm-11"><input type="text" id="" class="form-control" data-name="thing[list][]" /></div><div class="col-sm-1"><a class="btn btn-default remove-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-trash"></i></a></div></div></div><div class="arrayed-field-rows"><div class="row voffset1"><div class="col-sm-11"><input type="text" name="thing[list][]" id="thing_list_" value="One" class="form-control" /></div><div class="col-sm-1"><a class="btn btn-default remove-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-trash"></i></a></div></div><div class="row voffset1"><div class="col-sm-11"><input type="text" name="thing[list][]" id="thing_list_" value="Two" class="form-control" /></div><div class="col-sm-1"><a class="btn btn-default remove-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-trash"></i></a></div></div></div><div class="row voffset1"><div class="col-sm-12"><a class="btn btn-default add-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-plus"></i></a></div></div></div></div></div>'
|
|
12
|
+
assert_equal expected, @builder.arrayed_text_field(:list)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
test "arrayed_url_field with default values" do
|
|
16
|
+
expected = '<div class="form-group"><label class="control-label col-sm-2" for="thing_urls">Urls</label><div class="col-sm-10"><div data-arrayed-field="true"><div class="blueprint-for-arrayed-field" style="display:none;"><div class="row voffset1"><div class="col-sm-11"><input type="url" id="" class="form-control" data-name="thing[urls][]" /></div><div class="col-sm-1"><a class="btn btn-default remove-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-trash"></i></a></div></div></div><div class="arrayed-field-rows"><div class="row voffset1"><div class="col-sm-11"><input type="url" name="thing[urls][]" id="thing_urls_" value="www.example1.com" class="form-control" /></div><div class="col-sm-1"><a class="btn btn-default remove-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-trash"></i></a></div></div><div class="row voffset1"><div class="col-sm-11"><input type="url" name="thing[urls][]" id="thing_urls_" value="www.example2.com" class="form-control" /></div><div class="col-sm-1"><a class="btn btn-default remove-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-trash"></i></a></div></div></div><div class="row voffset1"><div class="col-sm-12"><a class="btn btn-default add-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-plus"></i></a></div></div></div></div></div>'
|
|
17
|
+
assert_equal expected, @builder.arrayed_url_field(:urls)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
test "ArrayedField, with nonexistent attribute, assumes the value is an empty array" do
|
|
21
|
+
expected = '<div class="form-group"><label class="control-label col-sm-2" for="thing_nonexistent">Nonexistent</label><div class="col-sm-10"><div data-arrayed-field="true"><div class="blueprint-for-arrayed-field" style="display:none;"><div class="row voffset1"><div class="col-sm-11"><input type="text" id="" class="form-control" data-name="thing[nonexistent][]" /></div><div class="col-sm-1"><a class="btn btn-default remove-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-trash"></i></a></div></div></div><div class="arrayed-field-rows"></div><div class="row voffset1"><div class="col-sm-12"><a class="btn btn-default add-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-plus"></i></a></div></div></div></div></div>'
|
|
22
|
+
assert_equal expected, @builder.arrayed_text_field(:nonexistent)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
test "ArrayedField, with non-array attribute, assumes the value is an empty array" do
|
|
26
|
+
expected = '<div class="form-group"><label class="control-label col-sm-2 required" for="thing_name">Name</label><div class="col-sm-10"><div data-arrayed-field="true"><div class="blueprint-for-arrayed-field" style="display:none;"><div class="row voffset1"><div class="col-sm-11"><input type="text" id="" class="form-control" data-name="thing[name][]" /></div><div class="col-sm-1"><a class="btn btn-default remove-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-trash"></i></a></div></div></div><div class="arrayed-field-rows"></div><div class="row voffset1"><div class="col-sm-12"><a class="btn btn-default add-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-plus"></i></a></div></div></div></div></div>'
|
|
27
|
+
assert_equal expected, @builder.arrayed_text_field(:name)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
test "pass options to the form group in the an ArrayedField" do
|
|
31
|
+
@output_buffer = @builder.arrayed_text_field(:list, wrapper_class: 'extra-class')
|
|
32
|
+
assert_select 'div.form-group.extra-class'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
test "arrayed_json_field with default values" do
|
|
36
|
+
expected = '<div class="form-group"><label class="control-label col-sm-2" for="thing_variables">Variables</label><div class="col-sm-10"><div data-arrayed-field="true"><div class="blueprint-for-arrayed-field" style="display:none;"><div class="row voffset1"><div class="col-sm-2"><input type="text" id="" class="form-control" placeholder="name" data-name="thing[variables][][name]" /></div><div class="col-sm-2"><input type="text" id="" class="form-control" placeholder="value" data-name="thing[variables][][value]" /></div><div class="col-sm-1"><a class="btn btn-default remove-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-trash"></i></a></div></div></div><div class="arrayed-field-rows"><div class="row voffset1"><div class="col-sm-2"><input type="text" name="thing[variables][][name]" id="thing_variables__name" class="form-control" placeholder="name" /></div><div class="col-sm-2"><input type="text" name="thing[variables][][value]" id="thing_variables__value" class="form-control" placeholder="value" /></div><div class="col-sm-1"><a class="btn btn-default remove-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-trash"></i></a></div></div><div class="row voffset1"><div class="col-sm-2"><input type="text" name="thing[variables][][name]" id="thing_variables__name" class="form-control" placeholder="name" /></div><div class="col-sm-2"><input type="text" name="thing[variables][][value]" id="thing_variables__value" class="form-control" placeholder="value" /></div><div class="col-sm-1"><a class="btn btn-default remove-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-trash"></i></a></div></div></div><div class="row voffset1"><div class="col-sm-12"><a class="btn btn-default add-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-plus"></i></a></div></div></div></div></div>'
|
|
37
|
+
assert_equal expected, @builder.arrayed_json_field(:variables, %i[ name value ])
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
test "arrayed_json_field with custom input types" do
|
|
41
|
+
expected = <<-HTML.chomp
|
|
42
|
+
<div class="form-group"><label class="control-label col-sm-2" for="thing_variables">Variables</label><div class="col-sm-10"><div data-arrayed-field="true"><div class="blueprint-for-arrayed-field" style="display:none;"><div class="row voffset1"><div class="col-sm-2"><select id="" class="form-control" data-name="thing[variables][][name]"><option value="var1">Variable One</option>
|
|
43
|
+
<option value="var2">Variable Two</option>
|
|
44
|
+
<option value="var3">Variable Three</option></select></div><div class="col-sm-2"><input type="text" id="" class="form-control" placeholder="value" data-name="thing[variables][][value]" /></div><div class="col-sm-1"><a class="btn btn-default remove-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-trash"></i></a></div></div></div><div class="arrayed-field-rows"><div class="row voffset1"><div class="col-sm-2"><select id="" class="form-control"><option value="var1">Variable One</option>
|
|
45
|
+
<option value="var2">Variable Two</option>
|
|
46
|
+
<option value="var3">Variable Three</option></select></div><div class="col-sm-2"><input type="text" name="thing[variables][][value]" id="thing_variables__value" class="form-control" placeholder="value" /></div><div class="col-sm-1"><a class="btn btn-default remove-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-trash"></i></a></div></div><div class="row voffset1"><div class="col-sm-2"><select id="" class="form-control"><option value="var1">Variable One</option>
|
|
47
|
+
<option value="var2">Variable Two</option>
|
|
48
|
+
<option value="var3">Variable Three</option></select></div><div class="col-sm-2"><input type="text" name="thing[variables][][value]" id="thing_variables__value" class="form-control" placeholder="value" /></div><div class="col-sm-1"><a class="btn btn-default remove-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-trash"></i></a></div></div></div><div class="row voffset1"><div class="col-sm-12"><a class="btn btn-default add-arrayed-field-row" href="javascript:void(0);"><i class=" glyphicon glyphicon-plus"></i></a></div></div></div></div></div>
|
|
49
|
+
HTML
|
|
50
|
+
assert_equal expected, @builder.arrayed_json_field(:variables, [ { name: { type: :select, options: options_for_variables } }, :value ])
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def options_for_variables
|
|
56
|
+
[
|
|
57
|
+
[ "Variable One", "var1" ],
|
|
58
|
+
[ "Variable Two", "var2" ],
|
|
59
|
+
[ "Variable Three", "var3" ],
|
|
60
|
+
]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class DateTimePickersTest < ActionView::TestCase
|
|
4
|
+
include BootstrapFormExtensions::DateTimePickers
|
|
5
|
+
|
|
6
|
+
def setup
|
|
7
|
+
setup_test_fixture
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
test "date_picker" do
|
|
11
|
+
expected = '<div class="form-group"><label class="control-label col-sm-2" for="thing_start_date">Start date</label><div class="col-sm-10"><div class="input-group date" data-provide="datepicker" data-date-today-highlight="true" data-date-format="yyyy-mm-dd" data-date-today-btn="linked" data-date-autoclose="true" data-date-disable-touch-keyboard="true" data-date-enable-on-readonly="false" data-date-show-on-focus="false"><input size="10" class="form-control" type="text" value="1971-10-21" name="thing[start_date]" id="thing_start_date" /><span class="input-group-addon"><i class=" glyphicon glyphicon-calendar"></i></span></div></div></div>'
|
|
12
|
+
assert_equal expected, @builder.date_picker(:start_date)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
test "add an option to date_picker" do
|
|
16
|
+
@output_buffer = @builder.date_picker :start_date, widget: { clear_btn: true }
|
|
17
|
+
assert_select 'div.date[data-date-clear-btn=true]'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
test "overwrite one of the default options to date_picker" do
|
|
21
|
+
@output_buffer = @builder.date_picker :start_date, widget: { format: 'dd-mm-yyyy' }
|
|
22
|
+
assert_select 'div.date[data-date-format="dd-mm-yyyy"]'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
test "time_picker" do
|
|
26
|
+
expected = '<div class="form-group"><label class="control-label col-sm-2" for="thing_start_time">Start time</label><div class="col-sm-10"><div class="input-group bootstrap-timepicker"><input class="form-control" size="8" data-provide="timepicker" type="text" value="07:30:00" name="thing[start_time]" id="thing_start_time" /><span class="input-group-addon"><i class=" glyphicon glyphicon-time"></i></span></div></div></div>'
|
|
27
|
+
assert_equal expected, @builder.time_picker(:start_time)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
test "add an option to time_picker" do
|
|
31
|
+
@output_buffer = @builder.time_picker :start_time, widget: { disable_mousewheel: true }
|
|
32
|
+
assert_select 'input[data-time-disable-mousewheel=true]'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
test "date_time_picker" do
|
|
36
|
+
expected = '<div class="form-group"><label class="control-label col-sm-2" for="thing_start_at">Start at</label><div class="col-sm-10 form-inline"><div class="form-group"><div class="input-group date" data-provide="datepicker" data-date-today-highlight="true" data-date-format="yyyy-mm-dd" data-date-today-btn="linked" data-date-autoclose="true" data-date-disable-touch-keyboard="true" data-date-enable-on-readonly="false" data-date-show-on-focus="false"><input size="10" class="form-control" type="text" value="1971-10-21" name="thing[start_date]" id="thing_start_date" /><span class="input-group-addon"><i class=" glyphicon glyphicon-calendar"></i></span></div></div> <div class="form-group"><div class="input-group bootstrap-timepicker"><input class="form-control" size="8" data-provide="timepicker" type="text" value="07:30:00" name="thing[start_time]" id="thing_start_time" /><span class="input-group-addon"><i class=" glyphicon glyphicon-time"></i></span></div></div></div></div>'
|
|
37
|
+
assert_equal expected, @builder.date_time_picker(:start_at)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
test "add an option to the date control in the date_time_picker" do
|
|
41
|
+
@output_buffer = @builder.date_time_picker :start_at, date_options: { widget: { clear_btn: true } }
|
|
42
|
+
assert_select 'div.date[data-date-clear-btn=true]'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
test "add an option to the time control in the date_time_picker" do
|
|
46
|
+
@output_buffer = @builder.date_time_picker :start_at, time_options: { widget: { disable_mousewheel: true } }
|
|
47
|
+
assert_select 'input[data-time-disable-mousewheel=true]'
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
== README
|
|
2
|
+
|
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
|
4
|
+
application up and running.
|
|
5
|
+
|
|
6
|
+
Things you may want to cover:
|
|
7
|
+
|
|
8
|
+
* Ruby version
|
|
9
|
+
|
|
10
|
+
* System dependencies
|
|
11
|
+
|
|
12
|
+
* Configuration
|
|
13
|
+
|
|
14
|
+
* Database creation
|
|
15
|
+
|
|
16
|
+
* Database initialization
|
|
17
|
+
|
|
18
|
+
* How to run the test suite
|
|
19
|
+
|
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
|
21
|
+
|
|
22
|
+
* Deployment instructions
|
|
23
|
+
|
|
24
|
+
* ...
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
Please feel free to use a different markup language if you do not plan to run
|
|
28
|
+
<tt>rake doc:app</tt>.
|
data/test/dummy/Rakefile
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
|
2
|
+
// listed below.
|
|
3
|
+
//
|
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
|
5
|
+
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
|
6
|
+
//
|
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
|
8
|
+
// compiled file.
|
|
9
|
+
//
|
|
10
|
+
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
|
11
|
+
// about supported directives.
|
|
12
|
+
//
|
|
13
|
+
//= require_tree .
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
|
3
|
+
* listed below.
|
|
4
|
+
*
|
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
|
7
|
+
*
|
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any styles
|
|
10
|
+
* defined in the other CSS/SCSS files in this directory. It is generally better to create a new
|
|
11
|
+
* file per style scope.
|
|
12
|
+
*
|
|
13
|
+
*= require_tree .
|
|
14
|
+
*= require_self
|
|
15
|
+
*/
|