entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

4votos

¿Como hacer para que solo se puedan picar ciertos caracteres?

Con este código consigo que no se puedan introducir más de 2 caracteres en el input, pero si yo quiero ademas que solo ciertos caracteres se puedan picar ¿Como lo hago?

$(document).ready(function() {
        $("body").on("click", "form", function( event ) {          
            var caracteres = 1;
            var elementopresionado = ".camponumerico";

            function limitarcaracteres() {
                                if($(this).val().length > caracteres) {                 
                        $(this).val($(this).val().substr(0, caracteres));
                }
            }           
            $(elementopresionado).keydown(limitarcaracteres);
        });

0voto

bichomen comentado

Hola, después de muchas pruebas y de rehacer el código des el principio, creo estar muy cerca del objetivo que busco:

$(document).ready(function() {
function limitarcaracteres(event) {         
                var MAX_CARACTERES = 1;
                var elementopresionado = ".camponumerico";
                var keyCode = event.which || event.keyCode;

                if(keyCode < 48 || keyCode > 57 && keyCode != 8) 
                {
                    return false;
                }           
                else if($(elementopresionado).val().length > MAX_CARACTERES) {                          
                    return false;
                }
                else if(parseInt($(elementopresionado).val()) < 1 || parseInt($(elementopresionado).val())  > 20) {     
                    return false;
                    $("#submit").prop( "disabled", true );
                }                   
                else {
                    $("#submit").prop( "disabled", false );
                }
            }

            $("body").on("keydown", ".camponumerico", function( event ) {
                    return limitarcaracteres(event);        
            });
});

Con este código primero compruebo que sean números lo que se introduce, después que no marque más de dos dígitos, lo compruebo con la variable MAX_CARACTERES y le doy el valor 1, porque la propiedad length empieza a contar por 0, si pongo 2 entonces me deja introducir 3 dígitos y eso es algo que yo no quiero, el problema lo tengo en la comprobación de los números permitidos después de varias pruebas me he dado cuenta que pone el valor del campo cuando marcas el siguiente dígito, para que me entendáis lo que hace es que si marco un solo dígito devuelve null, cuando marco el segundo dígito devuelve el valor del primer dígito y cuando marco el tercer dígito, es cuando devuelve el valor de los 2 primeros dígitos, pero claro volvemos a lo de principio, no quiero que marque más de dos dígitos. Por otro lado por poner un ejemplo los números permitidos son del 1 al 15 yo quiero que cuando el usuario marque 1 le deje poner el siguiente si marca 4 le deje marcar el segundo dígito pero si es 6, ya no lo pueda marcar, lo mismo si el primer dígito es 2 ya no le deje marcar el segundo dígito.

La parte final del código si todos los if se cumplen, que habilite el submit del formulario, que ahora lo he deshabilitado y solo se habilitada si se cumplen las condiciones de validación del formulario.

Como he dicho al principio estoy cerca, pero necesito que me hagáis ver la luz. gracias.

0voto

jrgm0005 comentado

Hola @bichomen,

Te vas acercando, pero te voy a dar un pequeño consejo.

Separa las funciones, la función limitarCaracteres hace más cosas, también filtra por el valor por ejemplo.

Controla por un lado, la tecla que se pulsa con una función, y por otro lado comprueba el valor que tiene la variable, si es mayor de 20 o de 15 ya no te sirve, así te estarías ahorrando comprobar por la longitud del campo.

Me explico, así con 2 funciones lo tienes controlado, igual que en el mismo comentario que te puse arriba.

Con eso lo tendrías solucionado o casi solucionado, revisa el comentario anterior que te puse con el código, porque estás haciendo lo mismo, solo que una comprobación más, la de comprobar si es menor que 1.

Un saludo.

0voto

bichomen comentado

Hola @jrgm0005,

EL problema, es que ya filtro por el valor, he modificado el codigo para var numero = $(".camponumerico").prop('value'); pero el resultado es el mismo, el problema es que la primera vez que presionas un carácter, no lo tiene en cuenta hasta que no se presiona el siguiente.

El valor de .camponumerico, es variable, si presiono una vez 3 su valor es 3, si a continuación presiono 5 su valor es 35, así debería ser pero no lo hace, no se si el keydown tiene algo que ver en esto

0voto

jrgm0005 comentado

Mmm, vale, puedes probar tal cual, pero con el evento keypress.

Yo creo que no te lo reconoce aún el valor por el keydown, tal vez tengas razón, pero lo que es el código lo tienes casi hecho ;)

1voto

magarzon comentado

A ver, para que no haya confusión: el campo length NO empieza por 0, (no es un índice, es una longitud), lo que pasa es que cuando tomas ese valor, el input todavía no se ha actualizado, y por tanto al principio tendrá valor 0 (el input está vacío).
Como tanto keydown como keypress se lanzan antes de que el campo tome el nuevo valor, y keyup no te deja "cancelar" el evento, lo que tendrías que hacer es algo así:

$(document).ready(function() {
function limitarcaracteres(event) {         
                var MAX_CARACTERES = 2;
                var elementopresionado = ".camponumerico";
                var keyCode = event.which || event.keyCode;
                var newVal = $(elementopresionado).val()+String.fromCharCode(keyCode);

                if(keyCode < 48 || keyCode > 57 && keyCode != 8) 
                {
                    return false;
                }           
                else if(newVal.length > MAX_CARACTERES) {                          
                    return false;
                }
                else if(parseInt(newVal) < 1 || parseInt(newVal)  > 20) {     
                    $("#submit").prop( "disabled", true );
                    return false;
                }                   
                else {
                    $("#submit").prop( "disabled", false );
                }
            }

            $("body").on("keypress", ".camponumerico", function( event ) {
                    return limitarcaracteres(event);        
            });
});

He cambiado el evento keydown por keypress, es mejor.

Por otro lado, hacer lo otro que dices de que si el límite es 15 y ha introducido un 6 no le deje, con este código también se conseguiría.

También hacer notar que tanto la propiedad which como la keyCode están obsoletas, en el futuro es posible que haya que refactorizar este código y utilizar la propiedad key, pero de momento esto funciona para todos los navegadores, y key no funciona para Safari (además que key devuelve el valor en sí, no el código ASCII, por lo que habría que cambiar el código)

Por último, perdona por no darme cuenta antes de que el val() que estabas obteniendo no era el "real" o actualizado, las soluciones que te pongo las hago "de cabeza" no las pruebo en sí.

0voto

bichomen comentado

Pues muchas gracias, ahora ya funciona, solo un pequeño detalle, como excepción puse que aceptarse presionarse la tecla de retroceso (&& keyCode != 8) para que se pudiese borrar, pero no funciona.

Si se inserta un 3 y después un 9, el formulario se bloquea y no puedes corregir el numero, al igual que si pones 12 y querías poner 13 no me deja borrar.

En principio el código ASCII de esta tecla es el 8, también estaría bien que funcionara con la tecla se suprimir (&& keyCode != 127).

¿Porque no funciona? Solo faltaría este detalle.

1voto

magarzon comentado

Eso es porque no me hiciste caso y usaste keydown en lugar de keypress. keypress no se lanza para teclas de control (backspace, suprimir...), con lo que no tienes que controlarlas, y tendrán su función original.

Si quisieras usar keydown, tendrías que controlar no solo el borrar y el suprimir, si no las teclas de cursor (no podrías usar si no la tecla suprimir (que por cierto es la 46, no la 127), ya que no puedes ponerte al principio del input), etc. Y tendrías que poner esta línea justo después de obtener el keyCode:

if (keyCode == 8 || keyCode == 46 || keyCode == 37 || keyCode == 39) {
  return true;
}

Pero vamos, que mejor usa keypress, porque si quieres tener cosas como que funcione el botón home para ir al principio. o que funcione el copy/paste, también tendrías que añadirlo como excepción.

0voto

bichomen comentado

Pero es que estoy utilizando keypress, como me pusiste arriba y no funciona

0voto

bichomen comentado

if (keyCode == 8 || keyCode == 46 || keyCode == 37 || keyCode == 39) { return true; }

Añadiendo esta linea tal y como indicas funciona con el keypress. Ahora si, perfecto.

¡¡Muchas gracias!!

0voto

magarzon comentado

Si añades esa línea y funciona, no estás usando keypress, porque keypress no se llama para esas teclas.

1voto

bichomen comentado

Te pego el codigo tal y como lo tengo ahora mismo con keypress, yo ya me conformo con el funcionamiento actual, seguramente tendrás razón pero desconozco porque, también es verdad que solo estoy probando con Firefox

function limitarcaracteres(event) {         
                var MAX_CARACTERES = 2;
                var elementopresionado = ".camponumerico";
                var keyCode = event.which || event.keyCode;             
                if (keyCode == 8 || keyCode == 46 || keyCode == 37 || keyCode == 39) {
                    return true;
                }
                var newVal = $(elementopresionado).val() + String.fromCharCode(keyCode);

                if(keyCode < 48 || keyCode > 57) 
                {
                    return false;
                }           
                else if(newVal.length > MAX_CARACTERES) {                          
                    return false;
                }
                else if(parseInt(newVal) < 1 || parseInt(newVal)  > 20) {     
                    $("#submit").prop( "disabled", true );
                    return false;
                }                   
                else {
                    $("#submit").prop( "disabled", false );
                }
            }
            $("body").on("keypress", ".camponumerico", function( event ) {
                return limitarcaracteres(event);        
            });

2votos

jrgm0005 comentado

Hola @bichomen @magarzon,

Me alegro que hayas resuelto tu problema.

Te dejo aquí una solución al mismo, que creo que hace lo que buscas, de una manera más sencilla y fácil de entender.

Link al ejemplo

Espero tu comentario a ver si lo que hace es lo que esperabas.

Un saludo.

1voto

bichomen comentado

Hola @jrgm0005, tu codigo esta bien y funcionan las teclas de control, yo prefiero tener todo agrupado en una función ya que el archivo jquery tiene muchas más funciones que esta y así queda todo más ordenado por funciones, solo un detalle, tu código no acepta el 20 y en cambio acepta el 0.

Saludos

1voto

jrgm0005 comentado

Ah sí, jaja lo hice así rápido para mostrar, eso sólo es cambiar el if de la función de si es menor que 20, pero era así para mostrarte.

Mi consejo es que separes lo máximo posible, porque aunque sean más funciones, siempre vas a poder reutilizar al máximo y eso es fundamental en proyectos grandes.

Me alegro que ya tengas solucionada tu duda.

Un saludo.

1voto

jrgm0005 comentado

Te he actualizado el código, por si quieres echarle un vistazo, para que veas qué tal se queda tal cual como quieres.

¿Qué te parece el código? ¿Es fácil de entender y de leer?

Un saludo.

3 Respuestas

3votos

magarzon Puntos30650

Modifica tu función limitarCaracteres así:

function limitarcaracteres(event) {
  if($(this).val().length > caracteres) {                
      return false; //No hace falta hacer un substr, con que devuelvas false ya no te añade el último caracter introducido
  }   

   var keyCode = event.which || event.keyCode;
   //En keyCode tienes el código ASCII de la tecla presionada, por ejemplo para permitir sólo números:
   return keyCode >= 48 && keyCode <= 57;
}  

Por cierto, me acabo de dar cuenta. ¿Por qué estableces el keydown cada vez que haces click en el form? De esta forma, vas a añadir N controladores, uno por cada vez que el usuario haga click en el formulario, que luego se van a ejecutar N veces cada vez que el usuario entre algún carácter en el campo (y además si el usuario accede al input pulsando tabulador, en lugar de hacer click en el form, no te va a funcionar). Deberías establecerlo fuera del formulario, aplicado al elemento input concreto.

1voto

bichomen comentado

Por cierto, me acabo de dar cuenta. ¿Por qué estableces el keydown cada vez que haces click en el form? De esta forma, vas a añadir N controladores, uno por cada vez que el usuario haga click en el formulario, que luego se van a ejecutar N veces cada vez que el usuario entre algún carácter en el campo (y además si el usuario accede al input pulsando tabulador, en lugar de hacer click en el form, no te va a funcionar). Deberías establecerlo fuera del formulario, aplicado al elemento input concreto.

Porque no me gustaba el efecto del keyup, el keydown evita que directamente escribas, con el keyup, escribes y luego se borra, no me había fijado en lo del tabulador

He modificado el código, para que solo pueda meter números del 1 al 20, pero no me funciona:

$("body").on("click", "form", function( event ) {          
            var caracteres = 1;
            var elementopresionado = ".camponumerico";
            var suma = 0;

            function limitarcaracteres(event) {
                if($(this).val().length > caracteres) {                 
                        return false;
                }
                var keyCode = event.which || event.keyCode;
                suma += keyCode.value;
                if (suma > 0 && suma <= 20 && keyCode >= 48 && keyCode <= 57) {
                    return keyCode;
                }
            }           
            $(elementopresionado).keydown(limitarcaracteres);           
        });

1voto

magarzon comentado

No te funciona por varios motivos:

  1. keyCode es un entero, no es un objeto, con lo que keyCode.value te va a dar como valor undefined
  2. La función tiene que devolver true o false, devolver keyCode te puede funcionar, porque cualquier valor entero positivo es equivalente a true, pero no estoy seguro que el no devolver nada en caso de no cumplirse la condición sea equivalente a devolver false
  3. Estás inicializando el valor de suma dentro del evento click del form. Si yo entro en el campo, meto un 3, hago click en otro lado, y vuelvo a entrar en el campo y meto un 0, con lo que el valor sería 30, me va a dejar, porque al hacer el segundo click va a inicializar la suma a 0.

Te doy el mismo consejo que antes, saca el keydown del evento click, y por otro lado si quieres limitar el valor, comprueba contra el valor del input (por ejemplo $(this).val(), no contra una suma que, como ya te he dicho, puede tener cualquier valor

2votos

Leonardo-Tadei comentado

Hola @bichomen,

lo que @magarzon quiere decirte no es que cambies el evento keydown por otro, si no que no le asignes el evento dentro del evento click, porque de esta forma le estás asignado el evento cada vez que el usuario clickea.

Asigna el manejador de evento fuera del click!

Saludos cordiales

2votos

jrgm0005 Puntos2990

Hola @bichomen,

Esto es un MUST para crecer como developer, DIVIDE Y VENCERAS, tienes que aprender a estudiar tu situación, estudiarla y ver lo que quieres obtener.

Haz las cosas por pasos, y que cada parte de código se encargue de una sola cosa.

Aquí te voy a dejar un ejemplo de como sería una solución aproximada, no sé si el código será el correcto ni será lo que estás buscando exactamente, pero échale un vistazo a cómo he ido solucionando y el proceso seguido, y así tú mismo pensaras la solución más limpia y clara posible a tu problema.

// Función que comprueba si el valor introducido es númerico
function entradaEsNumero(event){
var keyCode = event.which || event.keyCode;
   return keyCode >= 48 && keyCode <= 57;
}

// Función que comprueba si es menor que 20, que creo que no necesitas un acumulado
function valorMenorQue20(campoNumerico) {
return parseInt(campoNumerico.val()) < 20;
            }

// Una vez que tenemos nuestras funciones para lo que queremos, añadimos el evento, donde validamos, primero que sea númerico lo introducido, y después que su valor no es superior a 20.
$(".camponumerico").onkeydown = function(){
return entradaEsNumero(event) && valorMenorQue20($(".camponumerico"));
}

Si tienes más dudas no dudes en preguntar.

Un saludo.

Juan Ramón González Morales. UX Designer

1voto

bichomen comentado

Gracias @magarzon @Leonardo-Tadei @jrgm0005

La verdad me esta costando, he intentado aplicar lo que me habeis comentado, pero si no hago un $("body").on("click", ".camponumerico", function( ) { no consigo que funcione en parte, entiendo lo que comentaba @magarzon, pero no se como aplicarlo y luego enlazarlo con la función de delimitar el numero de caracteres del 1 al 20, he probado con este código pero no funciona:

$(".camponumerico").keydown(function() {

            var caracteres = 1;
            var elementopresionado = ".camponumerico";

            function limitarcaracteres(event) {
                if($(this).val().length > caracteres) {                 
                        return false;
                }
                var keyCode = event.which || event.keyCode;

                return keyCode >= 48 && keyCode <= 57;
            }

            function veinte(elementopresionado) {

                if(!parseInt(elementopresionado.val()) > 20 && !parseInt(elementopresionado.val()) <= 0) {
                    return false;   
                }
                else
                    return elementopresionado;
                }
            }   

            limitarcaracteres(event);           
            veinte(elementopresionado);

            if(limitarcaracteres(event) == false || veinte(elementopresionado) == false ) {
                return  false;
            }                   
        });  

1voto

magarzon comentado

No te funciona por varios motivos:

  • Cuando llamas a la función limitarcaracteres, le estás pasando un parámetro event que en realidad no está definido. Ese parámetro event es el evento "producido" por el keydown, por tanto debes definirlo en la función del keydown, algo así:
$(".camponumerico").keydown(function(event) {
///Aquí el resto
}
  • Estás llamando a la función veinte con un string ('.camponumerico'), no con un objeto jQuery.

  • Tu intención inicial era limitar el número de caracteres a 2, sin embargo lo estás limitando a 1, porque la variable caracteres se pone a 1 cada vez que introduces algo.

Por otro lado, ¿por qué llamas dos veces a limitarcaracteres y veinte, una por sí solos, y luego otra en el if?

Deberías guardar el resultado de las llamadas. Además, deberías sacar esas funciones fuera de la función del keydown, para una mejor organización y reutilización del código.Para ello debes cambiarlo un poco el código, porque el this ya no se referirá al input

Algo así te debería funcionar:

var MAX_CARACTERES = 2;

$(".camponumerico").keydown(function(event) {

    var elementopresionado = $(this);

    return limitarcaracteres(event) && veinte(elementopresionado);           
});

function limitarcaracteres(event) {
   var elementopresionado = event.currentTarget;
   if(elementopresionado.val().length > MAX_CARACTERES) {                 
      return false;
   }

   var keyCode = event.which || event.keyCode;

   return keyCode >= 48 && keyCode <= 57;
}

function veinte(elementopresionado) {
   return parseInt(elementopresionado.val()) >= 0 && parseInt(elementopresionado.val()) < 20) 
}   

1voto

bichomen comentado

Hola @magarzon, gracias por la ayuda he tenido que modificar un poco tu código por porque la función de veinte daba un error tal cual la ponías, aun así cuando presiono en .camponumerico, no salta el evento, no hace nada, he mirado en el depurador de Mozilla y esta todo correcto, pero el alert que he puesto no salta, eso es que no esta identificando el evento.

No se donde esta el error, por cierto he buscado event.currentTarget porque no sabía que hacía esta propiedad y lo que hace es devolver true o false un booleano ¿es correcto?, porque entonces elementopresionado.val().length fallaría, ya que no devolvería un int, así lo entiendo yo.

var MAX_CARACTERES = 2;

        $(".camponumerico").keydown(function(event) {
            alert('Entro?')
                var elementopresionado = $(this);   

                return limitarcaracteres(event) && veinte(elementopresionado);           
        });

        function limitarcaracteres(event) {
            var elementopresionado = event.currentTarget;
            if(elementopresionado.val().length > MAX_CARACTERES) {                 
                    return false;
            }

            var keyCode = event.which || event.keyCode;

            return keyCode >= 48 && keyCode <= 57;
        }

        function veinte(elementopresionado) {
            var numero = parseInt(elementopresionado.val());
            if(numero <= 0 && numero > 20) {
                return false;       
            }
            return numero;
        }

1voto

magarzon comentado

No sé dónde has mirado lo del currentTarget, pero lo que te devuelve es el elemento que ha lanzado el evento.

Y si ni siquiera te salta el alert, puede ser por dos motivos:

  1. Tu input no tiene la clase camponumerico o tienes algún typo (has puesto por ejemplo camponumerrico)
  2. No estás llamando a esta parte del código en el onReady, y por tanto nunca se asocia el evento a los elementos con la clase camponumerico.

1voto

bichomen comentado

No estás llamando a esta parte del código en el onReady, y por tanto nunca se asocia el evento a los elementos con la clase camponumerico.

No, si que lo estoy poniendo, no lo puse aquí porque lo vi obvio:

$(document).ready(function() {

...

});

1voto

jrgm0005 Puntos2990

Hola @bichomen ,

En ese código, las funciones tienes que declararlas fuera del evento, y en el evento llamarlas.Aún así échale un vistazo a mi código, que creo que te soluciona tu problema, o te deja en una aproximación bastante cercana.

1voto

magarzon comentado

Es mejor partir siempre de su código, y que sea lo más aproximado a su estructura y nomenclatura, para que asimile mejor los cambios y en qué se ha equivocado

1voto

jrgm0005 comentado

Puede ser, a veces me pongo así en plan por reducir y hacerlo lo más simple posible, que a lo mejor, se puede perder con cierta refactorización del código.

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta