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