import { ISerializers } from '@jupyter-widgets/base' ; import { uuid } from './utils' ; import { DescriptionView } from './widget_description' ; import { CoreDescriptionModel } from './widget_core' ; import { serialize_time } from './widget_time' ; export interface ISerializedDatetime { /**
     * UTC full year
     */ year : number ; /**
     * UTC zero-based month (0 means January, 11 means December)
     */ month : number ; /**
     * UTC day of month
     */ date : number ; /**
     * UTC hour (24H format)
     */ hours : number ; /**
     * UTC minutes
     */ minutes : number ; /**
     * UTC seconds
     */ seconds : number ; /**
     * UTC millisconds
     */ milliseconds : number ; } export function serialize_datetime ( value ) { if ( value === null ) { return null ; } else { return { year : value . getUTCFullYear ( ) , month : value . getUTCMonth ( ) , date : value . getUTCDate ( ) , hours : value . getUTCHours ( ) , minutes : value . getUTCMinutes ( ) , seconds : value . getUTCSeconds ( ) , milliseconds : value . getUTCMilliseconds ( ) , } ; } } export function deserialize_datetime ( value ) { if ( value === null ) { return null ; } else { const date = new Date ( ) ; date . setUTCFullYear ( value . year , value . month , value . date ) ; date . setUTCHours ( value . hours , value . minutes , value . seconds , value . milliseconds ) ; return date ; } } export const datetime_serializers = { serialize : serialize_datetime , deserialize : deserialize_datetime , } ; export class DatetimeModel extends CoreDescriptionModel { defaults ( ) { return { ... super . defaults ( ) , _model_name : 'DatetimeModel' , _view_name : 'DatetimeView' , value : null , disabled : false , min : null , max : null , } ; } static serializers : ISerializers = { ... CoreDescriptionModel . serializers , value : datetime_serializers , min : datetime_serializers , max : datetime_serializers , } ; } export class DatetimeView extends DescriptionView { render ( ) { super . render ( ) ; this . el . classList . add ( 'jupyter-widgets' ) ; this . el . classList . add ( 'widget-inline-hbox' ) ; this . el . classList . add ( 'widget-datetimepicker' ) ; const test = document . createElement ( 'input' ) ; test . type = 'datetime-local' ; if ( test . type === 'text' ) { this . _datepicker = document . createElement ( 'input' ) ; this . _datepicker . setAttribute ( 'type' , 'date' ) ; this . _datepicker . id = this . label . htmlFor = uuid ( ) ; this . _timepicker = document . createElement ( 'input' ) ; this . _timepicker . setAttribute ( 'type' , 'time' ) ; this . _timepicker . id = uuid ( ) ; this . el . appendChild ( this . _datepicker ) ; this . el . appendChild ( this . _timepicker ) ; } else { this . _datetimepicker = test ; this . _datetimepicker . id = this . label . htmlFor = uuid ( ) ; this . el . appendChild ( this . _datetimepicker ) ; } this . listenTo ( this . model , 'change:value' , this . _update_value ) ; this . listenTo ( this . model , 'change' , this . update2 ) ; this . _update_value ( ) ; this . update2 ( ) ; } /**
     * Update the contents of this view
     *
     * Called when the model is changed. The model may have been
     * changed by another view or by a state update from the back-end.
     */ update2 ( model ? , options ? ) { if ( options === undefined || options . updated_view !== this ) { const min = this . model . get ( 'min' ) as Date | null ; const max = this . model . get ( 'max' ) as Date | null ; if ( this . _datetimepicker ) { this . _datetimepicker . disabled = this . model . get ( 'disabled' ) ; this . _datetimepicker ! . min = Private . dt_as_dt_string ( min ) ; this . _datetimepicker ! . max = Private . dt_as_dt_string ( max ) ; } else { this . _datepicker ! . disabled = this . model . get ( 'disabled' ) ; this . _datepicker ! . min = Private . dt_as_date_string ( min ) ; this . _datepicker ! . max = Private . dt_as_date_string ( max ) ; this . _timepicker ! . disabled = this . model . get ( 'disabled' ) ; } } } events ( ) { void this . _picker_change ; void this . _picker_focusout ; return { 'change [type="date"]' : '_picker_change' , 'change [type="time"]' : '_picker_change' , 'change [type="datetime-local"]' : '_picker_change' , 'focusout [type="date"]' : '_picker_focusout' , 'focusout [type="datetime-local"]' : '_picker_focusout' , 'focusout [type="time"]' : '_picker_focusout' , } ; } private _update_value ( model ? , newValue ? , options ? ) { if ( options === undefined || options . updated_view !== this ) { const value = this . model . get ( 'value' ) as Date | null ; if ( this . _datetimepicker ) { this . _datetimepicker . value = Private . dt_as_dt_string ( value ) ; } else { this . _datepicker ! . valueAsDate = value ; this . _timepicker ! . value = Private . dt_as_time_string ( value ) ; } } } private _picker_change ( ) { if ( this . _datetimepicker ) { if ( ! this . _datetimepicker . validity . badInput ) { const v = this . _datetimepicker . value ; let date = v ? new Date ( v ) : null ; if ( date && isNaN ( date . valueOf ( ) ) ) { date = null ; } this . model . set ( 'value' , date , { updated_view : this } ) ; this . touch ( ) ; } } else { if ( ! this . _datepicker ! . validity . badInput && ! this . _timepicker ! . validity . badInput ) { const date = this . _datepicker ! . valueAsDate ; const time = serialize_time ( this . _timepicker ! . value ) ; if ( date !== null && time !== null ) { date . setHours ( time . hours , time . minutes , time . seconds , time . milliseconds ) ; } this . model . set ( 'value' , time !== null && date , { updated_view : this } ) ; this . touch ( ) ; } } } private _picker_focusout ( ) { const pickers = [ this . _datetimepicker , this . _datepicker , this . _timepicker ] ; if ( pickers . some ( ( p ) => p && p . validity . badInput ) ) { this . model . set ( 'value' , null ) ; this . touch ( ) ; } } private _datetimepicker : HTMLInputElement | undefined ; private _timepicker : HTMLInputElement | undefined ; private _datepicker : HTMLInputElement | undefined ; } namespace Private { export function dt_as_dt_string ( value ) { if ( value === null ) { return '' ; } const parts = [ ] ; parts . push ( `${ value . getFullYear ( ) . toString ( ) . padStart ( 4 , '0' ) }` ) ; parts . push ( `-${ ( value . getMonth ( ) + 1 ) . toString ( ) . padStart ( 2 , '0' ) }` ) ; parts . push ( `-${ value . getDate ( ) . toString ( ) . padStart ( 2 , '0' ) }` ) ; parts . push ( `T${ value . getHours ( ) . toString ( ) . padStart ( 2 , '0' ) }` ) ; parts . push ( `:${ value . getMinutes ( ) . toString ( ) . padStart ( 2 , '0' ) }` ) ; if ( value . getSeconds ( ) > 0 || value . getMilliseconds ( ) > 0 ) { parts . push ( `:${ value . getSeconds ( ) . toString ( ) . padStart ( 2 , '0' ) }` ) ; if ( value . getMilliseconds ( ) > 0 ) { parts . push ( `.${ value . getMilliseconds ( ) . toString ( ) . padStart ( 3 , '0' ) }` ) ; } } return parts . join ( '' ) ; } export function dt_as_date_string ( value ) { return value ? dt_as_dt_string ( value ) . split ( 'T' , 2 ) [ 0 ] : '' ; } export function dt_as_time_string ( value ) { return value ? dt_as_dt_string ( value ) . split ( 'T' , 2 ) [ 1 ] : '' ; } } export interface ISerializedNaiveDatetime { /**
     * full year
     */ year : number ; /**
     * zero-based month (0 means January, 11 means December)
     */ month : number ; /**
     * day of month
     */ date : number ; /**
     * hour (24H format)
     */ hours : number ; /**
     * minutes
     */ minutes : number ; /**
     * seconds
     */ seconds : number ; /**
     * millisconds
     */ milliseconds : number ; } export function serialize_naive ( value ) { if ( value === null ) { return null ; } else { return { year : value . getFullYear ( ) , month : value . getMonth ( ) , date : value . getDate ( ) , hours : value . getHours ( ) , minutes : value . getMinutes ( ) , seconds : value . getSeconds ( ) , milliseconds : value . getMilliseconds ( ) , } ; } } export function deserialize_naive ( value ) { if ( value === null ) { return null ; } else { const date = new Date ( ) ; date . setFullYear ( value . year , value . month , value . date ) ; date . setHours ( value . hours , value . minutes , value . seconds , value . milliseconds ) ; return date ; } } export const naive_serializers = { serialize : serialize_naive , deserialize : deserialize_naive , } ; export class NaiveDatetimeModel extends DatetimeModel { defaults ( ) { return { ... super . defaults ( ) , _model_name : 'NaiveDatetimeModel' } ; } static serializers : ISerializers = { ... CoreDescriptionModel . serializers , value : naive_serializers , min : naive_serializers , max : naive_serializers , } ; }