From 2af96a67b729db2c18c6206ba7fd35812d7d2d8e 2014-01-22 23:00:36 From: Jonathan Frederic Date: 2014-01-22 23:00:36 Subject: [PATCH] Float widget views now inherit from int counterparts --- diff --git a/IPython/html/static/notebook/js/widgets/widget_float.js b/IPython/html/static/notebook/js/widgets/widget_float.js index 1c98e50..96f8adf 100644 --- a/IPython/html/static/notebook/js/widgets/widget_float.js +++ b/IPython/html/static/notebook/js/widgets/widget_float.js @@ -14,255 +14,29 @@ * @namespace IPython **/ -define(["notebook/js/widgets/widget"], function(WidgetManager){ +define(["notebook/js/widgets/widget", + "notebook/js/widgets/widget_int"], + function(WidgetManager, int_widgets){ - var FloatSliderView = IPython.DOMWidgetView.extend({ - render : function(){ - // Called when view is rendered. - this.$el - .addClass('widget-hbox-single'); - this.$label = $('
') - .appendTo(this.$el) - .addClass('widget-hlabel') - .hide(); - this.$slider = $('
') - .slider({}) - .addClass('slider'); - - // Put the slider in a container - this.$slider_container = $('
') - .addClass('widget-hslider') - .append(this.$slider); - this.$el_to_style = this.$slider_container; // Set default element to style - this.$el.append(this.$slider_container); - - // Set defaults. - this.update(); - }, - - update : function(options){ - // Update the contents of this view - // - // Called when the model is changed. The model may have been - // changed by another view or by a state update from the back-end. - - if (options === undefined || options.updated_view != this) { - // JQuery slider option keys. These keys happen to have a - // one-to-one mapping with the corrosponding keys of the model. - var jquery_slider_keys = ['step', 'max', 'min', 'disabled']; - var that = this; - _.each(jquery_slider_keys, function(key, i) { - var model_value = that.model.get(key); - if (model_value !== undefined) { - that.$slider.slider("option", key, model_value); - } - }); - - // WORKAROUND FOR JQUERY SLIDER BUG. - // The horizontal position of the slider handle - // depends on the value of the slider at the time - // of orientation change. Before applying the new - // workaround, we set the value to the minimum to - // make sure that the horizontal placement of the - // handle in the vertical slider is always - // consistent. - var orientation = this.model.get('orientation'); - var value = this.model.get('min'); - this.$slider.slider('option', 'value', value); - this.$slider.slider('option', 'orientation', orientation); - value = this.model.get('value'); - this.$slider.slider('option', 'value', value); - - // Use the right CSS classes for vertical & horizontal sliders - if (orientation=='vertical') { - this.$slider_container - .removeClass('widget-hslider') - .addClass('widget-vslider'); - this.$el - .removeClass('widget-hbox-single') - .addClass('widget-vbox-single'); - this.$label - .removeClass('widget-hlabel') - .addClass('widget-vlabel'); - - } else { - this.$slider_container - .removeClass('widget-vslider') - .addClass('widget-hslider'); - this.$el - .removeClass('widget-vbox-single') - .addClass('widget-hbox-single'); - this.$label - .removeClass('widget-vlabel') - .addClass('widget-hlabel'); - } + var IntSliderView = int_widgets[0]; + var IntTextView = int_widgets[1]; - var description = this.model.get('description'); - if (description.length === 0) { - this.$label.hide(); - } else { - this.$label.text(description); - this.$label.show(); - } - } - return FloatSliderView.__super__.update.apply(this); - }, - - events: { - // Dictionary of events and their handlers. - "slide" : "handleSliderChange" - }, - - handleSliderChange: function(e, ui) { - // Handle when the slider value is changed. - // Calling model.set will trigger all of the other views of the - // model to update. - this.model.set('value', ui.value, {updated_view: this}); - this.touch(); + var FloatSliderView = IntSliderView.extend({ + _validate_slide_value: function(x) { + // Validate the value of the slider before sending it to the back-end + // and applying it to the other views on the page. + return x; }, }); WidgetManager.register_widget_view('FloatSliderView', FloatSliderView); - var FloatTextView = IPython.DOMWidgetView.extend({ - render : function(){ - // Called when view is rendered. - this.$el - .addClass('widget-hbox-single'); - this.$label = $('
') - .appendTo(this.$el) - .addClass('widget-hlabel') - .hide(); - this.$textbox = $('') - .addClass('input') - .addClass('widget-numeric-text') - .appendTo(this.$el); - this.$el_to_style = this.$textbox; // Set default element to style - this.update(); // Set defaults. - }, - - update : function(options){ - // Update the contents of this view - // - // Called when the model is changed. The model may have been - // changed by another view or by a state update from the back-end. - if (options === undefined || options.updated_view != this) { - var value = this.model.get('value'); - if (parseFloat(this.$textbox.val()) != value) { - this.$textbox.val(value); - } - - if (this.model.get('disabled')) { - this.$textbox.attr('disabled','disabled'); - } else { - this.$textbox.removeAttr('disabled'); - } - - var description = this.model.get('description'); - if (description.length === 0) { - this.$label.hide(); - } else { - this.$label.text(description); - this.$label.show(); - } - } - return FloatTextView.__super__.update.apply(this); - }, - - events: { - // Dictionary of events and their handlers. - - "keyup input" : "handleChanging", - "paste input" : "handleChanging", - "cut input" : "handleChanging", - - // Fires only when control is validated or looses focus. - "change input" : "handleChanged" - }, - - handleChanging: function(e) { - // Handles and validates user input. - - // Try to parse value as a float. - var numericalValue = 0.0; - if (e.target.value !== '') { - numericalValue = parseFloat(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)) { - if (this.model.get('max') !== undefined) { - numericalValue = Math.min(this.model.get('max'), numericalValue); - } - if (this.model.get('min') !== undefined) { - numericalValue = Math.max(this.model.get('min'), numericalValue); - } - - // Apply the value if it has changed. - if (numericalValue != this.model.get('value')) { - - // Calling model.set will trigger all of the other views of the - // model to update. - this.model.set('value', numericalValue, {updated_view: this}); - this.touch(); - } - } + var FloatTextView = IntTextView.extend({ + _parse_value: function(value) { + // Parse the value stored in a string. + return parseFloat(value); }, - - handleChanged: function(e) { - // Applies validated input. - if (this.model.get('value') != e.target.value) { - e.target.value = this.model.get('value'); - } - } }); WidgetManager.register_widget_view('FloatTextView', FloatTextView); - - - var ProgressView = IPython.DOMWidgetView.extend({ - render : function(){ - // Called when view is rendered. - this.$el - .addClass('widget-hbox-single'); - this.$label = $('
') - .appendTo(this.$el) - .addClass('widget-hlabel') - .hide(); - this.$progress = $('
') - .addClass('progress') - .addClass('widget-progress') - .appendTo(this.$el); - this.$el_to_style = this.$progress; // Set default element to style - this.$bar = $('
') - .addClass('bar') - .css('width', '50%') - .appendTo(this.$progress); - this.update(); // Set defaults. - }, - - update : function(){ - // Update the contents of this view - // - // Called when the model is changed. The model may have been - // changed by another view or by a state update from the back-end. - var value = this.model.get('value'); - var max = this.model.get('max'); - var min = this.model.get('min'); - var percent = 100.0 * (value - min) / (max - min); - this.$bar.css('width', percent + '%'); - - var description = this.model.get('description'); - if (description.length === 0) { - this.$label.hide(); - } else { - this.$label.text(description); - this.$label.show(); - } - return ProgressView.__super__.update.apply(this); - }, - }); - WidgetManager.register_widget_view('ProgressView', ProgressView); }); diff --git a/IPython/html/static/notebook/js/widgets/widget_int.js b/IPython/html/static/notebook/js/widgets/widget_int.js index 42b779f..b8278cf 100644 --- a/IPython/html/static/notebook/js/widgets/widget_int.js +++ b/IPython/html/static/notebook/js/widgets/widget_int.js @@ -117,9 +117,17 @@ define(["notebook/js/widgets/widget"], function(WidgetManager){ // Calling model.set will trigger all of the other views of the // model to update. - this.model.set('value', ~~ui.value, {updated_view: this}); // Double bit-wise not to truncate decimel + this.model.set('value', this._validate_slide_value(ui.value), {updated_view: this}); this.touch(); }, + + _validate_slide_value: function(x) { + // Validate the value of the slider before sending it to the back-end + // and applying it to the other views on the page. + + // Double bit-wise not truncates the decimel (int cast). + return ~~x; + }, }); WidgetManager.register_widget_view('IntSliderView', IntSliderView); @@ -148,7 +156,7 @@ define(["notebook/js/widgets/widget"], function(WidgetManager){ // changed by another view or by a state update from the back-end. if (options === undefined || options.updated_view != this) { var value = this.model.get('value'); - if (parseInt(this.$textbox.val()) != value) { + if (this._parse_value(this.$textbox.val()) != value) { this.$textbox.val(value); } @@ -182,10 +190,10 @@ define(["notebook/js/widgets/widget"], function(WidgetManager){ handleChanging: function(e) { // Handles and validates user input. - // Try to parse value as a float. + // Try to parse value as a int. var numericalValue = 0; if (e.target.value !== '') { - numericalValue = parseInt(e.target.value); + numericalValue = this._parse_value(e.target.value); } // If parse failed, reset value to value stored in model. @@ -215,7 +223,62 @@ define(["notebook/js/widgets/widget"], function(WidgetManager){ if (this.model.get('value') != e.target.value) { e.target.value = this.model.get('value'); } - } + }, + + _parse_value: function(value) { + // Parse the value stored in a string. + return parseInt(value); + }, }); WidgetManager.register_widget_view('IntTextView', IntTextView); + + + var ProgressView = IPython.DOMWidgetView.extend({ + render : function(){ + // Called when view is rendered. + this.$el + .addClass('widget-hbox-single'); + this.$label = $('
') + .appendTo(this.$el) + .addClass('widget-hlabel') + .hide(); + this.$progress = $('
') + .addClass('progress') + .addClass('widget-progress') + .appendTo(this.$el); + this.$el_to_style = this.$progress; // Set default element to style + this.$bar = $('
') + .addClass('bar') + .css('width', '50%') + .appendTo(this.$progress); + this.update(); // Set defaults. + }, + + update : function(){ + // Update the contents of this view + // + // Called when the model is changed. The model may have been + // changed by another view or by a state update from the back-end. + var value = this.model.get('value'); + var max = this.model.get('max'); + var min = this.model.get('min'); + var percent = 100.0 * (value - min) / (max - min); + this.$bar.css('width', percent + '%'); + + var description = this.model.get('description'); + if (description.length === 0) { + this.$label.hide(); + } else { + this.$label.text(description); + this.$label.show(); + } + return ProgressView.__super__.update.apply(this); + }, + }); + WidgetManager.register_widget_view('ProgressView', ProgressView); + + + // Return the slider and text views so they can be inheritted to create the + // float versions. + return [IntSliderView, IntTextView]; });