2011-08-22 20:18:29 +02:00
/ * *
2013-04-13 21:00:13 +02:00
* EGroupware eTemplate2 - JS Date object
2011-08-22 20:18:29 +02:00
*
* @ license http : //opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @ package etemplate
* @ subpackage api
* @ link http : //www.egroupware.org
* @ author Nathan Gray
* @ copyright Nathan Gray 2011
* @ version $Id$
* /
"use strict" ;
/ * e g w : u s e s
jquery . jquery ;
2012-03-09 01:36:35 +01:00
jquery . jquery - ui ;
2011-08-29 23:15:53 +02:00
lib / date ;
2011-08-24 12:18:07 +02:00
et2 _core _inputWidget ;
et2 _core _valueWidget ;
2011-08-22 20:18:29 +02:00
* /
/ * *
* Class which implements the "date" XET - Tag
2013-09-12 13:45:26 +02:00
*
2014-08-21 20:46:11 +02:00
* Dates are passed to the server in ISO8601 format ( "Y-m-d\TH:i:sP" ) , and data _format is
* handled server - side .
*
2013-04-13 21:00:13 +02:00
* @ augments et2 _inputWidget
2013-09-12 13:45:26 +02:00
* /
2013-04-13 21:00:13 +02:00
var et2 _date = et2 _inputWidget . extend (
{
2011-08-22 20:18:29 +02:00
attributes : {
"value" : {
"type" : "any"
} ,
"type" : {
"ignore" : false
2013-02-11 09:08:28 +01:00
} ,
"data_format" : {
2014-08-21 20:46:11 +02:00
"ignore" : true ,
2014-05-08 19:48:54 +02:00
"description" : "Date/Time format. Can be set as an options to date widget" ,
"default" : ''
2011-08-22 20:18:29 +02:00
}
} ,
2013-02-11 09:08:28 +01:00
legacyOptions : [ "data_format" ] ,
2013-04-13 21:00:13 +02:00
/ * *
* Constructor
2013-09-12 13:45:26 +02:00
*
2013-04-13 21:00:13 +02:00
* @ memberOf et2 _date
* /
2011-08-24 12:05:52 +02:00
init : function ( ) {
2011-08-22 20:18:29 +02:00
this . _super . apply ( this , arguments ) ;
2012-03-09 01:36:35 +01:00
this . date = new Date ( ) ;
2014-08-21 20:46:11 +02:00
this . date . setUTCHours ( 0 ) ;
2012-03-09 01:36:35 +01:00
this . date . setMinutes ( 0 ) ;
this . date . setSeconds ( 0 ) ;
2011-08-22 20:18:29 +02:00
this . input = null ;
this . createInputWidget ( ) ;
} ,
createInputWidget : function ( ) {
2011-08-29 23:15:53 +02:00
2012-03-09 01:36:35 +01:00
this . span = $j ( document . createElement ( "span" ) ) . addClass ( "et2_date" ) ;
2011-08-22 20:18:29 +02:00
2012-03-12 22:20:46 +01:00
this . input _date = $j ( document . createElement ( "input" ) ) ;
2014-01-30 16:30:14 +01:00
this . input _date . addClass ( "et2_date" ) . attr ( "type" , "text" )
. attr ( "size" , 7 ) // strlen("10:00pm")=7
2012-03-12 22:20:46 +01:00
. appendTo ( this . span ) ;
2012-03-09 01:36:35 +01:00
this . setDOMNode ( this . span [ 0 ] ) ;
// jQuery-UI date picker
2012-03-12 22:20:46 +01:00
if ( this . _type != 'date-timeonly' )
2011-08-31 21:58:38 +02:00
{
2012-03-12 22:20:46 +01:00
this . egw ( ) . calendar ( this . input _date , this . _type == "date-time" ) ;
2011-08-31 21:58:38 +02:00
}
2012-03-12 22:20:46 +01:00
else
2011-08-31 21:58:38 +02:00
{
2013-08-20 11:42:00 +02:00
this . input _date . addClass ( "et2_time" ) ;
2012-03-12 22:20:46 +01:00
this . egw ( ) . time ( this . input _date ) ;
2011-08-31 21:58:38 +02:00
}
2012-03-28 21:05:48 +02:00
// Update internal value when changed
2012-03-20 15:51:02 +01:00
var self = this ;
2014-01-29 12:27:24 +01:00
this . input _date . bind ( 'change' , function ( e ) {
self . set _value ( this . value ) ;
2014-01-29 14:10:31 +01:00
return false ;
2012-03-20 15:51:02 +01:00
} ) ;
2012-03-28 21:05:48 +02:00
// Framewok skips nulls, but null needs to be processed here
if ( this . options . value == null )
{
this . set _value ( null ) ;
}
2011-08-31 21:58:38 +02:00
} ,
2012-03-12 22:20:46 +01:00
2011-08-22 20:18:29 +02:00
set _type : function ( _type ) {
2012-03-22 16:56:16 +01:00
if ( _type != this . _type )
{
2012-03-29 01:05:42 +02:00
this . _type = _type ;
2012-03-22 16:56:16 +01:00
this . createInputWidget ( ) ;
}
2011-08-22 20:18:29 +02:00
} ,
2014-05-26 15:44:24 +02:00
2014-09-05 12:35:08 +02:00
/ * *
* Set ( full ) year of current date
*
* @ param { number } _value 4 - digit year
* /
set _year : function ( _value )
{
this . date . setUTCFullYear ( _value ) ;
this . set _value ( this . date ) ;
} ,
/ * *
* Set month ( 1. . 12 ) of current date
*
* @ param { number } _value 1. . 12
* /
set _month : function ( _value )
{
this . date . setUTCMonth ( _value - 1 ) ;
this . set _value ( this . date ) ;
} ,
/ * *
* Set day of current date
*
* @ param { number } _value 1. . 31
* /
set _date : function ( _value )
{
this . date . setUTCDate ( _value ) ;
this . set _value ( this . date ) ;
} ,
/ * *
* Set hour ( 0. . 23 ) of current date
*
* @ param { number } _value 0. . 23
* /
set _hours : function ( _value )
{
this . date . setUTCHours ( _value ) ;
this . set _value ( this . date ) ;
} ,
/ * *
* Set minute ( 0. . 59 ) of current date
*
* @ param { number } _value 0. . 59
* /
set _minutes : function ( _value )
{
this . date . setUTCMinutes ( _value ) ;
this . set _value ( this . date ) ;
} ,
/ * *
* Get ( full ) year of current date
*
* @ return { number | null } 4 - digit year or null for empty
* /
get _year : function ( )
{
return this . input _date . val ( ) == "" ? null : this . date . getUTCFullYear ( ) ;
} ,
/ * *
* Get month ( 1. . 12 ) of current date
*
* @ return { number | null } 1. . 12 or null for empty
* /
get _month : function ( )
{
return this . input _date . val ( ) == "" ? null : this . date . getUTCMonth ( ) + 1 ;
} ,
/ * *
* Get day of current date
*
* @ return { number | null } 1. . 31 or null for empty
* /
get _date : function ( )
{
return this . input _date . val ( ) == "" ? null : this . date . getUTCDate ( ) ;
} ,
/ * *
* Get hour ( 0. . 23 ) of current date
*
* @ return { number | null } 0. . 23 or null for empty
* /
get _hours : function ( )
{
return this . input _date . val ( ) == "" ? null : this . date . getUTCHours ( ) ;
} ,
/ * *
* Get minute ( 0. . 59 ) of current date
*
* @ return { number | null } 0. . 59 or null for empty
* /
get _minutes : function ( )
{
return this . input _date . val ( ) == "" ? null : this . date . getUTCMinutes ( ) ;
} ,
/ * *
* Get timestamp
*
* You can use set _value to set a timestamp .
*
2014-09-10 12:25:06 +02:00
* @ return { number | null } timestamp ( seconds since 1970 - 01 - 01 )
2014-09-05 12:35:08 +02:00
* /
get _time : function ( )
{
return this . input _date . val ( ) == "" ? null : this . date . getTime ( ) ;
} ,
2014-09-04 16:34:06 +02:00
/ * *
* Setting date
*
* @ param { string | number | Date } _value supported are the following formats :
* - Date object with usertime as UTC value
* - string like Date . toJSON ( )
* - 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
* /
2011-08-22 20:18:29 +02:00
set _value : function ( _value ) {
2014-08-26 15:38:42 +02:00
var old _value = this . _oldValue ;
2014-01-30 18:18:05 +01:00
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
_value == 0 && ( this . _type == 'date-time' || this . _type == 'date' ) )
2011-10-12 22:04:16 +02:00
{
if ( this . input _date )
{
this . input _date . val ( "" ) ;
}
2014-01-30 16:30:14 +01:00
if ( this . _oldValue !== et2 _no _init && old _value !== _value )
2012-03-20 18:45:51 +01:00
{
2012-03-20 22:46:22 +01:00
this . change ( this . input _date ) ;
2012-03-20 18:45:51 +01:00
}
2014-01-30 16:30:14 +01:00
this . _oldValue = _value ;
2011-10-12 22:04:16 +02:00
return ;
}
2014-09-30 22:13:15 +02:00
// timestamp in usertime, convert to 'Y-m-d\\TH:i:s\\Z', as we do on server-side with equivalent of PHP date()
if ( typeof _value == 'number' || typeof _value == 'string' && ! isNaN ( _value ) && _value [ 0 ] != '+' && _value [ 0 ] != '-' )
{
_value = date ( 'Y-m-d\\TH:i:s\\Z' , _value ) ;
}
2014-08-21 20:46:11 +02:00
// Check for full timestamp
2014-08-26 15:38:42 +02:00
if ( typeof _value == 'string' && _value . match ( /(\d{4})-(\d{2})-(\d{2})T(\d{2})\:(\d{2})\:(\d{2})(?:\.\d{3})?(?:Z|[+-](\d{2})\:(\d{2}))/ ) )
2014-08-21 20:46:11 +02:00
{
_value = new Date ( _value ) ;
}
2011-08-31 21:58:38 +02:00
// Handle just time as a string in the form H:i
2014-05-26 15:44:24 +02:00
if ( typeof _value == 'string' && isNaN ( _value ) )
2014-05-08 19:48:54 +02:00
{
2014-11-12 20:24:06 +01:00
try {
// silently fix skiped minutes or times with just one digit, as parser is quite pedantic ;-)
var fix _reg = new RegExp ( ( this . _type == "date-timeonly" ? '^' : ' ' ) + '([0-9]+)(:[0-9]*)?( ?(a|p)m?)?$' , 'i' ) ;
var matches = _value . match ( fix _reg ) ;
if ( matches && ( matches [ 1 ] . length < 2 || matches [ 2 ] === undefined || matches [ 2 ] . length < 3 ||
matches [ 3 ] && matches [ 3 ] != 'am' && matches [ 3 ] != 'pm' ) )
{
if ( matches [ 1 ] . length < 2 && ! matches [ 3 ] ) matches [ 1 ] = '0' + matches [ 1 ] ;
if ( matches [ 2 ] === undefined ) matches [ 2 ] = ':00' ;
while ( matches [ 2 ] . length < 3 ) matches [ 2 ] = ':0' + matches [ 2 ] . substr ( 1 ) ;
_value = _value . replace ( fix _reg , ( this . _type == "date-timeonly" ? '' : ' ' ) + matches [ 1 ] + matches [ 2 ] + matches [ 3 ] ) ;
if ( matches [ 4 ] !== undefined ) matches [ 3 ] = matches [ 4 ] . toLowerCase ( ) == 'a' ? 'am' : 'pm' ;
}
switch ( this . _type )
{
case "date-timeonly" :
var parsed = jQuery . datepicker . parseTime ( this . input _date . datepicker ( 'option' , 'timeFormat' ) , _value ) ;
if ( ! parsed ) // parseTime returns false
{
this . set _validation _error ( this . egw ( ) . lang ( "'%1' has an invalid format !!!" , _value ) ) ;
return ;
}
this . set _validation _error ( false ) ;
// this.date is on current date, changing it in get_value() to 1970-01-01, gives a time-difference, if we are currently on DST
this . date . setDate ( 1 ) ;
this . date . setMonth ( 0 ) ;
this . date . setFullYear ( 1970 ) ;
// Avoid javascript timezone offset, hour is in 'user time'
this . date . setUTCHours ( parsed . hour ) ;
this . date . setMinutes ( parsed . minute ) ;
if ( this . input _date . val ( ) != _value )
{
this . input _date . val ( _value ) ;
this . input _date . timepicker ( 'setTime' , _value ) ;
if ( this . _oldValue !== et2 _no _init )
{
this . change ( this . input _date ) ;
}
}
this . _oldValue = this . date . toJSON ( ) ;
2014-05-08 19:48:54 +02:00
return ;
2014-11-12 20:24:06 +01:00
default :
// Parse customfields's date with storage data_format to date object
// Or generally any date widgets with fixed date/time format
if ( this . id . match ( /^#/g ) && this . options . value == _value || ( this . options . data _format && this . options . value == _value ) )
2014-05-08 19:48:54 +02:00
{
2014-11-12 20:24:06 +01:00
switch ( this . _type )
{
case 'date' :
var parsed = jQuery . datepicker . parseDate ( this . egw ( ) . dateTimeFormat ( this . options . data _format ) , _value ) ;
break ;
case 'date-time' :
var DTformat = this . options . data _format . split ( ' ' ) ;
var parsed = jQuery . datepicker . parseDateTime ( this . egw ( ) . dateTimeFormat ( DTformat [ 0 ] ) , this . egw ( ) . dateTimeFormat ( DTformat [ 1 ] ) , _value ) ;
}
2014-05-08 19:48:54 +02:00
}
2014-11-12 20:24:06 +01:00
else // Parse other date widgets date with timepicker date/time format to date onject
2014-05-08 19:48:54 +02:00
{
2014-11-12 20:24:06 +01:00
var parsed = jQuery . datepicker . parseDateTime ( this . input _date . datepicker ( 'option' , 'dateFormat' ) ,
this . input _date . datepicker ( 'option' , 'timeFormat' ) , _value ) ;
if ( ! parsed )
{
this . set _validation _error ( this . egw ( ) . lang ( "%1' han an invalid format !!!" , _value ) ) ;
return ;
}
2014-05-08 19:48:54 +02:00
}
2014-11-12 20:24:06 +01:00
// Update local variable, but remove the timezone offset that
// javascript adds when we parse
if ( parsed )
2014-05-08 19:48:54 +02:00
{
2014-11-12 20:24:06 +01:00
this . date = new Date ( parsed . valueOf ( ) - parsed . getTimezoneOffset ( ) * 60000 ) ;
2014-05-08 19:48:54 +02:00
}
2014-11-12 20:24:06 +01:00
this . set _validation _error ( false ) ;
}
}
// catch exception from unparsable date and display it empty instead
catch ( e ) {
return this . set _value ( null ) ;
2011-08-29 23:15:53 +02:00
}
2011-08-31 21:58:38 +02:00
} else if ( typeof _value == 'object' && _value . date ) {
this . date = _value . date ;
2012-03-09 01:36:35 +01:00
} else if ( typeof _value == 'object' && _value . valueOf ) {
this . date = _value ;
2014-09-30 22:13:15 +02:00
} else
// string starting with + or - --> add/substract number of seconds from current value
{
this . date . setTime ( this . date . getTime ( ) + 1000 * parseInt ( _value ) ) ;
2011-08-22 20:18:29 +02:00
}
2012-03-20 15:51:02 +01:00
// Update input - popups do, but framework doesn't
2014-01-30 17:24:58 +01:00
_value = '' ;
2014-08-21 20:46:11 +02:00
// Add timezone offset back in, or formatDate will lose those hours
var formatDate = new Date ( this . date . valueOf ( ) + this . date . getTimezoneOffset ( ) * 60 * 1000 ) ;
2012-03-20 15:51:02 +01:00
if ( this . _type != 'date-timeonly' )
{
2014-08-21 20:46:11 +02:00
_value = jQuery . datepicker . formatDate ( this . input _date . datepicker ( "option" , "dateFormat" ) ,
formatDate
) ;
2012-03-20 15:51:02 +01:00
}
if ( this . _type != 'date' )
{
2014-01-30 17:24:58 +01:00
if ( this . _type != 'date-timeonly' ) _value += ' ' ;
_value += jQuery . datepicker . formatTime ( this . input _date . datepicker ( "option" , "timeFormat" ) , {
2014-08-21 20:46:11 +02:00
hour : formatDate . getHours ( ) ,
minute : formatDate . getMinutes ( ) ,
2014-01-30 16:30:14 +01:00
seconds : 0 ,
timezone : 0
} ) ;
2012-03-20 15:51:02 +01:00
}
2014-01-30 17:24:58 +01:00
this . input _date . val ( _value ) ;
2014-01-30 16:30:14 +01:00
if ( this . _oldValue !== et2 _no _init && old _value != this . getValue ( ) )
2012-03-20 18:45:51 +01:00
{
this . change ( this . input _date ) ;
}
2014-01-30 17:24:58 +01:00
this . _oldValue = _value ;
2011-08-31 02:08:59 +02:00
} ,
getValue : function ( ) {
2012-03-20 22:46:22 +01:00
if ( this . input _date . val ( ) == "" )
{
// User blanked the box
return null ;
}
2014-01-30 16:30:14 +01:00
// date-timeonly returns just the seconds, without any date!
if ( this . _type == 'date-timeonly' )
{
this . date . setDate ( 1 ) ;
this . date . setMonth ( 0 ) ;
this . date . setFullYear ( 1970 ) ;
}
2014-07-25 12:17:38 +02:00
else if ( this . _type == 'date' )
{
2014-08-21 20:46:11 +02:00
this . date . setUTCHours ( 0 ) ;
this . date . setUTCMinutes ( 0 ) ;
2014-07-25 12:17:38 +02:00
}
2014-08-27 18:57:44 +02:00
2014-01-14 13:35:28 +01:00
// Convert to timestamp - no seconds
this . date . setSeconds ( 0 , 0 ) ;
2014-12-05 12:07:08 +01:00
return this . date ? this . date . toJSON ( ) . replace ( /\.\d{3}Z$/ , 'Z' ) : this . date ;
2011-08-22 20:18:29 +02:00
}
} ) ;
et2 _register _widget ( et2 _date , [ "date" , "date-time" , "date-timeonly" ] ) ;
2013-04-13 21:00:13 +02:00
/ * *
* @ augments et2 _date
* /
var et2 _date _duration = et2 _date . extend (
{
2011-08-30 22:50:55 +02:00
attributes : {
"data_format" : {
"name" : "Data format" ,
"default" : "m" ,
"type" : "string" ,
"description" : "Units to read/store the data. 'd' = days (float), 'h' = hours (float), 'm' = minutes (int)."
} ,
"display_format" : {
"name" : "Display format" ,
2014-05-30 15:40:13 +02:00
"default" : "dhm" ,
2011-08-30 22:50:55 +02:00
"type" : "string" ,
"description" : "Permitted units for displaying the data. 'd' = days, 'h' = hours, 'm' = minutes. Use combinations to give a choice. Default is 'dh' = days or hours with selectbox."
} ,
"percent_allowed" : {
"name" : "Percent allowed" ,
"default" : false ,
"type" : "boolean" ,
"description" : "Allows to enter a percentage."
} ,
"hours_per_day" : {
"name" : "Hours per day" ,
"default" : 8 ,
"type" : "integer" ,
"description" : "Number of hours in a day, for converting between hours and (working) days."
} ,
"empty_not_0" : {
"name" : "0 or empty" ,
"default" : false ,
"type" : "boolean" ,
"description" : "Should the widget differ between 0 and empty, which get then returned as NULL"
} ,
"short_labels" : {
"name" : "Short labels" ,
"default" : false ,
"type" : "boolean" ,
"description" : "use d/h/m instead of day/hour/minute"
}
} ,
legacyOptions : [ "data_format" , "display_format" , "hours_per_day" , "empty_not_0" , "short_labels" ] ,
2011-09-08 19:11:49 +02:00
time _formats : { "d" : "d" , "h" : "h" , "m" : "m" } ,
2013-04-13 21:00:13 +02:00
/ * *
* Constructor
2013-09-12 13:45:26 +02:00
*
2013-04-13 21:00:13 +02:00
* @ memberOf et2 _date _duration
* /
2011-08-30 22:50:55 +02:00
init : function ( ) {
this . _super . apply ( this , arguments ) ;
this . input = null ;
// Legacy option put percent in with display format
if ( this . options . display _format . indexOf ( "%" ) != - 1 )
{
this . options . percent _allowed = true ;
this . options . display _format = this . options . display _format . replace ( "%" , "" ) ;
}
2011-09-08 19:11:49 +02:00
2012-03-30 16:30:26 +02:00
// Clean formats
this . options . display _format = this . options . display _format . replace ( /[^dhm]/ , '' ) ;
if ( ! this . options . display _format )
{
this . options . display _format = this . attributes . display _format [ "default" ] ;
}
2011-09-08 19:11:49 +02:00
// Get translations
this . time _formats = {
2012-03-02 11:44:56 +01:00
"d" : this . options . short _labels ? this . egw ( ) . lang ( "m" ) : this . egw ( ) . lang ( "Days" ) ,
"h" : this . options . short _labels ? this . egw ( ) . lang ( "h" ) : this . egw ( ) . lang ( "Hours" ) ,
"m" : this . options . short _labels ? this . egw ( ) . lang ( "m" ) : this . egw ( ) . lang ( "Minutes" )
2011-09-08 19:11:49 +02:00
} ,
2011-08-30 22:50:55 +02:00
this . createInputWidget ( ) ;
} ,
2013-09-12 13:45:26 +02:00
2011-08-30 22:50:55 +02:00
createInputWidget : function ( ) {
// Create nodes
2014-03-10 16:20:40 +01:00
this . node = $j ( document . createElement ( "span" ) )
. addClass ( 'et2_date_duration' ) ;
2014-01-30 17:24:58 +01:00
this . duration = $j ( document . createElement ( "input" ) )
2014-03-10 16:20:40 +01:00
. addClass ( 'et2_date_duration' )
2014-03-12 14:13:18 +01:00
. attr ( { type : 'number' , size : 3 } ) ;
2011-08-30 22:50:55 +02:00
this . node . append ( this . duration ) ;
if ( this . options . display _format . length > 1 )
{
2014-03-10 16:20:40 +01:00
this . format = $j ( document . createElement ( "select" ) )
. addClass ( 'et2_date_duration' ) ;
2011-08-30 22:50:55 +02:00
this . node . append ( this . format ) ;
for ( var i = 0 ; i < this . options . display _format . length ; i ++ ) {
2011-09-08 19:11:49 +02:00
this . format . append ( "<option value='" + this . options . display _format [ i ] + "'>" + this . time _formats [ this . options . display _format [ i ] ] + "</option>" ) ;
2011-08-30 22:50:55 +02:00
}
2012-03-30 16:30:26 +02:00
}
else if ( this . time _formats [ this . options . display _format ] )
{
this . format = $j ( "<span>" + this . time _formats [ this . options . display _format ] + "</span>" ) . appendTo ( this . node ) ;
}
else
{
this . format = $j ( "<span>" + this . time _formats [ "m" ] + "</span>" ) . appendTo ( this . node ) ;
2011-08-30 22:50:55 +02:00
}
} ,
attachToDOM : function ( ) {
var node = this . getInputNode ( ) ;
2013-02-05 09:55:09 +01:00
if ( node )
{
$j ( node ) . bind ( "change.et2_inputWidget" , this , function ( e ) {
e . data . change ( this ) ;
} ) ;
}
2011-08-30 22:50:55 +02:00
et2 _DOMWidget . prototype . attachToDOM . apply ( this , arguments ) ;
} ,
getDOMNode : function ( ) {
return this . node [ 0 ] ;
} ,
getInputNode : function ( ) {
return this . duration [ 0 ] ;
} ,
/ * *
* Use id on node , same as DOMWidget
2014-01-29 19:55:24 +01:00
*
* @ param { string } _value id to set
2011-08-30 22:50:55 +02:00
* /
set _id : function ( _value ) {
this . id = _value ;
2013-02-05 09:55:09 +01:00
var node = this . getDOMNode ( this ) ;
if ( node )
{
if ( _value != "" )
{
2013-07-17 15:08:48 +02:00
node . setAttribute ( "id" , this . getInstanceManager ( ) . uniqueId + '_' + this . id ) ;
2013-02-05 09:55:09 +01:00
}
else
{
node . removeAttribute ( "id" ) ;
}
}
2011-08-30 22:50:55 +02:00
} ,
set _value : function ( _value ) {
this . options . value = _value ;
2011-09-08 19:11:49 +02:00
var display = this . _convert _to _display ( _value ) ;
// Set display
if ( this . duration [ 0 ] . nodeName == "INPUT" )
{
this . duration . val ( display . value ) ;
}
else
{
this . duration . text ( display . value + " " ) ;
}
// Set unit as figured for display
if ( display . unit != this . options . display _format )
{
2012-03-30 16:30:26 +02:00
if ( this . format && this . format . children ( ) . length > 1 ) {
2011-09-08 19:11:49 +02:00
$j ( "option[value='" + display . unit + "']" , this . format ) . attr ( 'selected' , 'selected' ) ;
}
else
{
this . format . text ( this . time _formats [ display . unit ] ) ;
}
}
} ,
/ * *
* Converts the value in data format into value in display format .
*
* @ param _value int / float Data in data format
*
* @ return Object { value : Value in display format , unit : unit for display }
* /
_convert _to _display : function ( _value ) {
2011-08-30 22:50:55 +02:00
if ( _value )
2013-02-05 09:55:09 +01:00
{
2011-08-30 22:50:55 +02:00
// Put value into minutes for further processing
2013-02-05 09:55:09 +01:00
switch ( this . options . data _format )
2011-08-30 22:50:55 +02:00
{
case 'd' :
_value *= this . options . hours _per _day ;
// fall-through
case 'h' :
_value *= 60 ;
break ;
}
2013-02-05 09:55:09 +01:00
}
2011-08-30 22:50:55 +02:00
// Figure out best unit for display
var _unit = this . options . display _format == "d" ? "d" : "h" ;
2014-05-26 15:44:24 +02:00
if ( this . options . display _format . indexOf ( 'm' ) > - 1 && _value && _value < 60 )
2013-02-05 09:55:09 +01:00
{
_unit = 'm' ;
}
2014-05-26 15:44:24 +02:00
else if ( this . options . display _format . indexOf ( 'd' ) > - 1 && _value >= 60 * this . options . hours _per _day )
2013-02-05 09:55:09 +01:00
{
_unit = 'd' ;
}
2011-08-30 22:50:55 +02:00
_value = this . options . empty _not _0 && _value === '' || ! this . options . empty _not _0 && ! _value ? '' :
2013-02-05 09:55:09 +01:00
( _unit == 'm' ? parseInt ( _value ) : ( Math . round ( ( _value / 60.0 / ( _unit == 'd' ? this . options . hours _per _day : 1 ) ) * 100 ) / 100 ) ) ;
2011-09-22 23:28:26 +02:00
if ( _value === '' ) _unit = '' ;
2013-02-05 09:55:09 +01:00
// use decimal separator from user prefs
2012-03-02 11:44:56 +01:00
var format = this . egw ( ) . preference ( 'number_format' ) ;
2014-01-29 19:55:24 +01:00
var sep = format ? format [ 0 ] : '.' ;
if ( typeof _value == 'string' && format && sep && sep != '.' )
2013-02-05 09:55:09 +01:00
{
_value = _value . replace ( '.' , sep ) ;
}
2011-08-30 22:50:55 +02:00
2011-09-08 19:11:49 +02:00
return { value : _value , unit : _unit } ;
2011-08-30 22:50:55 +02:00
} ,
2013-09-12 13:45:26 +02:00
2011-08-30 22:50:55 +02:00
/ * *
* Change displayed value into storage value and return
* /
getValue : function ( ) {
2014-01-30 17:24:58 +01:00
var value = this . duration . val ( ) . replace ( ',' , '.' ) ;
2011-08-30 22:50:55 +02:00
if ( value === '' )
{
2014-06-11 11:14:43 +02:00
return this . options . empty _not _0 ? '' : 0 ;
2011-08-30 22:50:55 +02:00
}
// Put value into minutes for further processing
2014-08-27 18:32:20 +02:00
switch ( this . format && this . format . val ( ) ? this . format . val ( ) : this . options . display _format )
2011-08-30 22:50:55 +02:00
{
case 'd' :
value *= this . options . hours _per _day ;
// fall-through
case 'h' :
value *= 60 ;
break ;
}
switch ( this . options . data _format )
{
case 'd' :
value /= this . options . hours _per _day ;
// fall-through
case 'h' :
value /= 60.0 ;
break ;
}
return value ;
}
} ) ;
et2 _register _widget ( et2 _date _duration , [ "date-duration" ] ) ;
2013-04-13 21:00:13 +02:00
/ * *
* @ augments et2 _date _duration
* /
var et2 _date _duration _ro = et2 _date _duration . extend ( [ et2 _IDetachedDOM ] ,
{
/ * *
* @ memberOf et2 _date _duration _ro
* /
2011-09-08 19:11:49 +02:00
createInputWidget : function ( ) {
this . node = $j ( document . createElement ( "span" ) ) ;
this . duration = $j ( document . createElement ( "span" ) ) . appendTo ( this . node ) ;
this . format = $j ( document . createElement ( "span" ) ) . appendTo ( this . node ) ;
} ,
/ * *
2013-09-12 13:45:26 +02:00
* Code for implementing et2 _IDetachedDOM
2011-09-08 19:11:49 +02:00
* Fast - clonable read - only widget that only deals with DOM nodes , not the widget tree
* /
/ * *
* Build a list of attributes which can be set when working in the
* "detached" mode in the _attrs array which is provided
* by the calling code .
2014-01-29 19:55:24 +01:00
*
* @ param { array } _attrs array to add further attributes to
2011-09-08 19:11:49 +02:00
* /
getDetachedAttributes : function ( _attrs ) {
_attrs . push ( "value" ) ;
} ,
/ * *
* Returns an array of DOM nodes . The ( relativly ) same DOM - Nodes have to be
* passed to the "setDetachedAttributes" function in the same order .
2014-01-29 19:55:24 +01:00
*
* @ return { array }
2011-09-08 19:11:49 +02:00
* /
getDetachedNodes : function ( ) {
return [ this . duration [ 0 ] , this . format [ 0 ] ] ;
} ,
/ * *
* Sets the given associative attribute - > value array and applies the
* attributes to the given DOM - Node .
*
* @ param _nodes is an array of nodes which has to be in the same order as
* the nodes returned by "getDetachedNodes"
* @ param _values is an associative array which contains a subset of attributes
* returned by the "getDetachedAttributes" function and sets them to the
* given values .
* /
setDetachedAttributes : function ( _nodes , _values ) {
for ( var i = 0 ; i < _nodes . length ; i ++ ) {
// Clear the node
2011-09-13 19:37:29 +02:00
for ( var j = _nodes [ i ] . childNodes . length - 1 ; j >= 0 ; j -- )
2011-09-08 19:11:49 +02:00
{
2011-09-13 19:37:29 +02:00
_nodes [ i ] . removeChild ( _nodes [ i ] . childNodes [ j ] ) ;
2011-09-08 19:11:49 +02:00
}
}
2012-03-13 20:38:48 +01:00
if ( typeof _values . value !== 'undefined' )
2013-09-12 13:45:26 +02:00
{
2012-04-04 22:05:53 +02:00
_values . value = parseFloat ( _values . value ) ;
}
if ( _values . value )
2012-03-13 20:38:48 +01:00
{
var display = this . _convert _to _display ( _values . value ) ;
_nodes [ 0 ] . appendChild ( document . createTextNode ( display . value ) ) ;
_nodes [ 1 ] . appendChild ( document . createTextNode ( display . unit ) ) ;
}
2011-09-08 19:11:49 +02:00
}
} ) ;
et2 _register _widget ( et2 _date _duration _ro , [ "date-duration_ro" ] ) ;
2011-08-22 20:18:29 +02:00
/ * *
2011-08-31 22:32:24 +02:00
* et2 _date _ro is the readonly implementation of some date widget .
2013-04-13 21:00:13 +02:00
* @ augments et2 _valueWidget
2011-08-22 20:18:29 +02:00
* /
2013-09-12 13:45:26 +02:00
var et2 _date _ro = et2 _valueWidget . extend ( [ et2 _IDetachedDOM ] ,
2013-04-13 21:00:13 +02:00
{
2011-08-22 20:18:29 +02:00
/ * *
* Ignore all more advanced attributes .
* /
attributes : {
"value" : {
2014-09-08 13:38:23 +02:00
"type" : "string"
2011-08-22 20:18:29 +02:00
} ,
"type" : {
"ignore" : false
2013-02-11 09:08:28 +01:00
} ,
"data_format" : {
"ignore" : true ,
"description" : "Format data is in. This is not used client-side because it's always a timestamp client side."
2011-08-22 20:18:29 +02:00
}
} ,
2013-02-11 09:08:28 +01:00
legacyOptions : [ "data_format" ] ,
2011-08-22 20:18:29 +02:00
/ * *
* Internal container for working easily with dates
* /
date : new Date ( ) ,
2013-04-13 21:00:13 +02:00
/ * *
* Constructor
2013-09-12 13:45:26 +02:00
*
2013-04-13 21:00:13 +02:00
* @ memberOf et2 _date _ro
* /
2011-08-22 20:18:29 +02:00
init : function ( ) {
this . _super . apply ( this , arguments ) ;
2014-07-23 14:54:02 +02:00
this . _labelContainer = $j ( document . createElement ( "label" ) )
2014-02-21 13:22:33 +01:00
. addClass ( "et2_label" ) ;
2011-08-22 20:18:29 +02:00
this . value = "" ;
2013-02-08 12:10:45 +01:00
this . span = $j ( document . createElement ( this . _type == "date-since" || this . _type == "date-time_today" ? "span" : "time" ) )
2014-02-21 13:22:33 +01:00
. addClass ( "et2_date_ro et2_label" )
2014-07-23 14:54:02 +02:00
. appendTo ( this . _labelContainer ) ;
2011-08-22 20:18:29 +02:00
2014-07-23 14:54:02 +02:00
this . setDOMNode ( this . _labelContainer [ 0 ] ) ;
2011-08-22 20:18:29 +02:00
} ,
set _value : function ( _value ) {
2011-09-12 17:21:42 +02:00
if ( typeof _value == 'undefined' ) _value = 0 ;
2011-08-22 20:18:29 +02:00
this . value = _value ;
2011-09-12 17:21:42 +02:00
2011-10-19 17:15:54 +02:00
if ( _value == 0 || _value == null )
2011-09-12 17:21:42 +02:00
{
2012-03-22 16:56:16 +01:00
this . span . attr ( "datetime" , "" ) . text ( "" ) ;
2011-09-12 17:21:42 +02:00
return ;
}
2014-09-08 13:38:23 +02:00
if ( typeof _value == 'string' && _value . match ( /(\d{4})-(\d{2})-(\d{2})T(\d{2})\:(\d{2})\:(\d{2})(?:\.\d{3})?(?:Z|[+-](\d{2})\:(\d{2}))/ ) )
{
this . date = new Date ( _value ) ;
2014-09-08 13:41:18 +02:00
this . date = new Date ( this . date . valueOf ( ) + ( this . date . getTimezoneOffset ( ) * 60 * 1000 ) ) ;
2014-09-08 13:38:23 +02:00
}
else if ( typeof _value == 'string' && isNaN ( _value ) )
2012-03-08 01:20:04 +01:00
{
2014-11-12 20:24:06 +01:00
try {
// parseDateTime to handle string PHP: DateTime local date/time format
var parsed = ( typeof jQuery . datepicker . parseDateTime ( "yy-mm-dd" , "hh:mm:ss" , _value ) != 'undefined' ) ?
jQuery . datepicker . parseDateTime ( "yy-mm-dd" , "hh:mm:ss" , _value ) :
jQuery . datepicker . parseDateTime ( this . egw ( ) . preference ( 'dateformat' ) , this . egw ( ) . preference ( 'timeformat' ) == '24' ? 'H:i' : 'g:i a' , _value ) ;
}
// display unparsable dates as empty
catch ( e ) {
this . span . attr ( "datetime" , "" ) . text ( "" ) ;
return ;
}
2014-05-05 16:09:47 +02:00
var text = new Date ( parsed ) ;
2014-08-21 20:46:11 +02:00
// Update local variable, but remove the timezone offset that javascript adds
if ( parsed )
{
this . date = new Date ( text . valueOf ( ) - ( text . getTimezoneOffset ( ) * 60 * 1000 ) ) ;
}
2012-03-08 01:20:04 +01:00
// JS dates use milliseconds
2014-05-05 16:09:47 +02:00
this . date . setTime ( text . valueOf ( ) ) ;
2012-03-08 01:20:04 +01:00
}
else
{
2014-09-30 22:13:15 +02:00
// _value is timestamp in usertime, ready to be used with date() function identical to PHP date()
this . date = _value ;
2012-03-08 01:20:04 +01:00
}
2011-08-22 20:18:29 +02:00
var display = this . date . toString ( ) ;
2011-09-14 02:04:06 +02:00
switch ( this . _type ) {
2013-02-08 12:10:45 +01:00
case "date-time_today" :
// Today - just the time
2014-10-01 06:40:54 +02:00
if ( date ( 'Y-m-d' , this . date ) == date ( 'Y-m-d' ) )
2013-02-08 12:10:45 +01:00
{
display = date ( this . egw ( ) . preference ( 'timeformat' ) == '24' ? 'H:i' : 'g:i a' , this . date ) ;
}
2014-10-20 15:29:29 +02:00
// Before today - date and time
2013-02-08 12:10:45 +01:00
else
{
2014-10-20 15:29:29 +02:00
display = date ( this . egw ( ) . preference ( 'dateformat' ) + " " +
( this . egw ( ) . preference ( 'timeformat' ) == '24' ? 'H:i' : 'g:i a' ) , this . date ) ;
2013-02-08 12:10:45 +01:00
}
break ;
2011-08-22 20:18:29 +02:00
case "date" :
2012-03-02 11:44:56 +01:00
display = date ( this . egw ( ) . preference ( 'dateformat' ) , this . date ) ;
2011-08-22 20:18:29 +02:00
break ;
2011-08-29 23:15:53 +02:00
case "date-timeonly" :
2012-03-02 11:44:56 +01:00
display = date ( this . egw ( ) . preference ( 'timeformat' ) == '24' ? 'H:i' : 'g:i a' , this . date ) ;
2011-08-22 20:18:29 +02:00
break ;
case "date-time" :
2013-09-12 13:45:26 +02:00
display = date ( this . egw ( ) . preference ( 'dateformat' ) + " " +
2012-03-02 11:44:56 +01:00
( this . egw ( ) . preference ( 'timeformat' ) == '24' ? 'H:i' : 'g:i a' ) , this . date ) ;
2011-08-30 22:50:55 +02:00
break ;
case "date-since" :
var unit2label = {
'Y' : 'years' ,
'm' : 'month' ,
'd' : 'days' ,
'H' : 'hours' ,
'i' : 'minutes' ,
2011-09-02 18:23:26 +02:00
's' : 'seconds'
2011-08-30 22:50:55 +02:00
} ;
var unit2s = {
'Y' : 31536000 ,
'm' : 2628000 ,
'd' : 86400 ,
'H' : 3600 ,
'i' : 60 ,
2011-09-02 18:23:26 +02:00
's' : 1
2011-08-30 22:50:55 +02:00
} ;
var d = new Date ( ) ;
var diff = Math . round ( d . valueOf ( ) / 1000 ) - Math . round ( this . date . valueOf ( ) / 1000 ) ;
display = '' ;
for ( var unit in unit2s )
{
var unit _s = unit2s [ unit ] ;
if ( diff >= unit _s || unit == 's' )
{
2012-03-02 11:44:56 +01:00
display = Math . round ( diff / unit _s , 1 ) + ' ' + this . egw ( ) . lang ( unit2label [ unit ] ) ;
2011-08-30 22:50:55 +02:00
break ;
}
}
2013-04-13 21:00:13 +02:00
break ;
2011-08-22 20:18:29 +02:00
}
2011-08-29 23:15:53 +02:00
this . span . attr ( "datetime" , date ( "Y-m-d H:i:s" , this . date ) ) . text ( display ) ;
2011-09-12 17:21:42 +02:00
} ,
2014-05-26 15:44:24 +02:00
2014-07-23 14:54:02 +02:00
set _label : function ( label )
{
// Remove current label
this . _labelContainer . contents ( )
. filter ( function ( ) { return this . nodeType == 3 ; } ) . remove ( ) ;
var parts = et2 _csvSplit ( label , 2 , "%s" ) ;
this . _labelContainer . prepend ( parts [ 0 ] ) ;
this . _labelContainer . append ( parts [ 1 ] ) ;
this . label = label ;
} ,
2011-09-12 17:21:42 +02:00
/ * *
* Creates a list of attributes which can be set when working in the
* "detached" mode . The result is stored in the _attrs array which is provided
* by the calling code .
2014-01-29 19:55:24 +01:00
*
* @ param { array } _attrs array to add further attributes to
2011-09-12 17:21:42 +02:00
* /
getDetachedAttributes : function ( _attrs ) {
2014-02-21 13:22:33 +01:00
_attrs . push ( "label" , "value" , "class" ) ;
2011-09-12 17:21:42 +02:00
} ,
/ * *
* Returns an array of DOM nodes . The ( relatively ) same DOM - Nodes have to be
* passed to the "setDetachedAttributes" function in the same order .
2014-01-29 19:55:24 +01:00
*
* @ return { array }
2011-09-12 17:21:42 +02:00
* /
getDetachedNodes : function ( ) {
2014-07-23 14:54:02 +02:00
return [ this . _labelContainer [ 0 ] , this . span [ 0 ] ] ;
2011-09-12 17:21:42 +02:00
} ,
/ * *
* Sets the given associative attribute - > value array and applies the
* attributes to the given DOM - Node .
*
* @ param _nodes is an array of nodes which have to be in the same order as
* the nodes returned by "getDetachedNodes"
* @ param _values is an associative array which contains a subset of attributes
* returned by the "getDetachedAttributes" function and sets them to the
* given values .
* /
setDetachedAttributes : function ( _nodes , _values ) {
2014-07-23 14:54:02 +02:00
this . _labelContainer = jQuery ( _nodes [ 0 ] ) ;
2014-02-21 13:22:33 +01:00
this . span = jQuery ( _nodes [ 1 ] ) ;
2014-05-26 15:44:24 +02:00
2011-09-12 17:21:42 +02:00
this . set _value ( _values [ "value" ] ) ;
2014-02-21 13:22:33 +01:00
if ( _values [ "label" ] )
{
this . set _label ( _values [ "label" ] ) ;
}
2013-09-12 13:45:26 +02:00
if ( _values [ "class" ] )
2011-09-14 22:52:59 +02:00
{
this . span . addClass ( _values [ "class" ] ) ;
}
2011-08-22 20:18:29 +02:00
}
} ) ;
2013-02-08 12:10:45 +01:00
et2 _register _widget ( et2 _date _ro , [ "date_ro" , "date-time_ro" , "date-since" , "date-time_today" ] ) ;
2011-08-30 22:50:55 +02:00
2013-04-13 21:00:13 +02:00
/ * *
* @ augments et2 _date _ro
* /
var et2 _date _timeonly _ro = et2 _date _ro . extend (
{
2011-08-31 22:32:24 +02:00
attributes : {
"value" : {
"type" : "string"
}
} ,
2013-04-13 21:00:13 +02:00
/ * *
* Construtor
2013-09-12 13:45:26 +02:00
*
2013-04-13 21:00:13 +02:00
* @ param _value
* @ memberOf et2 _date _timeonly _ro
* /
2011-08-31 22:32:24 +02:00
set _value : function ( _value ) {
2012-03-02 11:44:56 +01:00
if ( this . egw ( ) . preference ( "timeformat" ) == "12" && _value . indexOf ( ":" ) > 0 ) {
2011-08-31 22:32:24 +02:00
var parts = _value . split ( ":" ) ;
if ( parts [ 0 ] >= 12 ) {
this . span . text ( ( parts [ 0 ] == "12" ? "12" : parseInt ( parts [ 0 ] ) - 12 ) + ":" + parts [ 1 ] + " pm" ) ;
}
else
{
this . span . text ( _value + " am" ) ;
}
}
else
{
this . span . text ( _value ) ;
}
}
} ) ;
et2 _register _widget ( et2 _date _timeonly _ro , [ "date-timeonly_ro" ] ) ;