padrino-helpers 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/.document +5 -0
  2. data/.gitignore +21 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +7 -0
  5. data/Rakefile +58 -0
  6. data/VERSION +1 -0
  7. data/lib/padrino-helpers.rb +16 -0
  8. data/lib/padrino-helpers/asset_tag_helpers.rb +97 -0
  9. data/lib/padrino-helpers/form_builder/abstract_form_builder.rb +139 -0
  10. data/lib/padrino-helpers/form_builder/standard_form_builder.rb +37 -0
  11. data/lib/padrino-helpers/form_helpers.rb +194 -0
  12. data/lib/padrino-helpers/format_helpers.rb +74 -0
  13. data/lib/padrino-helpers/output_helpers.rb +98 -0
  14. data/lib/padrino-helpers/render_helpers.rb +63 -0
  15. data/lib/padrino-helpers/tag_helpers.rb +42 -0
  16. data/test/active_support_helpers.rb +7 -0
  17. data/test/fixtures/markup_app/app.rb +61 -0
  18. data/test/fixtures/markup_app/views/capture_concat.erb +14 -0
  19. data/test/fixtures/markup_app/views/capture_concat.haml +13 -0
  20. data/test/fixtures/markup_app/views/content_for.erb +11 -0
  21. data/test/fixtures/markup_app/views/content_for.haml +9 -0
  22. data/test/fixtures/markup_app/views/content_tag.erb +11 -0
  23. data/test/fixtures/markup_app/views/content_tag.haml +9 -0
  24. data/test/fixtures/markup_app/views/fields_for.erb +8 -0
  25. data/test/fixtures/markup_app/views/fields_for.haml +6 -0
  26. data/test/fixtures/markup_app/views/form_for.erb +56 -0
  27. data/test/fixtures/markup_app/views/form_for.haml +47 -0
  28. data/test/fixtures/markup_app/views/form_tag.erb +57 -0
  29. data/test/fixtures/markup_app/views/form_tag.haml +45 -0
  30. data/test/fixtures/markup_app/views/link_to.erb +5 -0
  31. data/test/fixtures/markup_app/views/link_to.haml +4 -0
  32. data/test/fixtures/markup_app/views/mail_to.erb +3 -0
  33. data/test/fixtures/markup_app/views/mail_to.haml +3 -0
  34. data/test/fixtures/render_app/app.rb +53 -0
  35. data/test/fixtures/render_app/views/erb/test.erb +1 -0
  36. data/test/fixtures/render_app/views/haml/test.haml +1 -0
  37. data/test/fixtures/render_app/views/template/_user.haml +7 -0
  38. data/test/fixtures/render_app/views/template/haml_template.haml +1 -0
  39. data/test/fixtures/render_app/views/template/some_template.haml +2 -0
  40. data/test/helper.rb +73 -0
  41. data/test/test_asset_tag_helpers.rb +127 -0
  42. data/test/test_form_builder.rb +611 -0
  43. data/test/test_form_helpers.rb +406 -0
  44. data/test/test_format_helpers.rb +96 -0
  45. data/test/test_output_helpers.rb +63 -0
  46. data/test/test_render_helpers.rb +78 -0
  47. data/test/test_tag_helpers.rb +73 -0
  48. metadata +174 -0
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Padrino
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,7 @@
1
+ = padrino-helpers
2
+
3
+ Description goes here.
4
+
5
+ == Copyright
6
+
7
+ Copyright (c) 2009 Padrino. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,58 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "padrino-helpers"
8
+ gem.summary = "Helpers for padrino"
9
+ gem.description = "Tag helpers, asset helpers, form helpers, form builders and many more helpers for padrino"
10
+ gem.email = "nesquena@gmail.com"
11
+ gem.homepage = "http://github.com/padrino/padrino-helpers"
12
+ gem.authors = ["Padrino Team", "Nathan Esquenazi", "Davide D'Agostino", "Arthur Chiu"]
13
+ gem.add_runtime_dependency "sinatra", ">= 0.9.2"
14
+ gem.add_development_dependency "haml", ">= 2.2.1"
15
+ gem.add_development_dependency "shoulda", ">= 0"
16
+ gem.add_development_dependency "mocha", ">= 0.9.7"
17
+ gem.add_development_dependency "rack-test", ">= 0.5.0"
18
+ gem.add_development_dependency "webrat", ">= 0.5.1"
19
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
20
+ end
21
+ Jeweler::GemcutterTasks.new
22
+ rescue LoadError
23
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
24
+ end
25
+
26
+ require 'rake/testtask'
27
+ Rake::TestTask.new(:test) do |test|
28
+ test.libs << 'lib' << 'test'
29
+ test.pattern = 'test/**/test_*.rb'
30
+ test.verbose = true
31
+ end
32
+
33
+ begin
34
+ require 'rcov/rcovtask'
35
+ Rcov::RcovTask.new do |test|
36
+ test.libs << 'test'
37
+ test.pattern = 'test/**/test_*.rb'
38
+ test.verbose = true
39
+ end
40
+ rescue LoadError
41
+ task :rcov do
42
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
43
+ end
44
+ end
45
+
46
+ task :test => :check_dependencies
47
+
48
+ task :default => :test
49
+
50
+ require 'rake/rdoctask'
51
+ Rake::RDocTask.new do |rdoc|
52
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
53
+
54
+ rdoc.rdoc_dir = 'rdoc'
55
+ rdoc.title = "padrino-helpers #{version}"
56
+ rdoc.rdoc_files.include('README*')
57
+ rdoc.rdoc_files.include('lib/**/*.rb')
58
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,16 @@
1
+ require File.dirname(__FILE__) + '/../../padrino-core/lib/padrino-core/support_lite'
2
+ Dir[File.dirname(__FILE__) + '/padrino-helpers/**/*.rb'].each {|file| require file }
3
+
4
+ module Padrino
5
+ module Helpers
6
+ def self.registered(app)
7
+ app.set :default_builder, 'StandardFormBuilder'
8
+ app.helpers Padrino::Helpers::OutputHelpers
9
+ app.helpers Padrino::Helpers::TagHelpers
10
+ app.helpers Padrino::Helpers::AssetTagHelpers
11
+ app.helpers Padrino::Helpers::FormHelpers
12
+ app.helpers Padrino::Helpers::FormatHelpers
13
+ app.helpers Padrino::Helpers::RenderHelpers
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,97 @@
1
+ module Padrino
2
+ module Helpers
3
+ module AssetTagHelpers
4
+
5
+ # Creates a div to display the flash of given type if it exists
6
+ # flash_tag(:notice, :class => 'flash', :id => 'flash-notice')
7
+ def flash_tag(kind, options={})
8
+ flash_text = flash[kind]
9
+ return '' if flash_text.blank?
10
+ options.reverse_merge!(:class => 'flash')
11
+ content_tag(:div, flash_text, options)
12
+ end
13
+
14
+ # Creates a link element with given name, url and options
15
+ # link_to 'click me', '/dashboard', :class => 'linky'
16
+ # link_to('/dashboard', :class => 'blocky') do ... end
17
+ # parameters: name, url='javascript:void(0)', options={}, &block
18
+ def link_to(*args, &block)
19
+ if block_given?
20
+ url, options = (args[0] || 'javascript:void(0);'), (args[1] || {})
21
+ options.reverse_merge!(:href => url)
22
+ link_content = capture_html(&block)
23
+ result_link = content_tag(:a, link_content, options)
24
+ block_is_template?(block) ? concat_content(result_link) : result_link
25
+ else
26
+ name, url, options = args.first, (args[1] || 'javascript:void(0);'), (args[2] || {})
27
+ options.reverse_merge!(:href => url)
28
+ content_tag(:a, name, options)
29
+ end
30
+ end
31
+
32
+ # Creates a mail link element with given name and caption
33
+ # mail_to "me@demo.com" => <a href="mailto:me@demo.com">me@demo.com</a>
34
+ # mail_to "me@demo.com", "My Email" => <a href="mailto:me@demo.com">My Email</a>
35
+ def mail_to(email, caption=nil, mail_options={})
36
+ html_options = mail_options.slice!(:cc, :bcc, :subject, :body)
37
+ mail_query = Rack::Utils.build_query(mail_options).gsub(/\+/, '%20').gsub('%40', '@')
38
+ mail_href = "mailto:#{email}"; mail_href << "?#{mail_query}" if mail_query.present?
39
+ link_to (caption || email), mail_href, html_options
40
+ end
41
+
42
+ # Creates an image element with given url and options
43
+ # image_tag('icons/avatar.png')
44
+ def image_tag(url, options={})
45
+ options.reverse_merge!(:src => image_path(url))
46
+ tag(:img, options)
47
+ end
48
+
49
+ # Returns a stylesheet link tag for the sources specified as arguments
50
+ # stylesheet_link_tag 'style', 'application', 'layout'
51
+ def stylesheet_link_tag(*sources)
52
+ options = sources.extract_options!.symbolize_keys
53
+ sources.collect { |sheet| stylesheet_tag(sheet, options) }.join("\n")
54
+ end
55
+
56
+ # javascript_include_tag 'application', 'special'
57
+ def javascript_include_tag(*sources)
58
+ options = sources.extract_options!.symbolize_keys
59
+ sources.collect { |script| javascript_tag(script, options) }.join("\n")
60
+ end
61
+
62
+ # Returns the path to the image, either relative or absolute
63
+ def image_path(src)
64
+ src.gsub!(/\s/, '')
65
+ src =~ %r{^\s*(/|http)} ? src : File.join('/images', src)
66
+ end
67
+
68
+ protected
69
+
70
+ # stylesheet_tag('style', :media => 'screen')
71
+ def stylesheet_tag(source, options={})
72
+ options = options.dup.reverse_merge!(:href => stylesheet_path(source), :media => 'screen', :rel => 'stylesheet', :type => 'text/css')
73
+ tag(:link, options)
74
+ end
75
+
76
+ # javascript_tag 'application', :src => '/javascripts/base/application.js'
77
+ def javascript_tag(source, options={})
78
+ options = options.dup.reverse_merge!(:src => javascript_path(source), :type => 'text/javascript', :content => "")
79
+ tag(:script, options)
80
+ end
81
+
82
+ def javascript_path(source)
83
+ return source if source =~ /^http/
84
+ result_path = "/javascripts/#{File.basename(source, '.js')}.js"
85
+ stamp = File.exist?(result_path) ? File.mtime(result_path) : Time.now.to_i
86
+ "#{result_path}?#{stamp}"
87
+ end
88
+
89
+ def stylesheet_path(source)
90
+ return source if source =~ /^http/
91
+ result_path = "/stylesheets/#{File.basename(source, '.css')}.css"
92
+ stamp = File.exist?(result_path) ? File.mtime(result_path) : Time.now.to_i
93
+ "#{result_path}?#{stamp}"
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,139 @@
1
+ module Padrino
2
+ module Helpers
3
+ module FormBuilder
4
+ class AbstractFormBuilder
5
+ attr_accessor :template, :object
6
+
7
+ def initialize(template, object)
8
+ @template = template
9
+ @object = build_object(object)
10
+ raise "FormBuilder template must be initialized!" unless template
11
+ raise "FormBuilder object must be not be nil value. If there's no object, use a symbol instead! (i.e :user)" unless object
12
+ end
13
+
14
+ # f.error_messages
15
+ def error_messages(options={})
16
+ @template.error_messages_for(@object, options)
17
+ end
18
+
19
+ # f.label :username, :caption => "Nickname"
20
+ def label(field, options={})
21
+ options.reverse_merge!(:caption => field.to_s.titleize)
22
+ @template.label_tag(field_id(field), options)
23
+ end
24
+
25
+ # f.hidden_field :session_id, :value => "45"
26
+ def hidden_field(field, options={})
27
+ options.reverse_merge!(:value => field_value(field), :id => field_id(field))
28
+ @template.hidden_field_tag field_name(field), options
29
+ end
30
+
31
+ # f.text_field :username, :value => "(blank)", :id => 'username'
32
+ def text_field(field, options={})
33
+ options.reverse_merge!(:value => field_value(field), :id => field_id(field))
34
+ @template.text_field_tag field_name(field), options
35
+ end
36
+
37
+ # f.text_area :summary, :value => "(enter summary)", :id => 'summary'
38
+ def text_area(field, options={})
39
+ options.reverse_merge!(:value => field_value(field), :id => field_id(field))
40
+ @template.text_area_tag field_name(field), options
41
+ end
42
+
43
+ # f.password_field :password, :id => 'password'
44
+ def password_field(field, options={})
45
+ options.reverse_merge!(:value => field_value(field), :id => field_id(field))
46
+ @template.password_field_tag field_name(field), options
47
+ end
48
+
49
+ # f.select :color, :options => ['red', 'green'], :include_blank => true
50
+ # f.select :color, :collection => @colors, :fields => [:name, :id]
51
+ def select(field, options={})
52
+ options.reverse_merge!(:id => field_id(field), :selected => field_value(field))
53
+ @template.select_tag field_name(field), options
54
+ end
55
+
56
+ # f.check_box :remember_me, :value => 'true', :uncheck_value => '0'
57
+ def check_box(field, options={})
58
+ unchecked_value = options.delete(:uncheck_value) || '0'
59
+ options.reverse_merge!(:id => field_id(field), :value => '1')
60
+ options.merge!(:checked => true) if values_matches_field?(field, options[:value])
61
+ html = @template.check_box_tag field_name(field), options
62
+ html << hidden_field(field, :value => unchecked_value, :id => nil)
63
+ end
64
+
65
+ # f.radio_button :gender, :value => 'male'
66
+ def radio_button(field, options={})
67
+ options.reverse_merge!(:id => field_id(field, options[:value]))
68
+ options.merge!(:checked => true) if values_matches_field?(field, options[:value])
69
+ @template.radio_button_tag field_name(field), options
70
+ end
71
+
72
+ # f.file_field :photo, :class => 'avatar'
73
+ def file_field(field, options={})
74
+ options.reverse_merge!(:id => field_id(field))
75
+ @template.file_field_tag field_name(field), options
76
+ end
77
+
78
+ # f.submit "Update", :class => 'large'
79
+ def submit(caption="Submit", options={})
80
+ @template.submit_tag caption, options
81
+ end
82
+
83
+ # f.simage_submitubmit "buttons/submit.png", :class => 'large'
84
+ def image_submit(source, options={})
85
+ @template.image_submit_tag source, options
86
+ end
87
+
88
+ protected
89
+
90
+ # Returns the known field types for a formbuilder
91
+ def self.field_types
92
+ [:hidden_field, :text_field, :text_area, :password_field, :file_field, :radio_button, :check_box, :select]
93
+ end
94
+
95
+ # Returns the object's models name
96
+ # => user_assignment
97
+ def object_name
98
+ object.is_a?(Symbol) ? object : object.class.to_s.underscore
99
+ end
100
+
101
+ # Returns true if the value matches the value in the field
102
+ # field_has_value?(:gender, 'male')
103
+ def values_matches_field?(field, value)
104
+ value.present? && (field_value(field).to_s == value.to_s || field_value(field).to_s == 'true')
105
+ end
106
+
107
+ # Returns the value for the object's field
108
+ # field_value(:username) => "Joey"
109
+ def field_value(field)
110
+ @object && @object.respond_to?(field) ? @object.send(field) : ""
111
+ end
112
+
113
+ # Returns the name for the given field
114
+ # field_name(:username) => "user[username]"
115
+ def field_name(field)
116
+ "#{object_name}[#{field}]"
117
+ end
118
+
119
+ # Returns the id for the given field
120
+ # field_id(:username) => "user_username"
121
+ # field_id(:gender, :male) => "user_gender_male"
122
+ def field_id(field, value=nil)
123
+ value.blank? ? "#{object_name}_#{field}" : "#{object_name}_#{field}_#{value}"
124
+ end
125
+
126
+ # explicit_object is either a symbol or a record
127
+ # Returns a new record of the type specified in the object
128
+ def build_object(object_or_symbol)
129
+ object_or_symbol.is_a?(Symbol) ? object_class(object_or_symbol).new : object_or_symbol
130
+ end
131
+
132
+ # Returns the class type for the given object
133
+ def object_class(explicit_object)
134
+ explicit_object.is_a?(Symbol) ? explicit_object.to_s.classify.constantize : explicit_object.class
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,37 @@
1
+ module Padrino
2
+ module Helpers
3
+ module FormBuilder
4
+ class StandardFormBuilder < AbstractFormBuilder
5
+
6
+ # text_field_block(:username, { :class => 'long' }, { :class => 'wide-label' })
7
+ # text_area_block(:summary, { :class => 'long' }, { :class => 'wide-label' })
8
+ # password_field_block(:password, { :class => 'long' }, { :class => 'wide-label' })
9
+ # file_field_block(:photo, { :class => 'long' }, { :class => 'wide-label' })
10
+ # check_box_block(:remember_me, { :class => 'long' }, { :class => 'wide-label' })
11
+ # select_block(:color, :options => ['green', 'black'])
12
+ (self.field_types - [ :hidden_field, :radio_button ]).each do |field_type|
13
+ class_eval <<-EOF
14
+ def #{field_type}_block(field, options={}, label_options={})
15
+ label_options.reverse_merge!(:caption => options.delete(:caption)) if options[:caption]
16
+ field_html = label(field, label_options)
17
+ field_html << #{field_type}(field, options)
18
+ @template.content_tag(:p, field_html)
19
+ end
20
+ EOF
21
+ end
22
+
23
+ # submit_block("Update")
24
+ def submit_block(caption, options={})
25
+ submit_html = self.submit(caption, options)
26
+ @template.content_tag(:p, submit_html)
27
+ end
28
+
29
+ # image_submit_block("submit.png")
30
+ def image_submit_block(source, options={})
31
+ submit_html = self.image_submit(source, options)
32
+ @template.content_tag(:p, submit_html)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,194 @@
1
+ module Padrino
2
+ module Helpers
3
+ module FormHelpers
4
+ # Constructs a form for object using given or default form_builder
5
+ # form_for :user, '/register' do |f| ... end
6
+ # form_for @user, '/register', :id => 'register' do |f| ... end
7
+ def form_for(object, url, settings={}, &block)
8
+ builder_class = configured_form_builder_class(settings[:builder])
9
+ form_html = capture_html(builder_class.new(self, object), &block)
10
+ form_tag(url, settings) { form_html }
11
+ end
12
+
13
+ # Constructs form fields for an object using given or default form_builder
14
+ # Used within an existing form to allow alternate objects within one form
15
+ # fields_for @user.assignment do |assignment| ... end
16
+ # fields_for :assignment do |assigment| ... end
17
+ def fields_for(object, settings={}, &block)
18
+ builder_class = configured_form_builder_class(settings[:builder])
19
+ fields_html = capture_html(builder_class.new(self, object), &block)
20
+ concat_content fields_html
21
+ end
22
+
23
+ # Constructs a form without object based on options
24
+ # form_tag '/register' do ... end
25
+ def form_tag(url, options={}, &block)
26
+ options.reverse_merge!(:method => 'post', :action => url)
27
+ options[:enctype] = "multipart/form-data" if options.delete(:multipart)
28
+ inner_form_html = hidden_form_method_field(options[:method]) + capture_html(&block)
29
+ concat_content content_tag('form', inner_form_html, options)
30
+ end
31
+
32
+ # Constructs a field_set to group fields with given options
33
+ # field_set_tag("Office", :class => 'office-set')
34
+ # parameters: legend_text=nil, options={}
35
+ def field_set_tag(*args, &block)
36
+ options = args.extract_options!
37
+ legend_text = args[0].is_a?(String) ? args.first : nil
38
+ legend_html = legend_text.blank? ? '' : content_tag(:legend, legend_text)
39
+ field_set_content = legend_html + capture_html(&block)
40
+ concat_content content_tag('fieldset', field_set_content, options)
41
+ end
42
+
43
+ # Constructs list html for the errors for a given object
44
+ # error_messages_for @user
45
+ def error_messages_for(record, options={})
46
+ return "" if record.blank? or record.errors.none?
47
+ options.reverse_merge!(:header_message => "The #{record.class.to_s.downcase} could not be saved!")
48
+ error_messages = record.errors.full_messages
49
+ error_items = error_messages.collect { |er| content_tag(:li, er) }.join("\n")
50
+ error_html = content_tag(:p, options.delete(:header_message))
51
+ error_html << content_tag(:ul, error_items, :class => 'errors-list')
52
+ content_tag(:div, error_html, :class => 'field-errors')
53
+ end
54
+
55
+ # Constructs a label tag from the given options
56
+ # label_tag :username, :class => 'long-label'
57
+ # label_tag :username, :class => 'long-label' do ... end
58
+ def label_tag(name, options={}, &block)
59
+ options.reverse_merge!(:caption => name.to_s.titleize, :for => name)
60
+ caption_text = options.delete(:caption) + ": "
61
+ if block_given? # label with inner content
62
+ label_content = caption_text + capture_html(&block)
63
+ concat_content(content_tag(:label, label_content, options))
64
+ else # regular label
65
+ content_tag(:label, caption_text, options)
66
+ end
67
+ end
68
+
69
+ # Constructs a hidden field input from the given options
70
+ # hidden_field_tag :session_key, :value => "__secret__"
71
+ def hidden_field_tag(name, options={})
72
+ options.reverse_merge!(:name => name)
73
+ input_tag(:hidden, options)
74
+ end
75
+
76
+ # Constructs a text field input from the given options
77
+ # text_field_tag :username, :class => 'long'
78
+ def text_field_tag(name, options={})
79
+ options.reverse_merge!(:name => name)
80
+ input_tag(:text, options)
81
+ end
82
+
83
+ # Constructs a text area input from the given options
84
+ # text_area_tag :username, :class => 'long'
85
+ def text_area_tag(name, options={})
86
+ options.reverse_merge!(:name => name)
87
+ content_tag(:textarea, '', options)
88
+ end
89
+
90
+ # Constructs a password field input from the given options
91
+ # password_field_tag :password, :class => 'long'
92
+ def password_field_tag(name, options={})
93
+ options.reverse_merge!(:name => name)
94
+ input_tag(:password, options)
95
+ end
96
+
97
+ # Constructs a check_box from the given options
98
+ # options = [['caption', 'value'], ['Green', 'green1'], ['Blue', 'blue1'], ['Black', "black1"]]
99
+ # options = ['option', 'red', 'yellow' ]
100
+ # select_tag(:favorite_color, :options => ['red', 'yellow'], :selected => 'green1')
101
+ # select_tag(:country, :collection => @countries, :fields => [:name, :code])
102
+ def select_tag(name, options={})
103
+ options.reverse_merge!(:name => name)
104
+ collection, fields = options.delete(:collection), options.delete(:fields)
105
+ options[:options] = options_from_collection(collection, fields) if collection
106
+ options[:options].unshift('') if options.delete(:include_blank)
107
+ select_options_html = options_for_select(options.delete(:options), options.delete(:selected))
108
+ options.merge!(:name => "#{options[:name]}[]") if options[:multiple]
109
+ content_tag(:select, select_options_html, options)
110
+ end
111
+
112
+ # Constructs a check_box from the given options
113
+ # check_box_tag :remember_me, :value => 'Yes'
114
+ def check_box_tag(name, options={})
115
+ options.reverse_merge!(:name => name, :value => '1')
116
+ input_tag(:checkbox, options)
117
+ end
118
+
119
+ # Constructs a radio_button from the given options
120
+ # radio_button_tag :remember_me, :value => 'true'
121
+ def radio_button_tag(name, options={})
122
+ options.reverse_merge!(:name => name)
123
+ input_tag(:radio, options)
124
+ end
125
+
126
+ # Constructs a file field input from the given options
127
+ # file_field_tag :photo, :class => 'long'
128
+ def file_field_tag(name, options={})
129
+ options.reverse_merge!(:name => name)
130
+ input_tag(:file, options)
131
+ end
132
+
133
+ # Constructs a submit button from the given options
134
+ # submit_tag "Create", :class => 'success'
135
+ def submit_tag(caption="Submit", options={})
136
+ options.reverse_merge!(:value => caption)
137
+ input_tag(:submit, options)
138
+ end
139
+
140
+ # Constructs a button input from the given options
141
+ # button_tag "Cancel", :class => 'clear'
142
+ def button_tag(caption, options = {})
143
+ options.reverse_merge!(:value => caption)
144
+ input_tag(:button, options)
145
+ end
146
+
147
+ # Constructs a submit button from the given options
148
+ # submit_tag "Create", :class => 'success'
149
+ def image_submit_tag(source, options={})
150
+ options.reverse_merge!(:src => image_path(source))
151
+ input_tag(:image, options)
152
+ end
153
+
154
+ protected
155
+
156
+ # Returns an array of option items for a select field based on the given collection
157
+ # fields is an array containing the fields to display from each item in the collection
158
+ def options_from_collection(collection, fields)
159
+ return '' if collection.blank?
160
+ collection.collect { |item| [ item.send(fields.first), item.send(fields.last) ] }
161
+ end
162
+
163
+ # Returns the options tags for a select based on the given option items
164
+ def options_for_select(option_items, selected_value=nil)
165
+ return '' if option_items.blank?
166
+ option_items.collect do |caption, value|
167
+ value ||= caption
168
+ content_tag(:option, caption, :value => value, :selected => selected_value.to_s =~ /#{value}|#{caption}/)
169
+ end
170
+ end
171
+
172
+ # returns the hidden method field for 'put' and 'delete' forms
173
+ # Only 'get' and 'post' are allowed within browsers;
174
+ # 'put' and 'delete' are just specified using hidden fields with form action still 'put'.
175
+ # hidden_form_method_field('delete') => <input name="_method" value="delete" />
176
+ def hidden_form_method_field(desired_method)
177
+ return '' if (desired_method =~ /get|post/)
178
+ original_method = desired_method.dup
179
+ desired_method.replace('post')
180
+ hidden_field_tag(:_method, :value => original_method)
181
+ end
182
+
183
+ # Returns the FormBuilder class to use based on all available setting sources
184
+ # If explicitly defined, returns that, otherwise returns defaults
185
+ # configured_form_builder_class(nil) => StandardFormBuilder
186
+ def configured_form_builder_class(explicit_builder=nil)
187
+ default_builder = self.respond_to?(:options) && self.options.default_builder
188
+ configured_builder = explicit_builder || default_builder || 'StandardFormBuilder'
189
+ configured_builder = "Padrino::Helpers::FormBuilder::#{configured_builder}".constantize if configured_builder.is_a?(String)
190
+ configured_builder
191
+ end
192
+ end
193
+ end
194
+ end