lib/lipstick/helpers/form_helper.rb in aaf-lipstick-1.1.0 vs lib/lipstick/helpers/form_helper.rb in aaf-lipstick-2.0.0
- old
+ new
@@ -1,197 +1,178 @@
+# frozen_string_literal: true
module Lipstick
module Helpers
module FormHelper
include ActionView::Helpers::FormTagHelper
- def field_block(html_opts = {}, &block)
- if flag_enabled?(:inside_inline_form_tag)
- html_opts[:class] = "#{html_opts[:class]} inline".strip
+ def field_block(html_opts = {})
+ add_css_class(html_opts, 'form-group')
+ content_tag('div', html_opts) { yield }
+ end
+
+ def radio_button_tag(name, value, checked = false, options = {})
+ content_tag('div', class: 'radio') do
+ content_tag('label') do
+ concat(super)
+ concat(capture { yield })
+ end
end
+ end
- html_opts[:class] = "#{html_opts[:class]} field".strip
- content_tag('div', html_opts, &block)
+ def check_box_tag(*)
+ content_tag('div', class: 'checkbox') do
+ content_tag('label') do
+ concat(super)
+ concat(capture { yield })
+ end
+ end
end
- alias_method :orig_form_tag, :form_tag
+ alias orig_form_tag form_tag
- def form_tag(form_opts, html_opts = {}, &block)
- html_opts[:class] = "#{html_opts[:class]} ui form".strip
- orig_form_tag(form_opts, html_opts, &block)
+ def inline_form_tag(url_for_options = {}, options = {})
+ add_css_class(options, 'form-inline')
+ form_tag(url_for_options, options) { yield }
end
- def inline_form_tag(form_opts, html_opts = {}, &block)
- with_flag_enabled(:inside_inline_form_tag) do
- html_opts[:class] = "#{html_opts[:class]} ui form inline-form".strip
- orig_form_tag(form_opts, html_opts, &block)
+ def search_form_tag(filter, url: nil)
+ form_tag(url, method: :get) do
+ field_block { search_form_input_tag(filter) }
end
end
+ def search_form_input_tag(filter)
+ content_tag('div', class: 'row') do
+ content_tag('div', grouped_search_field(filter), class: 'col-lg-12')
+ end
+ end
+
+ def search_filter_text_field(filter)
+ orig_text_field_tag(:filter, filter,
+ placeholder: 'Search within these entries',
+ autocomplete: 'off',
+ class: 'form-control')
+ end
+
+ def search_button
+ button_tag(type: 'submit') do
+ concat(icon_tag('search'))
+ concat(' Search')
+ end
+ end
+
+ def grouped_search_field(filter)
+ content_tag('div', class: 'input-group') do
+ concat(search_filter_text_field(filter))
+ concat(content_tag('span', search_button, class: 'input-group-btn'))
+ end
+ end
+
def hidden_fields(&block)
content_tag('div', style: 'display: none;', &block)
end
- def text_field_tag(*args)
- content_tag('div', class: 'ui input') { super }
+ alias orig_text_field_tag text_field_tag
+
+ def text_field_tag(name, value = nil, opts = {})
+ add_css_class(opts, 'form-control')
+ super
end
- def field_help_text(text)
- icon_tag('field-help-text blue help', 'data-content' => text)
+ def text_area_tag(name, content = nil, opts = {})
+ add_css_class(opts, 'form-control')
+ super
end
- def button_tag(content_or_options = nil, options = nil, &block)
- add_class = ->(m) { m.dup.merge(class: "#{m[:class]} ui button".strip) }
+ def date_field_tag(name, value = nil, **opts)
+ opts[:class] = "#{opts[:class]} date-picker".strip
+ text_field_tag(name, value, opts)
+ end
+ def select_tag(name, option_tags = nil, **opts)
+ add_css_class(opts, 'form-control')
+ super
+ end
+
+ def button_tag(content_or_options = nil, options = nil, &block)
if content_or_options.is_a?(Hash)
- super(add_class.call(content_or_options), &block)
+ content_or_options[:class] ||= 'btn-default'
+ add_css_class(content_or_options, 'btn')
+ super
else
- super(content_or_options, add_class.call(options || {}), &block)
+ options ||= {}
+ options[:class] ||= 'btn-default'
+ add_css_class(options, 'btn')
+ super(content_or_options, options, &block)
end
end
def delete_button_tag(url, text: true, **opts)
- css_class = 'ui tiny red icon delete button floating dropdown'
- content_tag('div', class: "#{css_class} #{opts[:class]}".strip) do
- concat(icon_tag('trash'))
- action = text && text.is_a?(String) ? text : 'Delete'
- concat(action) if text
- confirm = button_link_to(url, method: :delete, class: 'small') do
- "Confirm #{action}"
- end
- concat(content_tag('div', confirm, class: 'menu'))
- end
- end
+ action = text && text.is_a?(String) ? text : 'Delete'
- def error_messages_tag
- content_tag('div', '', class: 'ui error message')
- end
-
- def radio_button_tag(name, value, checked = false, options = {}, &block)
- field_block do
- content_tag('div', class: 'ui radio checkbox') do
- concat(super)
- concat(capture(&block))
- end
+ content_tag('div', class: 'btn-group') do
+ concat(delete_dropdown_opener(text && action, opts))
+ concat(confirm_delete_dropdown(url, action))
end
end
def form_for(obj, opts = {}, &block)
- opts[:builder] = SemanticFormBuilder
- opts[:html] ||= {}
- opts[:html][:class] = "#{opts[:html][:class]} ui form".strip
+ opts[:builder] = BootstrapFormBuilder
super(obj, opts, &block)
end
- def radio_button_block(&block)
- content_tag('div', class: 'grouped fields', &block)
- end
-
# Generates the wrapping code for validating a form. The selector is
# passed to jQuery, and must uniquely select the form being validated.
# `sym` is the object name when using a `form_for` helper to generate the
# form.
#
# e.g.
- # <%= validate_form('#new-test-object', :test_object) do -%>
- # <%= validate_field(:name, ...) %> Validate the test_object[name] field
- # <%- end -%>
- def validate_form(selector, sym = nil, &block)
- content_tag('script', type: 'text/javascript') do
- jquery_callback(validation_body(selector, sym, &block)).html_safe
- end
- end
+ # <%=
+ # validate_form('#new-test-object', :test_object) do |v|
+ # v.validate_field(:name, ...) # Validate the test_object[name] field
+ # end
+ # %>
+ def validate_form(selector, sym = nil)
+ opts = {
+ type: 'application/vnd.aaf.lipstick.validations+json',
+ 'data-target': selector,
+ class: 'lipstick-validations'
+ }
- # Generates a validator for a field. `opts` is a Hash containing the
- # `type` and `prompt` for each desired validation per Semantic UI:
- # http://semantic-ui.com/modules/form.html
- #
- # e.g.
- # <%= validate_field(:email, email: 'Enter a valid email address') %>
- # <%= validate_field(:password, :'length[6]' => '6 characters minimum') %>
- # <%= validate_field(:multiple, empty: 'Not empty', url: 'Must be URL') %>
- def validate_field(name, opts)
- format('validations[%{name}] = ' \
- '(function(v) { %{inner} })' \
- '($.extend({rules: []}, validations[%{name}]));',
- name: name.to_json,
- inner: validation_for_field(name, opts)).html_safe
- end
-
- # Automatically generates validators for fields based on certain supported
- # validators from ActiveModel::Validations. The model must include the
- # Lipstick::AutoValidation module.
- #
- # class MyModel < ActiveRecord::Base
- # include Lipstick::AutoValidation
- #
- # validates :name, presence: true
- # validates :description, length: 1..255
- # end
- #
- # <%= auto_validate(@object, :name, :description) %>
- def auto_validate(obj, *fields)
- unless obj.class.respond_to?(:lipstick_auto_validators)
- fail("#{obj.class.name} does not include Lipstick::AutoValidation")
+ content_tag('script', opts) do
+ validation_json(sym) { |v| yield v }.html_safe
end
-
- validators = obj.class.lipstick_auto_validators
- capture do
- validators.slice(*fields).each do |name, opts|
- concat validate_field(name, opts)
- end
- end
end
private
- def validation_body(selector, sym, &block)
- 'var validations = {};' +
- validation_name_mapping_function(sym) +
- capture(&block) +
- validation_install(selector)
+ def validation_json(sym)
+ v = FormValidationBuilder.new(sym)
+ yield v
+ JSON.generate(v.to_h)
end
- # When we're using form_for, we need to map ObjectType#name to a field
- # named like: 'object_type[name]'
- # Otherwise, we just use the name directly.
- def validation_name_mapping_function(sym)
- if sym.nil?
- 'var map_name = function(n) { return n; };'
- else
- 'var map_name = function(n) { ' \
- "return #{sym.to_json} + '[' + n + ']';" \
- '};'
- end
- end
+ def delete_dropdown_opener(label, **opts)
+ opts = { 'aria-expanded': 'false', 'data-toggle': 'dropdown',
+ type: 'button', 'aria-haspopup': 'true' }.merge(opts)
- def validation_install(selector)
- format('$(%s).form(validations, { keyboardShortcuts: false });',
- selector.to_json)
- end
+ add_css_class(opts, 'btn-small btn-danger dropdown-toggle')
- def jquery_callback(body)
- format('jQuery(function($){%s});', body)
+ button_tag(opts) do
+ concat(icon_tag('trash'))
+ concat(' ')
+ concat(label)
+ end
end
- def validation_for_field(name, opts)
- rules = opts.map { |t, m| { type: t, prompt: m } }
- "v.rules = v.rules.concat(#{rules.to_json});" \
- "v.identifier = map_name(#{name.to_json});" \
- 'return v;'
+ def confirm_delete_dropdown(url, action)
+ link = link_to("Confirm #{action}", url, class: 'confirm-delete')
+ item = content_tag('li', link)
+ content_tag('ul', item, class: 'dropdown-menu')
end
- def with_flag_enabled(flag)
- old = Thread.current[flag]
- begin
- Thread.current[flag] = true
- yield
- ensure
- Thread.current[flag] = old
- end
- end
-
- def flag_enabled?(flag)
- Thread.current[flag]
+ def add_css_class(opts, class_name)
+ opts[:class] = "#{opts[:class]} #{class_name}".strip
end
end
end
end