En la caja de texto inicialmente habría escrito HH:MM, y mientras el usuario escribía su hora, el campo debería ir variando según la máscara, sustituyéndola. Es decir, para escribir 16:46, el usuario escribiría 1646 y automáticamente se vería escrito 16:46 pero con este estilo:
HH:MM -> Ninguna pulsación
1H:MM -> Pulsado: 1
16:MM -> Pulsado: 6
16:4M -> Pulsado:4
16:46 -> Pulsado:5
Bueno, pues lo hice en su día algo más simple, pero lo he mejorado bastante, tanto que se podría insertar en un proyecto sencillo:
Código PHP:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title></title>
<meta name="Author" content="derkeNuke">
</head>
<body>
<p>Inserte su hora en formato <b>HH:MM</b>:<br/>
<input type="text" id="caja" />
<div id="capaError" style="color:red; visibility:hidden;"></div>
<script type="text/javascript">
var laCaja=document.getElementById("caja");
var valor=""; //los números que vayamos ingresando en la caja
/********
MANEJADORES PARA EL CASO DE ERROR
********/
var capaError=document.getElementById("capaError");
var errorMostrandose=false; //variable de control que nos informa de si estamos mostrando la capaError
function mostrarError(errnum,str) { //mostrar
var cont;
switch(errnum) {
case 0: cont=str; break;
case 1: cont="Caracter no permitido en esa posicion. Formato <b>HH:MM</b> 24h. Ejemplo: 16:48."; break;
case 2: cont=laCaja.value+" no es una hora completa, termine de rellenarla por favor."; break;
default: cont="Error de formato HH:MM"; break;
}
capaError.innerHTML=cont;
capaError.style.visibility="visible";
errorMostrandose=true;
return false;
}
function ocultarError() { //ocultar
capaError.style.visibility="hidden";
errorMostrandose=false;
return true;
}
/********
SUSTITUYE HH:MM DEL CAMPO POR LO QUE VAYAMOS ESCRIBIENDO
********/
function ponMascara(valueActual,mascaraTotal) {
var mascara=mascaraTotal.substring( valueActual.length, mascaraTotal.length );
laCaja.value=valueActual+mascara;
}
/********
VALIDACIÓN DE LA HORA: Devuelve true en caso de que el caracter sea válido en la posición pos para el formato HH:MM 24h
********/
function esValidoHHMM(c,pos) {
if( pos==1 ) // primer caracter de las horas (entre 0 y 2)
return /^[0-2]$/.test(c);
else if( pos==2 ) // segundo caracter de las horas (depende del primero)
return /^([0-1][0-9])|(2[0-3])$/.test(valor+c);
else if( pos==3 || pos==4 ) // primer caracter de los minutos (entre 0 y 5)
return /^[0-5]$/.test(c);
else if( pos==5 ) // segundo caracter de los minutos (entre 0 y 9)
return /^[0-9]$/.test(c);
else // cualquier otro caso
return false;
}
/********
COLOCACIÓN DEL CURSOR: Da el foco a la caja colocando el cursor de inserción en la posición pos
********/
function ponCursorEnPos(pos){
if(typeof document.selection != 'undefined' && document.selection){ //método IE
var tex=laCaja.value;
laCaja.value='';
forzar_focus(); //debería ser focus(), pero nos salta el evento y no queremos
var str = document.selection.createRange();
laCaja.value=tex;
str.move("character", pos);
str.moveEnd("character", 0);
str.select();
}
else if(typeof laCaja.selectionStart != 'undefined'){ //método estándar
laCaja.setSelectionRange(pos,pos);
forzar_focus(); //debería ser focus(), pero nos salta el evento y no queremos
}
}
/********
ONKEYPRESS: controlará cada caracter, si es especial haremos su función, si es válido lo escribirá, y si es inválido muestra error
********/
laCaja.onkeypress=function(e){
var code;
if (!e) var e = window.event;
if (e.keyCode) code = e.keyCode; // detectamos el codigo de la tecla
else if (e.which) code = e.which;
var caracter = String.fromCharCode(code); // extraemos su caracter
if (code==8) { // caracter BACKSPACE para borrar números de la caja
// borramos un caracter de valor, y si hay un ":" borramos dos
if(valor.length==3) //hay colocado HH:
valor=valor.substring(0,1); //dejamos H
else if(valor.length>0) //si hay algo que borrar, borramos un caracter
valor=valor.substring(0,valor.length-1);
ponMascara(valor,"HH:MM"); //actualizamos el contenido
ponCursorEnPos(valor.length); //movemos el cursor ya que el contenido ha sido modificado
if(errorMostrandose) ocultarError(); //ocultamos el error si hubiera
}
else if( esValidoHHMM(caracter, valor.length+1) ) { // si es un número válido en el contexto, lo añadiremos
if(valor.length==2)
valor+=":";
if(valor.length<"HH:MM".length)
valor+=caracter;
ponMascara(valor,"HH:MM"); //actualizamos el contenido
ponCursorEnPos(valor.length); //movemos el cursor ya que el contenido ha sido modificado
if(errorMostrandose) ocultarError(); //ocultamos el error si hubiera
}
else
mostrarError(1); // caracter NO PERMITIDO
return false; //nunca aceptaremos que el evento continúe, controlaremos el value siempre nosotros
}
/********
MANEJADOR PARA EL FOCO: Función para el evento onfocus
********/
function focus_handler() {
ponCursorEnPos(valor.length);
}
laCaja.onfocus=focus_handler;
/********
MANEJADOR PARA EL FOCO: hace el focus sin hacer saltar el evento onfocus, es decir, sin hacer saltar focus_handler
********/
function forzar_focus() {
laCaja.onfocus=null; //quito
laCaja.focus(); //hago
setTimeout("laCaja.onfocus=focus_handler",1); //pongo (retrasado para IE...)
}
/********
ONBLUR: Comprueba si la hora está a medias para escribir el error
********/
laCaja.onblur=function() {
if(valor.length>0 && valor.length<5) //hora incompleta
mostrarError(2);
else if(errorMostrandose) ocultarError(); //ocultamos el error si hubiera
}
ponMascara("","HH:MM"); //inicialización
</script>
</body>
</html>
El código no es complicado, está fragmentado. Hay partes ilegibles porque son manías de los exploradores hacerlos así.
Tiene validación en tiempo real, es decir, si la tecla pulsada no encaja, somos advertidos (sin intrusión alguna). Además tiene soporte para la tecla BACKSPACE, pudiendo borrar dígitos si nos equivocásemos.
Quiero hacerle también soporte para las flechas, para poder navegar por el campo sin restricciones y cambiar el caracter que nos convenga, creo que va a ser complicado y habrá que meter mucho código de más. Lo intentaré en cuanto pueda.
Me gustaría que lo probárais para que veais lo que da de sí, e informar de los posibles fallos que pudiera haber.
Y por supuesto si hay sugerencias para el buen funcionamiento del script o su mejora, bienvenidisimas sean que las intentaré.
Cuando lo considere más o menos presentable, irá para las FAQ cómo no.
Saludos
![de acuerdo](http://static.forosdelweb.com/fdwtheme/images/smilies/dedosarriba.png)
![de acuerdo](http://static.forosdelweb.com/fdwtheme/images/smilies/dedosarriba.png)