require 'railsstrap/core_ext/rails/base_helper' require 'railsstrap/helpers/icon_helper' module Railsstrap module Form module BaseHelper include Railsstrap::Rails::BaseHelper include Railsstrap::Helpers private def base_field(method, field_type, options = {}, &block) errors = (object.errors[method] if object) || {} label = label_for method, errors, field_type, options field = field_container(options) do field_tags errors, field_type, options, &block end label_and_field = safe_join [label, field].compact label_and_field_container label_and_field, field_type, errors end def field_container(options = {}, &block) offset = options.delete :offset if horizontal_form? klass = [('col-sm-offset-3' if offset), 'col-sm-9'] content_tag :div, class: klass.compact.join(' '), &block else yield end end def field_tags(errors, field_type, options = {}, &block) prefix, suffix = options.delete(:prefix), options.delete(:suffix) help_text = options.delete(:help) field = @template.capture(&block) tags = [field_in_group(field, prefix, suffix)] if show_error_icon?(field_type, errors, suffix) && !basic_form? tags << error_icon_tag end if errors.any? && show_error_help? tags << help_tag(errors.to_sentence) elsif help_text tags << help_tag(help_text) end safe_join tags end def field_in_group(field, prefix, suffix) input_group_container(prefix || suffix) do safe_join [input_addon(prefix), field, input_addon(suffix)].compact end end def input_addon(addon) content_tag :span, addon, class: 'input-group-addon' if addon end def input_group_container(has_addons, &block) if has_addons content_tag :div, class: 'input-group', &block else yield end end def label_and_field_container(label_and_field, field_type, errors = {}) klass = ['form-group'] klass << 'has-error' if errors.any? klass << 'has-feedback' if show_error_icon?(field_type, errors) content_tag :div, label_and_field, class: klass.join(' ') end def show_error_icon?(field_type, errors, suffix = nil) no_icon = %w(checkbox number_field radio_button select legend) hide = no_icon.include?(field_type.to_s) errors.any? && @options.fetch(:errors, {}).fetch(:icons, true) && !hide && suffix.nil? end def error_icon_tag icon :remove, class: 'form-control-feedback' end def help_tag(help_text) klass = ['help-block', 'text-left'] klass << 'sr-only' if inline_form? content_tag :span, help_text, class: klass.join(' ') end # Rails wraps the label in
in case of # error, which messes up the error icon in Bootstrap basic forms unless # the icon is appended to the label itself, rather than at the end. def label_for(method, errors, field_type, options) if options.delete(:use_label) { true } args = [method, options.delete(:label), label_options(errors)] label(*args.compact).tap do |label| error_icon = show_error_icon? field_type, errors, options[:suffix] if (index = label =~ %r{
$}) && error_icon && basic_form? label.insert index, error_icon_tag end end end end def label_options(errors = {}) klass = [] klass << 'sr-only' if inline_form? klass << 'col-sm-3' if horizontal_form? klass << 'control-label' if horizontal_form? klass << 'control-label' if basic_form? && errors.any? {class: klass.join(' ')} if klass.any? end # Rails adds
which messes up # Bootstrap inline form unless the label is inserted within # the div itself. def label_and_field(container_class, method, options = {}, &block) label = safe_join [' ' , options.delete(:label)] label_options = options.delete(:label_options) || {} label_and_field = @template.capture(&block) if index = label_and_field =~ %r{
$} label_and_field.insert index, label else label_and_field.concat label end content_tag :div, class: container_class do content_tag :label, label_and_field, label_options end end def show_error_help? @options.fetch(:errors, {}).fetch(:messages, :inline).to_s == 'inline' end def inline_form? ['inline', 'navbar'].include? @options[:layout].to_s end def horizontal_form? @options[:layout].to_s == 'horizontal' end def basic_form? !inline_form? && !horizontal_form? end end end end