We have from the Internet the following calendar:

!function() { var today = moment(); function Calendar(selector, events) { this.el = document.querySelector(selector); this.events = events; this.current = moment().date(1); this.draw(); var current = document.querySelector('.today'); if(current) { var self = this; window.setTimeout(function() { self.openDay(current); }, 500); } } Calendar.prototype.draw = function() { //Create Header this.drawHeader(); //Draw Month this.drawMonth(); this.drawLegend(); } Calendar.prototype.drawHeader = function() { var self = this; if(!this.header) { //Create the header elements this.header = createElement('div', 'header'); this.header.className = 'header'; this.title = createElement('h1'); var right = createElement('div', 'right'); right.addEventListener('click', function() { self.nextMonth(); }); var left = createElement('div', 'left'); left.addEventListener('click', function() { self.prevMonth(); }); //Append the Elements this.header.appendChild(this.title); this.header.appendChild(right); this.header.appendChild(left); this.el.appendChild(this.header); } this.title.innerHTML = this.current.format('MMMM YYYY'); } Calendar.prototype.drawMonth = function() { var self = this; this.events.forEach(function(ev) { ev.date = self.current.clone().date(Math.random() * (29 - 1) + 1); }); if(this.month) { this.oldMonth = this.month; this.oldMonth.className = 'month out ' + (self.next ? 'next' : 'prev'); this.oldMonth.addEventListener('webkitAnimationEnd', function() { self.oldMonth.parentNode.removeChild(self.oldMonth); self.month = createElement('div', 'month'); self.backFill(); self.currentMonth(); self.fowardFill(); self.el.appendChild(self.month); window.setTimeout(function() { self.month.className = 'month in ' + (self.next ? 'next' : 'prev'); }, 16); }); } else { this.month = createElement('div', 'month'); this.el.appendChild(this.month); this.backFill(); this.currentMonth(); this.fowardFill(); this.month.className = 'month new'; } } Calendar.prototype.backFill = function() { var clone = this.current.clone(); var dayOfWeek = clone.day(); if(!dayOfWeek) { return; } clone.subtract('days', dayOfWeek+1); for(var i = dayOfWeek; i > 0 ; i--) { this.drawDay(clone.add('days', 1)); } } Calendar.prototype.fowardFill = function() { var clone = this.current.clone().add('months', 1).subtract('days', 1); var dayOfWeek = clone.day(); if(dayOfWeek === 6) { return; } for(var i = dayOfWeek; i < 6 ; i++) { this.drawDay(clone.add('days', 1)); } } Calendar.prototype.currentMonth = function() { var clone = this.current.clone(); while(clone.month() === this.current.month()) { this.drawDay(clone); clone.add('days', 1); } } Calendar.prototype.getWeek = function(day) { if(!this.week || day.day() === 0) { this.week = createElement('div', 'week'); this.month.appendChild(this.week); } } Calendar.prototype.drawDay = function(day) { var self = this; this.getWeek(day); //Outer Day var outer = createElement('div', this.getDayClass(day)); outer.addEventListener('click', function() { self.openDay(this); }); //Day Name var name = createElement('div', 'day-name', day.format('ddd')); //Day Number var number = createElement('div', 'day-number', day.format('DD')); //Events var events = createElement('div', 'day-events'); this.drawEvents(day, events); outer.appendChild(name); outer.appendChild(number); outer.appendChild(events); this.week.appendChild(outer); } Calendar.prototype.drawEvents = function(day, element) { if(day.month() === this.current.month()) { var todaysEvents = this.events.reduce(function(memo, ev) { if(ev.date.isSame(day, 'day')) { memo.push(ev); } return memo; }, []); todaysEvents.forEach(function(ev) { var evSpan = createElement('span', ev.color); element.appendChild(evSpan); }); } } Calendar.prototype.getDayClass = function(day) { classes = ['day']; if(day.month() !== this.current.month()) { classes.push('other'); } else if (today.isSame(day, 'day')) { classes.push('today'); } return classes.join(' '); } Calendar.prototype.openDay = function(el) { var details, arrow; var dayNumber = +el.querySelectorAll('.day-number')[0].innerText || +el.querySelectorAll('.day-number')[0].textContent; var day = this.current.clone().date(dayNumber); var currentOpened = document.querySelector('.details'); //Check to see if there is an open detais box on the current row if(currentOpened && currentOpened.parentNode === el.parentNode) { details = currentOpened; arrow = document.querySelector('.arrow'); } else { //Close the open events on differnt week row //currentOpened && currentOpened.parentNode.removeChild(currentOpened); if(currentOpened) { currentOpened.addEventListener('webkitAnimationEnd', function() { currentOpened.parentNode.removeChild(currentOpened); }); currentOpened.addEventListener('oanimationend', function() { currentOpened.parentNode.removeChild(currentOpened); }); currentOpened.addEventListener('msAnimationEnd', function() { currentOpened.parentNode.removeChild(currentOpened); }); currentOpened.addEventListener('animationend', function() { currentOpened.parentNode.removeChild(currentOpened); }); currentOpened.className = 'details out'; } //Create the Details Container details = createElement('div', 'details in'); //Create the arrow var arrow = createElement('div', 'arrow'); //Create the event wrapper details.appendChild(arrow); el.parentNode.appendChild(details); } var todaysEvents = this.events.reduce(function(memo, ev) { if(ev.date.isSame(day, 'day')) { memo.push(ev); } return memo; }, []); this.renderEvents(todaysEvents, details); arrow.style.left = el.offsetLeft - el.parentNode.offsetLeft + 27 + 'px'; } Calendar.prototype.renderEvents = function(events, ele) { //Remove any events in the current details element var currentWrapper = ele.querySelector('.events'); var wrapper = createElement('div', 'events in' + (currentWrapper ? ' new' : '')); events.forEach(function(ev) { var div = createElement('div', 'event'); var square = createElement('div', 'event-category ' + ev.color); var span = createElement('span', '', ev.eventName); div.appendChild(square); div.appendChild(span); wrapper.appendChild(div); }); if(!events.length) { var div = createElement('div', 'event empty'); var span = createElement('span', '', 'No Events'); div.appendChild(span); wrapper.appendChild(div); } if(currentWrapper) { currentWrapper.className = 'events out'; currentWrapper.addEventListener('webkitAnimationEnd', function() { currentWrapper.parentNode.removeChild(currentWrapper); ele.appendChild(wrapper); }); currentWrapper.addEventListener('oanimationend', function() { currentWrapper.parentNode.removeChild(currentWrapper); ele.appendChild(wrapper); }); currentWrapper.addEventListener('msAnimationEnd', function() { currentWrapper.parentNode.removeChild(currentWrapper); ele.appendChild(wrapper); }); currentWrapper.addEventListener('animationend', function() { currentWrapper.parentNode.removeChild(currentWrapper); ele.appendChild(wrapper); }); } else { ele.appendChild(wrapper); } } Calendar.prototype.drawLegend = function() { var legend = createElement('div', 'legend'); var calendars = this.events.map(function(e) { return e.calendar + '|' + e.color; }).reduce(function(memo, e) { if(memo.indexOf(e) === -1) { memo.push(e); } return memo; }, []).forEach(function(e) { var parts = e.split('|'); var entry = createElement('span', 'entry ' + parts[1], parts[0]); legend.appendChild(entry); }); this.el.appendChild(legend); } Calendar.prototype.nextMonth = function() { this.current.add('months', 1); this.next = true; this.draw(); } Calendar.prototype.prevMonth = function() { this.current.subtract('months', 1); this.next = false; this.draw(); } window.Calendar = Calendar; function createElement(tagName, className, innerText) { var ele = document.createElement(tagName); if(className) { ele.className = className; } if(innerText) { ele.innderText = ele.textContent = innerText; } return ele; } }(); !function() { var data = [ { eventName: 'Lunch Meeting w/ Mark', calendar: 'Work', color: 'orange' }, { eventName: 'Interview - Jr. Web Developer', calendar: 'Work', color: 'orange' }, { eventName: 'Demo New App to the Board', calendar: 'Work', color: 'orange' }, { eventName: 'Dinner w/ Marketing', calendar: 'Work', color: 'orange' }, { eventName: 'Game vs Portalnd', calendar: 'Sports', color: 'blue' }, { eventName: 'Game vs Houston', calendar: 'Sports', color: 'blue' }, { eventName: 'Game vs Denver', calendar: 'Sports', color: 'blue' }, { eventName: 'Game vs San Degio', calendar: 'Sports', color: 'blue' }, { eventName: 'School Play', calendar: 'Kids', color: 'yellow' }, { eventName: 'Parent/Teacher Conference', calendar: 'Kids', color: 'yellow' }, { eventName: 'Pick up from Soccer Practice', calendar: 'Kids', color: 'yellow' }, { eventName: 'Ice Cream Night', calendar: 'Kids', color: 'yellow' }, { eventName: 'Free Tamale Night', calendar: 'Other', color: 'green' }, { eventName: 'Bowling Team', calendar: 'Other', color: 'green' }, { eventName: 'Teach Kids to Code', calendar: 'Other', color: 'green' }, { eventName: 'Startup Weekend', calendar: 'Other', color: 'green' } ]; function addDate(ev) { } var calendar = new Calendar('#calendar', data); }(); 
 *, *:before, *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } body { overflow-x: hidden; font-family: 'HelveticaNeue-UltraLight', 'Helvetica Neue UltraLight', 'Helvetica Neue', Arial, Helvetica, sans-serif; font-weight: 100; color: rgba(255, 255, 255, 1); margin: 0; padding: 0; background: #4A4A4A; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } #calendar { -webkit-transform: translate3d(0, 0, 0); -moz-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); width: 420px; margin: 0 auto; height: 570px; overflow: hidden; } .header { height: 50px; width: 420px; background: rgba(66, 66, 66, 1); text-align: center; position:relative; z-index: 100; } .header h1 { margin: 0; padding: 0; font-size: 20px; line-height: 50px; font-weight: 100; letter-spacing: 1px; } .left, .right { position: absolute; width: 0px; height: 0px; border-style: solid; top: 50%; margin-top: -7.5px; cursor: pointer; } .left { border-width: 7.5px 10px 7.5px 0; border-color: transparent rgba(160, 159, 160, 1) transparent transparent; left: 20px; } .right { border-width: 7.5px 0 7.5px 10px; border-color: transparent transparent transparent rgba(160, 159, 160, 1); right: 20px; } .month { /*overflow: hidden;*/ opacity: 0; } .month.new { -webkit-animation: fadeIn 1s ease-out; opacity: 1; } .month.in.next { -webkit-animation: moveFromTopFadeMonth .4s ease-out; -moz-animation: moveFromTopFadeMonth .4s ease-out; animation: moveFromTopFadeMonth .4s ease-out; opacity: 1; } .month.out.next { -webkit-animation: moveToTopFadeMonth .4s ease-in; -moz-animation: moveToTopFadeMonth .4s ease-in; animation: moveToTopFadeMonth .4s ease-in; opacity: 1; } .month.in.prev { -webkit-animation: moveFromBottomFadeMonth .4s ease-out; -moz-animation: moveFromBottomFadeMonth .4s ease-out; animation: moveFromBottomFadeMonth .4s ease-out; opacity: 1; } .month.out.prev { -webkit-animation: moveToBottomFadeMonth .4s ease-in; -moz-animation: moveToBottomFadeMonth .4s ease-in; animation: moveToBottomFadeMonth .4s ease-in; opacity: 1; } .week { background: #4A4A4A; } .day { display: inline-block; width: 60px; padding: 10px; text-align: center; vertical-align: top; cursor: pointer; background: #4A4A4A; position: relative; z-index: 100; } .day.other { color: rgba(255, 255, 255, .3); } .day.today { color: rgba(156, 202, 235, 1); } .day-name { font-size: 9px; text-transform: uppercase; margin-bottom: 5px; color: rgba(255, 255, 255, .5); letter-spacing: .7px; } .day-number { font-size: 24px; letter-spacing: 1.5px; } .day .day-events { list-style: none; margin-top: 3px; text-align: center; height: 12px; line-height: 6px; overflow: hidden; } .day .day-events span { vertical-align: top; display: inline-block; padding: 0; margin: 0; width: 5px; height: 5px; line-height: 5px; margin: 0 1px; } .blue { background: rgba(156, 202, 235, 1); } .orange { background: rgba(247, 167, 0, 1); } .green { background: rgba(153, 198, 109, 1); } .yellow { background: rgba(249, 233, 0, 1); } .details { position: relative; width: 420px; height: 75px; background: rgba(164, 164, 164, 1); margin-top: 5px; border-radius: 4px; } .details.in { -webkit-animation: moveFromTopFade .5s ease both; -moz-animation: moveFromTopFade .5s ease both; animation: moveFromTopFade .5s ease both; } .details.out { -webkit-animation: moveToTopFade .5s ease both; -moz-animation: moveToTopFade .5s ease both; animation: moveToTopFade .5s ease both; } .arrow { position: absolute; top: -5px; left: 50%; margin-left: -2px; width: 0px; height: 0px; border-style: solid; border-width: 0 5px 5px 5px; border-color: transparent transparent rgba(164, 164, 164, 1) transparent; transition: all 0.7s ease; } .events { height: 75px; padding: 7px 0; overflow-y: auto; overflow-x: hidden; } .events.in { -webkit-animation: fadeIn .3s ease both; -moz-animation: fadeIn .3s ease both; animation: fadeIn .3s ease both; } .events.in { -webkit-animation-delay: .3s; -moz-animation-delay: .3s; animation-delay: .3s; } .details.out .events { -webkit-animation: fadeOutShrink .4s ease both; -moz-animation: fadeOutShink .4s ease both; animation: fadeOutShink .4s ease both; } .events.out { -webkit-animation: fadeOut .3s ease both; -moz-animation: fadeOut .3s ease both; animation: fadeOut .3s ease both; } .event { font-size: 16px; line-height: 22px; letter-spacing: .5px; padding: 2px 16px; vertical-align: top; } .event.empty { color: #eee; } .event-category { height: 10px; width: 10px; display: inline-block; margin: 6px 0 0; vertical-align: top; } .event span { display: inline-block; padding: 0 0 0 7px; } .legend { position: absolute; bottom: 0; width: 100%; height: 30px; background: rgba(60, 60, 60, 1); line-height: 30px; } .entry { position: relative; padding: 0 0 0 25px; font-size: 13px; display: inline-block; line-height: 30px; background: transparent; } .entry:after { position: absolute; content: ''; height: 5px; width: 5px; top: 12px; left: 14px; } .entry.blue:after { background: rgba(156, 202, 235, 1); } .entry.orange:after { background: rgba(247, 167, 0, 1); } .entry.green:after { background: rgba(153, 198, 109, 1); } .entry.yellow:after { background: rgba(249, 233, 0, 1); } /* Animations are cool! */ @-webkit-keyframes moveFromTopFade { from { opacity: .3; height:0px; margin-top:0px; -webkit-transform: translateY(-100%); } } @-moz-keyframes moveFromTopFade { from { height:0px; margin-top:0px; -moz-transform: translateY(-100%); } } @keyframes moveFromTopFade { from { height:0px; margin-top:0px; transform: translateY(-100%); } } @-webkit-keyframes moveToTopFade { to { opacity: .3; height:0px; margin-top:0px; opacity: 0.3; -webkit-transform: translateY(-100%); } } @-moz-keyframes moveToTopFade { to { height:0px; -moz-transform: translateY(-100%); } } @keyframes moveToTopFade { to { height:0px; transform: translateY(-100%); } } @-webkit-keyframes moveToTopFadeMonth { to { opacity: 0; -webkit-transform: translateY(-30%) scale(.95); } } @-moz-keyframes moveToTopFadeMonth { to { opacity: 0; -moz-transform: translateY(-30%); } } @keyframes moveToTopFadeMonth { to { opacity: 0; -moz-transform: translateY(-30%); } } @-webkit-keyframes moveFromTopFadeMonth { from { opacity: 0; -webkit-transform: translateY(30%) scale(.95); } } @-moz-keyframes moveFromTopFadeMonth { from { opacity: 0; -moz-transform: translateY(30%); } } @keyframes moveFromTopFadeMonth { from { opacity: 0; -moz-transform: translateY(30%); } } @-webkit-keyframes moveToBottomFadeMonth { to { opacity: 0; -webkit-transform: translateY(30%) scale(.95); } } @-moz-keyframes moveToBottomFadeMonth { to { opacity: 0; -webkit-transform: translateY(30%); } } @keyframes moveToBottomFadeMonth { to { opacity: 0; -webkit-transform: translateY(30%); } } @-webkit-keyframes moveFromBottomFadeMonth { from { opacity: 0; -webkit-transform: translateY(-30%) scale(.95); } } @-moz-keyframes moveFromBottomFadeMonth { from { opacity: 0; -webkit-transform: translateY(-30%); } } @keyframes moveFromBottomFadeMonth { from { opacity: 0; -webkit-transform: translateY(-30%); } } @-webkit-keyframes fadeIn { from { opacity: 0; } } @-moz-keyframes fadeIn { from { opacity: 0; } } @keyframes fadeIn { from { opacity: 0; } } @-webkit-keyframes fadeOut { to { opacity: 0; } } @-moz-keyframes fadeOut { to { opacity: 0; } } @keyframes fadeOut { to { opacity: 0; } } @-webkit-keyframes fadeOutShink { to { opacity: 0; padding: 0px; height: 0px; } } @-moz-keyframes fadeOutShink { to { opacity: 0; padding: 0px; height: 0px; } } @keyframes fadeOutShink { to { opacity: 0; padding: 0px; height: 0px; } } 
 <div id="calendar"></div> <script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.5.1/moment.min.js"></script> 

As I understand it, the events in it are displayed in random order. Is it possible to create the same list with the date, for example:

 { eventDate: '25.02.2005', eventName: 'Lunch Meeting w/ Mark', calendar: 'Work', color: 'orange' }, 

I am sure that this functionality is embedded in the script itself, but I just can’t find the original article, examples or parse the code.

Is it possible to supplement the functionality of event output with time? For example:

 { eventDate: '25.02.2005', eventTime: '12:24', eventName: 'Lunch Meeting w/ Mark', calendar: 'Work', color: 'orange' }, 

So that the data are displayed in order in one date by time.

enter image description here

In the appendix to everything, can this list be put into a separate file?

Thank!

  • And you did not think that such a conversion was not originally conceived in the work of the calendar? Although it’s enough to make such a decision just by changing the draw method, also adding a time display in drawEvent, renderEvent. After all, the events object is processed there. But this is not so quickly done. Yes, and too lazy to do so much work for thanks =) So try yourself to find a solution, and ask a more accurate question of what does not work. The output to the file is to you in the direction of ajax /node.js/php (well, or tricks with input Save As) - alexoander
  • And also - work with time goes through moment.js. It is there that you can read exactly how to convert the clock into the desired look and how to store it along with the date, for example (although this is not mandatory in this case) - alexoander
  • If the functionality is not laid, then what was the point at all in writing this calendar? To visually scatter tasks in a chaotic manner? However, if this is so, then the question is likely to be removed, since I have already found a suitable solution for my goals. - Alexey Giryayev
  • As for “thank you”, I spent my time answering other questions and didn’t scream about it, this resource was created just for such purposes. - Alexey Giryayev
  • Criticism is your personal attitude to my position on this issue. I have described everything to you exactly as it is. As for the meaning in the calendar, this is already asking where you got this code from. The creator of the code must have seen the calendar this way. But as I described above - to change this behavior is quite simple, if you spend some time and even indicated where to do it (which you actually asked) - alexoander

1 answer 1

Having dealt with the Moment.js script and the calendar code itself, a solution was found. As it was expected, the functionality was originally laid and there were not a lot of changes to be made, we remove part of the script responsible for outputting events in a random order and add the date to the list of events (standard format from moment.js).

Here is the working code, if someone needs a solution:

 !function() { var today = moment(); function Calendar(selector, events) { this.el = document.querySelector(selector); this.events = events; this.current = moment().date(1); this.events.forEach(function(ev) { ev.date = moment(ev.date); }); this.draw(); var current = document.querySelector('.today'); if(current) { var self = this; window.setTimeout(function() { self.openDay(current); }, 500); } } Calendar.prototype.draw = function() { //Create Header this.drawHeader(); //Draw Month this.drawMonth(); this.drawLegend(); } Calendar.prototype.drawHeader = function() { var self = this; if(!this.header) { //Create the header elements this.header = createElement('div', 'header'); this.header.className = 'header'; this.title = createElement('h1'); var right = createElement('div', 'right'); right.addEventListener('click', function() { self.nextMonth(); }); var left = createElement('div', 'left'); left.addEventListener('click', function() { self.prevMonth(); }); //Append the Elements this.header.appendChild(this.title); this.header.appendChild(right); this.header.appendChild(left); this.el.appendChild(this.header); } this.title.innerHTML = this.current.format('MMMM YYYY'); } Calendar.prototype.drawMonth = function() { var self = this; if(this.month) { this.oldMonth = this.month; this.oldMonth.className = 'month out ' + (self.next ? 'next' : 'prev'); this.oldMonth.addEventListener('webkitAnimationEnd', function() { self.oldMonth.parentNode.removeChild(self.oldMonth); self.month = createElement('div', 'month'); self.backFill(); self.currentMonth(); self.fowardFill(); self.el.appendChild(self.month); window.setTimeout(function() { self.month.className = 'month in ' + (self.next ? 'next' : 'prev'); }, 16); }); } else { this.month = createElement('div', 'month'); this.el.appendChild(this.month); this.backFill(); this.currentMonth(); this.fowardFill(); this.month.className = 'month new'; } } Calendar.prototype.backFill = function() { var clone = this.current.clone(); var dayOfWeek = clone.day(); if(!dayOfWeek) { return; } clone.subtract('days', dayOfWeek+1); for(var i = dayOfWeek; i > 0 ; i--) { this.drawDay(clone.add('days', 1)); } } Calendar.prototype.fowardFill = function() { var clone = this.current.clone().add('months', 1).subtract('days', 1); var dayOfWeek = clone.day(); if(dayOfWeek === 6) { return; } for(var i = dayOfWeek; i < 6 ; i++) { this.drawDay(clone.add('days', 1)); } } Calendar.prototype.currentMonth = function() { var clone = this.current.clone(); while(clone.month() === this.current.month()) { this.drawDay(clone); clone.add('days', 1); } } Calendar.prototype.getWeek = function(day) { if(!this.week || day.day() === 0) { this.week = createElement('div', 'week'); this.month.appendChild(this.week); } } Calendar.prototype.drawDay = function(day) { var self = this; this.getWeek(day); //Outer Day var outer = createElement('div', this.getDayClass(day)); outer.addEventListener('click', function() { self.openDay(this); }); //Day Name var name = createElement('div', 'day-name', day.format('ddd')); //Day Number var number = createElement('div', 'day-number', day.format('DD')); //Events var events = createElement('div', 'day-events'); this.drawEvents(day, events); outer.appendChild(name); outer.appendChild(number); outer.appendChild(events); this.week.appendChild(outer); } Calendar.prototype.drawEvents = function(day, element) { if(day.month() === this.current.month()) { var todaysEvents = this.events.reduce(function(memo, ev) { if(ev.date.isSame(day, 'day')) { memo.push(ev); } return memo; }, []); todaysEvents.forEach(function(ev) { var evSpan = createElement('span', ev.color); element.appendChild(evSpan); }); } } Calendar.prototype.getDayClass = function(day) { classes = ['day']; if(day.month() !== this.current.month()) { classes.push('other'); } else if (today.isSame(day, 'day')) { classes.push('today'); } return classes.join(' '); } Calendar.prototype.openDay = function(el) { var details, arrow; var dayNumber = +el.querySelectorAll('.day-number')[0].innerText || +el.querySelectorAll('.day-number')[0].textContent; var day = this.current.clone().date(dayNumber); var currentOpened = document.querySelector('.details'); //Check to see if there is an open detais box on the current row if(currentOpened && currentOpened.parentNode === el.parentNode) { details = currentOpened; arrow = document.querySelector('.arrow'); } else { //Close the open events on differnt week row //currentOpened && currentOpened.parentNode.removeChild(currentOpened); if(currentOpened) { currentOpened.addEventListener('webkitAnimationEnd', function() { currentOpened.parentNode.removeChild(currentOpened); }); currentOpened.addEventListener('oanimationend', function() { currentOpened.parentNode.removeChild(currentOpened); }); currentOpened.addEventListener('msAnimationEnd', function() { currentOpened.parentNode.removeChild(currentOpened); }); currentOpened.addEventListener('animationend', function() { currentOpened.parentNode.removeChild(currentOpened); }); currentOpened.className = 'details out'; } //Create the Details Container details = createElement('div', 'details in'); //Create the arrow var arrow = createElement('div', 'arrow'); //Create the event wrapper details.appendChild(arrow); el.parentNode.appendChild(details); } var todaysEvents = this.events.reduce(function(memo, ev) { if(ev.date.isSame(day, 'day')) { memo.push(ev); } return memo; }, []); this.renderEvents(todaysEvents, details); arrow.style.left = el.offsetLeft - el.parentNode.offsetLeft + 27 + 'px'; } Calendar.prototype.renderEvents = function(events, ele) { //Remove any events in the current details element var currentWrapper = ele.querySelector('.events'); var wrapper = createElement('div', 'events in' + (currentWrapper ? ' new' : '')); events.forEach(function(ev) { var div = createElement('div', 'event'); var square = createElement('div', 'event-category ' + ev.color); var span = createElement('span', '', ev.eventName); div.appendChild(square); div.appendChild(span); wrapper.appendChild(div); }); if(!events.length) { var div = createElement('div', 'event empty'); var span = createElement('span', '', 'No Events'); div.appendChild(span); wrapper.appendChild(div); } if(currentWrapper) { currentWrapper.className = 'events out'; currentWrapper.addEventListener('webkitAnimationEnd', function() { currentWrapper.parentNode.removeChild(currentWrapper); ele.appendChild(wrapper); }); currentWrapper.addEventListener('oanimationend', function() { currentWrapper.parentNode.removeChild(currentWrapper); ele.appendChild(wrapper); }); currentWrapper.addEventListener('msAnimationEnd', function() { currentWrapper.parentNode.removeChild(currentWrapper); ele.appendChild(wrapper); }); currentWrapper.addEventListener('animationend', function() { currentWrapper.parentNode.removeChild(currentWrapper); ele.appendChild(wrapper); }); } else { ele.appendChild(wrapper); } } Calendar.prototype.drawLegend = function() { var legend = createElement('div', 'legend'); var calendars = this.events.map(function(e) { return e.calendar + '|' + e.color; }).reduce(function(memo, e) { if(memo.indexOf(e) === -1) { memo.push(e); } return memo; }, []).forEach(function(e) { var parts = e.split('|'); var entry = createElement('span', 'entry ' + parts[1], parts[0]); legend.appendChild(entry); }); this.el.appendChild(legend); } Calendar.prototype.nextMonth = function() { this.current.add('months', 1); this.next = true; this.draw(); } Calendar.prototype.prevMonth = function() { this.current.subtract('months', 1); this.next = false; this.draw(); } window.Calendar = Calendar; function createElement(tagName, className, innerText) { var ele = document.createElement(tagName); if(className) { ele.className = className; } if(innerText) { ele.innderText = ele.textContent = innerText; } return ele; } }(); !function() { var data = [ { eventName: 'Покушать', calendar: 'Дом', color: 'orange', date: '2017-01-08' }, { eventName: 'Поспать', calendar: 'Работа', color: 'yellow', date: '2017-02-12' }, { eventName: 'Сходить по делам', calendar: 'Отдых', color: 'blue', date: '2017-03-27' }, { eventName: 'Написать текст', calendar: 'Разное', color: 'green', date: '2017-01-08' } ]; var calendar = new Calendar('#calendar', data); }(); 
 *, *:before, *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } body { overflow-x: hidden; font-family: 'HelveticaNeue-UltraLight', 'Helvetica Neue UltraLight', 'Helvetica Neue', Arial, Helvetica, sans-serif; font-weight: 100; color: rgba(255, 255, 255, 1); margin: 0; padding: 0; background: #4A4A4A; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } #calendar { -webkit-transform: translate3d(0, 0, 0); -moz-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); width: 420px; margin: 0 auto; height: 570px; overflow: hidden; } .header { height: 50px; width: 420px; background: rgba(66, 66, 66, 1); text-align: center; position:relative; z-index: 100; } .header h1 { margin: 0; padding: 0; font-size: 20px; line-height: 50px; font-weight: 100; letter-spacing: 1px; } .left, .right { position: absolute; width: 0px; height: 0px; border-style: solid; top: 50%; margin-top: -7.5px; cursor: pointer; } .left { border-width: 7.5px 10px 7.5px 0; border-color: transparent rgba(160, 159, 160, 1) transparent transparent; left: 20px; } .right { border-width: 7.5px 0 7.5px 10px; border-color: transparent transparent transparent rgba(160, 159, 160, 1); right: 20px; } .month { /*overflow: hidden;*/ opacity: 0; } .month.new { -webkit-animation: fadeIn 1s ease-out; opacity: 1; } .month.in.next { -webkit-animation: moveFromTopFadeMonth .4s ease-out; -moz-animation: moveFromTopFadeMonth .4s ease-out; animation: moveFromTopFadeMonth .4s ease-out; opacity: 1; } .month.out.next { -webkit-animation: moveToTopFadeMonth .4s ease-in; -moz-animation: moveToTopFadeMonth .4s ease-in; animation: moveToTopFadeMonth .4s ease-in; opacity: 1; } .month.in.prev { -webkit-animation: moveFromBottomFadeMonth .4s ease-out; -moz-animation: moveFromBottomFadeMonth .4s ease-out; animation: moveFromBottomFadeMonth .4s ease-out; opacity: 1; } .month.out.prev { -webkit-animation: moveToBottomFadeMonth .4s ease-in; -moz-animation: moveToBottomFadeMonth .4s ease-in; animation: moveToBottomFadeMonth .4s ease-in; opacity: 1; } .week { background: #4A4A4A; } .day { display: inline-block; width: 60px; padding: 10px; text-align: center; vertical-align: top; cursor: pointer; background: #4A4A4A; position: relative; z-index: 100; } .day.other { color: rgba(255, 255, 255, .3); } .day.today { color: rgba(156, 202, 235, 1); } .day-name { font-size: 9px; text-transform: uppercase; margin-bottom: 5px; color: rgba(255, 255, 255, .5); letter-spacing: .7px; } .day-number { font-size: 24px; letter-spacing: 1.5px; } .day .day-events { list-style: none; margin-top: 3px; text-align: center; height: 12px; line-height: 6px; overflow: hidden; } .day .day-events span { vertical-align: top; display: inline-block; padding: 0; margin: 0; width: 5px; height: 5px; line-height: 5px; margin: 0 1px; } .blue { background: rgba(156, 202, 235, 1); } .orange { background: rgba(247, 167, 0, 1); } .green { background: rgba(153, 198, 109, 1); } .yellow { background: rgba(249, 233, 0, 1); } .details { position: relative; width: 420px; height: 75px; background: rgba(164, 164, 164, 1); margin-top: 5px; border-radius: 4px; } .details.in { -webkit-animation: moveFromTopFade .5s ease both; -moz-animation: moveFromTopFade .5s ease both; animation: moveFromTopFade .5s ease both; } .details.out { -webkit-animation: moveToTopFade .5s ease both; -moz-animation: moveToTopFade .5s ease both; animation: moveToTopFade .5s ease both; } .arrow { position: absolute; top: -5px; left: 50%; margin-left: -2px; width: 0px; height: 0px; border-style: solid; border-width: 0 5px 5px 5px; border-color: transparent transparent rgba(164, 164, 164, 1) transparent; transition: all 0.7s ease; } .events { height: 75px; padding: 7px 0; overflow-y: auto; overflow-x: hidden; } .events.in { -webkit-animation: fadeIn .3s ease both; -moz-animation: fadeIn .3s ease both; animation: fadeIn .3s ease both; } .events.in { -webkit-animation-delay: .3s; -moz-animation-delay: .3s; animation-delay: .3s; } .details.out .events { -webkit-animation: fadeOutShrink .4s ease both; -moz-animation: fadeOutShink .4s ease both; animation: fadeOutShink .4s ease both; } .events.out { -webkit-animation: fadeOut .3s ease both; -moz-animation: fadeOut .3s ease both; animation: fadeOut .3s ease both; } .event { font-size: 16px; line-height: 22px; letter-spacing: .5px; padding: 2px 16px; vertical-align: top; } .event.empty { color: #eee; } .event-category { height: 10px; width: 10px; display: inline-block; margin: 6px 0 0; vertical-align: top; } .event span { display: inline-block; padding: 0 0 0 7px; } .legend { position: absolute; bottom: 0; width: 100%; height: 30px; background: rgba(60, 60, 60, 1); line-height: 30px; } .entry { position: relative; padding: 0 0 0 25px; font-size: 13px; display: inline-block; line-height: 30px; background: transparent; } .entry:after { position: absolute; content: ''; height: 5px; width: 5px; top: 12px; left: 14px; } .entry.blue:after { background: rgba(156, 202, 235, 1); } .entry.orange:after { background: rgba(247, 167, 0, 1); } .entry.green:after { background: rgba(153, 198, 109, 1); } .entry.yellow:after { background: rgba(249, 233, 0, 1); } /* Animations are cool! */ @-webkit-keyframes moveFromTopFade { from { opacity: .3; height:0px; margin-top:0px; -webkit-transform: translateY(-100%); } } @-moz-keyframes moveFromTopFade { from { height:0px; margin-top:0px; -moz-transform: translateY(-100%); } } @keyframes moveFromTopFade { from { height:0px; margin-top:0px; transform: translateY(-100%); } } @-webkit-keyframes moveToTopFade { to { opacity: .3; height:0px; margin-top:0px; opacity: 0.3; -webkit-transform: translateY(-100%); } } @-moz-keyframes moveToTopFade { to { height:0px; -moz-transform: translateY(-100%); } } @keyframes moveToTopFade { to { height:0px; transform: translateY(-100%); } } @-webkit-keyframes moveToTopFadeMonth { to { opacity: 0; -webkit-transform: translateY(-30%) scale(.95); } } @-moz-keyframes moveToTopFadeMonth { to { opacity: 0; -moz-transform: translateY(-30%); } } @keyframes moveToTopFadeMonth { to { opacity: 0; -moz-transform: translateY(-30%); } } @-webkit-keyframes moveFromTopFadeMonth { from { opacity: 0; -webkit-transform: translateY(30%) scale(.95); } } @-moz-keyframes moveFromTopFadeMonth { from { opacity: 0; -moz-transform: translateY(30%); } } @keyframes moveFromTopFadeMonth { from { opacity: 0; -moz-transform: translateY(30%); } } @-webkit-keyframes moveToBottomFadeMonth { to { opacity: 0; -webkit-transform: translateY(30%) scale(.95); } } @-moz-keyframes moveToBottomFadeMonth { to { opacity: 0; -webkit-transform: translateY(30%); } } @keyframes moveToBottomFadeMonth { to { opacity: 0; -webkit-transform: translateY(30%); } } @-webkit-keyframes moveFromBottomFadeMonth { from { opacity: 0; -webkit-transform: translateY(-30%) scale(.95); } } @-moz-keyframes moveFromBottomFadeMonth { from { opacity: 0; -webkit-transform: translateY(-30%); } } @keyframes moveFromBottomFadeMonth { from { opacity: 0; -webkit-transform: translateY(-30%); } } @-webkit-keyframes fadeIn { from { opacity: 0; } } @-moz-keyframes fadeIn { from { opacity: 0; } } @keyframes fadeIn { from { opacity: 0; } } @-webkit-keyframes fadeOut { to { opacity: 0; } } @-moz-keyframes fadeOut { to { opacity: 0; } } @keyframes fadeOut { to { opacity: 0; } } @-webkit-keyframes fadeOutShink { to { opacity: 0; padding: 0px; height: 0px; } } @-moz-keyframes fadeOutShink { to { opacity: 0; padding: 0px; height: 0px; } } @keyframes fadeOutShink { to { opacity: 0; padding: 0px; height: 0px; } } 
 <div id="calendar"></div> <script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.5.1/moment.min.js"></script> 

A little later I will add the addition of time to events and their sorting.