Skip to content

Instantly share code, notes, and snippets.

@ruanpetterson
Last active May 23, 2020 09:00
Show Gist options
  • Save ruanpetterson/6c36c4c04efdaac831425665e9e7ff17 to your computer and use it in GitHub Desktop.
Save ruanpetterson/6c36c4c04efdaac831425665e9e7ff17 to your computer and use it in GitHub Desktop.
Calendar Generator in Javascript
/**
* Calendar Generator
* @param {string} element - HTML element by ID
*/
var Calendar = function(element = '#calendar') {
let d = new Date()
this.year = d.getFullYear()
this.month = d.getMonth() + 1
this.element = element
this.generate()
}
Calendar.prototype.formatDate = function(date) {
/** Pad number with leading zeros (https://stackoverflow.com/a/10073788/2921788) */
const pad = (n, width, z) => {
z = z || '0'
n = n + ''
return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n
}
const Y = date.getFullYear()
const m = pad(date.getMonth() + 1, 2)
const d = pad(date.getDate(), 2)
return `${Y}-${m}-${d}`
}
Calendar.prototype.reset = function() {
let d = new Date()
this.year = d.getFullYear()
this.month = d.getMonth() + 1
this.generate()
}
Calendar.prototype.previousYear = function() {
this.year -= 1
this.generate()
}
Calendar.prototype.nextYear = function() {
this.year += 1
this.generate()
}
Calendar.prototype.previousMonth = function() {
if (this.month == 1) {
this.month = 12
this.year -= 1
} else {
this.month -= 1
}
this.generate()
}
Calendar.prototype.nextMonth = function() {
if (this.month == 12) {
this.month = 1
this.year += 1
} else {
this.month += 1
}
this.generate()
}
/**
* Set specific date
* @param {int} year - Year
* @param {int} month - Month
*/
Calendar.prototype.setDate = function(year, month) {
this.year = year
this.month = month
this.generate()
}
Calendar.prototype.generate = function() {
/** Creating structure */
const createStructure = () => {
const table = document.createElement('table')
const thead = document.createElement('thead')
const tbody = document.createElement('tbody')
for (let i = 0; i < 7; i++) {
thead.append(document.createElement('th'))
}
table.append(thead, tbody)
return table
}
const calendar = document.querySelector(this.element)
calendar.innerHTML = ''
calendar.append(createStructure())
const daysOfWeek = {
'en': ['sun', 'mon', 'tue', 'thu', 'wed', 'fri', 'sat'],
'pt': ['dom', 'seg', 'ter', 'qua', 'qui', 'sex', 'sáb']
}
const months = {
'en': ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'],
'pt': ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set', 'out', 'nov', 'dez']
}
daysOfWeek['en'].forEach((e, i) => calendar.querySelectorAll('th')[i].innerHTML = e)
/** Setting and generating rows */
const currentDay = new Date(this.year, this.month - 1, 1, 0, 0, 0, 0)
const lastDay = new Date(this.year, this.month, 0, 23, 59, 59, 999)
if (true) {
currentDay.setDate(currentDay.getDate() - (currentDay.getDay()))
lastDay.setDate(lastDay.getDate() + (6 - lastDay.getDay()))
}
const now = new Date()
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0)
const calendarBody = calendar.querySelector('tbody')
while (currentDay <= lastDay) {
const calendarRow = document.createElement('tr')
for (let i = 0; i < 7; i++) {
const calendarCell = document.createElement('td')
if (currentDay <= lastDay && i == currentDay.getDay()) {
const dataAttr = [
['data-date', this.formatDate(currentDay)],
['data-year', currentDay.getFullYear()],
['data-month', currentDay.getMonth() + 1],
['data-day-of-month', currentDay.getDate()],
['data-day-of-week', currentDay.getDay() + 1]
]
dataAttr.forEach(e => {
calendarCell.setAttribute(e[0], e[1])
})
if (currentDay.getDate() == 1) {
calendarCell.innerHTML = `<div><span>${months['en'][currentDay.getMonth()]} ${currentDay.getDate()}</span></div>`
} else {
calendarCell.innerHTML = `<div><span>${currentDay.getDate()}</span></div>`
}
if (currentDay.getTime() == today.getTime()) { calendarCell.classList.add('today') }
if (currentDay.getMonth() != this.month - 1) { calendarCell.classList.add('another-month') }
currentDay.setDate(currentDay.getDate() + 1)
}
calendarRow.append(calendarCell)
}
calendarBody.append(calendarRow)
}
}
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset="utf-8">
<title>Calendar</title>
<script src='calendar.js'></script>
<style>
body {
background-color: #eee;
font-family: 'Roboto', sans-serif;
font-size: 14px ;
margin: 0;
padding: 0;
}
h1 {
font-weight: 300;
text-align: center;
margin: 0;
padding-top: 32px;
}
.container {
background-color: #fff;
margin: 0 auto;
padding: 0 32px;
width: 768px;
min-height: 100vh;
}
#commands {
display: flex;
flex-direction: row;
padding: 16px 0;
height: 64px;
}
#commands > div {
flex: 1;
text-align: center;
padding: 24px 0;
}
#commands > div.date {
flex-grow: 10;
}
#commands > #previousYear, #commands > #nextYear,
#commands > #previousMonth, #commands > #nextMonth {
cursor: pointer;
}
#commands > #previousYear:hover, #commands > #nextYear:hover,
#commands > #previousMonth:hover, #commands > #nextMonth:hover {
background-color: #ddd;
}
#calendar {
height: 700px;
}
#calendar table {
border-collapse: collapse;
width: 100%;
}
#calendar table thead th {
font-size: 10px;
text-transform: uppercase;
padding-bottom: 6px;
}
#calendar table tbody tr > td {
font-size: 12px;
border: solid 1px #ddd;
height: 90px;
width: 90px;
padding: 5px;
vertical-align: top;
}
#calendar table tbody tr > td.another-month {
background-color: #f5f5f5;
color:#666;
font-size: 10px;
}
#calendar table tbody tr > td > div {
line-height: 24px;
top: 0;
left: 38px;
text-align: center;
text-transform: capitalize;
}
#calendar table tbody tr > td.today > div > span {
border-bottom: solid 2px #1a73e8;
}
</style>
</head>
<body>
<div class="container">
<h1>Example Calendar</h1>
<div id="commands">
<div href="#" id='previousYear'>&lt;&lt;</div>
<div href="#" id='previousMonth'>&lt;</div>
<div class="date"><span id="year"></span>/<span id="month"></span></div>
<div href="#" id='nextMonth'>&gt;</div>
<div href="#" id='nextYear'>&gt;&gt;</div>
</div>
<div id="calendar"></div>
</div>
<script>
window.addEventListener('load', () => {
const c = new Calendar()
const y = document.getElementById('year')
const m = document.getElementById('month')
const refreshDate = () => {
y.innerHTML = c.year
m.innerHTML = c.month
}
refreshDate()
document.getElementById('previousYear').addEventListener('click', e => {
e.preventDefault()
c.previousYear();
refreshDate()
})
document.getElementById('previousMonth').addEventListener('click', e => {
e.preventDefault()
c.previousMonth();
refreshDate()
})
document.getElementById('nextMonth').addEventListener('click', e => {
e.preventDefault()
c.nextMonth();
refreshDate()
})
document.getElementById('nextYear').addEventListener('click', e => {
e.preventDefault()
c.nextYear();
refreshDate()
})
})
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment