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>
|
<title>Calendar</title>
|
||||||
|
|
||||||
<link href="style.css" rel="stylesheet">
|
<link href="./style.css" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="calendar">
|
<div id="calendar">
|
||||||
<div id="calendar__header">
|
<div id="calendar__header">
|
||||||
<div class="year">2025</div>
|
<div class="year" id="year">2024</div>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<button>-</button>
|
<button> <</button>
|
||||||
<button>Today</button>
|
<button>Today</button>
|
||||||
<button>+</button>
|
<button> ></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="month">September</div>
|
<div class="month" id="month">September</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="calendar__body">
|
<div id="calendar__body">
|
||||||
@@ -28,6 +28,23 @@
|
|||||||
</div>
|
</div>
|
||||||
</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>
|
</body>
|
||||||
</html>
|
</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;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
font-family: 'Poppins', sans-serif;
|
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 {
|
.container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100dvh;
|
height: calc(100vh - var(--footer-height));
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex: 0 1 auto;
|
flex: 0 1 auto;
|
||||||
|
border-radius: .4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar {
|
#calendar {
|
||||||
width: 900px;
|
width: 1080px;
|
||||||
height: 650px;
|
height: 910px;
|
||||||
background: floralwhite;
|
|
||||||
border: 1px solid black;
|
/* 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 {
|
#calendar__header {
|
||||||
background: aliceblue;
|
background: rgba(0, 0, 0, 0.3);
|
||||||
|
color: #fff;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
height: 3rem;
|
height: var(--calendar-header-height);
|
||||||
}
|
border-radius: .4rem .4rem 0 0;
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
|
||||||
#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:
|
|
||||||
". . . . . . ."
|
|
||||||
". . . . . . ."
|
|
||||||
". . . . . . ."
|
|
||||||
". . . . . . ."
|
|
||||||
". . . . . . ."
|
|
||||||
". . . . . . .";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendar__header * {
|
#calendar__header * {
|
||||||
@@ -53,6 +71,10 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendar__header .year {
|
#calendar__header .year {
|
||||||
@@ -67,7 +89,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: .5rem;
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#calendar__header .actions button {
|
#calendar__header .actions button {
|
||||||
@@ -75,15 +97,60 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
|
|
||||||
|
background: none;
|
||||||
|
color: white;
|
||||||
|
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||||
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.day {
|
/* ===== BODY ===== */
|
||||||
background: burlywood;
|
#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;
|
height: 2.5rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: 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