##// END OF EJS Templates
Fixed bug that prevent model.save() from being called on...
Jonathan Frederic -
Show More
@@ -1,475 +1,480 b''
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2013 The IPython Development Team
2 // Copyright (C) 2013 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // WidgetModel, WidgetView, and WidgetManager
9 // WidgetModel, WidgetView, and WidgetManager
10 //============================================================================
10 //============================================================================
11 /**
11 /**
12 * Base Widget classes
12 * Base Widget classes
13 * @module IPython
13 * @module IPython
14 * @namespace IPython
14 * @namespace IPython
15 * @submodule widget
15 * @submodule widget
16 */
16 */
17
17
18 "use strict";
18 "use strict";
19
19
20 // Use require.js 'define' method so that require.js is intelligent enough to
20 // Use require.js 'define' method so that require.js is intelligent enough to
21 // syncronously load everything within this file when it is being 'required'
21 // syncronously load everything within this file when it is being 'required'
22 // elsewhere.
22 // elsewhere.
23 define(["components/underscore/underscore-min",
23 define(["components/underscore/underscore-min",
24 "components/backbone/backbone-min",
24 "components/backbone/backbone-min",
25 ], function(){
25 ], function(){
26
26
27
27
28 //--------------------------------------------------------------------
28 //--------------------------------------------------------------------
29 // WidgetModel class
29 // WidgetModel class
30 //--------------------------------------------------------------------
30 //--------------------------------------------------------------------
31 var WidgetModel = Backbone.Model.extend({
31 var WidgetModel = Backbone.Model.extend({
32 constructor: function(comm_manager, comm, widget_view_types) {
32 constructor: function(comm_manager, comm, widget_view_types) {
33 this.comm_manager = comm_manager;
33 this.comm_manager = comm_manager;
34 this.widget_view_types = widget_view_types;
34 this.widget_view_types = widget_view_types;
35 this.pending_msgs = 0;
35 this.pending_msgs = 0;
36 this.msg_throttle = 3;
36 this.msg_throttle = 3;
37 this.msg_buffer = null;
37 this.msg_buffer = null;
38 this.views = {};
38 this.views = {};
39
39
40 // Remember comm associated with the model.
40 // Remember comm associated with the model.
41 this.comm = comm;
41 this.comm = comm;
42 comm.model = this;
42 comm.model = this;
43
43
44 // Hook comm messages up to model.
44 // Hook comm messages up to model.
45 comm.on_close($.proxy(this.handle_comm_closed, this));
45 comm.on_close($.proxy(this.handle_comm_closed, this));
46 comm.on_msg($.proxy(this.handle_comm_msg, this));
46 comm.on_msg($.proxy(this.handle_comm_msg, this));
47
47
48 return Backbone.Model.apply(this);
48 return Backbone.Model.apply(this);
49 },
49 },
50
50
51
51
52 update_other_views: function(caller) {
52 update_other_views: function(caller) {
53 this.last_modified_view = caller;
53 this.last_modified_view = caller;
54 this.save(this.changedAttributes(), {patch: true});
54 this.save(this.changedAttributes(), {patch: true});
55
55
56 for (var output_area in this.views) {
56 for (var output_area in this.views) {
57 var views = this.views[output_area];
57 var views = this.views[output_area];
58 for (var view_index in views) {
58 for (var view_index in views) {
59 var view = views[view_index];
59 var view = views[view_index];
60 if (view !== caller) {
60 if (view !== caller) {
61 view.update();
61 view.update();
62 }
62 }
63 }
63 }
64 }
64 }
65 },
65 },
66
66
67
67
68 handle_status: function (output_area, msg) {
68 handle_status: function (output_area, msg) {
69 //execution_state : ('busy', 'idle', 'starting')
69 //execution_state : ('busy', 'idle', 'starting')
70 if (msg.content.execution_state=='idle') {
70 if (msg.content.execution_state=='idle') {
71
71
72 // Send buffer if this message caused another message to be
72 // Send buffer if this message caused another message to be
73 // throttled.
73 // throttled.
74 if (this.msg_buffer != null &&
74 if (this.msg_buffer != null &&
75 this.msg_throttle == this.pending_msgs) {
75 this.msg_throttle == this.pending_msgs) {
76
76
77 var output_area = this._get_output_area(msg.parent_header.msg_id);
77 var output_area = this._get_output_area(msg.parent_header.msg_id);
78 var callbacks = this._make_callbacks(output_area);
78 var callbacks = this._make_callbacks(output_area);
79 var data = {sync_method: 'update', sync_data: this.msg_buffer};
79 var data = {sync_method: 'update', sync_data: this.msg_buffer};
80 this.comm.send(data, callbacks);
80 this.comm.send(data, callbacks);
81 this.msg_buffer = null;
81 this.msg_buffer = null;
82 } else {
82 } else {
83
83
84 // Only decrease the pending message count if the buffer
84 // Only decrease the pending message count if the buffer
85 // doesn't get flushed (sent).
85 // doesn't get flushed (sent).
86 --this.pending_msgs;
86 --this.pending_msgs;
87 }
87 }
88 }
88 }
89 },
89 },
90
90
91
91
92 // Custom syncronization logic.
92 // Custom syncronization logic.
93 handle_sync: function (method, options) {
93 handle_sync: function (method, options) {
94 var model_json = this.toJSON();
94 var model_json = this.toJSON();
95
95
96 // Only send updated state if the state hasn't been changed
96 // Only send updated state if the state hasn't been changed
97 // during an update.
97 // during an update.
98 if (!this.updating) {
98 if (!this.updating) {
99 if (this.pending_msgs >= this.msg_throttle) {
99 if (this.pending_msgs >= this.msg_throttle) {
100 // The throttle has been exceeded, buffer the current msg so
100 // The throttle has been exceeded, buffer the current msg so
101 // it can be sent once the kernel has finished processing
101 // it can be sent once the kernel has finished processing
102 // some of the existing messages.
102 // some of the existing messages.
103 if (method=='patch') {
103 if (method=='patch') {
104 if (this.msg_buffer == null) {
104 if (this.msg_buffer == null) {
105 this.msg_buffer = $.extend({}, model_json); // Copy
105 this.msg_buffer = $.extend({}, model_json); // Copy
106 }
106 }
107 for (var attr in options.attrs) {
107 for (var attr in options.attrs) {
108 this.msg_buffer[attr] = options.attrs[attr];
108 this.msg_buffer[attr] = options.attrs[attr];
109 }
109 }
110 } else {
110 } else {
111 this.msg_buffer = $.extend({}, model_json); // Copy
111 this.msg_buffer = $.extend({}, model_json); // Copy
112 }
112 }
113
113
114 } else {
114 } else {
115 // We haven't exceeded the throttle, send the message like
115 // We haven't exceeded the throttle, send the message like
116 // normal. If this is a patch operation, just send the
116 // normal. If this is a patch operation, just send the
117 // changes.
117 // changes.
118 var send_json = model_json;
118 var send_json = model_json;
119 if (method=='patch') {
119 if (method=='patch') {
120 send_json = {};
120 send_json = {};
121 for (var attr in options.attrs) {
121 for (var attr in options.attrs) {
122 send_json[attr] = options.attrs[attr];
122 send_json[attr] = options.attrs[attr];
123 }
123 }
124 }
124 }
125
125
126 var data = {sync_method: method, sync_data: send_json};
126 var data = {sync_method: method, sync_data: send_json};
127 var output_area = this.last_modified_view.output_area;
127
128 var output_area = null;
129 if (this.last_modified_view != undefined && this.last_modified_view != null) {
130 output_area = this.last_modified_view.output_area;
131 }
132
128 var callbacks = this._make_callbacks(output_area);
133 var callbacks = this._make_callbacks(output_area);
129 this.comm.send(data, callbacks);
134 this.comm.send(data, callbacks);
130 this.pending_msgs++;
135 this.pending_msgs++;
131 }
136 }
132 }
137 }
133
138
134 // Since the comm is a one-way communication, assume the message
139 // Since the comm is a one-way communication, assume the message
135 // arrived.
140 // arrived.
136 return model_json;
141 return model_json;
137 },
142 },
138
143
139
144
140 // Handle incomming comm msg.
145 // Handle incomming comm msg.
141 handle_comm_msg: function (msg) {
146 handle_comm_msg: function (msg) {
142 var method = msg.content.data.method;
147 var method = msg.content.data.method;
143 switch (method){
148 switch (method){
144 case 'display':
149 case 'display':
145
150
146 // Try to get the cell index.
151 // Try to get the cell index.
147 var output_area = this._get_output_area(msg.parent_header.msg_id);
152 var output_area = this._get_output_area(msg.parent_header.msg_id);
148 if (output_area == null) {
153 if (output_area == null) {
149 console.log("Could not determine where the display" +
154 console.log("Could not determine where the display" +
150 " message was from. Widget will not be displayed")
155 " message was from. Widget will not be displayed")
151 } else {
156 } else {
152 this.display_view(msg.content.data.view_name,
157 this.display_view(msg.content.data.view_name,
153 msg.content.data.parent,
158 msg.content.data.parent,
154 output_area);
159 output_area);
155 }
160 }
156 break;
161 break;
157 case 'update':
162 case 'update':
158 this.handle_update(msg.content.data.state);
163 this.handle_update(msg.content.data.state);
159 break;
164 break;
160 }
165 }
161 },
166 },
162
167
163
168
164 // Handle when a widget is updated via the python side.
169 // Handle when a widget is updated via the python side.
165 handle_update: function (state) {
170 handle_update: function (state) {
166 this.updating = true;
171 this.updating = true;
167 try {
172 try {
168 for (var key in state) {
173 for (var key in state) {
169 if (state.hasOwnProperty(key)) {
174 if (state.hasOwnProperty(key)) {
170 if (key == "_css"){
175 if (key == "_css"){
171 this.css = state[key];
176 this.css = state[key];
172 } else {
177 } else {
173 this.set(key, state[key]);
178 this.set(key, state[key]);
174 }
179 }
175 }
180 }
176 }
181 }
177 this.id = this.comm.comm_id;
182 this.id = this.comm.comm_id;
178 this.save();
183 this.save();
179 } finally {
184 } finally {
180 this.updating = false;
185 this.updating = false;
181 }
186 }
182 },
187 },
183
188
184
189
185 // Handle when a widget is closed.
190 // Handle when a widget is closed.
186 handle_comm_closed: function (msg) {
191 handle_comm_closed: function (msg) {
187 for (var output_area in this.views) {
192 for (var output_area in this.views) {
188 var views = this.views[output_area];
193 var views = this.views[output_area];
189 for (var view_index in views) {
194 for (var view_index in views) {
190 var view = views[view_index];
195 var view = views[view_index];
191 view.remove();
196 view.remove();
192 }
197 }
193 }
198 }
194 },
199 },
195
200
196
201
197 // Create view that represents the model.
202 // Create view that represents the model.
198 display_view: function (view_name, parent_comm_id, output_area) {
203 display_view: function (view_name, parent_comm_id, output_area) {
199 var new_views = [];
204 var new_views = [];
200
205
201 var displayed = false;
206 var displayed = false;
202 if (parent_comm_id != undefined) {
207 if (parent_comm_id != undefined) {
203 var parent_comm = this.comm_manager.comms[parent_comm_id];
208 var parent_comm = this.comm_manager.comms[parent_comm_id];
204 var parent_model = parent_comm.model;
209 var parent_model = parent_comm.model;
205 var parent_views = parent_model.views[output_area];
210 var parent_views = parent_model.views[output_area];
206 for (var parent_view_index in parent_views) {
211 for (var parent_view_index in parent_views) {
207 var parent_view = parent_views[parent_view_index];
212 var parent_view = parent_views[parent_view_index];
208 if (parent_view.display_child != undefined) {
213 if (parent_view.display_child != undefined) {
209 var view = this._create_view(view_name, output_area);
214 var view = this._create_view(view_name, output_area);
210 new_views.push(view);
215 new_views.push(view);
211 parent_view.display_child(view);
216 parent_view.display_child(view);
212 displayed = true;
217 displayed = true;
213 }
218 }
214 }
219 }
215 }
220 }
216
221
217 if (!displayed) {
222 if (!displayed) {
218 // No parent view is defined or exists. Add the view's
223 // No parent view is defined or exists. Add the view's
219 // element to cell's widget div.
224 // element to cell's widget div.
220 var view = this._create_view(view_name, output_area);
225 var view = this._create_view(view_name, output_area);
221 new_views.push(view);
226 new_views.push(view);
222 this._get_widget_area_element(output_area, true)
227 this._get_widget_area_element(output_area, true)
223 .append(view.$el);
228 .append(view.$el);
224
229
225 }
230 }
226
231
227 for (var view_index in new_views) {
232 for (var view_index in new_views) {
228 var view = new_views[view_index];
233 var view = new_views[view_index];
229 view.update();
234 view.update();
230 }
235 }
231 },
236 },
232
237
233
238
234 // Create a view
239 // Create a view
235 _create_view: function (view_name, output_area) {
240 _create_view: function (view_name, output_area) {
236 var view = new this.widget_view_types[view_name]({model: this});
241 var view = new this.widget_view_types[view_name]({model: this});
237 view.render();
242 view.render();
238 if (this.views[output_area]==undefined) {
243 if (this.views[output_area]==undefined) {
239 this.views[output_area] = []
244 this.views[output_area] = []
240 }
245 }
241 this.views[output_area].push(view);
246 this.views[output_area].push(view);
242 view.output_area = output_area;
247 view.output_area = output_area;
243
248
244 // Handle when the view element is remove from the page.
249 // Handle when the view element is remove from the page.
245 var that = this;
250 var that = this;
246 view.$el.on("remove", function(){
251 view.$el.on("remove", function(){
247 var index = that.views[output_area].indexOf(view);
252 var index = that.views[output_area].indexOf(view);
248 if (index > -1) {
253 if (index > -1) {
249 that.views[output_area].splice(index, 1);
254 that.views[output_area].splice(index, 1);
250 }
255 }
251 view.remove(); // Clean-up view
256 view.remove(); // Clean-up view
252 if (that.views[output_area].length()==0) {
257 if (that.views[output_area].length()==0) {
253 delete that.views[output_area];
258 delete that.views[output_area];
254 }
259 }
255
260
256 // Close the comm if there are no views left.
261 // Close the comm if there are no views left.
257 if (that.views.length()==0) {
262 if (that.views.length()==0) {
258 that.comm.close();
263 that.comm.close();
259 }
264 }
260 });
265 });
261 return view;
266 return view;
262 },
267 },
263
268
264
269
265 // Build a callback dict.
270 // Build a callback dict.
266 _make_callbacks: function (output_area) {
271 _make_callbacks: function (output_area) {
267 var callbacks = {};
272 var callbacks = {};
268 if (output_area != null) {
273 if (output_area != null) {
269 var that = this;
274 var that = this;
270 callbacks = {
275 callbacks = {
271 iopub : {
276 iopub : {
272 output : $.proxy(output_area.handle_output, output_area),
277 output : $.proxy(output_area.handle_output, output_area),
273 clear_output : $.proxy(output_area.handle_clear_output, output_area),
278 clear_output : $.proxy(output_area.handle_clear_output, output_area),
274 status : function(msg){
279 status : function(msg){
275 that.handle_status(output_area, msg);
280 that.handle_status(output_area, msg);
276 },
281 },
277 get_output_area : function() {
282 get_output_area : function() {
278 if (that.last_modified_view != undefined &&
283 if (that.last_modified_view != undefined &&
279 that.last_modified_view.output_area != undefined) {
284 that.last_modified_view.output_area != undefined) {
280 return that.last_modified_view.output_area;
285 return that.last_modified_view.output_area;
281 } else {
286 } else {
282 return null
287 return null
283 }
288 }
284 },
289 },
285 },
290 },
286 };
291 };
287 }
292 }
288 return callbacks;
293 return callbacks;
289 },
294 },
290
295
291
296
292 // Get the output area corresponding to the msg_id.
297 // Get the output area corresponding to the msg_id.
293 // output_area is an instance of Ipython.OutputArea
298 // output_area is an instance of Ipython.OutputArea
294 _get_output_area: function (msg_id) {
299 _get_output_area: function (msg_id) {
295
300
296 // First, guess cell.execute triggered
301 // First, guess cell.execute triggered
297 var cells = IPython.notebook.get_cells();
302 var cells = IPython.notebook.get_cells();
298 for (var cell_index in cells) {
303 for (var cell_index in cells) {
299 if (cells[cell_index].last_msg_id == msg_id) {
304 if (cells[cell_index].last_msg_id == msg_id) {
300 var cell = IPython.notebook.get_cell(cell_index)
305 var cell = IPython.notebook.get_cell(cell_index)
301 return cell.output_area;
306 return cell.output_area;
302 }
307 }
303 }
308 }
304
309
305 // Second, guess widget triggered
310 // Second, guess widget triggered
306 var callbacks = this.comm_manager.kernel.get_callbacks_for_msg(msg_id)
311 var callbacks = this.comm_manager.kernel.get_callbacks_for_msg(msg_id)
307 if (callbacks != undefined && callbacks.iopub != undefined && callbacks.iopub.get_output_area != undefined) {
312 if (callbacks != undefined && callbacks.iopub != undefined && callbacks.iopub.get_output_area != undefined) {
308 var output_area = callbacks.iopub.get_output_area();
313 var output_area = callbacks.iopub.get_output_area();
309 if (output_area != null) {
314 if (output_area != null) {
310 return output_area;
315 return output_area;
311 }
316 }
312 }
317 }
313
318
314 // Not triggered by a widget or a cell
319 // Not triggered by a widget or a cell
315 return null;
320 return null;
316 },
321 },
317
322
318 // Gets widget output area (as a JQuery element) from the
323 // Gets widget output area (as a JQuery element) from the
319 // output_area (Ipython.OutputArea instance)
324 // output_area (Ipython.OutputArea instance)
320 _get_widget_area_element: function (output_area, show) {
325 _get_widget_area_element: function (output_area, show) {
321 var widget_area = output_area.element
326 var widget_area = output_area.element
322 .parent() // output_wrapper
327 .parent() // output_wrapper
323 .parent() // cell
328 .parent() // cell
324 .find('.widget-area');
329 .find('.widget-area');
325 if (show) { widget_area.show(); }
330 if (show) { widget_area.show(); }
326 return widget_area.find('.widget-subarea');
331 return widget_area.find('.widget-subarea');
327 },
332 },
328
333
329 });
334 });
330
335
331
336
332 //--------------------------------------------------------------------
337 //--------------------------------------------------------------------
333 // WidgetView class
338 // WidgetView class
334 //--------------------------------------------------------------------
339 //--------------------------------------------------------------------
335 var WidgetView = Backbone.View.extend({
340 var WidgetView = Backbone.View.extend({
336
341
337 initialize: function() {
342 initialize: function() {
338 this.visible = true;
343 this.visible = true;
339 this.model.on('change',this.update,this);
344 this.model.on('change',this.update,this);
340 this._add_class_calls = this.model.get('_add_class')[0];
345 this._add_class_calls = this.model.get('_add_class')[0];
341 this._remove_class_calls = this.model.get('_remove_class')[0];
346 this._remove_class_calls = this.model.get('_remove_class')[0];
342 },
347 },
343
348
344 update: function() {
349 update: function() {
345 if (this.model.get('visible') != undefined) {
350 if (this.model.get('visible') != undefined) {
346 if (this.visible != this.model.get('visible')) {
351 if (this.visible != this.model.get('visible')) {
347 this.visible = this.model.get('visible');
352 this.visible = this.model.get('visible');
348 if (this.visible) {
353 if (this.visible) {
349 this.$el.show();
354 this.$el.show();
350 } else {
355 } else {
351 this.$el.hide();
356 this.$el.hide();
352 }
357 }
353 }
358 }
354 }
359 }
355
360
356 if (this.model.css != undefined) {
361 if (this.model.css != undefined) {
357 for (var selector in this.model.css) {
362 for (var selector in this.model.css) {
358 if (this.model.css.hasOwnProperty(selector)) {
363 if (this.model.css.hasOwnProperty(selector)) {
359
364
360 // Apply the css traits to all elements that match the selector.
365 // Apply the css traits to all elements that match the selector.
361 var elements = this.get_selector_element(selector);
366 var elements = this.get_selector_element(selector);
362 if (elements.length > 0) {
367 if (elements.length > 0) {
363 var css_traits = this.model.css[selector];
368 var css_traits = this.model.css[selector];
364 for (var css_key in css_traits) {
369 for (var css_key in css_traits) {
365 if (css_traits.hasOwnProperty(css_key)) {
370 if (css_traits.hasOwnProperty(css_key)) {
366 elements.css(css_key, css_traits[css_key]);
371 elements.css(css_key, css_traits[css_key]);
367 }
372 }
368 }
373 }
369 }
374 }
370 }
375 }
371 }
376 }
372 }
377 }
373
378
374 var add_class = this.model.get('_add_class');
379 var add_class = this.model.get('_add_class');
375 if (add_class != undefined){
380 if (add_class != undefined){
376 var add_class_calls = add_class[0];
381 var add_class_calls = add_class[0];
377 if (add_class_calls > this._add_class_calls) {
382 if (add_class_calls > this._add_class_calls) {
378 this._add_class_calls = add_class_calls;
383 this._add_class_calls = add_class_calls;
379 var elements = this.get_selector_element(add_class[1]);
384 var elements = this.get_selector_element(add_class[1]);
380 if (elements.length > 0) {
385 if (elements.length > 0) {
381 elements.addClass(add_class[2]);
386 elements.addClass(add_class[2]);
382 }
387 }
383 }
388 }
384 }
389 }
385
390
386 var remove_class = this.model.get('_remove_class');
391 var remove_class = this.model.get('_remove_class');
387 if (remove_class != undefined){
392 if (remove_class != undefined){
388 var remove_class_calls = remove_class[0];
393 var remove_class_calls = remove_class[0];
389 if (remove_class_calls > this._remove_class_calls) {
394 if (remove_class_calls > this._remove_class_calls) {
390 this._remove_class_calls = remove_class_calls;
395 this._remove_class_calls = remove_class_calls;
391 var elements = this.get_selector_element(remove_class[1]);
396 var elements = this.get_selector_element(remove_class[1]);
392 if (elements.length > 0) {
397 if (elements.length > 0) {
393 elements.removeClass(remove_class[2]);
398 elements.removeClass(remove_class[2]);
394 }
399 }
395 }
400 }
396 }
401 }
397 },
402 },
398
403
399 get_selector_element: function(selector) {
404 get_selector_element: function(selector) {
400 // Get the elements via the css selector. If the selector is
405 // Get the elements via the css selector. If the selector is
401 // blank, apply the style to the $el_to_style element. If
406 // blank, apply the style to the $el_to_style element. If
402 // the $el_to_style element is not defined, use apply the
407 // the $el_to_style element is not defined, use apply the
403 // style to the view's element.
408 // style to the view's element.
404 var elements = this.$el.find(selector);
409 var elements = this.$el.find(selector);
405 if (selector=='') {
410 if (selector=='') {
406 if (this.$el_to_style == undefined) {
411 if (this.$el_to_style == undefined) {
407 elements = this.$el;
412 elements = this.$el;
408 } else {
413 } else {
409 elements = this.$el_to_style;
414 elements = this.$el_to_style;
410 }
415 }
411 }
416 }
412 return elements;
417 return elements;
413 },
418 },
414 });
419 });
415
420
416
421
417 //--------------------------------------------------------------------
422 //--------------------------------------------------------------------
418 // WidgetManager class
423 // WidgetManager class
419 //--------------------------------------------------------------------
424 //--------------------------------------------------------------------
420 var WidgetManager = function(){
425 var WidgetManager = function(){
421 this.comm_manager = null;
426 this.comm_manager = null;
422 this.widget_model_types = {};
427 this.widget_model_types = {};
423 this.widget_view_types = {};
428 this.widget_view_types = {};
424
429
425 var that = this;
430 var that = this;
426 Backbone.sync = function(method, model, options, error) {
431 Backbone.sync = function(method, model, options, error) {
427 var result = model.handle_sync(method, options);
432 var result = model.handle_sync(method, options);
428 if (options.success) {
433 if (options.success) {
429 options.success(result);
434 options.success(result);
430 }
435 }
431 };
436 };
432 }
437 }
433
438
434
439
435 WidgetManager.prototype.attach_comm_manager = function (comm_manager) {
440 WidgetManager.prototype.attach_comm_manager = function (comm_manager) {
436 this.comm_manager = comm_manager;
441 this.comm_manager = comm_manager;
437
442
438 // Register already register widget model types with the comm manager.
443 // Register already register widget model types with the comm manager.
439 for (var widget_model_name in this.widget_model_types) {
444 for (var widget_model_name in this.widget_model_types) {
440 this.comm_manager.register_target(widget_model_name, $.proxy(this.handle_com_open, this));
445 this.comm_manager.register_target(widget_model_name, $.proxy(this.handle_com_open, this));
441 }
446 }
442 }
447 }
443
448
444
449
445 WidgetManager.prototype.register_widget_model = function (widget_model_name, widget_model_type) {
450 WidgetManager.prototype.register_widget_model = function (widget_model_name, widget_model_type) {
446 // Register the widget with the comm manager. Make sure to pass this object's context
451 // Register the widget with the comm manager. Make sure to pass this object's context
447 // in so `this` works in the call back.
452 // in so `this` works in the call back.
448 if (this.comm_manager!=null) {
453 if (this.comm_manager!=null) {
449 this.comm_manager.register_target(widget_model_name, $.proxy(this.handle_com_open, this));
454 this.comm_manager.register_target(widget_model_name, $.proxy(this.handle_com_open, this));
450 }
455 }
451 this.widget_model_types[widget_model_name] = widget_model_type;
456 this.widget_model_types[widget_model_name] = widget_model_type;
452 }
457 }
453
458
454
459
455 WidgetManager.prototype.register_widget_view = function (widget_view_name, widget_view_type) {
460 WidgetManager.prototype.register_widget_view = function (widget_view_name, widget_view_type) {
456 this.widget_view_types[widget_view_name] = widget_view_type;
461 this.widget_view_types[widget_view_name] = widget_view_type;
457 }
462 }
458
463
459
464
460 WidgetManager.prototype.handle_com_open = function (comm, msg) {
465 WidgetManager.prototype.handle_com_open = function (comm, msg) {
461 var widget_type_name = msg.content.target_name;
466 var widget_type_name = msg.content.target_name;
462 var widget_model = new this.widget_model_types[widget_type_name](this.comm_manager, comm, this.widget_view_types);
467 var widget_model = new this.widget_model_types[widget_type_name](this.comm_manager, comm, this.widget_view_types);
463 }
468 }
464
469
465
470
466 //--------------------------------------------------------------------
471 //--------------------------------------------------------------------
467 // Init code
472 // Init code
468 //--------------------------------------------------------------------
473 //--------------------------------------------------------------------
469 IPython.WidgetManager = WidgetManager;
474 IPython.WidgetManager = WidgetManager;
470 IPython.WidgetModel = WidgetModel;
475 IPython.WidgetModel = WidgetModel;
471 IPython.WidgetView = WidgetView;
476 IPython.WidgetView = WidgetView;
472
477
473 IPython.widget_manager = new WidgetManager();
478 IPython.widget_manager = new WidgetManager();
474
479
475 });
480 });
General Comments 0
You need to be logged in to leave comments. Login now