Created
December 1, 2017 12:31
-
-
Save L2jLiga/7c08757044262c41facab52f3588b9c5 to your computer and use it in GitHub Desktop.
Simple calendar
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.calendar__wrapper { | |
display: flex; | |
flex-direction: row; | |
flex-wrap: wrap; | |
width: calc(45px * 7); | |
margin: 0 25px 25px; | |
} | |
.calendar__item { | |
color: rgba(0,0,0,.5); | |
display: inline-flex; | |
flex-basis: calc(100% / 7); | |
height: 45px; | |
justify-content: center; | |
align-items: center; | |
} | |
.calendar__header { | |
width: calc(45px * 7); | |
margin: 25px 25px 10px; | |
border-bottom: 1px solid; | |
display: flex; | |
flex-direction: row; | |
justify-content: space-between; | |
} | |
.calendar__button { | |
flex-basis: 15%; | |
text-align: left; | |
cursor: pointer; | |
background-color: rgba(126,126,126,.1); | |
} | |
.calendar__button-next { | |
text-align: right; | |
} | |
.calendar__month-label { | |
flex-basis: 40%; | |
text-align: center; | |
} | |
.calendar__item--actual { | |
color: black; | |
cursor: pointer; | |
} | |
.calendar__item--actual:not(.calendar__item--selected):hover { | |
background-color: rgba(15,72,23,.1); | |
} | |
.calendar__item--selected { | |
background-color: rgba(15,72,23,.3); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8" /> | |
<link rel="stylesheet" href="calendar.css" /> | |
<div class="calendar"> | |
<div class="calendar__header"> | |
<div class="calendar__button calendar__button--prev"></div> | |
<div class="calendar__month-label"></div> | |
<div class="calendar__button calendar__button--next"></div> | |
</div> | |
<div class="calendar__wrapper"></div> | |
</div> | |
<script src="calendar.js"></script> | |
<script> | |
const whenSelect = (year, month, day) => { | |
alert(`Выбрано: ${day}.${month + 1}.${year}`); | |
} | |
calendar(whenSelect); | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const calendar = (() => { | |
'use strict'; | |
const months = ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь']; | |
let initialDate = new Date(); | |
initialDate.setMonth(initialDate.getMonth() - 1); | |
initialDate.setHours(0, 0, 0, 0); | |
let prevMonthButton = document.querySelector('.calendar__button--prev'); | |
let monthLabel = document.querySelector('.calendar__month-label'); | |
let nextMonthButton = document.querySelector('.calendar__button--next'); | |
prevMonthButton.onclick = switchMonth.bind(this, true); | |
nextMonthButton.onclick = switchMonth.bind(this, false); | |
switchMonth(); | |
/** | |
* Switch month and generate new calendar grid | |
* @param {Boolean} isPrevButton - Is pressed previous month button | |
* @return {void} | |
*/ | |
function switchMonth(isPrevButton = false) { | |
let helperDate = new Date(initialDate); | |
if(isPrevButton) { | |
helperDate.setMonth(helperDate.getMonth() - 1); | |
nextMonthButton.innerHTML = months[helperDate.getMonth()]; | |
helperDate.setMonth(helperDate.getMonth() - 2); | |
prevMonthButton.innerHTML = months[helperDate.getMonth()]; | |
helperDate.setMonth(helperDate.getMonth() + 1); | |
monthLabel.innerHTML = months[helperDate.getMonth()]; | |
helperDate.setMonth(helperDate.getMonth() + 1); | |
} else { | |
helperDate.setMonth(helperDate.getMonth() - 1); | |
prevMonthButton.innerHTML = months[helperDate.getMonth()]; | |
helperDate.setMonth(helperDate.getMonth() + 2); | |
nextMonthButton.innerHTML = months[helperDate.getMonth()]; | |
helperDate.setMonth(helperDate.getMonth() - 1); | |
monthLabel.innerHTML = months[helperDate.getMonth()]; | |
helperDate.setMonth(helperDate.getMonth() + 1); | |
} | |
generateGrid(helperDate.getMonth(), helperDate.getFullYear()); | |
} | |
function generateGrid(month, year) { | |
initialDate = new Date(year, month, 1); | |
let helperDate = new Date(initialDate.getFullYear(), initialDate.getMonth() + 1, 0); | |
let calendar = document.querySelector('.calendar__wrapper'); | |
calendar.innerHTML = ''; | |
buildOffset(generateOffsetBefore(initialDate.getDay()), calendar, true); | |
buildActualDays(generateActualDays(), calendar); | |
buildOffset(generateOffsetAfter(helperDate.getDay()), calendar, false); | |
/** | |
* Helper method for create calendar item | |
* @return {Node} Created element | |
*/ | |
function createCalendarElement() { | |
let element = document.createElement('div'); | |
element.classList.add('calendar__item'); | |
return element; | |
} | |
/** | |
* Build offsets elements and append it into node | |
* @param {Array} offsetArray - Array with offset days | |
* @param {Node} node - Element which should contain this days | |
* @param {Boolean} isBeforeOffset - Is this offset before first day or not | |
* @return {void} | |
*/ | |
function buildOffset(offsetArray, node, isBeforeOffset = false) { | |
let helperDate = new Date(initialDate); | |
let offsetDaysCount = offsetArray.length; | |
if(isBeforeOffset) { | |
let helperDate = new Date(initialDate.getFullYear(), initialDate.getMonth(), 0); | |
helperDate.setDate(helperDate.getDate() - offsetDaysCount); | |
for(; offsetDaysCount > 0; offsetDaysCount--) { | |
let offsetElement = createCalendarElement(); | |
helperDate.setDate(helperDate.getDate() + 1); | |
offsetElement.innerHTML = helperDate.getDate(); | |
node.append(offsetElement); | |
} | |
return; | |
} | |
for(; offsetDaysCount > 0; offsetDaysCount--) { | |
let offsetElement = createCalendarElement(); | |
offsetElement.innerHTML = helperDate.getDate(); | |
helperDate.setDate(helperDate.getDate() + 1); | |
node.append(offsetElement); | |
} | |
} | |
/** | |
* Build actual days | |
* @return {void} | |
*/ | |
function buildActualDays(actualDays, node) { | |
actualDays.forEach(actualDay => { | |
let actualDayElement = createCalendarElement(); | |
actualDayElement.innerHTML = actualDay.index; | |
actualDayElement.classList.add('calendar__item--actual'); | |
actualDayElement.onclick = event => { | |
let lastSelected = findSelectedDay(actualDays); | |
if(lastSelected) { | |
lastSelected.select = false; | |
let lastSelectedDay = document.querySelectorAll('.calendar .calendar__item.calendar__item--actual')[lastSelected.index - 1]; | |
lastSelectedDay.classList.remove('calendar__item--selected'); | |
} | |
event.target.classList.add('calendar__item--selected'); | |
actualDay.select = true; | |
// TODO: This you can parse your function | |
whenSelect(year, month, actualDay.index); | |
} | |
node.append(actualDayElement); | |
}); | |
} | |
/** | |
* Helper method to find last selected day | |
* @param {Object[]} actualDays - Array which contains actual days | |
* @return {Object} Last selected day | |
*/ | |
function findSelectedDay(actualDays) { | |
return actualDays.filter(day => day.select)[0]; | |
} | |
/** | |
* Create array of objects with actual days, which included into month | |
* @return {Object[]} Array of included days into month | |
*/ | |
function generateActualDays() { | |
let helperDate = new Date(year, month, 0); | |
let daysInMonth = helperDate.getDate(); | |
let actualDays = new Array(daysInMonth); | |
for(; daysInMonth > 0; daysInMonth--) { | |
actualDays[daysInMonth] = { | |
index: daysInMonth, | |
select: false | |
} | |
} | |
return actualDays; | |
} | |
/** | |
* Create array with days which included in first week, | |
* but doesn't included in current month | |
* @param {Number} dayOfTheWeek - Day of the week from which month starts | |
* @return {Array} Days before first day | |
*/ | |
function generateOffsetBefore(dayOfTheWeek) { | |
let daysBefore = dayOfTheWeek - 1; | |
if(daysBefore === -1) daysBefore = 5; | |
let offsetArray = new Array(daysBefore); | |
for(; daysBefore >= 0; daysBefore--) { | |
offsetArray[daysBefore] = daysBefore; | |
} | |
return offsetArray; | |
} | |
/** | |
* Create array with days which included in last week, | |
* but doesn't included in current month | |
* @param {Number} dayOfTheWeek - Day of the week from which month end | |
* @return {Array} Days after last day | |
*/ | |
function generateOffsetAfter(dayOfTheWeek) { | |
let daysAfter = 7 - dayOfTheWeek; | |
let offsetArray = new Array(daysAfter); | |
for(; daysAfter >= 0; daysAfter--) { | |
offsetArray[daysAfter] = daysAfter; | |
} | |
return offsetArray; | |
} | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment