##// END OF EJS Templates
Intermediate changes to javascript side of backbone widgets
Jason Grout -
Show More
@@ -46,9 +46,9 b''
46 WidgetManager.prototype.attach_comm_manager = function (comm_manager) {
46 WidgetManager.prototype.attach_comm_manager = function (comm_manager) {
47 this.comm_manager = comm_manager;
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 for (var widget_model_name in this.widget_model_types) {
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 // Register the widget with the comm manager. Make sure to pass this object's context
57 // Register the widget with the comm manager. Make sure to pass this object's context
58 // in so `this` works in the call back.
58 // in so `this` works in the call back.
59 if (this.comm_manager !== null) {
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 this.widget_model_types[widget_model_name] = widget_model_type;
62 this.widget_model_types[widget_model_name] = widget_model_type;
63 };
63 };
@@ -66,12 +66,97 b''
66 WidgetManager.prototype.register_widget_view = function (widget_view_name, widget_view_type) {
66 WidgetManager.prototype.register_widget_view = function (widget_view_name, widget_view_type) {
67 this.widget_view_types[widget_view_name] = widget_view_type;
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 WidgetManager.prototype.get_msg_cell = function (msg_id) {
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 if (IPython.notebook !== undefined && IPython.notebook !== null) {
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 var widget_type_name = msg.content.target_name;
198 var widget_type_name = msg.content.target_name;
114 var widget_model = new this.widget_model_types[widget_type_name](this, comm.comm_id, comm);
199 var widget_model = new this.widget_model_types[widget_type_name](this, comm.comm_id, comm);
115 this._model_instances[comm.comm_id] = widget_model;
200 this._model_instances[comm.comm_id] = widget_model;
@@ -126,4 +211,4 b''
126
211
127 return IPython.widget_manager;
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 this.pending_msgs = 0;
28 this.pending_msgs = 0;
29 this.msg_throttle = 3;
29 this.msg_throttle = 3;
30 this.msg_buffer = null;
30 this.msg_buffer = null;
31 this.views = [];
32 this.id = widget_id;
31 this.id = widget_id;
33 this._custom_msg_callbacks = [];
34
32
35 if (comm !== undefined) {
33 if (comm !== undefined) {
36
37 // Remember comm associated with the model.
34 // Remember comm associated with the model.
38 this.comm = comm;
35 this.comm = comm;
39 comm.model = this;
36 comm.model = this;
40
37
41 // Hook comm messages up to model.
38 // Hook comm messages up to model.
39 var that = this;
42 comm.on_close($.proxy(this._handle_comm_closed, this));
40 comm.on_close($.proxy(this._handle_comm_closed, this));
43 comm.on_msg($.proxy(this._handle_comm_msg, this));
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) {
48 send: function (content, callbacks) {
51 if (this._has_comm()) {
49 console.log('send',content, callbacks);
52 // Used the last modified view as the sender of the message. This
50 if (this.comm !== undefined) {
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);
62 var data = {method: 'custom', custom_content: content};
51 var data = {method: 'custom', custom_content: content};
63
64 this.comm.send(data, callbacks);
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 // Handle when a widget is closed.
56 // Handle when a widget is closed.
110 _handle_comm_closed: function (msg) {
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 if (this._has_comm()) {
60 if (this._has_comm()) {
113 delete this.comm.model; // Delete ref so GC will collect widget model.
61 delete this.comm.model; // Delete ref so GC will collect widget model.
114 delete this.comm;
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 _handle_comm_msg: function (msg) {
69 _handle_comm_msg: function (msg) {
122 var method = msg.content.data.method;
70 var method = msg.content.data.method;
123 switch (method) {
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 case 'update':
72 case 'update':
138 this.apply_update(msg.content.data.state);
73 this.apply_update(msg.content.data.state);
139 break;
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 case 'custom':
75 case 'custom':
155 this._handle_custom_msg(msg.content.data.custom_content);
76 this.trigger('msg:custom', msg.content.data.custom_content);
156 break;
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 try {
88 try {
165 for (var key in state) {
89 for (var key in state) {
166 if (state.hasOwnProperty(key)) {
90 if (state.hasOwnProperty(key)) {
167 if (key == "_css") {
91 this.set(key, state[key]);
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 }
179 }
92 }
180 }
93 }
181 this.save();
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 //execution_state : ('busy', 'idle', 'starting')
102 //execution_state : ('busy', 'idle', 'starting')
190 if (this._has_comm()) {
103 if (this.comm !== undefined) {
191 if (msg.content.execution_state=='idle') {
104 if (msg.content.execution_state ==='idle') {
192
105
193 // Send buffer if this message caused another message to be
106 // Send buffer if this message caused another message to be
194 // throttled.
107 // throttled.
195 if (this.msg_buffer !== null &&
108 if (this.msg_buffer !== null &&
196 this.msg_throttle == this.pending_msgs) {
109 this.msg_throttle === this.pending_msgs) {
197
198 var callbacks = this._make_callbacks(cell);
199 var data = {method: 'backbone', sync_method: 'update', sync_data: this.msg_buffer};
110 var data = {method: 'backbone', sync_method: 'update', sync_data: this.msg_buffer};
200 this.comm.send(data, callbacks);
111 this.comm.send(data, callbacks);
201 this.msg_buffer = null;
112 this.msg_buffer = null;
@@ -217,7 +128,7 b' function(widget_manager, underscore, backbone){'
217
128
218 // Only send updated state if the state hasn't been changed
129 // Only send updated state if the state hasn't been changed
219 // during an update.
130 // during an update.
220 if (this._has_comm()) {
131 if (this.comm !== undefined) {
221 if (!this.updating) {
132 if (!this.updating) {
222 if (this.pending_msgs >= this.msg_throttle) {
133 if (this.pending_msgs >= this.msg_throttle) {
223 // The throttle has been exceeded, buffer the current msg so
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 var data = {method: 'backbone', sync_method: method, sync_data: send_json};
160 var data = {method: 'backbone', sync_method: method, sync_data: send_json};
250
161 this.comm.send(data, this.cell_callbacks());
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);
258 this.pending_msgs++;
162 this.pending_msgs++;
259 }
163 }
260 }
164 }
@@ -265,133 +169,22 b' function(widget_manager, underscore, backbone){'
265 return model_json;
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 // Build a callback dict.
172 // Build a callback dict.
393 _make_callbacks: function (cell) {
173 cell_callbacks: function (cell) {
394 var callbacks = {};
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 if (cell !== null) {
188 if (cell !== null) {
396
189
397 // Try to get output handlers
190 // Try to get output handlers
@@ -402,7 +195,7 b' function(widget_manager, underscore, backbone){'
402 handle_clear_output = $.proxy(cell.output_area.handle_clear_output, cell.output_area);
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 var that = this;
199 var that = this;
407 callbacks = {
200 callbacks = {
408 iopub : {
201 iopub : {
@@ -410,7 +203,7 b' function(widget_manager, underscore, backbone){'
410 clear_output : handle_clear_output,
203 clear_output : handle_clear_output,
411
204
412 status : function (msg) {
205 status : function (msg) {
413 that._handle_status(cell, msg);
206 that._handle_status(msg, that.cell_callbacks(cell));
414 },
207 },
415
208
416 // Special function only registered by widget messages.
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 return callbacks;
219 return callbacks;
426 },
220 },
221 });
427
222
428
223
429 // Get the output area corresponding to the msg_id.
224 //--------------------------------------------------------------------
430 // cell is an instance of IPython.Cell
225 // WidgetView class
431 _get_msg_cell: function (msg_id) {
226 //--------------------------------------------------------------------
432
227 var BaseWidgetView = Backbone.View.extend({
433 // First, check to see if the msg was triggered by cell execution.
228 initialize: function(options) {
434 var cell = this.widget_manager.get_msg_cell(msg_id);
229 this.model.on('change',this.update,this);
435 if (cell !== null) {
230 this.widget_manager = options.widget_manager;
436 return cell;
231 this.comm_manager = options.widget_manager.comm_manager;
437 }
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
286 touch: function () {
440 // for the message. get_cell callbacks are registered for
287 this.model.last_modified_view = this;
441 // widget messages, so this block is actually checking to see if the
288 this.model.save(this.model.changedAttributes(), {patch: true});
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;
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
294 var WidgetView = BaseWidgetView.extend({
468 //--------------------------------------------------------------------
295 initialize: function (options) {
469 // WidgetView class
470 //--------------------------------------------------------------------
471 var WidgetView = Backbone.View.extend({
472
473 initialize: function () {
474 this.visible = true;
296 this.visible = true;
475 this.model.on('sync',this.update,this);
297 BaseWidgetView.prototype.initialize.apply(this, arguments);
476 },
298 },
477
299
478 add_class: function (selector, class_list) {
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 update: function () {
314 update: function () {
504 if (this.model.get('visible') !== undefined) {
315 // jng: hook into change:visible trigger
505 if (this.visible != this.model.get('visible')) {
316 var visible = this.model.get('visible');
506 this.visible = this.model.get('visible');
317 if (visible !== undefined && this.visible !== visible) {
507 if (this.visible) {
318 this.visible = visible;
508 this.$el.show();
319 this.$el.toggle(visible)
509 } else {
510 this.$el.hide();
511 }
512 }
513 }
320 }
514
321
515 if (this.model.css !== undefined) {
322 if (this.model.css !== undefined) {
@@ -552,4 +359,4 b' function(widget_manager, underscore, backbone){'
552 IPython.WidgetView = WidgetView;
359 IPython.WidgetView = WidgetView;
553
360
554 return widget_manager;
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 render: function(){
52 render: function(){
53 this.$el
53 this.$el
54 .addClass('widget-container');
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 update: function(){
61 update: function(){
58 set_flex_properties(this, this.$el);
62 set_flex_properties(this, this.$el);
59 return IPython.WidgetView.prototype.update.call(this);
63 return IPython.WidgetView.prototype.update.call(this);
60 },
64 },
61
65 add_child_view: function(attr, view) {
62 display_child: function(view) {
66 if (attr==='children') {
63 this.$el.append(view.$el);
67 this.$el.append(view.$el);
64 },
68 }
69 }
65 });
70 });
66
71
67 widget_manager.register_widget_view('ContainerView', ContainerView);
72 widget_manager.register_widget_view('ContainerView', ContainerView);
@@ -229,8 +234,10 b' define(["notebook/js/widgets/base"], function(widget_manager) {'
229 return IPython.WidgetView.prototype.update.call(this);
234 return IPython.WidgetView.prototype.update.call(this);
230 },
235 },
231
236
232 display_child: function(view) {
237 add_child_view: function(attr, view) {
233 this.$body.append(view.$el);
238 if (attr==='children') {
239 this.$body.append(view.$el);
240 }
234 },
241 },
235
242
236 _get_selector_element: function(selector) {
243 _get_selector_element: function(selector) {
@@ -70,6 +70,7 b' define(["notebook/js/widgets/base"], function(widget_manager){'
70 this.$slider.slider('option', 'orientation', orientation);
70 this.$slider.slider('option', 'orientation', orientation);
71 value = this.model.get('value');
71 value = this.model.get('value');
72 this.$slider.slider('option', 'value', value);
72 this.$slider.slider('option', 'value', value);
73 console.log('updating value',value)
73
74
74 // Use the right CSS classes for vertical & horizontal sliders
75 // Use the right CSS classes for vertical & horizontal sliders
75 if (orientation=='vertical') {
76 if (orientation=='vertical') {
@@ -109,6 +110,7 b' define(["notebook/js/widgets/base"], function(widget_manager){'
109 events: { "slide" : "handleSliderChange" },
110 events: { "slide" : "handleSliderChange" },
110 handleSliderChange: function(e, ui) {
111 handleSliderChange: function(e, ui) {
111 this.model.set('value', ui.value);
112 this.model.set('value', ui.value);
113 console.log('triggered value change', ui.value, this.model);
112 this.touch();
114 this.touch();
113 },
115 },
114 });
116 });
@@ -27,7 +27,6 b' define(["notebook/js/widgets/base"], function(widget_manager){'
27 .addClass('accordion');
27 .addClass('accordion');
28 this.containers = [];
28 this.containers = [];
29 },
29 },
30
31 update: function() {
30 update: function() {
32 // Set tab titles
31 // Set tab titles
33 var titles = this.model.get('_titles');
32 var titles = this.model.get('_titles');
@@ -58,7 +57,7 b' define(["notebook/js/widgets/base"], function(widget_manager){'
58 return IPython.WidgetView.prototype.update.call(this);
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 var index = this.containers.length;
62 var index = this.containers.length;
64 var uuid = IPython.utils.uuid();
63 var uuid = IPython.utils.uuid();
@@ -103,7 +102,13 b' define(["notebook/js/widgets/base"], function(widget_manager){'
103
102
104 var TabView = IPython.WidgetView.extend({
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 render: function(){
110 render: function(){
111 console.log('rendering tabs', this);
107 var uuid = 'tabs'+IPython.utils.uuid();
112 var uuid = 'tabs'+IPython.utils.uuid();
108 var that = this;
113 var that = this;
109 this.$tabs = $('<div />', {id: uuid})
114 this.$tabs = $('<div />', {id: uuid})
@@ -113,8 +118,7 b' define(["notebook/js/widgets/base"], function(widget_manager){'
113 this.$tab_contents = $('<div />', {id: uuid + 'Content'})
118 this.$tab_contents = $('<div />', {id: uuid + 'Content'})
114 .addClass('tab-content')
119 .addClass('tab-content')
115 .appendTo(this.$el);
120 .appendTo(this.$el);
116
121 this.update();
117 this.containers = [];
118 },
122 },
119
123
120 update: function() {
124 update: function() {
@@ -135,8 +139,8 b' define(["notebook/js/widgets/base"], function(widget_manager){'
135 return IPython.WidgetView.prototype.update.call(this);
139 return IPython.WidgetView.prototype.update.call(this);
136 },
140 },
137
141
138 display_child: function(view) {
142 add_child_view: function(attr, view) {
139
143 console.log('adding child view', attr, view);
140 var index = this.containers.length;
144 var index = this.containers.length;
141 var uuid = IPython.utils.uuid();
145 var uuid = IPython.utils.uuid();
142
146
@@ -86,7 +86,7 b' var IPython = (function (IPython) {'
86 try {
86 try {
87 f(comm, msg);
87 f(comm, msg);
88 } catch (e) {
88 } catch (e) {
89 console.log("Exception opening new comm:", e, msg);
89 console.log("Exception opening new comm:", e, e.stack, msg);
90 comm.close();
90 comm.close();
91 this.unregister_comm(comm);
91 this.unregister_comm(comm);
92 }
92 }
@@ -102,7 +102,7 b' var IPython = (function (IPython) {'
102 try {
102 try {
103 comm.handle_close(msg);
103 comm.handle_close(msg);
104 } catch (e) {
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 try {
115 try {
116 comm.handle_msg(msg);
116 comm.handle_msg(msg);
117 } catch (e) {
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 try {
176 try {
177 callback(msg);
177 callback(msg);
178 } catch (e) {
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 class BaseWidget(LoggingConfigurable):
34 class BaseWidget(LoggingConfigurable):
35
35
36 # Shared declarations (Class level)
36 # Shared declarations (Class level)
37 _keys = List(Unicode, help="List of keys comprising the state of the model.")
37 _keys = List(Unicode, default_value = [],
38 _children_attr = List(Unicode, help="List of keys of children objects of the model.")
38 help="List of keys comprising the state of the model.", allow_none=False)
39 _children_lists_attr = List(Unicode, help="List of keys containing lists of children objects of the model.")
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 widget_construction_callback = None
44 widget_construction_callback = None
41
45
42 def on_widget_constructed(callback):
46 def on_widget_constructed(callback):
@@ -59,9 +63,10 b' class BaseWidget(LoggingConfigurable):'
59 to use to represent the widget.""")
63 to use to represent the widget.""")
60
64
61 # Private/protected declarations
65 # Private/protected declarations
66 # todo: change this to a context manager
62 _property_lock = (None, None) # Last updated (key, value) from the front-end. Prevents echo.
67 _property_lock = (None, None) # Last updated (key, value) from the front-end. Prevents echo.
63 _displayed = False
68 _displayed = False
64 _comm = None
69 _comm = Instance('IPython.kernel.comm.Comm')
65
70
66 def __init__(self, **kwargs):
71 def __init__(self, **kwargs):
67 """Public constructor
72 """Public constructor
@@ -72,6 +77,7 b' class BaseWidget(LoggingConfigurable):'
72
77
73 # Register after init to allow default values to be specified
78 # Register after init to allow default values to be specified
74 # TODO: register three different handlers, one for each list, and abstract out the common parts
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 self.on_trait_change(self._handle_property_changed, self.keys+self._children_attr+self._children_lists_attr)
81 self.on_trait_change(self._handle_property_changed, self.keys+self._children_attr+self._children_lists_attr)
76 Widget._handle_widget_constructed(self)
82 Widget._handle_widget_constructed(self)
77
83
@@ -90,7 +96,7 b' class BaseWidget(LoggingConfigurable):'
90 # Properties
96 # Properties
91 @property
97 @property
92 def keys(self):
98 def keys(self):
93 keys = ['_children_attr', '_children_lists_attr']
99 keys = ['_children_attr', '_children_lists_attr', 'default_view_name']
94 keys.extend(self._keys)
100 keys.extend(self._keys)
95 return keys
101 return keys
96
102
@@ -118,7 +124,6 b' class BaseWidget(LoggingConfigurable):'
118 if 'custom_content' in data:
124 if 'custom_content' in data:
119 self._handle_custom_msg(data['custom_content'])
125 self._handle_custom_msg(data['custom_content'])
120
126
121
122 def _handle_custom_msg(self, content):
127 def _handle_custom_msg(self, content):
123 """Called when a custom msg is recieved."""
128 """Called when a custom msg is recieved."""
124 for handler in self._msg_callbacks:
129 for handler in self._msg_callbacks:
@@ -153,7 +158,7 b' class BaseWidget(LoggingConfigurable):'
153
158
154
159
155 def _handle_property_changed(self, name, old, new):
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 # Make sure this isn't information that the front-end just sent us.
162 # Make sure this isn't information that the front-end just sent us.
158 if self._property_lock[0] != name and self._property_lock[1] != new:
163 if self._property_lock[0] != name and self._property_lock[1] != new:
159 # Send new state to frontend
164 # Send new state to frontend
@@ -197,7 +202,7 b' class BaseWidget(LoggingConfigurable):'
197 self._send({"method": "update",
202 self._send({"method": "update",
198 "state": self.get_state()})
203 "state": self.get_state()})
199
204
200 def get_state(self, key=None)
205 def get_state(self, key=None):
201 """Gets the widget state, or a piece of it.
206 """Gets the widget state, or a piece of it.
202
207
203 Parameters
208 Parameters
@@ -308,15 +313,18 b' class BaseWidget(LoggingConfigurable):'
308 def _open_communication(self):
313 def _open_communication(self):
309 """Opens a communication with the front-end."""
314 """Opens a communication with the front-end."""
310 # Create a comm.
315 # Create a comm.
311 if not hasattr(self, '_comm') or self._comm is None:
316 if self._comm is None:
312 self._comm = Comm(target_name=self.target_name)
317 self._comm = Comm(target_name=self.target_name)
313 self._comm.on_msg(self._handle_msg)
318 self._comm.on_msg(self._handle_msg)
314 self._comm.on_close(self._close_communication)
319 self._comm.on_close(self._close_communication)
315
320
321 # first update
322 self.send_state()
323
316
324
317 def _close_communication(self):
325 def _close_communication(self):
318 """Closes a communication with the front-end."""
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 try:
328 try:
321 self._comm.close()
329 self._comm.close()
322 finally:
330 finally:
@@ -332,9 +340,6 b' class BaseWidget(LoggingConfigurable):'
332 return False
340 return False
333
341
334 class Widget(BaseWidget):
342 class Widget(BaseWidget):
335
336 _children = List(Instance('IPython.html.widgets.widget.Widget'))
337 _children_lists_attr = List(Unicode, ['_children'])
338 visible = Bool(True, help="Whether or not the widget is visible.")
343 visible = Bool(True, help="Whether or not the widget is visible.")
339
344
340 # Private/protected declarations
345 # Private/protected declarations
@@ -59,7 +59,7 b' class ButtonWidget(Widget):'
59
59
60
60
61 def _handle_button_msg(self, content):
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 Parameters
64 Parameters
65 ----------
65 ----------
@@ -14,7 +14,7 b' Represents a container that can be used to group other widgets.'
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from .widget import Widget
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 # Classes
20 # Classes
@@ -23,6 +23,9 b' class ContainerWidget(Widget):'
23 target_name = Unicode('ContainerWidgetModel')
23 target_name = Unicode('ContainerWidgetModel')
24 default_view_name = Unicode('ContainerView')
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 # Keys, all private and managed by helper methods. Flexible box model
29 # Keys, all private and managed by helper methods. Flexible box model
27 # classes...
30 # classes...
28 _keys = ['_vbox', '_hbox', '_align_start', '_align_end', '_align_center',
31 _keys = ['_vbox', '_hbox', '_align_start', '_align_end', '_align_center',
@@ -15,7 +15,7 b' pages.'
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 from .widget import Widget
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 # Classes
21 # Classes
@@ -29,9 +29,12 b' class MulticontainerWidget(Widget):'
29 _titles = Dict(help="Titles of the pages")
29 _titles = Dict(help="Titles of the pages")
30 selected_index = Int(0)
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 # Public methods
35 # Public methods
33 def set_title(self, index, title):
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 Parameters
39 Parameters
37 ----------
40 ----------
@@ -149,7 +149,7 b' def parse_notifier_name(name):'
149 return ['anytrait']
149 return ['anytrait']
150 elif isinstance(name, (list, tuple)):
150 elif isinstance(name, (list, tuple)):
151 for n in name:
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 return name
153 return name
154
154
155
155
@@ -801,11 +801,14 b' class Instance(ClassBasedTraitType):'
801 if self._allow_none:
801 if self._allow_none:
802 return value
802 return value
803 self.error(obj, value)
803 self.error(obj, value)
804
804 try:
805 if isinstance(value, self.klass):
805 if isinstance(value, self.klass):
806 return value
806 return value
807 else:
807 else:
808 self.error(obj, value)
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 def info(self):
813 def info(self):
811 if isinstance(self.klass, py3compat.string_types):
814 if isinstance(self.klass, py3compat.string_types):
@@ -110,7 +110,17 b''
110 ],
110 ],
111 "language": "python",
111 "language": "python",
112 "metadata": {},
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 "prompt_number": 3
124 "prompt_number": 3
115 },
125 },
116 {
126 {
@@ -132,6 +142,26 b''
132 "prompt_number": 4
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 "cell_type": "markdown",
165 "cell_type": "markdown",
136 "metadata": {},
166 "metadata": {},
137 "source": [
167 "source": [
@@ -152,10 +182,13 b''
152 {
182 {
153 "metadata": {},
183 "metadata": {},
154 "output_type": "pyout",
184 "output_type": "pyout",
155 "prompt_number": 5,
185 "prompt_number": 11,
156 "text": [
186 "text": [
157 "['visible',\n",
187 "['visible',\n",
158 " '_css',\n",
188 " '_css',\n",
189 " '_children_attr',\n",
190 " '_children_lists_attr',\n",
191 " 'default_view_name',\n",
159 " 'value',\n",
192 " 'value',\n",
160 " 'step',\n",
193 " 'step',\n",
161 " 'max',\n",
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 "cell_type": "markdown",
205 "cell_type": "markdown",
@@ -184,7 +217,7 b''
184 "language": "python",
217 "language": "python",
185 "metadata": {},
218 "metadata": {},
186 "outputs": [],
219 "outputs": [],
187 "prompt_number": 6
220 "prompt_number": 12
188 },
221 },
189 {
222 {
190 "cell_type": "markdown",
223 "cell_type": "markdown",
@@ -205,13 +238,13 b''
205 {
238 {
206 "metadata": {},
239 "metadata": {},
207 "output_type": "pyout",
240 "output_type": "pyout",
208 "prompt_number": 7,
241 "prompt_number": 30,
209 "text": [
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 "cell_type": "markdown",
250 "cell_type": "markdown",
@@ -229,8 +262,38 b''
229 ],
262 ],
230 "language": "python",
263 "language": "python",
231 "metadata": {},
264 "metadata": {},
232 "outputs": [],
265 "outputs": [
233 "prompt_number": 8
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 "cell_type": "heading",
299 "cell_type": "heading",
@@ -259,13 +322,13 b''
259 {
322 {
260 "metadata": {},
323 "metadata": {},
261 "output_type": "pyout",
324 "output_type": "pyout",
262 "prompt_number": 9,
325 "prompt_number": 16,
263 "text": [
326 "text": [
264 "u'FloatSliderView'"
327 "u'FloatSliderView'"
265 ]
328 ]
266 }
329 }
267 ],
330 ],
268 "prompt_number": 9
331 "prompt_number": 16
269 },
332 },
270 {
333 {
271 "cell_type": "markdown",
334 "cell_type": "markdown",
@@ -284,7 +347,7 b''
284 "language": "python",
347 "language": "python",
285 "metadata": {},
348 "metadata": {},
286 "outputs": [],
349 "outputs": [],
287 "prompt_number": 10
350 "prompt_number": 17
288 },
351 },
289 {
352 {
290 "cell_type": "markdown",
353 "cell_type": "markdown",
@@ -108,7 +108,7 b''
108 "def on_value_change(name, value):\n",
108 "def on_value_change(name, value):\n",
109 " print(value)\n",
109 " print(value)\n",
110 "\n",
110 "\n",
111 "intrange.on_trait_change(on_value_change, 'value')"
111 "#intrange.on_trait_change(on_value_change, 'value')"
112 ],
112 ],
113 "language": "python",
113 "language": "python",
114 "metadata": {},
114 "metadata": {},
@@ -117,25 +117,13 b''
117 "output_type": "stream",
117 "output_type": "stream",
118 "stream": "stdout",
118 "stream": "stdout",
119 "text": [
119 "text": [
120 "28\n"
120 "['visible', '_css', '_children_attr', '_children_lists_attr', 'default_view_name', 'value', 'step', 'max', 'min', 'disabled', 'orientation', 'description']\n",
121 ]
121 "[]\n",
122 },
122 "[]\n"
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"
135 ]
123 ]
136 }
124 }
137 ],
125 ],
138 "prompt_number": 3
126 "prompt_number": 9
139 },
127 },
140 {
128 {
141 "cell_type": "heading",
129 "cell_type": "heading",
@@ -200,11 +188,32 b''
200 "cell_type": "code",
188 "cell_type": "code",
201 "collapsed": false,
189 "collapsed": false,
202 "input": [
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 "button = widgets.ButtonWidget(description=\"Click Me!\")\n",
211 "button = widgets.ButtonWidget(description=\"Click Me!\")\n",
204 "display(button)\n",
212 "display(button)\n",
205 "\n",
213 "\n",
206 "def on_button_clicked(sender):\n",
214 "def on_button_clicked(sender):\n",
207 " print(\"Button clicked.\")\n",
215 " print(\"Button clicked.\")\n",
216 " intrange.value +=1\n",
208 "\n",
217 "\n",
209 "button.on_click(on_button_clicked)"
218 "button.on_click(on_button_clicked)"
210 ],
219 ],
@@ -215,6 +224,22 b''
215 "output_type": "stream",
224 "output_type": "stream",
216 "stream": "stdout",
225 "stream": "stdout",
217 "text": [
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 "Button clicked.\n"
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 "cell_type": "markdown",
264 "cell_type": "markdown",
@@ -245,6 +270,36 b''
245 {
270 {
246 "cell_type": "code",
271 "cell_type": "code",
247 "collapsed": false,
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 "input": [
303 "input": [
249 "def show_button(sender=None):\n",
304 "def show_button(sender=None):\n",
250 " button = widgets.ButtonWidget()\n",
305 " button = widgets.ButtonWidget()\n",
@@ -261,8 +316,161 b''
261 ],
316 ],
262 "language": "python",
317 "language": "python",
263 "metadata": {},
318 "metadata": {},
264 "outputs": [],
319 "outputs": [
265 "prompt_number": 6
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 "metadata": {}
476 "metadata": {}
@@ -46,12 +46,11 b''
46 "cell_type": "code",
46 "cell_type": "code",
47 "collapsed": false,
47 "collapsed": false,
48 "input": [
48 "input": [
49 "container = widgets.MulticontainerWidget()\n",
50 "\n",
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 "\n",
51 "\n",
53 "string = widgets.StringWidget()\n",
52 "string = widgets.StringWidget(value='hi')\n",
54 "string.parent = container # or after the widget has been created.\n",
53 "container = widgets.MulticontainerWidget(children=[floatrange, string])\n",
55 "\n",
54 "\n",
56 "display(container) # Displays the `container` and all of it's children."
55 "display(container) # Displays the `container` and all of it's children."
57 ],
56 ],
@@ -187,12 +186,22 b''
187 "collapsed": false,
186 "collapsed": false,
188 "input": [
187 "input": [
189 "string = widgets.StringWidget(value=\"Hello World!\")\n",
188 "string = widgets.StringWidget(value=\"Hello World!\")\n",
190 "display(string, view_name=\"LabelView\") "
189 "display(string, view_name=\"HTMLView\") "
191 ],
190 ],
192 "language": "python",
191 "language": "python",
193 "metadata": {},
192 "metadata": {},
194 "outputs": [],
193 "outputs": [
195 "prompt_number": 7
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 "cell_type": "code",
207 "cell_type": "code",
@@ -203,7 +212,7 b''
203 "language": "python",
212 "language": "python",
204 "metadata": {},
213 "metadata": {},
205 "outputs": [],
214 "outputs": [],
206 "prompt_number": 8
215 "prompt_number": 12
207 },
216 },
208 {
217 {
209 "cell_type": "code",
218 "cell_type": "code",
@@ -214,7 +223,7 b''
214 "language": "python",
223 "language": "python",
215 "metadata": {},
224 "metadata": {},
216 "outputs": [],
225 "outputs": [],
217 "prompt_number": 9
226 "prompt_number": 13
218 },
227 },
219 {
228 {
220 "cell_type": "markdown",
229 "cell_type": "markdown",
@@ -228,18 +237,38 b''
228 "collapsed": false,
237 "collapsed": false,
229 "input": [
238 "input": [
230 "form = widgets.ContainerWidget()\n",
239 "form = widgets.ContainerWidget()\n",
231 "first = widgets.StringWidget(description=\"First Name:\", parent=form)\n",
240 "first = widgets.StringWidget(description=\"First Name:\")\n",
232 "last = widgets.StringWidget(description=\"Last Name:\", parent=form)\n",
241 "last = widgets.StringWidget(description=\"Last Name:\")\n",
233 "\n",
242 "\n",
234 "student = widgets.BoolWidget(description=\"Student:\", value=False, parent=form)\n",
243 "student = widgets.BoolWidget(description=\"Student:\", value=False)\n",
235 "school_info = widgets.ContainerWidget(visible=False, parent=form)\n",
244 "form.children=[first, last, student]\n",
236 "school = widgets.StringWidget(description=\"School:\", parent=school_info)\n",
245 "display(form)"
237 "grade = widgets.IntRangeWidget(description=\"Grade:\", min=0, max=12, default_view_name='IntTextView', parent=school_info)\n",
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 "\n",
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 "display(form)\n",
268 "display(form)\n",
241 "\n",
269 "\n",
242 "def on_student_toggle(name, value):\n",
270 "def on_student_toggle(name, value):\n",
271 " print value\n",
243 " if value:\n",
272 " if value:\n",
244 " school_info.visible = True\n",
273 " school_info.visible = True\n",
245 " else:\n",
274 " else:\n",
@@ -248,8 +277,66 b''
248 ],
277 ],
249 "language": "python",
278 "language": "python",
250 "metadata": {},
279 "metadata": {},
251 "outputs": [],
280 "outputs": [
252 "prompt_number": 10
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 "metadata": {}
342 "metadata": {}
General Comments 0
You need to be logged in to leave comments. Login now