How to get text of an input text box during onKeyP

2019-01-10 10:21发布

I am trying to get the text in a text box as the user types in it (jsfiddle playground):

function edValueKeyPress() {
    var edValue = document.getElementById("edValue");
    var s = edValue.value;

    var lblValue = document.getElementById("lblValue");
    lblValue.innerText = "The text box contains: " + s;

    //var s = $("#edValue").val();
    //$("#lblValue").text(s);    
}
<input id="edValue" type="text" onKeyPress="edValueKeyPress()"><br>
<span id="lblValue">The text box contains: </span>

​ The code runs without errors, except that the value of the input text box, during onKeyPress is always the value before the change:

enter image description here

Question: How do I get the text of a text box during onKeyPress?

Bonus Chatter

There are three events related to "the user is typing" in the HTML DOM:

  • onKeyDown
  • onKeyPress
  • onKeyUp

In Windows, the order of WM_Key messages becomes important when the user holds down a key, and the key begins to repeat:

  • WM_KEYDOWN('a') - user has pushed down the A key
  • WM_CHAR('a') - an a character has been received from the user
  • WM_CHAR('a') - an a character has been received from the user
  • WM_CHAR('a') - an a character has been received from the user
  • WM_CHAR('a') - an a character has been received from the user
  • WM_CHAR('a') - an a character has been received from the user
  • WM_KEYUP('a') - the user has released the A key

Will result in five characters appearing in a text control: aaaaa

The important point being that the you respond to the WM_CHAR message, the one that repeats. Otherwise you miss events when a key is pressed.

In HTML things are slightly different:

  • onKeyDown
  • onKeyPress
  • onKeyDown
  • onKeyPress
  • onKeyDown
  • onKeyPress
  • onKeyDown
  • onKeyPress
  • onKeyDown
  • onKeyPress
  • onKeyUp

Html delivers an KeyDown and KeyPress every key repeat. And the KeyUp event is only raised when the user releases the key.

Take aways

  • I can respond to onKeyDown or onKeyPress, but both are still raised before the input.value has been updated
  • I cannot respond to onKeyUp, because it doesn't happen as the text in the text-box changes.

Question: How do I get the text of a text-box during onKeyPress?

Bonus Reading

11条回答
【Aperson】
2楼-- · 2019-01-10 11:09

None of the answers so far offer a complete solution. There are quite a few issues to address:

  1. Not all keypresses are passed onto keydown and keypress handlers (e.g. backspace and delete keys are suppressed by some browsers).
  2. Handling keydown is not a good idea. There are situations where a keydown does NOT result in a keypress!
  3. setTimeout() style solutions get delayed under Google Chrome/Blink web browsers until the user stops typing.
  4. Mouse and touch events may be used to perform actions such as cut, copy, and paste. Those events will not trigger keyboard events.
  5. The browser, depending on the input method, may not deliver notification that the element has changed until the user navigates away from the field.

A more correct solution will handle the keypress, keyup, input, and change events.

Example:

<p><input id="editvalue" type="text"></p>
<p>The text box contains: <span id="labelvalue"></span></p>

<script>
function UpdateDisplay()
{
    var inputelem = document.getElementById("editvalue");
    var s = inputelem.value;

    var labelelem = document.getElementById("labelvalue");
    labelelem.innerText = s;
}

// Initial update.
UpdateDisplay();

// Register event handlers.
var inputelem = document.getElementById("editvalue");
inputelem.addEventListener('keypress', UpdateDisplay);
inputelem.addEventListener('keyup', UpdateDisplay);
inputelem.addEventListener('input', UpdateDisplay);
inputelem.addEventListener('change', UpdateDisplay);
</script>

Fiddle:

http://jsfiddle.net/VDd6C/2175/

Handling all four events catches all of the edge cases. When working with input from a user, all types of input methods should be considered and cross-browser and cross-device functionality should be verified. The above code has been tested in Firefox, Edge, and Chrome on desktop as well as the mobile devices I own.

查看更多
Anthone
3楼-- · 2019-01-10 11:11

So there are advantages and disadvantages to each event. The events onkeypress and onkeydown don't retrieve the latest value, and onkeypress doesn't fire for non-printable characters in some browsers. The onkeyup event doesn't detect when a key is held down for multiple characters.

This is a little hacky, but doing something like

function edValueKeyDown(input) {
    var s = input.value;

    var lblValue = document.getElementById("lblValue");
    lblValue.innerText = "The text box contains: "+s;

    //var s = $("#edValue").val();
    //$("#lblValue").text(s);    
}
<input id="edValue" type="text" onkeydown="setTimeout(edValueKeyDown, 0, this)" />

seems to handle the best of all worlds.

查看更多
你好瞎i
4楼-- · 2019-01-10 11:12

the value of the input text box, during onKeyPress is always the value before the change

This is on purpose: This allows the event listener to cancel the keypress.

If the event listeners cancels the event, the value is not updated. If the event is not canceled, the value is updated, but after the event listener was called.

To get the value after the field value has been updated, schedule a function to run on the next event loop. The usual way to do this is to call setTimeout with a timeout of 0:

$('#field').keyup(function() {
    var $field = $(this);

    // this is the value before the keypress
    var beforeVal = $field.val();

    setTimeout(function() {

        // this is the value after the keypress
        var afterVal = $field.val();
    }, 0);
});

Try here: http://jsfiddle.net/Q57gY/2/

Edit: Some browsers (e.g. Chrome) do not trigger keypress events for backspace; changed keypress to keyup in code.

查看更多
做个烂人
5楼-- · 2019-01-10 11:12

easy...

In your keyPress event handler, write

void ValidateKeyPressHandler(object sender, KeyPressEventArgs e)
{
    var tb = sender as TextBox;
    var startPos = tb.SelectionStart;
    var selLen= tb.SelectionLength;

    var afterEditValue = tb.Text.Remove(startPos, selLen)
                .Insert(startPos, e.KeyChar.ToString()); 
    //  ... more here
}
查看更多
forever°为你锁心
6楼-- · 2019-01-10 11:16

keep it Compact.
Each time you press a key, the function edValueKeyPress() is called.
You've also declared and initialized some variables in that function - which slow down the process and requires more CPU and memory as well.
You can simply use this code - derived from simple substitution.

function edValueKeyPress()
{
    document.getElementById("lblValue").innerText =""+document.getElementById("edValue").value;
}

That's all you want, and it's faster!

查看更多
登录 后发表回答