function WidgetDateTime (c) { c.widgetDateTime = this; this.container = c; this.name = c.getAttribute ('data-widget-name') || ''; this.timezone = c.getAttribute ('data-widget-timezone') || ''; this.required = c.getAttribute ('data-widget-required') != null; this._initialize (); } // WidgetDateTime WidgetDateTime.prototype._initialize = function () { var controls = this.container.getElementsByTagName ('*'); var controlsL = controls.length; for (var i = 0; i < controlsL; i++) { var control = controls[i]; var controlName = control.name; if (!controlName) continue; if (controlName.substring (0, this.name.length + 1) == this.name + '-') { var fieldName = controlName.substring (this.name.length + 1); if (fieldName == 'year') { this.initialYear = control.value || 1970; this.defaultYear = control.defaultValue || this.initialYear; this.yearInput = control; } else if (fieldName == 'month') { this.initialMonth = control.value || 1; this.defaultMonth = control.defaultValue || this.initialMonth; this.monthInput = control; } else if (fieldName == 'day') { this.initialDay = control.value || 1; this.defaultDay = control.defaultValue || this.initialDay; this.dayInput = control; } else if (fieldName == 'hour') { this.initialHour = control.value || 0; this.defaultHour = control.defaultValue || this.initialHour; this.hourInput = control; } else if (fieldName == 'minute') { this.initialMinute = control.value || 1; this.defaultMinute = control.defaultValue || this.initialMinute; this.minuteInput = control; } else if (fieldName == 'second') { this.initialSecond = control.value || 1; this.defaultSecond = control.defaultValue || this.initialSecond; this.secondInput = control; } } } if (!WidgetDateTime.supported) return; var def = this._localDateAndTimeString (this.defaultYear, this.defaultMonth, this.defaultDay, this.defaultHour, this.defaultMinute, this.defaultSecond); var initial = this._localDateAndTimeString (this.initialYear, this.initialMonth, this.initialDay, this.initialHour, this.initialMinute, this.initialSecond); if (this.timezone && this.timezone != 'Z') { /* Opera 9.61 (and WF2) does not support non-Z timezones. */ var offset = 0; var m; if (m = this.timezone.match (/^([+-])([0-9][0-9]):([0-9][0-9])$/)) { offset = parseInt (m[2]) * 60 + parseInt (m[3]); if (m[1] == '-') offset = -offset; offset *= 60 * 1000; } var input = document.createElement ('input'); input.type = 'datetime'; input.value = def + 'Z'; input.setAttribute ('value', def); def = this._dateToLocalDateAndTimeString (new Date (input.valueAsNumber - offset)); input.value = initial + 'Z'; initial = this._dateToLocalDateAndTimeString (new Date (input.valueAsNumber - offset)); } var input = document.createElement ('input'); input.type = this.timezone == '' ? 'datetime-local' : 'datetime'; input.name = this.name; input.defaultValue = def + (this.timezone == '' ? '' : 'Z'); input.value = initial + (this.timezone == '' ? '' : 'Z'); if (this.required) input.setAttribute ('required', ''); this.container.innerHTML = ''; this.container.appendChild (input); this.dateTimeInput = input; }; // _initialize WidgetDateTime.prototype._localDateAndTimeString = function (y, m, d, h, mi, s) { var r = (y || 1970); if (r.length < 4) { r = ("0000" + r).slice (-4); } r += '-' + ("0" + (m || 1)).slice (-2); r += '-' + ("0" + (d || 1)).slice (-2); r += 'T' + ("0" + (h || 0)).slice (-2); r += ':' + ("0" + (mi || 0)).slice (-2); r += ':' + ("0" + (s || 0)).slice (-2); return r; }; // _localDateAndTimeString WidgetDateTime.prototype._dateToLocalDateAndTimeString = function (date) { /* Opera 9.61 does not reflect .valueAsDate to value, so it cannot be used to obtain global date and time string. */ var r = ''; r = date.getUTCFullYear (); // JS does not support years 0001-0999 r += '-' + ('0' + (date.getUTCMonth () + 1)).slice (-2); r += '-' + ('0' + date.getUTCDate ()).slice (-2); r += 'T' + ('0' + date.getUTCHours ()).slice (-2); r += ':' + ('0' + date.getUTCMinutes ()).slice (-2); r += ':' + ('0' + date.getUTCSeconds ()).slice (-2); r += '.' + (date.getUTCMilliseconds () + '00').slice (2); return r; }; // _dateToLocalDateAndTimeString /* NOTE: Opera 9.61 shows as UTC whatever the user's timezone is. */ WidgetDateTime.prototype.setDate = function (date) { if (this.dateTimeInput) { this.dateTimeInput.value = this._dateToLocalDateAndTimeString (date); } else { if (this.yearInput) this.yearInput.value = date.getFullYear(); if (this.monthInput) this.monthInput.value = date.getMonth() + 1; if (this.dayInput) this.dayInput.value = date.getDate(); if (this.hourInput) this.hourInput.value = date.getHours(); if (this.minuteInput) this.minuteInput.value = date.getMinutes(); if (this.secondInput) this.secondInput.value = date.getSeconds(); } }; // setDate (function () { var input = document.createElement ('input'); input.setAttribute ('type', 'datetime'); WidgetDateTime.supported = input.type == 'datetime'; })(); if (window.WidgetDateTimeOnLoad) WidgetDateTimeOnLoad (); /* Usage:
/
/
:
:
The content of the container element (i.e. span#c in this example) is
used when control is not supported. The
content is replaced by a control if it
is supported.
You can use any form control and any other content, in any order, as
long as control's name ends with suffix such as "-year", "-month",
..., or "-second" and whose DOM interface has |value| DOM attribute.
You can omit some of controls (e.g. "-second") if desired.
The |data-widget-name| attribute of the container element represents
the control name. This attribute is REQUIRED. It must be used as
prefix of controls in the content. The value of this attribute is
used as the |name| attribute of the
element.
The |data-widget-timezone| attribute of the container element
represents the timezone of the values used by controls in the content.
The value must be "Z" or a string that matches
/^[+-]([0-1][0-9]|2[0-3]):[0-5][0-9]$/. If this attribute is
specified, an control is used. Otherwise, an
control is used.
Latest version of this script is available at