
¿Alguna vez has visto un calendario en una página web y has pensado, ¿cómo diablos hicieron eso? Para algo así, puede ser natural buscar un complemento, o incluso un Calendario de Google incrustado, pero en realidad es mucho más sencillo hacer uno de lo que piensas y solo requiere la trifecta de HTML, CSS y JavaScript. ¡Hagamos uno juntos!
Configuré una demostración en CodeSandbox para que pueda ver lo que estamos buscando.
Ver demostración
Primero identifiquemos algunos requisitos para lo que debería hacer el calendario. Debería:
- Mostrar una cuadrícula de mes para un mes determinado
- Muestra las fechas de los meses anteriores y siguientes para que la cuadrícula esté siempre llena
- Indicar fecha actual
- Muestra el nombre del mes seleccionado actualmente
- Navegar al mes anterior y al mes siguiente
- Permita que el usuario vuelva al mes actual con un solo clic
Ah, y crearemos esto como una aplicación de una sola página que obtiene las fechas del calendario de Day.js, una biblioteca de utilidades superligera.
Vamos a evitar elegir un marco específico para facilitar las cosas. Para esta configuración, estoy usando Parcel para la administración de paquetes, por lo que puedo escribir en Babel, agrupar las cosas y administrar la única dependencia para el proyecto. Revisar la package.json
presente en CodeSandbox para obtener más detalles.
Paso 1: comience con el marcado y los estilos básicos
Comencemos creando una plantilla básica para nuestro calendario. Esto no tiene por qué ser nada sofisticado. Pero también conviene hacerlo sin recurrir a tablas.
Podemos delinear nuestro marcado como tres capas donde tenemos:
- Una sección para el encabezado del calendario. Esto mostrará el mes seleccionado actualmente y los elementos responsables de paginar entre meses.
- Una sección para el encabezado de la cuadrícula del calendario. Nuevamente, no estamos llegando a las tablas de formularios, pero esto sería como un encabezado de tabla que contiene una lista que contiene los días de la semana, comenzando con el lunes.
- La cuadrícula del calendario. Ya sabes, cada día del mes actual, representado como un cuadrado en la cuadrícula.
Escribamos esto en un archivo llamado index.js
. Esto puede ir dentro de un src
carpeta en la carpeta del proyecto. De hecho tendremos un index.html
archivo en la raíz del proyecto que importa nuestro trabajo, pero el marcado principal residirá en el archivo JavaScript.
<!-- index.js -->
document.getElementById("app").innerHTML = `
<!-- Parent container for the calendar month -->
<div class="calendar-month">
<!-- The calendar header -->
<section class="calendar-month-header">
<!-- Month name -->
<div
id="selected-month"
class="calendar-month-header-selected-month"
>
July 2020
</div>
<!-- Pagination -->
<div class="calendar-month-header-selectors">
<span id="previous-month-selector"><</span>
<span id="present-month-selector">Today</span>
<span id="next-month-selector">></span>
</div>
</section>
<!-- Calendar grid header -->
<ol
id="days-of-week"
class="day-of-week"
>
<li>Mon</li>
...
<li>Sun</li>
</ol>
<!-- Calendar grid -->
<ol
id="calendar-days"
class="date-grid"
>
<li class="calendar-day">
<span>
1
</span>
...
<span>
29
</span>
</li>
</ol>
</div>
`;
Sigamos e importemos este archivo en ese index.html
archivo que vive en el directorio raíz del proyecto. No pasa nada especial aquí. Es simplemente HTML repetitivo con un elemento que está dirigido por nuestra aplicación y registra nuestro index.js
Archivo.
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<div id="app"></div>
<script src="https://css-tricks.com/how-to-make-a-monthly-calendar-with-real-data/src/index.js"></script>
</body>
</html>
Ahora que tenemos algunas marcas con las que trabajar, modifiquémoslo un poco para que tengamos una buena imagen para empezar. Específicamente, vamos a:
- Posicionar los elementos usando flexbox
- Crea un marco de calendario usando la cuadrícula CSS
- Coloque las etiquetas dentro de las celdas
Primero, creemos un nuevo archivo styles.css en el mismo src
carpeta donde tenemos index.js
y suelte esto en:
body {
--grey-100: #e4e9f0;
--grey-200: #cfd7e3;
--grey-300: #b5c0cd;
--grey-800: #3e4e63;
--grid-gap: 1px;
--day-label-size: 20px;
}
.calendar-month {
position: relative;
/* Color of the day cell borders */
background-color: var(--grey-200);
border: solid 1px var(--grey-200);
}
/* Month indicator and selectors positioning */
.calendar-month-header {
display: flex;
justify-content: space-between;
background-color: #fff;
padding: 10px;
}
/* Month indicator */
.calendar-month-header-selected-month {
font-size: 24px;
font-weight: 600;
}
/* Month selectors positioning */
.calendar-month-header-selectors {
display: flex;
align-items: center;
justify-content: space-between;
width: 80px;
}
.calendar-month-header-selectors > * {
cursor: pointer;
}
/* | Mon | Tue | Wed | Thu | Fri | Sat | Sun | */
.day-of-week {
color: var(--grey-800);
font-size: 18px;
background-color: #fff;
padding-bottom: 5px;
padding-top: 10px;
}
.day-of-week,
.days-grid {
/* 7 equal columns for weekdays and days cells */
display: grid;
grid-template-columns: repeat(7, 1fr);
}
.day-of-week > * {
/* Position the weekday label within the cell */
text-align: right;
padding-right: 5px;
}
.days-grid {
height: 100%;
position: relative;
/* Show border between the days */
grid-column-gap: var(--grid-gap);
grid-row-gap: var(--grid-gap);
border-top: solid 1px var(--grey-200);
}
.calendar-day {
position: relative;
min-height: 100px;
font-size: 16px;
background-color: #fff;
color: var(--grey-800);
padding: 5px;
}
/* Position the day label within the day cell */
.calendar-day > span {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
right: 2px;
width: var(--day-label-size);
height: var(--day-label-size);
}
La parte clave que configura nuestra cuadrícula es esta:
.day-of-week,
.days-grid {
/* 7 equal columns for weekdays and days cells */
display: grid;
grid-template-columns: repeat(7, 1fr);
}
Tenga en cuenta que tanto el encabezado de la cuadrícula del calendario como la cuadrícula del calendario en sí utilizan la cuadrícula CSS para diseñar las cosas. Sabemos que siempre habrá siete días a la semana, por lo que nos permite utilizar el repeat()
función para crear siete columnas que son proporcionales entre sí. También estamos declarando un min-height
de 100 px en cada fecha del calendario para asegurarse de que las filas sean consistentes.
Necesitamos conectar estos estilos con el marcado, así que agreguemos esto al principio de nuestro index.js
Archivo:
import "./styles.css";
Este es un buen lugar para detenerse y ver lo que tenemos hasta ahora.
Ver demostración
Paso 2: configurar el calendario del mes actual
Como probablemente haya notado, la plantilla solo contiene datos estáticos en este momento. El mes está codificado como julio y los números de días también están codificados. Ahí es donde entra en juego Day.js. Proporciona todos los datos que necesitamos para colocar correctamente las fechas en los días correctos de la semana para un mes determinado utilizando datos de calendario reales. Nos permite obtener y configurar cualquier cosa, desde la fecha de inicio de un mes hasta todas las opciones de formato de fecha que necesitamos para mostrar los datos.
Lo haremos:
- Obtener el mes actual
- Calcule dónde deben colocarse los días (días laborables)
- Calcule los días para mostrar las fechas de los meses anteriores y siguientes
- Ponga todos los días juntos en una sola matriz
Primero, necesitamos importar Day.js y eliminar todo el HTML estático (mes, días de la semana y días seleccionados). Lo haremos agregando esto a nuestro index.js
archivo justo encima de donde importamos los estilos:
import dayjs from "dayjs";
También nos apoyaremos en un par de complementos de Day.js para obtener ayuda. WeekDay nos ayuda a establecer el primer día de la semana. Algunos prefieren el domingo como primer día de la semana. Otros prefieren el lunes. Diablos, en algunos casos, tiene sentido comenzar con el viernes. Empezaremos por el lunes.
El complemento weekOfYear devuelve el valor numérico de la semana actual de todas las semanas del año. Hay 52 semanas en un año, por lo que diríamos que la semana que comienza el 1 de enero es la primera semana del año, y así sucesivamente.
Así que aquí lo que ponemos index.js
justo después de nuestras declaraciones de importación:
const weekday = require("dayjs/plugin/weekday");
const weekOfYear = require("dayjs/plugin/weekOfYear");
dayjs.extend(weekday);
dayjs.extend(weekOfYear);
Una vez que eliminamos los valores del calendario endurecidos, esto es lo que tenemos en index.js
hasta aquí:
import dayjs from "dayjs";
import "./styles.css";
const weekday = require("dayjs/plugin/weekday");
const weekOfYear = require("dayjs/plugin/weekOfYear");
dayjs.extend(weekday);
dayjs.extend(weekOfYear);
document.getElementById("app").innerHTML = `
<div class="calendar-month">
<section class="calendar-month-header">
<div
id="selected-month"
class="calendar-month-header-selected-month"
>
</div>
<div class="calendar-month-header-selectors">
<span id="previous-month-selector"><</span>
<span id="present-month-selector">Today</span>
<span id="next-month-selector">></span>
</div>
</section>
<ul
id="days-of-week"
class="day-of-week"
>
</ul>
<ul
id="calendar-days"
class="days-grid"
>
</ul>
</div>
`;
Ahora establezcamos algunas constantes. Específicamente, queremos construir una matriz de días de las semanas (es decir, lunes, martes, miércoles, etc.):
const WEEKDAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
Luego, queremos recuperar el año actual y establecerlo en YYYY
formato:
const INITIAL_YEAR = dayjs().format("YYYY");
Y queremos establecer el mes actual como punto de partida al cargar inicialmente el calendario, donde M
formatea el mes como un valor numérico (por ejemplo, enero es igual a 1):
const INITIAL_MONTH = dayjs().format("M");
Vamos a rellenar el encabezado de la cuadrícula de nuestro calendario con los días de la semana. Primero tomamos el elemento adecuado (#days-of-week
), luego iteramos a través de nuestro WEEKDAYS
matriz, creando un elemento de elemento de lista para cada elemento en la matriz mientras configura el nombre para cada uno:
// Select the calendar grid header element
const daysOfWeekElement = document.getElementById("days-of-week");
// Loop through the array of weekdays
WEEKDAYS.forEach(weekday => {
// For each item in the array, make a list item element
const weekDayElement = document.createElement("li");
// Append a child element inside the list item...
daysOfWeekElement.appendChild(weekDayElement);
/// ...that contains the value in the array
weekDayElement.innerText = weekday;
});
Paso 3: creación de la cuadrícula del calendario
Eso fue bastante sencillo, pero ahora comienza la verdadera diversión, ya que ahora jugaremos con la cuadrícula del calendario. Detengámonos por un segundo a pensar en lo que realmente necesitamos hacer para hacerlo bien.
Primero, queremos que los números de fecha caigan en las columnas correctas de los días de la semana. Por ejemplo, el 1 de julio de 2020 es un miércoles. Ahí es donde debería comenzar la numeración de fechas.
Si el primer día del mes cae en miércoles, eso significa que tendremos elementos de cuadrícula vacíos para el lunes y martes de la primera semana. El último día del mes es el 31 de julio, que cae en viernes. Eso significa que el sábado y el domingo estarán vacíos en la última semana de la cuadrícula. Fuimos a llenar aquellos con las fechas iniciales y finales de los meses anterior y siguiente, respectivamente, para que la cuadrícula del calendario esté siempre llena.
Crear días para el mes actual
Para agregar los días del mes actual a la cuadrícula, necesitamos saber cuántos días existen en el mes actual. Podemos conseguir eso usando el daysInMonth
método proporcionado por Day.js. Creemos un método auxiliar para eso.
function getNumberOfDaysInMonth(year, month) {
return dayjs(`${year}-${month}-01`).daysInMonth()
}
Cuando sabemos eso, creamos una matriz vacía con una longitud que es igual al número de días del mes actual. Entonces nosotros map()
esa matriz y crea un objeto de día para cada uno. El objeto que creamos tiene una estructura arbitraria, por lo que puede agregar otras propiedades si las necesita.
En este ejemplo, sin embargo, necesitamos un date
propiedad que se utilizará para verificar si una fecha en particular es el día actual. También devolveremos un dayOfMonth
propiedad que actúa como etiqueta (por ejemplo, 1, 2, 3, etc.). isCurrentMonth
comprueba si la fecha está en el mes actual o fuera de él. Si está fuera del mes actual, los aplicaremos para que la gente sepa que están fuera del rango del mes actual.
function createDaysForCurrentMonth(year, month) {
return [...Array(getNumberOfDaysInMonth(year, month))].map((day, index) => {
return {
date: dayjs(`${year}-${month}-${index + 1}`).format("YYYY-MM-DD"),
dayOfMonth: index + 1,
isCurrentMonth: true
};
});
}
Agregar fechas del mes anterior a la cuadrícula del calendario
Para que las fechas del mes anterior se muestren en el mes actual, debemos verificar cuál es el día de la semana del primer día del mes seleccionado. Ahí es donde podemos usar el complemento WeekDay para Day.js. Creemos un método auxiliar para eso.
function getWeekday(date) {
return dayjs(date).weekday()
}
Luego, basándonos en eso, debemos verificar qué día fue el último lunes del mes anterior. Necesitamos ese valor para saber cuántos días del mes anterior deben estar visibles en la vista del mes actual. Podemos obtener eso restando el valor del día de la semana del primer día del mes actual. Por ejemplo, si el primer día del mes es miércoles, debemos restar 3 días para obtener el último lunes del mes anterior. Tener ese valor nos permite crear una matriz de objetos diarios desde el último lunes del mes anterior hasta el final de ese mes.
function createDaysForPreviousMonth(year, month) {
const firstDayOfTheMonthWeekday = getWeekday(currentMonthDays[0].date);
const previousMonth = dayjs(`${year}-${month}-01`).subtract(1, "month");
// Account for first day of the month on a Sunday (firstDayOfTheMonthWeekday === 0)
const visibleNumberOfDaysFromPreviousMonth = firstDayOfTheMonthWeekday ? firstDayOfTheMonthWeekday - 1 : 6
const previousMonthLastMondayDayOfMonth = dayjs(
currentMonthDays[0].date
).subtract(visibleNumberOfDaysFromPreviousMonth, "day").date();
return [...Array(visibleNumberOfDaysFromPreviousMonth)].map((day, index) => {
return {
date: dayjs(
`${previousMonth.year()}-${previousMonth.month() + 1}-${previousMonthLastMondayDayOfMonth + index}`
).format("YYYY-MM-DD"),
dayOfMonth: previousMonthLastMondayDayOfMonth + index,
isCurrentMonth: false
};
});
}
Agregue fechas del próximo mes a la cuadrícula del calendario
Ahora, hagamos lo contrario y calculemos qué días necesitamos del próximo mes para completar la cuadrícula del mes actual. Afortunadamente, podemos usar el mismo ayudante que acabamos de crear para el cálculo del mes anterior. La diferencia es que calcularemos cuántos días del próximo mes deben ser visibles restando el valor numérico del día de la semana de 7.
Entonces, por ejemplo, si el último día del mes es sábado, necesitamos restar 1 día de 7 para construir una matriz de fechas necesarias para el próximo mes (domingo).
function createDaysForNextMonth(year, month) {
const lastDayOfTheMonthWeekday = getWeekday(`${year}-${month}-${currentMonthDays.length}`)
const visibleNumberOfDaysFromNextMonth = lastDayOfTheMonthWeekday ? 7 - lastDayOfTheMonthWeekday : lastDayOfTheMonthWeekday
return [...Array(visibleNumberOfDaysFromNextMonth)].map((day, index) => {
return {
date: dayjs(`${year}-${Number(month) + 1}-${index + 1}`).format("YYYY-MM-DD"),
dayOfMonth: index + 1,
isCurrentMonth: false
}
})
}
Bien, sabemos cómo crear todos los días que necesitamos, usemos los métodos que acabamos de crear y luego combinemos todos los días en una única matriz de todos los días que queremos mostrar en el mes actual, incluidas las fechas de relleno de los meses anteriores y siguientes. .
let currentMonthDays = createDaysForCurrentMonth(INITIAL_YEAR, INITIAL_MONTH)
let previousMonthDays = createDaysForPreviousMonth(INITIAL_YEAR, INITIAL_MONTH, currentMonthDays[0])
let nextMonthDays = createDaysForNextMonth(INITIAL_YEAR, INITIAL_MONTH)
let days = [...this.previousMonthDays, ...this.currentMonthDays, ...this.nextMonthDays]
Aquí está todo lo que acabamos de cubrir reunido en index.js
:
// Same as before ...
const WEEKDAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
const INITIAL_YEAR = dayjs().format("YYYY");
const INITIAL_MONTH = dayjs().format("M");
const daysOfWeekElement = document.getElementById("days-of-week");
// Add weekdays to calendar header
WEEKDAYS.forEach(weekday => {
const weekDayElement = document.createElement("li");
daysOfWeekElement.appendChild(weekDayElement);
weekDayElement.innerText = weekday;
});
let currentMonthDays = createDaysForCurrentMonth(INITIAL_YEAR, INITIAL_MONTH);
let previousMonthDays = createDaysForPreviousMonth(INITIAL_YEAR, INITIAL_MONTH);
let nextMonthDays = createDaysForNextMonth(INITIAL_YEAR, INITIAL_MONTH);
let days = [...previousMonthDays, ...currentMonthDays, ...nextMonthDays];
console.log(days);
function getNumberOfDaysInMonth(year, month) {
return dayjs(`${year}-${month}-01`).daysInMonth();
}
function createDaysForCurrentMonth(year, month) {
return [...Array(getNumberOfDaysInMonth(year, month))].map((day, index) => {
return {
date: dayjs(`${year}-${month}-${index + 1}`).format("YYYY-MM-DD"),
dayOfMonth: index + 1,
isCurrentMonth: true
};
});
}
function createDaysForPreviousMonth(year, month) {
const firstDayOfTheMonthWeekday = getWeekday(currentMonthDays[0].date);
const previousMonth = dayjs(`${year}-${month}-01`).subtract(1, "month");
// Cover first day of the month being sunday (firstDayOfTheMonthWeekday === 0)
const visibleNumberOfDaysFromPreviousMonth = firstDayOfTheMonthWeekday
? firstDayOfTheMonthWeekday - 1
: 6;
const previousMonthLastMondayDayOfMonth = dayjs(currentMonthDays[0].date)
.subtract(visibleNumberOfDaysFromPreviousMonth, "day")
.date();
return [...Array(visibleNumberOfDaysFromPreviousMonth)].map((day, index) => {
return {
date: dayjs(
`${previousMonth.year()}-${previousMonth.month() +
1}-${previousMonthLastMondayDayOfMonth + index}`
).format("YYYY-MM-DD"),
dayOfMonth: previousMonthLastMondayDayOfMonth + index,
isCurrentMonth: false
};
});
}
function createDaysForNextMonth(year, month) {
const lastDayOfTheMonthWeekday = getWeekday(
`${year}-${month}-${currentMonthDays.length}`
);
const nextMonth = dayjs(`${year}-${month}-01`).add(1, "month");
const visibleNumberOfDaysFromNextMonth = lastDayOfTheMonthWeekday
? 7 - lastDayOfTheMonthWeekday
: lastDayOfTheMonthWeekday;
return [...Array(visibleNumberOfDaysFromNextMonth)].map((day, index) => {
return {
date: dayjs(
`${nextMonth.year()}-${nextMonth.month() + 1}-${index + 1}`
).format("YYYY-MM-DD"),
dayOfMonth: index + 1,
isCurrentMonth: false
};
});
}
function getWeekday(date) {
return dayjs(date).weekday();
}
Ver demostración
Paso 4: muestra las fechas del calendario
De acuerdo, tenemos el marcado básico para nuestro calendario, los datos que necesitamos para mostrar las fechas del mes actual, más las fechas del mes anterior y el siguiente para completar los elementos de la cuadrícula vacíos. ¡Ahora necesitamos agregar las fechas al calendario!
Ya tenemos un contenedor para la cuadrícula del calendario, #calendar-days
. Tomemos ese elemento.
const calendarDaysElement = document.getElementById("calendar-days");
Ahora, creemos una función que agregará un día a nuestra vista de calendario.
function appendDay(day, calendarDaysElement) {
const dayElement = document.createElement("li");
const dayElementClassList = dayElement.classList;
// Generic calendar day class
dayElementClassList.add("calendar-day");
// Container for day of month number
const dayOfMonthElement = document.createElement("span");
// Content
dayOfMonthElement.innerText = day.dayOfMonth;
// Add an extra class to differentiate current month days from prev/next month days
if (!day.isCurrentMonth) {
dayElementClassList.add("calendar-day--not-current");
}
// Append the element to the container element
dayElement.appendChild(dayOfMonthElement);
calendarDaysElement.appendChild(dayElement);
}
Tenga en cuenta que estamos lanzando un cheque para las fechas que provienen del mes anterior y el próximo para que podamos agregar una clase para diseñarlas de manera diferente a las fechas en el mes actual:
.calendar-day--not-current {
background-color: var(--grey-100);
color: var(--grey-300);
}
¡Eso es! Nuestro calendario ahora debería verse como queríamos.
Ver demostración
Paso 5: seleccione el mes actual
Lo que tenemos hasta ahora es bastante bueno, pero queremos que el usuario pueda paginar de mes a mes hacia adelante y hacia atrás en el tiempo, comenzando desde el mes actual. Tenemos la mayor parte de la lógica en su lugar, por lo que todo lo que realmente necesitamos hacer es agregar un click
oyente a los botones de paginación que vuelve a ejecutar el cálculo de días y vuelve a dibujar el calendario con datos actualizados.
Antes de comenzar, definamos variables para fechas que están en el mes actual, el mes anterior y el mes siguiente para que podamos hacer referencia a ellas a lo largo del código.
let currentMonthDays;
let previousMonthDays;
let nextMonthDays;
Ahora, creemos un método que será responsable de volver a calcular los días del calendario y volver a representar el calendario al paginar a otro mes. Llamaremos a esa función createCalendar
. Este método aceptará dos atributos, año y mes, y en base a eso, el calendario se volverá a representar con nuevos datos y sin que se cargue una nueva página.
El método reemplazará el contenido del encabezado para mostrar siempre la etiqueta del mes seleccionado.
function createCalendar(year = INITIAL_YEAR, month = INITIAL_MONTH) {
document.getElementById("selected-month").innerText = dayjs(
new Date(year, month - 1)
).format("MMMM YYYY");
// ...
Luego, tomará el contenedor de días calendario y eliminará todos los días existentes.
// ...
const calendarDaysElement = document.getElementById("calendar-days");
removeAllDayElements(calendarDaysElement);
// ...
Cuando se borra el calendario, calculará los nuevos días que deben mostrarse utilizando los métodos que creamos antes.
//...
currentMonthDays = createDaysForCurrentMonth(
year,
month,
dayjs(`${year}-${month}-01`).daysInMonth()
);
previousMonthDays = createDaysForPreviousMonth(year, month);
nextMonthDays = createDaysForNextMonth(year, month);
const days = [...previousMonthDays, ...currentMonthDays, ...nextMonthDays];
// ...
Y, finalmente, agregará un elemento de día para cada día.
// ...
days.forEach(day => {
appendDay(day, calendarDaysElement);
});
Todavía falta una pieza de lógica: una removeAllDayElements
método que borra el calendario existente. Este método toma el primer elemento del día calendario, lo elimina y lo reemplaza por otro. A partir de ahí, ejecutará la lógica en un bucle hasta que se eliminen todos los elementos.
function removeAllDayElements(calendarDaysElement) {
let first = calendarDaysElement.firstElementChild;
while (first) {
first.remove();
first = calendarDaysElement.firstElementChild;
}
}
Ahora podemos reutilizar esa lógica cuando queremos cambiar el mes. Recuerde el primer paso cuando creamos una plantilla estática para nuestro componente. Agregamos estos elementos:
<div class="calendar-month-header-selectors">
<span id="previous-month-selector"><</span>
<span id="present-month-selector">Today</span>
<span id="next-month-selector">></span>
</div>
Estos son los controles para paginar entre meses. Para cambiarlo, necesitamos almacenar el mes seleccionado actualmente. Creemos una variable para realizar un seguimiento de lo que es y establezcamos su valor inicial en el mes actual.
let selectedMonth = dayjs(new Date(INITIAL_YEAR, INITIAL_MONTH - 1, 1));
Ahora, para que los selectores funcionen, necesitamos un poco de JavaScript. Para hacerlo más legible, crearemos otro método llamado initMonthSelectors
y mantendremos la lógica ahí. Este método agregará detectores de eventos a los elementos del selector. Escuchará eventos de clic y actualizará el valor de selectedMonth
al nombre del mes recién seleccionado antes de ejecutar el createCalendar
método con los valores adecuados de año y mes.
function initMonthSelectors() {
document
.getElementById("previous-month-selector")
.addEventListener("click", function() {
selectedMonth = dayjs(selectedMonth).subtract(1, "month");
createCalendar(selectedMonth.format("YYYY"), selectedMonth.format("M"));
});
document
.getElementById("present-month-selector")
.addEventListener("click", function() {
selectedMonth = dayjs(new Date(INITIAL_YEAR, INITIAL_MONTH - 1, 1));
createCalendar(selectedMonth.format("YYYY"), selectedMonth.format("M"));
});
document
.getElementById("next-month-selector")
.addEventListener("click", function() {
selectedMonth = dayjs(selectedMonth).add(1, "month");
createCalendar(selectedMonth.format("YYYY"), selectedMonth.format("M"));
});
}
¡Eso es! Nuestro calendario está listo. Si bien eso es genial y todo, sería aún mejor si pudiéramos marcar la fecha actual para que se destaque del resto. Eso no debería ser muy difícil. Ya estamos diseñando días que no están en el mes seleccionado, así que hagamos algo similar a eso.
Crearemos una variable que está configurada para hoy:
const TODAY = dayjs().format("YYYY-MM-DD");
Entonces, en el appendDay
método donde aplicamos una clase para fechas fuera del mes actual, tenemos que agregar otra verificación para ver si el elemento es la fecha de hoy. Si es así, agregaremos una clase a ese elemento:
function appendDay(day, calendarDaysElement) {
// ...
if (day.date === TODAY) {
dayElementClassList.add("calendar-day--today");
}
}
¡Ahora podemos darle estilo!
.calendar-day--today {
padding-top: 4px;
}
.calendar-day--today > div {
color: #fff;
border-radius: 9999px;
background-color: var(--grey-800);
}
¡Voilà, ahí lo tenemos! Echa un vistazo a la demostración final para ver todo junto.
Ver demostración