Table of Contents

Η οικοδόμηση μιας προσαρμοσμένης εφαρμογής ημερολογίου είναι ένας εξαιρετικός τρόπος για να εμβαθύνετε την κατανόησή σας της JavaScript, του προγράμματος περιήγησης Μοντέλο αντικείμενο (DOM), και της εμμονής δεδομένων από την πλευρά του πελάτη. Με τη μόχλευση του API αποθήκευσης ιστού — συγκεκριμένα Τοπική Αποθήκευση — μπορείτε να δημιουργήσετε ένα πλήρως λειτουργικό, καθοδηγούμενο από γεγονότα ημερολόγιο που τρέχει εξ ολοκλήρου στο πρόγραμμα περιήγησης χωρίς να χρειάζεται έναν διακομιστή υποστήριξης ή βάση δεδομένων. Αυτό το φροντιστήριο σας περπατά μέσα από κάθε βήμα, από τη δομή του HTML μέχρι την υλοποίηση προηγμένων χαρακτηριστικών όπως drag-and-drop διαχείριση γεγονότων.

Γιατί να Χτίσετε ένα Προσαρμοσμένο Ημερολόγιο;

Προ-χτισμένες βιβλιοθήκες ημερολογίου (όπως το FullCalendar ή το DayPilot) προσφέρουν γρήγορες λύσεις, αλλά η κατασκευή μιας από το μηδέν σας δίνει τον πλήρη έλεγχο πάνω στο περιβάλλον εργασίας χρήστη, τον χειρισμό δεδομένων και την απόδοση. Κερδίζετε επίσης τα χέρια ⁇ για την εμπειρία με τον πυρήνα έννοιες JavaScript όπως το αντικείμενο ], την αντιπροσωπεία εκδήλωσης, και το API. Η εφαρμογή που προκύπτει μπορεί να επεκταθεί σε ένα εργαλείο διαχείρισης έργου, ένα σύστημα κρατήσεων, ή ένα προσωπικό περιοδικό.

⁇ της δομής HTML

Ξεκινήστε με έναν καθαρό σκελετό HTML. Το ημερολόγιο χρειάζεται τρία κύρια συστατικά: μια γραμμή πλοήγησης (για μεταβαλλόμενους μήνες), ένα δοχείο καννάβου (για τα κύτταρα ημέρας), και μια φόρμα εισόδου γεγονότων. Χρησιμοποιήστε [[LFT:2]] στοιχεία με σημασιολογικά ονόματα κλάσης για εύκολο στυλ και σενάριο.

<div id="calendar">
 <div class="calendar-header">
 <button id="prevBtn">&larr;</button>
 <h2 id="monthYear"></h2>
 <button id="nextBtn">&rarr;</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>

Το θα κατοικηθεί δυναμικά από το JavaScript. Για μια φορητή ⁇ φιλική διάταξη, εξετάστε τη χρήση ενός πλέγματος CSS 7 ⁇ στήλη (μία για κάθε ημέρα της εβδομάδας).

Τοποθέτηση του ημερολογίου με CSS

Καθαρίστε, ανταποκρινόμενοι CSS μετατρέπει την ακατέργαστη HTML σε μια χρήσιμη διεπαφή. Χρησιμοποιήστε ένα CSS Grid για το πλέγμα ημερολογίου, ρυθμίζοντας [[LPT:5]]. Προσθέστε τους διαστημικούς διαχωριστές για ημέρες πριν από την πρώτη του μήνα. Για την προσβασιμότητα, εξασφαλίστε επαρκή χρωματική αντίθεση και συμπεριλάβετε [[LFT:6]] στυλ σε διαδραστικά στοιχεία. Ένα ελάχιστο φύλλο στυλ εμφανίζεται παρακάτω (inline ή συνδεδεμένο).

.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;
}

Χρησιμοποιήστε τα ερωτήματα μέσων για να μειώσετε το μέγεθος των κυττάρων σε στενές οθόνες, και να εξετάσει το κείμενο κρυψώνων γεγονότων και να δείξει μόνο μια καταμέτρηση.

Κεντρικό JavaScript: Δημιουργία του καννάβου ημερολογίου

Η κεντρική λειτουργία υπολογίζει την πρώτη ημέρα του μήνα και τον συνολικό αριθμό ημερών. Χρησιμοποιήστε για να πάρετε το δείκτη της ημέρας (0 = Κυριακή).

Εργασία με το αντικείμενο ημερομηνίας

Για να πάρετε την τελευταία ημέρα του μήνα, χρησιμοποιήστε (η ημέρα 0 του επόμενου μήνα δίνει την τελευταία ημέρα του τρέχοντος μήνα). Αποθηκεύστε τον τρέχοντα μήνα και το έτος σε παγκόσμιες μεταβλητές ώστε η πλοήγηση να μπορεί να τις ενημερώσει.

Οικοδόμηση του Πλέγματος

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);
 }
}

Ενημέρωση της εμφάνισης μήνα/έτος στην επικεφαλίδα:

Πλοήγηση μεταξύ μηνών

Συνδέστε τους ακροατές των εκδηλώσεων με κλικ στα πλήκτρα Previous and Next. Increment or decrement , προσαρμόζοντας το έτος αν χρειαστεί (π.χ., μετά τον Δεκέμβριο έρχονται στον Ιανουάριο του επόμενου έτους).

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();
});

Για επιπλέον χρηστικότητα, προσθέστε ένα Σήμερα κουμπί που επαναφέρει την προβολή στον τρέχοντα μήνα και τονίζει την τρέχουσα ημέρα.

Αποθήκευση & Ανάκτηση γεγονότων με τοπική αποθήκευση

Η τοπική αποθήκευση παρέχει ένα απλό κατάστημα βασικής αξίας που επιβιώνει από την επανεκκίνηση του προγράμματος περιήγησης. Χρησιμοποιήστε ένα συνεπές βασικό μοτίβο, π.χ. , αποθηκεύοντας συστοιχίες αντικειμένων γεγονότων JSON. Περιλάβετε ιδιότητες όπως , , ] και .

Αποθήκευση ενός νέου γεγονότος

Όταν ο χρήστης κάνει κλικ στο κουμπί “Αποθήκευση”, να συλλάβει την τιμή εισόδου και την τρέχουσα επιλεγμένη ημερομηνία. (Μπορείτε να προσθέσετε έναν επιλογέα ημερομηνίας ή να ανιχνεύσετε ποιο κελί ημέρας είναι κλικ.) Ανακτήστε τυχόν υπάρχοντα γεγονότα για την ημερομηνία αυτή από την Τοπική Αποθήκευση, πατήστε το νέο γεγονός, στη συνέχεια αποθηκεύστε πίσω.

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
}

Φόρτωση γεγονότων σε κύτταρα ημέρας

Μέσα , για κάθε μη-άδειο κελί ημέρας, καλέστε μια λειτουργία που αμφισβητεί την τοπική αποθήκευση για το συγκεκριμένο κλειδί ημερομηνίας. Αν υπάρχουν γεγονότα, βρόχο μέσω αυτών και προσαρτήστε στοιχεία στο κελί.

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);
 });
}

Διαγραφή και επεξεργασία γεγονότων

Για να διαγράψετε, επισυνάψτε ένα γεγονός κλικ σε κάθε στοιχείο γεγονότος (ή χρησιμοποιήστε την αντιπροσωπεία γεγονότων). Ανακτήστε τη διάταξη για την ημερομηνία αυτή, φιλτράρετε το γεγονός με το [[LFT:26]]] και αποθηκεύστε την ενημερωμένη διάταξη πίσω στην Τοπική Αποθήκευση. Η επεξεργασία μπορεί να γίνει με διπλό κλικ στο γεγονός, προτροπή για νέο κείμενο και ενημέρωση της διάταξης.

Προηγμένα χαρακτηριστικά για την ενίσχυση της λειτουργικότητας

Μόλις το βασικό ημερολόγιο λειτουργεί, μπορείτε να προσθέσετε χαρακτηριστικά που βελτιώνουν σημαντικά την εμπειρία του χρήστη.

Χρώμα ⁇ Κωδικοποίηση Γεγονότα ανά τύπο

Επιτρέπει στους χρήστες να εκχωρούν κατηγορίες (π.χ. εργασία, προσωπική, υγεία). Αποθηκεύστε ένα πεδίο στην Τοπική Αποθήκευση. Σε CSS, ορίστε κατηγορίες όπως , και εφαρμόστε τις δυναμικά.

Σύρετε ⁇ και ⁇ Drop αναδιαμόρφωση

Χρησιμοποιήστε το HTML5 Drag and Drop API για να μετακινήσετε τα γεγονότα μεταξύ των κυττάρων ημέρας. Όταν ένα γεγονός πέφτει σε μια διαφορετική ημέρα, ενημερώστε το κλειδί ημερομηνίας στην τοπική αποθήκευση: αφαιρέστε το γεγονός από την αρχική σειρά ημερομηνίας και ωθήστε το στη σειρά της νέας ημερομηνίας.

Επανάληψη των γεγονότων (Εβδομάδα / Μηνιαία)

Προσθέστε μια επιλογή “Επαναλάβετε” κατά την αποθήκευση ενός γεγονότος. Στη λειτουργία φόρτωσης, υπολογίστε αν η τρέχουσα ημερομηνία ταιριάζει με τον κανόνα επανάληψης (π.χ. κάθε Δευτέρα) και εμφανίστε το γεγονός ανάλογα. Αποθήκευση κανόνων επανάληψης σε ένα ξεχωριστό πλήκτρο τοπικής αποθήκευσης για την αποφυγή επικάλυψης.

Προβολή εβδομάδας και μίνι ημερολόγιο

Εναλλαγή μεταξύ προβολών μήνα και εβδομάδας. Μια προβολή εβδομάδας δείχνει μόνο τις ημέρες της τρέχουσας εβδομάδας με πιο οριζόντιο χώρο. Ένα μικρό μήνα ⁇ view μίνι ημερολόγιο βοηθά τους χρήστες να πηδούν σε οποιαδήποτε ημερομηνία γρήγορα.

Κάνοντας το Ημερολόγιο Ανταποκρίνσιμο και Προσβάσιμο

Δοκιμάστε το ημερολόγιο σε διάφορα μεγέθη οθόνης. Χρησιμοποιήστε [[LFT:30]] ερωτήματα για να στοίβαξετε τα κύτταρα ημέρας κάθετα σε πολύ μικρές οθόνες ή για να μειώσετε το padding. Βεβαιωθείτε ότι όλα τα διαδραστικά στοιχεία είναι πληκτρολόγιο ⁇ προσιτά: επισυνάψτε [[LFT:31]] γεγονότα για Enter και Escape. Χρησιμοποιήστε [[LFT:32]] χαρακτηριστικά σε κουμπιά και ζωντανές περιοχές για τους αναγνώστες οθόνης για να ανακοινώσετε αλλαγές μήνα και προσθήκες γεγονότων.

Συμβουλές για την απόδοση και τη διαχείριση δεδομένων

  • Αντιστοιχισμένη Αποθήκευση Εγγράφει[: Αντί να διαβάζει/γράφει Τοπική Αποθήκευση για κάθε λειτουργία εκδήλωσης, αποθηκεύει τα γεγονότα ολόκληρου του μήνα σε ένα αντικείμενο JavaScript και το ξεπλύνετε αλλάζει περιοδικά.
  • Όριο μεγέθους γεγονότων: Διατήρηση αντικειμένων γεγονότος μικρών. Αποφύγετε την αποθήκευση μεγάλων συμβολοσειρών ή δυαδικών δεδομένων.
  • Fallback for Storage Limits: Η τοπική αποθήκευση συνήθως καλύπτεται από 5-10 MB. Προειδοποίηση των χρηστών όταν η αποθήκευση είναι σχεδόν πλήρης.
  • Χρήση ευρετηρίου DB για μεγάλα σύνολα δεδομένων: Αν το ημερολόγιό σας θα κρατήσει χιλιάδες γεγονότα, εξετάστε IndexedDB για καλύτερες επιδόσεις και δυνατότητες αναζήτησης.

Συμπέρασμα

Δημιουργώντας μια προσαρμοσμένη εφαρμογή ημερολογίου με JavaScript και τοπική αποθήκευση είναι ένα ανταμειφτικό έργο που ακονίζει τις δεξιότητες πρόσθιας-end σας. Μαθαίνετε να χειραγωγείτε το DOM, να εργάζεστε με ημερομηνίες, να διαχειρίζεστε κατάσταση χωρίς διακομιστή και να χειρίζεστε αλληλεπιδράσεις χρήστη. Η βάση κώδικα μπορεί να επεκταθεί με συγχρονισμό διακομιστή, cloud backup, ή ενσωμάτωση με εξωτερικά ημερολόγια μέσω του Google Calendar API[. Ξεκινήστε με το βασικό πλέγμα, προσθέστε επιμονή, και στη συνέχεια στρώμα σε χαρακτηριστικά όπως drag ⁇ and ⁇ drop και επαναλαμβανόμενα γεγονότα. Το αποτέλεσμα είναι ένα προσαρμοσμένο ημερολόγιο που συμπεριφέρεται ακριβώς όπως το χρειάζεστε.

Για περαιτέρω ανάγνωση, εξερευνήστε το Αποθήκευση τεκμηρίωσης API και το Drag and Drop API στο MDN. Ευτυχισμένη κωδικοποίηση!