diff --git a/IPython/html/static/notebook/js/widget.js b/IPython/html/static/notebook/js/widget.js index 79152a4..c6770ae 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 0a2522a..6f2e3e7 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):