From 2ece435fb345e388bba7e47f5c8bb49e765d1688 Mon Sep 17 00:00:00 2001 From: Jan Schulz-Hofen Date: Tue, 24 Mar 2015 17:18:07 +0100 Subject: [PATCH] Use HTML5 date input fields instead of text fields with jquery ui date pickers (includes feature detection and graceful fall back to jquery ui date picker if the browser does not support it) --- app/helpers/application_helper.rb | 2 +- app/views/custom_fields/formats/_date.html.erb | 2 +- app/views/issues/_attributes.html.erb | 4 +-- app/views/issues/bulk_edit.html.erb | 4 +-- app/views/timelog/_form.html.erb | 2 +- app/views/timelog/bulk_edit.html.erb | 2 +- app/views/versions/_form.html.erb | 2 +- lib/redmine/field_format.rb | 4 +-- public/javascripts/application.js | 37 ++++++++++++++++++++++---- 9 files changed, 43 insertions(+), 16 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 7fdb49c..f5c22dc 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1139,7 +1139,7 @@ module ApplicationHelper def calendar_for(field_id) include_calendar_headers_tags - javascript_tag("$(function() { $('##{field_id}').datepicker(datepickerOptions); });") + javascript_tag("$(function() { $('##{field_id}').datepickerFallback(datepickerOptions); });") end def include_calendar_headers_tags diff --git a/app/views/custom_fields/formats/_date.html.erb b/app/views/custom_fields/formats/_date.html.erb index df3ba07..b52c063 100644 --- a/app/views/custom_fields/formats/_date.html.erb +++ b/app/views/custom_fields/formats/_date.html.erb @@ -1,3 +1,3 @@ -

<%= f.text_field(:default_value, :size => 10) %>

+

<%= f.date_field(:default_value, :value => @custom_field.default_value, :size => 10) %>

<%= calendar_for('custom_field_default_value') %>

<%= f.text_field :url_pattern, :size => 50, :label => :label_link_values_to %>

diff --git a/app/views/issues/_attributes.html.erb b/app/views/issues/_attributes.html.erb index 61ffa8a..a4d2557 100644 --- a/app/views/issues/_attributes.html.erb +++ b/app/views/issues/_attributes.html.erb @@ -48,7 +48,7 @@ <% if @issue.safe_attribute? 'start_date' %>

- <%= f.text_field(:start_date, :size => 10, :disabled => !@issue.leaf?, + <%= f.date_field(:start_date, :size => 10, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('start_date')) %> <%= calendar_for('issue_start_date') if @issue.leaf? %>

@@ -56,7 +56,7 @@ <% if @issue.safe_attribute? 'due_date' %>

- <%= f.text_field(:due_date, :size => 10, :disabled => !@issue.leaf?, + <%= f.date_field(:due_date, :size => 10, :disabled => !@issue.leaf?, :required => @issue.required_attribute?('due_date')) %> <%= calendar_for('issue_due_date') if @issue.leaf? %>

diff --git a/app/views/issues/bulk_edit.html.erb b/app/views/issues/bulk_edit.html.erb index b4ec3d5..b1d1c5e 100644 --- a/app/views/issues/bulk_edit.html.erb +++ b/app/views/issues/bulk_edit.html.erb @@ -147,7 +147,7 @@ <% if @safe_attributes.include?('start_date') %>

- <%= text_field_tag 'issue[start_date]', '', :value => @issue_params[:start_date], :size => 10 %><%= calendar_for('issue_start_date') %> + <%= date_field_tag 'issue[start_date]', '', :value => @issue_params[:start_date], :size => 10 %><%= calendar_for('issue_start_date') %>

<% end %> @@ -155,7 +155,7 @@ <% if @safe_attributes.include?('due_date') %>

- <%= text_field_tag 'issue[due_date]', '', :value => @issue_params[:due_date], :size => 10 %><%= calendar_for('issue_due_date') %> + <%= date_field_tag 'issue[due_date]', '', :value => @issue_params[:due_date], :size => 10 %><%= calendar_for('issue_due_date') %>

<% end %> diff --git a/app/views/timelog/_form.html.erb b/app/views/timelog/_form.html.erb index 9b07801..f3d653d 100644 --- a/app/views/timelog/_form.html.erb +++ b/app/views/timelog/_form.html.erb @@ -15,7 +15,7 @@ <%= f.text_field :issue_id, :size => 6 %> <%= "#{@time_entry.issue.tracker.name} ##{@time_entry.issue.id}: #{@time_entry.issue.subject}" if @time_entry.issue %>

-

<%= f.text_field :spent_on, :size => 10, :required => true %><%= calendar_for('time_entry_spent_on') %>

+

<%= f.date_field :spent_on, :size => 10, :required => true %><%= calendar_for('time_entry_spent_on') %>

<%= f.text_field :hours, :size => 6, :required => true %>

<%= f.text_field :comments, :size => 100, :maxlength => 255 %>

<%= f.select :activity_id, activity_collection_for_select_options(@time_entry), :required => true %>

diff --git a/app/views/timelog/bulk_edit.html.erb b/app/views/timelog/bulk_edit.html.erb index 8f6c674..640f7d8 100644 --- a/app/views/timelog/bulk_edit.html.erb +++ b/app/views/timelog/bulk_edit.html.erb @@ -18,7 +18,7 @@

- <%= text_field :time_entry, :spent_on, :size => 10 %><%= calendar_for('time_entry_spent_on') %> + <%= date_field :time_entry, :spent_on, :size => 10 %><%= calendar_for('time_entry_spent_on') %>

diff --git a/app/views/versions/_form.html.erb b/app/views/versions/_form.html.erb index db84f07..3d8ecd4 100644 --- a/app/views/versions/_form.html.erb +++ b/app/views/versions/_form.html.erb @@ -6,7 +6,7 @@

<%= f.text_field :description, :size => 60 %>

<%= f.select :status, Version::VERSION_STATUSES.collect {|s| [l("version_status_#{s}"), s]} %>

<%= f.text_field :wiki_page_title, :label => :label_wiki_page, :size => 60, :disabled => @project.wiki.nil? %>

-

<%= f.text_field :effective_date, :size => 10 %><%= calendar_for('version_effective_date') %>

+

<%= f.date_field :effective_date, :size => 10 %><%= calendar_for('version_effective_date') %>

<%= f.select :sharing, @version.allowed_sharings.collect {|v| [format_version_sharing(v), v]} %>

<% @version.custom_field_values.each do |value| %> diff --git a/lib/redmine/field_format.rb b/lib/redmine/field_format.rb index 8cb3bc4..ad48ece 100644 --- a/lib/redmine/field_format.rb +++ b/lib/redmine/field_format.rb @@ -420,12 +420,12 @@ module Redmine end def edit_tag(view, tag_id, tag_name, custom_value, options={}) - view.text_field_tag(tag_name, custom_value.value, options.merge(:id => tag_id, :size => 10)) + + view.date_field_tag(tag_name, custom_value.value, options.merge(:id => tag_id, :size => 10)) + view.calendar_for(tag_id) end def bulk_edit_tag(view, tag_id, tag_name, custom_field, objects, value, options={}) - view.text_field_tag(tag_name, value, options.merge(:id => tag_id, :size => 10)) + + view.date_field_tag(tag_name, value, options.merge(:id => tag_id, :size => 10)) + view.calendar_for(tag_id) + bulk_clear_tag(view, tag_id, tag_name, custom_field, value) end diff --git a/public/javascripts/application.js b/public/javascripts/application.js index a3ead6b..bd6c1aa 100644 --- a/public/javascripts/application.js +++ b/public/javascripts/application.js @@ -185,12 +185,12 @@ function buildFilterRow(field, operator, values) { case "date": case "date_past": tr.find('td.values').append( - '' + - ' ' + + '' + + ' ' + ' '+labelDayPlural+'' ); - $('#values_'+fieldId+'_1').val(values[0]).datepicker(datepickerOptions); - $('#values_'+fieldId+'_2').val(values[1]).datepicker(datepickerOptions); + $('#values_'+fieldId+'_1').val(values[0]).datepickerFallback(datepickerOptions); + $('#values_'+fieldId+'_2').val(values[1]).datepickerFallback(datepickerOptions); $('#values_'+fieldId).val(values[0]); break; case "string": @@ -554,7 +554,7 @@ function beforeShowDatePicker(input, inst) { } break; } - $(input).datepicker("option", "defaultDate", default_date); + $(input).datepickerFallback("option", "defaultDate", default_date); } function initMyPageSortable(list, url) { @@ -640,6 +640,33 @@ function toggleDisabledOnChange() { function toggleDisabledInit() { $('input[data-disables], input[data-enables]').each(toggleDisabledOnChange); } + +(function ( $ ) { + + // detect if native date input is supported + var nativeDateInputSupported = true; + + var input = document.createElement('input'); + input.setAttribute('type','date'); + if (input.type === 'text') { + nativeDateInputSupported = false; + } + + var notADateValue = 'not-a-date'; + input.setAttribute('value', notADateValue); + if (input.value === notADateValue) { + nativeDateInputSupported = false; + } + + $.fn.datepickerFallback = function( options ) { + if (nativeDateInputSupported) { + return this; + } else { + return this.datepicker( options ); + } + }; +}( jQuery )); + $(document).ready(function(){ $('#content').on('change', 'input[data-disables], input[data-enables]', toggleDisabledOnChange); toggleDisabledInit(); -- 1.9.5 (Apple Git-50.3)