Table of Contents
Bygge et egendefinert kalenderprogram er en utmerket måte å utdype din forståelse av JavaScript, nettleseren Document Object Model (DOM) og klient-side datautholdenhet. Ved å utnytte Web Storage API - spesielt lokal lagring - kan du opprette en fullt funksjonell, hendelsesdrevet kalender som kjører helt i nettleseren uten å trenge en backend server eller database. Denne opplæringen går gjennom hvert trinn, fra å strukturere HTML til å implementere avanserte funksjoner som dra-og-slepp hendelseshåndtering.
Hvorfor bygge en egendefinert kalender?
Forbygde kalenderbiblioteker (for eksempel FullCalendar eller DayPilot) tilbyr raske løsninger, men å bygge en fra grunnen gir deg fullstendig kontroll over brukergrensesnittet, datahåndtering og ytelse. Du får også hånd på erfaring med kjernen JavaScript-konsepter som objekt, hendelsesdelegasjon og API. Den resulterende appen kan utvides til et prosjektstyringsverktøy, et bookingsystem eller et personlig tidsskrift.
Sette opp HTML-strukturen
Start med et rent HTML skjelett. Kalenderen trenger tre hovedkomponenter: en navigasjonslinje (for skiftende måneder), en rutenettbeholder (for dagceller) og en hendelsesinnmatingsskjema. Bruk [[FLT: 2] elementer med semantiske klassenavn for enkel styling og skripting.
<div id="calendar">
<div class="calendar-header">
<button id="prevBtn">←</button>
<h2 id="monthYear"></h2>
<button id="nextBtn">→</button>
</div>
<div class="calendar-grid"></div>
<div class="event-form">
<input type="text" id="eventInput" placeholder="Add an event..." />
<button id="saveEvent">Save</button>
</div>
</div>
vil bli befolket dynamisk av JavaScript. For en mobil-vennlig layout, vurdere å bruke et 7-kolonne CSS-gitter (en for hver dag i uken). Reserver den første raden for dagnavn (Sun-Sat).
Styling av kalenderen med CSS
Rent, responsivt CSS forvandler den rå HTML til et brukbart grensesnitt. Bruk et CSS-nett for kalendernettet, innstilling [[FLT: 5]]. Legg til avstandsstykker i dager før den første måneden. For tilgjengelighet, sikre tilstrekkelig fargekontrast og inkludere [[FLT: 6]] stiler på interaktive elementer. Et minimalt stilark er vist nedenfor (innen linje eller lenket).
.calendar-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 2px;
}
.day-cell {
min-height: 80px;
border: 1px solid #ccc;
padding: 4px;
position: relative;
}
.day-cell.today {
background-color: #eef;
}
.event {
font-size: 0.8em;
background: #4caf50;
color: #fff;
padding: 2px 4px;
margin: 1px 0;
border-radius: 3px;
cursor: pointer;
}
Bruk mediespørsler for å redusere cellestørrelsen på smale skjermer, og vurder å skjule hendelsestekst og vise bare et antall.
Core JavaScript: Opprette kalenderruten
Alle dynamiske gjengivelser lever i JavaScript. Den sentrale funksjonen, , beregner den første dagen i måneden og det totale antall dager. Bruk til å få ukedagsindeksen (0 = søndag). Deretter genererer celler i en løkke fra 1 til den siste dagen i måneden.
Arbeid med datoobjektet
Objektet er ryggraden i kalenderlogikken. For å få den siste dagen i en måned, bruk (dag 0 i neste måned gir den siste dagen i den aktuelle måneden). Lagre den aktuelle måneden og året i globale variabler slik at navigasjonen kan oppdatere dem.
Bygge rutenettet
function renderCalendar() {
const grid = document.querySelector('.calendar-grid');
grid.innerHTML = '';
const firstDay = new Date(currentYear, currentMonth, 1).getDay();
const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate();
// Add empty cells for days before the 1st
for (let i = 0; i < firstDay; i++) {
const empty = document.createElement('div');
empty.className = 'day-cell empty';
grid.appendChild(empty);
}
// Generate day cells
for (let day = 1; day <= daysInMonth; day++) {
const cell = document.createElement('div');
cell.className = 'day-cell';
cell.dataset.date = `${currentYear}-${currentMonth + 1}-${day}`;
const dateSpan = document.createElement('span');
dateSpan.textContent = day;
cell.appendChild(dateSpan);
// Highlight today
const today = new Date();
if (currentYear === today.getFullYear() && currentMonth === today.getMonth() && day === today.getDate()) {
cell.classList.add('today');
}
// Load events for this date
loadEvents(cell);
grid.appendChild(cell);
}
}
Oppdater måned/år-visningen i overskriften:
Navigasjon mellom måneder
Legg til klikk på hendelseslyttere til de forrige og neste knappene. Bedrag eller nedbrytning , justere året om nødvendig (f.eks. etter desember kommer til januar neste år). Etter oppdatering av variablene, ring igjen.
document.getElementById('prevBtn').addEventListener('click', () => {
currentMonth--;
if (currentMonth < 0) {
currentMonth = 11;
currentYear--;
}
renderCalendar();
});
document.getElementById('nextBtn').addEventListener('click', () => {
currentMonth++;
if (currentMonth > 11) {
currentMonth = 0;
currentYear++;
}
renderCalendar();
});
For ekstra brukbarhet legger du til en I dag-knapp som tilbakestiller visningen til den aktuelle måneden og markerer dagens dag.
Lagring & Henter hendelser med lokal lagring
Local Storage gir en enkel nøkkelverdibutikk som overlever nettleseren starter på nytt. Bruk et konsistent nøkkelmønster, f.eks. , lagring av JSON-arrangementer av hendelsesobjekter. Inkluder egenskaper som , , og .
Spar en ny hendelse
Når brukeren klikker på \"Save\"-knappen, fange inngangsverdien og den valgte datoen. (Du kan legge til en datovelger eller oppdage hvilken dagcelle som klikkes.) Hent eksisterende hendelser for den datoen fra lokal lagring, trykk på den nye hendelsen, og lagre deretter tilbake.
function saveEvent(dateKey, eventText) {
const existing = JSON.parse(localStorage.getItem(dateKey)) || [];
existing.push({ id: Date.now(), text: eventText, time: new Date().toLocaleTimeString() });
localStorage.setItem(dateKey, JSON.stringify(existing));
renderCalendar(); // refresh to show new event
}
Laster inn hendelser i dagceller
Inne , for hver ikke-tom dagcelle, ringe en funksjon som spør Lokal lagring for den datonøkkelen. Hvis hendelser eksisterer, loop gjennom dem og legge til elementer til cellen.
function loadEvents(cell) {
const dateKey = cell.dataset.date;
const events = JSON.parse(localStorage.getItem(dateKey));
if (!events) return;
events.forEach(evt => {
const eventDiv = document.createElement('div');
eventDiv.className = 'event';
eventDiv.textContent = evt.text;
eventDiv.dataset.id = evt.id;
// Optional: add a delete button
cell.appendChild(eventDiv);
});
}
Slette og redigere hendelser
Hvis du vil slette, vedlegg en klikkhending til hvert hendelseselement (eller bruk hendelsesdelegasjon). Hent rekkefølgen for den datoen, filtrer ut hendelsen med , og lagre den oppdaterte tabellen tilbake til lokal lagring. Redigering kan gjøres ved å dobbeltklikke på hendelsen, spør om ny tekst og oppdatere tabellen.
Avanserte funksjoner for å forbedre funksjonaliteten
Når den grunnleggende kalenderen fungerer, kan du legge til funksjoner som forbedrer brukeropplevelsen betydelig.
Farge ⁇ Kode hendelser etter type
Tillat brukerne å tildele kategorier (f.eks. arbeid, personlig helse). Lagre et felt i lokal lagring. I CSS definerer klasser som , og påfør dem dynamisk.
Dra ⁇ og ⁇ Drop Rescheduling
Bruk HTML5 Dra og slepp API til å flytte hendelser mellom dagceller. Når en hendelse slippes på en annen dag, oppdatere datotasten i lokal lagring: fjern hendelsen fra den opprinnelige datotabellen og trykk den til den nye datoens rekkevidde.
Recitual Events (Vekke / Månedlig)
Legg til et \"gjentak\"-alternativ når du lagrer en hendelse. I innlastingsfunksjonen beregnes dersom den aktuelle datoen samsvarer med tilbakefallsregelen (f.eks. hver mandag) og viser hendelsen i samsvar med dette. Lagre gjentaingsreglene i en egen lokal lagringsnøkkel for å unngå duplisering.
Ukevisning og Mini kalender
Bytt mellom månedsvisning og ukevisning. En ukevisning viser bare dagens ukes dager med mer horisontalt rom. En liten måned ⁇ vis minikalender hjelper brukere å hoppe til hvilken som helst dato raskt.
Gjør kalenderansvar og tilgjengelig
Test kalenderen på ulike skjermstørrelser. Bruk [[FLT: 30] spørringer til stabel dagceller vertikalt på svært små skjermer eller for å redusere polstring. Sørg for at alle interaktive elementer er tastatur ⁇ tilgjengelig: vedlegg [[FLT: 31]] hendelser for Enter og Escape. Bruk [[FLT: 32] attributter på knapper og levende regioner for skjermlesere å kunngjøre månedsendringer og hendelsestillegg.
Tips til ytelse og datahåndtering
- Batched Storage Writes: I stedet for å lese/skrive lokal lagring for hver hendelsesoperasjon, cache hele månedens hendelser i et JavaScript-objekt og flush endringer regelmessig.
- Limit Event Size: Hold hendelsesobjektene små. Unngå å lagre store strenger eller binære data.
- Fallback for lagringsgrenser: Lokal lagring er vanligvis dekket ved 5-10 MB. Varsle brukerne når lagringen er nesten full.
- Bruk indeksertDB for store datasett: Hvis kalenderen din vil holde tusenvis av hendelser, bør du vurdere IndexedDB for bedre ytelse og spørringsevne.
Konklusjon
Opprette en egendefinert kalenderapp med JavaScript og lokal lagring er et givende prosjekt som skjerper dine front-end ferdigheter. Du lærer å manipulere DOM, arbeide med datoer, administrere tilstand uten en server, og håndtere brukerinteraksjoner. Kodebase kan forlenges med serversynkronisering, sky backup eller integrasjon med eksterne kalendere via Google kalender API. Start med det grunnleggende rutenettet, legg til utholdenhet og lag deretter på funksjoner som dra-og-dråpe og gjentakende hendelser. Resultatet er en skreddersydd kalender som oppfører seg nøyaktig hvordan du trenger det.
For videre lesing, utforsk Storage API-dokumentasjon og Dra og Drop API] på MDN. Glad koding!