Skip to content
This repository has been archived by the owner on Apr 4, 2019. It is now read-only.

[BUGFIX] Fix text input cursor behavior #447

Merged
merged 1 commit into from
Jan 31, 2016
Merged

[BUGFIX] Fix text input cursor behavior #447

merged 1 commit into from
Jan 31, 2016

Conversation

mmun
Copy link
Collaborator

@mmun mmun commented Jan 29, 2016

People are using bound <input>s. For the most part everything works great.

<input type="checkbox"
       checked={{user.isCool}}
       oninput={{action 'saveCoolness' user}} >

<textarea value={{user.description}}
          oninput={{action 'saveDescription' user}} >
  actions: {
    saveCoolness(user, event) {
      user.set('isCool', event.target.checked);
      Ember.run.throttle(user, 'save', 500);
    },

    saveDescription(user, event) {
      user.set('description', event.target.value);
      Ember.run.throttle(user, 'save', 500);
    }
  }

But not everything is rainbows and butterflies. Text inputs have an annoying
wart. Whenever you update their value, the cursor is moved to the end of the
input. This becomes a problem when you are trying to edit text in the middle of
a text input. Curiously, this issue doesn't affect <textarea> (confirmed on
Firefox/Chrome/Safari).

Here's an ember-twiddle that show cases the
current state of affairs.

Why does this happen?

A little background first. When you edit a text input through the browser GUI the oninput
event is triggered. When you change the input element's value property, the oninput
event is not fired, but the cursor is set to the end of the text field.

Now let's say you write

<input value={{user.name}} oninput={{action 'updateName'}}>

and

actions: {
  updateName(event) {
    this.set('user.name', event.target.value);
  }
}

If you edit the text input the browser will internally update the value property on the
input element and then fire the oninput event. Our handler mutates the value of user.name.
This triggers the value={{user.name}} binding to update, or in other words calls

input.value = user.name

Proposed fix

In order to fix this we can avoid setting .value when we don't need to. This will skirt the issue
of resetting the cursor when value is mutated. Specifically, we add a guard to PropertyAttrMorph
so that we avoid calling input.value = newValue if the follow conditions are met:

  • this.attrName === 'value'
  • this.element.tagName === 'INPUT'
  • this.element.value == newValue

Here is an ember-twiddle with the patch applied.
Note how editing the Name text input works correctly now. Even dead keys work just fine! (Try
entering Option-e + e in the text input. It should generate a "é" character.)

Trade-offs

Making this change has a small trade off. It alters DOM semantics so that, when the conditions
above are met, we treat the mutation as a no-op rather than a set-the-value-to-what-it-already-was.
We believe that this is a very small price to pay for a massive improvement in developer ergonomics.

@cibernox
Copy link

This makes me sooo happy. No more input components.

@stefanpenner
Copy link
Collaborator

Lgtm

@cibernox
Copy link

As a side note, even if you're probably aware, using native inputs is more than on order of magnitude faster and memory is at least 1/3 smaller.

@cibernox
Copy link

Quick benchmark (without this fix): https://benchmark-inputs.pagefrontapp.com/input-helper

Check console.debugs

rwjblue added a commit that referenced this pull request Jan 31, 2016
[BUGFIX] Fix text input cursor behavior
@rwjblue rwjblue merged commit 5a859b9 into master Jan 31, 2016
@rwjblue rwjblue deleted the fix-input-cursor branch January 31, 2016 01:53
mmun added a commit to emberjs/ember.js that referenced this pull request Jan 31, 2016
This PR contains two fixes to htmlbars

1. A fix to the tokenizer: tildeio/htmlbars#443
2. A fix to the behavior of text input cursors: tildeio/htmlbars#447
rwjblue pushed a commit to emberjs/ember.js that referenced this pull request Jan 31, 2016
This PR contains two fixes to htmlbars

1. A fix to the tokenizer: tildeio/htmlbars#443
2. A fix to the behavior of text input cursors: tildeio/htmlbars#447

(cherry picked from commit 40d9ff9)
rwjblue pushed a commit to emberjs/ember.js that referenced this pull request Jan 31, 2016
This PR contains two fixes to htmlbars

1. A fix to the tokenizer: tildeio/htmlbars#443
2. A fix to the behavior of text input cursors: tildeio/htmlbars#447

(cherry picked from commit 40d9ff9)
jcope2013 added a commit to jcope2013/htmlbars that referenced this pull request Jun 21, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants