##// END OF EJS Templates
Merge pull request #6171 from tarzzz/slider-value-validate...
Jonathan Frederic -
r17680:eb4529c1 merge
parent child Browse files
Show More
@@ -1,298 +1,310 b''
1 1 // Copyright (c) IPython Development Team.
2 2 // Distributed under the terms of the Modified BSD License.
3 3
4 4 define([
5 5 "widgets/js/widget",
6 6 "jqueryui",
7 7 "bootstrap",
8 8 ], function(widget, $){
9 9
10 10 var IntSliderView = widget.DOMWidgetView.extend({
11 11 render : function(){
12 12 // Called when view is rendered.
13 13 this.$el
14 14 .addClass('widget-hbox-single');
15 15 this.$label = $('<div />')
16 16 .appendTo(this.$el)
17 17 .addClass('widget-hlabel')
18 18 .hide();
19 19
20 20 this.$slider = $('<div />')
21 21 .slider({})
22 22 .addClass('slider');
23 23 // Put the slider in a container
24 24 this.$slider_container = $('<div />')
25 25 .addClass('widget-hslider')
26 26 .append(this.$slider);
27 27 this.$el.append(this.$slider_container);
28 28
29 29 this.$readout = $('<div/>')
30 30 .appendTo(this.$el)
31 31 .addClass('widget-hreadout')
32 32 .hide();
33 33
34 34 // Set defaults.
35 35 this.update();
36 36 },
37 37
38 38 update : function(options){
39 39 // Update the contents of this view
40 40 //
41 41 // Called when the model is changed. The model may have been
42 42 // changed by another view or by a state update from the back-end.
43 43 if (options === undefined || options.updated_view != this) {
44 44 // JQuery slider option keys. These keys happen to have a
45 45 // one-to-one mapping with the corrosponding keys of the model.
46 46 var jquery_slider_keys = ['step', 'max', 'min', 'disabled'];
47 47 var that = this;
48 48 that.$slider.slider({});
49 49 _.each(jquery_slider_keys, function(key, i) {
50 50 var model_value = that.model.get(key);
51 51 if (model_value !== undefined) {
52 52 that.$slider.slider("option", key, model_value);
53 53 }
54 54 });
55 55
56 56 // WORKAROUND FOR JQUERY SLIDER BUG.
57 57 // The horizontal position of the slider handle
58 58 // depends on the value of the slider at the time
59 59 // of orientation change. Before applying the new
60 60 // workaround, we set the value to the minimum to
61 61 // make sure that the horizontal placement of the
62 62 // handle in the vertical slider is always
63 63 // consistent.
64 64 var orientation = this.model.get('orientation');
65 var value = this.model.get('min');
66 this.$slider.slider('option', 'value', value);
65 var min = this.model.get('min');
66 var max = this.model.get('max');
67 this.$slider.slider('option', 'value', min);
67 68 this.$slider.slider('option', 'orientation', orientation);
68 value = this.model.get('value');
69 var value = this.model.get('value');
70 if(value > max) {
71 value = max;
72 }
73 else if(value < min){
74 value = min;
75 }
69 76 this.$slider.slider('option', 'value', value);
70 77 this.$readout.text(value);
71 78
79 if(this.model.get('value')!=value) {
80 this.model.set('value', value, {updated_view: this});
81 this.touch();
82 }
83
72 84 // Use the right CSS classes for vertical & horizontal sliders
73 85 if (orientation=='vertical') {
74 86 this.$slider_container
75 87 .removeClass('widget-hslider')
76 88 .addClass('widget-vslider');
77 89 this.$el
78 90 .removeClass('widget-hbox-single')
79 91 .addClass('widget-vbox-single');
80 92 this.$label
81 93 .removeClass('widget-hlabel')
82 94 .addClass('widget-vlabel');
83 95 this.$readout
84 96 .removeClass('widget-hreadout')
85 97 .addClass('widget-vreadout');
86 98
87 99 } else {
88 100 this.$slider_container
89 101 .removeClass('widget-vslider')
90 102 .addClass('widget-hslider');
91 103 this.$el
92 104 .removeClass('widget-vbox-single')
93 105 .addClass('widget-hbox-single');
94 106 this.$label
95 107 .removeClass('widget-vlabel')
96 108 .addClass('widget-hlabel');
97 109 this.$readout
98 110 .removeClass('widget-vreadout')
99 111 .addClass('widget-hreadout');
100 112 }
101 113
102 114 var description = this.model.get('description');
103 115 if (description.length === 0) {
104 116 this.$label.hide();
105 117 } else {
106 118 this.$label.text(description);
107 119 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
108 120 this.$label.show();
109 121 }
110 122
111 123 var readout = this.model.get('readout');
112 124 if (readout) {
113 125 this.$readout.show();
114 126 } else {
115 127 this.$readout.hide();
116 128 }
117 129 }
118 130 return IntSliderView.__super__.update.apply(this);
119 131 },
120 132
121 133 events: {
122 134 // Dictionary of events and their handlers.
123 135 "slide" : "handleSliderChange"
124 136 },
125 137
126 138 handleSliderChange: function(e, ui) {
127 139 // Called when the slider value is changed.
128 140
129 141 // Calling model.set will trigger all of the other views of the
130 142 // model to update.
131 143 var actual_value = this._validate_slide_value(ui.value);
132 144 this.model.set('value', actual_value, {updated_view: this});
133 145 this.$readout.text(actual_value);
134 146 this.touch();
135 147 },
136 148
137 149 _validate_slide_value: function(x) {
138 150 // Validate the value of the slider before sending it to the back-end
139 151 // and applying it to the other views on the page.
140 152
141 153 // Double bit-wise not truncates the decimel (int cast).
142 154 return ~~x;
143 155 },
144 156 });
145 157
146 158
147 159 var IntTextView = widget.DOMWidgetView.extend({
148 160 render : function(){
149 161 // Called when view is rendered.
150 162 this.$el
151 163 .addClass('widget-hbox-single');
152 164 this.$label = $('<div />')
153 165 .appendTo(this.$el)
154 166 .addClass('widget-hlabel')
155 167 .hide();
156 168 this.$textbox = $('<input type="text" />')
157 169 .addClass('form-control')
158 170 .addClass('widget-numeric-text')
159 171 .appendTo(this.$el);
160 172 this.update(); // Set defaults.
161 173 },
162 174
163 175 update : function(options){
164 176 // Update the contents of this view
165 177 //
166 178 // Called when the model is changed. The model may have been
167 179 // changed by another view or by a state update from the back-end.
168 180 if (options === undefined || options.updated_view != this) {
169 181 var value = this.model.get('value');
170 182 if (this._parse_value(this.$textbox.val()) != value) {
171 183 this.$textbox.val(value);
172 184 }
173 185
174 186 if (this.model.get('disabled')) {
175 187 this.$textbox.attr('disabled','disabled');
176 188 } else {
177 189 this.$textbox.removeAttr('disabled');
178 190 }
179 191
180 192 var description = this.model.get('description');
181 193 if (description.length === 0) {
182 194 this.$label.hide();
183 195 } else {
184 196 this.$label.text(description);
185 197 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
186 198 this.$label.show();
187 199 }
188 200 }
189 201 return IntTextView.__super__.update.apply(this);
190 202 },
191 203
192 204 events: {
193 205 // Dictionary of events and their handlers.
194 206 "keyup input" : "handleChanging",
195 207 "paste input" : "handleChanging",
196 208 "cut input" : "handleChanging",
197 209
198 210 // Fires only when control is validated or looses focus.
199 211 "change input" : "handleChanged"
200 212 },
201 213
202 214 handleChanging: function(e) {
203 215 // Handles and validates user input.
204 216
205 217 // Try to parse value as a int.
206 218 var numericalValue = 0;
207 219 if (e.target.value !== '') {
208 220 var trimmed = e.target.value.trim();
209 221 if (!(['-', '-.', '.', '+.', '+'].indexOf(trimmed) >= 0)) {
210 222 numericalValue = this._parse_value(e.target.value);
211 223 }
212 224 }
213 225
214 226 // If parse failed, reset value to value stored in model.
215 227 if (isNaN(numericalValue)) {
216 228 e.target.value = this.model.get('value');
217 229 } else if (!isNaN(numericalValue)) {
218 230 if (this.model.get('max') !== undefined) {
219 231 numericalValue = Math.min(this.model.get('max'), numericalValue);
220 232 }
221 233 if (this.model.get('min') !== undefined) {
222 234 numericalValue = Math.max(this.model.get('min'), numericalValue);
223 235 }
224 236
225 237 // Apply the value if it has changed.
226 238 if (numericalValue != this.model.get('value')) {
227 239
228 240 // Calling model.set will trigger all of the other views of the
229 241 // model to update.
230 242 this.model.set('value', numericalValue, {updated_view: this});
231 243 this.touch();
232 244 }
233 245 }
234 246 },
235 247
236 248 handleChanged: function(e) {
237 249 // Applies validated input.
238 250 if (this.model.get('value') != e.target.value) {
239 251 e.target.value = this.model.get('value');
240 252 }
241 253 },
242 254
243 255 _parse_value: function(value) {
244 256 // Parse the value stored in a string.
245 257 return parseInt(value);
246 258 },
247 259 });
248 260
249 261
250 262 var ProgressView = widget.DOMWidgetView.extend({
251 263 render : function(){
252 264 // Called when view is rendered.
253 265 this.$el
254 266 .addClass('widget-hbox-single');
255 267 this.$label = $('<div />')
256 268 .appendTo(this.$el)
257 269 .addClass('widget-hlabel')
258 270 .hide();
259 271 this.$progress = $('<div />')
260 272 .addClass('progress')
261 273 .addClass('widget-progress')
262 274 .appendTo(this.$el);
263 275 this.$bar = $('<div />')
264 276 .addClass('progress-bar')
265 277 .css('width', '50%')
266 278 .appendTo(this.$progress);
267 279 this.update(); // Set defaults.
268 280 },
269 281
270 282 update : function(){
271 283 // Update the contents of this view
272 284 //
273 285 // Called when the model is changed. The model may have been
274 286 // changed by another view or by a state update from the back-end.
275 287 var value = this.model.get('value');
276 288 var max = this.model.get('max');
277 289 var min = this.model.get('min');
278 290 var percent = 100.0 * (value - min) / (max - min);
279 291 this.$bar.css('width', percent + '%');
280 292
281 293 var description = this.model.get('description');
282 294 if (description.length === 0) {
283 295 this.$label.hide();
284 296 } else {
285 297 this.$label.text(description);
286 298 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]);
287 299 this.$label.show();
288 300 }
289 301 return ProgressView.__super__.update.apply(this);
290 302 },
291 303 });
292 304
293 305 return {
294 306 'IntSliderView': IntSliderView,
295 307 'IntTextView': IntTextView,
296 308 'ProgressView': ProgressView,
297 309 };
298 310 });
General Comments 0
You need to be logged in to leave comments. Login now