##// END OF EJS Templates
add locks to update everywhere by using options to pass this...
Jonathan Frederic -
Show More
@@ -1,133 +1,129 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2013 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // BoolWidget
10 10 //============================================================================
11 11
12 12 /**
13 13 * @module IPython
14 14 * @namespace IPython
15 15 **/
16 16
17 17 define(["notebook/js/widgets/widget"], function(widget_manager){
18 18
19 19 var BoolWidgetModel = IPython.WidgetModel.extend({});
20 20 widget_manager.register_widget_model('BoolWidgetModel', BoolWidgetModel);
21 21
22 22 var CheckboxView = IPython.DOMWidgetView.extend({
23 23
24 24 // Called when view is rendered.
25 25 render : function(){
26 26 this.$el
27 27 .addClass('widget-hbox-single');
28 28 this.$label = $('<div />')
29 29 .addClass('widget-hlabel')
30 30 .appendTo(this.$el)
31 31 .hide();
32 32 var that = this;
33 33 this.$checkbox = $('<input />')
34 34 .attr('type', 'checkbox')
35 35 .click(function(el) {
36 that.user_invoked_update = true;
37 36
38 37 // Calling model.set will trigger all of the other views of the
39 38 // model to update.
40 that.model.set('value', that.$checkbox.prop('checked'));
39 that.model.set('value', that.$checkbox.prop('checked'), {updated_view: this});
41 40 that.touch();
42 that.user_invoked_update = false;
43 41 })
44 42 .appendTo(this.$el);
45 43
46 44 this.$el_to_style = this.$checkbox; // Set default element to style
47 45 this.update(); // Set defaults.
48 46 },
49 47
50 update : function(){
48 update : function(options){
51 49 // Update the contents of this view
52 50 //
53 51 // Called when the model is changed. The model may have been
54 52 // changed by another view or by a state update from the back-end.
55 if (!this.user_invoked_update) {
53 if (options === undefined || options.updated_view != this) {
56 54 this.$checkbox.prop('checked', this.model.get('value'));
57 55
58 56 var disabled = this.model.get('disabled');
59 57 this.$checkbox.prop('disabled', disabled);
60 58
61 59 var description = this.model.get('description');
62 60 if (description.length === 0) {
63 61 this.$label.hide();
64 62 } else {
65 63 this.$label.html(description);
66 64 this.$label.show();
67 65 }
68 66 }
69 67 return IPython.DOMWidgetView.prototype.update.call(this);
70 68 },
71 69
72 70 });
73 71
74 72 widget_manager.register_widget_view('CheckboxView', CheckboxView);
75 73
76 74 var ToggleButtonView = IPython.DOMWidgetView.extend({
77 75
78 76 // Called when view is rendered.
79 77 render : function(){
80 78 this.$el
81 79 .html('');
82 80 this.$button = $('<button />')
83 81 .addClass('btn')
84 82 .attr('type', 'button')
85 83 .attr('data-toggle', 'button')
86 84 .appendTo(this.$el);
87 85 this.$el_to_style = this.$button; // Set default element to style
88 86
89 87 this.update(); // Set defaults.
90 88 },
91 89
92 update : function(){
90 update : function(options){
93 91 // Update the contents of this view
94 92 //
95 93 // Called when the model is changed. The model may have been
96 94 // changed by another view or by a state update from the back-end.
97 if (!this.user_invoked_update) {
95 if (options === undefined || options.updated_view != this) {
98 96 if (this.model.get('value')) {
99 97 this.$button.addClass('active');
100 98 } else {
101 99 this.$button.removeClass('active');
102 100 }
103 101
104 102 var disabled = this.model.get('disabled');
105 103 this.$button.prop('disabled', disabled);
106 104
107 105 var description = this.model.get('description');
108 106 if (description.length === 0) {
109 107 this.$button.html(' '); // Preserve button height
110 108 } else {
111 109 this.$button.html(description);
112 110 }
113 111 }
114 112 return IPython.DOMWidgetView.prototype.update.call(this);
115 113 },
116 114
117 115 events: {"click button" : "handleClick"},
118 116
119 117 // Handles and validates user input.
120 118 handleClick: function(e) {
121 this.user_invoked_update = true;
122 119
123 120 // Calling model.set will trigger all of the other views of the
124 121 // model to update.
125 this.model.set('value', ! $(e.target).hasClass('active'));
122 this.model.set('value', ! $(e.target).hasClass('active'), {updated_view: this});
126 123 this.touch();
127 this.user_invoked_update = false;
128 124 },
129 125 });
130 126
131 127 widget_manager.register_widget_view('ToggleButtonView', ToggleButtonView);
132 128
133 129 });
@@ -1,269 +1,271 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2013 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // FloatRangeWidget
10 10 //============================================================================
11 11
12 12 /**
13 13 * @module IPython
14 14 * @namespace IPython
15 15 **/
16 16
17 17 define(["notebook/js/widgets/widget"], function(widget_manager){
18 18 var FloatRangeWidgetModel = IPython.WidgetModel.extend({});
19 19 widget_manager.register_widget_model('FloatRangeWidgetModel', FloatRangeWidgetModel);
20 20
21 21 var FloatSliderView = IPython.DOMWidgetView.extend({
22 22
23 23 // Called when view is rendered.
24 24 render : function(){
25 25 this.$el
26 26 .addClass('widget-hbox-single')
27 27 .html('');
28 28 this.$label = $('<div />')
29 29 .appendTo(this.$el)
30 30 .addClass('widget-hlabel')
31 31 .hide();
32 32 this.$slider = $('<div />')
33 33 .slider({})
34 34 .addClass('slider');
35 35
36 36 // Put the slider in a container
37 37 this.$slider_container = $('<div />')
38 38 .addClass('widget-hslider')
39 39 .append(this.$slider);
40 40 this.$el_to_style = this.$slider_container; // Set default element to style
41 41 this.$el.append(this.$slider_container);
42 42
43 43 // Set defaults.
44 44 this.update();
45 45 },
46 46
47 update : function(){
47 update : function(options){
48 48 // Update the contents of this view
49 49 //
50 50 // Called when the model is changed. The model may have been
51 51 // changed by another view or by a state update from the back-end.
52 52
53 if (options === undefined || options.updated_view != this) {
53 54 // Slider related keys.
54 55 var _keys = ['step', 'max', 'min', 'disabled'];
55 56 for (var index in _keys) {
56 57 var key = _keys[index];
57 58 if (this.model.get(key) !== undefined) {
58 59 this.$slider.slider("option", key, this.model.get(key));
59 60 }
60 61 }
61 62
62 63 // WORKAROUND FOR JQUERY SLIDER BUG.
63 64 // The horizontal position of the slider handle
64 65 // depends on the value of the slider at the time
65 66 // of orientation change. Before applying the new
66 67 // workaround, we set the value to the minimum to
67 68 // make sure that the horizontal placement of the
68 69 // handle in the vertical slider is always
69 70 // consistent.
70 71 var orientation = this.model.get('orientation');
71 72 var value = this.model.get('min');
72 73 this.$slider.slider('option', 'value', value);
73 74 this.$slider.slider('option', 'orientation', orientation);
74 75 value = this.model.get('value');
75 76 this.$slider.slider('option', 'value', value);
76 77
77 78 // Use the right CSS classes for vertical & horizontal sliders
78 79 if (orientation=='vertical') {
79 80 this.$slider_container
80 81 .removeClass('widget-hslider')
81 82 .addClass('widget-vslider');
82 83 this.$el
83 84 .removeClass('widget-hbox-single')
84 85 .addClass('widget-vbox-single');
85 86 this.$label
86 87 .removeClass('widget-hlabel')
87 88 .addClass('widget-vlabel');
88 89
89 90 } else {
90 91 this.$slider_container
91 92 .removeClass('widget-vslider')
92 93 .addClass('widget-hslider');
93 94 this.$el
94 95 .removeClass('widget-vbox-single')
95 96 .addClass('widget-hbox-single');
96 97 this.$label
97 98 .removeClass('widget-vlabel')
98 99 .addClass('widget-hlabel');
99 100 }
100 101
101 102 var description = this.model.get('description');
102 103 if (description.length === 0) {
103 104 this.$label.hide();
104 105 } else {
105 106 this.$label.html(description);
106 107 this.$label.show();
107 108 }
109 }
108 110 return IPython.DOMWidgetView.prototype.update.call(this);
109 111 },
110 112
111 113 // Handles: User input
112 114 events: { "slide" : "handleSliderChange" },
113 115 handleSliderChange: function(e, ui) {
114 116
115 117 // Calling model.set will trigger all of the other views of the
116 118 // model to update.
117 this.model.set('value', ui.value);
119 this.model.set('value', ui.value, {updated_view: this});
118 120 this.touch();
119 121 },
120 122 });
121 123
122 124 widget_manager.register_widget_view('FloatSliderView', FloatSliderView);
123 125
124 126
125 127 var FloatTextView = IPython.DOMWidgetView.extend({
126 128
127 129 // Called when view is rendered.
128 130 render : function(){
129 131 this.$el
130 132 .addClass('widget-hbox-single')
131 133 .html('');
132 134 this.$label = $('<div />')
133 135 .appendTo(this.$el)
134 136 .addClass('widget-hlabel')
135 137 .hide();
136 138 this.$textbox = $('<input type="text" />')
137 139 .addClass('input')
138 140 .addClass('widget-numeric-text')
139 141 .appendTo(this.$el);
140 142 this.$el_to_style = this.$textbox; // Set default element to style
141 143 this.update(); // Set defaults.
142 144 },
143 145
144 update : function(){
146 update : function(options){
145 147 // Update the contents of this view
146 148 //
147 149 // Called when the model is changed. The model may have been
148 150 // changed by another view or by a state update from the back-end.
149 151
152 if (options === undefined || options.updated_view != this) {
150 153 var value = this.model.get('value');
151 if (!this.changing && parseFloat(this.$textbox.val()) != value) {
154 if (parseFloat(this.$textbox.val()) != value) {
152 155 this.$textbox.val(value);
153 156 }
154 157
155 158 if (this.model.get('disabled')) {
156 159 this.$textbox.attr('disabled','disabled');
157 160 } else {
158 161 this.$textbox.removeAttr('disabled');
159 162 }
160 163
161 164 var description = this.model.get('description');
162 165 if (description.length === 0) {
163 166 this.$label.hide();
164 167 } else {
165 168 this.$label.html(description);
166 169 this.$label.show();
167 170 }
171 }
168 172 return IPython.DOMWidgetView.prototype.update.call(this);
169 173 },
170 174
171 175
172 176 events: {"keyup input" : "handleChanging",
173 177 "paste input" : "handleChanging",
174 178 "cut input" : "handleChanging",
175 179 "change input" : "handleChanged"}, // Fires only when control is validated or looses focus.
176 180
177 181 // Handles and validates user input.
178 182 handleChanging: function(e) {
179 183
180 184 // Try to parse value as a float.
181 185 var numericalValue = 0.0;
182 186 if (e.target.value !== '') {
183 187 numericalValue = parseFloat(e.target.value);
184 188 }
185 189
186 190 // If parse failed, reset value to value stored in model.
187 191 if (isNaN(numericalValue)) {
188 192 e.target.value = this.model.get('value');
189 193 } else if (!isNaN(numericalValue)) {
190 194 if (this.model.get('max') !== undefined) {
191 195 numericalValue = Math.min(this.model.get('max'), numericalValue);
192 196 }
193 197 if (this.model.get('min') !== undefined) {
194 198 numericalValue = Math.max(this.model.get('min'), numericalValue);
195 199 }
196 200
197 201 // Apply the value if it has changed.
198 202 if (numericalValue != this.model.get('value')) {
199 this.changing = true;
200 203
201 204 // Calling model.set will trigger all of the other views of the
202 205 // model to update.
203 this.model.set('value', numericalValue);
206 this.model.set('value', numericalValue, {updated_view: this});
204 207 this.touch();
205 this.changing = false;
206 208 }
207 209 }
208 210 },
209 211
210 212 // Applies validated input.
211 213 handleChanged: function(e) {
212 214 // Update the textbox
213 215 if (this.model.get('value') != e.target.value) {
214 216 e.target.value = this.model.get('value');
215 217 }
216 218 }
217 219 });
218 220
219 221 widget_manager.register_widget_view('FloatTextView', FloatTextView);
220 222
221 223
222 224 var ProgressView = IPython.DOMWidgetView.extend({
223 225
224 226 // Called when view is rendered.
225 227 render : function(){
226 228 this.$el
227 229 .addClass('widget-hbox-single')
228 230 .html('');
229 231 this.$label = $('<div />')
230 232 .appendTo(this.$el)
231 233 .addClass('widget-hlabel')
232 234 .hide();
233 235 this.$progress = $('<div />')
234 236 .addClass('progress')
235 237 .addClass('widget-progress')
236 238 .appendTo(this.$el);
237 239 this.$el_to_style = this.$progress; // Set default element to style
238 240 this.$bar = $('<div />')
239 241 .addClass('bar')
240 242 .css('width', '50%')
241 243 .appendTo(this.$progress);
242 244 this.update(); // Set defaults.
243 245 },
244 246
245 247 update : function(){
246 248 // Update the contents of this view
247 249 //
248 250 // Called when the model is changed. The model may have been
249 251 // changed by another view or by a state update from the back-end.
250 252 var value = this.model.get('value');
251 253 var max = this.model.get('max');
252 254 var min = this.model.get('min');
253 255 var percent = 100.0 * (value - min) / (max - min);
254 256 this.$bar.css('width', percent + '%');
255 257
256 258 var description = this.model.get('description');
257 259 if (description.length === 0) {
258 260 this.$label.hide();
259 261 } else {
260 262 this.$label.html(description);
261 263 this.$label.show();
262 264 }
263 265 return IPython.DOMWidgetView.prototype.update.call(this);
264 266 },
265 267
266 268 });
267 269
268 270 widget_manager.register_widget_view('ProgressView', ProgressView);
269 271 });
@@ -1,219 +1,219 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2013 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // IntRangeWidget
10 10 //============================================================================
11 11
12 12 /**
13 13 * @module IPython
14 14 * @namespace IPython
15 15 **/
16 16
17 17 define(["notebook/js/widgets/widget"], function(widget_manager){
18 18 var IntRangeWidgetModel = IPython.WidgetModel.extend({});
19 19 widget_manager.register_widget_model('IntRangeWidgetModel', IntRangeWidgetModel);
20 20
21 21 var IntSliderView = IPython.DOMWidgetView.extend({
22 22
23 23 // Called when view is rendered.
24 24 render : function(){
25 25 this.$el
26 26 .addClass('widget-hbox-single')
27 27 .html('');
28 28 this.$label = $('<div />')
29 29 .appendTo(this.$el)
30 30 .addClass('widget-hlabel')
31 31 .hide();
32 32 this.$slider = $('<div />')
33 33 .slider({})
34 34 .addClass('slider');
35 35
36 36 // Put the slider in a container
37 37 this.$slider_container = $('<div />')
38 38 .addClass('widget-hslider')
39 39 .append(this.$slider);
40 40 this.$el_to_style = this.$slider_container; // Set default element to style
41 41 this.$el.append(this.$slider_container);
42 42
43 43 // Set defaults.
44 44 this.update();
45 45 },
46 46
47 update : function(){
47 update : function(options){
48 48 // Update the contents of this view
49 49 //
50 50 // Called when the model is changed. The model may have been
51 51 // changed by another view or by a state update from the back-end.
52
52 if (options === undefined || options.updated_view != this) {
53 53 // Slider related keys.
54 54 var _keys = ['step', 'max', 'min', 'disabled'];
55 55 for (var index in _keys) {
56 56 var key = _keys[index];
57 57 if (this.model.get(key) !== undefined) {
58 58 this.$slider.slider("option", key, this.model.get(key));
59 59 }
60 60 }
61 61
62 62 // WORKAROUND FOR JQUERY SLIDER BUG.
63 63 // The horizontal position of the slider handle
64 64 // depends on the value of the slider at the time
65 65 // of orientation change. Before applying the new
66 66 // workaround, we set the value to the minimum to
67 67 // make sure that the horizontal placement of the
68 68 // handle in the vertical slider is always
69 69 // consistent.
70 70 var orientation = this.model.get('orientation');
71 71 var value = this.model.get('min');
72 72 this.$slider.slider('option', 'value', value);
73 73 this.$slider.slider('option', 'orientation', orientation);
74 74 value = this.model.get('value');
75 75 this.$slider.slider('option', 'value', value);
76 76
77 77 // Use the right CSS classes for vertical & horizontal sliders
78 78 if (orientation=='vertical') {
79 79 this.$slider_container
80 80 .removeClass('widget-hslider')
81 81 .addClass('widget-vslider');
82 82 this.$el
83 83 .removeClass('widget-hbox-single')
84 84 .addClass('widget-vbox-single');
85 85 this.$label
86 86 .removeClass('widget-hlabel')
87 87 .addClass('widget-vlabel');
88 88
89 89 } else {
90 90 this.$slider_container
91 91 .removeClass('widget-vslider')
92 92 .addClass('widget-hslider');
93 93 this.$el
94 94 .removeClass('widget-vbox-single')
95 95 .addClass('widget-hbox-single');
96 96 this.$label
97 97 .removeClass('widget-vlabel')
98 98 .addClass('widget-hlabel');
99 99 }
100 100
101 101 var description = this.model.get('description');
102 102 if (description.length === 0) {
103 103 this.$label.hide();
104 104 } else {
105 105 this.$label.html(description);
106 106 this.$label.show();
107 107 }
108 }
108 109 return IPython.DOMWidgetView.prototype.update.call(this);
109 110 },
110 111
111 112 // Handles: User input
112 113 events: { "slide" : "handleSliderChange" },
113 114 handleSliderChange: function(e, ui) {
114 115
115 116 // Calling model.set will trigger all of the other views of the
116 117 // model to update.
117 this.model.set('value', ~~ui.value); // Double bit-wise not to truncate decimel
118 this.model.set('value', ~~ui.value, {updated_view: this}); // Double bit-wise not to truncate decimel
118 119 this.touch();
119 120 },
120 121 });
121 122
122 123 widget_manager.register_widget_view('IntSliderView', IntSliderView);
123 124
124 125 var IntTextView = IPython.DOMWidgetView.extend({
125 126
126 127 // Called when view is rendered.
127 128 render : function(){
128 129 this.$el
129 130 .addClass('widget-hbox-single')
130 131 .html('');
131 132 this.$label = $('<div />')
132 133 .appendTo(this.$el)
133 134 .addClass('widget-hlabel')
134 135 .hide();
135 136 this.$textbox = $('<input type="text" />')
136 137 .addClass('input')
137 138 .addClass('widget-numeric-text')
138 139 .appendTo(this.$el);
139 140 this.$el_to_style = this.$textbox; // Set default element to style
140 141 this.update(); // Set defaults.
141 142 },
142 143
143 update : function(){
144 update : function(options){
144 145 // Update the contents of this view
145 146 //
146 147 // Called when the model is changed. The model may have been
147 148 // changed by another view or by a state update from the back-end.
148
149 if (options === undefined || options.updated_view != this) {
149 150 var value = this.model.get('value');
150 if (!this.changing && parseInt(this.$textbox.val()) != value) {
151 if (parseInt(this.$textbox.val()) != value) {
151 152 this.$textbox.val(value);
152 153 }
153 154
154 155 if (this.model.get('disabled')) {
155 156 this.$textbox.attr('disabled','disabled');
156 157 } else {
157 158 this.$textbox.removeAttr('disabled');
158 159 }
159 160
160 161 var description = this.model.get('description');
161 162 if (description.length === 0) {
162 163 this.$label.hide();
163 164 } else {
164 165 this.$label.html(description);
165 166 this.$label.show();
166 167 }
168 }
167 169 return IPython.DOMWidgetView.prototype.update.call(this);
168 170 },
169 171
170 172
171 173 events: {"keyup input" : "handleChanging",
172 174 "paste input" : "handleChanging",
173 175 "cut input" : "handleChanging",
174 176 "change input" : "handleChanged"}, // Fires only when control is validated or looses focus.
175 177
176 178 // Handles and validates user input.
177 179 handleChanging: function(e) {
178 180
179 181 // Try to parse value as a float.
180 182 var numericalValue = 0;
181 183 if (e.target.value !== '') {
182 184 numericalValue = parseInt(e.target.value);
183 185 }
184 186
185 187 // If parse failed, reset value to value stored in model.
186 188 if (isNaN(numericalValue)) {
187 189 e.target.value = this.model.get('value');
188 190 } else if (!isNaN(numericalValue)) {
189 191 if (this.model.get('max') !== undefined) {
190 192 numericalValue = Math.min(this.model.get('max'), numericalValue);
191 193 }
192 194 if (this.model.get('min') !== undefined) {
193 195 numericalValue = Math.max(this.model.get('min'), numericalValue);
194 196 }
195 197
196 198 // Apply the value if it has changed.
197 199 if (numericalValue != this.model.get('value')) {
198 this.changing = true;
199 200
200 201 // Calling model.set will trigger all of the other views of the
201 202 // model to update.
202 this.model.set('value', numericalValue);
203 this.model.set('value', numericalValue, {updated_view: this});
203 204 this.touch();
204 this.changing = false;
205 205 }
206 206 }
207 207 },
208 208
209 209 // Applies validated input.
210 210 handleChanged: function(e) {
211 211 // Update the textbox
212 212 if (this.model.get('value') != e.target.value) {
213 213 e.target.value = this.model.get('value');
214 214 }
215 215 }
216 216 });
217 217
218 218 widget_manager.register_widget_view('IntTextView', IntTextView);
219 219 });
@@ -1,224 +1,225 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2013 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // MultiContainerWidget
10 10 //============================================================================
11 11
12 12 /**
13 13 * @module IPython
14 14 * @namespace IPython
15 15 **/
16 16
17 17 define(["notebook/js/widgets/widget"], function(widget_manager){
18 18 var MulticontainerModel = IPython.WidgetModel.extend({});
19 19 widget_manager.register_widget_model('MulticontainerWidgetModel', MulticontainerModel);
20 20
21 21 var AccordionView = IPython.DOMWidgetView.extend({
22 22
23 23 render: function(){
24 24 var guid = 'accordion' + IPython.utils.uuid();
25 25 this.$el
26 26 .attr('id', guid)
27 27 .addClass('accordion');
28 28 this.containers = [];
29 29 this.update_children([], this.model.get('children'));
30 30 this.model.on('change:children', function(model, value, options) {
31 31 this.update_children(model.previous('children'), value);
32 32 }, this);
33 33 },
34 34
35 35 update_children: function(old_list, new_list) {
36 36 _.each(this.containers, function(element, index, list) {
37 37 element.remove();
38 38 }, this);
39 39 this.containers = [];
40 40 this.update_child_views(old_list, new_list);
41 41 _.each(new_list, function(element, index, list) {
42 42 this.add_child_view(this.child_views[element]);
43 43 }, this)
44 44 },
45 45
46 46
47 update: function() {
47 update: function(options) {
48 48 // Update the contents of this view
49 49 //
50 50 // Called when the model is changed. The model may have been
51 51 // changed by another view or by a state update from the back-end.
52 52
53 if (options === undefined || options.updated_view != this) {
53 54 // Set tab titles
54 55 var titles = this.model.get('_titles');
55 56 for (var page_index in titles) {
56 57
57 58 var accordian = this.containers[page_index];
58 59 if (accordian !== undefined) {
59 60 accordian
60 61 .find('.accordion-heading')
61 62 .find('.accordion-toggle')
62 63 .html(titles[page_index]);
63 64 }
64 65 }
65 66
66 67 // Set selected page
67 68 var selected_index = this.model.get("selected_index");
68 69 if (0 <= selected_index && selected_index < this.containers.length) {
69 70 for (var index in this.containers) {
70 71 if (index==selected_index) {
71 72 this.containers[index].find('.accordion-body').collapse('show');
72 73 } else {
73 74 this.containers[index].find('.accordion-body').collapse('hide');
74 75 }
75 76
76 77 }
77 78 }
78
79 }
79 80 return IPython.DOMWidgetView.prototype.update.call(this);
80 81 },
81 82
82 83 add_child_view: function(view) {
83 84
84 85 var index = this.containers.length;
85 86 var uuid = IPython.utils.uuid();
86 87 var accordion_group = $('<div />')
87 88 .addClass('accordion-group')
88 89 .appendTo(this.$el);
89 90 var accordion_heading = $('<div />')
90 91 .addClass('accordion-heading')
91 92 .appendTo(accordion_group);
92 93 var that = this;
93 94 var accordion_toggle = $('<a />')
94 95 .addClass('accordion-toggle')
95 96 .attr('data-toggle', 'collapse')
96 97 .attr('data-parent', '#' + this.$el.attr('id'))
97 98 .attr('href', '#' + uuid)
98 99 .click(function(evt){
99 100
100 101 // Calling model.set will trigger all of the other views of the
101 102 // model to update.
102 that.model.set("selected_index", index);
103 that.model.set("selected_index", index, {updated_view: this});
103 104 that.touch();
104 105 })
105 106 .html('Page ' + index)
106 107 .appendTo(accordion_heading);
107 108 var accordion_body = $('<div />', {id: uuid})
108 109 .addClass('accordion-body collapse')
109 110 .appendTo(accordion_group);
110 111 var accordion_inner = $('<div />')
111 112 .addClass('accordion-inner')
112 113 .appendTo(accordion_body);
113 114 this.containers.push(accordion_group);
114 115 accordion_inner.append(view.$el);
115 116
116 117 this.update();
117 118
118 119 // Stupid workaround to close the bootstrap accordion tabs which
119 120 // open by default even though they don't have the `in` class
120 121 // attached to them. For some reason a delay is required.
121 122 // TODO: Better fix.
122 123 setTimeout(function(){ that.update(); }, 500);
123 124 },
124 125 });
125 126
126 127 widget_manager.register_widget_view('AccordionView', AccordionView);
127 128
128 129 var TabView = IPython.DOMWidgetView.extend({
129 130
130 131 initialize: function() {
131 132 this.containers = [];
132 133 IPython.DOMWidgetView.prototype.initialize.apply(this, arguments);
133 134 },
134 135
135 136 render: function(){
136 137 var uuid = 'tabs'+IPython.utils.uuid();
137 138 var that = this;
138 139 this.$tabs = $('<div />', {id: uuid})
139 140 .addClass('nav')
140 141 .addClass('nav-tabs')
141 142 .appendTo(this.$el);
142 143 this.$tab_contents = $('<div />', {id: uuid + 'Content'})
143 144 .addClass('tab-content')
144 145 .appendTo(this.$el);
145 146 this.containers = [];
146 147 this.update_children([], this.model.get('children'));
147 148 this.model.on('change:children', function(model, value, options) {
148 149 this.update_children(model.previous('children'), value);
149 150 }, this);
150 151 },
151 152
152 153 update_children: function(old_list, new_list) {
153 154 _.each(this.containers, function(element, index, list) {
154 155 element.remove();
155 156 }, this);
156 157 this.containers = [];
157 158 this.update_child_views(old_list, new_list);
158 159 _.each(new_list, function(element, index, list) {
159 160 this.add_child_view(this.child_views[element]);
160 161 }, this)
161 162 },
162 163
163 update: function() {
164 update: function(options) {
164 165 // Update the contents of this view
165 166 //
166 167 // Called when the model is changed. The model may have been
167 168 // changed by another view or by a state update from the back-end.
168
169 if (options === undefined || options.updated_view != this) {
169 170 // Set tab titles
170 171 var titles = this.model.get('_titles');
171 172 for (var page_index in titles) {
172 173 var tab_text = this.containers[page_index];
173 174 if (tab_text !== undefined) {
174 175 tab_text.html(titles[page_index]);
175 176 }
176 177 }
177 178
178 179 var selected_index = this.model.get('selected_index');
179 180 if (0 <= selected_index && selected_index < this.containers.length) {
180 181 this.select_page(selected_index);
181 182 }
182
183 }
183 184 return IPython.DOMWidgetView.prototype.update.call(this);
184 185 },
185 186
186 187 add_child_view: function(view) {
187 188 var index = this.containers.length;
188 189 var uuid = IPython.utils.uuid();
189 190
190 191 var that = this;
191 192 var tab = $('<li />')
192 193 .css('list-style-type', 'none')
193 194 .appendTo(this.$tabs);
194 195 var tab_text = $('<a />')
195 196 .attr('href', '#' + uuid)
196 197 .attr('data-toggle', 'tab')
197 198 .html('Page ' + index)
198 199 .appendTo(tab)
199 200 .click(function (e) {
200 201
201 202 // Calling model.set will trigger all of the other views of the
202 203 // model to update.
203 that.model.set("selected_index", index);
204 that.model.set("selected_index", index, {updated_view: this});
204 205 that.touch();
205 206 that.select_page(index);
206 207 });
207 208 this.containers.push(tab_text);
208 209
209 210 var contents_div = $('<div />', {id: uuid})
210 211 .addClass('tab-pane')
211 212 .addClass('fade')
212 213 .append(view.$el)
213 214 .appendTo(this.$tab_contents);
214 215 },
215 216
216 217 select_page: function(index) {
217 218 this.$tabs.find('li')
218 219 .removeClass('active');
219 220 this.containers[index].tab('show');
220 221 },
221 222 });
222 223
223 224 widget_manager.register_widget_view('TabView', TabView);
224 225 });
@@ -1,380 +1,385 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2013 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // SelectionWidget
10 10 //============================================================================
11 11
12 12 /**
13 13 * @module IPython
14 14 * @namespace IPython
15 15 **/
16 16
17 17 define(["notebook/js/widgets/widget"], function(widget_manager){
18 18 var SelectionWidgetModel = IPython.WidgetModel.extend({});
19 19 widget_manager.register_widget_model('SelectionWidgetModel', SelectionWidgetModel);
20 20
21 21 var DropdownView = IPython.DOMWidgetView.extend({
22 22
23 23 // Called when view is rendered.
24 24 render : function(){
25 25
26 26 this.$el
27 27 .addClass('widget-hbox-single')
28 28 .html('');
29 29 this.$label = $('<div />')
30 30 .appendTo(this.$el)
31 31 .addClass('widget-hlabel')
32 32 .hide();
33 33 this.$buttongroup = $('<div />')
34 34 .addClass('widget_item')
35 35 .addClass('btn-group')
36 36 .appendTo(this.$el);
37 37 this.$el_to_style = this.$buttongroup; // Set default element to style
38 38 this.$droplabel = $('<button />')
39 39 .addClass('btn')
40 40 .addClass('widget-combo-btn')
41 41 .html('&nbsp;')
42 42 .appendTo(this.$buttongroup);
43 43 this.$dropbutton = $('<button />')
44 44 .addClass('btn')
45 45 .addClass('dropdown-toggle')
46 46 .addClass('widget-combo-carrot-btn')
47 47 .attr('data-toggle', 'dropdown')
48 48 .html('<span class="caret"></span>')
49 49 .appendTo(this.$buttongroup);
50 50 this.$droplist = $('<ul />')
51 51 .addClass('dropdown-menu')
52 52 .appendTo(this.$buttongroup);
53 53
54 54 // Set defaults.
55 55 this.update();
56 56 },
57 57
58 update : function(){
58 update : function(options){
59 59 // Update the contents of this view
60 60 //
61 61 // Called when the model is changed. The model may have been
62 62 // changed by another view or by a state update from the back-end.
63 63
64 if (options === undefined || options.updated_view != this) {
64 65 var selected_item_text = this.model.get('value');
65 66 selected_item_text = selected_item_text.replace(/ /g, '&nbsp;');
66 67 selected_item_text = selected_item_text.replace(/\n/g, '<br>\n');
67 68 if (selected_item_text.length === 0) {
68 69 this.$droplabel.html('&nbsp;');
69 70 } else {
70 71 this.$droplabel.html(selected_item_text);
71 72 }
72 73
73 74 var items = this.model.get('values');
74 75 this.$droplist.html('');
75 76 for (var index in items) {
76 77 var that = this;
77 78 var item_button = $('<a href="#"/>')
78 79 .html(items[index])
79 80 .on('click', $.proxy(this.handle_click, this));
80 81 this.$droplist.append($('<li />').append(item_button));
81 82 }
82 83
83 84 if (this.model.get('disabled')) {
84 85 this.$buttongroup.attr('disabled','disabled');
85 86 this.$droplabel.attr('disabled','disabled');
86 87 this.$dropbutton.attr('disabled','disabled');
87 88 this.$droplist.attr('disabled','disabled');
88 89 } else {
89 90 this.$buttongroup.removeAttr('disabled');
90 91 this.$droplabel.removeAttr('disabled');
91 92 this.$dropbutton.removeAttr('disabled');
92 93 this.$droplist.removeAttr('disabled');
93 94 }
94 95
95 96 var description = this.model.get('description');
96 97 if (description.length === 0) {
97 98 this.$label.hide();
98 99 } else {
99 100 this.$label.html(description);
100 101 this.$label.show();
101 102 }
103 }
102 104 return IPython.DOMWidgetView.prototype.update.call(this);
103 105 },
104 106
105 107 // Handle when a value is clicked.
106 108 handle_click: function (e) {
107 109
108 110 // Calling model.set will trigger all of the other views of the
109 111 // model to update.
110 this.model.set('value', $(e.target).html(), this);
112 this.model.set('value', $(e.target).html(), {updated_view: this});
111 113 this.touch();
112 114 },
113 115
114 116 });
115 117
116 118 widget_manager.register_widget_view('DropdownView', DropdownView);
117 119
118 120 var RadioButtonsView = IPython.DOMWidgetView.extend({
119 121
120 122 // Called when view is rendered.
121 123 render : function(){
122 124 this.$el
123 125 .addClass('widget-hbox')
124 126 .html('');
125 127 this.$label = $('<div />')
126 128 .appendTo(this.$el)
127 129 .addClass('widget-hlabel')
128 130 .hide();
129 131 this.$container = $('<div />')
130 132 .appendTo(this.$el)
131 133 .addClass('widget-container')
132 134 .addClass('vbox');
133 135 this.$el_to_style = this.$container; // Set default element to style
134 136 this.update();
135 137 },
136 138
137 update : function(){
139 update : function(options){
138 140 // Update the contents of this view
139 141 //
140 142 // Called when the model is changed. The model may have been
141 143 // changed by another view or by a state update from the back-end.
142
144 if (options === undefined || options.updated_view != this) {
143 145 // Add missing items to the DOM.
144 146 var items = this.model.get('values');
145 147 var disabled = this.model.get('disabled');
146 148 for (var index in items) {
147 149 var item_query = ' :input[value="' + items[index] + '"]';
148 150 if (this.$el.find(item_query).length === 0) {
149 151 var $label = $('<label />')
150 152 .addClass('radio')
151 153 .html(items[index])
152 154 .appendTo(this.$container);
153 155
154 156 $('<input />')
155 157 .attr('type', 'radio')
156 158 .addClass(this.model)
157 159 .val(items[index])
158 160 .prependTo($label)
159 161 .on('click', $.proxy(this.handle_click, this));
160 162 }
161 163
162 164 var $item_element = this.$container.find(item_query);
163 165 if (this.model.get('value') == items[index]) {
164 166 $item_element.prop('checked', true);
165 167 } else {
166 168 $item_element.prop('checked', false);
167 169 }
168 170 $item_element.prop('disabled', disabled);
169 171 }
170 172
171 173 // Remove items that no longer exist.
172 174 this.$container.find('input').each(function(i, obj) {
173 175 var value = $(obj).val();
174 176 var found = false;
175 177 for (var index in items) {
176 178 if (items[index] == value) {
177 179 found = true;
178 180 break;
179 181 }
180 182 }
181 183
182 184 if (!found) {
183 185 $(obj).parent().remove();
184 186 }
185 187 });
186 188
187 189 var description = this.model.get('description');
188 190 if (description.length === 0) {
189 191 this.$label.hide();
190 192 } else {
191 193 this.$label.html(description);
192 194 this.$label.show();
193 195 }
196 }
194 197 return IPython.DOMWidgetView.prototype.update.call(this);
195 198 },
196 199
197 200 // Handle when a value is clicked.
198 201 handle_click: function (e) {
199 202
200 203 // Calling model.set will trigger all of the other views of the
201 204 // model to update.
202 this.model.set('value', $(e.target).val(), this);
205 this.model.set('value', $(e.target).val(), {updated_view: this});
203 206 this.touch();
204 207 },
205 208 });
206 209
207 210 widget_manager.register_widget_view('RadioButtonsView', RadioButtonsView);
208 211
209 212
210 213 var ToggleButtonsView = IPython.DOMWidgetView.extend({
211 214
212 215 // Called when view is rendered.
213 216 render : function(){
214 217 this.$el
215 218 .addClass('widget-hbox-single')
216 219 .html('');
217 220 this.$label = $('<div />')
218 221 .appendTo(this.$el)
219 222 .addClass('widget-hlabel')
220 223 .hide();
221 224 this.$buttongroup = $('<div />')
222 225 .addClass('btn-group')
223 226 .attr('data-toggle', 'buttons-radio')
224 227 .appendTo(this.$el);
225 228 this.$el_to_style = this.$buttongroup; // Set default element to style
226 229 this.update();
227 230 },
228 231
229 update : function(){
232 update : function(options){
230 233 // Update the contents of this view
231 234 //
232 235 // Called when the model is changed. The model may have been
233 236 // changed by another view or by a state update from the back-end.
234
237 if (options === undefined || options.updated_view != this) {
235 238 // Add missing items to the DOM.
236 239 var items = this.model.get('values');
237 240 var disabled = this.model.get('disabled');
238 241 for (var index in items) {
239 242 var item_query = ' :contains("' + items[index] + '")';
240 243 if (this.$buttongroup.find(item_query).length === 0) {
241 244 $('<button />')
242 245 .attr('type', 'button')
243 246 .addClass('btn')
244 247 .html(items[index])
245 248 .appendTo(this.$buttongroup)
246 249 .on('click', $.proxy(this.handle_click, this));
247 250 }
248 251
249 252 var $item_element = this.$buttongroup.find(item_query);
250 253 if (this.model.get('value') == items[index]) {
251 254 $item_element.addClass('active');
252 255 } else {
253 256 $item_element.removeClass('active');
254 257 }
255 258 $item_element.prop('disabled', disabled);
256 259 }
257 260
258 261 // Remove items that no longer exist.
259 262 this.$buttongroup.find('button').each(function(i, obj) {
260 263 var value = $(obj).html();
261 264 var found = false;
262 265 for (var index in items) {
263 266 if (items[index] == value) {
264 267 found = true;
265 268 break;
266 269 }
267 270 }
268 271
269 272 if (!found) {
270 273 $(obj).remove();
271 274 }
272 275 });
273 276
274 277 var description = this.model.get('description');
275 278 if (description.length === 0) {
276 279 this.$label.hide();
277 280 } else {
278 281 this.$label.html(description);
279 282 this.$label.show();
280 283 }
284 }
281 285 return IPython.DOMWidgetView.prototype.update.call(this);
282 286 },
283 287
284 288 // Handle when a value is clicked.
285 289 handle_click: function (e) {
286 290
287 291 // Calling model.set will trigger all of the other views of the
288 292 // model to update.
289 this.model.set('value', $(e.target).html(), this);
293 this.model.set('value', $(e.target).html(), {updated_view: this});
290 294 this.touch();
291 295 },
292 296
293 297 });
294 298
295 299 widget_manager.register_widget_view('ToggleButtonsView', ToggleButtonsView);
296 300
297 301 var ListBoxView = IPython.DOMWidgetView.extend({
298 302
299 303 // Called when view is rendered.
300 304 render : function(){
301 305 this.$el
302 306 .addClass('widget-hbox')
303 307 .html('');
304 308 this.$label = $('<div />')
305 309 .appendTo(this.$el)
306 310 .addClass('widget-hlabel')
307 311 .hide();
308 312 this.$listbox = $('<select />')
309 313 .addClass('widget-listbox')
310 314 .attr('size', 6)
311 315 .appendTo(this.$el);
312 316 this.$el_to_style = this.$listbox; // Set default element to style
313 317 this.update();
314 318 },
315 319
316 update : function(){
320 update : function(options){
317 321 // Update the contents of this view
318 322 //
319 323 // Called when the model is changed. The model may have been
320 324 // changed by another view or by a state update from the back-end.
321
325 if (options === undefined || options.updated_view != this) {
322 326 // Add missing items to the DOM.
323 327 var items = this.model.get('values');
324 328 for (var index in items) {
325 329 var item_query = ' :contains("' + items[index] + '")';
326 330 if (this.$listbox.find(item_query).length === 0) {
327 331 $('<option />')
328 332 .html(items[index])
329 333 .attr('value', items[index])
330 334 .appendTo(this.$listbox)
331 335 .on('click', $.proxy(this.handle_click, this));
332 336 }
333 337 }
334 338
335 339 // Select the correct element
336 340 this.$listbox.val(this.model.get('value'));
337 341
338 342 // Disable listbox if needed
339 343 var disabled = this.model.get('disabled');
340 344 this.$listbox.prop('disabled', disabled);
341 345
342 346 // Remove items that no longer exist.
343 347 this.$listbox.find('option').each(function(i, obj) {
344 348 var value = $(obj).html();
345 349 var found = false;
346 350 for (var index in items) {
347 351 if (items[index] == value) {
348 352 found = true;
349 353 break;
350 354 }
351 355 }
352 356
353 357 if (!found) {
354 358 $(obj).remove();
355 359 }
356 360 });
357 361
358 362 var description = this.model.get('description');
359 363 if (description.length === 0) {
360 364 this.$label.hide();
361 365 } else {
362 366 this.$label.html(description);
363 367 this.$label.show();
364 368 }
369 }
365 370 return IPython.DOMWidgetView.prototype.update.call(this);
366 371 },
367 372
368 373 // Handle when a value is clicked.
369 374 handle_click: function (e) {
370 375
371 376 // Calling model.set will trigger all of the other views of the
372 377 // model to update.
373 this.model.set('value', $(e.target).html(), this);
378 this.model.set('value', $(e.target).html(), {updated_view: this});
374 379 this.touch();
375 380 },
376 381
377 382 });
378 383
379 384 widget_manager.register_widget_view('ListBoxView', ListBoxView);
380 385 });
@@ -1,202 +1,202 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2013 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // StringWidget
10 10 //============================================================================
11 11
12 12 /**
13 13 * @module IPython
14 14 * @namespace IPython
15 15 **/
16 16
17 17 define(["notebook/js/widgets/widget"], function(widget_manager){
18 18 var StringWidgetModel = IPython.WidgetModel.extend({});
19 19 widget_manager.register_widget_model('StringWidgetModel', StringWidgetModel);
20 20
21 21 var HTMLView = IPython.DOMWidgetView.extend({
22 22
23 23 // Called when view is rendered.
24 24 render : function(){
25 25 this.update(); // Set defaults.
26 26 },
27 27
28 28 update : function(){
29 29 // Update the contents of this view
30 30 //
31 31 // Called when the model is changed. The model may have been
32 32 // changed by another view or by a state update from the back-end.
33 33 this.$el.html(this.model.get('value'));
34 34 return IPython.DOMWidgetView.prototype.update.call(this);
35 35 },
36 36
37 37 });
38 38
39 39 widget_manager.register_widget_view('HTMLView', HTMLView);
40 40
41 41
42 42 var LatexView = IPython.DOMWidgetView.extend({
43 43
44 44 // Called when view is rendered.
45 45 render : function(){
46 46 this.update(); // Set defaults.
47 47 },
48 48
49 49 update : function(){
50 50 // Update the contents of this view
51 51 //
52 52 // Called when the model is changed. The model may have been
53 53 // changed by another view or by a state update from the back-end.
54 54 this.$el.html(this.model.get('value'));
55 55 MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$el.get(0)]);
56 56
57 57 return IPython.DOMWidgetView.prototype.update.call(this);
58 58 },
59 59
60 60 });
61 61
62 62 widget_manager.register_widget_view('LatexView', LatexView);
63 63
64 64 var TextAreaView = IPython.DOMWidgetView.extend({
65 65
66 66 // Called when view is rendered.
67 67 render: function(){
68 68 this.$el
69 69 .addClass('widget-hbox')
70 70 .html('');
71 71 this.$label = $('<div />')
72 72 .appendTo(this.$el)
73 73 .addClass('widget-hlabel')
74 74 .hide();
75 75 this.$textbox = $('<textarea />')
76 76 .attr('rows', 5)
77 77 .addClass('widget-text')
78 78 .appendTo(this.$el);
79 79 this.$el_to_style = this.$textbox; // Set default element to style
80 80 this.update(); // Set defaults.
81 81
82 82 this.model.on('msg:custom', $.proxy(this._handle_textarea_msg, this));
83 83 },
84 84
85 85
86 86 _handle_textarea_msg: function (content){
87 87 if (content.method == "scroll_to_bottom") {
88 88 this.scroll_to_bottom();
89 89 }
90 90 },
91 91
92 92
93 93 scroll_to_bottom: function (){
94 94 this.$textbox.scrollTop(this.$textbox[0].scrollHeight);
95 95 },
96 96
97 97
98 update: function(){
98 update: function(options){
99 99 // Update the contents of this view
100 100 //
101 101 // Called when the model is changed. The model may have been
102 102 // changed by another view or by a state update from the back-end.
103 if (!this.user_invoked_update) {
103 if (options === undefined || options.updated_view != this) {
104 104 this.$textbox.val(this.model.get('value'));
105 }
106 105
107 106 var disabled = this.model.get('disabled');
108 107 this.$textbox.prop('disabled', disabled);
109 108
110 109 var description = this.model.get('description');
111 110 if (description.length === 0) {
112 111 this.$label.hide();
113 112 } else {
114 113 this.$label.html(description);
115 114 this.$label.show();
116 115 }
116 }
117 117 return IPython.DOMWidgetView.prototype.update.call(this);
118 118 },
119 119
120 120 events: {"keyup textarea": "handleChanging",
121 121 "paste textarea": "handleChanging",
122 122 "cut textarea": "handleChanging"},
123 123
124 124 // Handles and validates user input.
125 125 handleChanging: function(e) {
126 this.user_invoked_update = true;
127 126
128 127 // Calling model.set will trigger all of the other views of the
129 128 // model to update.
130 this.model.set('value', e.target.value);
129 this.model.set('value', e.target.value, {updated_view: this});
131 130 this.touch();
132 this.user_invoked_update = false;
133 131 },
134 132 });
135 133
136 134 widget_manager.register_widget_view('TextAreaView', TextAreaView);
137 135
138 136 var TextBoxView = IPython.DOMWidgetView.extend({
139 137
140 138 // Called when view is rendered.
141 139 render: function(){
142 140 this.$el
143 141 .addClass('widget-hbox-single')
144 142 .html('');
145 143 this.$label = $('<div />')
146 144 .addClass('widget-hlabel')
147 145 .appendTo(this.$el)
148 146 .hide();
149 147 this.$textbox = $('<input type="text" />')
150 148 .addClass('input')
151 149 .addClass('widget-text')
152 150 .appendTo(this.$el);
153 151 this.$el_to_style = this.$textbox; // Set default element to style
154 152 this.update(); // Set defaults.
155 153 },
156 154
157 update: function(){
155 update: function(options){
158 156 // Update the contents of this view
159 157 //
160 158 // Called when the model is changed. The model may have been
161 159 // changed by another view or by a state update from the back-end.
160 if (options === undefined || options.updated_view != this) {
162 161 if (this.$textbox.val() != this.model.get('value')) {
163 162 this.$textbox.val(this.model.get('value'));
164 163 }
165 164
166 165 var disabled = this.model.get('disabled');
167 166 this.$textbox.prop('disabled', disabled);
168 167
169 168 var description = this.model.get('description');
170 169 if (description.length === 0) {
171 170 this.$label.hide();
172 171 } else {
173 172 this.$label.html(description);
174 173 this.$label.show();
175 174 }
175 }
176 176 return IPython.DOMWidgetView.prototype.update.call(this);
177 177 },
178 178
179 179 events: {"keyup input": "handleChanging",
180 180 "paste input": "handleChanging",
181 181 "cut input": "handleChanging",
182 182 "keypress input": "handleKeypress"},
183 183
184 184 // Handles and validates user input.
185 185 handleChanging: function(e) {
186 186
187 187 // Calling model.set will trigger all of the other views of the
188 188 // model to update.
189 this.model.set('value', e.target.value);
189 this.model.set('value', e.target.value, {updated_view: this});
190 190 this.touch();
191 191 },
192 192
193 193 // Handles text submition
194 194 handleKeypress: function(e) {
195 195 if (e.keyCode == 13) { // Return key
196 196 this.send({event: 'submit'});
197 197 }
198 198 },
199 199 });
200 200
201 201 widget_manager.register_widget_view('TextBoxView', TextBoxView);
202 202 });
General Comments 0
You need to be logged in to leave comments. Login now