Como detectar o conteúdo de uma caixa de texto mudou

417

Quero detectar sempre que o conteúdo de uma caixa de texto for alterado. Posso usar o método keyup, mas isso também detectará pressionamentos de teclas que não geram letras, como as teclas de seta. Pensei em dois métodos de fazer isso usando o evento keyup:

  1. Verifique explicitamente se o código ascii da tecla pressionada é uma letra \ backspace \ delete
  2. Use fechamentos para lembrar qual era o texto na caixa de texto antes do pressionamento de tecla e verifique se isso foi alterado.

Ambos parecem meio complicados.

olamundo
fonte
7
Sim, capturar keyup para isso é ruim. Você pode colar coisas sem pressionar as teclas.
gastador
2
Alguma chance de você postar sua solução final? Eu preciso para resolver este problema também :)
Matt Dotson
1
or .keyup()event ... mais informações aqui: stackoverflow.com/questions/3003879/…
Victor S
1
Veja $ ("# some-input"). ChangePolling () ; para um wrapper que verifique o valor atual e dispara .change()se ele foi alterado.
Joel Purra
você precisa verificar isso também stackoverflow.com/a/23266812/3160597
azerafati

Respostas:

714

Comece a observar o evento 'input' em vez de 'change'.

jQuery('#some_text_box').on('input', function() {
    // do your stuff
});

... que é agradável e limpo, mas pode ser estendido para:

jQuery('#some_text_box').on('input propertychange paste', function() {
    // do your stuff
});
Atul Vani
fonte
12
'live' foi descontinuado. então faça uso de 'on' stackoverflow.com/a/15111970/1724777
NavaRajan
21
A única queda do 'input' é que ele não é compatível com o IE <9.
Catfish
5
input é um evento html5 que não é suportado em todos os navegadores. developer.mozilla.org/pt-BR/docs/Web/API/window.oninput
commonpike:
18
Você também pode cobrir mais bases usando: .on ('input propertychange paste', function () {
Graeck
23
A única queda do IE <9 é que ninguém o usa!
sohaiby
67

Use o evento onchange em HTML / JavaScript padrão.

No jQuery, esse é o evento change () . Por exemplo:

$('element').change(function() { // do something } );

EDITAR

Depois de ler alguns comentários, o que dizer de:

$(function() {
    var content = $('#myContent').val();

    $('#myContent').keyup(function() { 
        if ($('#myContent').val() != content) {
            content = $('#myContent').val();
            alert('Content has been changed');
        }
    });
});
Waleed Amjad
fonte
3
Sim, isso é semelhante ao que sugeri na opção 2 da minha pergunta. Eu prefiro fechamentos, pois o uso de um global fará com que essa função funcione apenas para uma caixa de texto. Enfim, parece estranho jquery não tem uma maneira mais simples de fazer isso.
olamundo
1
É realmente estranho, mas duvido que exista uma maneira melhor de fazê-lo. Você pode usar setInterval e, em seguida, verificar se o conteúdo foi alterado a cada 0,1 s e, em seguida, fazer alguma coisa. Isso também inclui pastas de mouse e assim por diante. Mas não parece muito elegante.
23909 Waleed Amjad
4
Ainda é possível que o conteúdo possa ser alterado sem pressionar as teclas, por exemplo, colando com o mouse. Se você se importa com isso, teoricamente também pode capturar eventos de mouse, mas essa configuração é ainda mais feia. Por outro lado, se você estiver disposto a ignorar as alterações acionadas por mouse, isso funcionará.
23811 Adam Bellaire
45

O evento 'change' não funciona corretamente, mas a 'entrada' é perfeita.

$('#your_textbox').bind('input', function() {
    /* This will be fired every time, when textbox's value changes. */
} );
schwarzkopfb
fonte
7
Isso funciona perfeitamente para minha situação, embora o uso de .onseja recomendado a partir de 1.7 (e não .bind).
Nick
8
O OP não especificou a necessidade de compatibilidade entre navegadores. @schwarzkopfb forneceu uma solução. Não há motivo para votar, porque você tem o representante para fazê-lo.
David East
3
@ David, ele também não especificou qual navegador
ozz
9
@ jmo21 Acho que podemos assumir o desenvolvimento da Web quando um navegador não é específico, a solução deve ser multifuncional. A norma está suportando todos os navegadores.
26415 Chris
3
@ Chris "A norma suporta todos os navegadores" - apenas se você é um sádico. Não há um bom motivo para evitar a qualidade do HTML5 para 2% dos usuários globais no IE 8/9. caniuse.com/#feat=input-event
Yarin
39

Que tal agora:

<jQuery 1.7

$("#input").bind("propertychange change keyup paste input", function(){
    // do stuff;
});

> jQuery 1.7

$("#input").on("propertychange change keyup paste input", function(){
    // do stuff;
});

Isso funciona no IE8 / IE9, FF, Chrome

Peixe-gato
fonte
1
O problema que tenho com esta resposta é que ele dispara quando você desfoca a caixa de texto, mesmo que o valor não tenha sido alterado. O culpado é a "mudança".
23615 Justin
Você está usando o Chrome? Parece que é um bug com o chrome e não o evento de alteração do jQuery bugs.jquery.com/ticket/9335
Peixe
funciona, mas possui um bug menor, se você fizer console.logo valor do campo, ele registrará duas vezes sempre que você digitar um caractere.
Samuel M.
21

Use fechamentos para lembrar qual era o texto na caixa de seleção antes do pressionamento de tecla e verifique se isso foi alterado.

Sim. Você não precisa usar fechamentos necessariamente, mas precisará lembrar o valor antigo e compará-lo com o novo.

Contudo! Isso ainda não pega todas as alterações, porque existem maneiras de editar o conteúdo da caixa de texto que não envolve nenhum pressionamento de tecla. Por exemplo, selecionando um intervalo de texto e clique com o botão direito do mouse em recortar. Ou arrastando-o. Ou soltar texto de outro aplicativo na caixa de texto. Ou alterando uma palavra através da verificação ortográfica do navegador. Ou...

Portanto, se você deve detectar todas as alterações, é necessário fazer uma pesquisa. Você pode window.setIntervalverificar o campo em relação ao seu valor anterior a cada (digamos) segundo. Também poderia ligar onkeyupà mesma função para que as alterações que são causadas por teclas pressionadas são reflectidos mais rápido.

Pesado? Sim. Mas é isso ou apenas faça isso da maneira normal de troca de HTML e não tente atualizar instantaneamente.

bobince
fonte
1
Atualmente, o inputevento HTML5 é viável e funciona nas versões atuais de todos os principais navegadores.
Tim Baixo
13
$(document).on('input','#mytxtBox',function () { 
 console.log($('#mytxtBox').val());
});

Você pode usar o evento 'input' para detectar a alteração do conteúdo na caixa de texto. Não use 'live' para vincular o evento, pois ele está obsoleto no Jquery-1.7; portanto, use 'on'.

NavaRajan
fonte
@NavaRajan Acabei de testar novamente no IE9. realmente não funciona no backspace.
Flores
Eu NÃO quero usar o .live, mas o problema que estou tendo é que, de alguma forma, voltei ao "futuro" e a um projeto do mvc3 no qual o líder da equipe quer ficar com "pronto para uso", para não única EF 4.0, mas jquery 1.5.1 está a ser utilizado ASSIM .on () não estava em 1.5.1, como ele foi adicionado na versão 1.7 jquery api.jquery.com/on
Tom Stickel
5

Suponho que você esteja procurando fazer algo interativo quando a caixa de texto for alterada (por exemplo, recuperar alguns dados via ajax). Eu estava procurando essa mesma funcionalidade. Sei que usar uma solução global não é a solução mais robusta ou elegante, mas foi com isso que fui. Aqui está um exemplo:

var searchValue = $('#Search').val();
$(function () {
    setTimeout(checkSearchChanged, 0.1);
});

function checkSearchChanged() {
    var currentValue = $('#Search').val();
    if ((currentValue) && currentValue != searchValue && currentValue != '') {
        searchValue = $('#Search').val();
        $('#submit').click();
    }
    else {
        setTimeout(checkSearchChanged, 0.1);
    }
}

Uma coisa importante a ser observada aqui é que estou usando setTimeout e não setInterval, pois não quero enviar várias solicitações ao mesmo tempo. Isso garante que o cronômetro "pare" quando o formulário for enviado e "inicie" quando a solicitação for concluída. Eu faço isso chamando checkSearchChanged quando minha chamada ajax é concluída. Obviamente, você pode expandir isso para verificar o comprimento mínimo, etc.

No meu caso, estou usando o ASP.Net MVC para que você possa ver como vincular isso ao MVC Ajax, também na seguinte postagem:

http://geekswithblogs.net/DougLampe/archive/2010/12/21/simple-interactive-search-with-jquery-and-asp.net-mvc.aspx

Doug Lampe
fonte
4

Eu recomendaria dar uma olhada no widget de preenchimento automático da UI do jQuery. Eles lidaram com a maioria dos casos lá, já que sua base de código é mais madura do que a maioria dos outros por aí.

Abaixo está um link para uma página de demonstração para que você possa verificar se funciona. http://jqueryui.com/demos/autocomplete/#default

Você obterá o maior benefício ao ler a fonte e ver como eles a resolveram. Você pode encontrá-lo aqui: https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.autocomplete.js .

Basicamente, eles fazem tudo, se vinculam input, keydown, keyup, keypress, focus and blur. Então eles têm um tratamento especial para todos os tipos de chaves, como page up, page down, up arrow key and down arrow key. Um cronômetro é usado antes de obter o conteúdo da caixa de texto. Quando um usuário digita uma chave que não corresponde a um comando (tecla para cima, tecla para baixo e assim por diante), existe um timer que explora o conteúdo após cerca de 300 milissegundos. Parece com isso no código:

// switch statement in the 
switch( event.keyCode ) {
            //...
            case keyCode.ENTER:
            case keyCode.NUMPAD_ENTER:
                // when menu is open and has focus
                if ( this.menu.active ) {
                    // #6055 - Opera still allows the keypress to occur
                    // which causes forms to submit
                    suppressKeyPress = true;
                    event.preventDefault();
                    this.menu.select( event );
                }
                break;
            default:
                suppressKeyPressRepeat = true;
                // search timeout should be triggered before the input value is changed
                this._searchTimeout( event );
                break;
            }
// ...
// ...
_searchTimeout: function( event ) {
    clearTimeout( this.searching );
    this.searching = this._delay(function() { // * essentially a warpper for a setTimeout call *
        // only search if the value has changed
        if ( this.term !== this._value() ) { // * _value is a wrapper to get the value *
            this.selectedItem = null;
            this.search( null, event );
        }
    }, this.options.delay );
},

O motivo para usar um timer é para que a interface do usuário tenha a chance de ser atualizada. Quando o Javascript está em execução, a interface do usuário não pode ser atualizada; portanto, a chamada para a função de atraso. Isso funciona bem para outras situações, como manter o foco na caixa de texto (usada por esse código).

Portanto, você pode usar o widget ou copiar o código em seu próprio widget se não estiver usando a interface do usuário do jQuery (ou, no meu caso, desenvolvendo um widget personalizado).

Michael Yagudaev
fonte
2

Gostaria de perguntar por que você está tentando detectar quando o conteúdo da caixa de texto mudou em tempo real ?

Uma alternativa seria definir um cronômetro (via setIntval?) E comparar o último valor salvo com o atual e, em seguida, redefinir um cronômetro. Isso garantiria capturar QUALQUER alteração, seja causada por chaves, mouse, algum outro dispositivo de entrada que você não considerasse, ou até mesmo JavaScript, alterando o valor (outra possibilidade que ninguém mencionou) de uma parte diferente do aplicativo.

DVK
fonte
minha situação (que me levou a essa pergunta) é que eu preciso mostrar um botão 'Atualizar carrinho' quando a quantidade em uma caixa de texto é alterada. o usuário não tem idéia de que precisa perder o foco e, caso contrário, poderá não ver o botão.
7779 Simon_Weaver
Desculpe, não tenho certeza de que isso responda à pergunta "por que não procurar diferenças em uma programação". Basta verificar com frequência suficiente (a cada 1/4 de segundo) e o usuário não saberá nenhuma diferença.
DVK
1

você considera usar o evento de mudança ?

$("#myTextBox").change(function() { alert("content changed"); });
Canavar
fonte
5
AFAIK, é acionado apenas quando o foco do elemento é perdido. Alguém que esteja familiarizado com fechamentos provavelmente conhece esse. )
Simon
Sim, isso não serve - o evento de alteração é chamado apenas quando a caixa de texto perde o foco. Quero lidar com a alteração logo após a tecla ser pressionada.
olamundo
1

Use o textchangeevento através do shimmer personalizado do jQuery para inputcompatibilidade entre navegadores . http://benalpert.com/2013/06/18/a-near-perfect-oninput-shim-for-ie-8-and-9.html (github bifurcado mais recentemente: https://github.com/pandell /jquery-splendid-textchange/blob/master/jquery.splendid.textchange.js )

Isso lida com todas as tags de entrada <textarea>content</textarea>, inclusive , que nem sempre funciona com change keyupetc. (!) Apenas o jQuery on("input propertychange")manipula as <textarea>tags de forma consistente, e o acima é um calço para todos os navegadores que não entendem o inputevento.

<!DOCTYPE html>
<html>
<head>
<script class="jsbin" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="https://raw.githubusercontent.com/pandell/jquery-splendid-textchange/master/jquery.splendid.textchange.js"></script>
<meta charset=utf-8 />
<title>splendid textchange test</title>

<script> // this is all you have to do. using splendid.textchange.js

$('textarea').on("textchange",function(){ 
  yourFunctionHere($(this).val());    });  

</script>
</head>
<body>
  <textarea style="height:3em;width:90%"></textarea>
</body>
</html>

Teste JS Bin

Isso também lida com colar, excluir e não duplica o esforço na digitação.

Se não estiver usando um calço, use on("input propertychange")eventos jQuery .

// works with most recent browsers (use this if not using src="...splendid.textchange.js")

$('textarea').on("input propertychange",function(){ 
  yourFunctionHere($(this).val());    
});  
Ber
fonte
0

Há um exemplo completo de trabalho aqui .

<html>
<title>jQuery Summing</title>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"> </script>
$(document).ready(function() {
$('.calc').on('input', function() {
var t1 = document.getElementById('txt1');
var t2 = document.getElementById('txt2');
var tot=0;
if (parseInt(t1.value))
tot += parseInt(t1.value);
if (parseInt(t2.value))
tot += parseInt(t2.value);
document.getElementById('txt3').value = tot;
});
});
</script>
</head>
<body>
<input type='text' class='calc' id='txt1'>
<input type='text' class='calc' id='txt2'>
<input type='text' id='txt3' readonly>
</body>
</html>
worldofjr
fonte
0

Algo assim deve funcionar, principalmente porque focuse focusoutacabaria com dois valores separados. Estou usando dataaqui porque ele armazena valores no elemento, mas não toca no DOM. Também é uma maneira fácil de armazenar o valor conectado ao seu elemento. Você poderia facilmente usar uma variável de escopo mais alto.

var changed = false;

$('textbox').on('focus', function(e) {
    $(this).data('current-val', $(this).text();
});

$('textbox').on('focusout', function(e) {
    if ($(this).data('current-val') != $(this).text())
        changed = true;
    }
    console.log('Changed Result', changed);
}
smcjones
fonte
0

Este Código detecta sempre que o conteúdo de uma caixa de texto é alterado pelo usuário e modificado pelo código Javascript.

var $myText = jQuery("#textbox");

$myText.data("value", $myText.val());

setInterval(function() {
    var data = $myText.data("value"),
    val = $myText.val();

    if (data !== val) {
        console.log("changed");
        $myText.data("value", val);
    }
}, 100);
Sandeep Yadav
fonte