##// END OF EJS Templates
Add Promise support to models.
Jonathan Frederic -
Show More
@@ -172,11 +172,19 b' define(['
172
172
173 WidgetManager.prototype.get_model = function (model_id) {
173 WidgetManager.prototype.get_model = function (model_id) {
174 // Look-up a model instance by its id.
174 // Look-up a model instance by its id.
175 var model = this._models[model_id];
175 var that = this;
176 if (model !== undefined && model.id == model_id) {
176 var model = that._models[model_id];
177 return model;
177 if (model !== undefined) {
178 return new Promise(function(resolve, reject){
179 if (model instanceof Promise) {
180 model.then(resolve, reject);
181 } else {
182 resolve(model);
183 }
184 });
185 } else {
186 return undefined;
178 }
187 }
179 return null;
180 };
188 };
181
189
182 WidgetManager.prototype._handle_comm_open = function (comm, msg) {
190 WidgetManager.prototype._handle_comm_open = function (comm, msg) {
@@ -213,30 +221,32 b' define(['
213 // widget_class: (optional) string
221 // widget_class: (optional) string
214 // Target name of the widget in the back-end.
222 // Target name of the widget in the back-end.
215 // comm: (optional) Comm
223 // comm: (optional) Comm
216 return new Promise(function(resolve, reject) {
224
225 // Create a comm if it wasn't provided.
226 var comm = options.comm;
227 if (!comm) {
228 comm = this.comm_manager.new_comm('ipython.widget', {'widget_class': options.widget_class});
229 }
230
231 var that = this;
232 var model_id = comm.comm_id;
233 var promise = new Promise(function(resolve, reject) {
217
234
218 // Get the model type using require or through the registry.
235 // Get the model type using require or through the registry.
219 var widget_type_name = options.model_name;
236 var widget_type_name = options.model_name;
220 var widget_module = options.model_module;
237 var widget_module = options.model_module;
221 var that = this;
222 utils.try_load(widget_type_name, widget_module, WidgetManager._model_types)
238 utils.try_load(widget_type_name, widget_module, WidgetManager._model_types)
223 .then(function(ModelType) {
239 .then(function(ModelType) {
224
225 // Create a comm if it wasn't provided.
226 var comm = options.comm;
227 if (!comm) {
228 comm = that.comm_manager.new_comm('ipython.widget', {'widget_class': options.widget_class});
229 }
230
231 var model_id = comm.comm_id;
232 var widget_model = new ModelType(that, model_id, comm);
240 var widget_model = new ModelType(that, model_id, comm);
233 widget_model.on('comm:close', function () {
241 widget_model.on('comm:close', function () {
234 delete that._models[model_id];
242 delete that._models[model_id];
235 });
243 });
236 that._models[model_id] = widget_model;
244 that._models[model_id] = widget_model;
237 reolve(widget_model);
245 resolve(widget_model);
238 }, reject);
246 }, reject);
239 });
247 });
248 this._models[model_id] = promise;
249 return promise;
240 };
250 };
241
251
242 // Backwards compatibility.
252 // Backwards compatibility.
@@ -92,11 +92,22 b' define(["widgets/js/manager",'
92 // Handle when a widget is updated via the python side.
92 // Handle when a widget is updated via the python side.
93 this.state_lock = state;
93 this.state_lock = state;
94 try {
94 try {
95 var that = this;
95 var state_keys = [];
96 WidgetModel.__super__.set.apply(this, [Object.keys(state).reduce(function(obj, key) {
96 var state_values = [];
97 obj[key] = that._unpack_models(state[key]);
97 for (var state_key in Object.keys(state)) {
98 return obj;
98 if (state.hasOwnProperty(state_key)) {
99 }, {})]);
99 state_keys.push(state_key);
100 state_values.push(this._unpack_models(state[state_key]));
101 }
102 }
103
104 Promise.all(state_values).then(function(promise_values){
105 var unpacked_state = {};
106 for (var i = 0; i < state_keys.length; i++) {
107 unpacked_state[state_keys[i]] = promise_values[i];
108 }
109 WidgetModel.__super__.set.apply(this, [unpacked_state]);
110 }, console.error);
100 } finally {
111 } finally {
101 this.state_lock = null;
112 this.state_lock = null;
102 }
113 }
@@ -254,30 +265,42 b' define(["widgets/js/manager",'
254 // Replace model ids with models recursively.
265 // Replace model ids with models recursively.
255 var that = this;
266 var that = this;
256 var unpacked;
267 var unpacked;
257 if ($.isArray(value)) {
268 return new Promise(function(resolve, reject) {
258 unpacked = [];
259 _.each(value, function(sub_value, key) {
260 unpacked.push(that._unpack_models(sub_value));
261 });
262 return unpacked;
263
264 } else if (value instanceof Object) {
265 unpacked = {};
266 _.each(value, function(sub_value, key) {
267 unpacked[key] = that._unpack_models(sub_value);
268 });
269 return unpacked;
270
269
271 } else if (typeof value === 'string' && value.slice(0,10) === "IPY_MODEL_") {
270 if ($.isArray(value)) {
272 var model = this.widget_manager.get_model(value.slice(10, value.length));
271 unpacked = [];
273 if (model) {
272 _.each(value, function(sub_value, key) {
274 return model;
273 unpacked.push(that._unpack_models(sub_value));
274 });
275 Promise.all(unpacked).then(resolve, reject);
276
277 } else if (value instanceof Object) {
278 unpacked_values = [];
279 unpacked_keys = [];
280 _.each(value, function(sub_value, key) {
281 unpacked_keys.push(key);
282 unpacked_values.push(that._unpack_models(sub_value));
283 });
284
285 Promise.all(unpacked_values).then(function(promise_values) {
286 unpacked = {};
287 for (var i = 0; i < unpacked_keys.length; i++) {
288 unpacked[unpacked_keys[i]] = promise_values[i];
289 }
290 resolve(unpacked);
291 }, reject);
292
293 } else if (typeof value === 'string' && value.slice(0,10) === "IPY_MODEL_") {
294 var model = this.widget_manager.get_model(value.slice(10, value.length));
295 if (model) {
296 model.then(resolve, reject);
297 } else {
298 resolve(value);
299 }
275 } else {
300 } else {
276 return value;
301 resolve(value);
277 }
302 }
278 } else {
303 });
279 return value;
280 }
281 },
304 },
282
305
283 on_some_change: function(keys, callback, context) {
306 on_some_change: function(keys, callback, context) {
@@ -322,11 +345,11 b' define(["widgets/js/manager",'
322 //
345 //
323 // -given a model and (optionally) a view name if the view name is
346 // -given a model and (optionally) a view name if the view name is
324 // not given, it defaults to the model's default view attribute.
347 // not given, it defaults to the model's default view attribute.
348 var that = this;
325 return new Promise(function(resolve, reject) {
349 return new Promise(function(resolve, reject) {
326 // TODO: this is hacky, and makes the view depend on this cell attribute and widget manager behavior
350 // TODO: this is hacky, and makes the view depend on this cell attribute and widget manager behavior
327 // it would be great to have the widget manager add the cell metadata
351 // it would be great to have the widget manager add the cell metadata
328 // to the subview without having to add it here.
352 // to the subview without having to add it here.
329 var that = this;
330 options = $.extend({ parent: this }, options || {});
353 options = $.extend({ parent: this }, options || {});
331
354
332 this.model.widget_manager.create_view(child_model, options).then(function(child_view) {
355 this.model.widget_manager.create_view(child_model, options).then(function(child_view) {
General Comments 0
You need to be logged in to leave comments. Login now