From 65fd13613b34cd4b58a2640ae53bd385f3be04b8 Mon Sep 17 00:00:00 2001 From: Sam Oliver Date: Mon, 7 Jul 2008 12:24:24 +0100 Subject: [PATCH] Added :prompt option to date helpers Set :prompt to true (for a generic prompt) or a prompt string. For date helpers with mutiple fields, specify the prompt you wish to set in a hash. This prepends an option with a generic prompt (Day, Month, Year, Hour, Minute, Seconds) or the given prompt string. Example: date_select("post", "written_on", :prompt=>{:day=>'Select day', :month=>'Select month', :year=>'Select year'}) This is similar to the :prompt option in collection_select --- actionpack/lib/action_view/helpers/date_helper.rb | 77 +++++- actionpack/test/template/date_helper_test.rb | 318 +++++++++++++++++++++ 2 files changed, 391 insertions(+), 4 deletions(-) diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb index 1aee9ef..27282c6 100755 --- a/actionpack/lib/action_view/helpers/date_helper.rb +++ b/actionpack/lib/action_view/helpers/date_helper.rb @@ -11,6 +11,12 @@ module ActionView # * :include_blank - set to true if it should be possible to set an empty date. # * :discard_type - set to true if you want to discard the type part of the select name. If set to true, the select_month # method would use simply "date" (which can be overwritten using :prefix) instead of "date[month]". + # * :prompt - set to true (for a generic prompt) or a prompt string. For date helpers with mutiple fields, specify the prompt + # you wish to set in a hash. This prepends an option with a generic prompt (Day, Month, Year, Hour, Minute, Seconds) or the given prompt + # string. + # + # Example: + # date_select("post", "written_on", :prompt=>{:day=>'Select day', :month=>'Select month', :year=>'Select year'}) module DateHelper include ActionView::Helpers::TagHelper DEFAULT_PREFIX = 'date' unless const_defined?('DEFAULT_PREFIX') @@ -148,6 +154,11 @@ module ActionView # # that will have a default day of 20. # date_select("credit_card", "bill_due", :default => { :day => 20 }) # + # # Generates a datetime select with a custom prompt. Use :prompt=>true for generic prompts. + # date_select("post", "written_on", :prompt=>{:day=>'Choose day, :month=>'Choose month', :year=>'Choose year'}) + # date_select("post", "written_on", :prompt=>{:hours=>true) # generic prompt for hours + # date_select("post", "written_on", :prompt=>true) # generic prompts for all + # # The selects are prepared for multi-parameter assignment to an Active Record object. # # Note: If the day is not included as an option but the month is, the day will be set to the 1st to ensure that all month @@ -183,6 +194,11 @@ module ActionView # # You can set the :minute_step to 15 which will give you: 00, 15, 30 and 45. # time_select 'game', 'game_time', {:minute_step => 15} # + # # Generates a datetime select with a custom prompt. Use :prompt=>true for generic prompts. + # time_select("post", "written_on", :prompt=>{:hour=>'Choose hour', :minute=>'Choose minute', :second=>'Choose seconds'}) + # time_select("post", "written_on", :prompt=>{:hour=>true) # generic prompt for hours + # time_select("post", "written_on", :prompt=>true) # generic prompts for all + # # The selects are prepared for multi-parameter assignment to an Active Record object. # # Note: If the day is not included as an option but the month is, the day will be set to the 1st to ensure that all month @@ -212,6 +228,11 @@ module ActionView # # attribute. # datetime_select("post", "written_on", :discard_type => true) # + # # Generates a datetime select with a custom prompt. Use :prompt=>true for generic prompts. + # datetime_select("post", "written_on", :prompt=>{:day=>'Choose day', :month=>'Choose month', :year=>'Choose year'}) + # datetime_select("post", "written_on", :prompt=>{:hour=>true) # generic prompt for hours + # datetime_select("post", "written_on", :prompt=>true) # generic prompts for all + # # The selects are prepared for multi-parameter assignment to an Active Record object. def datetime_select(object_name, method, options = {}, html_options = {}) InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_datetime_select_tag(options, html_options) @@ -250,6 +271,11 @@ module ActionView # # prefixed with 'payday' rather than 'date' # select_datetime(my_date_time, :prefix => 'payday') # + # # Generates a datetime select with a custom prompt. Use :prompt=>true for generic prompts. + # select_datetime(my_date_time, :prompt=>{:day=>'Choose day', :month=>'Choose month', :year=>'Choose year'}) + # select_datetime(my_date_time, :prompt=>{:hour=>true) # generic prompt for hours + # select_datetime(my_date_time, :prompt=>true) # generic prompts for all + # def select_datetime(datetime = Time.current, options = {}, html_options = {}) separator = options[:datetime_separator] || '' select_date(datetime, options, html_options) + separator + select_time(datetime, options, html_options) @@ -283,6 +309,11 @@ module ActionView # # prefixed with 'payday' rather than 'date' # select_datetime(my_date_time, :prefix => 'payday') # + # # Generates a date select with a custom prompt. Use :prompt=>true for generic prompts. + # select_date(my_date, :prompt=>{:day=>'Choose day', :month=>'Choose month', :year=>'Choose year'}) + # select_date(my_date, :prompt=>{:month=>true) # generic prompt for month + # select_date(my_date, :prompt=>true) # generic prompts for all + # def select_date(date = Date.current, options = {}, html_options = {}) options[:order] ||= [] [:year, :month, :day].each { |o| options[:order].push(o) unless options[:order].include?(o) } @@ -321,8 +352,14 @@ module ActionView # # separated by ':' and includes an input for seconds # select_time(my_time, :time_separator => ':', :include_seconds => true) # + # # Generates a time select with a custom prompt. Use :prompt=>true for generic prompts + # select_time(my_time, :prompt=>{:hours=>'Choose hours', :minutes=>'Choose minutes'}) + # select_time(my_time, :prompt=>{:hours=>true}) # prompt for hours only + # select_time(my_time, :prompt=>true) # prompt for all + # def select_time(datetime = Time.current, options = {}, html_options = {}) separator = options[:time_separator] || '' + select_time = '' select_hour(datetime, options, html_options) + separator + select_minute(datetime, options, html_options) + (options[:include_seconds] ? separator + select_second(datetime, options, html_options) : '') end @@ -392,7 +429,7 @@ module ActionView minute_options << "\n" end select_html(options[:field_name] || 'minute', minute_options.join, options, html_options) - end + end end # Returns a select tag with options for each of the hours 0 through 23 with the current hour selected. @@ -412,6 +449,10 @@ module ActionView # # that is named 'stride' rather than 'second' # select_minute(my_time, :field_name => 'stride') # + # # Generates a select field for minutes with a custom prompt. Use :prompt=>true for a + # # generic prompt. + # select_minute(14, :prompt=>'Choose minutes') + # def select_hour(datetime, options = {}, html_options = {}) val = datetime ? (datetime.kind_of?(Fixnum) ? datetime : datetime.hour) : '' if options[:use_hidden] @@ -446,8 +487,13 @@ module ActionView # # that is named 'due' rather than 'day' # select_day(my_time, :field_name => 'due') # + # # Generates a select field for days with a custom prompt. Use :prompt=>true for a + # # generic prompt. + # select_day(5, :prompt=>'Choose day') + # def select_day(date, options = {}, html_options = {}) val = date ? (date.kind_of?(Fixnum) ? date : date.day) : '' + if options[:use_hidden] hidden_html(options[:field_name] || 'day', val, options) else @@ -497,6 +543,10 @@ module ActionView # # will use keys like "Januar", "Marts." # select_month(Date.today, :use_month_names => %w(Januar Februar Marts ...)) # + # # Generates a select field for months that has a custom prompt. Use + # :prompt=>true for a generic prompt + # select_month(Date.today, :prompt=>'Choose month') + # def select_month(date, options = {}, html_options = {}) val = date ? (date.kind_of?(Fixnum) ? date : date.month) : '' if options[:use_hidden] @@ -543,8 +593,8 @@ module ActionView # select_year(Date.today, :start_year => 2005, :end_year => 1900) # # # Generates a select field for years that defaults to the year 2006 that - # # has ascending year values - # select_year(2006, :start_year => 2000, :end_year => 2010) + # # has ascending year values, with a custom prompt + # select_year(2006, :start_year => 2000, :end_year => 2010, :prompt=>'Choose year') # def select_year(date, options = {}, html_options = {}) val = date ? (date.kind_of?(Fixnum) ? date : date.year) : '' @@ -575,6 +625,7 @@ module ActionView select_options.merge!(:disabled => 'disabled') if options[:disabled] select_options.merge!(select_tag_options) unless select_tag_options.empty? select_html = "\n" + select_html << prompt_option_tag(type, options) select_html << content_tag(:option, '', :value => '') + "\n" if options[:include_blank] select_html << html_options.to_s content_tag(:select, select_html, select_options) + "\n" @@ -593,6 +644,24 @@ module ActionView def leading_zero_on_single_digits(number) number > 9 ? number : "0#{number}" end + + def prompt_option_tag(type, options) + default_options = {:year=>false, :month=>false, :day=>false, :hour=>false, :minute=>false, :second=>false} + default_prompts = {:year=>'Year', :month=>'Month', :day=>'Day', :hour=>'Hour', :minute=>'Minute', :second=>'Seconds'} + options[:prompt] ||= default_options + + case options[:prompt] + when Hash + prompt = default_options.merge(options[:prompt])[type.to_sym] + when String + prompt = options[:prompt] + else + prompt = default_prompts[type.to_sym] + end + + prompt ? content_tag(:option, prompt, :value => '') + "\n" : '' + end + end class InstanceTag #:nodoc: @@ -615,7 +684,7 @@ module ActionView defaults = { :discard_type => true } options = defaults.merge(options) datetime = value(object) - datetime ||= default_time_from_options(options[:default]) unless options[:include_blank] + datetime ||= default_time_from_options(options[:default]) unless options[:include_blank] || options[:prompt] position = { :year => 1, :month => 2, :day => 3, :hour => 4, :minute => 5, :second => 6 } diff --git a/actionpack/test/template/date_helper_test.rb b/actionpack/test/template/date_helper_test.rb index a435235..359063f 100755 --- a/actionpack/test/template/date_helper_test.rb +++ b/actionpack/test/template/date_helper_test.rb @@ -153,6 +153,22 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, select_day(16, {}, :class => 'selector') end + def test_select_day_with_default_prompt + expected = %(\n" + + assert_dom_equal expected, select_day(16, :prompt=>true) + end + + def test_select_day_with_custom_prompt + expected = %(\n" + + assert_dom_equal expected, select_day(16, :prompt=>'Choose day') + end + def test_select_month expected = %(\n) + expected << %(\n\n\n\n\n\n\n\n\n\n\n\n\n) + expected << "\n" + + assert_dom_equal expected, select_month(8, :prompt=>true) + end + + def test_select_month_with_custom_prompt + expected = %(\n" + + assert_dom_equal expected, select_month(8, :prompt=>'Choose month') + end + def test_select_year expected = %(\n" + + assert_dom_equal expected, select_year(nil, :start_year => 2003, :end_year => 2005, :prompt=>true) + end + + def test_select_year_with_custom_prompt + expected = %(\n" + + assert_dom_equal expected, select_year(nil, :start_year => 2003, :end_year => 2005, :prompt=>'Choose year') + end + def test_select_hour expected = %(\n) + expected << %(\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n) + expected << "\n" + + assert_dom_equal expected, select_hour(Time.mktime(2003, 8, 16, 8, 4, 18), :prompt=>true) + end + + def test_select_hour_with_custom_prompt + expected = %(\n" + + assert_dom_equal expected, select_hour(Time.mktime(2003, 8, 16, 8, 4, 18), :prompt=>'Choose hour') + end + def test_select_minute expected = %(\n) + expected << %(\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n) + expected << "\n" + + assert_dom_equal expected, select_minute(Time.mktime(2003, 8, 16, 8, 4, 18), :prompt=>true) + end + + def test_select_minute_with_custom_prompt + expected = %(\n" + + assert_dom_equal expected, select_minute(Time.mktime(2003, 8, 16, 8, 4, 18), :prompt=>'Choose minute') + end + def test_select_second expected = %(\n) + expected << %(\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n) + expected << "\n" + + assert_dom_equal expected, select_second(Time.mktime(2003, 8, 16, 8, 4, 18), :prompt=>true) + end + + def test_select_second_with_custom_prompt + expected = %(\n" + + assert_dom_equal expected, select_second(Time.mktime(2003, 8, 16, 8, 4, 18), :prompt=>'Choose seconds') + end + def test_select_date expected = %(\n) + expected << %(\n\n\n\n) + expected << "\n" + + expected << %(\n" + + expected << %(\n" + + expected << %(\n" + + expected << %(\n" + + assert_dom_equal expected, select_datetime(Time.mktime(2003, 8, 16, 8, 4, 18), :start_year => 2003, :end_year => 2005, :prefix => "date[first]", :prompt=>true) + end + + def test_select_datetime_with_custom_prompt + + expected = %(\n" + + expected << %(\n" + + expected << %(\n" + + expected << %(\n" + + expected << %(\n" + + assert_dom_equal expected, select_datetime(Time.mktime(2003, 8, 16, 8, 4, 18), :start_year => 2003, :end_year => 2005, :prefix => "date[first]", :prompt=>{:day=>'Choose day', :month=>'Choose month', :year=>'Choose year', :hour=>'Choose hour', :minute=>'Choose minute'}) + end + def test_select_time expected = %(\n) + expected << %(\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n) + expected << "\n" + + expected << %(\n" + + expected << %(\n" + + assert_dom_equal expected, select_time(Time.mktime(2003, 8, 16, 8, 4, 18), :include_seconds => true, :prompt=>true) + end + + def test_select_time_with_custom_prompt + + expected = %(\n" + + expected << %(\n" + + expected << %(\n" + + assert_dom_equal expected, select_time(Time.mktime(2003, 8, 16, 8, 4, 18), :prompt=>true, :include_seconds=>true, :prompt=>{:hour=>'Choose hour', :minute=>'Choose minute', :second=>'Choose seconds'}) + end + uses_mocha 'TestDatetimeAndTimeSelectUseTimeCurrentAsDefault' do def test_select_datetime_uses_time_current_as_default time = stub(:year => 2004, :month => 6, :day => 15, :hour => 16, :min => 35, :sec => 0) @@ -1183,6 +1361,46 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, _erbout end + def test_date_select_with_default_prompt + @post = Post.new + @post.written_on = Date.new(2004, 6, 15) + + expected = %{\n" + + expected << %{\n" + + expected << %{\n" + + assert_dom_equal expected, date_select("post", "written_on", :prompt=>true) + end + + def test_date_select_with_custom_prompt + @post = Post.new + @post.written_on = Date.new(2004, 6, 15) + + expected = %{\n" + + expected << %{\n" + + expected << %{\n" + + assert_dom_equal expected, date_select("post", "written_on", :prompt=>{:year=>'Choose year', :month=>'Choose month', :day=>'Choose day'}) + end + def test_time_select @post = Post.new @post.written_on = Time.local(2004, 6, 15, 15, 16, 35) @@ -1269,6 +1487,48 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, _erbout end + def test_time_select_with_default_prompt + @post = Post.new + @post.written_on = Time.local(2004, 6, 15, 15, 16, 35) + + expected = %{\n} + expected << %{\n} + expected << %{\n} + + expected << %(\n" + expected << " : " + expected << %(\n" + + assert_dom_equal expected, time_select("post", "written_on", :prompt=>true) + end + + def test_time_select_with_custom_prompt + @post = Post.new + @post.written_on = Time.local(2004, 6, 15, 15, 16, 35) + + expected = %{\n} + expected << %{\n} + expected << %{\n} + + expected << %(\n" + expected << " : " + expected << %(\n" + + assert_dom_equal expected, time_select("post", "written_on", :prompt=>{:hour=>'Choose hour', :minute=>'Choose minute'}) + end + def test_datetime_select @post = Post.new @post.updated_at = Time.local(2004, 6, 15, 16, 35) @@ -1759,6 +2019,64 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, datetime_select("post", "updated_at", {}, :class => 'selector') end + def test_datetime_select_with_default_prompt + @post = Post.new + @post.updated_at = Time.local(2004, 6, 15, 16, 35) + + expected = %{\n" + + expected << %{\n" + + expected << %{\n" + + expected << " — " + + expected << %{\n" + expected << " : " + expected << %{\n" + + assert_dom_equal expected, datetime_select("post", "updated_at", :prompt=>true) + end + + def test_datetime_select_with_custom_prompt + @post = Post.new + @post.updated_at = Time.local(2004, 6, 15, 16, 35) + + expected = %{\n" + + expected << %{\n" + + expected << %{\n" + + expected << " — " + + expected << %{\n" + expected << " : " + expected << %{\n" + + assert_dom_equal expected, datetime_select("post", "updated_at", :prompt=>{:year=>'Choose year', :month=>'Choose month', :day=>'Choose day', :hour=>'Choose hour', :minute=>'Choose minute'}) + end + uses_mocha 'TestInstanceTagDefaultTimeFromOptions' do def test_instance_tag_default_time_from_options_uses_time_current_as_default_when_hash_passed_as_arg dummy_instance_tag = ActionView::Helpers::InstanceTag.new(1,2,3) -- 1.6.0.2