stevedowney/bootstrap-view-helpers

View on GitHub
app/helpers/bootstrap/button_helper.rb

Summary

Maintainability
A
0 mins
Test Coverage
# Helper for producing Twitter Bootstrap buttons OR links that look like buttons.
#
# See:
# * http://twitter.github.io/bootstrap/base-css.html#buttons
# * http://twitter.github.io/bootstrap/components.html#buttonGroups
# * http://twitter.github.io/bootstrap/components.html#buttonDropdowns
# @example Button / Link
#
#   # button
#   button('Default')
#
#   # add url option to make <a> styled as button
#   button('Home', url: '/')
#
#   # a button styled as a link
#   button('Home', :link)
#
#   # give it a type; see BUTTON_TYPES
#   button('Info', :info)
#
#   # give it a size (see BUTTON_SIZES)
#   button('Small', :small)
#
#   # size, type, additional class and additional html attributes
#   button('Warning', :warning, :large, id: 'warn-id', class: 'more-class', my_key: 'my_value')
#
# @example Button Group
#   <%= button_group do %>
#     <%= button("Left", url: "/left") %>
#     <%= button("Right", id: 'right') %>
#   <% end %>
#
# @example Button Toolbar
#    <%= button_toolbar do %>
#      <%= button('Single Button', url: '/single') %>
#      <%= button_group do %>
#        <%= button('Group Button 1') %>
#        <%= button('Group Button 2') %>
#      <% end %>
#      <%= button('Another Single') %>
#   <% end %>
module Bootstrap::ButtonHelper
  InvalidButtonModifierError = Class.new(StandardError)

  BUTTON_TYPES = %w(default primary info success warning danger inverse link)
  BUTTON_SIZES = %w(default large small mini)
  BUTTON_OTHERS = %w(block)
  
  BUTTON_ALL = BUTTON_TYPES + BUTTON_SIZES + BUTTON_OTHERS
  
  # Returns <button> or <a> styled as Bootstrap button
  #
  # @overload button(text, options={})
  #   Default button
  #   @param [String] text text of button
  #   @param [Hash] options All keys except +:url+ become html attributes for the generated tag
  #   @option options [String] :url if present, return a <a> styled as a button
  # @overload button(text, type, options={})
  #   Button of type _type_
  #   @param [String] text text of button
  #   @param [String, Symbol] type type of button; see {Bootstrap::ButtonHelper::BUTTON_TYPES}
  #   @param [Hash] options All keys except +:url+ become html attributes for the generated tag
  #   @option options [String] :url if present, return a <a> styled as a button
  # @overload button(text, size, options={})
  #   Button of size _size_
  #   @param [String] text text of button
  #   @param [String, Symbol] size size of button; see {Bootstrap::ButtonHelper::BUTTON_SIZES}
  #   @param [Hash] options All keys except +:url+ become html attributes for the generated tag
  #   @option options [String] :url if present, return a <a> styled as a button
  # @overload button(text, type, size, options={})
  #   Button of type _type_, size _size_
  #   @param [String] text text of button
  #   @param [String, Symbol] type type of button; see {Bootstrap::ButtonHelper::BUTTON_TYPES}
  #   @param [String, Symbol] size size of button; see {Bootstrap::ButtonHelper::BUTTON_SIZES}
  #   @param [Hash] options All keys except +:url+ become html attributes for the generated tag
  #   @option options [String] :url if present, return a <a> styled as a button
  # @return [String] Html for a <button> (or <a> if +url+ option passed in)
  def button(*args)
    text = args.shift
    options = canonicalize_options(args.extract_options!)
    href = options.delete(:url)
    options = add_button_classes(options, args)

    if href.present?
      link_to(text, href, options)
    else
      content_tag(:button, text, options)
    end
  end
    
  # Returns a Bootstrap button toolbar
  #
  # @param [Hash] options will be come html attributes of generated <div>
  # @yield block usually consists of calls to {Bootstrap::ButtonHelper#button} or {Bootstrap::ButtonHelper#button_group}
  # @yieldreturn [String] html for contents of toolbar
  #
  # @return [String] html for button toolbar
  def button_toolbar(options={})
    options = canonicalize_options(options)
    options = ensure_class(options, 'btn-toolbar')
    
    content_tag(:div, options) do
      yield
    end
  end
  
  # Returns a Bootstrap button group
  #
  # @param [Hash] options will be come html attributes of generated <div>
  # @yield block usually consists of calls to {Bootstrap::ButtonHelper#button}
  # @yieldreturn [String] html for contents of group
  #
  # @return [String] html for button group
  def button_group(options={})
    options = canonicalize_options(options)
    options = ensure_class(options, 'btn-group')
    
    content_tag(:div, options) do
      yield
    end
  end
  
  # Ensures each entry in _types_and_sizes_ is a valid button modifier.
  #
  # @raise InvalidButtonModifierError if one of the args isn't a valid button modifier.
  # @private
  def validate_button_types_and_sizes(types_and_sizes)
    types_and_sizes.each { |e| raise(InvalidButtonModifierError, e.inspect) unless BUTTON_ALL.include?(e.to_s) }
  end

  private
  
  def add_button_classes(options, button_types_and_sizes)
    validate_button_types_and_sizes(button_types_and_sizes)
    classes = ['btn'] + button_types_and_sizes.map { |e| "btn-#{e}" }
    ensure_class(options, classes)
  end
  
end