Multiple custom Rails Form Helper and SimpleForm inputs in one Rails engine
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
app
lib
.gitignore
Gemfile
MIT-LICENSE
README.md
effective_form_inputs.gemspec

README.md

Effective Form Inputs

Multiple custom Rails Form Helper and SimpleForm inputs in one Rails engine.

This gem contains numerous custom form inputs along with their Javascript/CSS assets.

Each included form input is available to both the default Rails Form Helper and SimpleForm.

Rails 3.2.x and 4.x

Getting Started

Add to your Gemfile:

gem 'effective_form_inputs'

Run the bundle command to install it:

bundle install

Install All Form Inputs

This gem packages the javascript/css assets for numerous form inputs.

The assets for these inputs may be included all at once or individually.

To install all available inputs, add the following to your application.js:

//= require effective_form_inputs

and add the following to your application.css:

*= require effective_form_inputs

All of the included form inputs will now be available with no additional installation tasks.

Options Passing to JavaScript

All :input_js => options passed to any effective_form_input will be used to initialize the Javascript library

For example:

= form_for @user do |f|
  = f.effective_date_time_picker :updated_at, :input_js => {:format => 'dddd, MMMM Do YYYY', :showTodayButton => true}

or

= simple_form_for @user do |f|
  = f.input :updated_at, :as => :effective_date_time_picker, :input_js => {:format => 'dddd, MMMM Do YYYY', :showTodayButton => true}

will result in the following call to the Javascript library:

$('input.effective_date_time_picker').datetimepicker
  format: 'dddd, MMMM Do YYYY',
  showTodayButton: true

Any options passed in this way will be used to initialize the underlying javascript libraries.

Effective CKEditor Text Area

This custom form input replaces a standard textarea with a CKEditor html rich text area.

It is based on the widely used:

CKEditor (http://ckeditor.com/)

and built ontop of

effective_ckeditor (https://github.com/code-and-effect/effective_ckeditor/)

Installation

You must first install effective_ckeditor

gem 'effective_ckeditor'

Depending on how often you're going to display this form input, you now have two options:

  • You can do nothing, and when this form input is displayed it will use javascript to load the ckeditor .js and .css file on $(ready). It will make 2 additional requests, slowing down your page load by a moment.

  • Or, when you intend to use the input quite a bit, it's faster to add the effective_ckeditor resources to the asset pipeline. However, it will increase the asset payload by around 200kb.

To add it to the asset pipeline, put the following to your application.js:

//= require effective_ckeditor

and in your application.css, add:

*= require effective_ckeditor

There are no additional effective_ckeditor installation steps.

If you've already installed the 'All Form Inputs' assets (see above), there are no additional installation steps.

To install this form input individually, add the following to your application.js:

//= require effective_ckeditor_text_area/input

Usage

As a Rails Form Helper input:

= form_for @post do |f|
  = f.effective_ckeditor_text_area :body

As a SimpleForm input:

= simple_form_for @post do |f|
  = f.input :body, :as => :effective_ckeditor_text_area

Options

You can specify the toolbar as 'full' or 'simple':

The full toolbar includes Image, oEmbed and Assets, wheras simple does not.

= f.input :body, :as => :effective_ckeditor_text_area, :toolbar => 'full'
= f.input :body, :as => :effective_ckeditor_text_area, :toolbar => 'simple'

You can specify the height and width:

= f.input :body, :as => :effective_ckeditor_text_area, :height => '400px;', :width => '200px;'

And you can specify a contentsCss stylesheet:

By default, this loads the asset_path('application.css') file, you can also specify :bootstrap, false, a string url, or an array of urls.

When :bootstrap, this loads a CDN hosted bootstrap 3.3.7 stylesheet.

= f.input :body, :as => :effective_ckeditor_text_area, :contentsCss => :bootstrap

Effective Date Time Picker

This custom form input is based on the following awesome project:

Bootstrap 3 Datepicker (https://github.com/Eonasdan/bootstrap-datetimepicker)

Installation

If you've already installed the 'All Form Inputs' assets (see above), there are no additional installation steps.

To install this form input individually, add the following to your application.js:

//= require effective_date_time_picker/input

and add the following to your application.css:

*= require effective_date_time_picker/input

Usage

As a Rails Form Helper input:

= form_for @user do |f|
  = f.effective_date_time_picker :updated_at

As a SimpleForm input:

= simple_form_for @user do |f|
  = f.input :updated_at, :as => :effective_date_time_picker

As a SimpleForm input without the input group (calendar glyphicon)

= simple_form_for @user do |f|
  = f.input :updated_at, :as => :effective_date_time_picker, :input_group => false

Options

The default :input_js => options used to initialize this form input are as follows:

:input_js => {:format => 'YYYY-MM-DD h:mm A', :sideBySide => true}

For a full list of options, please refer to:

http://eonasdan.github.io/bootstrap-datetimepicker/Options/

Set Date

Use the following JavaScript to programatically set the date:

$('#start_at').data('DateTimePicker').date('2016-05-08')

Disabled Dates

Provide a String, Date, or Range to set the disabled dates.

:input_js => { disabledDates: '2020-01-01' }
:input_js => { disabledDates: Time.zone.now }
:input_js => { disabledDates: Time.zone.now.beginning_of_month..Time.zone.now.end_of_month }
:input_js => { disabledDates: [Time.zone.now, Time.zone.now + 1.day] }

Linked Dates

By default, when two matching effective date time picker inputs named start_* and end_* are present on the same form, they will become linked.

The end date selector will have its date <= start_date disabled.

To disable this behaviour, call with date_linked: false.

  = f.input :end_at, :as => :effective_date_time_picker, :date_linked => false

Events

The date picker library doesn't trigger a regular change. Instead you must watch for the dp.change event.

More info is available here:

http://eonasdan.github.io/bootstrap-datetimepicker/Events/

Effective Date Picker

This custom form input is based on the following awesome project:

Bootstrap 3 Datepicker (https://github.com/Eonasdan/bootstrap-datetimepicker)

Installation

If you've already installed the 'All Form Inputs' assets (see above), there are no additional installation steps.

To install this form input individually, add the following to your application.js:

//= require effective_date_picker/input

and add the following to your application.css:

*= require effective_date_picker/input

Usage

As a Rails Form Helper input:

= form_for @user do |f|
  = f.effective_date_picker :started_on

As a SimpleForm input:

= simple_form_for @user do |f|
  = f.input :started_on, :as => :effective_date_picker

As a SimpleForm input without the input group (calendar glyphicon)

= simple_form_for @user do |f|
  = f.input :updated_at, :as => :effective_date_picker, :input_group => false

Options

The default :input_js => options used to initialize this form input are as follows:

:input_js => {:format => 'YYYY-MM-DD'}

For more options, please see Effective Date Time Picker above

Effective Email

This custom form input makes sure the input is an email address.

Installation

If you've already installed the 'All Form Inputs' assets (see above), there are no additional installation steps.

To install this form input individually, add the following to your application.js:

//= require effective_email/input

Usage

As a Rails Form Helper input:

= form_for @user do |f|
  = f.effective_email :email

As a SimpleForm input:

= simple_form_for @user do |f|
  = f.input :email, :as => :effective_email

As a SimpleForm input without the input group (envelope glyphicon)

= simple_form_for @user do |f|
  = f.input :email, :as => :effective_email, :input_group => false

You should add a server side validation to enforce the format:

validates :email, format: { with: /\A.+@.+\..+\Z/ }
validates :email, effective_email: true   # Enforces same format as above

Options

There are no javascript options for this input.

Effective Panel Select

A totally new way to do grouped collection selects.

Looks like a select field, but when expanded, the usual popup is replaced with a slidedown tabbed panel.

Installation

If you've already installed the 'All Form Inputs' assets (see above), there are no additional installation steps.

To install this form input individually, add the following to your application.js:

//= require effective_panel_select/input

and add the following to your application.css:

*= require effective_panel_select/input

Usage

As a Rails form helper input:

= form_for @user do |f|
  = f.effective_panel_select :category, categories_collection

and as a SimpleForm input:

= simple_form_for @user do |f|
  = f.input :category, as: :effective_panel_select, collection: categories_collection

By default, the left sidebar uses the .nav-stacked class. You can customize this by passing the sidebar_class option to the helper input:

= f.input :category, as: :effective_panel_select, collection: categories_collection, sidebar_class: 'your-custom-class'

Collection

The collection is the same as a grouped select collection:

collection: {'Active' => Post.active, 'Past' => Post.past}
collection: {'Active' => [['Post A', 1], ['Post B', 2]], 'Past' => [['Post C', 3], ['Post D', 4]]}

Each group, 'Active' and 'Past', will have its own tab. And its options selectable inside it.

Options

The default input_js: options used to initialize this form input are as follows:

{
  placeholder: 'Please choose',
  invade: '.row',
  collapseOnSelect: true,  # Close the panel when an item is selected
  resetOnCollapse: true,   # Reset the panel to its selected value when collapsed
  keepFetched: false       # Keep fetched pages instead of clearing them from the DOM on reset
  showCount: false         # Show number of categories in each group on the tab pane
}

and there are also options that control the collection behaviour:

{
  label_method: :to_s,
  value_method: :to_s,
  group_label_method: :first,
  group_method: :second,
  option_value_method: :first,
  option_key_method: :second
}

AJAX

Initialize the input with ajax options to display inline each resource's show page.

HTML is fetched from the server using $.load.

Initialize your input as follows:

= f.input :category_id, as: :effective_panel_select, collection: categories_collection,
  input_js: { ajax: { url: category_path(':id') } }

Here the url should be /categories/:id. The string :id (including the :) will be replaced by the selected value.

A controller action to handle this ajax request looks like:

def show
  @category = Category.find(params[:id])

  # An effective panel select GET request will have effective_panel_select: true
  if params[:effective_panel_select]
    render layout: false
  end
end

Or, you can render the normal show page, with layout, and use $.load target.

= f.input :category_id, as: :effective_panel_select, collection: categories_collection,
  input_js: { ajax: { url: category_path(':id'), target: '#category' } }

By default, any fetched pages are remove() from the DOM when the panel is reset (on collapse).

You can change this behaviour with resetOnCollapse and keepFetched.

Invade

By default, when expanded, the panel will invade -- that is detach() and attach() itself -- to its closest $('.row').

The invaded parent DOM node has its children hidden, and just the panel is displayed.

Disable this behaviour by passing invade: false or tweak it with a different selector invade: '.container'.

Programatic access

An event is fired when the panel's value changes:

$(document).on 'change', '.effective-panel-select', (event) ->
  console.log $(event.currentTarget).effectivePanelSelect('val')

and you can manually do the following:

$('.effective-panel-select').effectivePanelSelect('toggle')
$('.effective-panel-select').effectivePanelSelect('expand')
$('.effective-panel-select').effectivePanelSelect('collapse')
$('.effective-panel-select').effectivePanelSelect('val')
$('.effective-panel-select').effectivePanelSelect('val', 123)  # setVal
$('.effective-panel-select').effectivePanelSelect('title')
$('.effective-panel-select').effectivePanelSelect('clear')

Effective Price

This custom form input uses no 3rd party jQuery plugins.

It displays a currency formatted value 100.00 but posts the "price as integer" value of 10000 to the server.

Think about this value as "the number of cents".

Installation

If you've already installed the 'All Form Inputs' assets (see above), there are no additional installation steps.

To install this form input individually, add the following to your application.js:

//= require effective_price/input

Usage

As a Rails Form Helper input:

= form_for @product do |f|
  = f.effective_price :price

As a SimpleForm input:

= simple_form_for @product do |f|
  = f.input :price, :as => :effective_price

As a SimpleForm input without the input group (glyphicon-usd glyphicon)

= simple_form_for @product do |f|
  = f.input :price, :as => :effective_price, :input_group => false

Options

You can pass include_blank: true to allow nil. By default nils are convereted, displayed and submitted as $0.00.

= f.input :price, :as => :effective_price, :include_blank => true

Rails Helper

This input also installs a rails view helper price_to_currency that takes a value like 10000 and displays it as $100.00

Effective Radio Buttons

This custom form input adds image support to the SimpleForm radio buttons. It doesn't really work as a regular rails form helper.

Installation

If you've already installed the 'All Form Inputs' assets (see above), there are no additional installation steps.

To install this form input individually, add the following to your application.css:

*= require effective_radio_buttons/input

There is no javascript.

Bootstrap button group

Pass buttons: true to the input options to render as a bootstrap button group.

As a SimpleForm input:

= simple_form_for @user do |f|
  = f.input :breakfast,
    :as => :effective_radio_buttons,
    :collection => ['eggs', 'toast', 'bacon'],
    :buttons => true

Inline

Pass inline: true to the input options to render the radio buttons inline.

As a SimpleForm input:

= simple_form_for @user do |f|
  = f.input :breakfast,
    :as => :effective_radio_buttons,
    :collection => ['eggs', 'toast', 'bacon'],
    :inline => true

Images

Pass images: [] as an array of strings with the same length as the collection to render image buttons.

= simple_form_for @user do |f|
  = f.input :breakfast,
    :as => :effective_radio_buttons,
    :collection => ['eggs', 'toast', 'bacon'],
    :images => [asset_path('eggs.png'), asset_path('toast.png'), asset_path('bacon.png')]

Effective Select

This custom form input is based on the following awesome project:

Select2 (https://select2.github.io/)

Installation

If you've already installed the 'All Form Inputs' assets (see above), there are no additional installation steps.

To install this form input individually, add the following to your application.js:

//= require effective_select/input

and add the following to your application.css:

*= require effective_select/input

Usage

As a Rails Form Helper input:

= form_for @user do |f|
  = f.effective_select :category, 10.times.map { |x| "Category #{x}"}
  = f.effective_select :categories, 10.times.map { |x| "Category #{x}"}, :multiple => true
  = f.effective_select :categories, 10.times.map { |x| "Category #{x}"}, :tags => true

and as a SimpleForm input:

= simple_form_for @user do |f|
  = f.input :category, :as => :effective_select, :collection => 10.times.map { |x| "Category #{x}"}
  = f.input :categories, :as => :effective_select, :collection => 10.times.map { |x| "Category #{x}"}, :multiple => true
  = f.input :categories, :as => :effective_select, :collection => 10.times.map { |x| "Category #{x}"}, :tags => true

Modes

The standard mode is a replacement for the default single select box.

Passing :multiple => true will allow multiple selections to be made.

Passing :multiple => true, :tags => true will allow multiple selections to be made, and new value options to be created. This will allow you to both select existing tags and create new tags in the same form control.

Passing :grouped => true will enable optgroup support. When in this mode, the collection should be a Hash of ActiveRecord Relations or Array of Arrays

:collection => {'Active' => Post.active, 'Past' => Post.past}
:collection => {'Active' => [['Post A', 1], ['Post B', 2]], 'Past' => [['Post C', 3], ['Post D', 4]]}

Passing :polymorphic => true will enable polymorphic support. In this mode, an additional 2 hidden input fields are created alongside the select field.

So calling

= f.input :primary_contact, :polymorphic => true, :collection => User.all.to_a + Member.all.to_a

will internally translate the collection into:

[['User 1', 'User_1'], ['User 2', 'User_2'], ['Member 100', 'Member_100']]

and instead of posting to the server with the parameter :primary_contact, it will intead post {:primary_contact_id => 2, :primary_contact_type => 'User'}.

Using both :polymorphic => true and :grouped => true is recommended. In this case the expected collection is as follows:

= f.input :primary_contact, :polymorphic => true, :grouped => true, :collection => {'Users' => User.all, 'Members' => 'Member.all'}

Options

The default :input_js => options used to initialize this form input are as follows:

{
  :theme => 'bootstrap',
  :minimumResultsForSearch => 6,
  :tokenSeparators => [',', ' '],
  :width => 'style',
  :placeholder => 'Please choose',
  :allowClear => !(options[:multiple])  # Only display the Clear 'x' on a single selection box
}

Interesting Available Options

To limit the number of items that can be selected in a multiple select box:

:maximumSelectionLength => 2

To hide the search box entirely:

:minimumResultsForSearch => 'Infinity'

For a full list of options, please refer to: https://select2.github.io/options.html

The following :input_js => options are not part of the standard select2 API, and are custom effective_select functionality only:

To add a css class to the select2 container or dropdown:

:containerClass => 'custom-container-class'
:dropdownClass => 'custom-dropdown-class'

to display a glyphicon infront of each option value:

:template => :glyphicon, :collection => User.all.map { |user| [user.to_s, user.to_param, { class: 'glyphicon-flag' }] }

Additional

Call with single_selected: true to ensure only the first selected option tag will be <option selected="selected">.

This can be useful when displaying multiple options with an identical value.

Clear value

It's a bit tricky to clear the selected value

$('select').val('').trigger('change.select2')

Working with dynamic options

The following information applies to effective_select only, and is not part of the standard select2 API.

To totally hide (instead of just grey out) any disabled options from the select2 dropdown, initialize the input with:

= f.input :category, :as => :effective_select, :collection => ..., :hide_disabled => true

If you want to dynamically add/remove options from the select field after page load, you must use the select2:reinitialize event:

# When something on my page changes
$(document).on 'change', '.something', (event) ->
  $select = $(event.target).closest('form').find('select.i-want-to-change')  # Find the select2 input to be updated

  # Go through its options, and modify some of them.
  # Using the above 'hide_disabled true' functionality, the following code hides the options from being displayed,
  # but you could actually remove the options, add new ones, or update the values/texts. whatever.
  $select.find('option').each (index, option) ->
    $(option).prop('disabled', true) if index > 10

  # Whenever the underlying options change, you need to manually trigger the following event:
  $select.select2().trigger('select2:reinitialize')

AJAX Support

There is currently no support for using AJAX to load remote data. This feature is supported by the underlying select2 library and will be implemented here at a future point.

Effective Static Control

A bootstrap3 Static control input.

Renders <p class='form-control-static'>value</p> with the appropriate SimpleForm wrappings.

Installation

There are no installation steps required for this form input

Usage

As a Rails Form Helper input:

= form_for @user do |f|
  = f.effective_static_control :category

As a SimpleForm input:

= simple_form_for @user do |f|
  = f.input :category, as: :effective_static_control
  = f.input :category, as: :effective_static_control

Options

There are no default options for this form input.

Effective Tel(ephone)

This custom form input uses a jQuery maskedInput plugin from the following awesome project:

jQuery Masked Input Plugin (https://github.com/digitalBush/jquery.maskedinput)

Installation

If you've already installed the 'All Form Inputs' assets (see above), there are no additional installation steps.

To install this form input individually, add the following to your application.js:

//= require effective_tel/input

Usage

As a Rails Form Helper input:

= form_for @user do |f|
  = f.effective_tel :phone

As a SimpleForm input:

= simple_form_for @user do |f|
  = f.input :phone, :as => :effective_tel

As a SimpleForm input without the input group (phone glyphicon)

= simple_form_for @user do |f|
  = f.input :phone, :as => :effective_tel, :input_group => false

You should add a server side validation to enforce the default "(123) 555-1234" with optional "x123" extension format:

validates :phone, format: { with: /\A\(\d{3}\) \d{3}-\d{4}( x\d+)?\Z/ }
validates :phone, effective_tel: true   # Enforces same format as above

Effective Time Picker

This custom form input is based on the following awesome project:

Bootstrap 3 Datepicker (https://github.com/Eonasdan/bootstrap-datetimepicker)

Installation

If you've already installed the 'All Form Inputs' assets (see above), there are no additional installation steps.

To install this form input individually, add the following to your application.js:

//= require effective_time_picker/input

and add the following to your application.css:

*= require effective_time_picker/input

Usage

As a Rails Form Helper input:

= form_for @user do |f|
  = f.effective_time_picker :started_at

As a SimpleForm input:

= simple_form_for @user do |f|
  = f.input :started_at, :as => :effective_time_picker

As a SimpleForm input without the input group (time glyphicon)

= simple_form_for @user do |f|
  = f.input :started_at, :as => :effective_time_picker, :input_group => false

Options

The default :input_js => options used to initialize this form input are as follows:

:input_js => {:format => ''%H:%M''}

For more options, please see Effective Date Time Picker above

Effective URL

This custom form input enforces the url starts with http:// or https://

If font-awesome-rails gem is installed, a font-awesome icon for facebook, google, linkedin, twitter, vimeo and youtube will be inserted based on the field name.

Installation

If you've already installed the 'All Form Inputs' assets (see above), there are no additional installation steps.

To install this form input individually, add the following to your application.js:

//= require effective_url/input

Usage

As a Rails Form Helper input:

= form_for @user do |f|
  = f.effective_url :website

As a SimpleForm input:

= simple_form_for @user do |f|
  = f.input :website, :as => :effective_url

As a SimpleForm input without the input group (globe glyphicon)

= simple_form_for @user do |f|
  = f.input :website, :as => :effective_url, :input_group => false

You should add a server side validation to enforce the url starts with http(s?)://

validates :website, format: { with: /\Ahttps?:\/\/\w+.+\Z/ }
validates :website, effective_url: true   # Enforced same format as above

Options

You can pass fontawesome: false and glyphicon: false to tweak the automatic social icon display behaviour.

License

MIT License. Copyright Code and Effect Inc.

Credits

The authors of this gem are not associated with any of the awesome projects used by this gem.

We are just extending these existing community projects for ease of use with Rails Form Helper and SimpleForm.

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Bonus points for test coverage
  6. Create new Pull Request