padrino-helpers 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +7 -0
- data/Rakefile +58 -0
- data/VERSION +1 -0
- data/lib/padrino-helpers.rb +16 -0
- data/lib/padrino-helpers/asset_tag_helpers.rb +97 -0
- data/lib/padrino-helpers/form_builder/abstract_form_builder.rb +139 -0
- data/lib/padrino-helpers/form_builder/standard_form_builder.rb +37 -0
- data/lib/padrino-helpers/form_helpers.rb +194 -0
- data/lib/padrino-helpers/format_helpers.rb +74 -0
- data/lib/padrino-helpers/output_helpers.rb +98 -0
- data/lib/padrino-helpers/render_helpers.rb +63 -0
- data/lib/padrino-helpers/tag_helpers.rb +42 -0
- data/test/active_support_helpers.rb +7 -0
- data/test/fixtures/markup_app/app.rb +61 -0
- data/test/fixtures/markup_app/views/capture_concat.erb +14 -0
- data/test/fixtures/markup_app/views/capture_concat.haml +13 -0
- data/test/fixtures/markup_app/views/content_for.erb +11 -0
- data/test/fixtures/markup_app/views/content_for.haml +9 -0
- data/test/fixtures/markup_app/views/content_tag.erb +11 -0
- data/test/fixtures/markup_app/views/content_tag.haml +9 -0
- data/test/fixtures/markup_app/views/fields_for.erb +8 -0
- data/test/fixtures/markup_app/views/fields_for.haml +6 -0
- data/test/fixtures/markup_app/views/form_for.erb +56 -0
- data/test/fixtures/markup_app/views/form_for.haml +47 -0
- data/test/fixtures/markup_app/views/form_tag.erb +57 -0
- data/test/fixtures/markup_app/views/form_tag.haml +45 -0
- data/test/fixtures/markup_app/views/link_to.erb +5 -0
- data/test/fixtures/markup_app/views/link_to.haml +4 -0
- data/test/fixtures/markup_app/views/mail_to.erb +3 -0
- data/test/fixtures/markup_app/views/mail_to.haml +3 -0
- data/test/fixtures/render_app/app.rb +53 -0
- data/test/fixtures/render_app/views/erb/test.erb +1 -0
- data/test/fixtures/render_app/views/haml/test.haml +1 -0
- data/test/fixtures/render_app/views/template/_user.haml +7 -0
- data/test/fixtures/render_app/views/template/haml_template.haml +1 -0
- data/test/fixtures/render_app/views/template/some_template.haml +2 -0
- data/test/helper.rb +73 -0
- data/test/test_asset_tag_helpers.rb +127 -0
- data/test/test_form_builder.rb +611 -0
- data/test/test_form_helpers.rb +406 -0
- data/test/test_format_helpers.rb +96 -0
- data/test/test_output_helpers.rb +63 -0
- data/test/test_render_helpers.rb +78 -0
- data/test/test_tag_helpers.rb +73 -0
- metadata +174 -0
data/.document
ADDED
data/.gitignore
ADDED
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
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
|