Write only once each key, ignoring the repetitions

29

I want that when a key is pressed a long time it does not write several times.

ejemplo:
tecla      tiempo      resultado
  a           3seg        a

I made this code but it does not work, use the 3 events.

var texto=document.getElementById("texto");
var pulsado=false;
texto.addEventListener('keydown', function(keyboardEvent) {
    if(pulsado) return false;
    pulsado=true;
});
texto.addEventListener('keypress', function(keyboardEvent) {
    if(!pulsado){
                
    }
});
texto.addEventListener('keyup', function(keyboardEvent) {
    pulsado=false;
});
<textarea id="texto"></textarea>
    
asked by hubman 19.03.2017 в 17:32
source

7 answers

30
  

I want that when a key is pressed for a long time it is not written several times
  [...]
  when you type fast, you do not write everything. How can I improve it?


Instead of measuring times, we have to know when the user is repeating a key. To do this, we use the property KeyboardEvent.repeat , which returns true when the key and remained pressed, generating a successive typing.

var texto=document.getElementById("texto");

texto.addEventListener('keydown', function(keyboardEvent) {
    //Si se está repitiendo, ignorar
    if (keyboardEvent.repeat)
        keyboardEvent.preventDefault();
});
<textarea id="texto" style="width: 100%; height: 8em"></textarea>


Adapted to different versions of Internet Explorer

IE does not stop being the exception to the rule (- how weird, no?). In this case, when we associate the event with addEventListener() , IE always returns KeyboardEvent.repeat == false . Instead, it returns the correct value when using attachEvent ...

But there is more, attachEvent became obsolete from IE11, which left without a direct solution. So, to solve this second problem, we use the meta tag for the legacy mode X-UA-Compatible : <meta http-equiv="X-UA-Compatible" content="IE=10" /> .

And, from yapa, we add some exceptions for keys that you normally want to repeat (backspace, del, flecha, home, etc).

<!DOCTYPE html>
<html>
<head>
    <title>Evitar caracteres repetidos</title>
    <meta http-equiv="X-UA-Compatible" content="IE=10" />
    <style>
        #texto {
            width: 100%;
            height: 8em;
        }
    </style>
</head>
<body>
    <textarea id="texto" placeholder="Mantenga presionada una tecla"></textarea>
    <script language="javascript">
        var texto = document.getElementById("texto"),
            excepcionesTeclas = [
                    8,9,13,46,      //backspace tab enter del
                    33,34,35,36,    //PgUp/Dn home end
                    37,38,39,40     //flechas
                ];

        //attachEvent para IE, addEventListener para el resto
        if (texto.attachEvent) texto.attachEvent('onkeydown', noRepetirTeclas);
        else texto.addEventListener('keydown', noRepetirTeclas);

        function noRepetirTeclas(keyboardEvent) {
            //obtener .repeat según navegador
            var repeat;
            if (window.event && 'repeat' in window.event)
                repeat = window.event.repeat;
            else
                repeat = keyboardEvent.repeat;
            //Si se está repitiendo, ignorar
            // excepcionesTeclas deja repetir backspace, flechas, etc.
            if (repeat && !~excepcionesTeclas.indexOf(keyboardEvent.keyCode)) {
                if (keyboardEvent.preventDefault)
                    keyboardEvent.preventDefault();
                else if ('returnValue' in keyboardEvent)
                    keyboardEvent.returnValue = false; //IE
                else
                    return false; //IE viejo
            }
        }
    </script>
</body>
</html>

* For IE 8- it is necessary to use the Polyfill from Array.prototype.IndexOf ().

Demo upload to a free hosting

    
answered by 27.03.2017 / 06:28
source
9
  

solve according to a Boolean variable: but when you write   Quick, you do not write everything. How can I improve it?

window.onload = function() {

  var pulsado = false,
    input = document.getElementById('input');

  input.addEventListener('keydown', function(e) {
    if (pulsado) e.preventDefault();
    pulsado = true;
  });

  input.addEventListener('keyup', function() {
    pulsado = false;
  });

}
pulsa una tecla <input type="text" id='input'>
    
answered by 19.03.2017 в 20:09
8

To solve this, what I do is verify if each key is pressed, instead of just one, then I add the list of letters to an object, putting a property as letras["f"]=true , when the key is released, it is set to false , which is a necessary condition to be able to re-tighten it.

As we were talking on the chat with @Mariano , he offered a solution to detect only letters and no special keys like Backspace (backspace). This means that as the word Backspace has a length of 9 characters and not exactly 1, it works normally, while the letters, in a personalized way.

When you press a key and if the length is 1:

  • If the key was pressed previously, avoid double typing,

  • If it is not marked as pressed, the letter is written and then marked as pressed.

window.onload = function() {

  var pulsado = false
  var letras={}
  input.addEventListener('keydown',function(e){

    if(letras[e.key]==undefined){letras[e.key]=false}
    if(e.key.length==1)
    {
      if(letras[e.key]){e.preventDefault()}else{letras[e.key]=true}
    }
  })
  input.addEventListener('keyup',function(e){
    letras[e.key]=false
  })
}
Pulsa una tecla: <input type="text" id='input' />
    
answered by 27.03.2017 в 07:49
3

Here I leave the example working, you may need some retouching if you have any other requirement. Basically it's about using the keyboard events correctly considering which one runs before:

var texto = document.getElementById("texto");
var pulsado = false;
var tiempo_max = 3000; // Max tiempo de pulsación
var ultima_pulsacion; // Fecha ultima pulsación

// KeyDown
texto.addEventListener('keydown', function(keyboardEvent) {
  // Eliminamos la posición del textarea si estamos en el intervalo de tiempo
  if(Date.now() - ultima_pulsacion < tiempo_max){
    texto.value = texto.value.slice(0, -1);
  }
});

// Key Press
texto.addEventListener('keypress', function(e){
  // Si no hay ultima posición
  if(!ultima_pulsacion){
    ultima_pulsacion = Date.now();
  } else if(Date.now() - ultima_pulsacion > tiempo_max){
    // Si hemos superado el intervalo de tiempo ponemos a null la ultima_pulsacion
    ultima_pulsacion = null;
    //texto.value = texto.value.slice(0, -1);
  }
});

// Key Up
texto.addEventListener('keyup', function(e){
  // ponemos a null la última pulsación 
  ultima_pulsacion = null;
});
<textarea id="texto"></textarea>
    
answered by 19.03.2017 в 18:42
1

Try this with a little more coding to get the result.

    <script>
            var LetraPulsada=""; // la letra que se introduce
            var textoAnterior=''; // el texto anterior a la ultima tecla introducida
            var timer = 0; // timer para contar el tiempo transcurrido
            var intervalo;  // el intervalo
            var textarea; // area de texto donde se introduce el texto
            window.onload = function () // cuando este lista la pagina agregamos los eventos y los listener
            {
                textarea = document.getElementById("texto"); // hacemos referencia al area de texto
                $("#texto").enterKey(function (e) // hacemos el pequeño plugin enterKey declarado al final de este codigo
                {
                    if (LetraPulsada==e.key && timer>1) // verificamos que la letra sea igual a la ultima introducida y que el tiempo transcurrido sea mayor a 1
                    {
                        console.log('= '+e.key+' '+LetraPulsada);
                        $("#texto").val(textoAnterior); // si es true entonces significa que una tecla se ha introducido seguida de una ultima similar por lo tanto negamos la entrada de la letra e introducimos el ultimo texto de la caja
                        clear(); // por si las dudas reiniciamos el conteo
                    }
                    else
                    { // si false entonces introducimos el texto
                        textoAnterior = $("#texto").val();
                        clear(); // por si las dudas reiniciamos el conteo
                    }
                    LetraPulsada=e.key; // guardamos la ultima letra tecleada para hacer uso de ella en las conparaciones de arriba
                });

                textarea.addEventListener("keypress", function()
                {
                    console.log("keypress"+timer);
//  asignamos valor al intervalo y sumamos el timer cada vez que se cumpla el tiempo especificado
                    intervalo = setInterval(function(){timer += 1;}, 1); // 1000 = 1s
                });

                textarea.addEventListener("keyup", function()
                { // cuando se deje de pulsar la tecla reinicamos el intervalo y el timer
                    console.log("keyup");
                    clearInterval(intervalo);
                    timer = 0;
                });
            };
            function clear() // funcion auxiliar para reinicar conteo
            {
                clearInterval(intervalo);
                timer = 0;
            }

            $.fn.enterKey = function (fnc) // pequeño plugin que reconoce si una tecla fue pulsada y retorna objeto con datos de la tecla pulsada
            {
                return this.each(function ()
                {
                    $(this).keypress(function (ev)
                    {
                        var keycode = (ev.keyCode ? ev.keyCode : ev.which);
                        fnc.call(this, ev);
                    })
                })
            }


        </script>
    <textarea id="texto"></textarea>

It is worth mentioning that I use jquery and javascript

    
answered by 01.04.2017 в 08:18
0

We create a variable and when the user presses a key, the keydown function will check the status of the variable, if true cancels the repetition, otherwise it will ignore and the variable true will become and when the user releases this variable it will become false .

Here is my example:

	var pulsado = false;
	$("#texto").keydown(function(e){ 
            if(pulsado) return false;
            pulsado = true;
	}).keyup(function(){
            pulsado = false;
		}
	);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<textarea id="texto"></textarea>
    
answered by 27.03.2017 в 07:09
-2

You do not need to use all three events, just reset the text area so that it always goes back to how it was at the beginning. Something like this:

function valida_longitud () {

  let permitido = 0;
  let areaTexto = document.getElementById("texto");

  if (areaTexto.value.length != permitido) {

    areaTexto.value = "";
  }

In the html you will only tell him to react when a key is pressed:

      <textarea id="texto" value="" onKeyDown="valida_longitud()"></textarea>

Now every time you find more letters in the text area they will not show, except for the last letter that was pressed

    
answered by 19.03.2017 в 18:48