Fixing DateTime localization issues

1- Some DateTime editors were not using the expected localization formats
2- The DateTime picker was not correctly initialized with localized formats
3- The TimePicker could not handle different am/pm designators
4- The drivers could not accept different designators

Now the am/pm designators used to parse the time and to render it are the one
from WorkContext.CurrentCulture, which means that is zn-TW is used as the
default culture, times will be displayed with "chinese chars here" instead of
AM, and will expect it when parsing it.

--HG--
branch : 1.4.x
This commit is contained in:
Sebastien Ros
2012-05-07 14:50:25 -07:00
parent 2f724c5239
commit b8031b68bd
20 changed files with 1404 additions and 504 deletions

View File

@@ -5,4 +5,4 @@ cfc264d41c1d299c104d76c5032d8ffee3047dcd src/Orchard.Web/Modules/Orchard.Rules
0b96793c3737e50863270c24debf6d44065b73bb src/Orchard.Web/Modules/Orchard.Tokens
4ed51e0e76c2aacc2de90ce9984fd00cfdfae2ce src/orchard.web/Modules/Orchard.Alias
0e660c8cfbfb5217abfb7cf6adf6f2cf484174d6 src/orchard.web/Modules/Orchard.Projections
0ce46c4e39390472b82459007c0e5a05c18d22d8 src/orchard.web/modules/Orchard.Fields
bbd96451a4e80b4564dbb23ab947711feed3b5d2 src/orchard.web/modules/Orchard.Fields

View File

@@ -312,6 +312,7 @@
$(MSBuildProjectDirectory)\**\*.user;
$(MSBuildProjectDirectory)\**\*.patch;
$(MSBuildProjectDirectory)\**\*.hg*\**\*;
$(LibFolder)\nunit\addins\**\*;
" />
<Zip-Stage Include="$(StageFolder)\**\*" />

View File

@@ -9,7 +9,6 @@ using Orchard.Localization;
namespace Orchard.Core.Common.DateEditor {
public class DateEditorDriver : ContentPartDriver<CommonPart> {
private readonly IDateTimeLocalization _dateTimeLocalization;
private readonly Lazy<CultureInfo> _cultureInfo;
public DateEditorDriver(
@@ -62,8 +61,8 @@ namespace Orchard.Core.Common.DateEditor {
// date and time are formatted using the same patterns as DateTimePicker is, preventing other cultures issues
var createdLocal = TimeZoneInfo.ConvertTimeFromUtc(part.CreatedUtc.Value, Services.WorkContext.CurrentTimeZone);
model.CreatedDate = createdLocal.ToString(_dateTimeLocalization.ShortDateFormat.Text);
model.CreatedTime = createdLocal.ToString(_dateTimeLocalization.ShortTimeFormat.Text);
model.CreatedDate = createdLocal.ToString(_dateTimeLocalization.ShortDateFormat.Text, _cultureInfo.Value);
model.CreatedTime = createdLocal.ToString(_dateTimeLocalization.ShortTimeFormat.Text, _cultureInfo.Value);
}
}
@@ -77,7 +76,7 @@ namespace Orchard.Core.Common.DateEditor {
var dateTimeFormat = _dateTimeLocalization.ShortDateFormat + " " + _dateTimeLocalization.ShortTimeFormat;
// use current culture
if (DateTime.TryParseExact(parseDateTime, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out createdUtc)) {
if (DateTime.TryParseExact(parseDateTime, dateTimeFormat, _cultureInfo.Value, DateTimeStyles.None, out createdUtc)) {
// the date time is entered locally for the configured timezone
part.CreatedUtc = TimeZoneInfo.ConvertTimeToUtc(createdUtc, Services.WorkContext.CurrentTimeZone);

View File

@@ -11,4 +11,10 @@ fieldset.createdutc-datetime input {
padding:1px;
text-align:center;
color:#666;
}
input#DateEditor_CreatedDate {
width:10em;
}
input#DateEditor_CreatedTime {
width:7em;
}

View File

@@ -1,11 +1,11 @@
@model Orchard.Core.Common.DateEditor.DateEditorViewModel
@{
var DateEditor = Model;
Script.Require("jQueryUtils_TimePicker");
Script.Require("jQueryUI_DatePicker");
Script.Require("jQueryUI_TimePicker");
Style.Require("Common_DatePicker");
Style.Require("jQueryUtils_TimePicker");
Style.Require("jQueryUI_DatePicker");
Style.Require("jQueryUI_DatePicker");
Style.Require("jQueryUI_TimePicker");
}
<fieldset class="createdutc-datetime">
@Html.LabelFor(m => DateEditor.CreatedDate, T("Created On"))
@@ -38,7 +38,7 @@
}
});
$('#@Html.FieldIdFor(m => DateEditor.CreatedDate)').datepicker({ showAnim: "" });
$('#@Html.FieldIdFor(m => DateEditor.CreatedTime)').timepickr({ showAnim: "" });
$('#@Html.FieldIdFor(m => DateEditor.CreatedTime)').timepicker({ stepMinute: 5});
})
//]]>
</script>

View File

@@ -6,12 +6,14 @@ using Orchard.DisplayManagement;
using Orchard.Localization;
using Orchard.Mvc.Html;
using Orchard.Services;
using System.Globalization;
namespace Orchard.Core.Shapes {
public class DateTimeShapes : IDependency {
private readonly IClock _clock;
private readonly IDateTimeLocalization _dateTimeLocalization;
private readonly IWorkContextAccessor _workContextAccessor;
private readonly Lazy<CultureInfo> _cultureInfo;
public DateTimeShapes(
IClock clock,
@@ -22,6 +24,8 @@ namespace Orchard.Core.Shapes {
_dateTimeLocalization = dateTimeLocalization;
_workContextAccessor = workContextAccessor;
T = NullLocalizer.Instance;
_cultureInfo = new Lazy<CultureInfo>(() => CultureInfo.GetCultureInfo(_workContextAccessor.GetContext().CurrentCulture));
}
public Localizer T { get; set; }
@@ -52,7 +56,7 @@ namespace Orchard.Core.Shapes {
return DateTime(DateTimeUtc, _dateTimeLocalization.LongDateTimeFormat);
}
return new MvcHtmlString(ConvertToDisplayTime(DateTimeUtc).ToString(CustomFormat.Text));
return new MvcHtmlString(ConvertToDisplayTime(DateTimeUtc).ToString(CustomFormat.Text, _cultureInfo.Value));
}
/// <summary>

View File

@@ -15,6 +15,7 @@ namespace Orchard.ArchiveLater.Drivers {
private const string TemplateName = "Parts/ArchiveLater";
private readonly IArchiveLaterService _archiveLaterService;
private readonly IDateTimeLocalization _dateTimeLocalization;
private readonly Lazy<CultureInfo> _cultureInfo;
public ArchiveLaterPartDriver(
IOrchardServices services,
@@ -24,6 +25,10 @@ namespace Orchard.ArchiveLater.Drivers {
_dateTimeLocalization = dateTimeLocalization;
T = NullLocalizer.Instance;
Services = services;
// initializing the culture info lazy initializer
_cultureInfo = new Lazy<CultureInfo>(() => CultureInfo.GetCultureInfo(Services.WorkContext.CurrentCulture));
}
public Localizer T { get; set; }
@@ -46,8 +51,8 @@ namespace Orchard.ArchiveLater.Drivers {
var model = new ArchiveLaterViewModel(part) {
ScheduledArchiveUtc = part.ScheduledArchiveUtc.Value,
ArchiveLater = part.ScheduledArchiveUtc.Value.HasValue,
ScheduledArchiveDate = part.ScheduledArchiveUtc.Value.HasValue ? localDate.Value.ToString(_dateTimeLocalization.ShortDateFormat.Text) : String.Empty,
ScheduledArchiveTime = part.ScheduledArchiveUtc.Value.HasValue ? localDate.Value.ToString(_dateTimeLocalization.ShortTimeFormat.Text) : String.Empty
ScheduledArchiveDate = part.ScheduledArchiveUtc.Value.HasValue ? localDate.Value.ToString(_dateTimeLocalization.ShortDateFormat.Text, _cultureInfo.Value) : String.Empty,
ScheduledArchiveTime = part.ScheduledArchiveUtc.Value.HasValue ? localDate.Value.ToString(_dateTimeLocalization.ShortTimeFormat.Text, _cultureInfo.Value) : String.Empty
};
return ContentShape("Parts_ArchiveLater_Edit",
@@ -64,7 +69,7 @@ namespace Orchard.ArchiveLater.Drivers {
var dateTimeFormat = _dateTimeLocalization.ShortDateFormat + " " + _dateTimeLocalization.ShortTimeFormat;
// use an english culture as it is the one used by jQuery.datepicker by default
if (DateTime.TryParseExact(parseDateTime, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out scheduled)) {
if (DateTime.TryParseExact(parseDateTime, dateTimeFormat, _cultureInfo.Value, DateTimeStyles.None, out scheduled)) {
// the date time is entered locally for the configured timezone
var timeZone = Services.WorkContext.CurrentTimeZone;

View File

@@ -7,10 +7,10 @@ html.dyn input.hinted {
font-style:italic;
}
input#ArchiveLater_ScheduledArchiveDate {
width:49%;
width:10em;
}
input#ArchiveLater_ScheduledArchiveTime {
width:43%;
width:7em;
}
.edit-item-sidebar fieldset.archive-later-datetime {

View File

@@ -1,11 +1,11 @@
@model Orchard.ArchiveLater.ViewModels.ArchiveLaterViewModel
@using System.Web.Mvc.Html;
@{
Style.Require("jQueryUtils_TimePicker");
Style.Require("jQueryUI_DatePicker");
Style.Require("jQueryUI_TimePicker");
Style.Require("ArchiveLater_DatePicker");
Script.Require("jQueryUI_DatePicker");
Script.Require("jQueryUtils_TimePicker");
Script.Require("jQueryUI_TimePicker");
}
<fieldset class="archive-later-datetime">
@@ -42,7 +42,7 @@
}
});
$('#@ViewData.TemplateInfo.GetFullHtmlFieldId("ScheduledArchiveDate")').datepicker({ showAnim: "" }).focus(function () { $('#@ViewData.TemplateInfo.GetFullHtmlFieldId("Command_ArchiveLater")').attr("checked", "checked") });
$('#@ViewData.TemplateInfo.GetFullHtmlFieldId("ScheduledArchiveTime")').timepickr().focus(function () { $('#@ViewData.TemplateInfo.GetFullHtmlFieldId("Command_ArchiveLater")').attr("checked", "checked") });
$('#@ViewData.TemplateInfo.GetFullHtmlFieldId("ScheduledArchiveTime")').timepicker({ stepMinute: 5 }).focus(function () { $('#@ViewData.TemplateInfo.GetFullHtmlFieldId("Command_ArchiveLater")').attr("checked", "checked") });
})
//]]>
</script>

View File

@@ -62,8 +62,8 @@ namespace Orchard.PublishLater.Drivers {
var localDate = new Lazy<DateTime>( () => TimeZoneInfo.ConvertTimeFromUtc(part.ScheduledPublishUtc.Value.Value, Services.WorkContext.CurrentTimeZone));
var model = new PublishLaterViewModel(part) {
ScheduledPublishUtc = part.ScheduledPublishUtc.Value,
ScheduledPublishDate = part.ScheduledPublishUtc.Value.HasValue && !part.IsPublished() ? localDate.Value.ToString(_dateTimeLocalization.ShortDateFormat.Text) : String.Empty,
ScheduledPublishTime = part.ScheduledPublishUtc.Value.HasValue && !part.IsPublished() ? localDate.Value.ToString(_dateTimeLocalization.ShortTimeFormat.Text) : String.Empty,
ScheduledPublishDate = part.ScheduledPublishUtc.Value.HasValue && !part.IsPublished() ? localDate.Value.ToString(_dateTimeLocalization.ShortDateFormat.Text, _cultureInfo.Value) : String.Empty,
ScheduledPublishTime = part.ScheduledPublishUtc.Value.HasValue && !part.IsPublished() ? localDate.Value.ToString(_dateTimeLocalization.ShortTimeFormat.Text, _cultureInfo.Value) : String.Empty,
};
return ContentShape("Parts_PublishLater_Edit",
@@ -83,7 +83,7 @@ namespace Orchard.PublishLater.Drivers {
var dateTimeFormat = _dateTimeLocalization.ShortDateFormat + " " + _dateTimeLocalization.ShortTimeFormat;
// use current culture
if (DateTime.TryParseExact(parseDateTime, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out scheduled)) {
if (DateTime.TryParseExact(parseDateTime, dateTimeFormat, _cultureInfo.Value, DateTimeStyles.None, out scheduled)) {
// the date time is entered locally for the configured timezone
var timeZone = Services.WorkContext.CurrentTimeZone;

View File

@@ -23,9 +23,9 @@ fieldset.publish-later-datetime input {
}
input#PublishLater_ScheduledPublishDate {
width:39%;
width:10em;
margin:0 0 0 12px;
}
input#PublishLater_ScheduledPublishTime {
width:33%;
width:7em;
}

View File

@@ -1,10 +1,10 @@
@model Orchard.PublishLater.ViewModels.PublishLaterViewModel
@{
Script.Require("jQueryUtils_TimePicker");
Script.Require("jQueryUI_DatePicker");
Script.Require("jQueryUI_TimePicker");
Style.Require("PublishLater_DatePicker");
Style.Require("jQueryUtils_TimePicker");
Style.Require("jQueryUI_DatePicker");
Style.Require("jQueryUI_TimePicker");
}
<fieldset class="publish-later-datetime">
<legend>@T("Publish")</legend>
@@ -40,7 +40,7 @@
});
$('#@ViewData.TemplateInfo.GetFullHtmlFieldId("ScheduledPublishDate")').datepicker({ showAnim: ""}).focus(function () { $('#@ViewData.TemplateInfo.GetFullHtmlFieldId("Command_PublishLater")').attr("checked", "checked") });
$('#@ViewData.TemplateInfo.GetFullHtmlFieldId("ScheduledPublishTime")').timepickr().focus(function () { $('#@ViewData.TemplateInfo.GetFullHtmlFieldId("Command_PublishLater")').attr("checked", "checked") });
$('#@ViewData.TemplateInfo.GetFullHtmlFieldId("ScheduledPublishTime")').timepicker({ stepMinute: 5}).focus(function () { $('#@ViewData.TemplateInfo.GetFullHtmlFieldId("Command_PublishLater")').attr("checked", "checked") });
})
//]]>
</script>

View File

@@ -47,6 +47,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Content Include="Scripts\jquery.ui.timepicker.min.js" />
<Content Include="Scripts\jquery-1.7.1.js" />
<Content Include="Scripts\jquery-1.7.1.min.js" />
<Content Include="Scripts\jquery-ui.js" />
@@ -114,7 +115,7 @@
<Content Include="Scripts\jquery.ui.widget.js" />
<Content Include="Scripts\jquery.ui.widget.min.js" />
<Content Include="Scripts\jquery.utils.js" />
<Content Include="Scripts\ui.timepickr.js" />
<Content Include="Scripts\jquery.ui.timepicker.js" />
<Content Include="Styles\images\ui-bg_flat_0_aaaaaa_40x100.png" />
<Content Include="Styles\images\ui-bg_flat_75_ffffff_40x100.png" />
<Content Include="Styles\images\ui-bg_glass_55_fbf9ee_1x400.png" />
@@ -130,7 +131,7 @@
<Content Include="Styles\images\ui-icons_cd0a0a_256x240.png" />
<Content Include="Styles\jquery-ui-1.8.18.custom.css" />
<Content Include="Styles\ui.datepicker.css" />
<Content Include="Styles\ui.timepickr.css" />
<Content Include="Styles\ui.timepicker.css" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">

View File

@@ -48,15 +48,11 @@ namespace Orchard.jQuery {
manifest.DefineScript("jQueryEffects_Slide").SetUrl("jquery.effects.slide.min.js", "jquery.effects.slide.js").SetVersion("1.8.18").SetDependencies("jQueryEffects_Core");
manifest.DefineScript("jQueryEffects_Transfer").SetUrl("jquery.effects.transfer.min.js", "jquery.effects.transfer.js").SetVersion("1.8.18").SetDependencies("jQueryEffects_Core");
// Utils
manifest.DefineScript("jQueryUtils").SetUrl("jquery.utils.js").SetDependencies("jQuery");
manifest.DefineScript("jQueryUtils_TimePicker").SetUrl("ui.timepickr.js").SetVersion("0.7.0a").SetDependencies("jQueryUtils", "jQueryUI_Core", "jQueryUI_Widget");
manifest.DefineStyle("jQueryUI_Orchard").SetUrl("jquery-ui-1.8.18.custom.css").SetVersion("1.8.18");
manifest.DefineStyle("jQueryUI_DatePicker").SetUrl("ui.datepicker.css").SetDependencies("jQueryUI_Orchard").SetVersion("1.7.2");
manifest.DefineStyle("jQueryUtils_TimePicker").SetUrl("ui.timepickr.css");
manifest.DefineScript("jQueryUI_TimePicker").SetUrl("jquery.ui.timepicker.min.js", "jquery.ui.timepicker.js").SetVersion("1.0.0").SetDependencies("jQueryUI_Slider");
manifest.DefineStyle("jQueryUI_TimePicker").SetUrl("ui.timepicker.css").SetDependencies("jQueryUI_Orchard").SetVersion("1.0.0");
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,420 +0,0 @@
/*
jQuery ui.timepickr - @VERSION
http://code.google.com/p/jquery-utils/
(c) Maxime Haineault <haineault@gmail.com>
http://haineault.com
MIT License (http://www.opensource.org/licenses/mit-license.php
Note: if you want the original experimental plugin checkout the rev 224
Dependencies
------------
- jquery.utils.js
- jquery.strings.js
- jquery.ui.js
*/
(function($) {
$.tpl('timepickr.menu', '<div class="ui-helper-reset ui-timepickr ui-widget ui-corner-all ui-widget-content" />'); //todo: (heskew) make the corner an option just like the items
$.tpl('timepickr.row', '<ol class="ui-timepickr-row ui-helper-clearfix" />');
$.tpl('timepickr.button', '<li class="{className:s}"><span class="ui-state-default">{label:s}</span></li>');
$.widget('ui.timepickr', {
options: {
convention: 12, // 24, 12
trigger: 'focus',
format12: '{h:02.d}:{m:02.d} {z}',
format24: '{h:02.d}:{m:02.d}',
hours: true,
prefix: ['AM', 'PM'],
suffix: ['AM', 'PM'],
prefixVal: false,
suffixVal: true,
rangeHour12: $.range(1, 13),
rangeHour24: [$.range(0, 12), $.range(12, 24)],
rangeMin: $.range(0, 60, 15),
rangeSec: $.range(0, 60, 15),
corners: 'all',
// plugins
core: true,
minutes: true,
seconds: false,
val: false,
updateLive: true,
resetOnBlur: true,
keyboardnav: true,
handle: false,
handleEvent: 'click'
},
plugins: {},
_create: function() {
this._dom = {
menu: $.tpl('timepickr.menu'),
row: $.tpl('timepickr.menu')
};
this._trigger('start');
this._trigger('initialized');
},
_trigger: function(type, e, ui) {
var ui = ui || this;
$.ui.plugin.call(this, type, [e, ui]);
return $.Widget.prototype._trigger.call(this, type, e, ui);
},
_createButton: function(i, format, className) {
var o = format && $.format(format, i) || i;
var cn = className && 'ui-timepickr-button ' + className || 'ui-timepickr-button';
return $.tpl('timepickr.button', { className: cn, label: o }).data('id', i)
.bind('mouseover', function() {
$(this).siblings().find('span')
.removeClass('ui-state-hover').end().end()
.find('span').addClass('ui-state-hover');
});
},
_addRow: function(range, format, className, insertAfter) {
var ui = this;
var btn = false;
var row = $.tpl('timepickr.row').bind('mouseover', function() {
$(this).next().show();
});
$.each(range, function(idx, val) {
ui._createButton(val, format || false).appendTo(row);
});
if (className) {
$(row).addClass(className);
}
if (this.options.corners) {
row.find('span').addClass('ui-corner-' + this.options.corners);
}
if (insertAfter) {
row.insertAfter(insertAfter);
}
else {
ui._dom.menu.append(row);
}
return row;
},
_setVal: function(val) {
val = val || this._getVal();
this.element.data('timepickr.initialValue', val);
this.element.val(this._formatVal(val));
if (this._dom.menu.is(':hidden')) {
this.element.trigger('change');
}
},
_getVal: function() {
var ols = this._dom.menu.find('ol');
function g(unit) {
var u = ols.filter('.' + unit).find('.ui-state-hover:first').text();
return u || ols.filter('.' + unit + 'li:first span').text();
}
return {
h: g('hours'),
m: g('minutes'),
s: g('seconds'),
a: g('prefix'),
z: g('suffix'),
f: this.options['format' + this.c],
c: this.c
};
},
_formatVal: function(ival) {
var val = ival || this._getVal();
if (!val.h) return;
val.c = this.options.convention;
val.f = val.c === 12 && this.options.format12 || this.options.format24;
return (new Time(val)).getTime();
},
blur: function() {
return this.element.blur();
},
focus: function() {
return this.element.focus();
},
show: function() {
this._trigger('show');
var pos = this.element.position();
var width = this.element.data('width');
var elementWidth = this.element.outerWidth();
var windowWidth = $(window).width() + $(window).scrollLeft();
if (width) {
this._dom.menu.css(
'left',
pos.left + width < windowWidth
? pos.left
: windowWidth - width
);
}
this._dom.menu.show(); //todo: (heskew) make show effect an option
},
hide: function() {
this._trigger('hide');
this._dom.menu.hide();
}
});
// These properties are shared accross every instances of timepickr
$.extend($.ui.timepickr, {
version: '@VERSION'
});
$.ui.plugin.add('timepickr', 'core', {
start: function(e, ui) {
var menu = ui._dom.menu;
var pos = ui.element.position();
//render off screen, to be repositioned by show()
menu.insertAfter(ui.element).css('left', '-9999em');
if (!$.boxModel) { // IE alignement fix
menu.css('margin-top', ui.element.height() + 8);
}
ui.element
.bind(ui.options.trigger, function() {
ui._dom.menu.find('ol:first').show();
ui.show();
ui._trigger('focus');
if (ui.options.trigger != 'focus') {
ui.element.focus();
}
ui._trigger('focus');
})
.bind('blur', function() {
ui.hide();
ui._trigger('blur');
});
menu.find('li').bind('mouseover.timepickr', function() {
ui._trigger('refresh');
});
},
initialized: function(e, ui) {
var menuItems = ui._dom.menu.find('ol');
var pos = ui.element.position();
//load up
ui.show();
menuItems.show();
//store width(s)
ui.element.data('width', ui._dom.menu.outerWidth());
//fix the width
ui._dom.menu.width(ui._dom.menu.width());
//hide
menuItems.hide();
ui.hide();
},
refresh: function(e, ui) {
// Realign each menu layers
ui._dom.menu.find('ol').each(function() {
var p = $(this).prev('ol');
try { // .. to not fuckup IE
$(this).css('left', p.position().left + p.find('.ui-state-hover').position().left);
} catch (e) { };
});
}
});
$.ui.plugin.add('timepickr', 'hours', {
start: function(e, ui) {
if (ui.options.convention === 24) {
// prefix is required in 24h mode
ui._dom.prefix = ui._addRow(ui.options.prefix, false, 'prefix');
// split-range
if ($.isArray(ui.options.rangeHour24[0])) {
var range = [];
$.merge(range, ui.options.rangeHour24[0]);
$.merge(range, ui.options.rangeHour24[1]);
ui._dom.hours = ui._addRow(range, '{0:0.2d}', 'hours');
ui._dom.hours.find('li').slice(ui.options.rangeHour24[0].length, -1).hide();
var lis = ui._dom.hours.find('li');
var show = [
function() {
lis.slice(ui.options.rangeHour24[0].length).hide().end()
.slice(0, ui.options.rangeHour24[0].length).show()
.filter(':visible:first').trigger('mouseover');
},
function() {
lis.slice(0, ui.options.rangeHour24[0].length).hide().end()
.slice(ui.options.rangeHour24[0].length).show()
.filter(':visible:first').trigger('mouseover');
}
];
ui._dom.prefix.find('li').bind('mouseover.timepickr', function() {
var index = ui._dom.menu.find('.prefix li').index(this);
show[index].call();
});
}
else {
ui._dom.hours = ui._addRow(ui.options.rangeHour24, '{0:0.2d}', 'hours');
ui._dom.hours.find('li').slice(12, -1).hide();
}
}
else {
ui._dom.hours = ui._addRow(ui.options.rangeHour12, '{0:0.2d}', 'hours');
// suffix is required in 12h mode
ui._dom.suffix = ui._addRow(ui.options.suffix, false, 'suffix');
}
}
});
$.ui.plugin.add('timepickr', 'minutes', {
start: function(e, ui) {
var p = ui._dom.hours && ui._dom.hours || false;
ui._dom.minutes = ui._addRow(ui.options.rangeMin, '{0:0.2d}', 'minutes', p);
}
});
$.ui.plugin.add('timepickr', 'seconds', {
start: function(e, ui) {
var p = ui._dom.minutes && ui._dom.minutes || false;
ui._dom.seconds = ui._addRow(ui.options.rangeSec, '{0:0.2d}', 'seconds', p);
}
});
$.ui.plugin.add('timepickr', 'val', {
start: function(e, ui) {
ui._setVal(ui.options.val);
}
});
$.ui.plugin.add('timepickr', 'updateLive', {
refresh: function(e, ui) {
ui._setVal();
}
});
$.ui.plugin.add('timepickr', 'resetOnBlur', {
start: function(e, ui) {
ui.element.data('timepickr.initialValue', ui._getVal());
ui._dom.menu.find('li > span').bind('mousedown.timepickr', function() {
ui.element.data('timepickr.initialValue', ui._getVal());
});
},
blur: function(e, ui) {
ui._setVal(ui.element.data('timepickr.initialValue'));
}
});
$.ui.plugin.add('timepickr', 'handle', {
start: function(e, ui) {
$(ui.options.handle).bind(ui.options.handleEvent + '.timepickr', function() {
ui.show();
});
}
});
$.ui.plugin.add('timepickr', 'keyboardnav', {
start: function(e, ui) {
ui.element
.bind('keydown', function(e) {
if ($.keyIs('enter', e)) {
ui._setVal();
ui.blur();
}
else if ($.keyIs('escape', e)) {
ui.blur();
}
});
}
});
var Time = function() { // arguments: h, m, s, c, z, f || time string
if (!(this instanceof arguments.callee)) {
throw Error("Constructor called as a function");
}
// arguments as literal object
if (arguments.length == 1 && $.isObject(arguments[0])) {
this.h = arguments[0].h || 0;
this.m = arguments[0].m || 0;
this.s = arguments[0].s || 0;
this.c = arguments[0].c && ($.inArray(arguments[0].c, [12, 24]) >= 0) && arguments[0].c || 24;
this.f = arguments[0].f || ((this.c == 12) && '{h:02.d}:{m:02.d} {z:02.d}' || '{h:02.d}:{m:02.d}');
this.z = arguments[0].z || 'am';
}
// arguments as string
else if (arguments.length < 4 && $.isString(arguments[1])) {
this.c = arguments[2] && ($.inArray(arguments[0], [12, 24]) >= 0) && arguments[0] || 24;
this.f = arguments[3] || ((this.c == 12) && '{h:02.d}:{m:02.d} {z:02.d}' || '{h:02.d}:{m:02.d}');
this.z = arguments[4] || 'am';
this.h = arguments[1] || 0; // parse
this.m = arguments[1] || 0; // parse
this.s = arguments[1] || 0; // parse
}
// no arguments (now)
else if (arguments.length === 0) {
// now
}
// standards arguments
else {
this.h = arguments[0] || 0;
this.m = arguments[1] || 0;
this.s = arguments[2] || 0;
this.c = arguments[3] && ($.inArray(arguments[3], [12, 24]) >= 0) && arguments[3] || 24;
this.f = this.f || ((this.c == 12) && '{h:02.d}:{m:02.d} {z:02.d}' || '{h:02.d}:{m:02.d}');
this.z = 'am';
}
return this;
};
Time.prototype.get = function(p, f, u) { return u && this.h || $.format(f, this.h); };
Time.prototype.getHours = function(unformated) { return this.get('h', '{0:02.d}', unformated); };
Time.prototype.getMinutes = function(unformated) { return this.get('m', '{0:02.d}', unformated); };
Time.prototype.getSeconds = function(unformated) { return this.get('s', '{0:02.d}', unformated); };
Time.prototype.setFormat = function(format) { return this.f = format; };
Time.prototype.getObject = function() { return { h: this.h, m: this.m, s: this.s, c: this.c, f: this.f, z: this.z }; };
Time.prototype.getTime = function() { return $.format(this.f, { h: this.h, m: this.m, z: this.z }); };
Time.prototype.parse = function(str) {
// 12h formats
if (this.c === 12) {
// Supported formats: (can't find any *official* standards for 12h..)
// - [hh]:[mm]:[ss] [zz] | [hh]:[mm] [zz] | [hh] [zz]
// - [hh]:[mm]:[ss] [z.z.] | [hh]:[mm] [z.z.] | [hh] [z.z.]
this.tokens = str.split(/\s|:/);
this.h = this.tokens[0] || 0;
this.m = this.tokens[1] || 0;
this.s = this.tokens[2] || 0;
this.z = this.tokens[3] || '';
return this.getObject();
}
// 24h formats
else {
// Supported formats:
// - ISO 8601: [hh][mm][ss] | [hh][mm] | [hh]
// - ISO 8601 extended: [hh]:[mm]:[ss] | [hh]:[mm] | [hh]
this.tokens = /:/.test(str) && str.split(/:/) || str.match(/[0-9]{2}/g);
this.h = this.tokens[0] || 0;
this.m = this.tokens[1] || 0;
this.s = this.tokens[2] || 0;
this.z = this.tokens[3] || '';
return this.getObject();
}
};
})(jQuery);

View File

@@ -0,0 +1,7 @@
/* css for timepicker */
.ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }
.ui-timepicker-div dl { text-align: left; }
.ui-timepicker-div dl dt { height: 25px; margin-bottom: -25px; }
.ui-timepicker-div dl dd { margin: 0 10px 10px 65px; }
.ui-timepicker-div td { font-size: 90%; }
.ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; }

View File

@@ -1,50 +0,0 @@
.ui-timepickr {
display:none;
position:absolute;
padding:2px 2px 2px 0;
}
.ui-timepickr-row {
padding:0;
float:right;
clear:both;
overflow:hidden;
margin:2px 0;
display:none;
position:relative;
}
.ui-timepickr-button {
float:left;
margin:0;
padding:0;
list-style:none;
list-style-type:none;
}
.ui-timepickr-button span {
font-size:.7em;
padding:4px 6px 4px 6px;
margin-left:2px;
text-align:center;
cursor:pointer;
display:block;
text-align:center;
/* system theme (default) */
border-width:1px;
border-style:solid;
/*border-color:ThreeDLightShadow ThreeDShadow ThreeDShadow ThreeDLightShadow;
color:ButtonText;
background:ButtonFace;*/
}
.ui-timepickr-button span.ui-state-hover {
/*color:HighlightText;
background:Highlight;*/
}
.ui-state-hover span {
/*background:#c30;*/
}

View File

@@ -1,5 +1,9 @@
@using Orchard.Core.Shapes.Localization
@using System.Globalization
@{
var cultureInfo = CultureInfo.GetCultureInfo(WorkContext.CurrentCulture);
var dateTimeLocalization = WorkContext.Resolve<IDateTimeLocalization>();
var monthNames = FormatJsList(dateTimeLocalization.MonthNames.Text);
var monthNamesShort = FormatJsList(dateTimeLocalization.MonthNamesShort.Text);
@@ -17,6 +21,11 @@
.Replace("Y", "y")
.Replace("M", "m")
;
var timeFormat = dateTimeLocalization.ShortTimeFormat.Text
.Replace("H", "h");
var ampm = timeFormat.ToLowerInvariant().Contains("tt") ? "true" : "false";
}
@functions {
@@ -46,6 +55,23 @@
showMonthAfterYear: @(dateTimeLocalization.ShowMonthAfterYear ? "true" : "false"), // True if the year select precedes month, false for month then year
yearSuffix: '@dateTimeLocalization.YearSuffix' // Additional text to append to the year in the month headers
};
$.datepicker.setDefaults($.datepicker.regional['']);
$.timepicker.regional[''] = {
timeOnlyTitle: '@T("Choose time")',
timeText: '@T("Time")',
hourText: '@T("Hour")',
minuteText: '@T("Minute")',
currentText: '@T("Now")', // Display text for current time link
closeText: '@T("Done")', // Display text for close link
timeFormat: '@timeFormat',
amNames: ['@cultureInfo.DateTimeFormat.AMDesignator', 'AM', 'A'],
pmNames: ['@cultureInfo.DateTimeFormat.PMDesignator', 'PM', 'P'],
ampm: @ampm
};
$.timepicker.setDefaults($.timepicker.regional['']);
})
//]]>
</script>