Chromium Code Reviews| Index: chrome/browser/resources/chromeos/set_time.js |
| diff --git a/chrome/browser/resources/chromeos/set_time.js b/chrome/browser/resources/chromeos/set_time.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..9cd4a9a819dfb1ed9270cae25db8968f508212cc |
| --- /dev/null |
| +++ b/chrome/browser/resources/chromeos/set_time.js |
| @@ -0,0 +1,223 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +cr.define('settime', function() { |
| + /** |
| + * TimeSetter handles a dialog to check and set system time. It can also |
| + * include a timezone dropdown if timezoneId is provided. |
| + * |
| + * TimeSetter uses the system time to populate the controls initially and |
| + * update them as the system time or timezone changes, and notifies Chrome |
| + * when the user changes the time or timezone. |
| + * @constructor |
| + */ |
| + function TimeSetter() {} |
| + |
| + cr.addSingletonGetter(TimeSetter); |
| + |
| + /** @const */ var BODY_PADDING_PX = 20; |
| + /** @const */ var LABEL_PADDING_PX = 5; |
| + |
| + TimeSetter.prototype = { |
| + /** |
| + * Performs initial setup. |
| + */ |
| + initialize: function() { |
| + // Store values for reverting inputs when the user's date/time is invalid. |
| + this.prevValues_ = {}; |
| + |
| + // The build time doesn't include a timezone, so subtract 1 day to get a |
| + // safe minimum date. |
| + this.minDate_ = new Date(loadTimeData.getValue('buildTime')); |
| + this.minDate_.setDate(this.minDate_.getDate() - 1); |
| + |
| + // Set the max date to the min date plus 20 years. |
| + this.maxDate_ = new Date(this.minDate_); |
| + this.maxDate_.setYear(this.minDate_.getFullYear() + 20); |
| + |
| + // Make sure the ostensible date is within this range. |
| + var now = new Date(); |
| + if (now > this.maxDate_) |
| + this.maxDate_ = now; |
| + else if (now < this.minDate_) |
| + this.minDate_ = now; |
| + |
| + $('date').setAttribute('min', this.toHtmlValues_(this.minDate_).date); |
| + $('date').setAttribute('max', this.toHtmlValues_(this.maxDate_).date); |
| + |
| + this.updateTime_(); |
| + |
| + // Show the timezone select if we have a timezone ID. |
| + var currentTimezoneId = loadTimeData.getValue('currentTimezoneId'); |
| + if (currentTimezoneId !== '') { |
| + this.setTimezone_(currentTimezoneId); |
| + $('timezone-select').addEventListener( |
| + 'change', this.onTimezoneChange_.bind(this), false); |
| + $('timezone').hidden = false; |
| + } |
| + |
| + this.sizeToFit_(); |
| + |
| + $('time').addEventListener('blur', this.onTimeBlur_.bind(this), false); |
| + $('date').addEventListener('blur', this.onTimeBlur_.bind(this), false); |
| + |
| + $('done').addEventListener('click', this.onSubmit_.bind(this), false); |
| + }, |
| + |
| + /** |
| + * Sets the current timezone. |
| + * @param {string} timezoneId The timezone ID to select. |
| + * @private |
| + */ |
| + setTimezone_: function(timezoneId) { |
| + $('timezone-select').value = timezoneId; |
| + this.updateTime_(); |
| + }, |
| + |
| + /** |
| + * Updates the date/time controls to the current local time. |
| + * Called initially, then called again once a minute. |
| + * @private |
| + */ |
| + updateTime_: function() { |
| + var now = new Date(); |
| + |
| + // Only update time controls if neither is focused or one is invalid. |
| + if ((document.activeElement.id != 'date' && |
| + document.activeElement.id != 'time') || |
| + $('date').value === '' || $('time').value === '') { |
|
michaelpg
2014/04/24 01:32:23
Apparently empty date/times are "valid" to Javascr
|
| + var htmlValues = this.toHtmlValues_(now); |
| + this.prevValues_.date = $('date').value = htmlValues.date; |
| + this.prevValues_.time = $('time').value = htmlValues.time; |
| + } |
| + |
| + window.clearTimeout(this.timeTimeout_); |
| + |
| + // Start timer to update these inputs every minute. |
| + var secondsRemaining = 60 - now.getSeconds(); // 0 <= getSeconds() < 60 |
| + this.timeTimeout_ = window.setTimeout(this.updateTime_.bind(this), |
| + secondsRemaining * 1000); |
| + }, |
| + |
| + /** |
| + * Attempts to set the system time to the time given by the controls. |
| + * @private |
| + */ |
| + applyTime_: function() { |
| + var date = $('date').valueAsDate; |
| + date.setMilliseconds(date.getMilliseconds() + $('time').valueAsNumber); |
| + |
| + // Add timezone offset to get real time. |
| + date.setMinutes(date.getMinutes() + date.getTimezoneOffset()); |
| + |
| + var seconds = Math.floor(date / 1000); |
| + chrome.send('setTimeInSeconds', [seconds]); |
| + }, |
| + |
| + /** |
| + * Handles events for the date/time controls. |
| + * @param {Event} e The blur event. |
| + * @private |
| + */ |
| + onTimeBlur_: function(e) { |
| + if (e.target.validity.valid && e.target.value !== '') { |
| + // Make this the new fallback time in case of future invalid input. |
| + this.prevValues_[e.target.id] = e.target.value; |
| + this.applyTime_(); |
| + } else { |
| + // Restore previous value. |
| + e.target.value = this.prevValues_[e.target.id]; |
| + } |
| + }, |
| + |
| + /** |
| + * Handles events for the timezone control. |
| + * @param {Event} e The change event. |
| + * @private |
| + */ |
| + onTimezoneChange_: function(e) { |
| + chrome.send('setTimezone', [e.target.value]); |
| + }, |
| + |
| + /** |
| + * Handles events for the submit button. |
| + * @param {Event} e The click event. |
| + * @private |
| + */ |
| + onSubmit_: function(e) { |
| + chrome.send('DialogClose'); |
| + }, |
| + |
| + /** |
| + * Resizes the window if necessary to show the entire contents. |
| + * @private |
| + */ |
| + sizeToFit_: function() { |
| + var newWidth = window.outerWidth; |
| + var newHeight = window.outerHeight; |
| + |
| + // Because of l10n, we should check if the window can fit the |
| + // timezone select. |
| + var timezoneWidth = $('timezone-select').offsetWidth; |
| + var labelWidth = $('timezone-label').offsetWidth; |
| + |
| + var minWidth = 2 * BODY_PADDING_PX + labelWidth + |
| + LABEL_PADDING_PX + timezoneWidth; |
| + if (window.innerWidth < minWidth) { |
| + // Apply the width to the body now so the next calculation is correct. |
| + document.body.style.width = (minWidth - 2 * BODY_PADDING_PX) + 'px'; |
| + newWidth = minWidth; |
| + } |
| + |
| + // After resizing horizontally, make sure the page will fit vertically. |
| + var minHeight = document.body.scrollHeight; |
| + if (window.innerHeight < minHeight) { |
| + newHeight = minHeight + |
| + window.outerHeight - window.innerHeight; // title bar |
| + } |
| + |
| + if (newWidth != window.outerWidth || newHeight != window.outerHeight) { |
| + // Move before resize for a less jumpy transition. |
| + window.moveTo(window.screen.width / 2 - newWidth / 2, |
| + window.screen.height / 2 - newHeight / 2); |
| + window.resizeTo(newWidth, newHeight); |
| + } |
| + }, |
| + |
| + /** |
| + * Builds date and time strings suitable for the values of HTML date and |
| + * time elements. |
| + * @param {Date} date The date object to represent. |
| + * @return {Object} A pair of strings in the following format: |
| + * { |
| + * date: 'Full-date string as defined in RFC 3339', |
| + * time: 'Time string as "HH:MM"' |
| + * } |
| + * @private |
| + */ |
| + toHtmlValues_: function(date) { |
| + // Get the current time and subtract the timezone offset, so the |
| + // JSON string is in local time. |
| + var localDate = new Date(date); |
| + localDate.setMinutes(date.getMinutes() - date.getTimezoneOffset()); |
| + return { |
| + date: localDate.toISOString().slice(0, 10), |
| + time: localDate.toISOString().slice(11, 16) |
| + }; |
| + }, |
| + }; |
| + |
| + TimeSetter.setTimezone = function(timezoneId) { |
| + TimeSetter.getInstance().setTimezone_(timezoneId); |
| + }; |
| + |
| + return { |
| + TimeSetter: TimeSetter |
| + }; |
| +}); |
| + |
| +document.addEventListener( |
| + 'DOMContentLoaded', |
| + settime.TimeSetter.getInstance().initialize.bind( |
| + settime.TimeSetter.getInstance())); |