2017-07-12 11:32:25 +00:00
import { module } from '../module' ;
import Component from '../lib/component' ;
import Flatpickr from 'vendor/src/flatpickr' ;
import './style.scss' ;
// equivalences to format date between flatpicker and angularjs
2017-09-19 13:03:39 +00:00
export const formatEquivalence = {
2017-07-12 11:32:25 +00:00
d : 'dd' , // Day of the month, 2 digits with leading zeros (01 to 31)
j : 'd' , // Day of the month without leading zeros (1 to 31)
m : 'MM' , // Month in year, padded (01-12)
n : 'M' , // Month in year (1-12)
y : 'yy' , // A two digit representation of a year (00-99)
Y : 'yyyy' , // A full numeric representation of a year, 4 digits (1999 or 2003)
H : 'HH' , // Hour in AM/PM, padded (01-12)
h : 'H' , // Hour in AM/PM, (1-12)
i : 'mm' , // Minutes (00 to 59)
s : 'ss' // Seconds (00 to 59)
} ;
class DatePicker extends Component {
2017-12-13 13:14:44 +00:00
constructor ( $element , $translate , $filter , $timeout , $attrs ) {
2017-07-12 11:32:25 +00:00
super ( $element ) ;
this . input = $element [ 0 ] . querySelector ( 'input' ) ;
this . $translate = $translate ;
this . $filter = $filter ;
2017-07-12 12:32:15 +00:00
this . $timeout = $timeout ;
2017-12-13 13:11:48 +00:00
this . $attrs = $attrs ;
2017-07-12 11:32:25 +00:00
this . enabled = true ;
2017-07-13 11:12:09 +00:00
this . _modelView = null ;
2017-07-12 11:32:25 +00:00
this . _model = undefined ;
2017-10-31 09:40:12 +00:00
this . _optionsChecked = false ;
2018-01-10 09:48:02 +00:00
this . _waitingInit = 0 ;
2017-11-02 07:18:37 +00:00
this . hasFocus = false ;
this . hasMouseIn = false ;
2017-07-13 09:03:22 +00:00
componentHandler . upgradeElement ( $element [ 0 ] . firstChild ) ;
2017-07-12 11:32:25 +00:00
}
get model ( ) {
return this . _model ;
}
set model ( value ) {
2018-01-10 09:48:02 +00:00
if ( this . _optionsChecked ) {
this . _waitingInit = 0 ;
this . _model = value ;
if ( value && ! this . modelView ) {
let initialDateFormat = this . $translate . use ( ) === 'es' ? 'd-m-Y' : 'Y-m-d' ;
if ( this . iniOptions . enableTime ) {
initialDateFormat += ' H:i:s' ;
}
let format = this . _formatFlat2Angular ( initialDateFormat ) ;
this . _modelView = this . $filter ( 'date' ) ( new Date ( value ) , format ) ;
this . mdlUpdate ( ) ;
}
} else if ( this . _waitingInit < 4 ) {
this . _waitingInit ++ ;
this . $timeout ( ( ) => {
this . model = value ;
} , 250 ) ;
} else {
this . model = null ;
this . modelView = '' ;
this . _waitingInit = 0 ;
2017-07-12 11:32:25 +00:00
}
}
get modelView ( ) {
return this . _modelView ;
}
set modelView ( value ) {
this . _modelView = value ;
2017-07-13 09:03:22 +00:00
this . input . value = value ;
2017-07-12 11:32:25 +00:00
this . _setModel ( value ) ;
2018-01-10 09:48:02 +00:00
this . mdlUpdate ( ) ;
2017-07-12 11:32:25 +00:00
}
2018-01-10 09:48:02 +00:00
2017-07-12 11:32:25 +00:00
onClear ( ) {
2017-07-13 09:03:22 +00:00
this . modelView = null ;
2017-07-12 11:32:25 +00:00
}
2017-12-04 07:17:29 +00:00
onClick ( ) {
if ( this . vp ) {
this . vp . open ( ) ;
}
}
2017-07-12 11:32:25 +00:00
mdlUpdate ( ) {
2018-01-10 09:48:02 +00:00
this . $timeout ( ( ) => {
let mdlField = this . element . firstChild . MaterialTextfield ;
if ( mdlField )
mdlField . updateClasses _ ( ) ;
} , 500 ) ;
2017-07-12 11:32:25 +00:00
}
_formatFlat2Angular ( string ) { // change string Flatpickr format to angular format (d-m-Y -> dd-MM-yyyy)
2017-07-13 09:03:22 +00:00
let aux = string . split ( /[ZT.,/ :-]/ ) ;
2017-07-12 11:32:25 +00:00
let parts = [ ] ;
aux . forEach (
val => {
2017-09-19 13:03:39 +00:00
parts . push ( formatEquivalence [ val ] ) ;
2017-07-12 11:32:25 +00:00
}
) ;
2017-07-13 11:12:09 +00:00
if ( string . indexOf ( ' ' ) !== - 1 || string . indexOf ( 'T' ) !== - 1 ) { // datetime format
2017-07-12 11:32:25 +00:00
let dates = parts . slice ( 0 , 3 ) . join ( '-' ) ;
let hours = parts . slice ( 3 , parts . length ) . join ( ':' ) ;
return ` ${ dates } ${ hours } ` . trim ( ) ;
} else if ( string . indexOf ( ':' ) !== - 1 ) { // only time format
return parts . join ( ':' ) ;
2017-10-03 12:41:35 +00:00
} // only date format
return parts . join ( '-' ) ;
2017-07-12 11:32:25 +00:00
}
_setModel ( value ) {
2017-07-12 12:32:15 +00:00
let model ;
2017-07-12 11:32:25 +00:00
if ( ! value ) {
2017-07-12 12:32:15 +00:00
model = undefined ;
2017-10-11 12:21:32 +00:00
} else if ( ! this . iniOptions || ( this . iniOptions . dateFormat && this . iniOptions . dateFormat . startsWith ( 'Y-m-d' ) ) ) {
2017-07-12 12:32:15 +00:00
model = value ;
2017-07-12 11:32:25 +00:00
} else {
2017-07-13 09:03:22 +00:00
let formats = this . iniOptions . dateFormat . split ( /[ZT.,/ :-]/ ) ;
let aux = value . split ( /[ZT.,/ :-]/ ) ;
2017-07-12 11:32:25 +00:00
let date = { } ;
formats . forEach (
( k , i ) => {
if ( k . toLowerCase ( ) === 'y' ) {
date . year = aux [ i ] ;
} else if ( k === 'm' || k === 'n' ) {
date . month = aux [ i ] ;
} else if ( k === 'd' || k === 'j' ) {
date . day = aux [ i ] ;
} else if ( k . toLowerCase ( ) === 'h' ) {
date . hour = aux [ i ] ;
} else if ( k === 'i' ) {
date . minutes = aux [ i ] ;
} else if ( k === 's' ) {
date . seccons = aux [ i ] ;
}
}
) ;
let dateStr = '' ;
let hourStr = '' ;
if ( date . year && date . month && date . day ) {
dateStr = ` ${ date . year } - ${ date . month } - ${ date . day } ` ;
}
if ( date . hour ) {
hourStr = date . hour ;
if ( date . minutes ) {
hourStr += ':' + date . minutes ;
} else {
hourStr += ':00' ;
}
if ( date . seccons ) {
hourStr += ':' + date . seccons ;
} else {
hourStr += ':00' ;
}
}
2017-07-12 12:32:15 +00:00
model = ` ${ dateStr } ${ hourStr } ` . trim ( ) ;
2017-07-13 06:58:48 +00:00
}
2017-07-12 12:32:15 +00:00
2017-07-12 12:57:40 +00:00
if ( this . model !== model ) {
this . model = model ;
}
2017-07-12 11:32:25 +00:00
}
2017-10-31 08:44:24 +00:00
_getOptions ( ) {
2017-10-31 09:40:12 +00:00
if ( this . iniOptions && this . _optionsChecked ) {
2017-10-31 08:44:24 +00:00
return this . iniOptions ;
2017-10-31 09:40:12 +00:00
} else if ( ! this . iniOptions ) {
this . iniOptions = { } ;
2017-10-31 08:44:24 +00:00
}
2017-07-12 11:32:25 +00:00
2017-10-31 09:40:12 +00:00
if ( ! this . iniOptions . locale )
this . iniOptions . locale = this . $translate . use ( ) ;
2017-07-12 11:32:25 +00:00
2018-01-09 12:53:21 +00:00
if ( ! this . iniOptions . dateFormat )
this . iniOptions . dateFormat = this . iniOptions . locale === 'es' ? 'd-m-Y' : 'm-d-Y' ;
2017-10-31 09:40:12 +00:00
else if ( this . iniOptions . dateFormat ) {
let format = this . iniOptions . dateFormat . split ( /[ZT.,/ :-]/ ) ;
2017-07-13 09:03:22 +00:00
if ( format . length <= 1 ) {
throw new Error ( ` Error: Invalid string format ${ format } ` ) ;
}
format . forEach (
val => {
2017-09-19 13:03:39 +00:00
if ( ! formatEquivalence [ val ] ) {
2017-10-31 09:40:12 +00:00
throw new Error ( ` Error in dateFormat ${ this . iniOptions . dateFormat } : is not like Flatpickr Formatting Token https://chmln.github.io/flatpickr/formatting/ ` ) ;
2017-07-13 09:03:22 +00:00
}
}
) ;
}
2017-12-13 13:11:48 +00:00
if ( this . $attrs . hasOwnProperty ( 'today' ) ) {
this . iniOptions . defaultDate = new Date ( ) ;
}
2017-10-31 09:40:12 +00:00
this . _optionsChecked = true ;
return this . iniOptions ;
2017-10-31 08:44:24 +00:00
}
2017-12-04 07:17:29 +00:00
initPicker ( ) {
2017-10-31 08:44:24 +00:00
this . iniOptions = this . _getOptions ( ) ;
2017-11-02 07:18:37 +00:00
this . isTimePicker = ( this . iniOptions && this . iniOptions . enableTime && this . iniOptions . noCalendar ) ;
2017-10-31 08:44:24 +00:00
this . vp = new Flatpickr ( this . input , this . iniOptions ) ;
2017-12-13 13:11:48 +00:00
if ( this . iniOptions . defaultDate ) {
this . modelView = this . vp . formatDate ( this . iniOptions . defaultDate , this . iniOptions . dateFormat ) ;
}
2017-07-12 11:32:25 +00:00
}
2017-12-04 07:17:29 +00:00
destroyPicker ( ) {
2017-07-12 11:32:25 +00:00
if ( this . vp )
this . vp . destroy ( ) ;
2017-12-04 07:17:29 +00:00
this . vp = undefined ;
}
2018-01-10 09:48:02 +00:00
$onChanges ( objChange ) {
if ( objChange . iniOptions && objChange . iniOptions . currentValue ) {
this . iniOptions = Object . assign ( this . iniOptions , objChange . iniOptions . currentValue ) ;
}
}
2017-12-04 07:17:29 +00:00
$onInit ( ) {
this . initPicker ( ) ;
}
$onDestroy ( ) {
this . destroyPicker ( ) ;
2017-07-12 11:32:25 +00:00
}
}
2017-12-13 13:14:44 +00:00
DatePicker . $inject = [ '$element' , '$translate' , '$filter' , '$timeout' , '$attrs' ] ;
2017-07-12 11:32:25 +00:00
module . component ( 'vnDatePicker' , {
template : require ( './datePicker.html' ) ,
bindings : {
model : '=' ,
label : '@?' ,
name : '@?' ,
enabled : '<?' ,
rule : '<?' ,
2017-07-13 09:03:22 +00:00
iniOptions : '<?'
2017-07-12 11:32:25 +00:00
} ,
controller : DatePicker
} ) ;