From f020d1c584cd095e3f1394289560faa616731e20 Mon Sep 17 00:00:00 2001 From: Oleg Marshev Date: Tue, 30 Sep 2014 14:37:45 +0300 Subject: [PATCH] Show date and time on Schedules and Details in UTC (TNL-85). --- .../js/models/settings/course_details.js | 10 +-- cms/static/js/views/settings/main.js | 40 +++++----- cms/templates/base.html | 1 - cms/templates/settings.html | 8 +- common/static/js/vendor/tzAbbr.js | 73 ------------------- 5 files changed, 28 insertions(+), 104 deletions(-) delete mode 100644 common/static/js/vendor/tzAbbr.js diff --git a/cms/static/js/models/settings/course_details.js b/cms/static/js/models/settings/course_details.js index 4cf2851903..50ccd60441 100644 --- a/cms/static/js/models/settings/course_details.js +++ b/cms/static/js/models/settings/course_details.js @@ -1,4 +1,4 @@ -define(["backbone", "underscore", "gettext"], function(Backbone, _, gettext) { +define(["backbone", "underscore", "gettext", "date"], function(Backbone, _, gettext, date) { var CourseDetails = Backbone.Model.extend({ defaults: { @@ -21,16 +21,16 @@ var CourseDetails = Backbone.Model.extend({ // When init'g from html script, ensure you pass {parse: true} as an option (2nd arg to reset) parse: function(attributes) { if (attributes['start_date']) { - attributes.start_date = new Date(attributes.start_date); + attributes.start_date = date.parse(attributes.start_date); } if (attributes['end_date']) { - attributes.end_date = new Date(attributes.end_date); + attributes.end_date = date.parse(attributes.end_date); } if (attributes['enrollment_start']) { - attributes.enrollment_start = new Date(attributes.enrollment_start); + attributes.enrollment_start = date.parse(attributes.enrollment_start); } if (attributes['enrollment_end']) { - attributes.enrollment_end = new Date(attributes.enrollment_end); + attributes.enrollment_end = date.parse(attributes.enrollment_end); } return attributes; }, diff --git a/cms/static/js/views/settings/main.js b/cms/static/js/views/settings/main.js index 1dba74041a..85c94cab58 100644 --- a/cms/static/js/views/settings/main.js +++ b/cms/static/js/views/settings/main.js @@ -1,6 +1,6 @@ -define(["js/views/validation", "codemirror", "underscore", "jquery", "jquery.ui", "tzAbbr", "js/models/uploads", +define(["js/views/validation", "codemirror", "underscore", "jquery", "jquery.ui", "js/utils/date_utils", "js/models/uploads", "js/views/uploads", "js/utils/change_on_enter", "jquery.timepicker", "date"], - function(ValidatingView, CodeMirror, _, $, ui, tzAbbr, FileUploadModel, FileUploadDialog, TriggerChangeEventOnEnter) { + function(ValidatingView, CodeMirror, _, $, ui, DateUtils, FileUploadModel, FileUploadDialog, TriggerChangeEventOnEnter) { var DetailsView = ValidatingView.extend({ // Model class is CMS.Models.Settings.CourseDetails @@ -12,7 +12,7 @@ var DetailsView = ValidatingView.extend({ "change textarea" : "updateModel", 'click .remove-course-introduction-video' : "removeVideo", 'focus #course-overview' : "codeMirrorize", - 'mouseover #timezone' : "updateTime", + 'mouseover .timezone' : "updateTime", // would love to move to a general superclass, but event hashes don't inherit in backbone :-( 'focus :input' : "inputFocus", 'blur :input' : "inputUnfocus", @@ -35,8 +35,6 @@ var DetailsView = ValidatingView.extend({ $(this).show(); }); - this.$el.find('#timezone').html("(" + tzAbbr() + ")"); - this.listenTo(this.model, 'invalid', this.handleValidationError); this.listenTo(this.model, 'change', this.showNotificationBar); this.selectorToField = _.invert(this.fieldToSelectorMap); @@ -81,11 +79,15 @@ var DetailsView = ValidatingView.extend({ }, updateTime : function(e) { - var now = new Date(); - var hours = now.getHours(); - var minutes = now.getMinutes(); - $(e.currentTarget).attr('title', (hours % 12 === 0 ? 12 : hours % 12) + ":" + (minutes < 10 ? "0" : "") + - now.getMinutes() + (hours < 12 ? "am" : "pm") + " (current local time)"); + var now = new Date(), + hours = now.getUTCHours(), + minutes = now.getUTCMinutes(), + currentTimeText = gettext('%(hours)s:%(minutes)s (current UTC time)'); + + $(e.currentTarget).attr('title', interpolate(currentTimeText, { + 'hours': hours, + 'minutes': minutes + }, true)); }, setupDatePicker: function (fieldName) { @@ -95,13 +97,8 @@ var DetailsView = ValidatingView.extend({ var timefield = $(div).find("input:.time"); var cachethis = this; var setfield = function () { - var date = datefield.datepicker('getDate'); - if (date) { - var time = timefield.timepicker("getSecondsFromMidnight"); - if (!time) { - time = 0; - } - var newVal = new Date(date.getTime() + time * 1000); + var newVal = DateUtils.getDate(datefield, timefield); + if (newVal) { if (!cacheModel.has(fieldName) || cacheModel.get(fieldName).getTime() !== newVal.getTime()) { cachethis.clearValidationErrors(); cachethis.setAndValidate(fieldName, newVal); @@ -126,13 +123,14 @@ var DetailsView = ValidatingView.extend({ timefield.on('changeTime', setfield); timefield.on('input', setfield); - datefield.datepicker('setDate', this.model.get(fieldName)); + date = this.model.get(fieldName) // timepicker doesn't let us set null, so check that we have a time - if (this.model.has(fieldName)) { - timefield.timepicker('setTime', this.model.get(fieldName)); - } // but reset the field either way + if (date) { + DateUtils.setDate(datefield, timefield, date); + } // but reset fields either way else { timefield.val(''); + datefield.val(''); } }, diff --git a/cms/templates/base.html b/cms/templates/base.html index 1a81e9192c..11c9d320aa 100644 --- a/cms/templates/base.html +++ b/cms/templates/base.html @@ -69,7 +69,6 @@ "jquery.immediateDescendents": "coffee/src/jquery.immediateDescendents", "datepair": "js/vendor/timepicker/datepair", "date": "js/vendor/date", - "tzAbbr": "js/vendor/tzAbbr", "underscore": "js/vendor/underscore-min", "underscore.string": "js/vendor/underscore.string.min", "backbone": "js/vendor/backbone-min", diff --git a/cms/templates/settings.html b/cms/templates/settings.html index 9065103cf4..bbeaad3d90 100644 --- a/cms/templates/settings.html +++ b/cms/templates/settings.html @@ -152,7 +152,7 @@ require(["domReady!", "jquery", "js/models/settings/course_details", "js/views/s
- + ${_("(UTC)")}
@@ -166,7 +166,7 @@ require(["domReady!", "jquery", "js/models/settings/course_details", "js/views/s
- + ${_("(UTC)")}
@@ -182,7 +182,7 @@ require(["domReady!", "jquery", "js/models/settings/course_details", "js/views/s
- + ${_("(UTC)")}
@@ -196,7 +196,7 @@ require(["domReady!", "jquery", "js/models/settings/course_details", "js/views/s
- + ${_("(UTC)")}
diff --git a/common/static/js/vendor/tzAbbr.js b/common/static/js/vendor/tzAbbr.js deleted file mode 100644 index b6188115df..0000000000 --- a/common/static/js/vendor/tzAbbr.js +++ /dev/null @@ -1,73 +0,0 @@ -/* Friendly timezone abbreviations in client-side JavaScript - -`tzAbbr()` or `tzAbbr(new Date(79,5,24))` -=> "EDT", "CST", "GMT", etc.! - -There's no 100% reliable way to get friendly timezone names in all -browsers using JS alone, but this tiny function scours a -stringified date as best it can and returns `null` in the few cases -where no friendly timezone name is found (so far, just Opera). - -Device tested & works in: -* IE 6 [through] 11 (latest versions of all) -* Firefox 3 [through] 16 (16 = latest version to date) -* Chrome 22 (latest version to date) -* Safari 6 (latest version to date) -* Mobile Safari on iOS 5 & 6 -* Android 4.0.3 stock browser -* Android 2.3.7 stock browser -* IE Mobile 9 (WP 7.5) - -Known to fail in: -* Opera 12 (desktop, latest version to date) - -For Opera, I've included (but commented out) a workaround spotted -on StackOverflow that returns a GMT offset when no abbreviation is -found. I haven't found a decent workaround. - -If you find any other cases where this method returns null or dodgy -results, please say so in the comments; even if we can't find a -workaround it'll at least help others determine if this approach is -suitable for their project! -*/ -define([], function() { - return function (dateInput) { - var dateObject = dateInput || new Date(), - dateString = dateObject + "", - tzAbbr = ( - // Works for the majority of modern browsers - dateString.match(/\(([^\)]+)\)$/) || - // IE outputs date strings in a different format: - dateString.match(/([A-Z]+) [\d]{4}$/) - ); - - if (tzAbbr) { - // Old Firefox uses the long timezone name (e.g., "Central - // Daylight Time" instead of "CDT") - /* - If the timezone string does not cotain capital English letters - (For example, the timezone string may be a Chinese string), - then the following code line will produce a null-reference - exception, and the execution of the javascript codes will - be stopped, which may cause some strange behaviors. So a - try-catch is needed here to prevent the execution being stopped. - */ - try { - tzAbbr = tzAbbr[1].match(/[A-Z]/g).join(""); - } catch(err) { - tzAbbr = tzAbbr[1]; - } - } - - // Uncomment these lines to return a GMT offset for browsers - // that don't include the user's zone abbreviation (e.g., - // "GMT-0500".) I prefer to have `null` in this case, but - // you may not! - // First seen on: http://stackoverflow.com/a/12496442 - // if (!tzAbbr && /(GMT\W*\d{4})/.test(dateString)) { - // return RegExp.$1; - // } - - return tzAbbr; - }; -});