Eventos JS: conectando um evento de mudança de valor em inputs de texto

Eu tenho uma input de texto cujo conteúdo é alterado por um script não por usuário. Então, eu gostaria de triggersr um evento quando o valor for alterado. Não consigo encontrar um evento adequado para isso. Eu até encontrei isso no StackOverflow , mas não é a solução que estou procurando.

Como fazer isso funcionar com jQuery e uma input de texto onde o valor é definido assim:

myTextControl.value = someValue 

Aqui quero triggersr um evento para ver o novo valor.

Não consigo encontrar um evento adequado para isso.

Sim, não há um.

Há events de mutação de DOM , mas eles não são compatíveis com vários navegadores e não são triggersdos para valores de formulário, pois não são refletidos em atributos (exceto no IE devido a um bug).

Somente no Mozilla, um relógio JavaScript pode ser configurado na propriedade value para capturar alterações de script. Somente no IE, um manipulador onPropertychange do JScript pode ser configurado para capturar alterações com scripts e orientadas pelo usuário. Em outros navegadores você teria que usar seu próprio interval poller para procurar por mudanças.

 function watchProperty(obj, name, handler) { if ('watch' in obj) { obj.watch(name, handler); } else if ('onpropertychange' in obj) { name= name.toLowerCase(); obj.onpropertychange= function() { if (window.event.propertyName.toLowerCase()===name) handler.call(obj); }; } else { var o= obj[name]; setInterval(function() { var n= obj[name]; if (o!==n) { o= n; handler.call(obj); } }, 200); } } watchProperty(document.getElementById('myinput'), 'value', function() { alert('changed!'); }); 

Isso é altamente insatisfatório. Ele não responderá a alterações controladas pelo usuário no Mozilla, ele permitirá apenas uma propriedade observada por object no IE, e em outros navegadores a function de manipulador será chamada muito mais tarde no stream de execução.

É quase certamente melhor rewrite as partes do script que definem value para chamar uma function de wrapper setValue, que você pode monitorar as alterações que deseja capturar.

Você pode adicionar um ouvinte de evento normal ao seu campo de input dessa maneira. (usando jQuery)

 $(myTextControl).change(function() { ... /* do appropriate event handling here */ ... }); 

Ok, considerando que o javascript que altera o valor de input não é controlado por você, fica difícil. Você ficou com duas opções:

1.) Crossbrowser compatível: Implementa o polling do valor de input com uma function que verifica continuamente se o valor mudou. (Algo ao longo destas linhas).

 //at beginning before other scripts changes the value create a global variable var oldValue = myTextControl.value; function checkIfValueChanged() { if(myTextControl.value != oldValue) { $(myTextControl).trigger("change"); clearInterval(checker); } } //every 500ms check if value changed var checker = setInterval('checkIfValueChanged()', 500); 

Nota : Se o script ou o usuário puder alterar o valor também, você deverá implementar algo para capturar isso para não acionar o evento de alteração várias vezes.

Se o valor puder ser alterado várias vezes pelo script externo, deixe a function intervalar em vez de cancelá-la e apenas atualize oldValue;

2.) AFAIK Ainda não suportado por todos os navegadores (teste-os naqueles que você precisa suportar)

Você poderia ligar a um evento DOM Nível 3 especial: DOMAttrModified (no Firefox, talvez outros também eu acho que o Opera também tem, Safari ??, Chrome ??) e no IE é claro que tem um propertychange diferente (e é proprietário e diferente do comportamento do W3C)

Agora, idealmente, você poderia combinar as duas opções e verificar se há suporte para DOMAttrModified ou propertychange e usar de acordo ou recorrer à solução de pesquisa.


Lendo links

Eventos de mutação de DOM do W3C

Evento DOMAttrModified do W3C

Evento de troca de propriedade MSDN DHTML

Plug-in de Monitoramento de Propriedade CSS do jQuery atualizado

Último link é um cara que basicamente já fez um plugin jQuery fazendo as coisas descritas por mim (não testado por mim, fornecido apenas como referência)

tente isso

 $('#myTextControl').bind('input', function(){ console.log('value changed'); }); 
 var oldVal = $('#myTextControl').val(); //Your script that changes the value if(oldVal != $('#myTextControl').val()) { //Your content has changed, do something } 

Você precisará ouvir os events do teclado quando o elemento que estiver assistindo tiver foco.