##// END OF EJS Templates
handle empty string in ToggleButtonsWidget
MinRK -
Show More
@@ -1,376 +1,382
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2013 The IPython Development Team
2 // Copyright (C) 2013 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // SelectionWidget
9 // SelectionWidget
10 //============================================================================
10 //============================================================================
11
11
12 /**
12 /**
13 * @module IPython
13 * @module IPython
14 * @namespace IPython
14 * @namespace IPython
15 **/
15 **/
16
16
17 define(["notebook/js/widgets/widget"], function(WidgetManager){
17 define(["notebook/js/widgets/widget"], function(WidgetManager){
18
18
19 var DropdownView = IPython.DOMWidgetView.extend({
19 var DropdownView = IPython.DOMWidgetView.extend({
20 render : function(){
20 render : function(){
21 // Called when view is rendered.
21 // Called when view is rendered.
22 this.$el
22 this.$el
23 .addClass('widget-hbox-single');
23 .addClass('widget-hbox-single');
24 this.$label = $('<div />')
24 this.$label = $('<div />')
25 .appendTo(this.$el)
25 .appendTo(this.$el)
26 .addClass('widget-hlabel')
26 .addClass('widget-hlabel')
27 .hide();
27 .hide();
28 this.$buttongroup = $('<div />')
28 this.$buttongroup = $('<div />')
29 .addClass('widget_item')
29 .addClass('widget_item')
30 .addClass('btn-group')
30 .addClass('btn-group')
31 .appendTo(this.$el);
31 .appendTo(this.$el);
32 this.$el_to_style = this.$buttongroup; // Set default element to style
32 this.$el_to_style = this.$buttongroup; // Set default element to style
33 this.$droplabel = $('<button />')
33 this.$droplabel = $('<button />')
34 .addClass('btn')
34 .addClass('btn')
35 .addClass('widget-combo-btn')
35 .addClass('widget-combo-btn')
36 .html("&nbsp;")
36 .html("&nbsp;")
37 .appendTo(this.$buttongroup);
37 .appendTo(this.$buttongroup);
38 this.$dropbutton = $('<button />')
38 this.$dropbutton = $('<button />')
39 .addClass('btn')
39 .addClass('btn')
40 .addClass('dropdown-toggle')
40 .addClass('dropdown-toggle')
41 .addClass('widget-combo-carrot-btn')
41 .addClass('widget-combo-carrot-btn')
42 .attr('data-toggle', 'dropdown')
42 .attr('data-toggle', 'dropdown')
43 .append($('<span />').addClass("caret"))
43 .append($('<span />').addClass("caret"))
44 .appendTo(this.$buttongroup);
44 .appendTo(this.$buttongroup);
45 this.$droplist = $('<ul />')
45 this.$droplist = $('<ul />')
46 .addClass('dropdown-menu')
46 .addClass('dropdown-menu')
47 .appendTo(this.$buttongroup);
47 .appendTo(this.$buttongroup);
48
48
49 // Set defaults.
49 // Set defaults.
50 this.update();
50 this.update();
51 },
51 },
52
52
53 update : function(options){
53 update : function(options){
54 // Update the contents of this view
54 // Update the contents of this view
55 //
55 //
56 // Called when the model is changed. The model may have been
56 // Called when the model is changed. The model may have been
57 // changed by another view or by a state update from the back-end.
57 // changed by another view or by a state update from the back-end.
58
58
59 if (options === undefined || options.updated_view != this) {
59 if (options === undefined || options.updated_view != this) {
60 var selected_item_text = this.model.get('value_name');
60 var selected_item_text = this.model.get('value_name');
61 if (selected_item_text.length === 0) {
61 if (selected_item_text.trim().length === 0) {
62 this.$droplabel.html("&nbsp;");
62 this.$droplabel.html("&nbsp;");
63 } else {
63 } else {
64 this.$droplabel.text(selected_item_text);
64 this.$droplabel.text(selected_item_text);
65 }
65 }
66
66
67 var items = this.model.get('value_names');
67 var items = this.model.get('value_names');
68 var $replace_droplist = $('<ul />')
68 var $replace_droplist = $('<ul />')
69 .addClass('dropdown-menu');
69 .addClass('dropdown-menu');
70 var that = this;
70 var that = this;
71 _.each(items, function(item, i) {
71 _.each(items, function(item, i) {
72 var item_button = $('<a href="#"/>')
72 var item_button = $('<a href="#"/>')
73 .text(item)
73 .text(item)
74 .on('click', $.proxy(that.handle_click, that));
74 .on('click', $.proxy(that.handle_click, that));
75 $replace_droplist.append($('<li />').append(item_button));
75 $replace_droplist.append($('<li />').append(item_button));
76 });
76 });
77
77
78 this.$droplist.replaceWith($replace_droplist);
78 this.$droplist.replaceWith($replace_droplist);
79 this.$droplist.remove();
79 this.$droplist.remove();
80 this.$droplist = $replace_droplist;
80 this.$droplist = $replace_droplist;
81
81
82 if (this.model.get('disabled')) {
82 if (this.model.get('disabled')) {
83 this.$buttongroup.attr('disabled','disabled');
83 this.$buttongroup.attr('disabled','disabled');
84 this.$droplabel.attr('disabled','disabled');
84 this.$droplabel.attr('disabled','disabled');
85 this.$dropbutton.attr('disabled','disabled');
85 this.$dropbutton.attr('disabled','disabled');
86 this.$droplist.attr('disabled','disabled');
86 this.$droplist.attr('disabled','disabled');
87 } else {
87 } else {
88 this.$buttongroup.removeAttr('disabled');
88 this.$buttongroup.removeAttr('disabled');
89 this.$droplabel.removeAttr('disabled');
89 this.$droplabel.removeAttr('disabled');
90 this.$dropbutton.removeAttr('disabled');
90 this.$dropbutton.removeAttr('disabled');
91 this.$droplist.removeAttr('disabled');
91 this.$droplist.removeAttr('disabled');
92 }
92 }
93
93
94 var description = this.model.get('description');
94 var description = this.model.get('description');
95 if (description.length === 0) {
95 if (description.length === 0) {
96 this.$label.hide();
96 this.$label.hide();
97 } else {
97 } else {
98 this.$label.text(description);
98 this.$label.text(description);
99 this.$label.show();
99 this.$label.show();
100 }
100 }
101 }
101 }
102 return DropdownView.__super__.update.apply(this);
102 return DropdownView.__super__.update.apply(this);
103 },
103 },
104
104
105 handle_click: function (e) {
105 handle_click: function (e) {
106 // Handle when a value is clicked.
106 // Handle when a value is clicked.
107
107
108 // Calling model.set will trigger all of the other views of the
108 // Calling model.set will trigger all of the other views of the
109 // model to update.
109 // model to update.
110 this.model.set('value_name', $(e.target).text(), {updated_view: this});
110 this.model.set('value_name', $(e.target).text(), {updated_view: this});
111 this.touch();
111 this.touch();
112 },
112 },
113
113
114 });
114 });
115 WidgetManager.register_widget_view('DropdownView', DropdownView);
115 WidgetManager.register_widget_view('DropdownView', DropdownView);
116
116
117
117
118 var RadioButtonsView = IPython.DOMWidgetView.extend({
118 var RadioButtonsView = IPython.DOMWidgetView.extend({
119 render : function(){
119 render : function(){
120 // Called when view is rendered.
120 // Called when view is rendered.
121 this.$el
121 this.$el
122 .addClass('widget-hbox');
122 .addClass('widget-hbox');
123 this.$label = $('<div />')
123 this.$label = $('<div />')
124 .appendTo(this.$el)
124 .appendTo(this.$el)
125 .addClass('widget-hlabel')
125 .addClass('widget-hlabel')
126 .hide();
126 .hide();
127 this.$container = $('<div />')
127 this.$container = $('<div />')
128 .appendTo(this.$el)
128 .appendTo(this.$el)
129 .addClass('widget-container')
129 .addClass('widget-container')
130 .addClass('vbox');
130 .addClass('vbox');
131 this.$el_to_style = this.$container; // Set default element to style
131 this.$el_to_style = this.$container; // Set default element to style
132 this.update();
132 this.update();
133 },
133 },
134
134
135 update : function(options){
135 update : function(options){
136 // Update the contents of this view
136 // Update the contents of this view
137 //
137 //
138 // Called when the model is changed. The model may have been
138 // Called when the model is changed. The model may have been
139 // changed by another view or by a state update from the back-end.
139 // changed by another view or by a state update from the back-end.
140 if (options === undefined || options.updated_view != this) {
140 if (options === undefined || options.updated_view != this) {
141 // Add missing items to the DOM.
141 // Add missing items to the DOM.
142 var items = this.model.get('value_names');
142 var items = this.model.get('value_names');
143 var disabled = this.model.get('disabled');
143 var disabled = this.model.get('disabled');
144 var that = this;
144 var that = this;
145 _.each(items, function(item, index) {
145 _.each(items, function(item, index) {
146 var item_query = ' :input[value="' + item + '"]';
146 var item_query = ' :input[value="' + item + '"]';
147 if (that.$el.find(item_query).length === 0) {
147 if (that.$el.find(item_query).length === 0) {
148 var $label = $('<label />')
148 var $label = $('<label />')
149 .addClass('radio')
149 .addClass('radio')
150 .text(item)
150 .text(item)
151 .appendTo(that.$container);
151 .appendTo(that.$container);
152
152
153 $('<input />')
153 $('<input />')
154 .attr('type', 'radio')
154 .attr('type', 'radio')
155 .addClass(that.model)
155 .addClass(that.model)
156 .val(item)
156 .val(item)
157 .prependTo($label)
157 .prependTo($label)
158 .on('click', $.proxy(that.handle_click, that));
158 .on('click', $.proxy(that.handle_click, that));
159 }
159 }
160
160
161 var $item_element = that.$container.find(item_query);
161 var $item_element = that.$container.find(item_query);
162 if (that.model.get('value_name') == item) {
162 if (that.model.get('value_name') == item) {
163 $item_element.prop('checked', true);
163 $item_element.prop('checked', true);
164 } else {
164 } else {
165 $item_element.prop('checked', false);
165 $item_element.prop('checked', false);
166 }
166 }
167 $item_element.prop('disabled', disabled);
167 $item_element.prop('disabled', disabled);
168 });
168 });
169
169
170 // Remove items that no longer exist.
170 // Remove items that no longer exist.
171 this.$container.find('input').each(function(i, obj) {
171 this.$container.find('input').each(function(i, obj) {
172 var value = $(obj).val();
172 var value = $(obj).val();
173 var found = false;
173 var found = false;
174 _.each(items, function(item, index) {
174 _.each(items, function(item, index) {
175 if (item == value) {
175 if (item == value) {
176 found = true;
176 found = true;
177 return false;
177 return false;
178 }
178 }
179 });
179 });
180
180
181 if (!found) {
181 if (!found) {
182 $(obj).parent().remove();
182 $(obj).parent().remove();
183 }
183 }
184 });
184 });
185
185
186 var description = this.model.get('description');
186 var description = this.model.get('description');
187 if (description.length === 0) {
187 if (description.length === 0) {
188 this.$label.hide();
188 this.$label.hide();
189 } else {
189 } else {
190 this.$label.text(description);
190 this.$label.text(description);
191 this.$label.show();
191 this.$label.show();
192 }
192 }
193 }
193 }
194 return RadioButtonsView.__super__.update.apply(this);
194 return RadioButtonsView.__super__.update.apply(this);
195 },
195 },
196
196
197 handle_click: function (e) {
197 handle_click: function (e) {
198 // Handle when a value is clicked.
198 // Handle when a value is clicked.
199
199
200 // Calling model.set will trigger all of the other views of the
200 // Calling model.set will trigger all of the other views of the
201 // model to update.
201 // model to update.
202 this.model.set('value_name', $(e.target).val(), {updated_view: this});
202 this.model.set('value_name', $(e.target).val(), {updated_view: this});
203 this.touch();
203 this.touch();
204 },
204 },
205 });
205 });
206 WidgetManager.register_widget_view('RadioButtonsView', RadioButtonsView);
206 WidgetManager.register_widget_view('RadioButtonsView', RadioButtonsView);
207
207
208
208
209 var ToggleButtonsView = IPython.DOMWidgetView.extend({
209 var ToggleButtonsView = IPython.DOMWidgetView.extend({
210 render : function(){
210 render : function(){
211 // Called when view is rendered.
211 // Called when view is rendered.
212 this.$el
212 this.$el
213 .addClass('widget-hbox-single');
213 .addClass('widget-hbox-single');
214 this.$label = $('<div />')
214 this.$label = $('<div />')
215 .appendTo(this.$el)
215 .appendTo(this.$el)
216 .addClass('widget-hlabel')
216 .addClass('widget-hlabel')
217 .hide();
217 .hide();
218 this.$buttongroup = $('<div />')
218 this.$buttongroup = $('<div />')
219 .addClass('btn-group')
219 .addClass('btn-group')
220 .attr('data-toggle', 'buttons-radio')
220 .attr('data-toggle', 'buttons-radio')
221 .appendTo(this.$el);
221 .appendTo(this.$el);
222 this.$el_to_style = this.$buttongroup; // Set default element to style
222 this.$el_to_style = this.$buttongroup; // Set default element to style
223 this.update();
223 this.update();
224 },
224 },
225
225
226 update : function(options){
226 update : function(options){
227 // Update the contents of this view
227 // Update the contents of this view
228 //
228 //
229 // Called when the model is changed. The model may have been
229 // Called when the model is changed. The model may have been
230 // changed by another view or by a state update from the back-end.
230 // changed by another view or by a state update from the back-end.
231 if (options === undefined || options.updated_view != this) {
231 if (options === undefined || options.updated_view != this) {
232 // Add missing items to the DOM.
232 // Add missing items to the DOM.
233 var items = this.model.get('value_names');
233 var items = this.model.get('value_names');
234 var disabled = this.model.get('disabled');
234 var disabled = this.model.get('disabled');
235 var that = this;
235 var that = this;
236 var item_html;
236 _.each(items, function(item, index) {
237 _.each(items, function(item, index) {
237 var item_query = ' :contains("' + item + '")';
238 if (item.trim().length == 0) {
238 if (that.$buttongroup.find(item_query).length === 0) {
239 item_html = "&nbsp;";
239 $('<button />')
240 } else {
241 item_html = IPython.utils.escape_html(item);
242 }
243 var item_query = '[data-value="' + item + '"]';
244 var $item_element = that.$buttongroup.find(item_query);
245 if (!$item_element.length) {
246 $item_element = $('<button/>')
240 .attr('type', 'button')
247 .attr('type', 'button')
241 .addClass('btn')
248 .addClass('btn')
242 .text(item)
249 .html(item_html)
243 .appendTo(that.$buttongroup)
250 .appendTo(that.$buttongroup)
251 .attr('data-value', item)
244 .on('click', $.proxy(that.handle_click, that));
252 .on('click', $.proxy(that.handle_click, that));
245 }
253 }
246
247 var $item_element = that.$buttongroup.find(item_query);
248 if (that.model.get('value_name') == item) {
254 if (that.model.get('value_name') == item) {
249 $item_element.addClass('active');
255 $item_element.addClass('active');
250 } else {
256 } else {
251 $item_element.removeClass('active');
257 $item_element.removeClass('active');
252 }
258 }
253 $item_element.prop('disabled', disabled);
259 $item_element.prop('disabled', disabled);
254 });
260 });
255
261
256 // Remove items that no longer exist.
262 // Remove items that no longer exist.
257 this.$buttongroup.find('button').each(function(i, obj) {
263 this.$buttongroup.find('button').each(function(i, obj) {
258 var value = $(obj).text();
264 var value = $(obj).data('value');
259 var found = false;
265 var found = false;
260 _.each(items, function(item, index) {
266 _.each(items, function(item, index) {
261 if (item == value) {
267 if (item == value) {
262 found = true;
268 found = true;
263 return false;
269 return false;
264 }
270 }
265 });
271 });
266
272
267 if (!found) {
273 if (!found) {
268 $(obj).remove();
274 $(obj).remove();
269 }
275 }
270 });
276 });
271
277
272 var description = this.model.get('description');
278 var description = this.model.get('description');
273 if (description.length === 0) {
279 if (description.length === 0) {
274 this.$label.hide();
280 this.$label.hide();
275 } else {
281 } else {
276 this.$label.text(description);
282 this.$label.text(description);
277 this.$label.show();
283 this.$label.show();
278 }
284 }
279 }
285 }
280 return ToggleButtonsView.__super__.update.apply(this);
286 return ToggleButtonsView.__super__.update.apply(this);
281 },
287 },
282
288
283 handle_click: function (e) {
289 handle_click: function (e) {
284 // Handle when a value is clicked.
290 // Handle when a value is clicked.
285
291
286 // Calling model.set will trigger all of the other views of the
292 // Calling model.set will trigger all of the other views of the
287 // model to update.
293 // model to update.
288 this.model.set('value_name', $(e.target).text(), {updated_view: this});
294 this.model.set('value_name', $(e.target).data('value'), {updated_view: this});
289 this.touch();
295 this.touch();
290 },
296 },
291 });
297 });
292 WidgetManager.register_widget_view('ToggleButtonsView', ToggleButtonsView);
298 WidgetManager.register_widget_view('ToggleButtonsView', ToggleButtonsView);
293
299
294
300
295 var SelectView = IPython.DOMWidgetView.extend({
301 var SelectView = IPython.DOMWidgetView.extend({
296 render : function(){
302 render : function(){
297 // Called when view is rendered.
303 // Called when view is rendered.
298 this.$el
304 this.$el
299 .addClass('widget-hbox');
305 .addClass('widget-hbox');
300 this.$label = $('<div />')
306 this.$label = $('<div />')
301 .appendTo(this.$el)
307 .appendTo(this.$el)
302 .addClass('widget-hlabel')
308 .addClass('widget-hlabel')
303 .hide();
309 .hide();
304 this.$listbox = $('<select />')
310 this.$listbox = $('<select />')
305 .addClass('widget-listbox')
311 .addClass('widget-listbox')
306 .attr('size', 6)
312 .attr('size', 6)
307 .appendTo(this.$el);
313 .appendTo(this.$el);
308 this.$el_to_style = this.$listbox; // Set default element to style
314 this.$el_to_style = this.$listbox; // Set default element to style
309 this.update();
315 this.update();
310 },
316 },
311
317
312 update : function(options){
318 update : function(options){
313 // Update the contents of this view
319 // Update the contents of this view
314 //
320 //
315 // Called when the model is changed. The model may have been
321 // Called when the model is changed. The model may have been
316 // changed by another view or by a state update from the back-end.
322 // changed by another view or by a state update from the back-end.
317 if (options === undefined || options.updated_view != this) {
323 if (options === undefined || options.updated_view != this) {
318 // Add missing items to the DOM.
324 // Add missing items to the DOM.
319 var items = this.model.get('value_names');
325 var items = this.model.get('value_names');
320 var that = this;
326 var that = this;
321 _.each(items, function(item, index) {
327 _.each(items, function(item, index) {
322 var item_query = ' :contains("' + item + '")';
328 var item_query = ' :contains("' + item + '")';
323 if (that.$listbox.find(item_query).length === 0) {
329 if (that.$listbox.find(item_query).length === 0) {
324 $('<option />')
330 $('<option />')
325 .text(item)
331 .text(item)
326 .attr('value_name', item)
332 .attr('value_name', item)
327 .appendTo(that.$listbox)
333 .appendTo(that.$listbox)
328 .on('click', $.proxy(that.handle_click, that));
334 .on('click', $.proxy(that.handle_click, that));
329 }
335 }
330 });
336 });
331
337
332 // Select the correct element
338 // Select the correct element
333 this.$listbox.val(this.model.get('value_name'));
339 this.$listbox.val(this.model.get('value_name'));
334
340
335 // Disable listbox if needed
341 // Disable listbox if needed
336 var disabled = this.model.get('disabled');
342 var disabled = this.model.get('disabled');
337 this.$listbox.prop('disabled', disabled);
343 this.$listbox.prop('disabled', disabled);
338
344
339 // Remove items that no longer exist.
345 // Remove items that no longer exist.
340 this.$listbox.find('option').each(function(i, obj) {
346 this.$listbox.find('option').each(function(i, obj) {
341 var value = $(obj).text();
347 var value = $(obj).text();
342 var found = false;
348 var found = false;
343 _.each(items, function(item, index) {
349 _.each(items, function(item, index) {
344 if (item == value) {
350 if (item == value) {
345 found = true;
351 found = true;
346 return false;
352 return false;
347 }
353 }
348 });
354 });
349
355
350 if (!found) {
356 if (!found) {
351 $(obj).remove();
357 $(obj).remove();
352 }
358 }
353 });
359 });
354
360
355 var description = this.model.get('description');
361 var description = this.model.get('description');
356 if (description.length === 0) {
362 if (description.length === 0) {
357 this.$label.hide();
363 this.$label.hide();
358 } else {
364 } else {
359 this.$label.text(description);
365 this.$label.text(description);
360 this.$label.show();
366 this.$label.show();
361 }
367 }
362 }
368 }
363 return SelectView.__super__.update.apply(this);
369 return SelectView.__super__.update.apply(this);
364 },
370 },
365
371
366 handle_click: function (e) {
372 handle_click: function (e) {
367 // Handle when a value is clicked.
373 // Handle when a value is clicked.
368
374
369 // Calling model.set will trigger all of the other views of the
375 // Calling model.set will trigger all of the other views of the
370 // model to update.
376 // model to update.
371 this.model.set('value_name', $(e.target).text(), {updated_view: this});
377 this.model.set('value_name', $(e.target).text(), {updated_view: this});
372 this.touch();
378 this.touch();
373 },
379 },
374 });
380 });
375 WidgetManager.register_widget_view('SelectView', SelectView);
381 WidgetManager.register_widget_view('SelectView', SelectView);
376 });
382 });
General Comments 0
You need to be logged in to leave comments. Login now