diff --git a/IPython/html/static/widgets/js/types.js b/IPython/html/static/widgets/js/types.js new file mode 100644 index 0000000..5cc10b3 --- /dev/null +++ b/IPython/html/static/widgets/js/types.js @@ -0,0 +1,50 @@ +// Copyright (c) IPython Development Team. +// Distributed under the terms of the Modified BSD License. + +define([ + "base/js/utils" +], function(utils){ + + return { + widget_serialization: { + deserialize: function deserialize_models(value, model) { + /** + * Replace model ids with models recursively. + */ + var unpacked; + if ($.isArray(value)) { + unpacked = []; + _.each(value, function(sub_value, key) { + unpacked.push(deserialize_models(sub_value, model)); + }); + return Promise.all(unpacked); + } else if (value instanceof Object) { + unpacked = {}; + _.each(value, function(sub_value, key) { + unpacked[key] = deserialize_models(sub_value, model); + }); + return utils.resolve_promises_dict(unpacked); + } else if (typeof value === 'string' && value.slice(0,10) === "IPY_MODEL_") { + // get_model returns a promise already + return model.widget_manager.get_model(value.slice(10, value.length)); + } else { + return Promise.resolve(value); + } + }, + }, + + list_of_numbers: { + deserialize: function (value, model) { + /* value is a DataView */ + /* create a float64 typed array */ + return new Float64Array(value.buffer) + }, + serialize: function (value, model) { + return value; + }, + } + } + + + +}); diff --git a/IPython/html/static/widgets/js/widget.js b/IPython/html/static/widgets/js/widget.js index e5f758d..b837f57 100644 --- a/IPython/html/static/widgets/js/widget.js +++ b/IPython/html/static/widgets/js/widget.js @@ -32,6 +32,7 @@ define(["widgets/js/manager", this.state_lock = null; this.id = model_id; this.views = {}; + this.serializers = {}; this._resolve_received_state = {}; if (comm !== undefined) { @@ -62,13 +63,13 @@ define(["widgets/js/manager", return Backbone.Model.apply(this); }, - send: function (content, callbacks) { + send: function (content, callbacks, buffers) { /** * Send a custom msg over the comm. */ if (this.comm !== undefined) { var data = {method: 'custom', content: content}; - this.comm.send(data, callbacks); + this.comm.send(data, callbacks, {}, buffers); this.pending_msgs++; } }, @@ -136,12 +137,37 @@ define(["widgets/js/manager", * Handle incoming comm msg. */ var method = msg.content.data.method; + var that = this; switch (method) { case 'update': this.state_change = this.state_change .then(function() { - return that.set_state(msg.content.data.state); + var state = msg.content.data.state || {}; + var buffer_keys = msg.content.data.buffers || []; + var buffers = msg.buffers || []; + var metadata = msg.content.data.metadata || {}; + var i,k; + for (var i=0; i 0) { // If this message was sent via backbone itself, it will not @@ -297,9 +346,7 @@ define(["widgets/js/manager", } else { // We haven't exceeded the throttle, send the message like // normal. - var data = {method: 'backbone', sync_data: attrs}; - this.comm.send(data, callbacks); - this.pending_msgs++; + this.send_sync_message(attrs, callbacks); } } // Since the comm is a one-way communication, assume the message @@ -308,68 +355,71 @@ define(["widgets/js/manager", this._buffered_state_diff = {}; }, - save_changes: function(callbacks) { - /** - * Push this model's state to the back-end - * - * This invokes a Backbone.Sync. - */ - this.save(this._buffered_state_diff, {patch: true, callbacks: callbacks}); - }, - _pack_models: function(value) { - /** - * Replace models with model ids recursively. - */ + send_sync_message: function(attrs, callbacks) { + // prepare and send a comm message syncing attrs var that = this; - var packed; - if (value instanceof Backbone.Model) { - return "IPY_MODEL_" + value.id; - - } else if ($.isArray(value)) { - packed = []; - _.each(value, function(sub_value, key) { - packed.push(that._pack_models(sub_value)); - }); - return packed; - } else if (value instanceof Date || value instanceof String) { - return value; - } else if (value instanceof Object) { - packed = {}; - _.each(value, function(sub_value, key) { - packed[key] = that._pack_models(sub_value); - }); - return packed; - - } else { - return value; + // first, build a state dictionary with key=the attribute and the value + // being the value or the promise of the serialized value + var state_promise_dict = {}; + var keys = Object.keys(attrs); + for (var i=0; i