From edebe5a2945a2f22437c323217f69d47143e9223 Mon Sep 17 00:00:00 2001 From: Raza Khan <110333158+raza-khan0108@users.noreply.github.com> Date: Wed, 28 Jan 2026 23:14:22 +0530 Subject: [PATCH 1/2] feat: add interactive calendar with event support --- examples/interactive-calendar/README.md | 66 +++++++++++ examples/interactive-calendar/index.html | 39 ++++++ examples/interactive-calendar/script.js | 121 +++++++++++++++++++ examples/interactive-calendar/style.css | 145 +++++++++++++++++++++++ 4 files changed, 371 insertions(+) create mode 100644 examples/interactive-calendar/README.md create mode 100644 examples/interactive-calendar/index.html create mode 100644 examples/interactive-calendar/script.js create mode 100644 examples/interactive-calendar/style.css diff --git a/examples/interactive-calendar/README.md b/examples/interactive-calendar/README.md new file mode 100644 index 00000000..08eb75a5 --- /dev/null +++ b/examples/interactive-calendar/README.md @@ -0,0 +1,66 @@ +# 📅 Interactive Calendar + +A lightweight, responsive calendar widget built with vanilla JavaScript. This project demonstrates DOM manipulation, Date object handling, and local state management without external libraries. + +## 🚀 Features + +- **Dynamic Rendering:** Automatically generates the correct grid for any month and year. +- **Navigation:** Browse through past and future months. +- **Current Date Highlighting:** visual indicator for today's date. +- **Event Management (Bonus):** Click any date to add, view, or delete notes. +- **Data Persistence:** Events are saved to the browser's `localStorage`, so they remain after refreshing the page. +- **Responsive Design:** Built with CSS Grid to adapt to different screen sizes. + +## 🛠️ Technologies Used + +- **HTML5:** Semantic structure. +- **CSS3:** Flexbox and Grid layout; CSS Variables for theming. +- **JavaScript (ES6+):** Logic for date calculation and event handling. + +## 📂 Project Structure + +```text +interactive-calendar/ +├── index.html # Main HTML structure +├── style.css # Styling and Grid layout +├── script.js # Calendar logic and Event handling +└── README.md # Project documentation + +##💡 How It Works +1. Date Calculation +The calendar grid is calculated using the native Date object: + +Start Day: new Date(year, month, 1).getDay() determines which day of the week the month starts on (0=Sunday, 1=Monday). + +Total Days: new Date(year, month + 1, 0).getDate() retrieves the exact number of days in the current month. + +2. Rendering the Grid +We use a loop to generate
elements. + +First, we insert empty placeholder divs to align the 1st of the month with the correct weekday column. + +Then, we generate the actual numbered days. + +3. State Management +Events are stored in a simple JSON object and saved to LocalStorage: + +JavaScript +// Data Structure Example +{ + "2023-10-25": "Meeting with team", + "2023-10-31": "Halloween Party" +} + +## 🏃‍♂️ How to Run +Clone the repository. + +Navigate to the interactive-calendar folder. + +Open index.html in your browser. + +# 🔮 Future Improvements +Add drag-and-drop functionality for events. + +Support for multiple events per day. + +Add specific time slots for events. \ No newline at end of file diff --git a/examples/interactive-calendar/index.html b/examples/interactive-calendar/index.html new file mode 100644 index 00000000..bbca4a72 --- /dev/null +++ b/examples/interactive-calendar/index.html @@ -0,0 +1,39 @@ + + + + + + Interactive Calendar + + + + +
+
+
+ < +

+ > +
+
+ +
+
Sun
Mon
Tue
Wed
Thu
Fri
Sat
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/examples/interactive-calendar/script.js b/examples/interactive-calendar/script.js new file mode 100644 index 00000000..ec4b04b2 --- /dev/null +++ b/examples/interactive-calendar/script.js @@ -0,0 +1,121 @@ +const monthYearElement = document.getElementById('month-year'); +const datesElement = document.getElementById('calendar-dates'); +const prevBtn = document.getElementById('month-prev'); +const nextBtn = document.getElementById('month-next'); + +// Modal Elements +const modal = document.getElementById('event-modal'); +const closeModalBtn = document.querySelector('.close-btn'); +const selectedDateTitle = document.getElementById('selected-date'); +const eventInput = document.getElementById('event-input'); +const saveEventBtn = document.getElementById('save-event-btn'); +const deleteEventBtn = document.getElementById('delete-event-btn'); + +let currentDate = new Date(); +let clickedDate = null; +let events = JSON.parse(localStorage.getItem('events')) || {}; + +const months = [ + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December" +]; + +// --- Core Functions --- + +function renderCalendar() { + const year = currentDate.getFullYear(); + const month = currentDate.getMonth(); + + monthYearElement.innerText = `${months[month]} ${year}`; + datesElement.innerHTML = ''; + + // First day of the month (0 = Sunday, 1 = Monday, etc.) + const firstDay = new Date(year, month, 1).getDay(); + // Total days in the current month + const totalDays = new Date(year, month + 1, 0).getDate(); + + // Add empty divs for days before the first day of the month + for (let i = 0; i < firstDay; i++) { + const emptyDiv = document.createElement('div'); + datesElement.appendChild(emptyDiv); + } + + // Render days + for (let day = 1; day <= totalDays; day++) { + const dayDiv = document.createElement('div'); + dayDiv.classList.add('day'); + dayDiv.innerText = day; + + // Check if this day is "Today" + const today = new Date(); + if (day === today.getDate() && month === today.getMonth() && year === today.getFullYear()) { + dayDiv.classList.add('current-date'); + } + + // Check for Events + const dateString = `${year}-${month + 1}-${day}`; + if (events[dateString]) { + dayDiv.classList.add('has-event'); + dayDiv.title = events[dateString]; // Tooltip + } + + // Add Click Event for Modal + dayDiv.addEventListener('click', () => openModal(dateString)); + + datesElement.appendChild(dayDiv); + } +} + +function openModal(dateStr) { + clickedDate = dateStr; + selectedDateTitle.innerText = `Event for: ${dateStr}`; + eventInput.value = events[dateStr] || ''; + modal.classList.remove('hidden'); +} + +function closeModal() { + modal.classList.add('hidden'); + clickedDate = null; +} + +// --- Event Listeners --- + +prevBtn.addEventListener('click', () => { + currentDate.setMonth(currentDate.getMonth() - 1); + renderCalendar(); +}); + +nextBtn.addEventListener('click', () => { + currentDate.setMonth(currentDate.getMonth() + 1); + renderCalendar(); +}); + +closeModalBtn.addEventListener('click', closeModal); + +saveEventBtn.addEventListener('click', () => { + if (eventInput.value.trim()) { + events[clickedDate] = eventInput.value; + localStorage.setItem('events', JSON.stringify(events)); + } + closeModal(); + renderCalendar(); +}); + +deleteEventBtn.addEventListener('click', () => { + if (events[clickedDate]) { + delete events[clickedDate]; + localStorage.setItem('events', JSON.stringify(events)); + } + closeModal(); + renderCalendar(); +}); + +// Close modal if clicking outside +window.addEventListener('click', (e) => { + if (e.target === modal) { + closeModal(); + } +}); + +// Initial Render +renderCalendar(); \ No newline at end of file diff --git a/examples/interactive-calendar/style.css b/examples/interactive-calendar/style.css new file mode 100644 index 00000000..f5559b09 --- /dev/null +++ b/examples/interactive-calendar/style.css @@ -0,0 +1,145 @@ +:root { + --primary-color: #4a90e2; + --bg-color: #f4f4f9; + --text-color: #333; + --highlight-color: #e0f7fa; +} + +body { + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + background-color: var(--bg-color); + display: flex; + justify-content: center; + align-items: center; + min-height: 100vh; + margin: 0; +} + +.calendar-container { + background: white; + width: 90%; + max-width: 400px; + border-radius: 10px; + box-shadow: 0 10px 25px rgba(0,0,0,0.1); + overflow: hidden; + padding: 20px; +} + +.calendar-header { + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 20px; +} + +.calendar-navigation { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; +} + +.nav-btn { + cursor: pointer; + font-size: 1.5rem; + -webkit-user-select: none; + user-select: none; + padding: 0 10px; +} + +.nav-btn:hover { + color: var(--primary-color); +} + +/* Grid System */ +.calendar-weekdays, .calendar-dates { + display: grid; + grid-template-columns: repeat(7, 1fr); + text-align: center; +} + +.calendar-weekdays div { + font-weight: bold; + color: #888; + margin-bottom: 10px; +} + +.day { + padding: 10px; + cursor: pointer; + border-radius: 5px; + transition: background 0.2s; + position: relative; +} + +.day:hover { + background-color: #f0f0f0; +} + +.day.current-date { + background-color: var(--primary-color); + color: white; + font-weight: bold; +} + +.day.has-event::after { + content: ''; + position: absolute; + bottom: 5px; + left: 50%; + transform: translateX(-50%); + width: 5px; + height: 5px; + background-color: red; + border-radius: 50%; +} + +.day.inactive { + color: #ccc; + pointer-events: none; +} + +/* Modal Styles */ +.modal { + position: fixed; + top: 0; left: 0; width: 100%; height: 100%; + background: rgba(0,0,0,0.5); + display: flex; + justify-content: center; + align-items: center; +} + +.hidden { display: none; } + +.modal-content { + background: white; + padding: 20px; + border-radius: 8px; + width: 300px; + position: relative; +} + +.close-btn { + position: absolute; + top: 10px; right: 15px; + cursor: pointer; + font-size: 1.2rem; +} + +textarea { + width: 100%; + height: 60px; + margin: 10px 0; + padding: 5px; +} + +button { + background: var(--primary-color); + color: white; + border: none; + padding: 8px 15px; + cursor: pointer; + border-radius: 4px; +} + +button.secondary { background: #ccc; } \ No newline at end of file From 8daabe08e5a7814cceeffddd4322630e1be444e7 Mon Sep 17 00:00:00 2001 From: Raza Khan <110333158+raza-khan0108@users.noreply.github.com> Date: Thu, 29 Jan 2026 23:11:07 +0530 Subject: [PATCH 2/2] fix: address code review feedback (accessibility, renaming, and logic fixes) --- examples/interactive-calendar/README.md | 76 ++++++++++++++------- examples/interactive-calendar/index.html | 11 ++- examples/interactive-calendar/script.js | 87 ++++++++++++++---------- examples/interactive-calendar/style.css | 2 + 4 files changed, 109 insertions(+), 67 deletions(-) diff --git a/examples/interactive-calendar/README.md b/examples/interactive-calendar/README.md index 08eb75a5..8bdaacf9 100644 --- a/examples/interactive-calendar/README.md +++ b/examples/interactive-calendar/README.md @@ -1,21 +1,28 @@ # 📅 Interactive Calendar -A lightweight, responsive calendar widget built with vanilla JavaScript. This project demonstrates DOM manipulation, Date object handling, and local state management without external libraries. +A lightweight, responsive calendar widget built with **vanilla JavaScript**. +This project demonstrates **DOM manipulation**, **Date object handling**, and **local state management** without external libraries. + +--- ## 🚀 Features - **Dynamic Rendering:** Automatically generates the correct grid for any month and year. - **Navigation:** Browse through past and future months. -- **Current Date Highlighting:** visual indicator for today's date. +- **Current Date Highlighting:** Visual indicator for today's date. - **Event Management (Bonus):** Click any date to add, view, or delete notes. - **Data Persistence:** Events are saved to the browser's `localStorage`, so they remain after refreshing the page. - **Responsive Design:** Built with CSS Grid to adapt to different screen sizes. +--- + ## 🛠️ Technologies Used -- **HTML5:** Semantic structure. -- **CSS3:** Flexbox and Grid layout; CSS Variables for theming. -- **JavaScript (ES6+):** Logic for date calculation and event handling. +- **HTML5:** Semantic structure +- **CSS3:** Flexbox and Grid layout, CSS Variables for theming +- **JavaScript (ES6+):** Date calculation and event handling logic + +--- ## 📂 Project Structure @@ -23,44 +30,61 @@ A lightweight, responsive calendar widget built with vanilla JavaScript. This pr interactive-calendar/ ├── index.html # Main HTML structure ├── style.css # Styling and Grid layout -├── script.js # Calendar logic and Event handling +├── script.js # Calendar logic and event handling └── README.md # Project documentation +``` + +--- + +## 💡 How It Works -##💡 How It Works -1. Date Calculation -The calendar grid is calculated using the native Date object: +### 1. Date Calculation -Start Day: new Date(year, month, 1).getDay() determines which day of the week the month starts on (0=Sunday, 1=Monday). +The calendar grid is calculated using the native `Date` object: -Total Days: new Date(year, month + 1, 0).getDate() retrieves the exact number of days in the current month. +- **Start Day:** + `new Date(year, month, 1).getDay()` + Determines which day of the week the month starts on + `(0 = Sunday, 1 = Monday, ...)` -2. Rendering the Grid -We use a loop to generate
elements. +- **Total Days:** + `new Date(year, month + 1, 0).getDate()` + Retrieves the exact number of days in the current month -First, we insert empty placeholder divs to align the 1st of the month with the correct weekday column. +--- -Then, we generate the actual numbered days. +### 2. Rendering the Grid -3. State Management -Events are stored in a simple JSON object and saved to LocalStorage: +- A loop generates `
` elements for the calendar. +- Empty placeholder divs are inserted to align the first day of the month correctly. +- Numbered day cells are then rendered dynamically. -JavaScript +--- + +### 3. State Management + +Events are stored in a simple JSON object and persisted using `localStorage`. + +```javascript // Data Structure Example { "2023-10-25": "Meeting with team", "2023-10-31": "Halloween Party" } +``` -## 🏃‍♂️ How to Run -Clone the repository. +--- -Navigate to the interactive-calendar folder. +## 🏃‍♂️ How to Run -Open index.html in your browser. +1. Clone the repository +2. Navigate to the `interactive-calendar` folder +3. Open `index.html` in your browser -# 🔮 Future Improvements -Add drag-and-drop functionality for events. +--- -Support for multiple events per day. +## 🔮 Future Improvements -Add specific time slots for events. \ No newline at end of file +- Add drag-and-drop functionality for events +- Support multiple events per day +- Add specific time slots for events diff --git a/examples/interactive-calendar/index.html b/examples/interactive-calendar/index.html index bbca4a72..4dfc408f 100644 --- a/examples/interactive-calendar/index.html +++ b/examples/interactive-calendar/index.html @@ -4,16 +4,15 @@ Interactive Calendar - - +
- < + <

- > + >
@@ -24,9 +23,9 @@

-