import { CoreDescriptionModel } from './widget_core' ; import { IntSliderView , IntRangeSliderView , IntTextView , BaseIntSliderView , } from './widget_int' ; import { format } from 'd3-format' ; import noUiSlider from 'nouislider' ; export class FloatModel extends CoreDescriptionModel { defaults ( ) { return { ... super . defaults ( ) , _model_name : 'FloatModel' , value : 0 , } ; } } export class BoundedFloatModel extends FloatModel { defaults ( ) { return { ... super . defaults ( ) , _model_name : 'BoundedFloatModel' , max : 100.0 , min : 0.0 , } ; } } export class FloatSliderModel extends BoundedFloatModel { defaults ( ) { return { ... super . defaults ( ) , _model_name : 'FloatSliderModel' , _view_name : 'FloatSliderView' , step : 1.0 , orientation : 'horizontal' , _range : false , readout : true , readout_format : '.2f' , slider_color : null , continuous_update : true , disabled : false , } ; } initialize ( attributes , options ) { super . initialize ( attributes , options ) ; this . on ( 'change:readout_format' , this . update_readout_format , this ) ; this . update_readout_format ( ) ; } update_readout_format ( ) { this . readout_formatter = format ( this . get ( 'readout_format' ) ) ; } readout_formatter : any ; } export class FloatLogSliderModel extends BoundedFloatModel { defaults ( ) { return { ... super . defaults ( ) , _model_name : 'FloatLogSliderModel' , _view_name : 'FloatLogSliderView' , step : 0.1 , orientation : 'horizontal' , _range : false , readout : true , readout_format : '.3g' , slider_color : null , continuous_update : true , disabled : false , base : 10 , value : 1.0 , min : 0 , max : 4 , } ; } initialize ( attributes , options ) { super . initialize ( attributes , options ) ; this . on ( 'change:readout_format' , this . update_readout_format , this ) ; this . update_readout_format ( ) ; } update_readout_format ( ) { this . readout_formatter = format ( this . get ( 'readout_format' ) ) ; } readout_formatter : any ; } export class FloatRangeSliderModel extends FloatSliderModel { } export class FloatSliderView extends IntSliderView { /**
     * Validate the value of the slider before sending it to the back-end
     * and applying it to the other views on the page.
     */ _validate_slide_value ( x ) { return x ; } _parse_value = parseFloat ; } export class FloatLogSliderView extends BaseIntSliderView { update ( options ? ) { super . update ( options ) ; const value = this . model . get ( 'value' ) ; this . readout . textContent = this . valueToString ( value ) ; } param value returns logCalc ( value ) { const min = this . model . get ( 'min' ) ; const max = this . model . get ( 'max' ) ; const base = this . model . get ( 'base' ) ; let log_value = Math . log ( value ) / Math . log ( base ) ; if ( log_value > max ) { log_value = max ; } else if ( log_value < min ) { log_value = min ; } return log_value ; } createSlider ( ) { const orientation = this . model . get ( 'orientation' ) ; const behavior = this . model . get ( 'behavior' ) ; noUiSlider . create ( this . $slider , { start : this . logCalc ( this . model . get ( 'value' ) ) , behaviour : behavior , range : { min : this . model . get ( 'min' ) , max : this . model . get ( 'max' ) , } , step : this . model . get ( 'step' ) ?? undefined , animate : false , orientation : orientation , direction : orientation === 'horizontal' ? 'ltr' : 'rtl' , format : { from : ( value ) : number => Number ( value ) , to : ( value ) : number => value , } , } ) ; this . $slider . noUiSlider . on ( 'update' , ( values , handle ) => { this . handleSliderChange ( values , handle ) ; } ) ; this . $slider . noUiSlider . on ( 'end' , ( values , handle ) => { this . handleSliderChanged ( values , handle ) ; } ) ; } /**
     * Write value to a string
     */ valueToString ( value ) { const format = this . model . readout_formatter ; return format ( value ) ; } /**
     * Parse value from a string
     */ stringToValue ( text ) { return text === null ? NaN : this . _parse_value ( text ) ; } /**
     * this handles the entry of text into the contentEditable label first, the
     * value is checked if it contains a parseable value then it is clamped
     * within the min-max range of the slider finally, the model is updated if
     * the value is to be changed
     *
     * if any of these conditions are not met, the text is reset
     */ handleTextChange ( ) { let value = this . stringToValue ( this . readout . textContent ) ; const vmin = this . model . get ( 'min' ) ; const vmax = this . model . get ( 'max' ) ; const base = this . model . get ( 'base' ) ; if ( isNaN ( value ) ) { this . readout . textContent = this . valueToString ( this . model . get ( 'value' ) ) ; } else { value = Math . max ( Math . min ( value , Math . pow ( base , vmax ) ) , Math . pow ( base , vmin ) ) ; if ( value !== this . model . get ( 'value' ) ) { this . readout . textContent = this . valueToString ( value ) ; this . model . set ( 'value' , value , { updated_view : this } ) ; this . touch ( ) ; } else { this . readout . textContent = this . valueToString ( this . model . get ( 'value' ) ) ; } } } /**
     * Called when the slider value is changing.
     */ handleSliderChange ( values , handle ) { const base = this . model . get ( 'base' ) ; const actual_value = Math . pow ( base , this . _validate_slide_value ( values [ 0 ] ) ) ; this . readout . textContent = this . valueToString ( actual_value ) ; if ( this . model . get ( 'continuous_update' ) ) { this . handleSliderChanged ( values , handle ) ; } } /**
     * Called when the slider value has changed.
     *
     * Calling model.set will trigger all of the other views of the
     * model to update.
     */ handleSliderChanged ( values , handle ) { if ( this . _updating_slider ) { return ; } const base = this . model . get ( 'base' ) ; const actual_value = Math . pow ( base , this . _validate_slide_value ( values [ 0 ] ) ) ; this . model . set ( 'value' , actual_value , { updated_view : this } ) ; this . touch ( ) ; } updateSliderValue ( model , value , options ) { if ( options . updated_view === this ) { return ; } const log_value = this . logCalc ( this . model . get ( 'value' ) ) ; this . $slider . noUiSlider . set ( log_value ) ; } updateSliderOptions ( e ) { this . $slider . noUiSlider . updateOptions ( { start : this . logCalc ( this . model . get ( 'value' ) ) , range : { min : this . model . get ( 'min' ) , max : this . model . get ( 'max' ) , } , step : this . model . get ( 'step' ) , } ) ; } _validate_slide_value ( x ) { return x ; } _parse_value = parseFloat ; private _updating_slider : boolean ; } export class FloatRangeSliderView extends IntRangeSliderView { /**
     * Validate the value of the slider before sending it to the back-end
     * and applying it to the other views on the page.
     */ _validate_slide_value ( x ) { return x ; } _parse_value = parseFloat ; _range_regex = /^\s*([+-]?(?:\d*\.?\d+|\d+\.)(?:[eE][-:]?\d+)?)\s*[-:–]\s*([+-]?(?:\d*\.?\d+|\d+\.)(?:[eE][+-]?\d+)?)/ ; } export class FloatTextModel extends FloatModel { defaults ( ) { return { ... super . defaults ( ) , _model_name : 'FloatTextModel' , _view_name : 'FloatTextView' , disabled : false , continuous_update : false , } ; } } export class BoundedFloatTextModel extends BoundedFloatModel { defaults ( ) { return { ... super . defaults ( ) , _model_name : 'BoundedFloatTextModel' , _view_name : 'FloatTextView' , disabled : false , continuous_update : false , step : 0.1 , } ; } } export class FloatTextView extends IntTextView { _parse_value = parseFloat ; _default_step = 'any' ; /**
     * Handle key press
     */ handleKeypress ( e ) { e . stopPropagation ( ) ; } /**
     * Handle key up
     */ handleKeyUp ( e ) { } } export class FloatProgressModel extends BoundedFloatModel { defaults ( ) { return { ... super . defaults ( ) , _model_name : 'FloatProgressModel' , _view_name : 'ProgressView' , orientation : 'horizontal' , bar_style : '' , style : null , } ; } }