diff --git a/IPython/html/static/notebook/js/widgets/string.js b/IPython/html/static/notebook/js/widgets/string.js
index f221d8d..16af4bb 100644
--- a/IPython/html/static/notebook/js/widgets/string.js
+++ b/IPython/html/static/notebook/js/widgets/string.js
@@ -113,7 +113,7 @@ define(["notebook/js/widget"], function(widget_manager){
// Handles: Backend -> Frontend Sync
// Frontent -> Frontend Sync
update : function(){
- if (!this.user_invoked_update) {
+ if (this.$textbox.val() != this.model.get('value')) {
this.$textbox.val(this.model.get('value'));
}
@@ -137,19 +137,15 @@ define(["notebook/js/widget"], function(widget_manager){
// Handles and validates user input.
handleChanging: function(e) {
- this.user_invoked_update = true;
this.model.set('value', e.target.value);
this.model.update_other_views(this);
- this.user_invoked_update = false;
},
// Handles text submition
handleKeypress: function(e) {
if (e.keyCode == 13) { // Return key
- this.user_invoked_update = true;
this.model.set('submits', this.model.get('submits') + 1);
this.model.update_other_views(this);
- this.user_invoked_update = false;
}
},
});
diff --git a/IPython/html/widgets/widget.py b/IPython/html/widgets/widget.py
index 2c540eb..0a2522a 100644
--- a/IPython/html/widgets/widget.py
+++ b/IPython/html/widgets/widget.py
@@ -58,7 +58,7 @@ class Widget(LoggingConfigurable):
old._children.remove(self)
# Private/protected declarations
- _property_lock = False
+ _property_lock = (None, None) # Last updated (key, value) from the front-end. Prevents echo.
_css = Dict() # Internal CSS property dict
_add_class = List() # Used to add a js class to a DOM element (call#, selector, class_name)
_remove_class = List() # Used to remove a js class from a DOM element (call#, selector, class_name)
@@ -153,20 +153,21 @@ class Widget(LoggingConfigurable):
def _handle_recieve_state(self, sync_data):
"""Called when a state is recieved from the frontend."""
- self._property_lock = True
- try:
-
- # Use _keys instead of keys - Don't get retrieve the css from the client side.
- for name in self._keys:
- if name in sync_data:
+ # Use _keys instead of keys - Don't get retrieve the css from the client side.
+ for name in self._keys:
+ if name in sync_data:
+ try:
+ self._property_lock = (name, sync_data[name])
setattr(self, name, sync_data[name])
- finally:
- self._property_lock = False
+ finally:
+ self._property_lock = (None, None)
def _handle_property_changed(self, name, old, new):
"""Called when a proeprty has been changed."""
- if not self._property_lock and self._comm is not None:
+ # Make sure this isn't information that the front-end just sent us.
+ if self._property_lock[0] != name and self._property_lock[1] != new \
+ and self._comm is not None:
# TODO: Validate properties.
# Send new state to frontend
self.send_state(key=name)