Created
June 12, 2010 00:03
-
-
Save kwatch/435213 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
module SelectTagHelper | |
## | |
## Generate <select> tag. Both <option> and <opttags> are supported. | |
## | |
## ex. | |
## <% values = {'H'=>'Haruhi', 'M'=>'Mikuru', 'Y'=>'Yuki'} %> | |
## <%= select_tag('yome', 'H', 'class="yome"') do |t| | |
## t.option(nil, 'Please select') | |
## values.each {|k,v| t.option(k, v) } | |
## end %> | |
## | |
## #=> <select name="yome" class="yome"> | |
## # <option value="">Please select</option> | |
## # <option value="H" selected="selected">Haruhi</option> | |
## # <option value="M">Mikuru</option> | |
## # <option value="Y">Yuki</option> | |
## # </select> | |
## | |
## ex. | |
## <% girls = {'H'=>'Haruhi', 'M'=>'Mikuru', 'Y'=>'Yuki'} %> | |
## <% boys = {'I'=>'Itsuki', 'K'=>'Kyon'} %> | |
## <%= select_tag('yome', 'H', :class=>"yome") do |t| | |
## t.option(nil, 'Please select') | |
## t.optgroup('Girls') do girls.each {|k, v| t.option(k, v) } end | |
## t.optgroup('Boys') do boys.each {|k, v| t.option(k, v) } end | |
## end %> | |
## | |
## #=> <select name="yome" class="yome"> | |
## # <option value="">Please select</option> | |
## # <optgroup label="Girls"> | |
## # <option value="H" selected="selected">Haruhi</option> | |
## # <option value="M">Mikuru</option> | |
## # <option value="Y">Yuki</option> | |
## # </optgroup> | |
## # <optgroup label="Boys"> | |
## # <option value="I">Itsuki</option> | |
## # <option value="K">Kyon</option> | |
## # </optgroup> | |
## # </select> | |
## | |
def select_tag(name, value, attrs=nil, &block) | |
return SelectTag.new.build(name, value, attrs, &block) | |
end | |
## | |
## Generate <select multiple="multiple"> tag. | |
## | |
## 'values' arguments can be an Array, Hash, or scalar value. | |
## | |
def multiple_select_tag(name, values, attrs=nil, &block) | |
return MultipleSelectTag.new.build(name, values, attrs, &block) | |
end | |
## | |
## Helper class for select_tag() method | |
## | |
class SelectTag # :nodoc: | |
def build(name, value=nil, attrs=nil) | |
@value = value | |
@tag = "<select name=\"#{name}\"#{tag_attr_str(attrs)}>\n" | |
yield self | |
@tag << "</select>" | |
@tag | |
end | |
def option(val, label=nil, attrs=nil) | |
label = val if label.nil? | |
s1 = selected?(val) ? ' selected="selected"' : nil | |
s2 = tag_attr_str(attrs) | |
@tag << "<option value=\"#{val}\"#{s1}#{s2}>#{label}</option>\n" | |
end | |
def optgroup(label, attrs=nil) | |
@tag << "<optgroup label=\"#{label}\">\n" | |
yield self | |
@tag << "</optgroup>\n" | |
end | |
private | |
def tag_attr_str(html) | |
case html | |
when nil ; nil | |
when String ; " #{html}" | |
when Hash ; html.collect {|k, v| " #{k}=\"#{v}\"" }.join | |
else ; raise ArgumentError.new("#{html.inspect}: String or Hash expected") | |
end | |
end | |
def selected?(val) | |
@value == val && ! val.nil? | |
end | |
end | |
## | |
## Helper class for multiple_select_tag() method | |
## | |
class MultipleSelectTag < SelectTag # :nodoc: | |
def build(name, values=nil, attrs=nil, &block) | |
set_values(values) | |
@tag = "<select name=\"#{name}\" multiple=\"multiple\"#{tag_attr_str(attrs)}>\n" | |
yield self | |
@tag << "</select>" | |
@tag | |
end | |
private | |
def set_values(values) | |
case values | |
when nil ; @values = {} | |
when Hash ; @values = values | |
when Enumerable ; @values = {} | |
values.each {|x| @values[x] = true } | |
else ; @values = {values => true} | |
end | |
end | |
def selected?(val) | |
@values.include?(val) | |
end | |
end | |
end | |
if __FILE__ == $0 | |
ARGV.concat(%w[-f nested -c]) # or %w[-D -f nested] | |
require 'rubygems' | |
require 'spec' | |
## describe のかわりに specs_of を、また it のかわりに spec を使う | |
Spec::DSL::Main.module_eval { alias specs_of describe } | |
Spec::Example::ExampleGroupMethods.module_eval { alias spec it } | |
Object.class_eval { include SelectTagHelper } | |
specs_of SelectTagHelper, "#select_tag()" do | |
girls = {'H'=>'Haruhi', 'M'=>'Mikuru', 'Y'=>'Yuki'} | |
boys = {'I'=>'Itsuki', 'K'=>'Kyon'} | |
expected1 = <<'END' | |
<select name="yome" class="yome"> | |
<option value="">Please select</option> | |
<option value="H" selected="selected">Haruhi</option> | |
<option value="M">Mikuru</option> | |
<option value="Y">Yuki</option> | |
</select> | |
END | |
expected1.chomp! | |
expected2 = <<'END' | |
<select name="yome" class="yome"> | |
<option value="">Please select</option> | |
<optgroup label="Girls"> | |
<option value="H" selected="selected">Haruhi</option> | |
<option value="M">Mikuru</option> | |
<option value="Y">Yuki</option> | |
</optgroup> | |
<optgroup label="Boys"> | |
<option value="I">Itsuki</option> | |
<option value="K">Kyon</option> | |
</optgroup> | |
</select> | |
END | |
expected2.chomp! | |
spec "<select> タグを生成する" do | |
html = select_tag('yome', nil, 'class="yome"') do |t| | |
t.option(nil, 'Please select') | |
girls.each {|k,v| t.option(k, v) } | |
end | |
html.should == expected1.sub(/ selected="selected"/, '') | |
end | |
spec "現在値が指定されたら <option> タグに 'selected' 属性を追加する" do | |
html = select_tag('yome', 'H', 'class="yome"') do |t| | |
t.option(nil, 'Please select') | |
girls.each {|k,v| t.option(k, v) } | |
end | |
html.should == expected1 | |
end | |
spec "<option> タグと同様に <optgroup> タグもサポートする" do | |
html = select_tag('yome', nil, 'class="yome"') do |t| | |
t.option(nil, 'Please select') | |
t.optgroup('Girls') do | |
girls.each {|k, v| t.option(k, v) } | |
end | |
t.optgroup('Boys') do | |
boys.each {|k, v| t.option(k, v) } | |
end | |
end | |
html.should == expected2.sub(/ selected="selected"/, '') | |
end | |
end | |
specs_of SelectTagHelper, "#multiple_selected()" do | |
girls = {'H'=>'Haruhi', 'M'=>'Mikuru', 'Y'=>'Yuki'} | |
boys = {'I'=>'Itsuki', 'K'=>'Kyon'} | |
expected1 = <<'END' | |
<select name="yome" multiple="multiple" class="yome"> | |
<option value="">Please select</option> | |
<option value="H" selected="selected">Haruhi</option> | |
<option value="M">Mikuru</option> | |
<option value="Y" selected="selected">Yuki</option> | |
</select> | |
END | |
expected1.chomp! | |
expected2 = <<'END' | |
<select name="yome" multiple="multiple" class="yome"> | |
<option value="">Please select</option> | |
<optgroup label="Girls"> | |
<option value="H" selected="selected">Haruhi</option> | |
<option value="M">Mikuru</option> | |
<option value="Y">Yuki</option> | |
</optgroup> | |
<optgroup label="Boys"> | |
<option value="I">Itsuki</option> | |
<option value="K" selected="selected">Kyon</option> | |
</optgroup> | |
</select> | |
END | |
expected2.chomp! | |
spec "'multiple' 属性つきの <select> タグを生成する" do | |
html = multiple_select_tag('yome', nil, 'class="yome"') do |t| | |
t.option(nil, 'Please select') | |
girls.each {|k, v| t.option(k, v) } | |
end | |
html.should == expected1.gsub(/ selected="selected"/, '') | |
end | |
spec "現在値が配列で指定されたら <option> タグに 'selected' 属性を追加する" do | |
html = multiple_select_tag('yome', ['H', 'Y'], 'class="yome"') do |t| | |
t.option(nil, 'Please select') | |
girls.each {|k, v| t.option(k, v) } | |
end | |
html.should == expected1 | |
end | |
spec "現在値がHashで指定されたら <option> タグに 'selected' 属性を追加する" do | |
html = multiple_select_tag('yome', {'H'=>true, 'Y'=>true}, 'class="yome"') do |t| | |
t.option(nil, 'Please select') | |
girls.each {|k, v| t.option(k, v) } | |
end | |
html.should == expected1 | |
end | |
spec "現在値が文字列や数値で指定されたら <option> タグに 'selected' 属性を追加する" do | |
html = multiple_select_tag('yome', 'Y', 'class="yome"') do |t| | |
t.option(nil, 'Please select') | |
girls.each {|k, v| t.option(k, v) } | |
end | |
html.should == expected1.sub(/ selected="selected"/, '') # remove the first one | |
end | |
spec "<option> タグだけでなく <optgroups> タグもサポートする" do | |
html = multiple_select_tag('yome', ['H', 'K'], 'class="yome"') do |t| | |
t.option(nil, 'Please select') | |
t.optgroup('Girls') do | |
girls.each {|k, v| t.option(k, v) } | |
end | |
t.optgroup('Boys') do | |
boys.each {|k, v| t.option(k, v) } | |
end | |
end | |
html.should == expected2 | |
end | |
end | |
require 'spec/autorun' | |
exit Spec::Runner::CommandLine.run | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment