Using a FormBuilder is the easiest way to add new methods to a form_for block; to create a custom FormBuilder simply create a file .rb in your helper directory and put this code inside:
# the custom FormBuilder
class ColorPickerFormBuilder < ActionView::Helpers::FormBuilder
end
What we have just done is created a new FormBuilder by extending the base one, for now we haven’t added any method yet but we can use this builder like the base one; to do this we need just to use the ”:builder” option while calling the form_for method:
<% form_for(:milestone, :url => milestone_path(@milestone.project,@milestone), :html => { :method => :put }, :builder => ColorPickerFormBuilder) do |f| %>
…your form code here…<% end %>
Adding the color picker method
To add the color picker the only step to perform is write a method named ‘color_picker’ in the formbuilder we’ve previously created:
def color_picker(method, options={})
toret = "<div class=\"colorpicker\">"
options[:avaiable].each_pair do |key,opt|
toret += "<div id=\"coloritem_#{key}\" class=\"coloritem " + (opt == options[:selected] ? "cpselected" : "") + "\" style=\"background: #{opt}\">"
toret += "<a href=\"#\" onClick=\"set_color_picker(‘coloritem_#{key}’,'#{opt}’);return false;\"></a>"
toret += "</div>\n"
end
toret += "<input type=\"hidden\" name=\"#{@object_name.to_s}[#{method.to_s}]\" value=\"#{options[:selected]}\" id=\"hidden_color_picker\"/>"
toret += "<div class=\"clear\"></div>"
toret += "</div>"
return toret
end
Now we can call this new control in the same way we would use for a text_field or a text_area:
… in your environment.rb file…
MIL_TYPES = { 1 => "#ff6600",
2 => "#785f4b",
3 => "#56bb98",
4 => "#786575",
5 => "#000000"
}.freeze
… inside a form_for block …
<%= f.color_picker :color, :avaiable => MIL_TYPES, :selected=> @milestone.color %>
CSS and Javascript
The last step is to do a little styling of this controller and add a bit of javascript:
In your CSS file:
div.coloritem{
float: left;
margin-left: 5px;
width: 20px;
height: 20px;
}
div.cpselected{
border: 2px solid #000000;
}
div.coloritem A{
display: block;
width: 100%;
height: 100%;
}
In your javascript file (usually application.js):
function set_color_picker(element_name,color){
items = document.getElementsByClassName(‘coloritem’);
for(x=0;x<items.length;x++){
Element.removeClassName(items[x],’cpselected’);
}
Element.addClassName(element_name,’cpselected’)
document.getElementById(‘hidden_color_picker’).value = color
}