@@ -12,13 +12,14 @@ import {
12
12
import * as _ from 'underscore' ;
13
13
14
14
import {
15
- IntSliderView , IntRangeSliderView , IntTextView
15
+ IntSliderView , IntRangeSliderView , IntTextView , BaseIntSliderView
16
16
} from './widget_int' ;
17
17
18
18
import {
19
19
format
20
20
} from 'd3-format' ;
21
21
22
+
22
23
export
23
24
class FloatModel extends CoreDescriptionModel {
24
25
defaults ( ) {
@@ -69,6 +70,36 @@ class FloatSliderModel extends BoundedFloatModel {
69
70
readout_formatter : any ;
70
71
}
71
72
73
+ export
74
+ class FloatLogSliderModel extends BoundedFloatModel {
75
+ defaults ( ) {
76
+ return _ . extend ( super . defaults ( ) , {
77
+ _model_name : 'FloatLogSliderModel' ,
78
+ _view_name : 'FloatLogSliderView' ,
79
+ step : 1.0 ,
80
+ orientation : 'horizontal' ,
81
+ _range : false ,
82
+ readout : true ,
83
+ readout_format : '.2f' ,
84
+ slider_color : null ,
85
+ continuous_update : true ,
86
+ disabled : false ,
87
+ base : 2. ,
88
+ } ) ;
89
+ }
90
+ initialize ( attributes , options ) {
91
+ super . initialize ( attributes , options ) ;
92
+ this . on ( 'change:readout_format' , this . update_readout_format , this ) ;
93
+ this . update_readout_format ( ) ;
94
+ }
95
+
96
+ update_readout_format ( ) {
97
+ this . readout_formatter = format ( this . get ( 'readout_format' ) ) ;
98
+ }
99
+
100
+ readout_formatter : any ;
101
+ }
102
+
72
103
export
73
104
class FloatRangeSliderModel extends FloatSliderModel { }
74
105
@@ -85,6 +116,111 @@ class FloatSliderView extends IntSliderView {
85
116
_parse_value = parseFloat ;
86
117
}
87
118
119
+
120
+ export
121
+ class FloatLogSliderView extends BaseIntSliderView {
122
+
123
+ update ( options ?) {
124
+ super . update ( options ) ;
125
+ let min = this . model . get ( 'min' ) ;
126
+ let max = this . model . get ( 'max' ) ;
127
+ let value = this . model . get ( 'value' ) ;
128
+ let base = this . model . get ( 'base' ) ;
129
+
130
+ let log_value = Math . log ( value ) / Math . log ( base ) ;
131
+
132
+ if ( log_value > max ) {
133
+ log_value = max ;
134
+ } else if ( log_value < min ) {
135
+ log_value = min ;
136
+ }
137
+ this . $slider . slider ( 'option' , 'value' , log_value ) ;
138
+ this . readout . textContent = this . valueToString ( value ) ;
139
+ if ( this . model . get ( 'value' ) !== value ) {
140
+ this . model . set ( 'value' , value , { updated_view : this } ) ;
141
+ this . touch ( ) ;
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Write value to a string
147
+ */
148
+ valueToString ( value : number ) : string {
149
+ let format = this . model . readout_formatter ;
150
+ return format ( value ) ;
151
+ }
152
+
153
+ /**
154
+ * Parse value from a string
155
+ */
156
+ stringToValue ( text : string ) : number {
157
+ return this . _parse_value ( text ) ;
158
+ }
159
+
160
+ /**
161
+ * this handles the entry of text into the contentEditable label first, the
162
+ * value is checked if it contains a parseable value then it is clamped
163
+ * within the min-max range of the slider finally, the model is updated if
164
+ * the value is to be changed
165
+ *
166
+ * if any of these conditions are not met, the text is reset
167
+ */
168
+ handleTextChange ( ) {
169
+ let value = this . stringToValue ( this . readout . textContent ) ;
170
+ let vmin = this . model . get ( 'min' ) ;
171
+ let vmax = this . model . get ( 'max' ) ;
172
+
173
+ if ( isNaN ( value as number ) ) {
174
+ this . readout . textContent = this . valueToString ( this . model . get ( 'value' ) ) ;
175
+ } else {
176
+ value = Math . max ( Math . min ( value as number , vmax ) , vmin ) ;
177
+
178
+ if ( value !== this . model . get ( 'value' ) ) {
179
+ this . readout . textContent = this . valueToString ( value ) ;
180
+ this . model . set ( 'value' , value , { updated_view : this } ) ;
181
+ this . touch ( ) ;
182
+ } else {
183
+ this . readout . textContent = this . valueToString ( this . model . get ( 'value' ) ) ;
184
+ }
185
+ }
186
+ }
187
+ /**
188
+ * Called when the slider value is changing.
189
+ */
190
+ handleSliderChange ( e , ui ) {
191
+ let base = this . model . get ( 'base' ) ;
192
+ let actual_value = Math . pow ( base , this . _validate_slide_value ( ui . value ) ) ;
193
+ this . readout . textContent = this . valueToString ( actual_value ) ;
194
+
195
+ // Only persist the value while sliding if the continuous_update
196
+ // trait is set to true.
197
+ if ( this . model . get ( 'continuous_update' ) ) {
198
+ this . handleSliderChanged ( e , ui ) ;
199
+ }
200
+ }
201
+
202
+ /**
203
+ * Called when the slider value has changed.
204
+ *
205
+ * Calling model.set will trigger all of the other views of the
206
+ * model to update.
207
+ */
208
+ handleSliderChanged ( e , ui ) {
209
+ let base = this . model . get ( 'base' ) ;
210
+ let actual_value = Math . pow ( base , this . _validate_slide_value ( ui . value ) ) ;
211
+ this . model . set ( 'value' , actual_value , { updated_view : this } ) ;
212
+ this . touch ( ) ;
213
+ }
214
+
215
+ _validate_slide_value ( x ) {
216
+ return x ;
217
+ }
218
+
219
+ _parse_value = parseFloat ;
220
+
221
+ }
222
+
223
+
88
224
export
89
225
class FloatRangeSliderView extends IntRangeSliderView {
90
226
/**
0 commit comments