¿Cómo obtener el texto de un cuadro de texto de entrada durante onKeyPress?

85

Estoy tratando de obtener el texto en un cuadro de texto mientras el usuario escribe en él ( 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>

El código se ejecuta sin errores, excepto que el valor del input textcuadro, durante onKeyPresses siempre el valor antes del cambio:

ingrese la descripción de la imagen aquí

Pregunta : ¿Cómo obtengo el texto de un cuadro de texto durante onKeyPress?

Chatter adicional

Hay tres eventos relacionados con "el usuario está escribiendo" en el DOM HTML:

  • onKeyDown
  • onKeyPress
  • onKeyUp

En Windows , el orden de los WM_Keymensajes se vuelve importante cuando el usuario mantiene presionada una tecla y la tecla comienza a repetirse:

  • WM_KEYDOWN('a')- el usuario ha pulsado la Atecla
  • WM_CHAR('a')- ase ha recibido un personaje del usuario
  • WM_CHAR('a')- ase ha recibido un personaje del usuario
  • WM_CHAR('a')- ase ha recibido un personaje del usuario
  • WM_CHAR('a')- ase ha recibido un personaje del usuario
  • WM_CHAR('a')- ase ha recibido un personaje del usuario
  • WM_KEYUP('a')- el usuario ha soltado la Allave

Dará como resultado la aparición de cinco caracteres en un control de texto: aaaaa

Lo importante es que tú respondas al WM_CHARmensaje, el que se repite. De lo contrario, perderá eventos cuando se presione una tecla.

En HTML, las cosas son ligeramente diferentes:

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

Html ofrece una KeyDowny KeyPresscada tecla repetida. Y el KeyUpevento solo se genera cuando el usuario suelta la tecla.

Para llevar

  • Yo puedo responder a onKeyDowno onKeyPress, pero ambos todavía se levantan antes de que el input.valuese ha actualizado
  • No puedo responder onKeyUp, porque no sucede cuando cambia el texto en el cuadro de texto.

Pregunta: ¿Cómo obtengo el texto de un cuadro de texto durante onKeyPress?

Lectura adicional

Ian Boyd
fuente
1
Creo que debe agregar la pulsación de tecla actual al valor antes de devolverlo; el valor se actualiza en keyUp, pero los datos están disponibles en keyDown.
Mathletics
Key up funciona para mí, no necesitas jQ para algo como esto, a menos que quieras agregar hinchazón
Ryan B
es suficiente solo enKeyUp para su tarea
dmytro
El manejo de @mit Only onKeyUpno muestra los cambios en el cuadro de texto a medida que ocurren.
Ian Boyd
si desea mantener presionada cualquier tecla y obtener el resultado en el cuadro de texto, por supuesto, debe usar el violín de Jonathan M de los eventos onKeyPress y onKeyDown , pero si desea obtener un resultado sin mantener presionadas las teclas, es suficiente solo enKeyUp mi violín .
dmytro

Respuestas:

19

Manejar el inputevento es una solución consistente: es compatible con elementos textareay inputen todos los navegadores contemporáneos y se activa exactamente cuando lo necesita:

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

    var lblValue = document.getElementById("lblValue");
    lblValue.innerText = "The text box contains: " + s;
}
<input id="edValue" type="text" onInput="edValueKeyPress()"><br>
<span id="lblValue">The text box contains: </span>

Sin embargo, reescribiría esto un poco:

function showCurrentValue(event)
{
    const value = event.target.value;
    document.getElementById("lblValue").innerText = value;
}
<input id="edValue" type="text" onInput="showCurrentValue(event)"><br>
The text box contains: <span id="lblValue"></span>

YakovL
fuente
54

Mantenlo simple. Utilice ambos onKeyPress()y onKeyUp():

<input id="edValue" type="text" onKeyPress="edValueKeyPress()" onKeyUp="edValueKeyPress()">

Esto se encarga de obtener el valor de cadena más actualizado (después de subir la tecla) y también se actualiza si el usuario mantiene presionada una tecla.

jsfiddle: http://jsfiddle.net/VDd6C/8/

Jonathan M
fuente
Dado que la respuesta de arnaud576875 tuvo que rendirse y retroceder (anulando onKeyUpel propósito del uso onKeypress), esta es la respuesta más simple, limpia y cercana que cualquiera verá. Solo el usuario más atento notará que los comentarios no coinciden con lo que ingresaron.
Ian Boyd
@Ian, encantado de ayudar. ¿Qué quiere decir con "los comentarios no coinciden con lo que ingresaron"? ¿Se necesita un ajuste?
Jonathan M
¡Recuerdo lo que quise decir ahora! La retroalimentación a la que me refiero sería colorear el <input>elemento en rojo o verde, o dar alguna otra retroalimentación al usuario de que lo que ha escrito es bueno o malo. Si bien su respuesta aceptada todavía adolece del problema de ser siempre un carácter de "uno por uno" : solo el usuario más atento notará que los comentarios no coinciden con lo que ingresaron ". En realidad, dado que el un error solo ocurre durante la repetición de teclas (es decir, mantienen presionada la tecla) nadie (además de mí) va a notar el problema.
Ian Boyd
19

el valor del cuadro de texto de entrada, durante onKeyPress es siempre el valor antes del cambio

Esto es a propósito: esto permite que el oyente del evento cancele la pulsación de tecla.

Si los detectores de eventos cancelan el evento , el valor no se actualiza. Si el evento no se cancela, el valor se actualiza, pero después de llamar al detector de eventos .

Para obtener el valor después de que se haya actualizado el valor del campo, programe una función para que se ejecute en el siguiente ciclo de eventos. La forma habitual de hacer esto es llamar setTimeoutcon un tiempo de espera de 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);
});

Pruebe aquí: http://jsfiddle.net/Q57gY/2/

Editar : algunos navegadores (por ejemplo, Chrome) no activan eventos de pulsación de teclas para retroceso; se cambió la pulsación de tecla a tecla en el código.

Arnaud Le Blanc
fuente
Estaba a punto de publicar esto. Aquí está el jsFiddle que hice.
kapa
Tienes razón, parece que Chrome no activa eventos de pulsación de teclas para retroceder; actualizado
Arnaud Le Blanc
@Ian, ¿el OP quiere que se actualice cuando se mantiene presionada una tecla? No estaba muy seguro de si esto era un requisito. Sin embargo, esta solución no tiene esa funcionalidad.
Jonathan M
Para ser claros: No activar eventos de pulsación de tecla para retroceso es por Estándar: "tecla que produce un valor de carácter" - para otras teclas use "keydown" (antes del cambio, cancelable) o "keyup" (después del cambio)
sebilasse
5

manténgalo compacto.
Cada vez que presiona una tecla, edValueKeyPress()se llama a la función .
También ha declarado e inicializado algunas variables en esa función, lo que ralentiza el proceso y también requiere más CPU y memoria.
Simplemente puede usar este código, derivado de una simple sustitución.

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

Eso es todo lo que quieres y es más rápido.

Wajahath
fuente
3
<asp:TextBox ID="txtMobile" runat="server" CssClass="form-control" style="width:92%;  margin:0px 5px 0px 5px;" onkeypress="javascript:return isNumberKey(event);" MaxLength="12"></asp:TextBox>

<script>
    function isNumberKey(evt) {
        var charCode = (evt.which) ? evt.which : event.keyCode;
        if (charCode > 31 && (charCode < 48 || charCode > 57)) {
            return false;
        }
        return true;
    }
</script>
raksh pal
fuente
3

Ninguna de las respuestas hasta ahora ofrece una solución completa. Hay bastantes problemas que abordar:

  1. No todas las pulsaciones de teclas son pasados a keydowny keypressmanipuladores (por ejemplo, teclas retroceder y borrar son suprimidas por algunos navegadores).
  2. El manejo keydownno es una buena idea. ¡Hay situaciones en las que una pulsación de tecla NO da como resultado una pulsación de tecla!
  3. setTimeout() Las soluciones de estilo se retrasan en los navegadores web Google Chrome / Blink hasta que el usuario deja de escribir.
  4. Los eventos táctiles y del mouse se pueden usar para realizar acciones como cortar, copiar y pegar. Esos eventos no activarán eventos de teclado.
  5. Es posible que el navegador, según el método de entrada, no envíe una notificación de que el elemento ha cambiado hasta que el usuario se aleje del campo.

Una solución más correcta manejará los keypress, keyup, input, y changeeventos.

Ejemplo:

<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>

Violín:

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

El manejo de los cuatro eventos detecta todos los casos extremos. Al trabajar con la entrada de un usuario, se deben considerar todos los tipos de métodos de entrada y se debe verificar la funcionalidad entre navegadores y dispositivos. El código anterior se ha probado en Firefox, Edge y Chrome en el escritorio, así como en los dispositivos móviles que poseo.

Cubículo Suave
fuente
¿Por qué no solo inputevento?
YakovL
inputno siempre dispara. Ningún evento cubre todas las situaciones.
CubicleSoft
Sería amable de su parte si describe "no siempre" con más detalle, como lo especificó keypressen la respuesta
YakovL
1

Normalmente concateno el valor del campo (es decir, antes de que se actualice) con la clave asociada con el evento clave. Lo siguiente usa JS reciente, por lo que sería necesario ajustar el soporte en IE más antiguos.

Ejemplo JS reciente

document.querySelector('#test').addEventListener('keypress', function(evt) {
    var real_val = this.value + String.fromCharCode(evt.which);
    if (evt.which == 8) real_val = real_val.substr(0, real_val.length - 2);
    alert(real_val);
}, false);

Ejemplo de soporte para IE más antiguos

//get field
var field = document.getElementById('test');

//bind, somehow
if (window.addEventListener)
    field.addEventListener('keypress', keypress_cb, false);
else
    field.attachEvent('onkeypress', keypress_cb);

//callback
function keypress_cb(evt) {
    evt = evt || window.event;
    var code = evt.which || evt.keyCode,
        real_val = this.value + String.fromCharCode(code);
    if (code == 8) real_val = real_val.substr(0, real_val.length - 2);
}

[EDITAR: este enfoque, de forma predeterminada, deshabilita las pulsaciones de teclas para cosas como el espacio posterior, CTRL + A. El código anterior se adapta al primero, pero necesitaría más ajustes para permitir el segundo y algunas otras eventualidades. Vea el comentario de Ian Boyd a continuación.]

Mitia
fuente
1
@ bažmegakapa O con la deletetecla, o si el usuario presiona una tecla que no modifica el contenido ( Ctrl+A), o si el usuario selecciona algún texto y luego presiona apara reemplazar un subconjunto. Es una buena idea, Utkanos, pero frágil.
Ian Boyd
1
Convenido. Lo dejaré ya que hay un kilometraje en él, pero, como usted dice, tendría que incorporar concesiones para estas advertencias.
Mitya
1

fácil...

En su controlador de eventos keyPress, escriba

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
}
Charles Bretana
fuente
¿Qué pasa si e.KeyChares la Backspaceclave? ¿O la Deletellave? O Ctrl+A?
Ian Boyd
¿Es esto incluso JavaScript? void? object? métodos de primera mayúscula?
YakovL
1

Entonces, hay ventajas y desventajas en cada evento. Los eventos onkeypressy onkeydownno recuperan el valor más reciente y onkeypressno se activa para caracteres no imprimibles en algunos navegadores. El onkeyupevento no detecta cuándo se mantiene presionada una tecla para varios caracteres.

Esto es un poco hacky, pero haciendo algo como

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)" />

parece manejar lo mejor de todos los mundos.

dx_over_dt
fuente
1

Al usar event.key podemos obtener valores antes de ingresarlos en el cuadro de texto de entrada HTML. Aquí está el código.

function checkText()
{
  console.log("Value Entered which was prevented was - " + event.key);
  
  //Following will prevent displaying value on textbox
  //You need to use your validation functions here and return value true or false.
  return false;
}
<input type="text" placeholder="Enter Value" onkeypress="return checkText()" />

vibs2006
fuente
Esto se desmorona cuando se cambia el texto a través de algo que es no pulsar una tecla (cortar, pegar, borrar seleccionado, etc)
Ian Boyd
@IanBoyd sí estuvo de acuerdo. Para mantener el ejemplo simple, he implementado solo validaciones de pulsaciones de teclas.
vibs2006
0

Intente concatenar el evento charCode con el valor que obtenga. Aquí hay una muestra de mi código:

<input type="text" name="price" onkeypress="return (cnum(event,this))" maxlength="10">
<p id="demo"></p>

js:

function cnum(event, str) {
    var a = event.charCode;
    var ab = str.value + String.fromCharCode(a);
    document.getElementById('demo').innerHTML = ab;
}

El valor en abobtendrá el último valor en el campo de entrada.

Rama Krishna
fuente
Lo siento, noté otra publicación con un enfoque aún mejor en esta página después de publicar esto. No vi eso antes de publicar. Pero creo que el mío es más sencillo de entender el concepto.
Rama Krishna
Que se desmorona bastante rápido cuando la llave está borrado , tecla de retroceso , Ctrl + X o Ctrl + V , o cuando el ratón selecciona todo el texto y pulse i Espacio
Ian Boyd
Acabo de escribir mi idea. puede implementarlo de acuerdo con sus requisitos utilizando códigos clave u otros métodos. Esta es solo mi idea.
Rama Krishna
1
Las ideas no son respuestas. Las respuestas en SO deben ser soluciones concisas que respondan definitivamente a la pregunta del OP para que todos puedan beneficiarse. Esto claramente no cumple con ese criterio.
CubicleSoft
0

Hay una forma mejor de hacer esto. Utilice el método concat. Ejemplo

declarar una variable global. esto funciona bien en angular 10, simplemente páselo a Vanilla JavaScript. Ejemplo:

HTML

<input id="edValue" type="text" onKeyPress="edValueKeyPress($event)"><br>
<span id="lblValue">The text box contains: </span>

CÓDIGO

emptyString = ''

edValueKeyPress ($event){
   this.emptyString = this.emptyString.concat($event.key);
   console.log(this.emptyString);
}
Abraham Velázquez
fuente
Y cuando la clave es Delete, Ctrl+ X, Ctrl+ V, Backspace? ¿O si han seleccionado algún texto y luego presionan A?
Ian Boyd