##// END OF EJS Templates
Intermediate changes to javascript side of backbone widgets
Jason Grout -
Show More
@@ -46,9 +46,9 b''
46 46 WidgetManager.prototype.attach_comm_manager = function (comm_manager) {
47 47 this.comm_manager = comm_manager;
48 48
49 // Register already register widget model types with the comm manager.
49 // Register already-registered widget model types with the comm manager.
50 50 for (var widget_model_name in this.widget_model_types) {
51 this.comm_manager.register_target(widget_model_name, $.proxy(this._handle_com_open, this));
51 this.comm_manager.register_target(widget_model_name, $.proxy(this._handle_comm_open, this));
52 52 }
53 53 };
54 54
@@ -57,7 +57,7 b''
57 57 // Register the widget with the comm manager. Make sure to pass this object's context
58 58 // in so `this` works in the call back.
59 59 if (this.comm_manager !== null) {
60 this.comm_manager.register_target(widget_model_name, $.proxy(this._handle_com_open, this));
60 this.comm_manager.register_target(widget_model_name, $.proxy(this._handle_comm_open, this));
61 61 }
62 62 this.widget_model_types[widget_model_name] = widget_model_type;
63 63 };
@@ -66,12 +66,97 b''
66 66 WidgetManager.prototype.register_widget_view = function (widget_view_name, widget_view_type) {
67 67 this.widget_view_types[widget_view_name] = widget_view_type;
68 68 };
69
69 WidgetManager.prototype.handle_msg = function(msg, model) {
70 var method = msg.content.data.method;
71 switch (method) {
72 case 'display':
73 var cell = this.get_msg_cell(msg.parent_header.msg_id);
74 if (cell === null) {
75 console.log("Could not determine where the display" +
76 " message was from. Widget will not be displayed");
77 } else {
78 var view = this.create_view(model,
79 msg.content.data.view_name, cell);
80 if (view !== undefined
81 && cell.widget_subarea !== undefined
82 && cell.widget_subarea !== null) {
83 cell.widget_area.show();
84 cell.widget_subarea.append(view.$el);
85 }
86 }
87 break;
88 case 'set_snapshot':
89 var cell = this.get_msg_cell(msg.parent_header.msg_id);
90 cell.metadata.snapshot = msg.content.data.snapshot;
91 break;
92 }
93 }
94
95 WidgetManager.prototype.create_view = function(model, view_name, cell) {
96 view_name = view_name || model.get('default_view_name');
97 var ViewType = this.widget_view_types[view_name];
98 if (ViewType !== undefined && ViewType !== null) {
99 var view = new ViewType({model: model, widget_manager: this, cell: cell});
100 view.render();
101 //this.views.push(view);
102
103 /*
104 // jng: Handle when the view element is remove from the page.
105 // observe the view destruction event and do this. We may need
106 // to override the view's remove method to trigger this event.
107 var that = this;
108 view.$el.on("remove", function () {
109 var index = that.views.indexOf(view);
110 if (index > -1) {
111 that.views.splice(index, 1);
112 }
113 view.remove(); // Clean-up view
114
115 // Close the comm if there are no views left.
116 if (that.views.length() === 0) {
117 //jng: trigger comm close event
118 }
119
120
121 if (that.comm !== undefined) {
122 that.comm.close();
123 delete that.comm.model; // Delete ref so GC will collect widget model.
124 delete that.comm;
125 }
126 delete that.widget_id; // Delete id from model so widget manager cleans up.
127 });
128 */
129 return view;
130 }
131 },
70 132
71 133 WidgetManager.prototype.get_msg_cell = function (msg_id) {
134 var cell = null;
135 // First, check to see if the msg was triggered by cell execution.
72 136 if (IPython.notebook !== undefined && IPython.notebook !== null) {
73 return IPython.notebook.get_msg_cell(msg_id);
137 cell = IPython.notebook.get_msg_cell(msg_id);
138 }
139 if (cell !== null) {
140 return cell
141 }
142 // Second, check to see if a get_cell callback was defined
143 // for the message. get_cell callbacks are registered for
144 // widget messages, so this block is actually checking to see if the
145 // message was triggered by a widget.
146 var kernel = this.get_kernel();
147 if (kernel !== undefined && kernel !== null) {
148 var callbacks = kernel.get_callbacks_for_msg(msg_id);
149 if (callbacks !== undefined &&
150 callbacks.iopub !== undefined &&
151 callbacks.iopub.get_cell !== undefined) {
152
153 return callbacks.iopub.get_cell();
154 }
74 155 }
156
157 // Not triggered by a cell or widget (no get_cell callback
158 // exists).
159 return null;
75 160 };
76 161
77 162
@@ -109,7 +194,7 b''
109 194 };
110 195
111 196
112 WidgetManager.prototype._handle_com_open = function (comm, msg) {
197 WidgetManager.prototype._handle_comm_open = function (comm, msg) {
113 198 var widget_type_name = msg.content.target_name;
114 199 var widget_model = new this.widget_model_types[widget_type_name](this, comm.comm_id, comm);
115 200 this._model_instances[comm.comm_id] = widget_model;
@@ -126,4 +211,4 b''
126 211
127 212 return IPython.widget_manager;
128 213 });
129 }()); No newline at end of file
214 }());
@@ -28,17 +28,15 b' function(widget_manager, underscore, backbone){'
28 28 this.pending_msgs = 0;
29 29 this.msg_throttle = 3;
30 30 this.msg_buffer = null;
31 this.views = [];
32 31 this.id = widget_id;
33 this._custom_msg_callbacks = [];
34 32
35 33 if (comm !== undefined) {
36
37 34 // Remember comm associated with the model.
38 35 this.comm = comm;
39 36 comm.model = this;
40 37
41 38 // Hook comm messages up to model.
39 var that = this;
42 40 comm.on_close($.proxy(this._handle_comm_closed, this));
43 41 comm.on_msg($.proxy(this._handle_comm_msg, this));
44 42 }
@@ -47,68 +45,18 b' function(widget_manager, underscore, backbone){'
47 45 },
48 46
49 47
50 send: function (content, cell) {
51 if (this._has_comm()) {
52 // Used the last modified view as the sender of the message. This
53 // will insure that any python code triggered by the sent message
54 // can create and display widgets and output.
55 if (cell === undefined) {
56 if (this.last_modified_view !== undefined &&
57 this.last_modified_view.cell !== undefined) {
58 cell = this.last_modified_view.cell;
59 }
60 }
61 var callbacks = this._make_callbacks(cell);
48 send: function (content, callbacks) {
49 console.log('send',content, callbacks);
50 if (this.comm !== undefined) {
62 51 var data = {method: 'custom', custom_content: content};
63
64 52 this.comm.send(data, callbacks);
65 53 }
66 54 },
67 55
68
69 on_view_created: function (callback) {
70 this._view_created_callback = callback;
71 },
72
73
74 on_close: function (callback) {
75 this._close_callback = callback;
76 },
77
78
79 on_msg: function (callback, remove) {
80 if (remove) {
81 var found_index = -1;
82 for (var index in this._custom_msg_callbacks) {
83 if (callback === this._custom_msg_callbacks[index]) {
84 found_index = index;
85 break;
86 }
87 }
88
89 if (found_index >= 0) {
90 this._custom_msg_callbacks.splice(found_index, 1);
91 }
92 } else {
93 this._custom_msg_callbacks.push(callback);
94 }
95 },
96
97
98 _handle_custom_msg: function (content) {
99 for (var index in this._custom_msg_callbacks) {
100 try {
101 this._custom_msg_callbacks[index](content);
102 } catch (e) {
103 console.log("Exception in widget model msg callback", e, content);
104 }
105 }
106 },
107
108
109 56 // Handle when a widget is closed.
110 57 _handle_comm_closed: function (msg) {
111 this._execute_views_method('remove');
58 // jng: widget manager should observe the comm_close event and delete views when triggered
59 this.trigger('comm:close');
112 60 if (this._has_comm()) {
113 61 delete this.comm.model; // Delete ref so GC will collect widget model.
114 62 delete this.comm;
@@ -117,43 +65,19 b' function(widget_manager, underscore, backbone){'
117 65 },
118 66
119 67
120 // Handle incomming comm msg.
68 // Handle incoming comm msg.
121 69 _handle_comm_msg: function (msg) {
122 70 var method = msg.content.data.method;
123 71 switch (method) {
124 case 'display':
125
126 // Try to get the cell.
127 var cell = this._get_msg_cell(msg.parent_header.msg_id);
128 if (cell === null) {
129 console.log("Could not determine where the display" +
130 " message was from. Widget will not be displayed");
131 } else {
132 this.create_views(msg.content.data.view_name,
133 msg.content.data.parent,
134 cell);
135 }
136 break;
137 72 case 'update':
138 73 this.apply_update(msg.content.data.state);
139 74 break;
140 case 'add_class':
141 case 'remove_class':
142 var selector = msg.content.data.selector;
143 if (selector === undefined) {
144 selector = '';
145 }
146
147 var class_list = msg.content.data.class_list;
148 this._execute_views_method(method, selector, class_list);
149 break;
150 case 'set_snapshot':
151 var cell = this._get_msg_cell(msg.parent_header.msg_id);
152 cell.metadata.snapshot = msg.content.data.snapshot;
153 break;
154 75 case 'custom':
155 this._handle_custom_msg(msg.content.data.custom_content);
76 this.trigger('msg:custom', msg.content.data.custom_content);
156 77 break;
78 default:
79 // pass on to widget manager
80 this.widget_manager.handle_msg(msg, this);
157 81 }
158 82 },
159 83
@@ -164,18 +88,7 b' function(widget_manager, underscore, backbone){'
164 88 try {
165 89 for (var key in state) {
166 90 if (state.hasOwnProperty(key)) {
167 if (key == "_css") {
168
169 // Set the css value of the model as an attribute
170 // instead of a backbone trait because we are only
171 // interested in backend css -> frontend css. In
172 // other words, if the css dict changes in the
173 // frontend, we don't need to push the changes to
174 // the backend.
175 this.css = state[key];
176 } else {
177 this.set(key, state[key]);
178 }
91 this.set(key, state[key]);
179 92 }
180 93 }
181 94 this.save();
@@ -185,17 +98,15 b' function(widget_manager, underscore, backbone){'
185 98 },
186 99
187 100
188 _handle_status: function (cell, msg) {
101 _handle_status: function (msg, callbacks) {
189 102 //execution_state : ('busy', 'idle', 'starting')
190 if (this._has_comm()) {
191 if (msg.content.execution_state=='idle') {
103 if (this.comm !== undefined) {
104 if (msg.content.execution_state ==='idle') {
192 105
193 106 // Send buffer if this message caused another message to be
194 107 // throttled.
195 108 if (this.msg_buffer !== null &&
196 this.msg_throttle == this.pending_msgs) {
197
198 var callbacks = this._make_callbacks(cell);
109 this.msg_throttle === this.pending_msgs) {
199 110 var data = {method: 'backbone', sync_method: 'update', sync_data: this.msg_buffer};
200 111 this.comm.send(data, callbacks);
201 112 this.msg_buffer = null;
@@ -217,7 +128,7 b' function(widget_manager, underscore, backbone){'
217 128
218 129 // Only send updated state if the state hasn't been changed
219 130 // during an update.
220 if (this._has_comm()) {
131 if (this.comm !== undefined) {
221 132 if (!this.updating) {
222 133 if (this.pending_msgs >= this.msg_throttle) {
223 134 // The throttle has been exceeded, buffer the current msg so
@@ -247,14 +158,7 b' function(widget_manager, underscore, backbone){'
247 158 }
248 159
249 160 var data = {method: 'backbone', sync_method: method, sync_data: send_json};
250
251 var cell = null;
252 if (this.last_modified_view !== undefined && this.last_modified_view !== null) {
253 cell = this.last_modified_view.cell;
254 }
255
256 var callbacks = this._make_callbacks(cell);
257 this.comm.send(data, callbacks);
161 this.comm.send(data, this.cell_callbacks());
258 162 this.pending_msgs++;
259 163 }
260 164 }
@@ -265,133 +169,22 b' function(widget_manager, underscore, backbone){'
265 169 return model_json;
266 170 },
267 171
268
269 _handle_view_created: function (view) {
270 if (this._view_created_callback) {
271 try {
272 this._view_created_callback(view);
273 } catch (e) {
274 console.log("Exception in widget model view displayed callback", e, view, this);
275 }
276 }
277 },
278
279
280 _execute_views_method: function (/* method_name, [argument0], [argument1], [...] */) {
281 var method_name = arguments[0];
282 var args = null;
283 if (arguments.length > 1) {
284 args = [].splice.call(arguments,1);
285 }
286
287 for (var view_index in this.views) {
288 var view = this.views[view_index];
289 var method = view[method_name];
290 if (args === null) {
291 method.apply(view);
292 } else {
293 method.apply(view, args);
294 }
295 }
296 },
297
298
299 // Create view that represents the model.
300 create_views: function (view_name, parent_id, cell) {
301 var new_views = [];
302 var view;
303
304 // Try creating and adding the view to it's parent.
305 var displayed = false;
306 if (parent_id !== undefined) {
307 var parent_model = this.widget_manager.get_model(parent_id);
308 if (parent_model !== null) {
309 var parent_views = parent_model.views;
310 for (var parent_view_index in parent_views) {
311 var parent_view = parent_views[parent_view_index];
312 if (parent_view.cell === cell) {
313 if (parent_view.display_child !== undefined) {
314 view = this._create_view(view_name, cell);
315 if (view !== null) {
316 new_views.push(view);
317 parent_view.display_child(view);
318 displayed = true;
319 this._handle_view_created(view);
320 }
321 }
322 }
323 }
324 }
325 }
326
327 // If no parent view is defined or exists. Add the view's
328 // element to cell's widget div.
329 if (!displayed) {
330 view = this._create_view(view_name, cell);
331 if (view !== null) {
332 new_views.push(view);
333
334 if (cell.widget_subarea !== undefined && cell.widget_subarea !== null) {
335 cell.widget_area.show();
336 cell.widget_subarea.append(view.$el);
337 this._handle_view_created(view);
338 }
339 }
340 }
341
342 // Force the new view(s) to update their selves
343 for (var view_index in new_views) {
344 view = new_views[view_index];
345 view.update();
346 }
347 },
348
349
350 // Create a view
351 _create_view: function (view_name, cell) {
352 var ViewType = this.widget_manager.widget_view_types[view_name];
353 if (ViewType !== undefined && ViewType !== null) {
354 var view = new ViewType({model: this});
355 view.render();
356 this.views.push(view);
357 view.cell = cell;
358
359 // Handle when the view element is remove from the page.
360 var that = this;
361 view.$el.on("remove", function () {
362 var index = that.views.indexOf(view);
363 if (index > -1) {
364 that.views.splice(index, 1);
365 }
366 view.remove(); // Clean-up view
367
368 // Close the comm if there are no views left.
369 if (that.views.length() === 0) {
370 if (that._close_callback) {
371 try {
372 that._close_callback(that);
373 } catch (e) {
374 console.log("Exception in widget model close callback", e, that);
375 }
376 }
377
378 if (that._has_comm()) {
379 that.comm.close();
380 delete that.comm.model; // Delete ref so GC will collect widget model.
381 delete that.comm;
382 }
383 delete that.widget_id; // Delete id from model so widget manager cleans up.
384 }
385 });
386 return view;
387 }
388 return null;
389 },
390
391
392 172 // Build a callback dict.
393 _make_callbacks: function (cell) {
173 cell_callbacks: function (cell) {
394 174 var callbacks = {};
175 console.log('cell_callbacks A', cell);
176 if (cell === undefined) {
177 // Used the last modified view as the sender of the message. This
178 // will insure that any python code triggered by the sent message
179 // can create and display widgets and output.
180 if (this.last_modified_view !== undefined &&
181 this.last_modified_view.cell !== undefined) {
182 cell = this.last_modified_view.cell;
183 } else {
184 cell = null;
185 }
186 }
187 console.log('cell_callbacks B', cell);
395 188 if (cell !== null) {
396 189
397 190 // Try to get output handlers
@@ -402,7 +195,7 b' function(widget_manager, underscore, backbone){'
402 195 handle_clear_output = $.proxy(cell.output_area.handle_clear_output, cell.output_area);
403 196 }
404 197
405 // Create callback dict usign what is known
198 // Create callback dict using what is known
406 199 var that = this;
407 200 callbacks = {
408 201 iopub : {
@@ -410,7 +203,7 b' function(widget_manager, underscore, backbone){'
410 203 clear_output : handle_clear_output,
411 204
412 205 status : function (msg) {
413 that._handle_status(cell, msg);
206 that._handle_status(msg, that.cell_callbacks(cell));
414 207 },
415 208
416 209 // Special function only registered by widget messages.
@@ -422,57 +215,86 b' function(widget_manager, underscore, backbone){'
422 215 },
423 216 };
424 217 }
218 console.log('constructed callbacks for',cell);
425 219 return callbacks;
426 220 },
221 });
427 222
428 223
429 // Get the output area corresponding to the msg_id.
430 // cell is an instance of IPython.Cell
431 _get_msg_cell: function (msg_id) {
432
433 // First, check to see if the msg was triggered by cell execution.
434 var cell = this.widget_manager.get_msg_cell(msg_id);
435 if (cell !== null) {
436 return cell;
437 }
224 //--------------------------------------------------------------------
225 // WidgetView class
226 //--------------------------------------------------------------------
227 var BaseWidgetView = Backbone.View.extend({
228 initialize: function(options) {
229 this.model.on('change',this.update,this);
230 this.widget_manager = options.widget_manager;
231 this.comm_manager = options.widget_manager.comm_manager;
232 this.cell = options.cell
233 this.render();
234 // jng: maybe the following shouldn't be automatic---maybe the render method should take
235 // care of knowing what needs to be added as a child?
236 var children_attr = this.model.get('_children_attr');
237 for (var i in children_attr) {
238 var child_attr = children_attr[i];
239 var child_model = this.comm_manager.comms[this.model.get(child_attr)].model;
240 var child_view_name = this.child_view_name(child_attr, child_model);
241 var child_view = this.widget_manager.create_view(child_model, child_view_name, this.cell);
242 this.add_child_view(child_attr, child_view);
243 }
244 var children_lists_attr = this.model.get('_children_lists_attr')
245 for (var i in children_lists_attr) {
246 var child_attr = children_lists_attr[i];
247 var child_list = this.model.get(child_attr);
248 for (var j in child_list) {
249 var child_model = this.comm_manager.comms[child_list[j]].model;
250 var child_view_name = this.child_view_name(child_attr, child_model);
251 var child_view = this.widget_manager.create_view(child_model, child_view_name, this.cell);
252 this.add_child_view(child_attr, child_view);
253 }
254 }
255 },
256 update: function(){
257 // update thyself to be consistent with this.model
258 },
259
260 child_view: function(attr, viewname) {
261 var child_model = this.comm_manager.comms[this.model.get(attr)].model;
262 var child_view = this.widget_manager.create_view(child_model, view_name, this.cell);
263 return child_view;
264 },
265
266 render: function(){
267 // render thyself
268 },
269 child_view_name: function(attr, model) {
270 // attr is the name of the attribute we are constructing a view for
271 // model is the model stored in that attribute
272 // return a valid view_name to construct a view of that type
273 // or null for the default view for the model
274 return null;
275 },
276 add_child_view: function(attr, view) {
277 //attr is the name of the attribute containing a reference to this child
278 //view is the child view that has been constructed
279 //typically this will just add the child view's view.el attribute to some dom element
280 },
281
282 send: function (content) {
283 this.model.send(content, this.model.cell_callbacks(this.cell));
284 },
438 285
439 // Second, check to see if a get_cell callback was defined
440 // for the message. get_cell callbacks are registered for
441 // widget messages, so this block is actually checking to see if the
442 // message was triggered by a widget.
443 var kernel = this.widget_manager.get_kernel();
444 if (kernel !== undefined && kernel !== null) {
445 var callbacks = kernel.get_callbacks_for_msg(msg_id);
446 if (callbacks !== undefined &&
447 callbacks.iopub !== undefined &&
448 callbacks.iopub.get_cell !== undefined) {
449
450 return callbacks.iopub.get_cell();
451 }
452 }
453
454 // Not triggered by a cell or widget (no get_cell callback
455 // exists).
456 return null;
286 touch: function () {
287 this.model.last_modified_view = this;
288 this.model.save(this.model.changedAttributes(), {patch: true});
457 289 },
458 290
459 291
460 // Function that checks if a comm has been attached to this widget
461 // model. Returns True if a valid comm is attached.
462 _has_comm: function() {
463 return this.comm !== undefined && this.comm !== null;
464 },
465 292 });
466 293
467
468 //--------------------------------------------------------------------
469 // WidgetView class
470 //--------------------------------------------------------------------
471 var WidgetView = Backbone.View.extend({
472
473 initialize: function () {
294 var WidgetView = BaseWidgetView.extend({
295 initialize: function (options) {
474 296 this.visible = true;
475 this.model.on('sync',this.update,this);
297 BaseWidgetView.prototype.initialize.apply(this, arguments);
476 298 },
477 299
478 300 add_class: function (selector, class_list) {
@@ -489,27 +311,12 b' function(widget_manager, underscore, backbone){'
489 311 }
490 312 },
491 313
492
493 send: function (content) {
494 this.model.send(content, this.cell);
495 },
496
497
498 touch: function () {
499 this.model.last_modified_view = this;
500 this.model.save(this.model.changedAttributes(), {patch: true});
501 },
502
503 314 update: function () {
504 if (this.model.get('visible') !== undefined) {
505 if (this.visible != this.model.get('visible')) {
506 this.visible = this.model.get('visible');
507 if (this.visible) {
508 this.$el.show();
509 } else {
510 this.$el.hide();
511 }
512 }
315 // jng: hook into change:visible trigger
316 var visible = this.model.get('visible');
317 if (visible !== undefined && this.visible !== visible) {
318 this.visible = visible;
319 this.$el.toggle(visible)
513 320 }
514 321
515 322 if (this.model.css !== undefined) {
@@ -552,4 +359,4 b' function(widget_manager, underscore, backbone){'
552 359 IPython.WidgetView = WidgetView;
553 360
554 361 return widget_manager;
555 }); No newline at end of file
362 });
@@ -52,16 +52,21 b' define(["notebook/js/widgets/base"], function(widget_manager) {'
52 52 render: function(){
53 53 this.$el
54 54 .addClass('widget-container');
55 var children = this.model.get('children')
56 for(var i in this.model.get('children')) {
57
58 this.update()
55 59 },
56 60
57 61 update: function(){
58 62 set_flex_properties(this, this.$el);
59 63 return IPython.WidgetView.prototype.update.call(this);
60 64 },
61
62 display_child: function(view) {
63 this.$el.append(view.$el);
64 },
65 add_child_view: function(attr, view) {
66 if (attr==='children') {
67 this.$el.append(view.$el);
68 }
69 }
65 70 });
66 71
67 72 widget_manager.register_widget_view('ContainerView', ContainerView);
@@ -229,8 +234,10 b' define(["notebook/js/widgets/base"], function(widget_manager) {'
229 234 return IPython.WidgetView.prototype.update.call(this);
230 235 },
231 236
232 display_child: function(view) {
233 this.$body.append(view.$el);
237 add_child_view: function(attr, view) {
238 if (attr==='children') {
239 this.$body.append(view.$el);
240 }
234 241 },
235 242
236 243 _get_selector_element: function(selector) {
@@ -70,6 +70,7 b' define(["notebook/js/widgets/base"], function(widget_manager){'
70 70 this.$slider.slider('option', 'orientation', orientation);
71 71 value = this.model.get('value');
72 72 this.$slider.slider('option', 'value', value);
73 console.log('updating value',value)
73 74
74 75 // Use the right CSS classes for vertical & horizontal sliders
75 76 if (orientation=='vertical') {
@@ -109,6 +110,7 b' define(["notebook/js/widgets/base"], function(widget_manager){'
109 110 events: { "slide" : "handleSliderChange" },
110 111 handleSliderChange: function(e, ui) {
111 112 this.model.set('value', ui.value);
113 console.log('triggered value change', ui.value, this.model);
112 114 this.touch();
113 115 },
114 116 });
@@ -27,7 +27,6 b' define(["notebook/js/widgets/base"], function(widget_manager){'
27 27 .addClass('accordion');
28 28 this.containers = [];
29 29 },
30
31 30 update: function() {
32 31 // Set tab titles
33 32 var titles = this.model.get('_titles');
@@ -58,7 +57,7 b' define(["notebook/js/widgets/base"], function(widget_manager){'
58 57 return IPython.WidgetView.prototype.update.call(this);
59 58 },
60 59
61 display_child: function(view) {
60 add_child_view: function(attr, view) {
62 61
63 62 var index = this.containers.length;
64 63 var uuid = IPython.utils.uuid();
@@ -103,7 +102,13 b' define(["notebook/js/widgets/base"], function(widget_manager){'
103 102
104 103 var TabView = IPython.WidgetView.extend({
105 104
105 initialize: function() {
106 this.containers = [];
107 IPython.WidgetView.prototype.initialize.apply(this, arguments);
108 },
109
106 110 render: function(){
111 console.log('rendering tabs', this);
107 112 var uuid = 'tabs'+IPython.utils.uuid();
108 113 var that = this;
109 114 this.$tabs = $('<div />', {id: uuid})
@@ -113,8 +118,7 b' define(["notebook/js/widgets/base"], function(widget_manager){'
113 118 this.$tab_contents = $('<div />', {id: uuid + 'Content'})
114 119 .addClass('tab-content')
115 120 .appendTo(this.$el);
116
117 this.containers = [];
121 this.update();
118 122 },
119 123
120 124 update: function() {
@@ -135,8 +139,8 b' define(["notebook/js/widgets/base"], function(widget_manager){'
135 139 return IPython.WidgetView.prototype.update.call(this);
136 140 },
137 141
138 display_child: function(view) {
139
142 add_child_view: function(attr, view) {
143 console.log('adding child view', attr, view);
140 144 var index = this.containers.length;
141 145 var uuid = IPython.utils.uuid();
142 146
@@ -86,7 +86,7 b' var IPython = (function (IPython) {'
86 86 try {
87 87 f(comm, msg);
88 88 } catch (e) {
89 console.log("Exception opening new comm:", e, msg);
89 console.log("Exception opening new comm:", e, e.stack, msg);
90 90 comm.close();
91 91 this.unregister_comm(comm);
92 92 }
@@ -102,7 +102,7 b' var IPython = (function (IPython) {'
102 102 try {
103 103 comm.handle_close(msg);
104 104 } catch (e) {
105 console.log("Exception closing comm: ", e, msg);
105 console.log("Exception closing comm: ", e, e.stack, msg);
106 106 }
107 107 };
108 108
@@ -115,7 +115,7 b' var IPython = (function (IPython) {'
115 115 try {
116 116 comm.handle_msg(msg);
117 117 } catch (e) {
118 console.log("Exception handling comm msg: ", e, msg);
118 console.log("Exception handling comm msg: ", e, e.stack, msg);
119 119 }
120 120 };
121 121
@@ -176,7 +176,7 b' var IPython = (function (IPython) {'
176 176 try {
177 177 callback(msg);
178 178 } catch (e) {
179 console.log("Exception in Comm callback", e, msg);
179 console.log("Exception in Comm callback", e, e.stack, msg);
180 180 }
181 181 }
182 182 };
@@ -34,9 +34,13 b' from IPython.utils.py3compat import string_types'
34 34 class BaseWidget(LoggingConfigurable):
35 35
36 36 # Shared declarations (Class level)
37 _keys = List(Unicode, help="List of keys comprising the state of the model.")
38 _children_attr = List(Unicode, help="List of keys of children objects of the model.")
39 _children_lists_attr = List(Unicode, help="List of keys containing lists of children objects of the model.")
37 _keys = List(Unicode, default_value = [],
38 help="List of keys comprising the state of the model.", allow_none=False)
39 _children_attr = List(Unicode, default_value = [],
40 help="List of keys of children objects of the model.", allow_none=False)
41 _children_lists_attr = List(Unicode, default_value = [],
42 help="List of keys containing lists of children objects of the model.",
43 allow_none=False)
40 44 widget_construction_callback = None
41 45
42 46 def on_widget_constructed(callback):
@@ -59,9 +63,10 b' class BaseWidget(LoggingConfigurable):'
59 63 to use to represent the widget.""")
60 64
61 65 # Private/protected declarations
66 # todo: change this to a context manager
62 67 _property_lock = (None, None) # Last updated (key, value) from the front-end. Prevents echo.
63 68 _displayed = False
64 _comm = None
69 _comm = Instance('IPython.kernel.comm.Comm')
65 70
66 71 def __init__(self, **kwargs):
67 72 """Public constructor
@@ -72,6 +77,7 b' class BaseWidget(LoggingConfigurable):'
72 77
73 78 # Register after init to allow default values to be specified
74 79 # TODO: register three different handlers, one for each list, and abstract out the common parts
80 #print self.keys, self._children_attr, self._children_lists_attr
75 81 self.on_trait_change(self._handle_property_changed, self.keys+self._children_attr+self._children_lists_attr)
76 82 Widget._handle_widget_constructed(self)
77 83
@@ -90,7 +96,7 b' class BaseWidget(LoggingConfigurable):'
90 96 # Properties
91 97 @property
92 98 def keys(self):
93 keys = ['_children_attr', '_children_lists_attr']
99 keys = ['_children_attr', '_children_lists_attr', 'default_view_name']
94 100 keys.extend(self._keys)
95 101 return keys
96 102
@@ -118,7 +124,6 b' class BaseWidget(LoggingConfigurable):'
118 124 if 'custom_content' in data:
119 125 self._handle_custom_msg(data['custom_content'])
120 126
121
122 127 def _handle_custom_msg(self, content):
123 128 """Called when a custom msg is recieved."""
124 129 for handler in self._msg_callbacks:
@@ -153,7 +158,7 b' class BaseWidget(LoggingConfigurable):'
153 158
154 159
155 160 def _handle_property_changed(self, name, old, new):
156 """Called when a proeprty has been changed."""
161 """Called when a property has been changed."""
157 162 # Make sure this isn't information that the front-end just sent us.
158 163 if self._property_lock[0] != name and self._property_lock[1] != new:
159 164 # Send new state to frontend
@@ -197,7 +202,7 b' class BaseWidget(LoggingConfigurable):'
197 202 self._send({"method": "update",
198 203 "state": self.get_state()})
199 204
200 def get_state(self, key=None)
205 def get_state(self, key=None):
201 206 """Gets the widget state, or a piece of it.
202 207
203 208 Parameters
@@ -308,15 +313,18 b' class BaseWidget(LoggingConfigurable):'
308 313 def _open_communication(self):
309 314 """Opens a communication with the front-end."""
310 315 # Create a comm.
311 if not hasattr(self, '_comm') or self._comm is None:
316 if self._comm is None:
312 317 self._comm = Comm(target_name=self.target_name)
313 318 self._comm.on_msg(self._handle_msg)
314 319 self._comm.on_close(self._close_communication)
315 320
321 # first update
322 self.send_state()
323
316 324
317 325 def _close_communication(self):
318 326 """Closes a communication with the front-end."""
319 if hasattr(self, '_comm') and self._comm is not None:
327 if self._comm is not None:
320 328 try:
321 329 self._comm.close()
322 330 finally:
@@ -332,9 +340,6 b' class BaseWidget(LoggingConfigurable):'
332 340 return False
333 341
334 342 class Widget(BaseWidget):
335
336 _children = List(Instance('IPython.html.widgets.widget.Widget'))
337 _children_lists_attr = List(Unicode, ['_children'])
338 343 visible = Bool(True, help="Whether or not the widget is visible.")
339 344
340 345 # Private/protected declarations
@@ -59,7 +59,7 b' class ButtonWidget(Widget):'
59 59
60 60
61 61 def _handle_button_msg(self, content):
62 """Hanlde a msg from the front-end
62 """Handle a msg from the front-end
63 63
64 64 Parameters
65 65 ----------
@@ -14,7 +14,7 b' Represents a container that can be used to group other widgets.'
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16 from .widget import Widget
17 from IPython.utils.traitlets import Unicode, Bool
17 from IPython.utils.traitlets import Unicode, Bool, List, Instance
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Classes
@@ -23,6 +23,9 b' class ContainerWidget(Widget):'
23 23 target_name = Unicode('ContainerWidgetModel')
24 24 default_view_name = Unicode('ContainerView')
25 25
26 children = []#List(Instance('IPython.html.widgets.widget.Widget'))
27 _children_lists_attr = List(Unicode, ['children'])
28
26 29 # Keys, all private and managed by helper methods. Flexible box model
27 30 # classes...
28 31 _keys = ['_vbox', '_hbox', '_align_start', '_align_end', '_align_center',
@@ -15,7 +15,7 b' pages.'
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17 from .widget import Widget
18 from IPython.utils.traitlets import Unicode, Dict, Int
18 from IPython.utils.traitlets import Unicode, Dict, Int, List, Instance
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Classes
@@ -29,9 +29,12 b' class MulticontainerWidget(Widget):'
29 29 _titles = Dict(help="Titles of the pages")
30 30 selected_index = Int(0)
31 31
32 children = []#List(Instance('IPython.html.widgets.widget.Widget'))
33 _children_lists_attr = List(Unicode, ['children'])
34
32 35 # Public methods
33 36 def set_title(self, index, title):
34 """Sets the title of a container pages
37 """Sets the title of a container page
35 38
36 39 Parameters
37 40 ----------
@@ -149,7 +149,7 b' def parse_notifier_name(name):'
149 149 return ['anytrait']
150 150 elif isinstance(name, (list, tuple)):
151 151 for n in name:
152 assert isinstance(n, str), "names must be strings"
152 assert isinstance(n, basestring), "names must be strings: %s, %r"%(type(n), n)
153 153 return name
154 154
155 155
@@ -801,11 +801,14 b' class Instance(ClassBasedTraitType):'
801 801 if self._allow_none:
802 802 return value
803 803 self.error(obj, value)
804
805 if isinstance(value, self.klass):
806 return value
807 else:
808 self.error(obj, value)
804 try:
805 if isinstance(value, self.klass):
806 return value
807 else:
808 self.error(obj, value)
809 except TypeError as e:
810 print self.klass, type(self.klass)
811 raise TypeError("validate, %s, %s"%(self.klass, type(self.klass)))
809 812
810 813 def info(self):
811 814 if isinstance(self.klass, py3compat.string_types):
@@ -110,7 +110,17 b''
110 110 ],
111 111 "language": "python",
112 112 "metadata": {},
113 "outputs": [],
113 "outputs": [
114 {
115 "output_type": "stream",
116 "stream": "stdout",
117 "text": [
118 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'value', 'step', 'max', 'min', 'disabled', 'orientation', 'description']\n",
119 "[]\n",
120 "[]\n"
121 ]
122 }
123 ],
114 124 "prompt_number": 3
115 125 },
116 126 {
@@ -132,6 +142,26 b''
132 142 "prompt_number": 4
133 143 },
134 144 {
145 "cell_type": "code",
146 "collapsed": false,
147 "input": [
148 "mywidget.value"
149 ],
150 "language": "python",
151 "metadata": {},
152 "outputs": [
153 {
154 "metadata": {},
155 "output_type": "pyout",
156 "prompt_number": 13,
157 "text": [
158 "55.1"
159 ]
160 }
161 ],
162 "prompt_number": 13
163 },
164 {
135 165 "cell_type": "markdown",
136 166 "metadata": {},
137 167 "source": [
@@ -152,10 +182,13 b''
152 182 {
153 183 "metadata": {},
154 184 "output_type": "pyout",
155 "prompt_number": 5,
185 "prompt_number": 11,
156 186 "text": [
157 187 "['visible',\n",
158 188 " '_css',\n",
189 " '_children_attr',\n",
190 " '_children_lists_attr',\n",
191 " 'default_view_name',\n",
159 192 " 'value',\n",
160 193 " 'step',\n",
161 194 " 'max',\n",
@@ -166,7 +199,7 b''
166 199 ]
167 200 }
168 201 ],
169 "prompt_number": 5
202 "prompt_number": 11
170 203 },
171 204 {
172 205 "cell_type": "markdown",
@@ -184,7 +217,7 b''
184 217 "language": "python",
185 218 "metadata": {},
186 219 "outputs": [],
187 "prompt_number": 6
220 "prompt_number": 12
188 221 },
189 222 {
190 223 "cell_type": "markdown",
@@ -205,13 +238,13 b''
205 238 {
206 239 "metadata": {},
207 240 "output_type": "pyout",
208 "prompt_number": 7,
241 "prompt_number": 30,
209 242 "text": [
210 "0.0"
243 "25.0"
211 244 ]
212 245 }
213 246 ],
214 "prompt_number": 7
247 "prompt_number": 30
215 248 },
216 249 {
217 250 "cell_type": "markdown",
@@ -229,8 +262,38 b''
229 262 ],
230 263 "language": "python",
231 264 "metadata": {},
232 "outputs": [],
233 "prompt_number": 8
265 "outputs": [
266 {
267 "output_type": "stream",
268 "stream": "stdout",
269 "text": [
270 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'value', 'values', 'disabled', 'description']\n",
271 "[]\n",
272 "[]\n"
273 ]
274 }
275 ],
276 "prompt_number": 14
277 },
278 {
279 "cell_type": "code",
280 "collapsed": false,
281 "input": [
282 "mysecondwidget.value"
283 ],
284 "language": "python",
285 "metadata": {},
286 "outputs": [
287 {
288 "metadata": {},
289 "output_type": "pyout",
290 "prompt_number": 15,
291 "text": [
292 "u'Item C'"
293 ]
294 }
295 ],
296 "prompt_number": 15
234 297 },
235 298 {
236 299 "cell_type": "heading",
@@ -259,13 +322,13 b''
259 322 {
260 323 "metadata": {},
261 324 "output_type": "pyout",
262 "prompt_number": 9,
325 "prompt_number": 16,
263 326 "text": [
264 327 "u'FloatSliderView'"
265 328 ]
266 329 }
267 330 ],
268 "prompt_number": 9
331 "prompt_number": 16
269 332 },
270 333 {
271 334 "cell_type": "markdown",
@@ -284,7 +347,7 b''
284 347 "language": "python",
285 348 "metadata": {},
286 349 "outputs": [],
287 "prompt_number": 10
350 "prompt_number": 17
288 351 },
289 352 {
290 353 "cell_type": "markdown",
@@ -108,7 +108,7 b''
108 108 "def on_value_change(name, value):\n",
109 109 " print(value)\n",
110 110 "\n",
111 "intrange.on_trait_change(on_value_change, 'value')"
111 "#intrange.on_trait_change(on_value_change, 'value')"
112 112 ],
113 113 "language": "python",
114 114 "metadata": {},
@@ -117,25 +117,13 b''
117 117 "output_type": "stream",
118 118 "stream": "stdout",
119 119 "text": [
120 "28\n"
121 ]
122 },
123 {
124 "output_type": "stream",
125 "stream": "stdout",
126 "text": [
127 "55\n"
128 ]
129 },
130 {
131 "output_type": "stream",
132 "stream": "stdout",
133 "text": [
134 "94\n"
120 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'value', 'step', 'max', 'min', 'disabled', 'orientation', 'description']\n",
121 "[]\n",
122 "[]\n"
135 123 ]
136 124 }
137 125 ],
138 "prompt_number": 3
126 "prompt_number": 9
139 127 },
140 128 {
141 129 "cell_type": "heading",
@@ -200,11 +188,32 b''
200 188 "cell_type": "code",
201 189 "collapsed": false,
202 190 "input": [
191 "display(intrange)\n",
192 "print('hi')"
193 ],
194 "language": "python",
195 "metadata": {},
196 "outputs": [
197 {
198 "output_type": "stream",
199 "stream": "stdout",
200 "text": [
201 "hi\n"
202 ]
203 }
204 ],
205 "prompt_number": 5
206 },
207 {
208 "cell_type": "code",
209 "collapsed": false,
210 "input": [
203 211 "button = widgets.ButtonWidget(description=\"Click Me!\")\n",
204 212 "display(button)\n",
205 213 "\n",
206 214 "def on_button_clicked(sender):\n",
207 215 " print(\"Button clicked.\")\n",
216 " intrange.value +=1\n",
208 217 "\n",
209 218 "button.on_click(on_button_clicked)"
210 219 ],
@@ -215,6 +224,22 b''
215 224 "output_type": "stream",
216 225 "stream": "stdout",
217 226 "text": [
227 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'description', 'disabled']\n",
228 "[]\n",
229 "[]\n"
230 ]
231 },
232 {
233 "output_type": "stream",
234 "stream": "stdout",
235 "text": [
236 "Button clicked.\n"
237 ]
238 },
239 {
240 "output_type": "stream",
241 "stream": "stdout",
242 "text": [
218 243 "Button clicked.\n"
219 244 ]
220 245 },
@@ -233,7 +258,7 b''
233 258 ]
234 259 }
235 260 ],
236 "prompt_number": 5
261 "prompt_number": 12
237 262 },
238 263 {
239 264 "cell_type": "markdown",
@@ -245,6 +270,36 b''
245 270 {
246 271 "cell_type": "code",
247 272 "collapsed": false,
273 "input": [],
274 "language": "python",
275 "metadata": {},
276 "outputs": [
277 {
278 "metadata": {},
279 "output_type": "pyout",
280 "prompt_number": 11,
281 "text": [
282 "{'content': {'data': \"{'parent_header': {}, 'msg_type': u'comm_msg', 'msg_id': u'3DBB06AD83C942DD85DC6477B08F1FBF', 'content': {u'data': {u'method': u'custom', u'custom_content': {u'event': u'click'}}, u'comm_id': u'eea5f11ae7aa473993dd0c81d6016648'}, 'header': {u'username': u'username', u'msg_id': u'3DBB06AD83C942DD85DC6477B08F1FBF', u'msg_type': u'comm_msg', u'session': u'0F6D6BE728DA47A38CFC4BDEACF34FC4'}, 'buffers': [], 'metadata': {}}\\ncustom message {'parent_header': {}, 'msg_type': u'comm_msg', 'msg_id': u'3DBB06AD83C942DD85DC6477B08F1FBF', 'content': {u'data': {u'method': u'custom', u'custom_content': {u'event': u'click'}}, u'comm_id': u'eea5f11ae7aa473993dd0c81d6016648'}, 'header': {u'username': u'username', u'msg_id': u'3DBB06AD83C942DD85DC6477B08F1FBF', u'msg_type': u'comm_msg', u'session': u'0F6D6BE728DA47A38CFC4BDEACF34FC4'}, 'buffers': [], 'metadata': {}}\\nhandling click\\n{u'event': u'click'}\\nButton clicked.\\n2\\n\",\n",
283 " 'name': 'stdout'},\n",
284 " 'header': {'msg_id': 'd9dc144a-d86c-42c1-8bab-f8a6bc525723',\n",
285 " 'msg_type': 'stream',\n",
286 " 'session': '9b9408d8-7420-4e0c-976d-cdda9f8d2564',\n",
287 " 'username': 'kernel'},\n",
288 " 'metadata': {},\n",
289 " 'msg_id': 'd9dc144a-d86c-42c1-8bab-f8a6bc525723',\n",
290 " 'msg_type': 'stream',\n",
291 " 'parent_header': {'msg_id': '3DBB06AD83C942DD85DC6477B08F1FBF',\n",
292 " 'msg_type': 'comm_msg',\n",
293 " 'session': '0F6D6BE728DA47A38CFC4BDEACF34FC4',\n",
294 " 'username': 'username'}}"
295 ]
296 }
297 ],
298 "prompt_number": 11
299 },
300 {
301 "cell_type": "code",
302 "collapsed": false,
248 303 "input": [
249 304 "def show_button(sender=None):\n",
250 305 " button = widgets.ButtonWidget()\n",
@@ -261,8 +316,161 b''
261 316 ],
262 317 "language": "python",
263 318 "metadata": {},
264 "outputs": [],
265 "prompt_number": 6
319 "outputs": [
320 {
321 "output_type": "stream",
322 "stream": "stdout",
323 "text": [
324 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'description', 'disabled']\n",
325 "[]\n",
326 "[]\n"
327 ]
328 },
329 {
330 "output_type": "stream",
331 "stream": "stdout",
332 "text": [
333 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'description', 'disabled']\n",
334 "[]\n",
335 "[]\n"
336 ]
337 },
338 {
339 "output_type": "stream",
340 "stream": "stdout",
341 "text": [
342 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'description', 'disabled']\n",
343 "[]\n",
344 "[]\n"
345 ]
346 },
347 {
348 "output_type": "stream",
349 "stream": "stdout",
350 "text": [
351 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'description', 'disabled']\n",
352 "[]\n",
353 "[]\n"
354 ]
355 },
356 {
357 "output_type": "stream",
358 "stream": "stdout",
359 "text": [
360 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'description', 'disabled']\n",
361 "[]\n",
362 "[]\n"
363 ]
364 },
365 {
366 "output_type": "stream",
367 "stream": "stdout",
368 "text": [
369 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'description', 'disabled']\n",
370 "[]\n",
371 "[]\n"
372 ]
373 },
374 {
375 "output_type": "stream",
376 "stream": "stdout",
377 "text": [
378 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'description', 'disabled']\n",
379 "[]\n",
380 "[]\n"
381 ]
382 },
383 {
384 "output_type": "stream",
385 "stream": "stdout",
386 "text": [
387 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'description', 'disabled']\n",
388 "[]\n",
389 "[]\n"
390 ]
391 },
392 {
393 "output_type": "stream",
394 "stream": "stdout",
395 "text": [
396 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'description', 'disabled']\n",
397 "[]\n",
398 "[]\n"
399 ]
400 },
401 {
402 "output_type": "stream",
403 "stream": "stdout",
404 "text": [
405 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'description', 'disabled']\n",
406 "[]\n",
407 "[]\n"
408 ]
409 },
410 {
411 "output_type": "stream",
412 "stream": "stdout",
413 "text": [
414 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'description', 'disabled']\n",
415 "[]\n",
416 "[]\n"
417 ]
418 },
419 {
420 "output_type": "stream",
421 "stream": "stdout",
422 "text": [
423 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'description', 'disabled']\n",
424 "[]\n",
425 "[]\n"
426 ]
427 },
428 {
429 "output_type": "stream",
430 "stream": "stdout",
431 "text": [
432 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'description', 'disabled']\n",
433 "[]\n",
434 "[]\n"
435 ]
436 },
437 {
438 "output_type": "stream",
439 "stream": "stdout",
440 "text": [
441 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'description', 'disabled']\n",
442 "[]\n",
443 "[]\n"
444 ]
445 },
446 {
447 "output_type": "stream",
448 "stream": "stdout",
449 "text": [
450 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'description', 'disabled']\n",
451 "[]\n",
452 "[]\n"
453 ]
454 },
455 {
456 "output_type": "stream",
457 "stream": "stdout",
458 "text": [
459 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'description', 'disabled']\n",
460 "[]\n",
461 "[]\n"
462 ]
463 }
464 ],
465 "prompt_number": 7
466 },
467 {
468 "cell_type": "code",
469 "collapsed": false,
470 "input": [],
471 "language": "python",
472 "metadata": {},
473 "outputs": []
266 474 }
267 475 ],
268 476 "metadata": {}
@@ -46,12 +46,11 b''
46 46 "cell_type": "code",
47 47 "collapsed": false,
48 48 "input": [
49 "container = widgets.MulticontainerWidget()\n",
50 49 "\n",
51 "floatrange = widgets.FloatRangeWidget(parent=container) # You can set the parent in the constructor,\n",
50 "floatrange = widgets.FloatRangeWidget() # You can set the parent in the constructor,\n",
52 51 "\n",
53 "string = widgets.StringWidget()\n",
54 "string.parent = container # or after the widget has been created.\n",
52 "string = widgets.StringWidget(value='hi')\n",
53 "container = widgets.MulticontainerWidget(children=[floatrange, string])\n",
55 54 "\n",
56 55 "display(container) # Displays the `container` and all of it's children."
57 56 ],
@@ -187,12 +186,22 b''
187 186 "collapsed": false,
188 187 "input": [
189 188 "string = widgets.StringWidget(value=\"Hello World!\")\n",
190 "display(string, view_name=\"LabelView\") "
189 "display(string, view_name=\"HTMLView\") "
191 190 ],
192 191 "language": "python",
193 192 "metadata": {},
194 "outputs": [],
195 "prompt_number": 7
193 "outputs": [
194 {
195 "output_type": "stream",
196 "stream": "stdout",
197 "text": [
198 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'value', 'disabled', 'description']\n",
199 "[]\n",
200 "[]\n"
201 ]
202 }
203 ],
204 "prompt_number": 11
196 205 },
197 206 {
198 207 "cell_type": "code",
@@ -203,7 +212,7 b''
203 212 "language": "python",
204 213 "metadata": {},
205 214 "outputs": [],
206 "prompt_number": 8
215 "prompt_number": 12
207 216 },
208 217 {
209 218 "cell_type": "code",
@@ -214,7 +223,7 b''
214 223 "language": "python",
215 224 "metadata": {},
216 225 "outputs": [],
217 "prompt_number": 9
226 "prompt_number": 13
218 227 },
219 228 {
220 229 "cell_type": "markdown",
@@ -228,18 +237,38 b''
228 237 "collapsed": false,
229 238 "input": [
230 239 "form = widgets.ContainerWidget()\n",
231 "first = widgets.StringWidget(description=\"First Name:\", parent=form)\n",
232 "last = widgets.StringWidget(description=\"Last Name:\", parent=form)\n",
240 "first = widgets.StringWidget(description=\"First Name:\")\n",
241 "last = widgets.StringWidget(description=\"Last Name:\")\n",
233 242 "\n",
234 "student = widgets.BoolWidget(description=\"Student:\", value=False, parent=form)\n",
235 "school_info = widgets.ContainerWidget(visible=False, parent=form)\n",
236 "school = widgets.StringWidget(description=\"School:\", parent=school_info)\n",
237 "grade = widgets.IntRangeWidget(description=\"Grade:\", min=0, max=12, default_view_name='IntTextView', parent=school_info)\n",
243 "student = widgets.BoolWidget(description=\"Student:\", value=False)\n",
244 "form.children=[first, last, student]\n",
245 "display(form)"
246 ],
247 "language": "python",
248 "metadata": {},
249 "outputs": [],
250 "prompt_number": 2
251 },
252 {
253 "cell_type": "code",
254 "collapsed": false,
255 "input": [
256 "form = widgets.ContainerWidget()\n",
257 "first = widgets.StringWidget(description=\"First Name:\")\n",
258 "last = widgets.StringWidget(description=\"Last Name:\")\n",
259 "\n",
260 "student = widgets.BoolWidget(description=\"Student:\", value=False)\n",
261 "school_info = widgets.ContainerWidget(visible=False, children=[\n",
262 " widgets.StringWidget(description=\"School:\"),\n",
263 " widgets.IntRangeWidget(description=\"Grade:\", min=0, max=12, default_view_name='IntTextView')\n",
264 " ])\n",
238 265 "\n",
239 "pet = widgets.StringWidget(description=\"Pet's Name:\", parent=form)\n",
266 "pet = widgets.StringWidget(description=\"Pet's Name:\")\n",
267 "form.children = [first, last, student, school_info, pet]\n",
240 268 "display(form)\n",
241 269 "\n",
242 270 "def on_student_toggle(name, value):\n",
271 " print value\n",
243 272 " if value:\n",
244 273 " school_info.visible = True\n",
245 274 " else:\n",
@@ -248,8 +277,66 b''
248 277 ],
249 278 "language": "python",
250 279 "metadata": {},
251 "outputs": [],
252 "prompt_number": 10
280 "outputs": [
281 {
282 "output_type": "stream",
283 "stream": "stdout",
284 "text": [
285 "True\n"
286 ]
287 },
288 {
289 "output_type": "stream",
290 "stream": "stdout",
291 "text": [
292 "False\n"
293 ]
294 },
295 {
296 "output_type": "stream",
297 "stream": "stdout",
298 "text": [
299 "True\n"
300 ]
301 },
302 {
303 "output_type": "stream",
304 "stream": "stdout",
305 "text": [
306 "False\n"
307 ]
308 },
309 {
310 "output_type": "stream",
311 "stream": "stdout",
312 "text": [
313 "True\n"
314 ]
315 },
316 {
317 "output_type": "stream",
318 "stream": "stdout",
319 "text": [
320 "False\n"
321 ]
322 },
323 {
324 "output_type": "stream",
325 "stream": "stdout",
326 "text": [
327 "True\n"
328 ]
329 }
330 ],
331 "prompt_number": 2
332 },
333 {
334 "cell_type": "code",
335 "collapsed": false,
336 "input": [],
337 "language": "python",
338 "metadata": {},
339 "outputs": []
253 340 }
254 341 ],
255 342 "metadata": {}
General Comments 0
You need to be logged in to leave comments. Login now