diff --git a/IPython/html/static/notebook/js/widgetmanager.js b/IPython/html/static/notebook/js/widgetmanager.js index 26697ae..0e94bda 100644 --- a/IPython/html/static/notebook/js/widgetmanager.js +++ b/IPython/html/static/notebook/js/widgetmanager.js @@ -23,19 +23,6 @@ // elsewhere. define(["underscore", "backbone", - ], function (Underscore, Backbone) { - - Backbone.sync = function (method, model, options) { - // Sync widget models to back-end. - // - // Backbone.sync method must be in widgetmanager.js file instead of - // widget.js so it can be overwritten for different contexts. - var result = model._handle_sync(method, options); - if (options.success) { - options.success(result); - } - }; - //-------------------------------------------------------------------- // WidgetManager class @@ -168,10 +155,6 @@ output : handle_output, clear_output : handle_clear_output, - status : function (msg) { - view.model._handle_status(msg, that.callbacks(view)); - }, - // Special function only registered by widget messages. // Allows us to get the cell for a message so we know // where to add widgets if the code requires it. diff --git a/IPython/html/static/notebook/js/widgets/widget.js b/IPython/html/static/notebook/js/widgets/widget.js index 21c0a69..60994b8 100644 --- a/IPython/html/static/notebook/js/widgets/widget.js +++ b/IPython/html/static/notebook/js/widgets/widget.js @@ -120,57 +120,71 @@ function(WidgetManager, Underscore, Backbone){ } }, - _handle_sync: function (method, options) { - // Custom syncronization logic. - var model_json = this.toJSON(); - var attr; - - // Only send updated state if the state hasn't been changed - // during an update. - if (this.comm !== undefined) { - if (this.pending_msgs >= this.msg_throttle) { - // The throttle has been exceeded, buffer the current msg so - // it can be sent once the kernel has finished processing - // some of the existing messages. - if (this.msg_buffer === null) { - this.msg_buffer = $.extend({}, model_json); // Copy - } - for (attr in options.attrs) { - var value = this._pack_models(options.attrs[attr]); - if (this.key_value_lock === null || attr !== this.key_value_lock[0] || value !== this.key_value_lock[1]) { - this.msg_buffer[attr] = value; - } - } + callbacks: function(callbacks) { + // Create msg callbacks for a comm msg. + var that = this; + if (callbacks.iopub === undefined) {callbacks.iopub = {};} + callbacks.iopub.status = function (msg) { + that._handle_status(msg, callbacks); + } + return callbacks; + }, - } else { - // We haven't exceeded the throttle, send the message like - // normal. If this is a patch operation, just send the - // changes. - var send_json = model_json; - send_json = {}; - for (attr in options.attrs) { - var value = this._pack_models(options.attrs[attr]); - if (this.key_value_lock === null || attr !== this.key_value_lock[0] || value !== this.key_value_lock[1]) { - send_json[attr] = value; - } - } - - var is_empty = true; - for (var prop in send_json) if (send_json.hasOwnProperty(prop)) is_empty = false; - if (!is_empty) { - ++this.pending_msgs; - var data = {method: 'backbone', sync_data: send_json}; - this.comm.send(data, options.callbacks); - } + sync: function (method, model, options) { + var error = options.error || function() {console.error('Backbone sync error:', arguments);} + if (this.comm === undefined) { + error(); + return false; + } + + var attrs = (method==='patch') ? options.attrs : model.toJSON(options); + + if (this.key_value_lock !== null) { + var k = this.key_value_lock[0]; + var v = this.key_value_lock[1]; + if (attrs[k]===v) { + delete attrs[k]; } } + if (_.size(attrs) == 0) { + error(); + return false; + } + var callbacks = model.callbacks(options.callbacks || {}); + if (this.pending_msgs >= this.msg_throttle) { + // The throttle has been exceeded, buffer the current msg so + // it can be sent once the kernel has finished processing + // some of the existing messages. + + // combine updates if it is a 'patch' sync, otherwise replace updates + switch (method) { + case 'patch': + this.msg_buffer = _.extend(this.msg_buffer || {}, attrs); + break; + case 'update': + this.msg_buffer = attrs; + break; + default: + error(); + return false; + } + this.msg_buffer_callbacks = callbacks; + + } else { + // We haven't exceeded the throttle, send the message like + // normal. If this is a patch operation, just send the + // changes. + var data = {method: 'backbone', sync_data: attrs}; + this.comm.send(data, callbacks); + this.pending_msgs++; + } // Since the comm is a one-way communication, assume the message - // arrived. - return model_json; + // arrived. Don't call success since we don't have a model back from the server + // this means we miss out on the 'sync' event. }, - push: function(callbacks) { + save_changes: function(callbacks) { // Push this model's state to the back-end // // This invokes a Backbone.Sync. @@ -294,7 +308,7 @@ function(WidgetManager, Underscore, Backbone){ }, touch: function () { - this.model.push(this.callbacks()); + this.model.save_changes(this.callbacks()); }, });