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());
},
});