From f8a227d45bb39bba767a62b225b660abd4d2e14e Mon Sep 17 00:00:00 2001 From: Sam Oliver Date: Sun, 21 Dec 2008 19:46:33 +0000 Subject: [PATCH] Added prompt options to date helpers --- actionpack/lib/action_view/helpers/date_helper.rb | 83 ++++++- actionpack/test/template/date_helper_test.rb | 318 +++++++++++++++++++++ 2 files changed, 399 insertions(+), 2 deletions(-) diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb index a04bb8c..2c062c1 100644 --- a/actionpack/lib/action_view/helpers/date_helper.rb +++ b/actionpack/lib/action_view/helpers/date_helper.rb @@ -136,6 +136,10 @@ module ActionView # dates. # * :default - Set a default date if the affected date isn't set or is nil. # * :disabled - Set to true if you want show the select fields as disabled. + # * :prompt - Set to true (for a generic prompt), a prompt string or a hash of prompt strings + # for :year, :month, :day, :hour, :minute and :second. + # Setting this option prepends a select option with a generic prompt (Day, Month, Year, Hour, Minute, Seconds) + # or the given prompt string. # # If anything is passed in the +html_options+ hash it will be applied to every select tag in the set. # @@ -171,6 +175,9 @@ module ActionView # # that will have a default day of 20. # date_select("credit_card", "bill_due", :default => { :day => 20 }) # + # # Generates a date select with custom prompts + # date_select("post", "written_on", :prompt => { :day=>'Select day', :month=>'Select month', :year=>'Select year' }) + # # 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 @@ -210,6 +217,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} # + # # Creates a time select tag 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 @@ -241,6 +253,11 @@ module ActionView # # as the written_on 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, options.delete(:object)).to_datetime_select_tag(options, html_options) @@ -285,6 +302,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 = {}) DateTimeSelector.new(datetime, options, html_options).select_datetime end @@ -321,6 +343,11 @@ module ActionView # # prefixed with 'payday' rather than 'date' # select_date(my_date, :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 => {:hour => true}) # generic prompt for hours + # select_date(my_date, :prompt => true) # generic prompts for all + # def select_date(date = Date.current, options = {}, html_options = {}) DateTimeSelector.new(date, options, html_options).select_date end @@ -352,6 +379,11 @@ 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 => {:day => 'Choose day', :month => 'Choose month', :year => 'Choose year'}) + # select_time(my_time, :prompt => {:hour => true}) # generic prompt for hours + # select_time(my_time, :prompt => true) # generic prompts for all + # def select_time(datetime = Time.current, options = {}, html_options = {}) DateTimeSelector.new(datetime, options, html_options).select_time end @@ -373,6 +405,10 @@ module ActionView # # that is named 'interval' rather than 'second' # select_second(my_time, :field_name => 'interval') # + # # Generates a select field for seconds with a custom prompt. Use :prompt=>true for a + # # generic prompt. + # select_minute(14, :prompt => 'Choose seconds') + # def select_second(datetime, options = {}, html_options = {}) DateTimeSelector.new(datetime, options, html_options).select_second end @@ -395,6 +431,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_minute(datetime, options = {}, html_options = {}) DateTimeSelector.new(datetime, options, html_options).select_minute end @@ -416,6 +456,10 @@ module ActionView # # that is named 'stride' rather than 'second' # select_hour(my_time, :field_name => 'stride') # + # # Generates a select field for hours with a custom prompt. Use :prompt => true for a + # # generic prompt. + # select_hour(13, :prompt=>'Choose hour') + # def select_hour(datetime, options = {}, html_options = {}) DateTimeSelector.new(datetime, options, html_options).select_hour end @@ -437,6 +481,10 @@ 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 = {}) DateTimeSelector.new(date, options, html_options).select_day end @@ -475,6 +523,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 with a custom prompt. Use :prompt=>true for a + # # generic prompt. + # select_month(14, :prompt => 'Choose month') + # def select_month(date, options = {}, html_options = {}) DateTimeSelector.new(date, options, html_options).select_month end @@ -502,6 +554,10 @@ module ActionView # # has ascending year values # select_year(2006, :start_year => 2000, :end_year => 2010) # + # # Generates a select field for years with a custom prompt. Use :prompt=>true for a + # # generic prompt. + # select_year(14, :prompt=>'Choose year') + # def select_year(date, options = {}, html_options = {}) DateTimeSelector.new(date, options, html_options).select_year end @@ -515,7 +571,11 @@ module ActionView POSITION = { :year => 1, :month => 2, :day => 3, :hour => 4, :minute => 5, :second => 6 }.freeze unless const_defined?('POSITION') - + + DEFAULT_PROMPTS = { + :year=>'Year', :month=>'Month', :day=>'Day', :hour=>'Hour', :minute=>'Minute', :second=>'Seconds' + }.freeze unless const_defined?('DEFAULT_PROMPTS') + def initialize(datetime, options = {}, html_options = {}) @options = options.dup @html_options = html_options.dup @@ -764,11 +824,30 @@ module ActionView select_html = "\n" select_html << content_tag(:option, '', :value => '') + "\n" if @options[:include_blank] + select_html << prompt_option_tag(type, @options[:prompt]) + "\n" if @options[:prompt] select_html << select_options_as_html.to_s content_tag(:select, select_html, select_options) + "\n" end - + + # Builds a prompt option tag with supplied options or from default options + # prompt_option_tag(:month, :prompt => 'Select month') + # => "" + def prompt_option_tag(type, options) + default_options = {:year=>false, :month=>false, :day=>false, :hour=>false, :minute=>false, :second=>false} + + case options + when Hash + prompt = default_options.merge(options)[type.to_sym] + when String + prompt = options + else + prompt = ActionView::Helpers::DateTimeSelector::DEFAULT_PROMPTS[type.to_sym] + end + + prompt ? content_tag(:option, prompt, :value => '') : '' + end + # Builds hidden input tag for date part and value # build_hidden(:year, 2008) # => "" diff --git a/actionpack/test/template/date_helper_test.rb b/actionpack/test/template/date_helper_test.rb index 49ba140..a4ab6c5 100644 --- 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 def test_date_select @post = Post.new @@ -1276,6 +1454,46 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, date_select("post", "written_on", { :date_separator => " / " }) 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 @@ -1402,6 +1620,48 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, time_select("post", "written_on", { :time_separator => " - ", :include_seconds => true }) 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 @@ -1525,6 +1785,64 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, datetime_select("post", "updated_at", { :date_separator => " / ", :datetime_separator => " , ", :time_separator => " - ", :include_seconds => true }) 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 def test_date_select_with_zero_value_and_no_start_year expected = %(