diff --git a/IPython/html/static/notebook/js/widget.js b/IPython/html/static/notebook/js/widget.js
index 823939fac..f36da0739 100644
--- a/IPython/html/static/notebook/js/widget.js
+++ b/IPython/html/static/notebook/js/widget.js
@@ -32,7 +32,7 @@ define(["static/components/underscore/underscore-min.js",
//--------------------------------------------------------------------
var WidgetModel = Backbone.Model.extend({
apply: function(sender) {
- this.save();
+ this.save(this.changedAttributes(), {patch: true});
for (var index in this.views) {
var view = this.views[index];
@@ -95,7 +95,7 @@ define(["static/components/underscore/underscore-min.js",
var that = this;
Backbone.sync = function(method, model, options, error) {
- var result = that.send_sync(method, model);
+ var result = that.send_sync(method, model, options);
if (options.success) {
options.success(result);
}
@@ -214,6 +214,7 @@ define(["static/components/underscore/underscore-min.js",
}
}
}
+ comm.model.id = comm.comm_id;
comm.model.save();
this.updating = false;
}
@@ -234,7 +235,7 @@ define(["static/components/underscore/underscore-min.js",
}
// Send widget state to python backend.
- WidgetManager.prototype.send_sync = function (method, model) {
+ WidgetManager.prototype.send_sync = function (method, model, options) {
var model_json = model.toJSON();
// Only send updated state if the state hasn't been changed during an update.
@@ -250,10 +251,21 @@ define(["static/components/underscore/underscore-min.js",
clear_output : $.proxy(outputarea.handle_clear_output, outputarea)}
};
};
- var data = {sync_method: method, sync_data: model_json};
+
+ // If this is a patch operation, just send the changes.
+ var send_json = model_json;
+ if (method=='patch') {
+ send_json = {};
+ for (var attr in options.attrs) {
+ send_json[attr] = options.attrs[attr];
+ }
+ }
+ var data = {sync_method: method, sync_data: send_json};
comm.send(data, callbacks);
}
+ // Since the comm is a one-way communication, assume the message
+ // arrived.
return model_json;
}
diff --git a/IPython/html/widgets/widget.py b/IPython/html/widgets/widget.py
index 2a36aa795..08e03c4ca 100644
--- a/IPython/html/widgets/widget.py
+++ b/IPython/html/widgets/widget.py
@@ -96,11 +96,10 @@ class Widget(LoggingConfigurable):
### Event handlers
def _handle_msg(self, msg):
- # Handle backbone sync methods
+ # Handle backbone sync methods CREATE, PATCH, and UPDATE
sync_method = msg['content']['data']['sync_method']
sync_data = msg['content']['data']['sync_data']
- if sync_method.lower() in ['create', 'update']:
- self._handle_recieve_state(sync_data)
+ self._handle_recieve_state(sync_data) # handles all methods
def _handle_recieve_state(self, sync_data):
@@ -119,7 +118,7 @@ class Widget(LoggingConfigurable):
if not self._property_lock and self.comm is not None:
# TODO: Validate properties.
# Send new state to frontend
- self.send_state()
+ self.send_state(key=name)
def _handle_close(self):
@@ -154,8 +153,15 @@ class Widget(LoggingConfigurable):
return None
- def send_state(self):
+ def send_state(self, key=None):
state = {}
+
+ # If a key is provided, just send the state of that key.
+ keys = []
+ if key is None:
+ keys.extend(self.keys)
+ else:
+ keys.append(key)
for key in self.keys:
try:
state[key] = getattr(self, key)