Cómo hacer un control para poder seleccionar el año que queremos ver en el calendario jQuery.
Imaginar que necesitamos seleccionar una fecha que está 6 años hacia delante en el calendario. Tendríamos que ir 12 x 6 meses hacia delante para poder mostrar el mes y año del que queremos seleccionar la fecha y eso es poco práctico.
Así que, para evitar que la navegación por meses se quede corta, vamos a hacer un pequeño control para poder seleccionar cualquier año. El resultado de lo que vamos a realizar se puede ver en una página aparte.
Control para el cambio de año
En este ejemplo lo único que vamos a crear es un botón para el cambio de año. Ese botón aparecerá al lado del año en el calendario y al pulsarlo creará una capa con diversos números de año (10 años para atrás y otros 10 para adelante). Las diversas opciones de año se podrán pulsar y entonces desaparecerá la capa de los años y se actualizará el año del calendario.
var botonCambioAno = $('<a href="#" class="botoncambiaano"><span></span></a>')
botonCambioAno.click(function(e){
e.preventDefault();
var botonActivoSelAnos = $(this);
//creo una capa con una serie de años para elegir
var capaAnos = $('<div class="capaselanos"></div>');
//genero 10 años antes y 10 después
for (var i=ano-10; i<=ano+10; i++){
var codigoEnlace = '<a href="#"';
if (i==ano)
codigoEnlace += ' class="seleccionado"';
if (i==ano+10)
codigoEnlace += ' class="ultimo"';
codigoEnlace += '><span>' + i + '</span></a>';
var opcionAno = $(codigoEnlace);
opcionAno.click(function(e){
e.preventDefault();
ano = parseInt($(this).children().text());
capaDiasMes.empty();
muestraDiasMes(mes, ano);
capaAnos.slideUp();
capaAnos.detach();
})
capaAnos.append(opcionAno);
}
//coloco la capa en la página
$(document.body).append(capaAnos);
//posiciono la capa
capaAnos.css({
top: (botonActivoSelAnos.offset().top + 12) + "px",
left: (botonActivoSelAnos.offset().left - 25) + "px"
})
capaAnos.slideDown();
})
Eso es todo, con esta modificación ya queda listo el calendario jQuery, por lo menos todo lo que hemos querido implementar en estas fases. Seguramente otras personas necesitarán otras modificaciones, y esperamos que al haber visto el calendario en sus distintas etapas sea más sencillo encontrar por uno mismo el lugar o lugares donde se debe modificar.
Con todo, hemos creado un calendario dinámico para la selección de fechas en menos de 300 líneas de código, que ocupa 9 KB de código Javascript, lo que lo hace más que razonablemente ligero para utilizar en cualquier proyecto. Además, a través de la hoja de estilos, cualquier persona podrá alterar radicalmente el aspecto del calendario para adaptarlo al look & feel de su sitio web.
Código completo del plugin calendario
Para acabar, vamos a colocar el código Javascript completo del plugin Calendario jQuery.
jQuery.fn.calendarioDW = function() {
this.each(function(){
//saber si estoy mostrando el calendario
var mostrando = false;
//variable con el calendario
var calendario;
//variable con los días del mes
var capaDiasMes;
//variable para mostrar el mes y ano que se está viendo
var capaTextoMesAnoActual = $('<div class="visualmesano"></div>');
//iniciales de los días de la semana
var dias = ["l", "m", "x", "j", "v", "s", "d"];
//nombres de los meses
var nombresMes = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"]
//elemento input
var elem = $(this);
//creo un enlace-botón para activar el calendario
var boton = $("<a class='botoncal' href='#'><span></span></a>");
//inserto el enlace-botón después del campo input
elem.after(boton);
//evento para clic en el botón
boton.click(function(e){
e.preventDefault();
mostrarCalendario();
});
//evento para clic en el campo
elem.click(function(e){
this.blur();
mostrarCalendario();
});
//función para mostrar el calendario
function mostrarCalendario(){
if(!mostrando){
mostrando = true;
//es que hay que mostrar el calendario
//dias de la semana
var capaDiasSemana = $('<div class="diassemana"></div>');
$(dias).each(function(indice, valor){
var codigoInsertar = '<span';
if (indice==0){
codigoInsertar += ' class="primero"';
}
if (indice==6){
codigoInsertar += ' class="domingo ultimo"';
}
codigoInsertar += ">" + valor + '</span>';
capaDiasSemana.append(codigoInsertar);
});
//capa con los días del mes
capaDiasMes = $('<div class="diasmes"></div>');
//un objeto de la clase date para calculo de fechas
var objFecha = new Date();
//miro si en el campo INPUT tengo alguna fecha escrita
var textoFechaEscrita = elem.val();
if (textoFechaEscrita!= ""){
if (validarFechaEscrita(textoFechaEscrita)){
var arrayFechaEscrita = textoFechaEscrita.split("/");
//hago comprobación sobre si el año tiene dos cifras
if(arrayFechaEscrita[2].length == 2){
if (arrayFechaEscrita[2].charAt(0)=="0"){
arrayFechaEscrita[2] = arrayFechaEscrita[2].substring(1);
}
arrayFechaEscrita[2] = parseInt(arrayFechaEscrita[2]);
if (arrayFechaEscrita[2] < 50)
arrayFechaEscrita[2] += 2000;
}
objFecha = new Date(arrayFechaEscrita[2], arrayFechaEscrita[1]-1, arrayFechaEscrita[0])
}
}
//mes y año actuales
var mes = objFecha.getMonth();
var ano = objFecha.getFullYear();
//muestro los días del mes y año dados
muestraDiasMes(mes, ano);
//control para ocultar el calendario
var botonCerrar = $('<a href="#" class="calencerrar"><span></span></a>');
botonCerrar.click(function(e){
e.preventDefault();
calendario.hide("slow");
})
var capaCerrar = $('<div class="capacerrar"></div>');
capaCerrar.append(botonCerrar)
//controles para ir al mes siguiente / anterior
var botonMesSiguiente = $('<a href="#" class="botonmessiguiente"><span></span></a>');
botonMesSiguiente.click(function(e){
e.preventDefault();
mes = (mes + 1) % 12;
if (mes==0)
ano++;
capaDiasMes.empty();
muestraDiasMes(mes, ano);
})
var botonMesAnterior = $('<a href="#" class="botonmesanterior"><span></span></a>');
botonMesAnterior.click(function(e){
e.preventDefault();
mes = (mes - 1);
if (mes==-1){
ano--;
mes = 11
}
capaDiasMes.empty();
muestraDiasMes(mes, ano);
})
var botonCambioAno = $('<a href="#" class="botoncambiaano"><span></span></a>')
botonCambioAno.click(function(e){
e.preventDefault();
var botonActivoSelAnos = $(this);
//creo una capa con una serie de años para elegir
var capaAnos = $('<div class="capaselanos"></div>');
//genero 10 años antes y 10 después
for (var i=ano-10; i<=ano+10; i++){
var codigoEnlace = '<a href="#"';
if (i==ano)
codigoEnlace += ' class="seleccionado"';
if (i==ano+10)
codigoEnlace += ' class="ultimo"';
codigoEnlace += '><span>' + i + '</span></a>';
var opcionAno = $(codigoEnlace);
opcionAno.click(function(e){
e.preventDefault();
ano = parseInt($(this).children().text());
capaDiasMes.empty();
muestraDiasMes(mes, ano);
capaAnos.slideUp();
capaAnos.detach();
})
capaAnos.append(opcionAno);
}
//coloco la capa en la página
$(document.body).append(capaAnos);
//posiciono la capa
capaAnos.css({
top: (botonActivoSelAnos.offset().top + 12) + "px",
left: (botonActivoSelAnos.offset().left - 25) + "px"
})
capaAnos.slideDown();
})
//capa para mostrar el texto del mes y ano actual
var capaTextoMesAno = $('<div class="textomesano"></div>');
var capaTextoMesAnoControl = $('<div class="mesyano"></div>')
capaTextoMesAno.append(botonMesSiguiente);
capaTextoMesAno.append(botonMesAnterior);
capaTextoMesAno.append(capaTextoMesAnoControl);
capaTextoMesAnoControl.append(capaTextoMesAnoActual);
capaTextoMesAnoControl.append(botonCambioAno);
//calendario y el borde
calendario = $('<div class="capacalendario"></div>');
var calendarioBorde = $('<div class="capacalendarioborde"></div>');
calendario.append(calendarioBorde);
calendarioBorde.append(capaCerrar);
calendarioBorde.append(capaTextoMesAno);
calendarioBorde.append(capaDiasSemana);
calendarioBorde.append(capaDiasMes);
//inserto el calendario en el documento
$(document.body).append(calendario);
//lo posiciono con respecto al boton
calendario.css({
top: boton.offset().top + "px",
left: (boton.offset().left + 20) + "px"
})
//muestro el calendario
calendario.show("slow");
}else{
//es que el calendario ya se estaba mostrando...
calendario.fadeOut("fast");
calendario.fadeIn("fast");
}
}
function muestraDiasMes(mes, ano){
//console.log("muestro (mes, ano): ", mes, " ", ano)
//muestro en la capaTextoMesAno el mes y ano que voy a dibujar
capaTextoMesAnoActual.text(nombresMes[mes] + " " + ano);
//muestro los días del mes
var contadorDias = 1;
//calculo la fecha del primer día de este mes
var primerDia = calculaNumeroDiaSemana(1, mes, ano);
//calculo el último día del mes
var ultimoDiaMes = ultimoDia(mes,ano);
//escribo la primera fila de la semana
for (var i=0; i<7; i++){
if (i < primerDia){
//si el dia de la semana i es menor que el numero del primer dia de la semana no pongo nada en la celda
var codigoDia = '<span class="diainvalido';
if (i == 0)
codigoDia += " primero";
codigoDia += '"></span>';
} else {
var codigoDia = '<span';
if (i == 0)
codigoDia += ' class="primero"';
if (i == 6)
codigoDia += ' class="ultimo domingo"';
codigoDia += '>' + contadorDias + '</span>';
contadorDias++;
}
var diaActual = $(codigoDia);
capaDiasMes.append(diaActual);
}
//recorro todos los demás días hasta el final del mes
var diaActualSemana = 1;
while (contadorDias <= ultimoDiaMes){
var codigoDia = '<span';
//si estamos a principio de la semana escribo la clase primero
if (diaActualSemana % 7 == 1)
codigoDia += ' class="primero"';
//si estamos al final de la semana es domingo y ultimo dia
if (diaActualSemana % 7 == 0)
codigoDia += ' class="domingo ultimo"';
codigoDia += '>' + contadorDias + '</span>';
contadorDias++;
diaActualSemana++;
var diaActual = $(codigoDia);
capaDiasMes.append(diaActual);
}
//compruebo que celdas me faltan por escribir vacias de la última semana del mes
diaActualSemana--;
if (diaActualSemana%7!=0){
//console.log("dia actual semana ", diaActualSemana, " -- %7=", diaActualSemana%7)
for (var i=(diaActualSemana%7)+1; i<=7; i++){
var codigoDia = '<span class="diainvalido';
if (i==7)
codigoDia += ' ultimo'
codigoDia += '"></span>';
var diaActual = $(codigoDia);
capaDiasMes.append(diaActual);
}
}
//crear el evento para cuando se pulsa un día de mes
//console.log(capaDiasMes.children());
capaDiasMes.children().click(function(e){
var numDiaPulsado = $(this).text();
if (numDiaPulsado != ""){
elem.val(numDiaPulsado + "/" + (mes+1) + "/" + ano);
calendario.fadeOut();
}
})
}
//función para calcular el número de un día de la semana
function calculaNumeroDiaSemana(dia,mes,ano){
var objFecha = new Date(ano, mes, dia);
var numDia = objFecha.getDay();
if (numDia == 0)
numDia = 6;
else
numDia--;
return numDia;
}
//función para ver si una fecha es correcta
function checkdate ( m, d, y ) {
// función por http://kevin.vanzonneveld.net
// extraida de las librerías phpjs.org manual en http://www.desarrolloweb.com/manuales/manual-librerias-phpjs.html
return m > 0 && m < 13 && y > 0 && y < 32768 && d > 0 && d <= (new Date(y, m, 0)).getDate();
}
//funcion que devuelve el último día de un mes y año dados
function ultimoDia(mes,ano){
var ultimo_dia=28;
while (checkdate(mes+1,ultimo_dia + 1,ano)){
ultimo_dia++;
}
return ultimo_dia;
}
function validarFechaEscrita(fecha){
var arrayFecha = fecha.split("/");
if (arrayFecha.length!=3)
return false;
return checkdate(arrayFecha[1], arrayFecha[0], arrayFecha[2]);
}
});
return this;
};
Si lo deseas, puedes ver este último ejemplo de calendario en una página aparte.
Recuerda que si deseas aprender a usar este calendario en tu proyecto debes seguir las explicaciones del artículo Pasos para implementar el plugin calendario jQuery.
Por nuestra parte y por el momento, nada más... esperamos que este desarrollo haya sido fácil de entender y sea fácil de utilizar por los interesados en utilizar un datepicker en sus proyectos. Sobre todo, esperamos que una persona con conocimientos de jQuery pueda modificarlo para adaptarlo a las necesidades propias de cada uno.
Finalizamos solicitando a los lectores que si modifican el calendario nos manden una copia para publicarlo en este manual. Gracias!
Miguel Angel Alvarez
Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...