Show More
@@ -64,7 +64,7 b' define([' | |||||
64 | if (options === undefined || options.updated_view != this) { |
|
64 | if (options === undefined || options.updated_view != this) { | |
65 | // JQuery slider option keys. These keys happen to have a |
|
65 | // JQuery slider option keys. These keys happen to have a | |
66 | // one-to-one mapping with the corrosponding keys of the model. |
|
66 | // one-to-one mapping with the corrosponding keys of the model. | |
67 |
var jquery_slider_keys = ['step', |
|
67 | var jquery_slider_keys = ['step', 'disabled']; | |
68 | var that = this; |
|
68 | var that = this; | |
69 | that.$slider.slider({}); |
|
69 | that.$slider.slider({}); | |
70 | _.each(jquery_slider_keys, function(key, i) { |
|
70 | _.each(jquery_slider_keys, function(key, i) { | |
@@ -73,6 +73,14 b' define([' | |||||
73 | that.$slider.slider("option", key, model_value); |
|
73 | that.$slider.slider("option", key, model_value); | |
74 | } |
|
74 | } | |
75 | }); |
|
75 | }); | |
|
76 | ||||
|
77 | var max = this.model.get('max'); | |||
|
78 | var min = this.model.get('min'); | |||
|
79 | if (min <= max) { | |||
|
80 | if (max !== undefined) this.$slider.slider('option', 'max', max); | |||
|
81 | if (min !== undefined) this.$slider.slider('option', 'min', min); | |||
|
82 | } | |||
|
83 | ||||
76 | var range_value = this.model.get("_range"); |
|
84 | var range_value = this.model.get("_range"); | |
77 | if (range_value !== undefined) { |
|
85 | if (range_value !== undefined) { | |
78 | this.$slider.slider("option", "range", range_value); |
|
86 | this.$slider.slider("option", "range", range_value); |
@@ -154,4 +154,22 b' casper.notebook_test(function () {' | |||||
154 | this.test.assertEquals(this.get_output_cell(index).text, '50\n', |
|
154 | this.test.assertEquals(this.get_output_cell(index).text, '50\n', | |
155 | 'Invalid int textbox characters ignored'); |
|
155 | 'Invalid int textbox characters ignored'); | |
156 | }); |
|
156 | }); | |
|
157 | ||||
|
158 | index = this.append_cell( | |||
|
159 | 'a = widgets.IntSlider()\n' + | |||
|
160 | 'display(a)\n' + | |||
|
161 | 'a.max = -1\n' + | |||
|
162 | 'print("Success")\n'); | |||
|
163 | this.execute_cell_then(index, function(index){ | |||
|
164 | this.test.assertEquals(0, 0, 'Invalid int range max bound does not cause crash.'); | |||
|
165 | }); | |||
|
166 | ||||
|
167 | index = this.append_cell( | |||
|
168 | 'a = widgets.IntSlider()\n' + | |||
|
169 | 'display(a)\n' + | |||
|
170 | 'a.min = 101\n' + | |||
|
171 | 'print("Success")\n'); | |||
|
172 | this.execute_cell_then(index, function(index){ | |||
|
173 | this.test.assertEquals(0, 0, 'Invalid int range min bound does not cause crash.'); | |||
|
174 | }); | |||
157 | }); No newline at end of file |
|
175 | }); |
@@ -125,7 +125,6 b' class Widget(LoggingConfigurable):' | |||||
125 | self._model_id = kwargs.pop('model_id', None) |
|
125 | self._model_id = kwargs.pop('model_id', None) | |
126 | super(Widget, self).__init__(**kwargs) |
|
126 | super(Widget, self).__init__(**kwargs) | |
127 |
|
127 | |||
128 | self.on_trait_change(self._handle_property_changed, self.keys) |
|
|||
129 | Widget._call_widget_constructed(self) |
|
128 | Widget._call_widget_constructed(self) | |
130 | self.open() |
|
129 | self.open() | |
131 |
|
130 | |||
@@ -323,13 +322,21 b' class Widget(LoggingConfigurable):' | |||||
323 | def _handle_custom_msg(self, content): |
|
322 | def _handle_custom_msg(self, content): | |
324 | """Called when a custom msg is received.""" |
|
323 | """Called when a custom msg is received.""" | |
325 | self._msg_callbacks(self, content) |
|
324 | self._msg_callbacks(self, content) | |
326 |
|
325 | |||
327 |
def _ |
|
326 | def _notify_trait(self, name, old_value, new_value): | |
328 | """Called when a property has been changed.""" |
|
327 | """Called when a property has been changed.""" | |
329 | # Make sure this isn't information that the front-end just sent us. |
|
328 | # Trigger default traitlet callback machinery. This allows any user | |
330 | if self._should_send_property(name, new): |
|
329 | # registered validation to be processed prior to allowing the widget | |
331 | # Send new state to front-end |
|
330 | # machinery to handle the state. | |
332 | self.send_state(key=name) |
|
331 | LoggingConfigurable._notify_trait(self, name, old_value, new_value) | |
|
332 | ||||
|
333 | # Send the state after the user registered callbacks for trait changes | |||
|
334 | # have all fired (allows for user to validate values). | |||
|
335 | if self.comm is not None and name in self.keys: | |||
|
336 | # Make sure this isn't information that the front-end just sent us. | |||
|
337 | if self._should_send_property(name, new_value): | |||
|
338 | # Send new state to front-end | |||
|
339 | self.send_state(key=name) | |||
333 |
|
340 | |||
334 | def _handle_displayed(self, **kwargs): |
|
341 | def _handle_displayed(self, **kwargs): | |
335 | """Called when a view has been displayed for this widget instance""" |
|
342 | """Called when a view has been displayed for this widget instance""" |
@@ -37,13 +37,24 b' class _BoundedInt(_Int):' | |||||
37 | def __init__(self, *pargs, **kwargs): |
|
37 | def __init__(self, *pargs, **kwargs): | |
38 | """Constructor""" |
|
38 | """Constructor""" | |
39 | DOMWidget.__init__(self, *pargs, **kwargs) |
|
39 | DOMWidget.__init__(self, *pargs, **kwargs) | |
40 |
self.on_trait_change(self._validate, ['value' |
|
40 | self.on_trait_change(self._validate_value, ['value']) | |
|
41 | self.on_trait_change(self._handle_max_changed, ['max']) | |||
|
42 | self.on_trait_change(self._handle_min_changed, ['min']) | |||
41 |
|
43 | |||
42 | def _validate(self, name, old, new): |
|
44 | def _validate_value(self, name, old, new): | |
43 |
"""Validate value |
|
45 | """Validate value.""" | |
44 | if self.min > new or new > self.max: |
|
46 | if self.min > new or new > self.max: | |
45 | self.value = min(max(new, self.min), self.max) |
|
47 | self.value = min(max(new, self.min), self.max) | |
46 |
|
48 | |||
|
49 | def _handle_max_changed(self, name, old, new): | |||
|
50 | """Make sure the min is always <= the max.""" | |||
|
51 | if new < self.min: | |||
|
52 | raise ValueError("setting max < min") | |||
|
53 | ||||
|
54 | def _handle_min_changed(self, name, old, new): | |||
|
55 | """Make sure the max is always >= the min.""" | |||
|
56 | if new > self.max: | |||
|
57 | raise ValueError("setting min > max") | |||
47 |
|
58 | |||
48 | class IntText(_Int): |
|
59 | class IntText(_Int): | |
49 | """Textbox widget that represents a int.""" |
|
60 | """Textbox widget that represents a int.""" | |
@@ -134,11 +145,9 b' class _BoundedIntRange(_IntRange):' | |||||
134 | if name == "min": |
|
145 | if name == "min": | |
135 | if new > self.max: |
|
146 | if new > self.max: | |
136 | raise ValueError("setting min > max") |
|
147 | raise ValueError("setting min > max") | |
137 | self.min = new |
|
|||
138 | elif name == "max": |
|
148 | elif name == "max": | |
139 | if new < self.min: |
|
149 | if new < self.min: | |
140 | raise ValueError("setting max < min") |
|
150 | raise ValueError("setting max < min") | |
141 | self.max = new |
|
|||
142 |
|
151 | |||
143 | low, high = self.value |
|
152 | low, high = self.value | |
144 | if name == "value": |
|
153 | if name == "value": |
General Comments 0
You need to be logged in to leave comments.
Login now