diff --git a/IPython/html/static/notebook/js/widget.js b/IPython/html/static/notebook/js/widget.js index 177b1cd6c..4be054751 100644 --- a/IPython/html/static/notebook/js/widget.js +++ b/IPython/html/static/notebook/js/widget.js @@ -309,6 +309,8 @@ 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]; }, update: function() { @@ -322,25 +324,14 @@ define(["components/underscore/underscore-min", } } } + if (this.model.css != undefined) { for (var selector in this.model.css) { if (this.model.css.hasOwnProperty(selector)) { - // Get the elements via the css selector. If the selector is - // blank, apply the style to the $el_to_style element. If - // 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 (this.$el_to_style == undefined) { - elements = this.$el; - } else { - elements = this.$el_to_style; - } - } - // Apply the css traits to all elements that match the selector. - if (elements.length>0){ + var elements = this.get_selector_element(selector); + if (elements.length > 0) { var css_traits = this.model.css[selector]; for (var css_key in css_traits) { if (css_traits.hasOwnProperty(css_key)) { @@ -351,6 +342,46 @@ 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) { + // Get the elements via the css selector. If the selector is + // blank, apply the style to the $el_to_style element. If + // 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 (this.$el_to_style == undefined) { + elements = this.$el; + } else { + elements = this.$el_to_style; + } + } + return elements; }, }); diff --git a/IPython/html/widgets/widget.py b/IPython/html/widgets/widget.py index 2205cf102..3069afa9e 100644 --- a/IPython/html/widgets/widget.py +++ b/IPython/html/widgets/widget.py @@ -44,6 +44,9 @@ def init_widget_js(): #----------------------------------------------------------------------------- class Widget(LoggingConfigurable): + # Shared declarations + _keys = [] + # Public declarations target_name = Unicode('widget', help="""Name of the backbone model registered in the frontend to create and sync this widget with.""") @@ -64,11 +67,12 @@ class Widget(LoggingConfigurable): new._children.append(self) if old is not None and self in old._children: old._children.remove(self) - + # Private/protected declarations - _keys = [] _property_lock = False - _css = Dict() + _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 @@ -87,6 +91,8 @@ class Widget(LoggingConfigurable): via the default_view_name property. """ self._children = [] + self._add_class = [0] + self._remove_class = [0] super(Widget, self).__init__(**kwargs) # Register after init to allow default values to be specified @@ -108,7 +114,7 @@ class Widget(LoggingConfigurable): # Properties def _get_keys(self): - keys = ['_css', 'visible'] + keys = ['visible', '_css', '_add_class', '_remove_class'] keys.extend(self._keys) return keys keys = property(_get_keys) @@ -212,7 +218,39 @@ class Widget(LoggingConfigurable): # Only update the property if it has changed. if not (key in self._css[selector] and value in self._css[selector][key]): self._css[selector][key] = value - self.send_state() # Send new state to client. + self.send_state('_css') # Send new state to client. + + + def add_class(self, class_name, selector=""): + """Add class[es] to a DOM element + + Parameters + ---------- + class_name: unicode + Class name(s) to add to the DOM element(s). Multiple class names + must be space separated. + selector: unicode (optional) + 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') + + + def remove_class(self, class_name, selector=""): + """Remove class[es] from a DOM element + + Parameters + ---------- + class_name: unicode + Class name(s) to remove from the DOM element(s). Multiple class + names must be space separated. + selector: unicode (optional) + 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') # Support methods