new design and added class function
This commit is contained in:
100
Calendar.js
Normal file
100
Calendar.js
Normal file
@@ -0,0 +1,100 @@
|
||||
import {getDaysInMonth, getFirstDayInMonth, getWeekdaysForLocale} from "./utils.js";
|
||||
|
||||
class Calendar {
|
||||
constructor(calendarDiv, options = {locale: 'en-GB', firstDayInWeek: 'Sunday'}) {
|
||||
this.calendarDiv = calendarDiv
|
||||
this.options = options
|
||||
this.date = new Date(Date.now())
|
||||
// this.date = new Date(2021, 5, 12)
|
||||
console.log(this.date)
|
||||
this.visiableDays = 42
|
||||
|
||||
this.locale = this.options.locale
|
||||
this.firstDayInWeek = this.options.firstDayInWeek
|
||||
|
||||
this.weekdays = getWeekdaysForLocale(this.locale, 'long', this.firstDayInWeek)
|
||||
this.randomImgUrl = 'https://picsum.photos/1920/1080'
|
||||
}
|
||||
|
||||
init() {
|
||||
const body = document.querySelector('body')
|
||||
if (body) {
|
||||
body.style.backgroundImage = 'url(' + this.randomImgUrl + ')'
|
||||
body.style.backgroundSize = 'cover'
|
||||
body.style.backgroundRepeat = 'no-repeat'
|
||||
body.style.backgroundPosition = 'center center'
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const calendarHeader = this.calendarDiv.querySelector('#calendar__header')
|
||||
if (calendarHeader) {
|
||||
const yearDiv = calendarHeader.querySelector('#year')
|
||||
const monthDiv = calendarHeader.querySelector('#month')
|
||||
|
||||
if (yearDiv) {
|
||||
yearDiv.innerText = Intl.DateTimeFormat(this.locale, {year: 'numeric'}).format(this.date)
|
||||
}
|
||||
|
||||
if (monthDiv) {
|
||||
monthDiv.innerText = Intl.DateTimeFormat(this.locale, {month: 'long'}).format(this.date)
|
||||
}
|
||||
}
|
||||
|
||||
const calendarBody = this.calendarDiv.querySelector('#calendar__body')
|
||||
if (calendarBody) {
|
||||
// Weekdays
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const weekday = document.createElement('div')
|
||||
weekday.classList.add('day', 'weekday')
|
||||
weekday.textContent = this.weekdays[i]
|
||||
calendarBody.appendChild(weekday)
|
||||
}
|
||||
|
||||
// Days
|
||||
const currentMonthDays = getDaysInMonth(this.date.getMonth(), this.date.getFullYear())
|
||||
const lastMonthDays = getDaysInMonth(this.date.getMonth() - 1, this.date.getFullYear())
|
||||
const nextMonthDays = getDaysInMonth(this.date.getMonth() + 1, this.date.getFullYear())
|
||||
const firstDayInMonth = getFirstDayInMonth(this.date.getMonth(), this.date.getFullYear())
|
||||
|
||||
let daysAtEndOfMonth = this.visiableDays - currentMonthDays - firstDayInMonth + 1
|
||||
let daysAtStartOfMonth = this.visiableDays - daysAtEndOfMonth - currentMonthDays
|
||||
if (daysAtStartOfMonth < 0) {
|
||||
daysAtStartOfMonth = daysAtStartOfMonth + 7
|
||||
daysAtEndOfMonth = daysAtEndOfMonth - 7
|
||||
}
|
||||
console.log(daysAtStartOfMonth, daysAtEndOfMonth)
|
||||
|
||||
for (let i = 0; i < this.visiableDays; i++) {
|
||||
const day = document.createElement('div')
|
||||
const dateSpan = document.createElement('span')
|
||||
dateSpan.id = 'date'
|
||||
day.classList.add('day', 'monthday')
|
||||
|
||||
let visibleDate = i - daysAtStartOfMonth + 1
|
||||
|
||||
// last month date
|
||||
if (i < daysAtStartOfMonth) {
|
||||
visibleDate = lastMonthDays + visibleDate
|
||||
day.classList.add('dim')
|
||||
}
|
||||
|
||||
// next month date
|
||||
if (this.visiableDays - i - 1 < daysAtEndOfMonth) {
|
||||
visibleDate = visibleDate - currentMonthDays
|
||||
day.classList.add('dim')
|
||||
}
|
||||
|
||||
dateSpan.innerText = visibleDate.toString()
|
||||
|
||||
const dayId = `${this.date.getFullYear()}${this.date.getMonth()}${this.date.getDay()}`
|
||||
day.classList.add('day-' + dayId)
|
||||
|
||||
day.appendChild(dateSpan)
|
||||
calendarBody.appendChild(day)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Calendar;
|
31
index.html
31
index.html
@@ -8,19 +8,19 @@
|
||||
|
||||
<title>Calendar</title>
|
||||
|
||||
<link href="style.css" rel="stylesheet">
|
||||
<link href="./style.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="calendar">
|
||||
<div id="calendar">
|
||||
<div id="calendar__header">
|
||||
<div class="year">2025</div>
|
||||
<div class="year" id="year">2024</div>
|
||||
<div class="actions">
|
||||
<button>-</button>
|
||||
<button> <</button>
|
||||
<button>Today</button>
|
||||
<button>+</button>
|
||||
<button> ></button>
|
||||
</div>
|
||||
<div class="month">September</div>
|
||||
<div class="month" id="month">September</div>
|
||||
</div>
|
||||
|
||||
<div id="calendar__body">
|
||||
@@ -28,6 +28,23 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="script.js"></script>
|
||||
<footer>
|
||||
<div>
|
||||
© 2025 VikingOwl
|
||||
</div>
|
||||
<div style="margin: 0 .5rem">—</div>
|
||||
<a href="https://somegit.dev/vikingowl/Calendar">Gitea</a>
|
||||
</footer>
|
||||
|
||||
<script type="module">
|
||||
import Calendar from "./Calendar.js";
|
||||
|
||||
const calendarDiv = document.querySelector("#calendar");
|
||||
if (calendarDiv) {
|
||||
const calendar = new Calendar(calendarDiv, {locale: 'de-DE', firstDayInWeek: 'Monday'})
|
||||
calendar.init()
|
||||
calendar.render()
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
63
script.js
63
script.js
@@ -1,63 +0,0 @@
|
||||
const WEEKDAYS = Object.freeze({
|
||||
MONDAY: 0,
|
||||
TUESDAY: 1,
|
||||
WEDNESDAY: 2,
|
||||
THURSDAY: 3,
|
||||
FRIDAY: 4,
|
||||
SATURDAY: 5,
|
||||
SUNDAY: 6
|
||||
});
|
||||
|
||||
const MONTHS = Object.freeze({
|
||||
JANUARY: 0,
|
||||
FEBRUARY: 1,
|
||||
MARCH: 2,
|
||||
APRIL: 3,
|
||||
MAY: 4,
|
||||
JUNE: 5,
|
||||
JULY: 6,
|
||||
AUGUST: 7,
|
||||
SEPTEMBER: 8,
|
||||
OCTOBER: 9,
|
||||
NOVEMBER: 10,
|
||||
DEZEMBER: 11
|
||||
})
|
||||
|
||||
function generateDays() {
|
||||
const visibleDays = 42 // 7 col, 5 row
|
||||
const calendarBody = document.getElementById('calendar__body')
|
||||
if (calendarBody) {
|
||||
for (let i = 0; i < visibleDays; i++) {
|
||||
const day = document.createElement('div')
|
||||
day.classList.add('day')
|
||||
if (i < Object.keys(WEEKDAYS).length) {
|
||||
day.classList.add('weekday')
|
||||
day.textContent = Object.keys(WEEKDAYS)[i]
|
||||
} else {
|
||||
const dayId = i % 7 + 1
|
||||
day.classList.add('day-' + dayId)
|
||||
}
|
||||
calendarBody.appendChild(day)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addCalendarDays() {
|
||||
const date = new Date()
|
||||
|
||||
console.log(date.getMonth())
|
||||
}
|
||||
|
||||
function setHeaderInfo(month, year) {
|
||||
const yearDOM = document.querySelector('#calendar__header .year')
|
||||
const monthDOM = document.querySelector('#calendar__header .month')
|
||||
|
||||
if (month) {
|
||||
month.textContent = month
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
generateDays()
|
||||
addCalendarDays()
|
||||
})
|
127
style.css
127
style.css
@@ -3,47 +3,65 @@
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'Poppins', sans-serif;
|
||||
|
||||
--footer-height: 3rem;
|
||||
--calendar-header-height: 4rem;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #000;
|
||||
}
|
||||
|
||||
footer {
|
||||
height: var(--footer-height);
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
color: #fff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: #76d714;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
footer a:hover {
|
||||
color: #609926;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 100dvh;
|
||||
height: calc(100vh - var(--footer-height));
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex: 0 1 auto;
|
||||
border-radius: .4rem;
|
||||
}
|
||||
|
||||
.calendar {
|
||||
width: 900px;
|
||||
height: 650px;
|
||||
background: floralwhite;
|
||||
border: 1px solid black;
|
||||
#calendar {
|
||||
width: 1080px;
|
||||
height: 910px;
|
||||
|
||||
/* From https://css.glass */
|
||||
background: rgba(62, 31, 31, 0.2);
|
||||
border-radius: .4rem;
|
||||
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(5px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
/* ===== HEADER ===== */
|
||||
#calendar__header {
|
||||
background: aliceblue;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
color: #fff;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: 3rem;
|
||||
}
|
||||
|
||||
#calendar__body {
|
||||
width: 100%;
|
||||
height: calc(100% - 3rem);
|
||||
padding: 0.5rem;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
|
||||
grid-template-rows: auto 1fr 1fr 1fr 1fr 1fr;
|
||||
gap: 0.5rem 0.5rem;
|
||||
grid-template-areas:
|
||||
". . . . . . ."
|
||||
". . . . . . ."
|
||||
". . . . . . ."
|
||||
". . . . . . ."
|
||||
". . . . . . ."
|
||||
". . . . . . .";
|
||||
height: var(--calendar-header-height);
|
||||
border-radius: .4rem .4rem 0 0;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
#calendar__header * {
|
||||
@@ -53,6 +71,10 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#calendar__header .year {
|
||||
@@ -67,7 +89,7 @@
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: .5rem;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
#calendar__header .actions button {
|
||||
@@ -75,15 +97,60 @@
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 1rem;
|
||||
|
||||
background: none;
|
||||
color: white;
|
||||
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.day {
|
||||
background: burlywood;
|
||||
/* ===== BODY ===== */
|
||||
#calendar__body {
|
||||
width: 100%;
|
||||
height: calc(100% - var(--calendar-header-height));
|
||||
padding: 1rem;
|
||||
border-radius: 10px;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
|
||||
grid-template-rows: auto 1fr 1fr 1fr 1fr 1fr 1fr;
|
||||
gap: 0.5rem 0.5rem;
|
||||
grid-template-areas:
|
||||
". . . . . . ."
|
||||
". . . . . . ."
|
||||
". . . . . . ."
|
||||
". . . . . . ."
|
||||
". . . . . . ."
|
||||
". . . . . . ."
|
||||
". . . . . . .";
|
||||
}
|
||||
|
||||
.weekday {
|
||||
#calendar__body .day {
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
border-radius: 0.2rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#calendar__body .dim {
|
||||
background: rgba(192, 192, 192, 0.7);
|
||||
}
|
||||
|
||||
#calendar__body .weekday {
|
||||
height: 2.5rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
user-select: none;
|
||||
cursor: initial;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
#calendar__body .monthday {
|
||||
display: flex;
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
#calendar__body .monthday #date {
|
||||
margin-top: .3rem;
|
||||
margin-left: .5rem;
|
||||
}
|
||||
|
34
utils.js
Normal file
34
utils.js
Normal file
@@ -0,0 +1,34 @@
|
||||
export function getWeekdaysForLocale(localeName = 'en-GB', weekday = 'long', firstDayInWeek = 'Sunday') {
|
||||
const {format} = new Intl.DateTimeFormat(localeName, {weekday})
|
||||
const year = firstDayInWeek === 'Sunday' ? 2023 : firstDayInWeek === 'Monday' ? 2022 : 2023
|
||||
const month = firstDayInWeek === 'Sunday' ? 4 : firstDayInWeek === 'Monday' ? 1 : 4
|
||||
|
||||
return [...Array(7).keys()]
|
||||
.map((day) => format(new Date(Date.UTC(year, month, day))))
|
||||
}
|
||||
|
||||
export function getFirstDayInMonth(month = 0, year = 2025) {
|
||||
if (month === -1) {
|
||||
month = 11
|
||||
year--
|
||||
}
|
||||
if (month === 12) {
|
||||
month = 0
|
||||
year++
|
||||
}
|
||||
return new Date(year, month, 1).getDay()
|
||||
}
|
||||
|
||||
export function getDaysInMonth(month = 0, year = 2025) {
|
||||
month++
|
||||
if (month === -1) {
|
||||
month = 11
|
||||
year--
|
||||
}
|
||||
if (month === 12) {
|
||||
month = 0
|
||||
year++
|
||||
}
|
||||
|
||||
return new Date(year, month, 0).getDate()
|
||||
}
|
Reference in New Issue
Block a user