From 6e057c18b7c0d5af39b91d7a47a5feb4755b332e 2014-01-16 10:55:58 From: Jonathan Frederic Date: 2014-01-16 10:55:58 Subject: [PATCH] Add int range widget --- diff --git a/IPython/html/widgets/int_range/__init__.py b/IPython/html/widgets/int_range/__init__.py new file mode 100644 index 0000000..ad95056 --- /dev/null +++ b/IPython/html/widgets/int_range/__init__.py @@ -0,0 +1 @@ +from widget import IntRangeWidget \ No newline at end of file diff --git a/IPython/html/widgets/int_range/model.js b/IPython/html/widgets/int_range/model.js new file mode 100644 index 0000000..e927052 --- /dev/null +++ b/IPython/html/widgets/int_range/model.js @@ -0,0 +1,2 @@ +var IntRangeWidgetModel = IPython.WidgetModel.extend({}); +IPython.notebook.widget_manager.register_widget_model('IntRangeWidgetModel', IntRangeWidgetModel); diff --git a/IPython/html/widgets/int_range/view_slider.js b/IPython/html/widgets/int_range/view_slider.js new file mode 100644 index 0000000..17bb0d1 --- /dev/null +++ b/IPython/html/widgets/int_range/view_slider.js @@ -0,0 +1,43 @@ +var IntSliderView = IPython.WidgetView.extend({ + + // Called when view is rendered. + render : function(){ + this.$el.html(''); + this.$slider = $('
') + .slider({}) + .addClass('slider'); + + // Put the slider in a container + this.$slider_container = $('
') + .css('padding-top', '4px') + .css('padding-bottom', '4px') + .addClass(this.model.comm.comm_id) + .append(this.$slider); + this.$el.append(this.$slider_container); + + // Set defaults. + this.update(); + }, + + // Handles: Backend -> Frontend Sync + // Frontent -> Frontend Sync + update : function(){ + // Slider related keys. + var _keys = ['value', 'step', 'max', 'min', 'disabled', 'orientation']; + for (var index in _keys) { + var key = _keys[index]; + if (this.model.get(key) != undefined) { + this.$slider.slider("option", key, this.model.get(key)); + } + } + }, + + // Handles: User input + events: { "slide" : "handleSliderChange" }, + handleSliderChange: function(e, ui) { + this.model.set('value', ~~ui.value); // Double bit-wise not to truncate decimel + this.model.apply(this); + }, +}); + +IPython.notebook.widget_manager.register_widget_view('IntSliderView', IntSliderView); diff --git a/IPython/html/widgets/int_range/view_text.js b/IPython/html/widgets/int_range/view_text.js new file mode 100644 index 0000000..eb35e13 --- /dev/null +++ b/IPython/html/widgets/int_range/view_text.js @@ -0,0 +1,70 @@ +var IntTextView = IPython.WidgetView.extend({ + + // Called when view is rendered. + render : function(){ + this.$el + .html('') + .addClass(this.model.comm.comm_id); + this.$textbox = $('') + .addClass('input') + .appendTo(this.$el); + this.update(); // Set defaults. + }, + + // Handles: Backend -> Frontend Sync + // Frontent -> Frontend Sync + update : function(){ + var value = this.model.get('value'); + if (!this.changing && parseInt(this.$textbox.val()) != value) { + this.$textbox.val(value); + } + + if (this.model.get('disabled')) { + this.$textbox.attr('disabled','disabled'); + } else { + this.$textbox.removeAttr('disabled'); + } + }, + + + events: {"keyup input" : "handleChanging", + "paste input" : "handleChanging", + "cut input" : "handleChanging", + "change input" : "handleChanged"}, // Fires only when control is validated or looses focus. + + // Handles and validates user input. + handleChanging: function(e) { + + // Try to parse value as a float. + var numericalValue = 0; + if (e.target.value != '') { + numericalValue = parseInt(e.target.value); + } + + // If parse failed, reset value to value stored in model. + if (isNaN(numericalValue)) { + e.target.value = this.model.get('value'); + } else if (!isNaN(numericalValue)) { + numericalValue = Math.min(this.model.get('max'), numericalValue); + numericalValue = Math.max(this.model.get('min'), numericalValue); + + // Apply the value if it has changed. + if (numericalValue != this.model.get('value')) { + this.changing = true; + this.model.set('value', numericalValue); + this.model.apply(this); + this.changing = false; + } + } + }, + + // Applies validated input. + handleChanged: function(e) { + // Update the textbox + if (this.model.get('value') != e.target.value) { + e.target.value = this.model.get('value'); + } + } +}); + +IPython.notebook.widget_manager.register_widget_view('IntTextView', IntTextView); diff --git a/IPython/html/widgets/int_range/widget.py b/IPython/html/widgets/int_range/widget.py new file mode 100644 index 0000000..8ad82ba --- /dev/null +++ b/IPython/html/widgets/int_range/widget.py @@ -0,0 +1,17 @@ +import os + +from ..widget import Widget +from IPython.utils.traitlets import Unicode, Int, Bool +from IPython.utils.javascript import display_all_js + +class IntRangeWidget(Widget): + target_name = Unicode('IntRangeWidgetModel') + default_view_name = Unicode('IntSliderView') + _keys = ['value', 'step', 'max', 'min', 'disabled', 'orientation'] + + value = Int(0) + max = Int(100) # Max value + min = Int(0) # Min value + disabled = Bool(False) # Enable or disable user changes + step = Int(1) # Minimum step that the value can take (ignored by some views) + orientation = Unicode(u'horizontal') # Vertical or horizontal (ignored by some views)