La entrada de texto HTML solo permite la entrada numérica
¿Existe una manera rápida de configurar una entrada de texto HTML ( <input type=text />
) para permitir solo pulsaciones de teclas numéricas (más '.')?
javascript
Puede filtrar los valores de entrada de un texto <input>
con la siguiente setInputFilter
función (admite Copiar+Pegar, Arrastrar+Soltar, atajos de teclado, operaciones del menú contextual, teclas que no se pueden escribir, la posición del cursor, diferentes diseños de teclado, mensajes de error de validez y todos los navegadores) . desde IE 9 ):
// Restricts input for the given textbox to the given inputFilter function.
function setInputFilter(textbox, inputFilter, errMsg) {
[ "input", "keydown", "keyup", "mousedown", "mouseup", "select", "contextmenu", "drop", "focusout" ].forEach(function(event) {
textbox.addEventListener(event, function(e) {
if (inputFilter(this.value)) {
// Accepted value.
if ([ "keydown", "mousedown", "focusout" ].indexOf(e.type) >= 0){
this.classList.remove("input-error");
this.setCustomValidity("");
}
this.oldValue = this.value;
this.oldSelectionStart = this.selectionStart;
this.oldSelectionEnd = this.selectionEnd;
}
else if (this.hasOwnProperty("oldValue")) {
// Rejected value: restore the previous one.
this.classList.add("input-error");
this.setCustomValidity(errMsg);
this.reportValidity();
this.value = this.oldValue;
this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
}
else {
// Rejected value: nothing to restore.
this.value = "";
}
});
});
}
Ahora puede utilizar la setInputFilter
función para instalar un filtro de entrada:
setInputFilter(document.getElementById("myTextBox"), function(value) {
return /^\d*\.?\d*$/.test(value); // Allow digits and '.' only, using a RegExp.
}, "Only digits and '.' are allowed");
Aplica tu estilo preferido a la input-error
clase. He aquí una sugerencia:
.input-error{
outline: 1px solid red;
}
Tenga en cuenta que aún debe realizar la validación del lado del servidor .
Otra advertencia es que esto romperá la pila de deshacer ya que se establece this.value
directamente. Esto significa que CtrlZno funcionará para deshacer las entradas después de escribir un carácter no válido.
Manifestación
Consulte la demostración de JSFiddle para obtener más ejemplos de filtros de entrada o ejecute el fragmento de pila a continuación:
Mostrar fragmento de código
Mecanografiado
Aquí hay una versión TypeScript de esto.
function setInputFilter(textbox: Element, inputFilter: (value: string) => boolean, errMsg: string): void {
["input", "keydown", "keyup", "mousedown", "mouseup", "select", "contextmenu", "drop", "focusout" ].forEach(function(event) {
textbox.addEventListener(event, function(this: (HTMLInputElement | HTMLTextAreaElement) & { oldValue: string; oldSelectionStart: number | null, oldSelectionEnd: number | null }) {
if (inputFilter(this.value)) {
this.oldValue = this.value;
this.oldSelectionStart = this.selectionStart;
this.oldSelectionEnd = this.selectionEnd;
}
else if (Object.prototype.hasOwnProperty.call(this, "oldValue")) {
this.value = this.oldValue;
if (this.oldSelectionStart !== null &&
this.oldSelectionEnd !== null) {
this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
}
}
else {
this.value = "";
}
});
});
}
jQuery
También hay una versión jQuery de esto. Vea esta respuesta .
HTML5
HTML5 tiene una solución nativa <input type="number">
(consulte la especificación y la documentación ). La documentación tiene una demostración funcional de este tipo de entrada.
- En lugar de leer la
value
propiedad, lea lavalueAsNumber
propiedad de la entrada para obtener el valor escrito como un número en lugar de una cadena. - Se recomienda el uso dentro de a
<form>
porque de esta manera se facilita la validación; por ejemplo, al presionar Enterse mostrará automáticamente un mensaje de error si el valor no es válido.- Puede utilizar el
checkValidity
método o elrequestSubmit
método en todo el formulario para comprobar explícitamente la validez. - Tenga en cuenta que es posible que necesite utilizar el
required
atributo para no permitir una entrada vacía.
- Puede utilizar el
- Puede utilizar el
checkValidity
método o lavalidity
propiedad en el propio elemento de entrada para comprobar explícitamente la validez. - Puede utilizar
reportValidity
para mostrar un mensaje de error y utilizarsetCustomValidity
para configurar su propio mensaje.
Este enfoque tiene fundamentalmente una experiencia de usuario diferente: se le permite ingresar caracteres no válidos y la validación se realiza por separado . Esto tiene la ventaja de que la pila de deshacer ( CtrlZ) no se romperá. Tenga en cuenta que se debe realizar la validación del lado del servidor, independientemente del enfoque que elija.
Pero tenga en cuenta que la compatibilidad con el navegador varía:
- La mayoría de los navegadores solo validarán la entrada al enviar el formulario y no al escribir.
- La mayoría de los navegadores móviles no admiten los
step
atributosmin
ymax
. - Chrome (versión 71.0.3578.98) todavía permite al usuario ingresar los caracteres
e
enE
el campo. Consulte también las Preguntas y respuestas ¿ Por qué la entrada HTML permite ingresartype="number"
la letra en el campo?e
. - Firefox (versión 64.0) y Edge (EdgeHTML versión 17.17134) aún permiten al usuario ingresar cualquier texto en el campo.
Manifestación
document.querySelector("form").addEventListener("submit", (event) => {
event.preventDefault();
console.log(`Submit!
Number is ${event.target.elements.number.valueAsNumber},
integer is ${event.target.elements.integer.valueAsNumber},
form data is ${JSON.stringify(Object.fromEntries(new FormData(event.target).entries()))}.`);
})
label {
display: block;
}
<form>
<fieldset>
<legend>Get a feel for the UX here:</legend>
<label>Enter any number: <input name="number" type="number" step="any" required></label>
<label>Enter any integer: <input name="integer" type="number" step="1" required></label>
<label>Submit: <input name="submitter" type="submit"></label>
</fieldset>
</form>
Utilice este DOM
<input type='text' onkeypress='validate(event)' />
Y este guión
function validate(evt) {
var theEvent = evt || window.event;
// Handle paste
if (theEvent.type === 'paste') {
key = event.clipboardData.getData('text/plain');
} else {
// Handle key press
var key = theEvent.keyCode || theEvent.which;
key = String.fromCharCode(key);
}
var regex = /[0-9]|\./;
if( !regex.test(key) ) {
theEvent.returnValue = false;
if(theEvent.preventDefault) theEvent.preventDefault();
}
}
Aquí hay uno simple que permite exactamente un decimal, pero no más. El evento de entrada utiliza expresiones regulares para reemplazar texto sobre la marcha según los dos patrones:
- Elimina todo lo que no sea un dígito o un punto.
- Eliminar cualquier segunda instancia de un punto
<input type="text" oninput="this.value = this.value.replace(/[^0-9.]/g, '').replace(/(\..*?)\..*/g, '$1');" />
Como alguien comentó a continuación, la solución anterior no maneja ceros a la izquierda. Si su caso de uso particular requiere que estos no estén permitidos, puede agregarlos al patrón anterior de esta manera:
<input type="text" oninput="this.value = this.value.replace(/[^0-9.]/g, '').replace(/(\..*?)\..*/g, '$1').replace(/^0[^.]/, '0');" />
Eso permitirá 0.123
o .123
pero no 0123
o 00.123
.
He buscado durante mucho tiempo una buena respuesta a esto, y la necesitamos desesperadamente <input type="number"
, pero aparte de eso, estas 2 son las formas más concisas que se me ocurren:
<input type="text"
onkeyup="this.value=this.value.replace(/[^\d]/,'')">
Si no le gusta el carácter no aceptado que se muestra durante una fracción de segundo antes de borrarlo, el siguiente método es mi solución. Tenga en cuenta las numerosas condiciones adicionales, esto es para evitar deshabilitar todo tipo de navegación y teclas de acceso rápido. Si alguien sabe cómo compactar esto, ¡háganoslo saber!
<input type="text"
onkeydown="return ( event.ctrlKey || event.altKey
|| (47<event.keyCode && event.keyCode<58 && event.shiftKey==false)
|| (95<event.keyCode && event.keyCode<106)
|| (event.keyCode==8) || (event.keyCode==9)
|| (event.keyCode>34 && event.keyCode<40)
|| (event.keyCode==46) )">
La mayoría de las respuestas aquí tienen la debilidad de utilizar eventos clave .
Muchas de las respuestas limitarían su capacidad para seleccionar texto con macros de teclado, copiar y pegar y más comportamientos no deseados, otras parecen depender de complementos jQuery específicos, que matan moscas con ametralladoras.
Esta solución simple parece funcionar mejor para mí en varias plataformas, independientemente del mecanismo de entrada (pulsación de tecla, copiar y pegar, hacer clic derecho en copiar y pegar, voz a texto, etc.). Todas las macros del teclado de selección de texto seguirían funcionando e incluso limitarían la capacidad de establecer un valor no numérico mediante un script.
function forceNumeric(){
var $input = $(this);
$input.val($input.val().replace(/[^\d]+/g,''));
}
$('body').on('propertychange input', 'input[type="number"]', forceNumeric);