2020-01-22 17:56:38 +01:00
"use strict" ;
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
* /
2020-01-22 17:56:38 +01:00
var _ _extends = ( this && this . _ _extends ) || ( function ( ) {
var extendStatics = function ( d , b ) {
extendStatics = Object . setPrototypeOf ||
( { _ _proto _ _ : [ ] } instanceof Array && function ( d , b ) { d . _ _proto _ _ = b ; } ) ||
function ( d , b ) { for ( var p in b ) if ( b . hasOwnProperty ( p ) ) d [ p ] = b [ p ] ; } ;
return extendStatics ( d , b ) ;
} ;
return function ( d , b ) {
extendStatics ( d , b ) ;
function _ _ ( ) { this . constructor = d ; }
d . prototype = b === null ? Object . create ( b ) : ( _ _ . prototype = b . prototype , new _ _ ( ) ) ;
} ;
} ) ( ) ;
Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
2021-02-05 14:57:38 +01:00
exports . et2 _date _range = exports . et2 _date _ro = exports . et2 _date _duration _ro = exports . et2 _date _duration = exports . et2 _date = void 0 ;
2011-08-22 20:18:29 +02:00
/ * e g w : u s e s
2020-01-22 17:56:38 +01:00
/ v e n d o r / b o w e r - a s s e t / j q u e r y / d i s t / j q u e r y . j s ;
/ v e n d o r / b o w e r - a s s e t / j q u e r y - u i / j q u e r y - u i . j s ;
lib / date ;
et2 _core _inputWidget ;
et2 _core _valueWidget ;
2011-08-22 20:18:29 +02:00
* /
2020-01-22 17:56:38 +01:00
require ( "./et2_core_common" ) ;
var et2 _core _inheritance _1 = require ( "./et2_core_inheritance" ) ;
var et2 _core _widget _1 = require ( "./et2_core_widget" ) ;
var et2 _core _valueWidget _1 = require ( "./et2_core_valueWidget" ) ;
var et2 _core _inputWidget _1 = require ( "./et2_core_inputWidget" ) ;
var et2 _core _DOMWidget _1 = require ( "./et2_core_DOMWidget" ) ;
// all calls to jQueryUI.datetimepicker as jQuery.datepicker give errors which are currently suppressed with @ts-ignore
// adding npm package @types/jquery.ui.datetimepicker did NOT help :(
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-19 23:22:26 +02:00
* Dates are passed to the server in ISO8601 format ( "Y-m-d\TH:i:sP" ) , and data _format is
* handled server - side .
2014-08-18 18:47:27 +02:00
*
2016-02-08 18:23:54 +01:00
* 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 .
2013-09-12 13:45:26 +02:00
* /
2020-01-22 17:56:38 +01:00
var et2 _date = /** @class */ ( function ( _super ) {
_ _extends ( et2 _date , _super ) ;
/ * *
* Constructor
* /
function et2 _date ( _parent , _attrs , _child ) {
var _this =
// Call the inherited constructor
2020-01-22 18:38:33 +01:00
_super . call ( this , _parent , _attrs , et2 _core _inheritance _1 . ClassWithAttributes . extendAttributes ( et2 _date . _attributes , _child || { } ) ) || this ;
2020-01-22 17:56:38 +01:00
_this . input _date = null ;
_this . is _mobile = false ;
_this . date = new Date ( ) ;
_this . date . setUTCHours ( 0 ) ;
_this . date . setMinutes ( 0 ) ;
_this . date . setSeconds ( 0 ) ;
_this . createInputWidget ( ) ;
return _this ;
}
et2 _date . prototype . createInputWidget = function ( ) {
this . span = jQuery ( document . createElement ( this . options . inline ? 'div' : "span" ) ) . addClass ( "et2_date" ) ;
this . input _date = jQuery ( document . createElement ( this . options . inline ? "div" : "input" ) ) ;
if ( this . options . blur )
this . input _date . attr ( 'placeholder' , this . egw ( ) . lang ( this . options . blur ) ) ;
this . input _date . addClass ( "et2_date" ) . attr ( "type" , "text" )
. attr ( "size" , 7 ) // strlen("10:00pm")=7
. appendTo ( this . span ) ;
this . setDOMNode ( this . span [ 0 ] ) ;
// inline calendar is not existing in html5, so allways use datepicker instead
this . is _mobile = egwIsMobile ( ) && ! this . options . inline ;
if ( this . is _mobile ) {
this . dateFormat = 'yy-mm-dd' ;
this . timeFormat = 'HH:mm' ;
switch ( this . getType ( ) ) {
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 {
this . dateFormat = this . egw ( ) . dateTimeFormat ( this . egw ( ) . preference ( "dateformat" ) ) ;
this . timeFormat = this . egw ( ) . preference ( "timeformat" ) == 12 ? "h:mmtt" : "HH:mm" ;
// jQuery-UI date picker
if ( this . getType ( ) != 'date-timeonly' ) {
this . egw ( ) . calendar ( this . input _date , this . getType ( ) == "date-time" ) ;
}
else {
this . input _date . addClass ( "et2_time" ) ;
this . egw ( ) . time ( this . input _date ) ;
}
// Avoid collision of datepicker dialog with input field
var widget = this ;
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
} ) ;
}
// Add tooltip to Today/Now button
jQuery ( '[data-handler="today"]' , cal ) . attr ( 'title' , widget . getType ( ) == 'date' ? egw . lang ( 'Today' ) : egw . lang ( 'Now' ) ) ;
} , 0 ) ;
} )
. datepicker ( 'option' , 'onClose' , function ( dateText , inst ) {
// Lose focus, avoids an issue with focus
// not allowing datepicker to re-open
inst . input . blur ( ) ;
} ) ;
}
// Update internal value when changed
var self = this ;
this . input _date . bind ( 'change' , function ( e ) {
self . set _value ( this . value ) ;
return false ;
} ) ;
// Framewok skips nulls, but null needs to be processed here
if ( this . options . value == null ) {
this . set _value ( null ) ;
}
} ;
et2 _date . prototype . set _type = function ( _type ) {
if ( _type != this . getType ( ) ) {
_super . prototype . setType . call ( this , _type ) ;
this . createInputWidget ( ) ;
}
} ;
/ * *
* Dynamic disable or enable datepicker
*
* @ param { boolean } _ro
* /
et2 _date . prototype . set _readonly = function ( _ro ) {
if ( this . input _date && ! this . input _date . attr ( 'disabled' ) != ! _ro ) {
2020-01-22 20:12:36 +01:00
this . input _date . prop ( 'disabled' , ! ! _ro )
2020-01-22 17:56:38 +01:00
. datepicker ( 'option' , 'disabled' , ! ! _ro ) ;
}
} ;
/ * *
* Set ( full ) year of current date
*
* @ param { number } _value 4 - digit year
* /
et2 _date . prototype . 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
* /
et2 _date . prototype . set _month = function ( _value ) {
this . date . setUTCMonth ( _value - 1 ) ;
this . set _value ( this . date ) ;
} ;
/ * *
* Set day of current date
*
* @ param { number } _value 1. . 31
* /
et2 _date . prototype . 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
* /
et2 _date . prototype . 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
* /
et2 _date . prototype . 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
* /
et2 _date . prototype . 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
* /
et2 _date . prototype . 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
* /
et2 _date . prototype . 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
* /
et2 _date . prototype . 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
* /
et2 _date . prototype . get _minutes = function ( ) {
return this . input _date . val ( ) == "" ? null : this . date . getUTCMinutes ( ) ;
} ;
/ * *
* Get timestamp
*
* You can use set _value to set a timestamp .
*
* @ return { number | null } timestamp ( seconds since 1970 - 01 - 01 )
* /
et2 _date . prototype . get _time = function ( ) {
return this . input _date . val ( ) == "" ? null : this . date . getTime ( ) ;
} ;
/ * *
* The range of years displayed in the year drop - down : either relative
* to today ' s year ( "-nn:+nn" ) , relative to the currently selected year
* ( "c-nn:c+nn" ) , absolute ( "nnnn:nnnn" ) , or combinations of these formats
* ( "nnnn:-nn" ) . Note that this option only affects what appears in the
* drop - down , to restrict which dates may be selected use the min _date
* and / or max _date options .
* @ param { string } _value
* /
et2 _date . prototype . set _year _range = function ( _value ) {
if ( this . input _date && this . getType ( ) == 'date' && ! this . is _mobile ) {
this . input _date . datepicker ( 'option' , 'yearRange' , _value ) ;
}
this . options . year _range = _value ;
} ;
/ * *
* Set the minimum allowed date
*
* The minimum selectable date . When set to null , there is no minimum .
* Multiple types supported :
* Date : A date object containing the minimum date .
* Number : A number of days from today . For example 2 represents two days
* from today and - 1 represents yesterday .
* String : A string in the format defined by the dateFormat option , or a
* relative date . Relative dates must contain value and period pairs ;
* valid periods are "y" for years , "m" for months , "w" for weeks , and
* "d" for days . For example , "+1m +7d" represents one month and seven
* days from today .
* @ param { Date | Number | String } _value
* /
et2 _date . prototype . set _min = function ( _value ) {
2021-10-19 22:23:31 +02:00
// minDate option checks the type, so make sure we're passing numbers as numbers (0, not "0")
// @ts-ignore
if ( typeof _value === "string" && ! isNaN ( _value ) && "" + parseInt ( _value ) == _value ) {
_value = parseInt ( _value ) ;
}
2020-01-22 17:56:38 +01:00
if ( this . input _date ) {
if ( this . is _mobile ) {
this . input _date . attr ( 'min' , this . _relativeDate ( _value ) ) ;
}
else {
// Check for full timestamp
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}))/ ) ) {
_value = new Date ( _value ) ;
// Add timezone offset back in, or formatDate will lose those hours
var formatDate = new Date ( _value . valueOf ( ) + this . date . getTimezoneOffset ( ) * 60 * 1000 ) ;
if ( this . getType ( ) == 'date' ) {
_value = jQuery . datepicker . formatDate ( this . dateFormat , formatDate ) ;
}
}
this . input _date . datepicker ( 'option' , 'minDate' , _value ) ;
}
}
this . options . min = _value ;
} ;
/ * *
* Convert non html5 min or max attributes described above to timestamps
*
* @ param { string | Date } _value
* /
et2 _date . prototype . _relativeDate = function ( _value ) {
if ( typeof _value == 'string' && _value . match ( /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/ ) )
return _value ;
// @ts-ignore
return jQuery . datepicker . _determineDate ( jQuery . datepicker , _value , this . date ) . toJSON ( ) ;
} ;
/ * *
* Set the maximum allowed date
*
* The maximum selectable date . When set to null , there is no maximum .
* Multiple types supported :
* Date : A date object containing the maximum date .
* Number : A number of days from today . For example 2 represents two days
* from today and - 1 represents yesterday .
* String : A string in the format defined by the dateFormat option , or a
* relative date . Relative dates must contain value and period pairs ;
* valid periods are "y" for years , "m" for months , "w" for weeks , and
* "d" for days . For example , "+1m +7d" represents one month and seven
* days from today .
* @ param { Date | Number | String } _value
* /
et2 _date . prototype . set _max = function ( _value ) {
2021-10-19 22:23:31 +02:00
// maxDate option checks the type, so make sure we're passing numbers as numbers (0, not "0")
// @ts-ignore
if ( typeof _value === "string" && ! isNaN ( _value ) && "" + parseInt ( _value ) == _value ) {
_value = parseInt ( _value ) ;
}
2020-01-22 17:56:38 +01:00
if ( this . input _date ) {
if ( this . is _mobile ) {
this . input _date . attr ( 'max' , this . _relativeDate ( _value ) ) ;
}
else {
// Check for full timestamp
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}))/ ) ) {
_value = new Date ( _value ) ;
// Add timezone offset back in, or formatDate will lose those hours
var formatDate = new Date ( _value . valueOf ( ) + this . date . getTimezoneOffset ( ) * 60 * 1000 ) ;
if ( this . getType ( ) == 'date' ) {
_value = jQuery . datepicker . formatDate ( this . dateFormat , formatDate ) ;
}
}
this . input _date . datepicker ( 'option' , 'maxDate' , _value ) ;
}
}
this . options . max = _value ;
} ;
/ * *
* 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
* /
et2 _date . prototype . set _value = function ( _value ) {
var old _value = this . _oldValue ;
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 . getType ( ) == 'date-time' || this . getType ( ) == 'date' ) ) {
if ( this . input _date ) {
this . input _date . val ( "" ) ;
}
if ( this . _oldValue !== et2 _no _init && old _value !== _value ) {
this . change ( this . input _date ) ;
}
this . _oldValue = _value ;
return ;
}
// 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 ) ;
}
// Check for full timestamp
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})|)$/ ) ) {
_value = new Date ( _value ) ;
}
// Handle just time as a string in the form H:i
if ( typeof _value == 'string' && isNaN ( _value ) ) {
try {
// silently fix skiped minutes or times with just one digit, as parser is quite pedantic ;-)
var fix _reg = new RegExp ( ( this . getType ( ) == "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 . getType ( ) == "date-timeonly" ? '' : ' ' ) + matches [ 1 ] + matches [ 2 ] + matches [ 3 ] ) ;
if ( matches [ 4 ] !== undefined )
matches [ 3 ] = matches [ 4 ] . toLowerCase ( ) == 'a' ? 'am' : 'pm' ;
}
switch ( this . getType ( ) ) {
case "date-timeonly" :
// @ts-ignore
var parsed = jQuery . datepicker . parseTime ( this . 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 ) ;
// @ts-ignore
this . input _date . timepicker ( 'setTime' , _value ) ;
if ( this . _oldValue !== et2 _no _init ) {
this . change ( this . input _date ) ;
}
}
this . _oldValue = this . date . toJSON ( ) ;
return ;
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 ) ) {
switch ( this . getType ( ) ) {
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 ( ' ' ) ;
// @ts-ignore
var parsed = jQuery . datepicker . parseDateTime ( this . egw ( ) . dateTimeFormat ( DTformat [ 0 ] ) , this . egw ( ) . dateTimeFormat ( DTformat [ 1 ] ) , _value ) ;
}
}
else // Parse other date widgets date with timepicker date/time format to date onject
{
// @ts-ignore
var parsed = jQuery . datepicker . parseDateTime ( this . dateFormat , this . timeFormat , _value . replace ( 'T' , ' ' ) ) ;
if ( ! parsed ) {
this . set _validation _error ( this . egw ( ) . lang ( "%1' han an invalid format !!!" , _value ) ) ;
return ;
}
}
// Update local variable, but remove the timezone offset that
// javascript adds when we parse
if ( parsed ) {
this . date = new Date ( parsed . valueOf ( ) - parsed . getTimezoneOffset ( ) * 60000 ) ;
}
this . set _validation _error ( false ) ;
}
}
// catch exception from unparsable date and display it empty instead
catch ( e ) {
return this . set _value ( null ) ;
}
}
else if ( typeof _value == 'object' && _value . date ) {
this . date = _value . date ;
}
else if ( typeof _value == 'object' && _value . valueOf ) {
this . date = _value ;
}
else
// string starting with + or - --> add/substract number of seconds from current value
{
this . date . setTime ( this . date . getTime ( ) + 1000 * parseInt ( _value ) ) ;
}
// Update input - popups do, but framework doesn't
_value = '' ;
// Add timezone offset back in, or formatDate will lose those hours
var formatDate = new Date ( this . date . valueOf ( ) + this . date . getTimezoneOffset ( ) * 60 * 1000 ) ;
if ( this . getType ( ) != 'date-timeonly' ) {
_value = jQuery . datepicker . formatDate ( this . dateFormat , formatDate ) ;
}
if ( this . getType ( ) != 'date' ) {
if ( this . getType ( ) != 'date-timeonly' )
_value += this . is _mobile ? 'T' : ' ' ;
// @ts-ignore
_value += jQuery . datepicker . formatTime ( this . timeFormat , {
hour : formatDate . getHours ( ) ,
minute : formatDate . getMinutes ( ) ,
seconds : 0 ,
timezone : 0
} ) ;
}
if ( this . options . inline ) {
this . input _date . datepicker ( "setDate" , formatDate ) ;
}
else {
this . input _date . val ( _value ) ;
}
if ( this . _oldValue !== et2 _no _init && old _value != this . getValue ( ) ) {
this . change ( this . input _date ) ;
}
this . _oldValue = _value ;
} ;
et2 _date . prototype . getValue = function ( ) {
if ( this . input _date . val ( ) == "" ) {
// User blanked the box
return null ;
}
// date-timeonly returns just the seconds, without any date!
if ( this . getType ( ) == 'date-timeonly' ) {
this . date . setUTCDate ( 1 ) ;
this . date . setUTCMonth ( 0 ) ;
this . date . setUTCFullYear ( 1970 ) ;
}
else if ( this . getType ( ) == 'date' ) {
this . date . setUTCHours ( 0 ) ;
this . date . setUTCMinutes ( 0 ) ;
}
// Convert to timestamp - no seconds
this . date . setSeconds ( 0 , 0 ) ;
return ( this . date && typeof this . date . toJSON != 'undefined' && this . date . toJSON ( ) ) ? this . date . toJSON ( ) . replace ( /\.\d{3}Z$/ , 'Z' ) : this . date ;
} ;
et2 _date . _attributes = {
"value" : {
"type" : "any"
} ,
"type" : {
"ignore" : false
} ,
"blur" : {
"name" : "Placeholder" ,
"type" : "string" ,
"default" : "" ,
"description" : "This text get displayed if an input-field is empty and does not have the input-focus (blur). It can be used to show a default value or a kind of help-text."
} ,
"data_format" : {
"ignore" : true ,
"description" : "Date/Time format. Can be set as an options to date widget" ,
"default" : ''
} ,
year _range : {
name : "Year range" ,
type : "string" ,
default : "c-10:c+10" ,
description : "The range of years displayed in the year drop-down: either relative to today's year (\"-nn:+nn\"), relative to the currently selected year (\"c-nn:c+nn\"), absolute (\"nnnn:nnnn\"), or combinations of these formats (\"nnnn:-nn\"). Note that this option only affects what appears in the drop-down, to restrict which dates may be selected use the min and/or max options."
} ,
min : {
"name" : "Minimum" ,
"type" : "any" ,
"default" : et2 _no _init ,
"description" : ' Minimum allowed date . Multiple types supported : \
2015-04-21 21:46:33 +02:00
Date : A date object containing the minimum date . \
Number : A number of days from today . For example 2 represents two days from today and - 1 represents yesterday . \
String : A string in the user \ 's date format, or a relative date. Relative dates must contain value and period pairs; valid periods are "y" for years, "m" for months, "w" for weeks, and "d" for days. For example, "+1m +7d" represents one month and seven days from today.'
2020-01-22 17:56:38 +01:00
} ,
max : {
"name" : "Maximum" ,
"type" : "any" ,
"default" : et2 _no _init ,
"description" : ' Maximum allowed date . Multiple types supported : \
2015-04-21 21:46:33 +02:00
Date : A date object containing the maximum date . \
Number : A number of days from today . For example 2 represents two days from today and - 1 represents yesterday . \
String : A string in the user \ 's date format, or a relative date. Relative dates must contain value and period pairs; valid periods are "y" for years, "m" for months, "w" for weeks, and "d" for days. For example, "+1m +7d" represents one month and seven days from today.'
2020-01-22 17:56:38 +01:00
} ,
inline : {
"name" : "Inline" ,
"type" : "boolean" ,
"default" : false ,
"description" : "Instead of an input field with a popup calendar, the calendar is displayed inline, with no input field"
}
} ;
2020-03-30 18:28:48 +02:00
et2 _date . legacyOptions = [ "data_format" ] ;
2020-01-22 17:56:38 +01:00
return et2 _date ;
} ( et2 _core _inputWidget _1 . et2 _inputWidget ) ) ;
2020-01-22 20:12:36 +01:00
exports . et2 _date = et2 _date ;
2020-01-22 17:56:38 +01:00
et2 _core _widget _1 . et2 _register _widget ( et2 _date , [ "date" , "date-time" , "date-timeonly" ] ) ;
2013-04-13 21:00:13 +02:00
/ * *
2020-01-22 17:56:38 +01:00
* Class which implements the "date-duration" XET - Tag
2013-04-13 21:00:13 +02:00
* /
2020-01-22 17:56:38 +01:00
var et2 _date _duration = /** @class */ ( function ( _super ) {
_ _extends ( et2 _date _duration , _super ) ;
/ * *
* Constructor
* /
function et2 _date _duration ( _parent , _attrs , _child ) {
var _this =
// Call the inherited constructor
2020-01-22 18:38:33 +01:00
_super . call ( this , _parent , _attrs , et2 _core _inheritance _1 . ClassWithAttributes . extendAttributes ( et2 _date _duration . _attributes , _child || { } ) ) || this ;
2020-02-13 19:56:52 +01:00
_this . format = null ;
2020-01-22 17:56:38 +01:00
// 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 ( "%" , "" ) ;
}
// Clean formats
2021-02-05 14:57:38 +01:00
_this . options . display _format = _this . options . display _format . replace ( /[^dhms]/ , '' ) ;
2020-01-22 17:56:38 +01:00
if ( ! _this . options . display _format ) {
// @ts-ignore
_this . options . display _format = _this . attributes . display _format [ "default" ] ;
}
// Get translations
_this . time _formats = {
2021-02-05 14:57:38 +01:00
d : _this . options . short _labels ? _this . egw ( ) . lang ( "d" ) : _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" ) ,
s : _this . options . short _labels ? _this . egw ( ) . lang ( "s" ) : _this . egw ( ) . lang ( "Seconds" )
2020-01-22 17:56:38 +01:00
} ,
_this . createInputWidget ( ) ;
return _this ;
}
et2 _date _duration . prototype . createInputWidget = function ( ) {
// Create nodes
this . node = jQuery ( document . createElement ( "span" ) )
. addClass ( 'et2_date_duration' ) ;
2021-02-05 14:57:38 +01:00
var inputs = [ ] ;
for ( var i = this . options . select _unit ? 1 : this . options . display _format . length ; i > 0 ; -- i ) {
var input = document . createElement ( "input" ) ;
inputs . push ( input ) ;
if ( ! this . options . select _unit ) {
var attr = { min : 0 } ;
switch ( this . options . display _format [ this . options . display _format . length - i ] ) {
case 's' :
attr . max = 60 ;
attr . title = this . egw ( ) . lang ( 'Seconds' ) ;
break ;
case 'm' :
attr . max = 60 ;
attr . title = this . egw ( ) . lang ( 'Minutes' ) ;
break ;
case 'h' :
attr . max = 24 ;
attr . title = this . egw ( ) . lang ( 'Hours' ) ;
break ;
case 'd' :
attr . title = this . egw ( ) . lang ( 'Days' ) ;
break ;
}
jQuery ( input ) . attr ( attr ) ;
}
}
this . duration = jQuery ( inputs )
2020-01-22 17:56:38 +01:00
. addClass ( 'et2_date_duration' )
2021-02-05 14:57:38 +01:00
. attr ( {
type : 'number' ,
size : 3 ,
step : this . options . step ,
lang : this . egw ( ) . preference ( 'number_format' ) [ 0 ] === "," ? "en-150" : "en-001"
} ) ;
2020-01-22 17:56:38 +01:00
this . node . append ( this . duration ) ;
var self = this ;
// seems the 'invalid' event doesn't work in all browsers, eg. FF therefore
// we use focusout event to check the valifdity of input right after user
// enters the value.
this . duration . on ( 'focusout' , function ( ) {
if ( ! self . duration [ 0 ] . checkValidity ( ) )
return self . duration . change ( ) ;
} ) ;
} ;
/ * *
* Clientside validation
*
* @ param { array } _messages
* /
et2 _date _duration . prototype . isValid = function ( _messages ) {
var ok = true ;
// if we have a html5 validation error, show it, as this.input.val() will be empty!
2021-02-09 14:51:10 +01:00
for ( var i = 0 ; this . duration && i < this . duration . length ; ++ i ) {
if ( this . duration [ i ] &&
this . duration [ i ] . validationMessage &&
! this . duration [ i ] . validity . stepMismatch ) {
_messages . push ( this . duration [ i ] . validationMessage ) ;
ok = false ;
}
2020-01-22 17:56:38 +01:00
}
return _super . prototype . isValid . call ( this , _messages ) && ok ;
} ;
et2 _date _duration . prototype . attachToDOM = function ( ) {
2021-02-09 14:51:10 +01:00
if ( this . duration ) {
for ( var i = 0 ; i < this . duration . length ; ++ i ) {
var node = this . duration [ i ] ;
jQuery ( node ) . bind ( "change.et2_inputWidget" , this , function ( e ) {
e . data . change ( this ) ;
} ) ;
}
2020-01-22 17:56:38 +01:00
}
return et2 _core _DOMWidget _1 . et2 _DOMWidget . prototype . attachToDOM . apply ( this , arguments ) ;
} ;
et2 _date _duration . prototype . getDOMNode = function ( ) {
return this . node [ 0 ] ;
} ;
et2 _date _duration . prototype . getInputNode = function ( ) {
return this . duration [ 0 ] ;
} ;
/ * *
* Use id on node , same as DOMWidget
*
* @ param { string } _value id to set
* /
et2 _date _duration . prototype . set _id = function ( _value ) {
this . id = _value ;
var node = this . getDOMNode ( ) ;
if ( node ) {
if ( _value != "" ) {
node . setAttribute ( "id" , this . getInstanceManager ( ) . uniqueId + '_' + this . id ) ;
}
else {
node . removeAttribute ( "id" ) ;
}
}
} ;
2021-02-05 14:57:38 +01:00
et2 _date _duration . prototype . _unit2seconds = function ( _unit ) {
switch ( _unit ) {
case 's' :
return 1 ;
case 'm' :
return 60 ;
case 'h' :
return 3600 ;
case 'd' :
return 3600 * this . options . hours _per _day ;
}
} ;
2021-02-22 09:52:15 +01:00
et2 _date _duration . prototype . _unit _from _value = function ( _value , _unit , _highest ) {
2021-02-05 14:57:38 +01:00
_value *= this . _unit2seconds ( this . data _format ) ;
// get value for given _unit
switch ( _unit ) {
case 's' :
2021-02-22 09:52:15 +01:00
return _highest ? _value : _value % 60 ;
2021-02-05 14:57:38 +01:00
case 'm' :
2021-02-22 09:52:15 +01:00
_value = Math . floor ( _value / 60 ) ;
return _highest ? _value : _value % 60 ;
2021-02-05 14:57:38 +01:00
case 'h' :
2021-02-22 09:52:15 +01:00
_value = Math . floor ( _value / 3600 ) ;
return _highest ? _value : _value % this . options . hours _per _day ;
2021-02-05 14:57:38 +01:00
case 'd' :
return Math . floor ( _value / 3600 * this . options . hours _per _day ) ;
}
} ;
2020-01-22 17:56:38 +01:00
et2 _date _duration . prototype . set _value = function ( _value ) {
this . options . value = _value ;
2021-02-05 14:57:38 +01:00
if ( ! this . options . select _unit && this . options . display _format . length > 1 ) {
for ( var i = this . options . display _format . length ; -- i >= 0 ; ) {
2021-03-29 18:02:55 +02:00
jQuery ( this . duration [ i ] ) . val ( this . _unit _from _value ( _value , this . options . display _format [ i ] , ! i ) ) ;
2021-02-05 14:57:38 +01:00
}
return ;
}
2020-02-10 23:32:31 +01:00
var display = this . _convert _to _display ( parseFloat ( _value ) ) ;
2020-01-22 17:56:38 +01:00
// 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
2020-09-11 20:22:34 +02:00
if ( display . unit && display . unit != this . options . display _format ) {
2020-01-22 17:56:38 +01:00
if ( this . format && this . format . children ( ) . length > 1 ) {
jQuery ( "option[value='" + display . unit + "']" , this . format ) . attr ( 'selected' , 'selected' ) ;
}
else {
this . format . text ( display . unit ? this . time _formats [ display . unit ] : '' ) ;
}
}
} ;
2020-02-10 23:32:31 +01:00
et2 _date _duration . prototype . set _display _format = function ( format ) {
2020-09-11 20:22:34 +02:00
if ( format . length < 1 ) {
2020-02-07 17:30:43 +01:00
this . node . remove ( 'select.et2_date_duration' ) ;
2020-08-28 21:53:23 +02:00
this . format . remove ( ) ;
2020-02-13 19:56:52 +01:00
this . format = null ;
2020-02-07 17:30:43 +01:00
}
this . options . display _format = format ;
2021-02-05 14:57:38 +01:00
if ( ( this . format == null || this . format . is ( 'select' ) ) &&
( this . options . display _format . length <= 1 || this . options . readonly || ! this . options . select _unit ) ) {
2020-02-13 19:56:52 +01:00
if ( this . format ) {
this . format . remove ( ) ;
}
this . format = jQuery ( document . createElement ( 'span' ) ) . appendTo ( this . node ) ;
2020-02-10 23:32:31 +01:00
}
2021-02-05 14:57:38 +01:00
if ( ! this . options . select _unit && this . options . display _format . length > 1 ) {
// no unit selection or display
this . format . hide ( ) ;
}
else if ( this . options . display _format . length > 1 && ! this . options . readonly ) {
2020-02-13 19:56:52 +01:00
if ( this . format && ! this . format . is ( 'select' ) ) {
this . format . remove ( ) ;
this . format = null ;
}
if ( ! this . format ) {
this . format = jQuery ( document . createElement ( "select" ) )
. addClass ( 'et2_date_duration' ) ;
this . node . append ( this . format ) ;
}
this . format . empty ( ) ;
2020-02-10 23:32:31 +01:00
for ( var i = 0 ; i < this . options . display _format . length ; i ++ ) {
2020-02-07 17:30:43 +01:00
this . format . append ( "<option value='" + this . options . display _format [ i ] + "'>" + this . time _formats [ this . options . display _format [ i ] ] + "</option>" ) ;
}
}
2020-02-10 23:32:31 +01:00
else if ( this . time _formats [ this . options . display _format ] ) {
2020-02-13 19:56:52 +01:00
this . format . text ( this . time _formats [ this . options . display _format ] ) ;
2020-02-07 17:30:43 +01:00
}
2020-02-10 23:32:31 +01:00
else {
2020-02-13 19:56:52 +01:00
this . format . text ( this . time _formats [ "m" ] ) ;
2020-02-07 17:30:43 +01:00
}
} ;
2020-01-22 17:56:38 +01:00
/ * *
* 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 }
* /
et2 _date _duration . prototype . _convert _to _display = function ( _value ) {
2021-02-05 14:57:38 +01:00
if ( ! this . options . select _unit ) {
var vals = [ ] ;
for ( var i = 0 ; i < this . options . display _format . length ; ++ i ) {
var unit = this . options . display _format [ i ] ;
2021-02-22 09:52:15 +01:00
var val = this . _unit _from _value ( _value , unit , i === 0 ) ;
2021-02-05 14:57:38 +01:00
if ( unit === 's' || unit === 'm' || unit === 'h' && this . options . display _format [ 0 ] === 'd' ) {
vals . push ( sprintf ( '%02d' , val ) ) ;
}
else {
vals . push ( val ) ;
}
}
return { value : vals . join ( ':' ) , unit : '' } ;
}
2020-01-22 17:56:38 +01:00
if ( _value ) {
// Put value into minutes for further processing
switch ( this . options . data _format ) {
case 'd' :
_value *= this . options . hours _per _day ;
// fall-through
case 'h' :
_value *= 60 ;
break ;
2021-02-05 14:57:38 +01:00
case 's' :
_value /= 60.0 ;
break ;
2020-01-22 17:56:38 +01:00
}
}
// Figure out best unit for display
var _unit = this . options . display _format == "d" ? "d" : "h" ;
if ( this . options . display _format . indexOf ( 'm' ) > - 1 && _value && _value < 60 ) {
_unit = 'm' ;
}
else if ( this . options . display _format . indexOf ( 'd' ) > - 1 && _value >= 60 * this . options . hours _per _day ) {
_unit = 'd' ;
}
_value = this . options . empty _not _0 && _value === '' || ! this . options . empty _not _0 && ! _value ? '' :
( _unit == 'm' ? parseInt ( _value ) : ( Math . round ( ( _value / 60.0 / ( _unit == 'd' ? this . options . hours _per _day : 1 ) ) * 100 ) / 100 ) ) ;
if ( _value === '' )
_unit = '' ;
// use decimal separator from user prefs
var format = this . egw ( ) . preference ( 'number_format' ) ;
var sep = format ? format [ 0 ] : '.' ;
if ( typeof _value == 'string' && format && sep && sep != '.' ) {
_value = _value . replace ( '.' , sep ) ;
}
return { value : _value , unit : _unit } ;
} ;
/ * *
* Change displayed value into storage value and return
* /
et2 _date _duration . prototype . getValue = function ( ) {
2021-02-05 14:57:38 +01:00
if ( ! this . options . select _unit && this . options . display _format . length > 1 ) {
var value _1 = 0 ;
for ( var i = this . options . display _format . length ; -- i >= 0 ; ) {
value _1 += parseInt ( jQuery ( this . duration [ i ] ) . val ( ) ) * this . _unit2seconds ( this . options . display _format [ i ] ) ;
}
if ( this . options . data _format !== 's' ) {
value _1 /= this . _unit2seconds ( this . options . data _format ) ;
}
return this . options . data _format === 'm' ? Math . round ( value _1 ) : value _1 ;
}
2020-01-22 17:56:38 +01:00
var value = this . duration . val ( ) . replace ( ',' , '.' ) ;
if ( value === '' ) {
return this . options . empty _not _0 ? '' : 0 ;
}
// Put value into minutes for further processing
switch ( this . format && this . format . val ( ) ? this . format . val ( ) : this . options . display _format ) {
case 'd' :
value *= this . options . hours _per _day ;
// fall-through
case 'h' :
value *= 60 ;
break ;
}
// Minutes should be an integer. Floating point math.
2021-02-05 14:57:38 +01:00
if ( this . options . data _format !== 's' ) {
value = Math . round ( value ) ;
}
2020-01-22 17:56:38 +01:00
switch ( this . options . data _format ) {
case 'd' :
value /= this . options . hours _per _day ;
// fall-through
case 'h' :
value /= 60.0 ;
break ;
2021-02-05 14:57:38 +01:00
case 's' :
value = Math . round ( value * 60.0 ) ;
break ;
2020-01-22 17:56:38 +01:00
}
return value ;
} ;
et2 _date _duration . _attributes = {
"data_format" : {
"name" : "Data format" ,
"default" : "m" ,
"type" : "string" ,
2021-02-05 14:57:38 +01:00
"description" : "Units to read/store the data. 'd' = days (float), 'h' = hours (float), 'm' = minutes (int), 's' = seconds (int)."
2020-01-22 17:56:38 +01:00
} ,
"display_format" : {
"name" : "Display format" ,
"default" : "dhm" ,
"type" : "string" ,
2021-02-05 14:57:38 +01:00
"description" : "Permitted units for displaying the data. 'd' = days, 'h' = hours, 'm' = minutes, 's' = seconds. Use combinations to give a choice. Default is 'dh' = days or hours with selectbox."
} ,
"select_unit" : {
"name" : "Select unit or input per unit" ,
"default" : true ,
"type" : "boolean" ,
"description" : "Display a unit-selection for multiple units, or an input field per unit."
2020-01-22 17:56:38 +01:00
} ,
"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"
} ,
"step" : {
"name" : "Step limit" ,
"default" : 'any' ,
"type" : "string" ,
"description" : "Works with the min and max attributes to limit the increments at which a numeric or date-time value can be set."
}
} ;
2020-03-30 18:28:48 +02:00
et2 _date _duration . legacyOptions = [ "data_format" , "display_format" , "hours_per_day" , "empty_not_0" , "short_labels" ] ;
2020-01-22 17:56:38 +01:00
return et2 _date _duration ;
} ( et2 _date ) ) ;
2020-01-22 20:12:36 +01:00
exports . et2 _date _duration = et2 _date _duration ;
2020-01-22 17:56:38 +01:00
et2 _core _widget _1 . et2 _register _widget ( et2 _date _duration , [ "date-duration" ] ) ;
2013-04-13 21:00:13 +02:00
/ * *
2020-01-22 17:56:38 +01:00
* r / o date - duration
2013-04-13 21:00:13 +02:00
* /
2020-01-22 17:56:38 +01:00
var et2 _date _duration _ro = /** @class */ ( function ( _super ) {
_ _extends ( et2 _date _duration _ro , _super ) ;
function et2 _date _duration _ro ( ) {
return _super !== null && _super . apply ( this , arguments ) || this ;
}
et2 _date _duration _ro . prototype . createInputWidget = function ( ) {
this . node = jQuery ( document . createElement ( "span" ) ) ;
this . duration = jQuery ( document . createElement ( "span" ) ) . appendTo ( this . node ) ;
this . format = jQuery ( document . createElement ( "span" ) ) . appendTo ( this . node ) ;
} ;
/ * *
* Code for implementing et2 _IDetachedDOM
* 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 .
*
* @ param { array } _attrs array to add further attributes to
* /
et2 _date _duration _ro . prototype . 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 .
*
* @ return { array }
* /
et2 _date _duration _ro . prototype . 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 .
* /
et2 _date _duration _ro . prototype . setDetachedAttributes = function ( _nodes , _values ) {
for ( var i = 0 ; i < _nodes . length ; i ++ ) {
// Clear the node
for ( var j = _nodes [ i ] . childNodes . length - 1 ; j >= 0 ; j -- ) {
_nodes [ i ] . removeChild ( _nodes [ i ] . childNodes [ j ] ) ;
}
}
if ( typeof _values . value !== 'undefined' ) {
_values . value = parseFloat ( _values . value ) ;
}
if ( _values . value ) {
var display = this . _convert _to _display ( _values . value ) ;
_nodes [ 0 ] . appendChild ( document . createTextNode ( display . value ) ) ;
_nodes [ 1 ] . appendChild ( document . createTextNode ( display . unit ) ) ;
}
} ;
return et2 _date _duration _ro ;
} ( et2 _date _duration ) ) ;
2020-01-22 20:12:36 +01:00
exports . et2 _date _duration _ro = et2 _date _duration _ro ;
2020-01-22 17:56:38 +01:00
et2 _core _widget _1 . 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 .
2011-08-22 20:18:29 +02:00
* /
2020-01-22 17:56:38 +01:00
var et2 _date _ro = /** @class */ ( function ( _super ) {
_ _extends ( et2 _date _ro , _super ) ;
/ * *
* Constructor
* /
function et2 _date _ro ( _parent , _attrs , _child ) {
var _this =
// Call the inherited constructor
2020-01-22 18:38:33 +01:00
_super . call ( this , _parent , _attrs , et2 _core _inheritance _1 . ClassWithAttributes . extendAttributes ( et2 _date _ro . _attributes , _child || { } ) ) || this ;
2020-01-22 17:56:38 +01:00
/ * *
* Internal container for working easily with dates
* /
_this . date = new Date ( ) ;
_this . value = "" ;
_this . _labelContainer = jQuery ( document . createElement ( "label" ) )
. addClass ( "et2_label" ) ;
_this . span = jQuery ( document . createElement ( _this . getType ( ) == "date-since" || _this . getType ( ) == "date-time_today" ? "span" : "time" ) )
. addClass ( "et2_date_ro et2_label" )
. appendTo ( _this . _labelContainer ) ;
_this . setDOMNode ( _this . _labelContainer [ 0 ] ) ;
return _this ;
}
et2 _date _ro . prototype . set _value = function ( _value ) {
if ( typeof _value == 'undefined' )
_value = 0 ;
this . value = _value ;
if ( _value == 0 || _value == null ) {
this . span . attr ( "datetime" , "" ) . text ( "" ) ;
return ;
}
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 ) ;
this . date = new Date ( this . date . valueOf ( ) + ( this . date . getTimezoneOffset ( ) * 60 * 1000 ) ) ;
}
else if ( typeof _value == 'string' && ( isNaN ( _value ) ||
this . options . data _format && this . options . data _format . substr ( 0 , 3 ) === 'Ymd' ) ) {
try {
// data_format is not handled server-side for custom-fields in nextmatch
// as parseDateTime requires a separate between date and time, we fix the value here
switch ( this . options . data _format ) {
case 'Ymd' :
case 'YmdHi' :
case 'YmdHis' :
_value = _value . substr ( 0 , 4 ) + '-' + _value . substr ( 4 , 2 ) + '-' + _value . substr ( 6 , 2 ) + ' ' +
( _value . substr ( 8 , 2 ) || '00' ) + ':' + ( _value . substr ( 10 , 2 ) || '00' ) + ':' + ( _value . substr ( 12 , 2 ) || '00' ) ;
break ;
}
// parseDateTime to handle string PHP: DateTime local date/time format
// @ts-ignore
var parsed = ( typeof jQuery . datepicker . parseDateTime ( "yy-mm-dd" , "hh:mm:ss" , _value ) != 'undefined' ) ?
// @ts-ignore
jQuery . datepicker . parseDateTime ( "yy-mm-dd" , "hh:mm:ss" , _value ) :
// @ts-ignore
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 ;
}
var text = new Date ( parsed ) ;
// Update local variable, but remove the timezone offset that javascript adds
if ( parsed ) {
this . date = new Date ( text . valueOf ( ) - ( text . getTimezoneOffset ( ) * 60 * 1000 ) ) ;
}
// JS dates use milliseconds
this . date . setTime ( text . valueOf ( ) ) ;
}
else {
// _value is timestamp in usertime, ready to be used with date() function identical to PHP date()
this . date = _value ;
}
var display = this . date . toString ( ) ;
switch ( this . getType ( ) ) {
case "time_or_date" :
case "date-time_today" :
// Today - just the time
if ( date ( 'Y-m-d' , this . date ) == date ( 'Y-m-d' ) ) {
display = date ( this . egw ( ) . preference ( 'timeformat' ) == '24' ? 'H:i' : 'g:i a' , this . date ) ;
}
else if ( this . getType ( ) === "time_or_date" ) {
display = date ( this . egw ( ) . preference ( 'dateformat' ) , this . date ) ;
}
// Before today - date and time
else {
display = date ( this . egw ( ) . preference ( 'dateformat' ) + " " +
( this . egw ( ) . preference ( 'timeformat' ) == '24' ? 'H:i' : 'g:i a' ) , this . date ) ;
}
break ;
case "date" :
display = date ( this . egw ( ) . preference ( 'dateformat' ) , this . date ) ;
break ;
case "date-timeonly" :
display = date ( this . egw ( ) . preference ( 'timeformat' ) == '24' ? 'H:i' : 'g:i a' , this . date ) ;
break ;
case "date-time" :
display = date ( this . egw ( ) . preference ( 'dateformat' ) + " " +
( this . egw ( ) . preference ( 'timeformat' ) == '24' ? 'H:i' : 'g:i a' ) , this . date ) ;
break ;
case "date-since" :
var unit2label = {
'Y' : 'years' ,
'm' : 'month' ,
'd' : 'days' ,
'H' : 'hours' ,
'i' : 'minutes' ,
's' : 'seconds'
} ;
var unit2s = {
'Y' : 31536000 ,
'm' : 2628000 ,
'd' : 86400 ,
'H' : 3600 ,
'i' : 60 ,
's' : 1
} ;
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' ) {
display = Math . round ( diff / unit _s ) + ' ' + this . egw ( ) . lang ( unit2label [ unit ] ) ;
break ;
}
}
break ;
}
this . span . attr ( "datetime" , date ( "Y-m-d H:i:s" , this . date ) ) . text ( display ) ;
} ;
et2 _date _ro . prototype . 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 ;
// add class if label is empty
this . _labelContainer . toggleClass ( 'et2_label_empty' , ! label || ! parts [ 0 ] ) ;
} ;
/ * *
* 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 .
*
* @ param { array } _attrs array to add further attributes to
* /
et2 _date _ro . prototype . getDetachedAttributes = function ( _attrs ) {
_attrs . push ( "label" , "value" , "class" ) ;
} ;
/ * *
* Returns an array of DOM nodes . The ( relatively ) same DOM - Nodes have to be
* passed to the "setDetachedAttributes" function in the same order .
*
* @ return { array }
* /
et2 _date _ro . prototype . getDetachedNodes = function ( ) {
return [ this . _labelContainer [ 0 ] , this . span [ 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 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 .
* /
et2 _date _ro . prototype . setDetachedAttributes = function ( _nodes , _values ) {
this . _labelContainer = jQuery ( _nodes [ 0 ] ) ;
this . span = jQuery ( _nodes [ 1 ] ) ;
this . set _value ( _values [ "value" ] ) ;
if ( _values [ "label" ] ) {
this . set _label ( _values [ "label" ] ) ;
}
if ( _values [ "class" ] ) {
this . span . addClass ( _values [ "class" ] ) ;
}
} ;
/ * *
* Ignore all more advanced attributes .
* /
et2 _date _ro . _attributes = {
"value" : {
"type" : "string"
} ,
"type" : {
"ignore" : false
} ,
"data_format" : {
"ignore" : true ,
"description" : "Format data is in. This is not used client-side because it's always a timestamp client side."
} ,
min : { ignore : true } ,
max : { ignore : true } ,
year _range : { ignore : true }
} ;
return et2 _date _ro ;
} ( et2 _core _valueWidget _1 . et2 _valueWidget ) ) ;
2020-01-22 20:12:36 +01:00
exports . et2 _date _ro = et2 _date _ro ;
2020-01-22 17:56:38 +01:00
et2 _core _widget _1 . et2 _register _widget ( et2 _date _ro , [ "date_ro" , "date-time_ro" , "date-since" , "date-time_today" , "time_or_date" , "date-timeonly_ro" ] ) ;
2016-02-18 00:45:30 +01:00
/ * *
* Widget for selecting a date range
* /
2020-01-22 17:56:38 +01:00
var et2 _date _range = /** @class */ ( function ( _super ) {
_ _extends ( et2 _date _range , _super ) ;
/ * *
* Constructor
* /
function et2 _date _range ( _parent , _attrs , _child ) {
var _this =
// Call the inherited constructor
2020-01-22 18:38:33 +01:00
_super . call ( this , _parent , _attrs , et2 _core _inheritance _1 . ClassWithAttributes . extendAttributes ( et2 _date _range . _attributes , _child || { } ) ) || this ;
2020-01-22 17:56:38 +01:00
_this . div = jQuery ( document . createElement ( 'div' ) )
. attr ( { class : 'et2_date_range' } ) ;
_this . from = null ;
_this . to = null ;
_this . select = null ;
// Set domid
_this . set _id ( _this . id ) ;
_this . setDOMNode ( _this . div [ 0 ] ) ;
_this . _createWidget ( ) ;
_this . set _relative ( _this . options . relative || false ) ;
return _this ;
}
et2 _date _range . prototype . _createWidget = function ( ) {
var widget = this ;
this . from = et2 _core _widget _1 . et2 _createWidget ( 'date' , {
id : this . id + '[from]' ,
blur : egw . lang ( 'From' ) ,
2021-10-22 13:27:37 +02:00
onchange : function ( _node , _widget ) {
widget . to . set _min ( widget . from . getValue ( ) ) ;
if ( _node instanceof jQuery )
widget . onchange . call ( widget , _widget , widget ) ;
}
2020-01-22 17:56:38 +01:00
} , this ) ;
this . to = et2 _core _widget _1 . et2 _createWidget ( 'date' , {
id : this . id + '[to]' ,
blur : egw . lang ( 'To' ) ,
2021-10-22 13:27:37 +02:00
onchange : function ( _node , _widget ) {
widget . from . set _max ( widget . to . getValue ( ) ) ;
if ( _node instanceof jQuery )
widget . onchange . call ( widget , _widget , widget ) ;
}
2020-01-22 17:56:38 +01:00
} , this ) ;
this . select = et2 _core _widget _1 . et2 _createWidget ( 'select' , {
id : this . id + '[relative]' ,
select _options : et2 _date _range . relative _dates ,
empty _label : this . options . blur || 'All'
} , this ) ;
this . select . loadingFinished ( ) ;
} ;
/ * *
* Function which allows iterating over the complete widget tree .
* Overridden here to avoid problems with children when getting value
*
* @ param _callback is the function which should be called for each widget
* @ param _context is the context in which the function should be executed
* @ param _type is an optional parameter which specifies a class / interface
* the elements have to be instanceOf .
* /
et2 _date _range . prototype . iterateOver = function ( _callback , _context , _type ) {
if ( typeof _type == "undefined" ) {
_type = et2 _core _widget _1 . et2 _widget ;
}
if ( this . isInTree ( ) && this . instanceOf ( _type ) ) {
_callback . call ( _context , this ) ;
}
} ;
/ * *
* Toggles relative or absolute dates
*
* @ param { boolean } _value
* /
et2 _date _range . prototype . set _relative = function ( _value ) {
this . options . relative = _value ;
if ( this . options . relative ) {
jQuery ( this . from . getDOMNode ( ) ) . hide ( ) ;
jQuery ( this . to . getDOMNode ( ) ) . hide ( ) ;
}
else {
jQuery ( this . select . getDOMNode ( ) ) . hide ( ) ;
}
} ;
et2 _date _range . prototype . set _value = function ( value ) {
// @ts-ignore
if ( ! value || typeof value == 'null' ) {
this . select . set _value ( '' ) ;
this . from . set _value ( null ) ;
this . to . set _value ( null ) ;
}
// Relative
if ( value && typeof value === 'string' ) {
this . _set _relative _value ( value ) ;
}
else if ( value && typeof value . from === 'undefined' && value [ 0 ] ) {
value = {
from : value [ 0 ] ,
to : value [ 1 ] || new Date ( ) . valueOf ( ) / 1000
} ;
}
else if ( value && value . from && value . to ) {
this . from . set _value ( value . from ) ;
this . to . set _value ( value . to ) ;
}
} ;
et2 _date _range . prototype . getValue = function ( ) {
return this . options . relative ?
this . select . getValue ( ) :
{ from : this . from . getValue ( ) , to : this . to . getValue ( ) } ;
} ;
et2 _date _range . prototype . _set _relative _value = function ( _value ) {
if ( this . options . relative ) {
jQuery ( this . select . getDOMNode ( ) ) . show ( ) ;
}
// Show description
this . select . set _value ( _value ) ;
var tempDate = new Date ( ) ;
var today = new Date ( tempDate . getFullYear ( ) , tempDate . getMonth ( ) , tempDate . getDate ( ) , 0 , - tempDate . getTimezoneOffset ( ) , 0 ) ;
// Use strings to avoid references
this . from . set _value ( today . toJSON ( ) ) ;
this . to . set _value ( today . toJSON ( ) ) ;
var relative = null ;
for ( var index in et2 _date _range . relative _dates ) {
if ( et2 _date _range . relative _dates [ index ] . value === _value ) {
relative = et2 _date _range . relative _dates [ index ] ;
break ;
}
}
if ( relative ) {
var dates = [ "from" , "to" ] ;
var value = today . toJSON ( ) ;
for ( var i = 0 ; i < dates . length ; i ++ ) {
var date = dates [ i ] ;
if ( typeof relative [ date ] == "function" ) {
value = relative [ date ] ( new Date ( value ) ) ;
}
else {
value = this [ date ] . _relativeDate ( relative [ date ] ) ;
}
this [ date ] . set _value ( value ) ;
}
}
} ;
et2 _date _range . _attributes = {
value : {
"type" : "any" ,
"description" : "An object with keys 'from' and 'to' for absolute ranges, or a relative range string"
} ,
relative : {
name : 'Relative' ,
type : 'boolean' ,
description : 'Is the date range relative (this week) or absolute (2016-02-15 - 2016-02-21). This will affect the value returned.'
}
} ;
// Class Constants
et2 _date _range . relative _dates = [
// Start and end are relative offsets, see et2_date.set_min()
// or Date objects
{
value : 'Today' ,
2020-04-15 19:21:53 +02:00
label : egw . lang ( 'Today' ) ,
2020-01-22 17:56:38 +01:00
from : function ( date ) { return date ; } ,
to : function ( date ) { return date ; }
} ,
{
2020-04-15 19:21:53 +02:00
label : egw . lang ( 'Yesterday' ) ,
2020-01-22 17:56:38 +01:00
value : 'Yesterday' ,
from : function ( date ) {
date . setUTCDate ( date . getUTCDate ( ) - 1 ) ;
return date ;
} ,
to : ''
} ,
{
2020-04-15 19:21:53 +02:00
label : egw . lang ( 'This week' ) ,
2020-01-22 17:56:38 +01:00
value : 'This week' ,
from : function ( date ) { return egw . week _start ( date ) ; } ,
to : function ( date ) {
date . setUTCDate ( date . getUTCDate ( ) + 6 ) ;
return date ;
}
} ,
{
2020-04-15 19:21:53 +02:00
label : egw . lang ( 'Last week' ) ,
2020-01-22 17:56:38 +01:00
value : 'Last week' ,
from : function ( date ) {
var d = egw . week _start ( date ) ;
d . setUTCDate ( d . getUTCDate ( ) - 7 ) ;
return d ;
} ,
to : function ( date ) {
date . setUTCDate ( date . getUTCDate ( ) + 6 ) ;
return date ;
}
} ,
{
2020-04-15 19:21:53 +02:00
label : egw . lang ( 'This month' ) ,
2020-01-22 17:56:38 +01:00
value : 'This month' ,
from : function ( date ) {
date . setUTCDate ( 1 ) ;
return date ;
} ,
to : function ( date ) {
date . setUTCMonth ( date . getUTCMonth ( ) + 1 ) ;
date . setUTCDate ( 0 ) ;
return date ;
}
} ,
{
2020-04-15 19:21:53 +02:00
label : egw . lang ( 'Last month' ) ,
2020-01-22 17:56:38 +01:00
value : 'Last month' ,
from : function ( date ) {
date . setUTCMonth ( date . getUTCMonth ( ) - 1 ) ;
date . setUTCDate ( 1 ) ;
return date ;
} ,
to : function ( date ) {
date . setUTCMonth ( date . getUTCMonth ( ) + 1 ) ;
date . setUTCDate ( 0 ) ;
return date ;
}
} ,
{
2020-04-15 19:21:53 +02:00
label : egw . lang ( 'Last 3 months' ) ,
2020-01-22 17:56:38 +01:00
value : 'Last 3 months' ,
from : function ( date ) {
date . setUTCMonth ( date . getUTCMonth ( ) - 2 ) ;
date . setUTCDate ( 1 ) ;
return date ;
} ,
to : function ( date ) {
date . setUTCMonth ( date . getUTCMonth ( ) + 3 ) ;
date . setUTCDate ( 0 ) ;
return date ;
}
} ,
/ *
'This quarter' => array ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) , // Just a marker, needs special handling
'Last quarter' => array ( 0 , - 4 , 0 , 0 , 0 , - 4 , 0 , 0 ) , // Just a marker
* /
{
2020-04-15 19:21:53 +02:00
label : egw . lang ( 'This year' ) ,
2020-01-22 17:56:38 +01:00
value : 'This year' ,
from : function ( d ) {
d . setUTCMonth ( 0 ) ;
d . setUTCDate ( 1 ) ;
return d ;
} ,
to : function ( d ) {
d . setUTCMonth ( 11 ) ;
d . setUTCDate ( 31 ) ;
return d ;
}
} ,
{
2020-04-15 19:21:53 +02:00
label : egw . lang ( 'Last year' ) ,
2020-01-22 17:56:38 +01:00
value : 'Last year' ,
from : function ( d ) {
d . setUTCMonth ( 0 ) ;
d . setUTCDate ( 1 ) ;
d . setUTCYear ( d . getUTCYear ( ) - 1 ) ;
return d ;
} ,
to : function ( d ) {
d . setUTCMonth ( 11 ) ;
d . setUTCDate ( 31 ) ;
d . setUTCYear ( d . getUTCYear ( ) - 1 ) ;
return d ;
}
}
/ * S t i l l n e e d e d ?
'2 years ago' => array ( - 2 , 0 , 0 , 0 , - 1 , 0 , 0 , 0 ) ,
'3 years ago' => array ( - 3 , 0 , 0 , 0 , - 2 , 0 , 0 , 0 ) ,
* /
] ;
return et2 _date _range ;
} ( et2 _core _inputWidget _1 . et2 _inputWidget ) ) ;
2020-01-22 20:12:36 +01:00
exports . et2 _date _range = et2 _date _range ;
2020-01-22 17:56:38 +01:00
et2 _core _widget _1 . et2 _register _widget ( et2 _date _range , [ "date-range" ] ) ;
//# sourceMappingURL=et2_widget_date.js.map