2010-05-13 13 views
108

¿Cómo puedo detectar el cambio de evento en textarea usando javascript?
Estoy tratando de detectar cuántos caracteres quedan disponibles mientras escribe.Textarea onchange detección

Intenté usar el evento onchange, pero parece que solo se activa cuando el foco está desactivado.

Respuesta

75

Necesitará usar onkeyupyonchange para esto. El cambio evitará que se pegue el menú de contexto, y la activación de la tecla se activará con cada pulsación de tecla.

Consulte mi respuesta en How to impose maxlength on textArea para obtener una muestra del código.

+3

Solo quería enfatizar lo que Josh ya dijo, que debería usar keyup, no keydown para esto: parece que se llama keydown antes de que el cambio se realice realmente en el área de texto, por lo que estará usando la longitud incorrecta (y no se usa No sé realmente qué tan apagado está: podría estar tipeando o borrando, y podría haber seleccionado texto, lo que significa que es más que solo +/- 1). – brianmearns

+49

¡Estoy dando un -1 aquí, lo siento! 'onkeyup' es un evento terrible para la detección de entrada. Use 'oninput' y' onpropertychange' (para soporte de IE). Ver http://whattheheadsaid.com/2010/09/effectively-detecting-user-input-in-javascript. –

+5

El "único" problema es 'onchange' ** NO ** disparado cuando se produce un corte/pegado en el menú de contexto. – Tom

4
+1

Eso te llevará a una parte del camino. La otra cosa a considerar es cortar y pegar desde el menú Editar o el menú contextual. –

+1

¡Ese es un gran punto! * thinking * – gurun8

+0

@ gurun8: que no funcionará cuando el texto se pegue con un menú con un clic del mouse. – user2284570

1

Que sea fácil para ti y utilizar un plugin de jQuery como jquery.maxlength. Tutorial al http://www.anon-design.se/demo/maxlength-with-jquery.

+1

* No es suficiente jQuery! * (Palabra "jquery" aparece solo 3 veces en respuesta a la publicación original.) – npup

+1

Buena respuesta, pero después de haber tenido alguna experiencia, creo que este es un problema común que un codificador de JavaScript debería poder resolver. –

-5

Lo mejor que puede hacer es establecer una función para llamar en un período de tiempo determinado y esta función para verificar el contenido de su área de texto.

self.setInterval('checkTextAreaValue()', 50); 
+7

son una muy mala idea. Simplemente destruirá el rendimiento. Además, al igual que otros publicados, existe alguna solución –

+2

Este es el siglo XXI. Ningún navegador debería tener problemas para manejar una comparación de cadenas cada 50 ms. Guarde en caché sus selectores y esta es una solución perfectamente aceptable. – nullability

8

Sé que esta no es exactamente su pregunta, pero pensé que esto podría ser útil. Para ciertas aplicaciones, es bueno tener la función de cambio activada no cada vez que se presiona una tecla. Esto se puede lograr con algo como esto:

var text = document.createElement('textarea'); 
text.rows = 10; 
text.cols = 40; 
document.body.appendChild(text); 

text.onkeyup = function(){ 
var callcount = 0; 
    var action = function(){ 
     alert('changed'); 
    } 
    var delayAction = function(action, time){ 
     var expectcallcount = callcount; 
     var delay = function(){ 
      if(callcount == expectcallcount){ 
       action(); 
      } 
     } 
     setTimeout(delay, time); 
    } 
    return function(eventtrigger){ 
     ++callcount; 
     delayAction(action, 1200); 
    } 
}(); 

Esto funciona mediante la prueba de si un caso más reciente ha disparado dentro de un cierto periodo de retardo. ¡Buena suerte!

+0

+1 para la acción retardada 'estrangulamiento'! Uso algo similar en mi aplicación. – psulek

16
  • Para Google-Chrome, la entrada será suficiente (Probado en Windows 7 con la versión 22.0.1229.94 m).
  • Para IE 9, oninput captará todo excepto el corte a través del menú contextual y el retroceso.
  • Para IE 8, se requiere onpropertychange para capturar pegado además de oninput.
  • Para IE 9 + 8, se requiere onkeyup para recuperar el espacio de retroceso.
  • Para IE 9 + 8, onmousemove es la única manera que encontré para coger el corte a través de ContextMenu

No probado en Firefox.

var isIE = /*@[email protected]*/false; // Note: This line breaks closure compiler... 

    function SuperDuperFunction() { 
     // DoSomething 
    } 


    function SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally() { 
     if(isIE) // For Chrome, oninput works as expected 
      SuperDuperFunction(); 
    } 

<textarea id="taSource" 
      class="taSplitted" 
      rows="4" 
      cols="50" 
      oninput="SuperDuperFunction();" 
      onpropertychange="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();" 
      onmousemove="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();" 
      onkeyup="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();"> 
Test 
</textarea> 
97

Es 2012, la era de la post-PC está aquí, y todavía tenemos que luchar con algo tan básico como este. Esto debería ser muy simple.

Hasta el momento en que el sueño se ha cumplido, aquí está la mejor manera de hacer esto, entre navegadores: utilizar una combinación de los input y onpropertychange eventos, así:

var area = container.querySelector('textarea'); 
if (area.addEventListener) { 
    area.addEventListener('input', function() { 
    // event handling code for sane browsers 
    }, false); 
} else if (area.attachEvent) { 
    area.attachEvent('onpropertychange', function() { 
    // IE-specific event handling code 
    }); 
} 

El input evento se ocupa de IE9+, FF, Chrome, Opera and Safari, y onpropertychange se ocupa de IE8 (también funciona con IE6 y 7, pero hay algunos errores).

La ventaja de usar input y onpropertychange es que no se activan innecesariamente (como al pulsar las teclas o CtrlShift); así que si desea ejecutar una operación relativamente costosa cuando el contenido de la zona de texto cambia, esta es la manera de ir.

Ahora IE, como siempre, hace un trabajo a medias de soportar esto: ni input ni onpropertychange incendios en IE cuando los personajes son eliminarán del área de texto. Por lo tanto, si necesita manejar la eliminación de caracteres en IE, use keypress (en oposición a usar keyup/keydown, ya que solo se disparan una vez, incluso si el usuario presiona y mantiene presionada una tecla).

Fuente: http://www.alistapart.com/articles/expanding-text-areas-made-elegant/

EDIT: Parece incluso la solución anterior no es perfecto, como acertadamente señaló en los comentarios: la presencia de la propiedad addEventListener en el área de texto hace no implica que estés trabajando con un navegador sensato; de manera similar, la presencia de la propiedad attachEvent hace no implica IE. Si desea que su código sea realmente hermético, debería considerar cambiar eso. Consulte Tim Down's comment para ver los punteros.

+1

Este es el mejor enfoque. No me gustan las inferencias aquí (el soporte del navegador para 'addEventListener' no implica soporte para el evento' input', o viceversa); la detección de características sería mejor. Ver [esta publicación del blog] (https://web.archive.org/web/20130215103706/http://whattheheadsaid.com/2011/10/update-html5-oninput-event-plugin-for-jquery) para una discusión de esta. –

+0

Totalmente de acuerdo con Tim en este caso. 'oninput' es cómo deberíamos hacer esto, pero probablemente no deberías usar' addEventListener' como prueba para el soporte del navegador. +1 en cualquier caso. –

+1

En desacuerdo, la entrada no se ocupará de IE9. Cortar/Pegar a través del menú contextual desafortunadamente también es entrada, y también lo es el retroceso.No me molesté en probar, pero no pondría ningún dinero en la apuesta de que IE10 + solucionó ese problema. –

5

Sé que esta pregunta era específica de JavaScript, sin embargo, parece no haber una buena y limpia forma de SIEMPRE detectar cuando un área de texto cambia en todos los navegadores actuales. He aprendido que jquery se ha ocupado de eso por nosotros. Incluso maneja los cambios del menú contextual a las áreas de texto. La misma sintaxis se usa independientemente del tipo de entrada.

$('div.lawyerList').on('change','textarea',function(){ 
     // Change occurred so count chars... 
    }); 

o

Código
$('textarea').on('change',function(){ 
     // Change occurred so count chars... 
    }); 
+3

Encontré que el evento de cambio no era más consistente con jQuery que con JS simple. Utilicé el 'bind (' cut-paste '') de jQuery y funciona como un amuleto: escribir, cortar y pegar usando el teclado o el menú contextual, incluso arrastrar/soltar texto. –

+2

Desafortunadamente, FF no activa el cambio. 'evento para' textarea'. –

0

he utilizado para IE 11 sin jQuery y sólo por una única área de texto:

Javascript:

// Impede que o comentário tenha mais de num_max caracteres 
var internalChange= 0; // important, prevent reenter 
function limit_char(max) 
{ 
    if (internalChange == 1) 
    { 
     internalChange= 0; 
     return; 
    } 
    internalChange= 1; 
    // <form> and <textarea> are the ID's of your form and textarea objects 
    <form>.<textarea>.value= <form>.<textarea>.value.substring(0,max); 
} 

y html:

<TEXTAREA onpropertychange='limit_char(5)' ... 
0

La copia de seguridad debería ser suficiente si se combina con el atributo de validación/patrón de entrada HTML5. Por lo tanto, cree un patrón (regex) para validar la entrada y actuar sobre el estado .checkValidity(). Algo como abajo podría funcionar. En su caso, usted desearía una expresión regular para que coincida con la longitud. Mi solución está en uso/demo-able en línea here.

<input type="text" pattern="[a-zA-Z]+" id="my-input"> 

var myInput = document.getElementById = "my-input"; 

myInput.addEventListener("keyup", function(){ 
    if(!this.checkValidity() || !this.value){ 
    submitButton.disabled = true; 
    } else { 
    submitButton.disabled = false; 
    } 
}); 
0

Pruebe este.Es simple, y dado que es 2016, estoy seguro de que funcionará en la mayoría de los navegadores.

<textarea id="text" cols="50" rows="5" onkeyup="check()" maxlength="15"></textarea> 
<div><span id="spn"></span> characters left</div> 

function check(){ 
    var string = document.getElementById("url").value 
    var left = 15 - string.length; 
    document.getElementById("spn").innerHTML = left; 
} 
+0

Así que obtienes url por id, pero no aparece en tu código. –