diff --git a/IPython/html/static/notebook/js/widget.js b/IPython/html/static/notebook/js/widget.js
index 79152a465..c6770aebb 100644
--- a/IPython/html/static/notebook/js/widget.js
+++ b/IPython/html/static/notebook/js/widget.js
@@ -108,13 +108,7 @@ define(["components/underscore/underscore-min",
// Handle when a widget is closed.
_handle_comm_closed: function (msg) {
- for (var cell in this.views) {
- var views = this.views[cell];
- for (var view_index in views) {
- var view = views[view_index];
- view.remove();
- }
- }
+ this._execute_views_method('remove');
delete this.comm.model; // Delete ref so GC will collect widget model.
},
@@ -139,6 +133,12 @@ define(["components/underscore/underscore-min",
case 'update':
this._handle_update(msg.content.data.state);
break;
+ case 'add_class':
+ case 'remove_class':
+ var selector = msg.content.data.selector;
+ var class_list = msg.content.data.class_list;
+ this._execute_views_method(method, selector, class_list);
+ break;
case 'custom':
this._handle_custom_msg(msg.content.data.custom_content);
break;
@@ -262,6 +262,28 @@ define(["components/underscore/underscore-min",
},
+ _execute_views_method: function (/* method_name, [argument0], [argument1], [...] */) {
+ var method_name = arguments[0];
+ var args = null;
+ if (arguments.length > 1) {
+ args = [].splice.call(arguments,1);
+ }
+
+ for (var cell in this.views) {
+ var views = this.views[cell];
+ for (var view_index in views) {
+ var view = views[view_index];
+ var method = view[method_name];
+ if (args === null) {
+ method.apply(view);
+ } else {
+ method.apply(view, args);
+ }
+ }
+ }
+ },
+
+
// Create view that represents the model.
_display_view: function (view_name, parent_comm_id, cell) {
var new_views = [];
@@ -428,10 +450,22 @@ define(["components/underscore/underscore-min",
initialize: function() {
this.visible = true;
this.model.on('change',this.update,this);
- this._add_class_calls = this.model.get('_add_class')[0];
- this._remove_class_calls = this.model.get('_remove_class')[0];
},
+ add_class: function(selector, class_list){
+ var elements = this._get_selector_element(selector);
+ if (elements.length > 0) {
+ elements.addClass(class_list);
+ }
+ },
+
+ remove_class: function(selector, class_list){
+ var elements = this._get_selector_element(selector);
+ if (elements.length > 0) {
+ elements.removeClass(class_list);
+ }
+ },
+
update: function() {
if (this.model.get('visible') != undefined) {
if (this.visible != this.model.get('visible')) {
@@ -461,30 +495,6 @@ define(["components/underscore/underscore-min",
}
}
}
-
- var add_class = this.model.get('_add_class');
- if (add_class != undefined){
- var add_class_calls = add_class[0];
- if (add_class_calls > this._add_class_calls) {
- this._add_class_calls = add_class_calls;
- var elements = this._get_selector_element(add_class[1]);
- if (elements.length > 0) {
- elements.addClass(add_class[2]);
- }
- }
- }
-
- var remove_class = this.model.get('_remove_class');
- if (remove_class != undefined){
- var remove_class_calls = remove_class[0];
- if (remove_class_calls > this._remove_class_calls) {
- this._remove_class_calls = remove_class_calls;
- var elements = this._get_selector_element(remove_class[1]);
- if (elements.length > 0) {
- elements.removeClass(remove_class[2]);
- }
- }
- }
},
_get_selector_element: function(selector) {
@@ -493,7 +503,7 @@ define(["components/underscore/underscore-min",
// the $el_to_style element is not defined, use apply the
// style to the view's element.
var elements = this.$el.find(selector);
- if (selector=='') {
+ if (selector===undefined || selector===null || selector=='') {
if (this.$el_to_style == undefined) {
elements = this.$el;
} else {
diff --git a/IPython/html/widgets/widget.py b/IPython/html/widgets/widget.py
index 0a2522aa8..6f2e3e786 100644
--- a/IPython/html/widgets/widget.py
+++ b/IPython/html/widgets/widget.py
@@ -60,8 +60,6 @@ class Widget(LoggingConfigurable):
# Private/protected declarations
_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)
_displayed = False
_comm = None
@@ -80,8 +78,6 @@ class Widget(LoggingConfigurable):
via the default_view_name property.
"""
self._children = []
- self._add_class = [0]
- self._remove_class = [0]
self._display_callbacks = []
self._msg_callbacks = []
super(Widget, self).__init__(**kwargs)
@@ -108,7 +104,7 @@ class Widget(LoggingConfigurable):
# Properties
def _get_keys(self):
- keys = ['visible', '_css', '_add_class', '_remove_class']
+ keys = ['visible', '_css']
keys.extend(self._keys)
return keys
keys = property(_get_keys)
@@ -309,8 +305,9 @@ class Widget(LoggingConfigurable):
JQuery selector to select the DOM element(s) that the class(es) will
be added to.
"""
- self._add_class = [self._add_class[0] + 1, selector, class_name]
- self.send_state(key='_add_class')
+ self._comm.send({"method": "add_class",
+ "class_list": class_name,
+ "selector": selector})
def remove_class(self, class_name, selector=""):
@@ -325,8 +322,9 @@ class Widget(LoggingConfigurable):
JQuery selector to select the DOM element(s) that the class(es) will
be removed from.
"""
- self._remove_class = [self._remove_class[0] + 1, selector, class_name]
- self.send_state(key='_remove_class')
+ self._comm.send({"method": "remove_class",
+ "class_list": class_name,
+ "selector": selector})
def send(self, content):