#
# Changes:
# 2012-06-05 allard: Added inline help messages, set default check_box label if none is set
#
# This file goes in lib/
# Usage:
# <%= bootstrap_form_for @calendar_entry do |f| %>
# <%= content_tag :legend, (locals[:title] || 'Edit Calendar Entry') %>
# <%= f.text_field :name, :class => 'span3' %>
# <%= f.text_area :description, :class => 'span3' %>
# <%= f.jquery_datetime_select :start_time, :class => 'span3' %>
# <%= f.jquery_datetime_select :end_time, :class => 'span3' %>
# <%= f.check_box :all_day, { :label => 'Agree?, :description => 'left hand label'' } %>
# <%= f.text_field :tag_string, :label_options => { :text => 'Tags' }, :class => 'span3' do %>
#
Use commas to separate tags.
# <% end %>
#
# <%= f.submit 'Save', :class => 'btn btn-primary' %>
# <%= link_to 'Cancel', calendar_entries_path, :class => 'btn' %>
#
# <% end %>
#
# Inline help:
# <%= f.text_field :name, :help => "inline help message"
#
module BootstrapFormBuilder
module FormHelper
[:form_for, :fields_for].each do |method|
module_eval do
define_method "bootstrap_#{method}" do |record, *args, &block|
# add the TwitterBootstrap builder to the options
options = args.extract_options!
options[:builder] = BootstrapFormBuilder::FormBuilder
if method == :form_for
options[:html] ||= {}
options[:html][:class] ||= 'form-horizontal'
end
# call the original method with our overridden options
send method, record, *(args << options), &block
end
end
end
end
class FormBuilder < ActionView::Helpers::FormBuilder
include FormHelper
include ActionView::Helpers::TagHelper
def get_error_text(object, field, options)
if object.nil? || options[:hide_errors]
""
else
errors = object.errors[field.to_sym]
if errors.empty? then "" else errors.first end
end
end
def get_object_id(field, options)
object = @template.instance_variable_get("@#{@object_name}")
return options[:id] || object.class.name.underscore + '_' + field.to_s
end
def get_label(field, options)
labelOptions = {:class => 'control-label'}.merge(options[:label_options] || {})
text = options[:label] || labelOptions[:text] || nil
options.delete(:label)
options.delete(:label_options)
labelTag = label(field, text, labelOptions)
end
def inline_help(options)
return "" unless options[:help]
text = options[:help]
options.delete(:help)
content_tag :span, text, :class => 'help-inline'
end
def submit(value, options = {}, *args)
super(value, {:class => "btn btn-primary"}.merge(options), *args)
end
def jquery_date_select(field, options = {})
id = get_object_id(field, options)
date =
if options['start_date']
options['start_date']
elsif object.nil?
Date.now
else
object.send(field.to_sym)
end
date_picker_script = ""
return basic_date_select(field, options.merge(javascript: date_picker_script))
end
def basic_date_select(field, options = {})
placeholder_text = options[:placeholder_text] || ''
id = get_object_id(field, options)
errorText = get_error_text(object, field, options)
wrapperClass = 'control-group' + (errorText.empty? ? '' : ' error')
errorSpan = if errorText.empty? then "" else "#{errorText}" end
labelTag = get_label(field, options)
date =
if options[:start_date]
options[:start_date]
elsif object.nil?
Date.now.utc
else
object.send(field.to_sym)
end
javascript = options[:javascript] ||
"
"
("" +
labelTag +
"
" +
super_text_field(field, {
:id => id, :placeholder => placeholder_text, :value => date.to_s,
:class => options[:class]
}.merge(options[:text_field] || {})) +
errorSpan +
javascript +
"
" +
"
").html_safe
end
def jquery_datetime_select(field, options = {})
id = get_object_id(field, options)
date_time =
if options['start_time']
options['start_time']
elsif object.nil?
DateTime.now.utc
else
object.send(field.to_sym)
end
datetime_picker_script = ""
return basic_datetime_select(field, options.merge(javascript: datetime_picker_script))
end
def basic_datetime_select(field, options = {})
placeholder_text = options[:placeholder_text] || ''
id = get_object_id(field, options)
errorText = get_error_text(object, field, options)
wrapperClass = 'control-group' + (errorText.empty? ? '' : ' error')
errorSpan = if errorText.empty? then "" else "#{errorText}" end
labelTag = get_label(field, options)
date_time =
if options[:start_time]
options[:start_time]
elsif object.nil?
DateTime.now.utc
else
object.send(field.to_sym)
end
javascript = options[:javascript] ||
"
"
("" +
labelTag +
"
" +
super_text_field(field, {
:id => id, :placeholder => placeholder_text, :value => date_time.to_s,
:class => options[:class]
}.merge(options[:text_field] || {})) +
errorSpan +
javascript +
"
" +
"
").html_safe
end
basic_helpers = %w{text_field text_area select email_field password_field number_field}
multipart_helpers = %w{date_select datetime_select}
trailing_label_helpers = %w{check_box}
basic_helpers.each do |name|
# First alias old method
class_eval("alias super_#{name.to_s} #{name}")
define_method(name) do |field, *args, &help_block|
options = args.last.is_a?(Hash) ? args.last : {}
object = @template.instance_variable_get("@#{@object_name}")
labelTag = get_label(field, options)
errorText = get_error_text(object, field, options)
wrapperClass = 'control-group' + (errorText.empty? ? '' : ' error')
errorSpan = if errorText.empty? then "" else "#{errorText}" end
("" +
labelTag +
"
" +
super(field, *args) +
inline_help(options) +
errorSpan +
(help_block ? @template.capture(&help_block) : "") +
"
" +
"
"
).html_safe
end
end
multipart_helpers.each do |name|
define_method(name) do |field, *args, &help_block|
options = args.last.is_a?(Hash) ? args.last : {}
object = @template.instance_variable_get("@#{@object_name}")
labelTag = get_label(field, options)
options[:class] = 'inline ' + options[:class] if options[:class]
errorText = get_error_text(object, field, options)
wrapperClass = 'control-group' + (errorText.empty? ? '' : ' error')
errorSpan = if errorText.empty? then "" else "#{errorText}" end
("" +
labelTag +
"
" +
super(field, *args) +
inline_help(options) +
errorSpan +
(help_block ? @template.capture(&help_block) : "") +
"
" +
"
"
).html_safe
end
end
trailing_label_helpers.each do |name|
# First alias old method
class_eval("alias super_#{name.to_s} #{name}")
define_method(name) do |field, *args, &help_block|
options = args.first.is_a?(Hash) ? args.first : {}
object = @template.instance_variable_get("@#{@object_name}")
labelOptions = {:class => 'checkbox'}.merge(options[:label_options] || {})
labelOptions["for"] = "#{@object_name}_#{field}"
label_text = options[:label] || labelOptions[:text] || field.to_s.capitalize
options.delete(:label)
options.delete(:label_options)
errorText = get_error_text(object, field, options)
wrapperClass = 'control-group' + (errorText.empty? ? '' : ' error')
errorSpan = if errorText.empty? then "" else "#{errorText}" end
description = if options[:description] then %{} else "" end
options.delete(:description)
("" +
description +
"
" +
tag(:label, labelOptions, true) +
super(field, *args) +
inline_help(options) +
errorSpan +
(help_block ? @template.capture(&help_block) : "") +
label_text +
"" +
"
" +
"
"
).html_safe
end
end
end
end