# frozen_string_literal: true # # Helpful methods HTML5 elements in a form # module CoreHtml5FormHelper # @abstract Render a password field # @todo Combine this with the html5_text_field, the only thing different is the field type def html5_password(model, field, options = {}) classes = options[:classes] || %w[col-sm-12 col-lg-6] value = model.send(field) options[:type] = :password options[:place_holder] ||= mask_value(value) tag_options = html5_text_field_options(model, field, options) content_tag(:div, class: (%w[form-floating form-floating-outline mb-3 col] + classes).join(' ')) do concat(tag(:input, tag_options)) concat(form_label_tag(model, field, value, options)) end end def html5_text_field(model, field, options = {}) classes = options[:classes] || %w[col-sm-12 col-lg-6] value = model.send(field) options[:type] ||= :text options[:value] = value options[:disabled] ||= false tag_options = html5_text_field_options(model, field, options) content_tag(:div, class: (%w[form-floating form-floating-outline mb-3 col] + classes).join(' ')) do concat(tag(:input, tag_options)) concat(html5_label_tag(model, field, value, options)) end end def html5_label_tag(model, field, value, options = {}) # dont do a label if we are in default browser mode return if options[:no_label] return if options[:input_classes].present? && options[:input_classes].include?('browser-default') # or if we have a prompt with now value place_holder = field_placeholder_text(model, field, default: options[:placeholder]) return if place_holder.blank? && value.blank? && options[:prompt].present? error = model.errors[field] key = "ui_form.#{model.class.to_s.underscore}.labels.#{field}" classes = value.nil? && place_holder.blank? ? '' : 'active' classes += error.present? ? ' invalid red-text' : ' valid' options[:class] = classes options[:for] = html5_field_id(model, field, options) options['data-error'] = error.join(', ') if error.present? content_tag(:label, options) do concat(I18n.exists?(key) ? I18n.t(key) : field.to_s.humanize) concat(" #{error.join(', ')}") if error.present? end end def html5_text_field_options(model, field, options) hint_key = "ui_form.#{model.class.to_s.underscore}.hints.#{field}" if I18n.exists?(hint_key) classes = %w[form-control validate tooltipped] options[:data] = { tooltip: I18n.t(hint_key), position: :top } else classes = %w[form-control validate] end classes += options[:input_classes] if options[:input_classes].present? options[:name] = html5_field_name(model, field, options) options[:id] = html5_field_id(model, field, options) place_holder = options[:place_holder] || html5_field_place_holder(model, field) if place_holder.present? classes << 'active' options[:placeholder] = place_holder end classes << 'active' if options[:value].present? options[:class] = classes.uniq options end def html5_field_name(model, field, options = {}) return options[:form_name] if options[:form_name].present? # TODO: Need to handle the other side of the 1:M use case where # the field name needs to end in _ids, not _id. field = "#{field}_id" if model.class.reflect_on_association(field).present? if options[:index].present? if options[:array_name].present? if options[:base_name].present? "#{options[:base_name]}[#{options[:array_name]}[#{options[:index]}][#{field}]]" else "#{options[:array_name]}[#{options[:index]}][#{field}]" end else "#{model.class.to_s.underscore}[#{options[:index]}][#{field}]" end else "#{model.class.to_s.underscore}[#{field}]" end end def html5_field_id(model, field, options = {}) return options[:form_id] if options[:form_id].present? # TODO: Need to handle the other side of the 1:M use case where # the field name needs to end in _ids, not _id. field = "#{field}_id" if model.class.reflect_on_association(field).present? if options[:index].present? if options[:array_name].present? if options[:base_name].present? "#{options[:form_id_prefix]}#{options[:base_name]}_#{options[:array_name]}_#{options[:index]}_#{field}" else "#{options[:form_id_prefix]}#{options[:array_name]}_#{options[:index]}_#{field}" end else "#{options[:form_id_prefix]}#{model.class.to_s.underscore}_#{options[:index]}_#{field}" end else "#{options[:form_id_prefix]}#{model.class.to_s.underscore}_#{field}" end end def html5_field_place_holder(model, field) place_holder_key = "ui_form.#{model.class.to_s.underscore}.placeholders.#{field}" I18n.exists?(place_holder_key) ? I18n.t(place_holder_key) : nil end def html5_checkbox(model, field, options = {}) classes = options[:classes] || %w[col-sm-12 col-lg-6] value = model.send(field) options[:disabled] ||= false properties = { class: 'form-check-input', id: html5_field_id(model, field, options), name: html5_field_name(model, field, options), type: :checkbox, disabled: options[:disabled] } properties[:checked] = true if model.send(field) checkbox_tag = tag(:input, properties) content_tag(:div, class: (%w[form-check mt-4] + classes).join(' ')) do concat(content_tag(:label) do concat(checkbox_tag) concat(html5_checkbox_label_tag(model, field, value, input_classes: classes)) end) end end def html5_checkbox_label_tag(model, field, value, options = {}) # dont do a label if we are in default browser mode return if options[:input_classes].present? && options[:input_classes].include?('browser-default') # or if we have a prompt with now value place_holder = html5_field_place_holder(model, field) return if place_holder.blank? && value.blank? && options[:prompt].present? error = model.errors[field] key = "ui_form.#{model.class.to_s.underscore}.labels.#{field}" classes = value.nil? && place_holder.blank? ? '' : 'active' classes += error.present? ? ' invalid red-text' : ' valid' options[:class] = classes options['data-error'] = error.join(', ') if error.present? content_tag(:span, options) do concat(I18n.exists?(key) ? I18n.t(key) : field.to_s.humanize) end end end