##// END OF EJS Templates
Merge pull request #7725 from SylvainCorlay/fabutton...
Jonathan Frederic -
r20608:66d38c2d merge
parent child Browse files
Show More
@@ -1,158 +1,157 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 "jquery",
7 7 "bootstrap",
8 8 ], function(widget, $){
9 9
10 10 var CheckboxView = widget.DOMWidgetView.extend({
11 11 render : function(){
12 12 /**
13 13 * Called when view is rendered.
14 14 */
15 15 this.$el
16 16 .addClass('widget-hbox widget-checkbox');
17 17 this.$label = $('<div />')
18 18 .addClass('widget-label')
19 19 .appendTo(this.$el)
20 20 .hide();
21 21 this.$checkbox = $('<input />')
22 22 .attr('type', 'checkbox')
23 23 .appendTo(this.$el)
24 24 .click($.proxy(this.handle_click, this));
25 25
26 26 this.update(); // Set defaults.
27 27 },
28 28
29 29 update_attr: function(name, value) {
30 30 /**
31 31 * Set a css attr of the widget view.
32 32 */
33 33 if (name == 'padding' || name == 'margin') {
34 34 this.$el.css(name, value);
35 35 } else {
36 36 this.$checkbox.css(name, value);
37 37 }
38 38 },
39 39
40 40 handle_click: function() {
41 41 /**
42 42 * Handles when the checkbox is clicked.
43 43 *
44 44 * Calling model.set will trigger all of the other views of the
45 45 * model to update.
46 46 */
47 47 var value = this.model.get('value');
48 48 this.model.set('value', ! value, {updated_view: this});
49 49 this.touch();
50 50 },
51 51
52 52 update : function(options){
53 53 /**
54 54 * Update the contents of this view
55 55 *
56 56 * Called when the model is changed. The model may have been
57 57 * changed by another view or by a state update from the back-end.
58 58 */
59 59 this.$checkbox.prop('checked', this.model.get('value'));
60 60
61 61 if (options === undefined || options.updated_view != this) {
62 var disabled = this.model.get('disabled');
63 this.$checkbox.prop('disabled', disabled);
62 this.$checkbox.prop("disabled", this.model.get("disabled"));
64 63
65 var description = this.model.get('description');
64 var description = this.model.get("description");
66 65 if (description.trim().length === 0) {
67 66 this.$label.hide();
68 67 } else {
69 68 this.typeset(this.$label, description);
70 69 this.$label.show();
71 70 }
72 71 }
73 72 return CheckboxView.__super__.update.apply(this);
74 73 },
75 74
76 75 });
77 76
78 77
79 78 var ToggleButtonView = widget.DOMWidgetView.extend({
80 79 render : function() {
81 80 /**
82 81 * Called when view is rendered.
83 82 */
84 83 var that = this;
85 84 this.setElement($('<button />')
86 85 .addClass('btn btn-default')
87 86 .attr('type', 'button')
88 87 .on('click', function (e) {
89 88 e.preventDefault();
90 89 that.handle_click();
91 90 }));
92 91 this.$el.attr("data-toggle", "tooltip");
93 92 this.model.on('change:button_style', function(model, value) {
94 93 this.update_button_style();
95 94 }, this);
96 95 this.update_button_style('');
97 96
98 97 this.update(); // Set defaults.
99 98 },
100 99
101 100 update_button_style: function(previous_trait_value) {
102 101 var class_map = {
103 102 primary: ['btn-primary'],
104 103 success: ['btn-success'],
105 104 info: ['btn-info'],
106 105 warning: ['btn-warning'],
107 106 danger: ['btn-danger']
108 107 };
109 108 this.update_mapped_classes(class_map, 'button_style', previous_trait_value);
110 109 },
111 110
112 111 update : function(options){
113 112 /**
114 113 * Update the contents of this view
115 114 *
116 * Called when the model is changed. The model may have been
115 * Called when the model is changed. The model may have been
117 116 * changed by another view or by a state update from the back-end.
118 117 */
119 118 if (this.model.get('value')) {
120 119 this.$el.addClass('active');
121 120 } else {
122 121 this.$el.removeClass('active');
123 122 }
124 123
125 124 if (options === undefined || options.updated_view != this) {
126
127 var disabled = this.model.get('disabled');
128 this.$el.prop('disabled', disabled);
129
130 var description = this.model.get('description');
125 this.$el.prop("disabled", this.model.get("disabled"));
131 126 this.$el.attr("title", this.model.get("tooltip"));
132 if (description.trim().length === 0) {
127
128 var description = this.model.get("description");
129 var icon = this.model.get("icon");
130 if (description.trim().length === 0 && icon.trim().length ===0) {
133 131 this.$el.html("&nbsp;"); // Preserve button height
134 132 } else {
135 133 this.$el.text(description);
134 $('<i class="fa"></i>').prependTo(this.$el).addClass(icon);
136 135 }
137 136 }
138 137 return ToggleButtonView.__super__.update.apply(this);
139 138 },
140 139
141 140 handle_click: function(e) {
142 141 /**
143 142 * Handles and validates user input.
144 143 *
145 144 * Calling model.set will trigger all of the other views of the
146 145 * model to update.
147 146 */
148 147 var value = this.model.get('value');
149 148 this.model.set('value', ! value, {updated_view: this});
150 149 this.touch();
151 150 },
152 151 });
153 152
154 153 return {
155 154 'CheckboxView': CheckboxView,
156 155 'ToggleButtonView': ToggleButtonView,
157 156 };
158 157 });
@@ -1,77 +1,75 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 "jquery",
7 7 "bootstrap",
8 8 ], function(widget, $){
9 9
10 10 var ButtonView = widget.DOMWidgetView.extend({
11 11 render : function(){
12 12 /**
13 13 * Called when view is rendered.
14 14 */
15 15 this.setElement($("<button />")
16 16 .addClass('btn btn-default'));
17 17 this.$el.attr("data-toggle", "tooltip");
18 18 this.model.on('change:button_style', function(model, value) {
19 19 this.update_button_style();
20 20 }, this);
21 21 this.update_button_style('');
22 22
23 23 this.update(); // Set defaults.
24 24 },
25 25
26 26 update : function(){
27 27 /**
28 28 * Update the contents of this view
29 29 *
30 * Called when the model is changed. The model may have been
30 * Called when the model is changed. The model may have been
31 31 * changed by another view or by a state update from the back-end.
32 32 */
33 var description = this.model.get('description');
33 this.$el.prop("disabled", this.model.get("disabled"));
34 34 this.$el.attr("title", this.model.get("tooltip"));
35 if (description.length === 0) {
35
36 var description = this.model.get("description");
37 var icon = this.model.get("icon");
38 if (description.trim().length === 0 && icon.trim().length ===0) {
36 39 this.$el.html("&nbsp;"); // Preserve button height
37 40 } else {
38 41 this.$el.text(description);
39 }
40
41 if (this.model.get('disabled')) {
42 this.$el.attr('disabled','disabled');
43 } else {
44 this.$el.removeAttr('disabled');
42 $('<i class="fa"></i>').prependTo(this.$el).addClass(icon);
45 43 }
46 44
47 45 return ButtonView.__super__.update.apply(this);
48 46 },
49 47
50 48 update_button_style: function(previous_trait_value) {
51 49 var class_map = {
52 50 primary: ['btn-primary'],
53 51 success: ['btn-success'],
54 52 info: ['btn-info'],
55 53 warning: ['btn-warning'],
56 54 danger: ['btn-danger']
57 55 };
58 56 this.update_mapped_classes(class_map, 'button_style', previous_trait_value);
59 57 },
60 58
61 59 events: {
62 60 // Dictionary of events and their handlers.
63 61 'click': '_handle_click',
64 62 },
65 63
66 64 _handle_click: function(){
67 65 /**
68 66 * Handles when the button is clicked.
69 67 */
70 68 this.send({event: 'click'});
71 69 },
72 70 });
73 71
74 72 return {
75 73 'ButtonView': ButtonView,
76 74 };
77 75 });
@@ -1,573 +1,583 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 "base/js/utils",
7 7 "jquery",
8 8 "underscore",
9 9 "bootstrap",
10 10 ], function(widget, utils, $, _){
11 11
12 12 var DropdownView = widget.DOMWidgetView.extend({
13 13 render : function(){
14 14 /**
15 15 * Called when view is rendered.
16 16 */
17 17 this.$el
18 18 .addClass('widget-hbox widget-dropdown');
19 19 this.$label = $('<div />')
20 20 .appendTo(this.$el)
21 21 .addClass('widget-label')
22 22 .hide();
23 23 this.$buttongroup = $('<div />')
24 24 .addClass('widget_item')
25 25 .addClass('btn-group')
26 26 .appendTo(this.$el);
27 27 this.$droplabel = $('<button />')
28 28 .addClass('btn btn-default')
29 29 .addClass('widget-combo-btn')
30 30 .html("&nbsp;")
31 31 .appendTo(this.$buttongroup);
32 32 this.$dropbutton = $('<button />')
33 33 .addClass('btn btn-default')
34 34 .addClass('dropdown-toggle')
35 35 .addClass('widget-combo-carrot-btn')
36 36 .attr('data-toggle', 'dropdown')
37 37 .append($('<span />').addClass("caret"))
38 38 .appendTo(this.$buttongroup);
39 39 this.$droplist = $('<ul />')
40 40 .addClass('dropdown-menu')
41 41 .appendTo(this.$buttongroup);
42 42
43 43 this.model.on('change:button_style', function(model, value) {
44 44 this.update_button_style();
45 45 }, this);
46 46 this.update_button_style('');
47 47
48 48 // Set defaults.
49 49 this.update();
50 50 },
51 51
52 52 update : function(options){
53 53 /**
54 54 * Update the contents of this view
55 55 *
56 56 * Called when the model is changed. The model may have been
57 57 * changed by another view or by a state update from the back-end.
58 58 */
59 59
60 60 if (options === undefined || options.updated_view != this) {
61 61 var selected_item_text = this.model.get('selected_label');
62 62 if (selected_item_text.trim().length === 0) {
63 63 this.$droplabel.html("&nbsp;");
64 64 } else {
65 65 this.$droplabel.text(selected_item_text);
66 66 }
67 67
68 68 var items = this.model.get('_options_labels');
69 69 var $replace_droplist = $('<ul />')
70 70 .addClass('dropdown-menu');
71 71 // Copy the style
72 72 $replace_droplist.attr('style', this.$droplist.attr('style'));
73 73 var that = this;
74 74 _.each(items, function(item, i) {
75 75 var item_button = $('<a href="#"/>')
76 76 .text(item)
77 77 .on('click', $.proxy(that.handle_click, that));
78 78 $replace_droplist.append($('<li />').append(item_button));
79 79 });
80 80
81 81 this.$droplist.replaceWith($replace_droplist);
82 82 this.$droplist.remove();
83 83 this.$droplist = $replace_droplist;
84 84
85 85 if (this.model.get('disabled')) {
86 86 this.$buttongroup.attr('disabled','disabled');
87 87 this.$droplabel.attr('disabled','disabled');
88 88 this.$dropbutton.attr('disabled','disabled');
89 89 this.$droplist.attr('disabled','disabled');
90 90 } else {
91 91 this.$buttongroup.removeAttr('disabled');
92 92 this.$droplabel.removeAttr('disabled');
93 93 this.$dropbutton.removeAttr('disabled');
94 94 this.$droplist.removeAttr('disabled');
95 95 }
96 96
97 97 var description = this.model.get('description');
98 98 if (description.length === 0) {
99 99 this.$label.hide();
100 100 } else {
101 101 this.typeset(this.$label, description);
102 102 this.$label.show();
103 103 }
104 104 }
105 105 return DropdownView.__super__.update.apply(this);
106 106 },
107 107
108 108 update_button_style: function(previous_trait_value) {
109 109 var class_map = {
110 110 primary: ['btn-primary'],
111 111 success: ['btn-success'],
112 112 info: ['btn-info'],
113 113 warning: ['btn-warning'],
114 114 danger: ['btn-danger']
115 115 };
116 116 this.update_mapped_classes(class_map, 'button_style', previous_trait_value, this.$droplabel);
117 117 this.update_mapped_classes(class_map, 'button_style', previous_trait_value, this.$dropbutton);
118 118 },
119 119
120 120 update_attr: function(name, value) {
121 121 /**
122 122 * Set a css attr of the widget view.
123 123 */
124 124 if (name.substring(0, 6) == 'border' || name == 'background' || name == 'color') {
125 125 this.$droplabel.css(name, value);
126 126 this.$dropbutton.css(name, value);
127 127 this.$droplist.css(name, value);
128 128 } else if (name == 'width') {
129 129 this.$droplist.css(name, value);
130 130 this.$droplabel.css(name, value);
131 131 } else if (name == 'padding') {
132 132 this.$droplist.css(name, value);
133 133 this.$buttongroup.css(name, value);
134 134 } else if (name == 'margin') {
135 135 this.$buttongroup.css(name, value);
136 136 } else if (name == 'height') {
137 137 this.$droplabel.css(name, value);
138 138 this.$dropbutton.css(name, value);
139 139 } else if (name == 'padding' || name == 'margin') {
140 140 this.$el.css(name, value);
141 141 } else {
142 142 this.$droplist.css(name, value);
143 143 this.$droplabel.css(name, value);
144 144 }
145 145 },
146 146
147 147 handle_click: function (e) {
148 148 /**
149 149 * Handle when a value is clicked.
150 150 *
151 151 * Calling model.set will trigger all of the other views of the
152 152 * model to update.
153 153 */
154 154 this.model.set('selected_label', $(e.target).text(), {updated_view: this});
155 155 this.touch();
156 156
157 157 // Manually hide the droplist.
158 158 e.stopPropagation();
159 159 e.preventDefault();
160 160 this.$buttongroup.removeClass('open');
161 161 },
162 162
163 163 });
164 164
165 165
166 166 var RadioButtonsView = widget.DOMWidgetView.extend({
167 167 render : function(){
168 168 /**
169 169 * Called when view is rendered.
170 170 */
171 171 this.$el
172 172 .addClass('widget-hbox widget-radio');
173 173 this.$label = $('<div />')
174 174 .appendTo(this.$el)
175 175 .addClass('widget-label')
176 176 .hide();
177 177 this.$container = $('<div />')
178 178 .appendTo(this.$el)
179 179 .addClass('widget-radio-box');
180 180 this.update();
181 181 },
182 182
183 183 update : function(options){
184 184 /**
185 185 * Update the contents of this view
186 186 *
187 187 * Called when the model is changed. The model may have been
188 188 * changed by another view or by a state update from the back-end.
189 189 */
190 190 if (options === undefined || options.updated_view != this) {
191 191 // Add missing items to the DOM.
192 192 var items = this.model.get('_options_labels');
193 193 var disabled = this.model.get('disabled');
194 194 var that = this;
195 195 _.each(items, function(item, index) {
196 196 var item_query = ' :input[data-value="' + encodeURIComponent(item) + '"]';
197 197 if (that.$el.find(item_query).length === 0) {
198 198 var $label = $('<label />')
199 199 .addClass('radio')
200 200 .text(item)
201 201 .appendTo(that.$container);
202 202
203 203 $('<input />')
204 204 .attr('type', 'radio')
205 205 .addClass(that.model)
206 206 .val(item)
207 207 .attr('data-value', encodeURIComponent(item))
208 208 .prependTo($label)
209 209 .on('click', $.proxy(that.handle_click, that));
210 210 }
211 211
212 212 var $item_element = that.$container.find(item_query);
213 213 if (that.model.get('selected_label') == item) {
214 214 $item_element.prop('checked', true);
215 215 } else {
216 216 $item_element.prop('checked', false);
217 217 }
218 218 $item_element.prop('disabled', disabled);
219 219 });
220 220
221 221 // Remove items that no longer exist.
222 222 this.$container.find('input').each(function(i, obj) {
223 223 var value = $(obj).val();
224 224 var found = false;
225 225 _.each(items, function(item, index) {
226 226 if (item == value) {
227 227 found = true;
228 228 return false;
229 229 }
230 230 });
231 231
232 232 if (!found) {
233 233 $(obj).parent().remove();
234 234 }
235 235 });
236 236
237 237 var description = this.model.get('description');
238 238 if (description.length === 0) {
239 239 this.$label.hide();
240 240 } else {
241 241 this.$label.text(description);
242 242 this.typeset(this.$label, description);
243 243 this.$label.show();
244 244 }
245 245 }
246 246 return RadioButtonsView.__super__.update.apply(this);
247 247 },
248 248
249 249 update_attr: function(name, value) {
250 250 /**
251 251 * Set a css attr of the widget view.
252 252 */
253 253 if (name == 'padding' || name == 'margin') {
254 254 this.$el.css(name, value);
255 255 } else {
256 256 this.$container.css(name, value);
257 257 }
258 258 },
259 259
260 260 handle_click: function (e) {
261 261 /**
262 262 * Handle when a value is clicked.
263 263 *
264 264 * Calling model.set will trigger all of the other views of the
265 265 * model to update.
266 266 */
267 267 this.model.set('selected_label', $(e.target).val(), {updated_view: this});
268 268 this.touch();
269 269 },
270 270 });
271 271
272 272
273 273 var ToggleButtonsView = widget.DOMWidgetView.extend({
274 274 initialize: function() {
275 275 this._css_state = {};
276 276 ToggleButtonsView.__super__.initialize.apply(this, arguments);
277 277 },
278 278
279 279 render: function() {
280 280 /**
281 281 * Called when view is rendered.
282 282 */
283 283 this.$el
284 284 .addClass('widget-hbox widget-toggle-buttons');
285 285 this.$label = $('<div />')
286 286 .appendTo(this.$el)
287 287 .addClass('widget-label')
288 288 .hide();
289 289 this.$buttongroup = $('<div />')
290 290 .addClass('btn-group')
291 291 .appendTo(this.$el);
292 292
293 293 this.model.on('change:button_style', function(model, value) {
294 294 this.update_button_style();
295 295 }, this);
296 296 this.update_button_style('');
297 297 this.update();
298 298 },
299 299
300 300 update : function(options){
301 301 /**
302 302 * Update the contents of this view
303 303 *
304 304 * Called when the model is changed. The model may have been
305 305 * changed by another view or by a state update from the back-end.
306 306 */
307 307 if (options === undefined || options.updated_view != this) {
308 308 // Add missing items to the DOM.
309 309 var items = this.model.get('_options_labels');
310 var icons = this.model.get('icons');
311 var previous_icons = this.model.previous('icons') || [];
310 312 var disabled = this.model.get('disabled');
311 313 var that = this;
312 314 var item_html;
313 315 _.each(items, function(item, index) {
314 if (item.trim().length === 0) {
316 if (item.trim().length === 0 && (!icons[index] ||
317 icons[index].trim().length === 0)) {
315 318 item_html = "&nbsp;";
316 319 } else {
317 320 item_html = utils.escape_html(item);
318 321 }
319 322 var item_query = '[data-value="' + encodeURIComponent(item) + '"]';
320 323 var $item_element = that.$buttongroup.find(item_query);
324 var $icon_element = $item_element.find('.fa');
321 325 if (!$item_element.length) {
322 326 $item_element = $('<button/>')
323 327 .attr('type', 'button')
324 328 .addClass('btn btn-default')
325 329 .html(item_html)
326 330 .appendTo(that.$buttongroup)
327 331 .attr('data-value', encodeURIComponent(item))
332 .attr('data-toggle', 'tooltip')
328 333 .attr('value', item)
329 334 .on('click', $.proxy(that.handle_click, that));
330 335 that.update_style_traits($item_element);
336 $icon_element = $('<i class="fa"></i>').prependTo($item_element);
331 337 }
332 338 if (that.model.get('selected_label') == item) {
333 339 $item_element.addClass('active');
334 340 } else {
335 341 $item_element.removeClass('active');
336 342 }
337 $item_element.prop('disabled', disabled);
343 $item_element.prop('disabled', disabled);
344 $item_element.attr('title', that.model.get('tooltips')[index]);
345 $icon_element
346 .removeClass(previous_icons[index])
347 .addClass(icons[index]);
338 348 });
339 349
340 350 // Remove items that no longer exist.
341 351 this.$buttongroup.find('button').each(function(i, obj) {
342 352 var value = $(obj).attr('value');
343 353 var found = false;
344 354 _.each(items, function(item, index) {
345 355 if (item == value) {
346 356 found = true;
347 357 return false;
348 358 }
349 359 });
350 360
351 361 if (!found) {
352 362 $(obj).remove();
353 363 }
354 364 });
355 365
356 366 var description = this.model.get('description');
357 367 if (description.length === 0) {
358 368 this.$label.hide();
359 369 } else {
360 370 this.$label.text();
361 371 this.typeset(this.$label, description);
362 372 this.$label.show();
363 373 }
364 374 }
365 375 return ToggleButtonsView.__super__.update.apply(this);
366 376 },
367 377
368 378 update_attr: function(name, value) {
369 379 /**
370 380 * Set a css attr of the widget view.
371 381 */
372 382 if (name == 'padding' || name == 'margin') {
373 383 this.$el.css(name, value);
374 384 } else {
375 385 this._css_state[name] = value;
376 386 this.update_style_traits();
377 387 }
378 388 },
379 389
380 390 update_style_traits: function(button) {
381 391 for (var name in this._css_state) {
382 392 if (this._css_state.hasOwnProperty(name)) {
383 393 if (name == 'margin') {
384 394 this.$buttongroup.css(name, this._css_state[name]);
385 395 } else if (name != 'width') {
386 396 if (button) {
387 397 button.css(name, this._css_state[name]);
388 398 } else {
389 399 this.$buttongroup.find('button').css(name, this._css_state[name]);
390 400 }
391 401 }
392 402 }
393 403 }
394 404 },
395 405
396 406 update_button_style: function(previous_trait_value) {
397 407 var class_map = {
398 408 primary: ['btn-primary'],
399 409 success: ['btn-success'],
400 410 info: ['btn-info'],
401 411 warning: ['btn-warning'],
402 412 danger: ['btn-danger']
403 413 };
404 414 this.update_mapped_classes(class_map, 'button_style', previous_trait_value, this.$buttongroup.find('button'));
405 415 },
406 416
407 417 handle_click: function (e) {
408 418 /**
409 419 * Handle when a value is clicked.
410 420 *
411 421 * Calling model.set will trigger all of the other views of the
412 422 * model to update.
413 423 */
414 424 this.model.set('selected_label', $(e.target).attr('value'), {updated_view: this});
415 425 this.touch();
416 426 },
417 427 });
418 428
419 429
420 430 var SelectView = widget.DOMWidgetView.extend({
421 431 render : function(){
422 432 /**
423 433 * Called when view is rendered.
424 434 */
425 435 this.$el
426 436 .addClass('widget-hbox widget-select');
427 437 this.$label = $('<div />')
428 438 .appendTo(this.$el)
429 439 .addClass('widget-label')
430 440 .hide();
431 441 this.$listbox = $('<select />')
432 442 .addClass('widget-listbox form-control')
433 443 .attr('size', 6)
434 444 .appendTo(this.$el)
435 445 .on('change', $.proxy(this.handle_change, this));
436 446 this.update();
437 447 },
438 448
439 449 update : function(options){
440 450 /**
441 451 * Update the contents of this view
442 452 *
443 453 * Called when the model is changed. The model may have been
444 454 * changed by another view or by a state update from the back-end.
445 455 */
446 456 if (options === undefined || options.updated_view != this) {
447 457 // Add missing items to the DOM.
448 458 var items = this.model.get('_options_labels');
449 459 var that = this;
450 460 _.each(items, function(item, index) {
451 461 var item_query = 'option[data-value="' + encodeURIComponent(item) + '"]';
452 462 if (that.$listbox.find(item_query).length === 0) {
453 463 $('<option />')
454 464 .text(item)
455 465 .attr('data-value', encodeURIComponent(item))
456 466 .attr('selected_label', item)
457 467 .on("click", $.proxy(that.handle_click, that))
458 468 .appendTo(that.$listbox);
459 469 }
460 470 });
461 471
462 472 // Select the correct element
463 473 this.$listbox.val(this.model.get('selected_label'));
464 474
465 475 // Disable listbox if needed
466 476 var disabled = this.model.get('disabled');
467 477 this.$listbox.prop('disabled', disabled);
468 478
469 479 // Remove items that no longer exist.
470 480 this.$listbox.find('option').each(function(i, obj) {
471 481 var value = $(obj).text();
472 482 var found = false;
473 483 _.each(items, function(item, index) {
474 484 if (item == value) {
475 485 found = true;
476 486 return false;
477 487 }
478 488 });
479 489
480 490 if (!found) {
481 491 $(obj).remove();
482 492 }
483 493 });
484 494
485 495 var description = this.model.get('description');
486 496 if (description.length === 0) {
487 497 this.$label.hide();
488 498 } else {
489 499 this.typeset(this.$label, description);
490 500 this.$label.show();
491 501 }
492 502 }
493 503 return SelectView.__super__.update.apply(this);
494 504 },
495 505
496 506 update_attr: function(name, value) {
497 507 /**
498 508 * Set a css attr of the widget view.
499 509 */
500 510 if (name == 'padding' || name == 'margin') {
501 511 this.$el.css(name, value);
502 512 } else {
503 513 this.$listbox.css(name, value);
504 514 }
505 515 },
506 516
507 517 handle_click: function (e) {
508 518 /**
509 519 * Handle when a new value is clicked.
510 520 */
511 521 this.$listbox.val($(e.target).val()).change();
512 522 },
513 523
514 524 handle_change: function (e) {
515 525 /**
516 526 * Handle when a new value is selected.
517 527 *
518 528 * Calling model.set will trigger all of the other views of the
519 529 * model to update.
520 530 */
521 531 this.model.set('selected_label', this.$listbox.val(), {updated_view: this});
522 532 this.touch();
523 533 },
524 534 });
525 535
526 536
527 537 var SelectMultipleView = SelectView.extend({
528 538 render: function(){
529 539 /**
530 540 * Called when view is rendered.
531 541 */
532 542 SelectMultipleView.__super__.render.apply(this);
533 543 this.$el.removeClass('widget-select')
534 544 .addClass('widget-select-multiple');
535 545 this.$listbox.attr('multiple', true)
536 546 .on('change', $.proxy(this.handle_change, this));
537 547 return this;
538 548 },
539 549
540 550 update: function(){
541 551 /**
542 552 * Update the contents of this view
543 553 *
544 554 * Called when the model is changed. The model may have been
545 555 * changed by another view or by a state update from the back-end.
546 556 */
547 557 SelectMultipleView.__super__.update.apply(this, arguments);
548 558 this.$listbox.val(this.model.get('selected_labels'));
549 559 },
550 560
551 561 handle_change: function (e) {
552 562 /**
553 563 * Handle when a new value is selected.
554 564 *
555 565 * Calling model.set will trigger all of the other views of the
556 566 * model to update.
557 567 */
558 568 this.model.set('selected_labels',
559 569 (this.$listbox.val() || []).slice(),
560 570 {updated_view: this});
561 571 this.touch();
562 572 },
563 573 });
564 574
565 575
566 576 return {
567 577 'DropdownView': DropdownView,
568 578 'RadioButtonsView': RadioButtonsView,
569 579 'ToggleButtonsView': ToggleButtonsView,
570 580 'SelectView': SelectView,
571 581 'SelectMultipleView': SelectMultipleView,
572 582 };
573 583 });
@@ -1,92 +1,92 b''
1 1 // Test widget bool class
2 2 casper.notebook_test(function () {
3 3 "use strict";
4 4
5 5 // Create a checkbox and togglebutton.
6 6 var bool_index = this.append_cell(
7 7 'from IPython.html import widgets\n' +
8 8 'from IPython.display import display, clear_output\n' +
9 9 'bool_widgets = [widgets.Checkbox(description="Title", value=True),\n' +
10 10 ' widgets.ToggleButton(description="Title", value=True)]\n' +
11 11 'display(bool_widgets[0])\n' +
12 12 'display(bool_widgets[1])\n' +
13 13 'print("Success")');
14 14 this.execute_cell_then(bool_index, function(index){
15 15 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
16 16 'Create bool widget cell executed with correct output.');
17 17 });
18 18
19 19 // Wait for the widgets to actually display.
20 20 var widget_checkbox_selector = '.widget-area .widget-subarea .widget-hbox input';
21 21 var widget_togglebutton_selector = '.widget-area .widget-subarea button';
22 22 this.wait_for_element(bool_index, widget_checkbox_selector);
23 23 this.wait_for_element(bool_index, widget_togglebutton_selector);
24 24
25 25 // Continue the tests.
26 26 this.then(function() {
27 27 this.test.assert(this.cell_element_exists(bool_index,
28 28 '.widget-area .widget-subarea'),
29 29 'Widget subarea exists.');
30 30
31 31 this.test.assert(this.cell_element_exists(bool_index,
32 32 widget_checkbox_selector),
33 33 'Checkbox exists.');
34 34
35 35 this.test.assert(this.cell_element_function(bool_index,
36 36 widget_checkbox_selector, 'prop', ['checked']),
37 37 'Checkbox is checked.');
38 38
39 39 this.test.assert(this.cell_element_exists(bool_index,
40 40 '.widget-area .widget-subarea .widget-hbox .widget-label'),
41 41 'Checkbox label exists.');
42 42
43 43 this.test.assert(this.cell_element_function(bool_index,
44 44 '.widget-area .widget-subarea .widget-hbox .widget-label', 'html')=="Title",
45 45 'Checkbox labeled correctly.');
46 46
47 47 this.test.assert(this.cell_element_exists(bool_index,
48 48 widget_togglebutton_selector),
49 49 'Toggle button exists.');
50 50
51 51 this.test.assert(this.cell_element_function(bool_index,
52 widget_togglebutton_selector, 'html')=="Title",
52 widget_togglebutton_selector, 'html')=='<i class="fa"></i>Title',
53 53 'Toggle button labeled correctly.');
54 54
55 55 this.test.assert(this.cell_element_function(bool_index,
56 56 widget_togglebutton_selector, 'hasClass', ['active']),
57 57 'Toggle button is toggled.');
58 58 });
59 59
60 60 // Try changing the state of the widgets programatically.
61 61 var index = this.append_cell(
62 62 'bool_widgets[0].value = False\n' +
63 63 'bool_widgets[1].value = False\n' +
64 64 'print("Success")');
65 65 this.execute_cell_then(index, function(index){
66 66 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
67 67 'Change bool widget value cell executed with correct output.');
68 68
69 69 this.test.assert(! this.cell_element_function(bool_index,
70 70 widget_checkbox_selector, 'prop', ['checked']),
71 71 'Checkbox is not checked. (1)');
72 72
73 73 this.test.assert(! this.cell_element_function(bool_index,
74 74 widget_togglebutton_selector, 'hasClass', ['active']),
75 75 'Toggle button is not toggled. (1)');
76 76
77 77 // Try toggling the bool by clicking on the checkbox.
78 78 this.cell_element_function(bool_index, widget_checkbox_selector, 'click');
79 79
80 80 this.test.assert(this.cell_element_function(bool_index,
81 81 widget_checkbox_selector, 'prop', ['checked']),
82 82 'Checkbox is checked. (2)');
83 83
84 84 // Try toggling the bool by clicking on the toggle button.
85 85 this.cell_element_function(bool_index, widget_togglebutton_selector, 'click');
86 86
87 87 this.test.assert(this.cell_element_function(bool_index,
88 88 widget_togglebutton_selector, 'hasClass', ['active']),
89 89 'Toggle button is toggled. (3)');
90 90
91 91 });
92 92 });
@@ -1,48 +1,48 b''
1 1 // Test widget button class
2 2 casper.notebook_test(function () {
3 3 var button_index = this.append_cell(
4 4 'from IPython.html import widgets\n' +
5 5 'from IPython.display import display, clear_output\n' +
6 6 'button = widgets.Button(description="Title")\n' +
7 7 'display(button)\n' +
8 8 'print("Success")\n' +
9 9 'def handle_click(sender):\n' +
10 10 ' display("Clicked")\n' +
11 11 'button.on_click(handle_click)');
12 12 this.execute_cell_then(button_index, function(index){
13 13 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
14 14 'Create button cell executed with correct output.');
15 15 });
16 16
17 17 // Wait for the widgets to actually display.
18 18 var widget_button_selector = '.widget-area .widget-subarea button';
19 19 this.wait_for_element(button_index, widget_button_selector);
20 20
21 21 // Continue with the tests.
22 22 this.then(function() {
23 23 this.test.assert(this.cell_element_exists(button_index,
24 24 '.widget-area .widget-subarea'),
25 25 'Widget subarea exists.');
26 26
27 27 this.test.assert(this.cell_element_exists(button_index,
28 28 widget_button_selector),
29 29 'Widget button exists.');
30 30
31 31 this.test.assert(this.cell_element_function(button_index,
32 widget_button_selector, 'html')=='Title',
32 widget_button_selector, 'html')=='<i class="fa"></i>Title',
33 33 'Set button description.');
34 34
35 35 this.cell_element_function(button_index,
36 36 widget_button_selector, 'click');
37 37 });
38 38
39 39 this.wait_for_output(button_index, 1);
40 40
41 41 this.then(function () {
42 42 var warning_text = this.get_output_cell(button_index, 1).text;
43 43 this.test.assertNotEquals(warning_text.indexOf('Warning'), -1,
44 44 'Importing widgets show a warning');
45 45 this.test.assertEquals(this.get_output_cell(button_index, 2).data['text/plain'], "'Clicked'",
46 46 'Button click event fires.');
47 47 });
48 48 });
@@ -1,71 +1,76 b''
1 1 """Bool class.
2 2
3 3 Represents a boolean using a widget.
4 4 """
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (c) 2013, the IPython Development Team.
7 7 #
8 8 # Distributed under the terms of the Modified BSD License.
9 9 #
10 10 # The full license is in the file COPYING.txt, distributed with this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16 from .widget import DOMWidget, register
17 17 from IPython.utils.traitlets import Unicode, Bool, CaselessStrEnum
18 18 from IPython.utils.warn import DeprecatedClass
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Classes
22 22 #-----------------------------------------------------------------------------
23 23 class _Bool(DOMWidget):
24 24 """A base class for creating widgets that represent booleans."""
25 25 value = Bool(False, help="Bool value", sync=True)
26 26 description = Unicode('', help="Description of the boolean (label).", sync=True)
27 27 disabled = Bool(False, help="Enable or disable user changes.", sync=True)
28 28
29 29 def __init__(self, value=None, **kwargs):
30 30 if value is not None:
31 31 kwargs['value'] = value
32 32 super(_Bool, self).__init__(**kwargs)
33 33
34 34 @register('IPython.Checkbox')
35 35 class Checkbox(_Bool):
36 36 """Displays a boolean `value` in the form of a checkbox.
37 37
38 38 Parameters
39 39 ----------
40 40 value : {True,False}
41 41 value of the checkbox: True-checked, False-unchecked
42 42 description : str
43 43 description displayed next to the checkbox
44 44 """
45 45 _view_name = Unicode('CheckboxView', sync=True)
46 46
47 47
48 48 @register('IPython.ToggleButton')
49 49 class ToggleButton(_Bool):
50 50 """Displays a boolean `value` in the form of a toggle button.
51 51
52 52 Parameters
53 53 ----------
54 54 value : {True,False}
55 55 value of the toggle button: True-pressed, False-unpressed
56 56 description : str
57 57 description displayed next to the button
58 tooltip: str
59 tooltip caption of the toggle button
60 icon: str
61 font-awesome icon name
58 62 """
59 63
60 64 _view_name = Unicode('ToggleButtonView', sync=True)
61 65 tooltip = Unicode(help="Tooltip caption of the toggle button.", sync=True)
66 icon = Unicode('', help= "Font-awesome icon.", sync=True)
62 67
63 68 button_style = CaselessStrEnum(
64 69 values=['primary', 'success', 'info', 'warning', 'danger', ''],
65 70 default_value='', allow_none=True, sync=True, help="""Use a
66 71 predefined styling for the button.""")
67 72
68 73
69 74 # Remove in IPython 4.0
70 75 CheckboxWidget = DeprecatedClass(Checkbox, 'CheckboxWidget')
71 76 ToggleButtonWidget = DeprecatedClass(ToggleButton, 'ToggleButtonWidget')
@@ -1,72 +1,82 b''
1 1 """Button class.
2 2
3 3 Represents a button in the frontend using a widget. Allows user to listen for
4 4 click events on the button and trigger backend code when the clicks are fired.
5 5 """
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (c) 2013, the IPython Development Team.
8 8 #
9 9 # Distributed under the terms of the Modified BSD License.
10 10 #
11 11 # The full license is in the file COPYING.txt, distributed with this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17 from .widget import DOMWidget, CallbackDispatcher, register
18 18 from IPython.utils.traitlets import Unicode, Bool, CaselessStrEnum
19 19 from IPython.utils.warn import DeprecatedClass
20 20
21 21 #-----------------------------------------------------------------------------
22 22 # Classes
23 23 #-----------------------------------------------------------------------------
24 24 @register('IPython.Button')
25 25 class Button(DOMWidget):
26 26 """Button widget.
27 This widget has an `on_click` method that allows you to listen for the
28 user clicking on the button. The click event itself is stateless.
27 29
28 This widget has an `on_click` method that allows you to listen for the
29 user clicking on the button. The click event itself is stateless."""
30 Parameters
31 ----------
32 description : str
33 description displayed next to the button
34 tooltip: str
35 tooltip caption of the toggle button
36 icon: str
37 font-awesome icon name
38 """
30 39 _view_name = Unicode('ButtonView', sync=True)
31 40
32 41 # Keys
33 42 description = Unicode('', help="Button label.", sync=True)
34 43 tooltip = Unicode(help="Tooltip caption of the button.", sync=True)
35 44 disabled = Bool(False, help="Enable or disable user changes.", sync=True)
45 icon = Unicode('', help= "Font-awesome icon.", sync=True)
36 46
37 47 button_style = CaselessStrEnum(
38 48 values=['primary', 'success', 'info', 'warning', 'danger', ''],
39 49 default_value='', allow_none=True, sync=True, help="""Use a
40 50 predefined styling for the button.""")
41 51
42 52 def __init__(self, **kwargs):
43 53 """Constructor"""
44 54 super(Button, self).__init__(**kwargs)
45 55 self._click_handlers = CallbackDispatcher()
46 56 self.on_msg(self._handle_button_msg)
47 57
48 58 def on_click(self, callback, remove=False):
49 59 """Register a callback to execute when the button is clicked.
50 60
51 61 The callback will be called with one argument,
52 62 the clicked button widget instance.
53 63
54 64 Parameters
55 65 ----------
56 66 remove : bool (optional)
57 67 Set to true to remove the callback from the list of callbacks."""
58 68 self._click_handlers.register_callback(callback, remove=remove)
59 69
60 70 def _handle_button_msg(self, _, content):
61 71 """Handle a msg from the front-end.
62 72
63 73 Parameters
64 74 ----------
65 75 content: dict
66 76 Content of the msg."""
67 77 if content.get('event', '') == 'click':
68 78 self._click_handlers(self)
69 79
70 80
71 81 # Remove in IPython 4.0
72 82 ButtonWidget = DeprecatedClass(Button, 'ButtonWidget')
@@ -1,240 +1,248 b''
1 1 """Selection classes.
2 2
3 3 Represents an enumeration using a widget.
4 4 """
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (c) 2013, the IPython Development Team.
7 7 #
8 8 # Distributed under the terms of the Modified BSD License.
9 9 #
10 10 # The full license is in the file COPYING.txt, distributed with this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 from collections import OrderedDict
18 18 from threading import Lock
19 19
20 20 from .widget import DOMWidget, register
21 21 from IPython.utils.traitlets import (
22 Unicode, Bool, Any, Dict, TraitError, CaselessStrEnum, Tuple
22 Unicode, Bool, Any, Dict, TraitError, CaselessStrEnum, Tuple, List
23 23 )
24 24 from IPython.utils.py3compat import unicode_type
25 25 from IPython.utils.warn import DeprecatedClass
26 26
27 27 #-----------------------------------------------------------------------------
28 28 # SelectionWidget
29 29 #-----------------------------------------------------------------------------
30 30 class _Selection(DOMWidget):
31 31 """Base class for Selection widgets
32 32
33 33 ``options`` can be specified as a list or dict. If given as a list,
34 34 it will be transformed to a dict of the form ``{str(value):value}``.
35
36 When programmatically setting the value, a reverse lookup is performed
37 among the options to set the value of ``selected_label`` accordingly. The
38 reverse lookup uses the equality operator by default, but an other
39 predicate may be provided via the ``equals`` argument. For example, when
40 dealing with numpy arrays, one may set equals=np.array_equal.
35 41 """
36 42
37 43 value = Any(help="Selected value")
38 44 selected_label = Unicode(help="The label of the selected value", sync=True)
39 45 options = Any(help="""List of (key, value) tuples or dict of values that the
40 46 user can select.
41 47
42 48 The keys of this list are the strings that will be displayed in the UI,
43 49 representing the actual Python choices.
44 50
45 51 The keys of this list are also available as _options_labels.
46 52 """)
47 53
48 54 _options_dict = Dict()
49 55 _options_labels = Tuple(sync=True)
50 56 _options_values = Tuple()
51 57
52 58 disabled = Bool(False, help="Enable or disable user changes", sync=True)
53 59 description = Unicode(help="Description of the value this widget represents", sync=True)
54 60
55 61 def __init__(self, *args, **kwargs):
56 62 self.value_lock = Lock()
57 63 self.options_lock = Lock()
58 64 self.equals = kwargs.pop('equals', lambda x, y: x == y)
59 65 self.on_trait_change(self._options_readonly_changed, ['_options_dict', '_options_labels', '_options_values', '_options'])
60 66 if 'options' in kwargs:
61 67 self.options = kwargs.pop('options')
62 68 DOMWidget.__init__(self, *args, **kwargs)
63 69 self._value_in_options()
64 70
65 71 def _make_options(self, x):
66 72 # If x is a dict, convert it to list format.
67 73 if isinstance(x, (OrderedDict, dict)):
68 74 return [(k, v) for k, v in x.items()]
69 75
70 76 # Make sure x is a list or tuple.
71 77 if not isinstance(x, (list, tuple)):
72 78 raise ValueError('x')
73 79
74 80 # If x is an ordinary list, use the option values as names.
75 81 for y in x:
76 82 if not isinstance(y, (list, tuple)) or len(y) < 2:
77 83 return [(i, i) for i in x]
78 84
79 85 # Value is already in the correct format.
80 86 return x
81 87
82 88 def _options_changed(self, name, old, new):
83 89 """Handles when the options tuple has been changed.
84 90
85 91 Setting options implies setting option labels from the keys of the dict.
86 92 """
87 93 if self.options_lock.acquire(False):
88 94 try:
89 95 self.options = new
90 96
91 97 options = self._make_options(new)
92 98 self._options_dict = {i[0]: i[1] for i in options}
93 99 self._options_labels = [i[0] for i in options]
94 100 self._options_values = [i[1] for i in options]
95 101 self._value_in_options()
96 102 finally:
97 103 self.options_lock.release()
98 104
99 105 def _value_in_options(self):
100 106 # ensure that the chosen value is one of the choices
101 107
102 108 if self._options_values:
103 109 if self.value not in self._options_values:
104 110 self.value = next(iter(self._options_values))
105 111
106 112 def _options_readonly_changed(self, name, old, new):
107 113 if not self.options_lock.locked():
108 114 raise TraitError("`.%s` is a read-only trait. Use the `.options` tuple instead." % name)
109 115
110 116 def _value_changed(self, name, old, new):
111 117 """Called when value has been changed"""
112 118 if self.value_lock.acquire(False):
113 119 try:
114 120 # Reverse dictionary lookup for the value name
115 121 for k, v in self._options_dict.items():
116 122 if self.equals(new, v):
117 123 # set the selected value name
118 124 self.selected_label = k
119 125 return
120 126 # undo the change, and raise KeyError
121 127 self.value = old
122 128 raise KeyError(new)
123 129 finally:
124 130 self.value_lock.release()
125 131
126 132 def _selected_label_changed(self, name, old, new):
127 133 """Called when the value name has been changed (typically by the frontend)."""
128 134 if self.value_lock.acquire(False):
129 135 try:
130 136 self.value = self._options_dict[new]
131 137 finally:
132 138 self.value_lock.release()
133 139
134 140
135 141 class _MultipleSelection(_Selection):
136 142 """Base class for MultipleSelection widgets.
137 143
138 144 As with ``_Selection``, ``options`` can be specified as a list or dict. If
139 145 given as a list, it will be transformed to a dict of the form
140 146 ``{str(value): value}``.
141 147
142 148 Despite their names, ``value`` (and ``selected_label``) will be tuples, even
143 149 if only a single option is selected.
144 150 """
145 151
146 152 value = Tuple(help="Selected values")
147 153 selected_labels = Tuple(help="The labels of the selected options",
148 154 sync=True)
149 155
150 156 @property
151 157 def selected_label(self):
152 158 raise AttributeError(
153 159 "Does not support selected_label, use selected_labels")
154 160
155 161 def _value_in_options(self):
156 162 # ensure that the chosen value is one of the choices
157 163 if self.options:
158 164 old_value = self.value or []
159 165 new_value = []
160 166 for value in old_value:
161 167 if value in self._options_dict.values():
162 168 new_value.append(value)
163 169 if new_value:
164 170 self.value = new_value
165 171 else:
166 172 self.value = [next(iter(self._options_dict.values()))]
167 173
168 174 def _value_changed(self, name, old, new):
169 175 """Called when value has been changed"""
170 176 if self.value_lock.acquire(False):
171 177 try:
172 178 self.selected_labels = [
173 179 self._options_labels[self._options_values.index(v)]
174 180 for v in new
175 181 ]
176 182 except:
177 183 self.value = old
178 184 raise KeyError(new)
179 185 finally:
180 186 self.value_lock.release()
181 187
182 188 def _selected_labels_changed(self, name, old, new):
183 189 """Called when the selected label has been changed (typically by the
184 190 frontend)."""
185 191 if self.value_lock.acquire(False):
186 192 try:
187 193 self.value = [self._options_dict[name] for name in new]
188 194 finally:
189 195 self.value_lock.release()
190 196
191 197
192 198 @register('IPython.ToggleButtons')
193 199 class ToggleButtons(_Selection):
194 200 """Group of toggle buttons that represent an enumeration. Only one toggle
195 201 button can be toggled at any point in time."""
196 202 _view_name = Unicode('ToggleButtonsView', sync=True)
203 tooltips = List(Unicode(), sync=True)
204 icons = List(Unicode(), sync=True)
197 205
198 206 button_style = CaselessStrEnum(
199 207 values=['primary', 'success', 'info', 'warning', 'danger', ''],
200 208 default_value='', allow_none=True, sync=True, help="""Use a
201 209 predefined styling for the buttons.""")
202 210
203 211 @register('IPython.Dropdown')
204 212 class Dropdown(_Selection):
205 213 """Allows you to select a single item from a dropdown."""
206 214 _view_name = Unicode('DropdownView', sync=True)
207 215
208 216 button_style = CaselessStrEnum(
209 217 values=['primary', 'success', 'info', 'warning', 'danger', ''],
210 218 default_value='', allow_none=True, sync=True, help="""Use a
211 219 predefined styling for the buttons.""")
212 220
213 221 @register('IPython.RadioButtons')
214 222 class RadioButtons(_Selection):
215 223 """Group of radio buttons that represent an enumeration. Only one radio
216 224 button can be toggled at any point in time."""
217 225 _view_name = Unicode('RadioButtonsView', sync=True)
218 226
219 227
220 228
221 229 @register('IPython.Select')
222 230 class Select(_Selection):
223 231 """Listbox that only allows one item to be selected at any given time."""
224 232 _view_name = Unicode('SelectView', sync=True)
225 233
226 234
227 235 @register('IPython.SelectMultiple')
228 236 class SelectMultiple(_MultipleSelection):
229 237 """Listbox that allows many items to be selected at any given time.
230 238 Despite their names, inherited from ``_Selection``, the currently chosen
231 239 option values, ``value``, or their labels, ``selected_labels`` must both be
232 240 updated with a list-like object."""
233 241 _view_name = Unicode('SelectMultipleView', sync=True)
234 242
235 243
236 244 # Remove in IPython 4.0
237 245 ToggleButtonsWidget = DeprecatedClass(ToggleButtons, 'ToggleButtonsWidget')
238 246 DropdownWidget = DeprecatedClass(Dropdown, 'DropdownWidget')
239 247 RadioButtonsWidget = DeprecatedClass(RadioButtons, 'RadioButtonsWidget')
240 248 SelectWidget = DeprecatedClass(Select, 'SelectWidget')
General Comments 0
You need to be logged in to leave comments. Login now