Como obter o texto de uma caixa de texto de entrada durante o onKeyPress?

87

Estou tentando obter o texto em uma caixa de texto conforme o usuário digita ( playground jsfiddle ):

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>

O código é executado sem erros, exceto que o valor da input textcaixa, durante onKeyPressé sempre o valor antes da alteração:

insira a descrição da imagem aqui

Pergunta : Como obtenho o texto de uma caixa de texto durante onKeyPress?

Bônus de bate-papo

Existem três eventos relacionados a "o usuário está digitando" no HTML DOM:

  • onKeyDown
  • onKeyPress
  • onKeyUp

No Windows , a ordem das WM_Keymensagens torna-se importante quando o usuário mantém uma tecla pressionada e a tecla começa a se repetir:

  • WM_KEYDOWN('a')- o usuário pressionou a Atecla
  • WM_CHAR('a')- um acaractere foi recebido do usuário
  • WM_CHAR('a')- um acaractere foi recebido do usuário
  • WM_CHAR('a')- um acaractere foi recebido do usuário
  • WM_CHAR('a')- um acaractere foi recebido do usuário
  • WM_CHAR('a')- um acaractere foi recebido do usuário
  • WM_KEYUP('a')- o usuário liberou a Achave

Resultará em cinco caracteres aparecendo em um controle de texto: aaaaa

O importante é que você responda à WM_CHARmensagem, aquela que se repete. Caso contrário, você perderá eventos quando uma tecla for pressionada.

Em HTML, as coisas são ligeiramente diferentes:

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

Html entrega um KeyDowne KeyPresscada repetição de tecla. E o KeyUpevento só é gerado quando o usuário libera a tecla.

Aprendizado

  • I pode responder a onKeyDownou onKeyPress, mas ambos ainda são levantadas antes da input.valuefoi atualizado
  • Não posso responder onKeyUp, porque isso não acontece quando o texto na caixa de texto muda.

Pergunta: Como obtenho o texto de uma caixa de texto durante onKeyPress?

Leitura de bônus

Ian Boyd
fonte
1
Acredito que você precise anexar o pressionamento de tecla atual ao valor antes de retorná-lo; o valor é atualizado em keyUp, mas os dados estão disponíveis para você em keyDown.
Mathletics
Key up funciona para mim, você não precisa de jQ para algo assim, a menos que você goste de adicionar inchaço
Ryan B
é suficiente apenas onKeyUp para sua tarefa
dmytro
@mit Somente manipulação onKeyUpnão mostra as mudanças na caixa de texto conforme elas acontecem.
Ian Boyd
se você quiser manter qualquer tecla pressionada e obter o resultado na caixa de texto, você deve usar os eventos onKeyPress e onKeyDown do violino de Jonathan M , mas se você quiser obter o resultado sem segurar as teclas, basta apenas onKeyUp my fiddle .
dmytro

Respostas:

20

Manipular o inputevento é uma solução consistente: ele é compatível com elementos textareae inputem todos os navegadores contemporâneos e dispara exatamente quando você precisa:

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>

Eu reescreveria um pouco, embora:

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

Mantenha simples. Use onKeyPress()e onKeyUp():

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

Isso se encarrega de obter o valor da string mais atualizado (após a ativação da chave) e também atualiza se o usuário mantiver uma tecla pressionada.

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

Jonathan M
fonte
Já que a resposta de arnaud576875 teve que desistir e voltar para onKeyUp(derrotando o propósito de usar onKeypress), esta é a resposta mais simples, limpa e próxima que alguém verá. Apenas o usuário atento e observador perceberá que o feedback não corresponde ao que foi inserido.
Ian Boyd
@Ian, fico feliz em ajudar. O que você quer dizer com "o feedback não corresponde ao que foi inserido"? É necessário um ajuste?
Jonathan M
eu lembro o que eu quis dizer agora! O feedback a que me refiro seria colorir o <input>elemento de vermelho ou verde, ou dar algum outro feedback ao usuário de que o que ele digitou é bom ou ruim. Embora sua resposta aceita ainda sofra do problema de sempre ser um personagem "fora de lugar" : apenas o usuário mais observador notará que o feedback não corresponde ao que ele digitou. " Na realidade, desde o um erro só acontece durante a repetição da tecla (ou seja, eles estão segurando a tecla) ninguém (além de mim) vai notar o problema.
Ian Boyd
19

o valor da caixa de texto de entrada, durante onKeyPress é sempre o valor antes da mudança

Isso é proposital: permite que o ouvinte de evento cancele o pressionamento de tecla.

Se os ouvintes de eventos cancelarem o evento , o valor não será atualizado. Se o evento não for cancelado, o valor será atualizado, mas após a chamada do ouvinte de evento .

Para obter o valor após a atualização do valor do campo, agende uma função para ser executada no próximo loop de evento. A maneira usual de fazer isso é ligar setTimeoutcom um tempo limite 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);
});

Tente aqui: http://jsfiddle.net/Q57gY/2/

Editar : Alguns navegadores (por exemplo, Chrome) não acionam eventos de pressionamento de tecla para backspace; mudou keypress para keyup no código.

Arnaud Le Blanc
fonte
Estava prestes a postar isso. Aqui está o jsFiddle que fiz.
kapa
Você está certo, o Chrome parece não acionar eventos de pressionamento de tecla para backspace; atualizado
Arnaud Le Blanc
@Ian, o OP deseja que ele seja atualizado enquanto uma tecla é mantida pressionada? Não tinha certeza se isso era um requisito. No entanto, essa solução não tem essa funcionalidade.
Jonathan M
Para ser claro: não acionar eventos de pressionamento de tecla para backspace é o padrão: "tecla que produz um valor de caractere" - para outras teclas, use "keydown" (antes da alteração, cancelável) ou "keyup" (após a alteração)
sebilasse
5

mantenha-o compacto.
Cada vez que você pressiona uma tecla, a função edValueKeyPress()é chamada.
Você também declarou e inicializou algumas variáveis ​​nessa função - o que torna o processo lento e requer mais CPU e memória também.
Você pode simplesmente usar este código - derivado de uma substituição simples.

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

Isso é tudo que você quer e é mais rápido!

Wajahath
fonte
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>
amigo raksh
fonte
3

Nenhuma das respostas até agora oferece uma solução completa. Existem alguns problemas a serem resolvidos:

  1. Nem todos os pressionamentos de tecla são passados ​​para keydowne keypressmanipuladores (por exemplo, backspace e delete keys são suprimidos por alguns navegadores).
  2. O manuseio keydownnão é uma boa ideia. Existem situações em que uma tecla pressionada NÃO resulta em um pressionamento de tecla!
  3. setTimeout() as soluções de estilo ficam atrasadas nos navegadores Google Chrome / Blink até que o usuário pare de digitar.
  4. Os eventos de mouse e toque podem ser usados ​​para executar ações como cortar, copiar e colar. Esses eventos não irão acionar eventos de teclado.
  5. O navegador, dependendo do método de entrada, pode não entregar a notificação de que o elemento foi alterado até que o usuário saia do campo.

Uma solução mais correta irá lidar com os keypress, keyup, input, e changeeventos.

Exemplo:

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

Violino:

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

O tratamento de todos os quatro eventos captura todos os casos extremos. Ao trabalhar com a entrada de um usuário, todos os tipos de métodos de entrada devem ser considerados e a funcionalidade entre navegadores e dispositivos deve ser verificada. O código acima foi testado no Firefox, Edge e Chrome no desktop, bem como nos dispositivos móveis que possuo.

CubicleSoft
fonte
Por que não apenas inputevento?
YakovL
inputnem sempre dispara. Nenhum evento cobre todas as situações.
CubicleSoft
seria legal da sua parte se você descrever "nem sempre" com mais detalhes, como especificou keypressna resposta
YakovL
1

Normalmente concateno o valor do campo (ou seja, antes de ser atualizado) com a chave associada ao evento de chave. O seguinte usa JS recente, portanto, precisaria de ajustes para suporte em IEs mais antigos.

Exemplo recente de JS

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

Suporte para exemplo de IEs mais antigos

//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 - esta abordagem, por padrão, desabilita pressionamentos de tecla para coisas como back space, CTRL + A. O código acima acomoda o primeiro, mas precisaria de mais ajustes para permitir o último e algumas outras eventualidades. Veja o comentário de Ian Boyd abaixo.]

Mitya
fonte
1
@ bažmegakapa Ou com a deletetecla, ou se o usuário pressiona uma tecla que não modifica o conteúdo ( Ctrl+A), ou se o usuário seleciona algum texto e pressiona apara substituir um subconjunto. É uma boa ideia, Utkanos, mas frágil.
Ian Boyd
1
Acordado. Vou deixar assim, pois há alguma quilometragem nele, mas, como você disse, você teria que adicionar provisões para essas advertências.
Mitya
1

fácil...

Em seu manipulador de eventos keyPress, escreva

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
fonte
O que acontece se e.KeyCharfor a Backspacechave? Ou a Deletechave? Ou Ctrl+A?
Ian Boyd
Isso é mesmo JavaScript? void? object? métodos de primeira maiúscula?
YakovL de
1

Portanto, existem vantagens e desvantagens em cada evento. Os eventos onkeypresse onkeydownnão recuperam o valor mais recente e onkeypressnão disparam para caracteres não imprimíveis em alguns navegadores. O onkeyupevento não detecta quando uma tecla é pressionada para vários caracteres.

Isso é um pouco hackeado, mas fazendo 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 lidar com o melhor de todos os mundos.

dx_over_dt
fonte
1

Usando event.key , podemos obter valores antes da entrada na caixa de texto HTML Input. Aqui está o 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
fonte
Isso se desintegra quando o texto é alterado por algo que não seja um pressionamento de tecla (cortar, colar, excluir selecionado, etc)
Ian Boyd
@IanBoyd sim concordou. Para manter o exemplo simples, implementei apenas validações de teclas.
vibs2006
0

Tente concatenar o evento charCode com o valor obtido. Aqui está um exemplo do meu 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;
}

O valor em abobterá o valor mais recente no campo de entrada.

Rama Krishna
fonte
Desculpe, notei outro post com uma abordagem ainda melhor nesta página depois de postar isso. Eu não vi isso antes de postar. Mas acho que o meu é mais simples de entender o conceito.
Rama Krishna
Isso desmorona muito rápido quando a tecla é delete , backspace , Ctrl + X ou Ctrl + V , ou quando o mouse seleciona todo o texto e eu pressiono Espaço
Ian Boyd
Acabei de escrever minha ideia. você pode implementá-lo de acordo com sua necessidade, usando códigos-chave ou outros métodos. Esta é apenas minha ideia.
Rama Krishna
1
Idéias não são respostas. As respostas sobre o SO devem ser soluções concisas que respondam definitivamente à pergunta do OP para que todos possam se beneficiar. Isso claramente não atende a esses critérios.
CubicleSoft
0

Existe uma maneira melhor de fazer isso. Use o método concat. Exemplo

declara uma variável global. isso funciona bem no angular 10, basta passá-lo para o Vanilla JavaScript. Exemplo:

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 Velazquez
fonte
E quando a chave é Delete, Ctrl+ X, Ctrl+ V, Backspace? Ou se eles selecionaram algum texto e pressionaram A?
Ian Boyd