mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-02-10 15:30:25 +01:00
Using HTML5 input field for mobile browsers to get there native UI for date/time entry
This commit is contained in:
parent
915ca69e86
commit
88ea87fedb
@ -26,6 +26,9 @@
|
|||||||
* Dates are passed to the server in ISO8601 format ("Y-m-d\TH:i:sP"), and data_format is
|
* Dates are passed to the server in ISO8601 format ("Y-m-d\TH:i:sP"), and data_format is
|
||||||
* handled server-side.
|
* handled server-side.
|
||||||
*
|
*
|
||||||
|
* Widgets uses jQuery date- and time-picker for desktop browsers and
|
||||||
|
* HTML5 input fields for mobile devices to get their native UI for date/time entry.
|
||||||
|
*
|
||||||
* @augments et2_inputWidget
|
* @augments et2_inputWidget
|
||||||
*/
|
*/
|
||||||
var et2_date = et2_inputWidget.extend(
|
var et2_date = et2_inputWidget.extend(
|
||||||
@ -87,7 +90,8 @@ String: A string in the user\'s date format, or a relative date. Relative dates
|
|||||||
*
|
*
|
||||||
* @memberOf et2_date
|
* @memberOf et2_date
|
||||||
*/
|
*/
|
||||||
init: function() {
|
init: function()
|
||||||
|
{
|
||||||
this._super.apply(this, arguments);
|
this._super.apply(this, arguments);
|
||||||
|
|
||||||
this.date = new Date();
|
this.date = new Date();
|
||||||
@ -95,12 +99,15 @@ String: A string in the user\'s date format, or a relative date. Relative dates
|
|||||||
this.date.setMinutes(0);
|
this.date.setMinutes(0);
|
||||||
this.date.setSeconds(0);
|
this.date.setSeconds(0);
|
||||||
this.input = null;
|
this.input = null;
|
||||||
|
this.is_mobile = egwIsMobile();
|
||||||
|
this.dateFormat = this.is_mobile ? 'yy-mm-dd' : this.egw().dateTimeFormat(this.egw().preference("dateformat"));
|
||||||
|
this.timeFormat = this.is_mobile ? 'HH:mm' : this.egw().preference("timeformat") == 12 ? "h:mmtt" : "HH:mm";
|
||||||
|
|
||||||
this.createInputWidget();
|
this.createInputWidget();
|
||||||
},
|
},
|
||||||
|
|
||||||
createInputWidget: function() {
|
createInputWidget: function()
|
||||||
|
{
|
||||||
this.span = $j(document.createElement(this.options.inline ? 'div' : "span")).addClass("et2_date");
|
this.span = $j(document.createElement(this.options.inline ? 'div' : "span")).addClass("et2_date");
|
||||||
|
|
||||||
this.input_date = $j(document.createElement(this.options.inline ? "div" : "input"));
|
this.input_date = $j(document.createElement(this.options.inline ? "div" : "input"));
|
||||||
@ -111,38 +118,57 @@ String: A string in the user\'s date format, or a relative date. Relative dates
|
|||||||
|
|
||||||
this.setDOMNode(this.span[0]);
|
this.setDOMNode(this.span[0]);
|
||||||
|
|
||||||
// jQuery-UI date picker
|
if (this.is_mobile)
|
||||||
if(this._type != 'date-timeonly')
|
|
||||||
{
|
{
|
||||||
this.egw().calendar(this.input_date, this._type == "date-time");
|
switch(this._type)
|
||||||
|
{
|
||||||
|
case 'date':
|
||||||
|
this.input_date.attr('type', 'date');
|
||||||
|
break;
|
||||||
|
case 'date-time':
|
||||||
|
this.input_date.attr('type', 'datetime-local');
|
||||||
|
break;
|
||||||
|
case 'date-timeonly':
|
||||||
|
this.input_date.addClass("et2_time");
|
||||||
|
this.input_date.attr('type', 'time');
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.input_date.addClass("et2_time");
|
// jQuery-UI date picker
|
||||||
this.egw().time(this.input_date);
|
if(this._type != 'date-timeonly')
|
||||||
|
{
|
||||||
|
this.egw().calendar(this.input_date, this._type == "date-time");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.input_date.addClass("et2_time");
|
||||||
|
this.egw().time(this.input_date);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avoid collision of datepicker dialog with input field
|
||||||
|
this.input_date.datepicker('option', 'beforeShow', function(input, inst){
|
||||||
|
var cal = inst.dpDiv;
|
||||||
|
setTimeout(function () {
|
||||||
|
var $input = jQuery(input);
|
||||||
|
var inputOffset = $input.offset();
|
||||||
|
// position the datepicker in freespace zone
|
||||||
|
// avoid datepicker calendar collision with input field
|
||||||
|
if (cal.height() + inputOffset.top > window.innerHeight)
|
||||||
|
{
|
||||||
|
cal.position({
|
||||||
|
my: "left center",
|
||||||
|
at: 'right bottom',
|
||||||
|
collision: 'flip fit',
|
||||||
|
of: input
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
},0);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avoid collision of datepicker dialog with input field
|
|
||||||
this.input_date.datepicker('option', 'beforeShow', function(input, inst){
|
|
||||||
var cal = inst.dpDiv;
|
|
||||||
setTimeout(function () {
|
|
||||||
var $input = jQuery(input);
|
|
||||||
var inputOffset = $input.offset();
|
|
||||||
// position the datepicker in freespace zone
|
|
||||||
// avoid datepicker calendar collision with input field
|
|
||||||
if (cal.height() + inputOffset.top > window.innerHeight)
|
|
||||||
{
|
|
||||||
cal.position({
|
|
||||||
my: "left center",
|
|
||||||
at: 'right bottom',
|
|
||||||
collision: 'flip fit',
|
|
||||||
of: input,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
},0);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update internal value when changed
|
// Update internal value when changed
|
||||||
var self = this;
|
var self = this;
|
||||||
this.input_date.bind('change', function(e){
|
this.input_date.bind('change', function(e){
|
||||||
@ -297,7 +323,7 @@ String: A string in the user\'s date format, or a relative date. Relative dates
|
|||||||
*/
|
*/
|
||||||
set_year_range: function(_value)
|
set_year_range: function(_value)
|
||||||
{
|
{
|
||||||
if(this.input_date && this._type == 'date')
|
if(this.input_date && this._type == 'date' && !this.is_mobile)
|
||||||
{
|
{
|
||||||
this.input_date.datepicker('option','yearRange',_value);
|
this.input_date.datepicker('option','yearRange',_value);
|
||||||
}
|
}
|
||||||
@ -319,10 +345,18 @@ String: A string in the user\'s date format, or a relative date. Relative dates
|
|||||||
* days from today.
|
* days from today.
|
||||||
* @param {Date|Number|String} _value
|
* @param {Date|Number|String} _value
|
||||||
*/
|
*/
|
||||||
set_min: function(_value) {
|
set_min: function(_value)
|
||||||
|
{
|
||||||
if(this.input_date)
|
if(this.input_date)
|
||||||
{
|
{
|
||||||
this.input_date.datepicker('option','minDate',_value);
|
if (this.is_mobile)
|
||||||
|
{
|
||||||
|
this.input_date.attr('min', _value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.input_date.datepicker('option','minDate',_value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.options.min = _value;
|
this.options.min = _value;
|
||||||
},
|
},
|
||||||
@ -342,10 +376,18 @@ String: A string in the user\'s date format, or a relative date. Relative dates
|
|||||||
* days from today.
|
* days from today.
|
||||||
* @param {Date|Number|String} _value
|
* @param {Date|Number|String} _value
|
||||||
*/
|
*/
|
||||||
set_max: function(_value) {
|
set_max: function(_value)
|
||||||
|
{
|
||||||
if(this.input_date)
|
if(this.input_date)
|
||||||
{
|
{
|
||||||
this.input_date.datepicker('option','maxDate',_value);
|
if (this.is_mobile)
|
||||||
|
{
|
||||||
|
this.input_date.attr('max', _value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.input_date.datepicker('option','maxDate',_value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.options.max = _value;
|
this.options.max = _value;
|
||||||
},
|
},
|
||||||
@ -359,7 +401,8 @@ String: A string in the user\'s date format, or a relative date. Relative dates
|
|||||||
* - string or number with timestamp in usertime like server-side uses it
|
* - string or number with timestamp in usertime like server-side uses it
|
||||||
* - string starting with + or - to add/substract given number of seconds from current value, "+600" to add 10 minutes
|
* - string starting with + or - to add/substract given number of seconds from current value, "+600" to add 10 minutes
|
||||||
*/
|
*/
|
||||||
set_value: function(_value) {
|
set_value: function(_value)
|
||||||
|
{
|
||||||
var old_value = this._oldValue;
|
var old_value = this._oldValue;
|
||||||
if(_value === null || _value === "" || _value === undefined ||
|
if(_value === null || _value === "" || _value === undefined ||
|
||||||
// allow 0 as empty-value for date and date-time widgets, as that is used a lot eg. in InfoLog
|
// allow 0 as empty-value for date and date-time widgets, as that is used a lot eg. in InfoLog
|
||||||
@ -406,7 +449,7 @@ String: A string in the user\'s date format, or a relative date. Relative dates
|
|||||||
switch(this._type)
|
switch(this._type)
|
||||||
{
|
{
|
||||||
case "date-timeonly":
|
case "date-timeonly":
|
||||||
var parsed = jQuery.datepicker.parseTime(this.input_date.datepicker('option', 'timeFormat'), _value);
|
var parsed = jQuery.datepicker.parseTime(this.timeFormat, _value);
|
||||||
if (!parsed) // parseTime returns false
|
if (!parsed) // parseTime returns false
|
||||||
{
|
{
|
||||||
this.set_validation_error(this.egw().lang("'%1' has an invalid format !!!",_value));
|
this.set_validation_error(this.egw().lang("'%1' has an invalid format !!!",_value));
|
||||||
@ -448,8 +491,8 @@ String: A string in the user\'s date format, or a relative date. Relative dates
|
|||||||
}
|
}
|
||||||
else // Parse other date widgets date with timepicker date/time format to date onject
|
else // Parse other date widgets date with timepicker date/time format to date onject
|
||||||
{
|
{
|
||||||
var parsed = jQuery.datepicker.parseDateTime(this.input_date.datepicker('option', 'dateFormat'),
|
var parsed = jQuery.datepicker.parseDateTime(this.dateFormat,
|
||||||
this.input_date.datepicker('option', 'timeFormat'), _value);
|
this.timeFormat, _value.replace('T', ' '));
|
||||||
if(!parsed)
|
if(!parsed)
|
||||||
{
|
{
|
||||||
this.set_validation_error(this.egw().lang("%1' han an invalid format !!!",_value));
|
this.set_validation_error(this.egw().lang("%1' han an invalid format !!!",_value));
|
||||||
@ -486,15 +529,13 @@ String: A string in the user\'s date format, or a relative date. Relative dates
|
|||||||
var formatDate = new Date(this.date.valueOf() + this.date.getTimezoneOffset() * 60 * 1000);
|
var formatDate = new Date(this.date.valueOf() + this.date.getTimezoneOffset() * 60 * 1000);
|
||||||
if(this._type != 'date-timeonly')
|
if(this._type != 'date-timeonly')
|
||||||
{
|
{
|
||||||
_value = jQuery.datepicker.formatDate(this.input_date.datepicker("option","dateFormat"),
|
_value = jQuery.datepicker.formatDate(this.dateFormat, formatDate);
|
||||||
formatDate
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if(this._type != 'date')
|
if(this._type != 'date')
|
||||||
{
|
{
|
||||||
if(this._type != 'date-timeonly') _value += ' ';
|
if(this._type != 'date-timeonly') _value += this.is_mobile ? 'T' : ' ';
|
||||||
|
|
||||||
_value += jQuery.datepicker.formatTime(this.input_date.datepicker("option","timeFormat"),{
|
_value += jQuery.datepicker.formatTime(this.timeFormat, {
|
||||||
hour: formatDate.getHours(),
|
hour: formatDate.getHours(),
|
||||||
minute: formatDate.getMinutes(),
|
minute: formatDate.getMinutes(),
|
||||||
seconds: 0,
|
seconds: 0,
|
||||||
|
Loading…
Reference in New Issue
Block a user