Minimalist calendar in Pure javascript. Nada de JQuery ni librerías externas. Y poco más que decir del uso que se le puede dar a este tipo de "widget"
<div class="wrapper">
<div id="calendario"></div>
</div>
.wrapper {display: flex;align-items: center;justify-content: center;
flex-direction: column;min-height: 100%;
}
button::-moz-focus-inner { border: 0;padding: 0;}
#calendario {margin: 20px 0;position: relative;overflow: hidden;
height: 310px;width: 350px;font-size: 14px;
box-shadow: 0px 1px 4px rgba(0,0,0,0.4);
}
table {border-collapse: collapse;table-layout: fixed;
width: 350px;box-shadow: 0px 1px 3px rgba(0,0,0,0.2);
background-color: #fff;position: absolute;top: 0;
left: 0;transform: translateX(0);
transition: all 0.3s ease;
}
table.activo {transform: translateX(0px)top;}
table.inactivo {transition: all 0.3s 0.01s ease;}
table.ir_derecha {transform: translateX(-299px);}
table.ir_izquierda {transform: translateX(300px);}
td,th {text-align: center;background-color: #fff;}
th {padding: 10px;}
tr:first-child th {font-size: 20px;
font-weight: bold;border-left: none;
border-top: none;
}
td:last-child, th:last-child {border-right: none;}
th {border-top: 1px solid rgba(0,0,0,0.1);
border-right: 1px solid rgba(0,0,0,0.1);
background-color: #9b59b6;color: #fff;
text-shadow: 0px -1px 0px rgba(0,0,0,0.2);
font-weight: normal;
}
th .any {font-size: 12px;font-weight: normal;
display: block;text-shadow: none;
color: rgba(0,0,0,0.4);
}
tr:nth-child(2) th {padding: 5px;}
td {padding: 0;border-bottom: 1px solid rgba(0,0,0,0.05);}
td>span {color: #555;padding: 10px;display: block;
border: 2px solid transparent;
transition: border 0.3s ease;
}
td:nth-child(even)>span {background-color: rgba(0,0,0,0.02);}
td:last-child>span,td:nth-child(6)>span {color: #9b59b6;}
td.hoy>span {font-weight: bold;background-color: #9b59b6;
color: #fff;border: 2px solid rgba(0,0,0,0.1);
}
td.out_bord > span {opacity: 0.2;}
td > span:hover {background: #a57cb6;color: #fff;}
.button_next, .button_prev {background: rgba(0,0,0,0.1);
color: #fff;font-family: inherit;border: none;
font-size: 18px;font-weight: bold;
text-shadow: inherit;padding: 2px 10px 5px 10px;
line-height: 1px;height: 30px;width: 30px;
vertical-align: middle;border-radius: 100%;
position: absolute;top: 15px;
}
.button_next { right: 10px; padding-left: 13px;}
.button_prev { left: 10px; padding-right: 13px;}
.button_next:hover,.button_prev:hover {background: rgba(0,0,0,0.2);
}
button:hover { cursor: pointer; }button:focus { outline: none; }
var meses = ['Enero','Febrero','Marzo','Abril','Mayo','Junio', 'Julio',
'Agosto','Septiembre','Octubre','Noviembre','Diciembre'];
var dias = ['Domingo','Lunes','Martes','Miercoles',
'Jueves','Viernes','Sábado'];
var dias_abr = ['Dom','Lun','Mar','Mie','Jue',
'Vie','Sab'];
Number.prototype.pad = function(num) {var str = '';
for(var i = 0; i < (num-this.toString().length); i++)
str += '0';
return str += this.toString();
}
function calendario(widget, data)
{var original = widget.getElementsByClassName('activo')[0];
if(typeof original === 'undefined')
{original = document.createElement('table');
original.setAttribute('data-actual',
data.getFullYear() + '/' +
data.getMonth().pad(2) + '/' +
data.getDate().pad(2))
widget.appendChild(original);
}
var diff = data - new Date(original.getAttribute('data-actual'));
diff = new Date(diff).getMonth();var e = document.createElement('table');
e.className = diff === 0 ? 'ir_derecha' : 'ir_izquierda';
e.innerHTML = '';widget.appendChild(e);
e.setAttribute('data-actual',
data.getFullYear() + '/' +
data.getMonth().pad(2) + '/' +
data.getDate().pad(2))
var fila = document.createElement('tr');
var titol = document.createElement('th');
titol.setAttribute('colspan', 7);
var boton_prev = document.createElement('button');
boton_prev.className = 'button_prev';
boton_prev.innerHTML = '◂';
var boton_next = document.createElement('button');
boton_next.className = 'button_next';
boton_next.innerHTML = '▸';
titol.appendChild(boton_prev);
titol.appendChild(document.createElement('span')).innerHTML =
meses[data.getMonth()] + '' + data.getFullYear() + '';
titol.appendChild(boton_next);
boton_prev.onclick = function() {
data.setMonth(data.getMonth() - 1);
calendario(widget, data);
};
boton_next.onclick = function() {
data.setMonth(data.getMonth() + 1);
calendario(widget, data);
};
fila.appendChild(titol);
e.appendChild(fila);
fila = document.createElement('tr');
for(var i = 1; i < 7; i++)
{
fila.innerHTML += '' + dias_abr[i] + ' ';
}
fila.innerHTML += '' + dias_abr[0] + ' ';
e.appendChild(fila);
var inici_mes = new Date(data.getFullYear(), data.getMonth(), -1).getDay();
var actual = new Date(data.getFullYear(),
data.getMonth(), -inici_mes);
for(var s = 0; s < 6; s++)
{
var fila = document.createElement('tr');
for(var d = 1; d < 8; d++)
{
var cela = document.createElement('td');
var span = document.createElement('span');
cela.appendChild(span);
span.innerHTML = actual.getDate();
if(actual.getMonth() !== data.getMonth())
cela.className = 'out_bord';
if(data.getDate() == actual.getDate() &&
data.getMonth() == actual.getMonth())
cela.className = 'hoy';
actual.setDate(actual.getDate()+1);
fila.appendChild(cela);
}
e.appendChild(fila);
}
setTimeout(function() {
e.className = 'activo';
original.className +=
diff === 0 ? ' ir_izquierda' : ' ir_derecha';
}, 20);
original.className = 'inactivo';
setTimeout(function() {
var inactivos = document.getElementsByClassName('inactivo');
for(var i = 0; i < inactivos.length; i++)
widget.removeChild(inactivos[i]);
}, 1000);
}
calendario(document.getElementById('calendario'), new Date());