Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow text input on slider widgets #6106

Merged
merged 7 commits into from Oct 9, 2014

Conversation

chronitis
Copy link
Contributor

This adds "click-to-edit" to the text readout to the right of a slider, allowing precise values to be set.

Changes are entirely on the javascript. Editing is handled using the HTML5 contentEditable attribute rather than explicitly creating any input widget. The modified value is committed by either clicking outside the text, or pressing enter. Works for both Int and FloatSliderView.

The new value is validated for float/int and min/max, but the step size (if set) is not enforced.

This will need updating if #6050 is merged.

@minrk
Copy link
Member

minrk commented Jul 23, 2014

ping @ellisonbg, @jdfreder for review

@minrk minrk added this to the 3.0 milestone Jul 23, 2014
@ellisonbg
Copy link
Member

Haven't looked at the implementation yet.

Is this something we want to support? It adds complexity and textual editing of the slider's value can already be done by linking it to a second text input widget. It also impacts the visual size of the slider - I think it is important to keep it compact. I am probably 50/50 myself.

@chronitis
Copy link
Contributor Author

The layout of the slider is not actually changed.

If the slider is created with readout=True (the default) a label with the value is already displayed to the right. This just allows you to click the existing label and edit the contents inplace.

If readout is disabled, no label is displayed and this does nothing.

The use case is wanting to normally be able to try a range of values, in typical data-exploration style, but occasionally wanting to be able to cherry-pick a specific (probably round) value which mouse resolution makes difficult to select with the slider (eg, when you can only manage to select 99 or 101). This I would assert is something that people might want to do relatively often without wanting to go back and alter the slider parameters or set up a bound text entry widget.

The change consists only of setting the contentEditable attribute on the label and adding an event handler to detect a new value being entered.

@SylvainCorlay
Copy link
Member

content_editable could also be a key of the widget.

@jdfreder
Copy link
Member

jdfreder commented Aug 5, 2014

I think this implementation is overly complicated- it seems like you are just reimplementing the IntTextView and FloatTextView here. Did you look at replacing the readout with them instead?

@chronitis
Copy link
Contributor Author

Using IntTextView as a child of the slider would require dealing with synchronisation between the traits and probably complications in nesting the box models and events - probably doable, but I don't think it could be done more simply than this.

It is true that the handleTextChange function largely duplicates IntTextView.handleChanging. I can see if it is possible to re-use the existing function.

@chronitis
Copy link
Contributor Author

@jdfreder https://gist.github.com/chronitis/5bb76f913aa91eebc177 shows a possible re-working (the common validate and update logic is removed from both widgets to a separate function). I'm not sure if this actually makes it more readable though - let me know if this seems a reasonable direction and I'll commit this to the PR.

@jasongrout
Copy link
Member

Not using content editable makes it work better for numeric input on mobile, I think. For example, see http://sagecell.sagemath.org/?q=dxgrse

@chronitis
Copy link
Contributor Author

http://caniuse.com/#feat=contenteditable claims very wide support (everything minus android 2.3 and opera mini) for contenteditable, but the Sage version using input does look pretty good too - preferences?

@jasongrout
Copy link
Member

but the input also pulls up a numeric keyboard on mobile, IIRC. Would contenteditable? I think mobile in general has a hard time with knowing when to pull up a keyboard on content editable, and definitely wouldn't know to bring up a numeric keyboard.

@ellisonbg
Copy link
Member

@jdfreder @jasongrout @SylvainCorlay can you folks make a decision on this widget related PR and push it through review. In our call today, we decided that in principle we are OK with it - but you 3 should make the final decision.

@SylvainCorlay
Copy link
Member

I have not read the code yet. I imagine that one may not want to enable content-editable for all sliders. Having a widget key to enable/disable it (set to true by default) could be an option.

@chronitis
Copy link
Contributor Author

I can add a trait to the widget that disables this behaviour easily (and will, if there is consensus to do so) - but I wonder if doing it on a per-widget basis makes sense?

It is not obvious to me that a user is likely to care enough to selectively disable this on certain sliders (or other widgets) but not others. A global option to enable or disable use of content-editable perhaps makes more sense?

@jasongrout
Copy link
Member

It is not obvious to me that a user is likely to care enough to selectively disable this on certain sliders (or other widgets) but not others. A global option to enable or disable use of content-editable perhaps makes more sense?

If that's the case, then it would make more sense to have a subclass the user can use that has the current behavior, rather than a global option.

@jasongrout
Copy link
Member

I have not read the code yet. I imagine that one may not want to enable content-editable for all sliders. Having a widget key to enable/disable it (set to true by default) could be an option.

I think we ought to just enable it always, and wait for usecases to come up where you don't want enabled before adding an option to turn it off.

@jdfreder
Copy link
Member

TODO: I'm going to review the gist you published.

Sorry for the delay, I've been away a couple of weeks.

@@ -9,6 +9,10 @@ define([
var IntTextView = int_widgets.IntTextView;

var FloatSliderView = IntSliderView.extend({
_parse_text_input: parseFloat,

_range_regex: /^\s*([+-]?\d*\.?\d+)\s*[-:]\s*([+-]?\d*\.?\d+)/,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be ^\s*([+-]?\d*\.?\d?)\s*[-:]\s*([+-]?\d*\.?\d?) which allows the python shorthand float declaration, i.e. 1.-2..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As written this matches a lone decimal point, and does not match numbers with >1 decimal place - but I agree with the point. I'll fix it so it matches 1..

Edit: I think ([+-]?(?:\d*\.?\d+|\d+\.)(?:[eE][+-]?\d+)?) (x2) matches all appropriate patterns, including exponents (which are probably wanted for scientific use).

@jdfreder
Copy link
Member

@jdfreder https://gist.github.com/chronitis/5bb76f913aa91eebc177 shows a possible re-working (the common validate and update logic is removed from both widgets to a separate function). I'm not sure if this actually makes it more readable though - let me know if this seems a reasonable direction and I'll commit this to the PR.

Hey @chronitis , thanks for trying this. This isn't actually what I was envisioning, I was talking about scrapping the use of content-editable all together and just re-using the numeric text widgets as readouts (of course with some styling changes). I don't think this makes sense anymore, now that the slider widgets support value ranges. I added a couple of comments inline, otherwise the code looks good.

} else {
// clamp to range
values = [Math.max(Math.min(values[0], vmax), vmin),
Math.max(Math.min(values[1], vmax), vmin)];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At first glance I thought this would cause trouble, since you do not check if min and max are undefined, but the widget won't exist in the front-end until it's been opened from the back-end, and the second it's opened from the back-end, a full state is pushed. When a widget like this is opened from the front-end, it will be important to remember that some values have to be defined on the model before it will work properly (this is probably not the only place) @jasongrout @SylvainCorlay .

@Carreau
Copy link
Member

Carreau commented Sep 24, 2014

Leaving on need review (cause we need to finish reviewing), but will need a rebase at some point also.

@chronitis
Copy link
Contributor Author

Rebased to current master.

},

handleKeyDown: function(e) {
if (e.keyCode == 13) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to require static/base/js/keyboard and user keycode.enter here ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 for this suggestion

@Carreau
Copy link
Member

Carreau commented Oct 1, 2014

Looks good. I had a quick overview, but I'm not conforable on widgets.

One potential minor comment to use explicit keymap with enter instead of hardcoded 13.
But it is just a suggestion.

@jdfreder
Copy link
Member

jdfreder commented Oct 8, 2014

Thanks @chronitis this looks good. I'm marking it as ready to merge and I'll let someone else click the button!

@Carreau
Copy link
Member

Carreau commented Oct 9, 2014

Agreed looks good. I'll push the green button.

Carreau added a commit that referenced this pull request Oct 9, 2014
@Carreau Carreau merged commit d4de7b7 into ipython:master Oct 9, 2014
@chronitis chronitis deleted the interact-slider-textedit branch October 9, 2014 15:46
mattvonrocketstein pushed a commit to mattvonrocketstein/ipython that referenced this pull request Nov 3, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants