Skip to content

Instantly share code, notes, and snippets.

@nesvand
Last active August 29, 2015 14:19
Show Gist options
  • Save nesvand/062eaca65ecfaf5230c4 to your computer and use it in GitHub Desktop.
Save nesvand/062eaca65ecfaf5230c4 to your computer and use it in GitHub Desktop.
Google CLNDR
/* @calendar styling */
.events-list::-webkit-scrollbar {
-webkit-appearance: none;
width: 7px;
}
.events-list::-webkit-scrollbar-thumb {
border-radius: 4px;
background-color: rgba(0,0,0,.5);
-webkit-box-shadow: 0 0 1px rgba(255,255,255,.5);
}
#calendar {
font-family: Asap, Helvetica, Arial;
margin: 0 auto;
width: 100%;
-moz-box-shadow: 4px 4px 0 rgba(120, 119, 119, 0.9);
-webkit-box-shadow: 4px 4px 0 rgba(120, 119, 119, 0.9);
box-shadow: 4px 4px 0 rgba(120, 119, 119, 0.9);
}
#calendar .clndr {
overflow: hidden;
border-bottom: 7px solid #71BBD2;
}
#calendar .clndr .controls {
background-color: #256681;
color: white;
}
#calendar .clndr .controls .clndr-previous-button,
#calendar .clndr .controls .clndr-next-button {
width: 15%;
padding-top: 5px;
padding-bottom: 5px;
display: inline-block;
text-align: center;
cursor: pointer;
-webkit-user-select: none;
/* Chrome/Safari */
-moz-user-select: none;
/* Firefox */
-ms-user-select: none;
/* IE10+ */
-webkit-transition: background-color 0.5s;
-moz-transition: background-color 0.5s;
-ms-transition: background-color 0.5s;
-o-transition: background-color 0.5s;
transition: background-color 0.5s;
}
#calendar .clndr .controls .clndr-previous-button:hover,
#calendar .clndr .controls .clndr-next-button:hover {
background-color: #3E9EC6;
}
#calendar .clndr .controls .month {
width: 70%;
padding-top: 5px;
padding-bottom: 5px;
display: inline-block;
text-align: center;
text-transform: uppercase;
font-weight: 700;
letter-spacing: 1px;
}
#calendar .clndr .days-container {
position: relative;
width: 100%;
height: 265px;
display: inline-block;
}
#calendar .clndr .days-container .days {
position: absolute;
left: 0;
width: 100%;
height: 270px;
-webkit-transition: left 0.5s;
-moz-transition: left 0.5s;
-ms-transition: left 0.5s;
-o-transition: left 0.5s;
transition: left 0.5s;
background-color: #ebebeb;
}
#calendar .clndr .days-container .days .day,
#calendar .clndr .days-container .days .empty {
width: 14.2857%;
display: inline-block;
height: 40px;
padding: 1em 0;
font-size: 12px;
text-align: center;
color: #212121;
background-color: #EBEBEB;
background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHZlcnNpb249IjEuMiIgYmFzZVByb2ZpbGU9InRpbnkiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjExNHB4IiBoZWlnaHQ9IjY2cHgiIHZpZXdCb3g9IjAgMCAxMTQgNjYiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxwb2x5Z29uIGZpbGw9IiNFOEU4RTgiIHBvaW50cz0iMTE0LDAgMCw2NiAxMTQsNjYgIi8+PC9zdmc+);
background-size: cover;
background-position: center center;
border-right: 1px solid rgba(255, 255, 255, 0.5);
border-bottom: 1px solid rgba(255, 255, 255, 0.5);
}
#calendar .clndr .days-container .days .day.event,
#calendar .clndr .days-container .days .empty.event {
background-color: #fff;
background-image: none;
-webkit-transition: background-color 0.5s;
-moz-transition: background-color 0.5s;
-ms-transition: background-color 0.5s;
-o-transition: background-color 0.5s;
transition: background-color 0.5s;
cursor: pointer;
}
#calendar .clndr .days-container .days .day.event:hover,
#calendar .clndr .days-container .days .empty.event:hover {
background-color: #b8b8b8;
}
#calendar .clndr .days-container .days .day.event .day-number,
#calendar .clndr .days-container .days .empty.event .day-number {
padding-bottom: 4px;
border-bottom: 2px solid #3883A3;
}
#calendar .clndr .days-container .days .day.adjacent-month,
#calendar .clndr .days-container .days .empty.adjacent-month {
color: rgba(0, 0, 0, 0.3);
}
#calendar .clndr .days-container .days .empty {
height: 31px;
vertical-align: bottom;
}
#calendar .clndr .days-container .days .headers {
background-color: #3883A3;
padding-top: 5px;
padding-bottom: 5px;
}
#calendar .clndr .days-container .days .headers .day-header {
width: 14.2857%;
display: inline-block;
text-align: center;
color: white;
}
#calendar .clndr .days-container .events {
position: absolute;
left: 100%;
width: 100%;
height: 270px;
-webkit-transition: left 0.5s;
-moz-transition: left 0.5s;
-ms-transition: left 0.5s;
-o-transition: left 0.5s;
transition: left 0.5s;
background-color: #ebebeb;
}
#calendar .clndr .days-container .events .headers {
position: relative;
}
#calendar .clndr .days-container .events .event-header {
width: 100%;
background-color: #71BBD2;
padding-top: 5px;
padding-bottom: 5px;
text-align: center;
color: white;
}
#calendar .clndr .days-container .events .x-button {
position: absolute;
font-size: 80%;
top: 7px;
left: 20px;
cursor: pointer;
-webkit-transition: color 0.25s;
-moz-transition: color 0.25s;
-ms-transition: color 0.25s;
-o-transition: color 0.25s;
transition: color 0.25s;
}
#calendar .clndr .days-container .events .x-button:hover {
color: white;
}
#calendar .clndr .days-container .events .events-list {
overflow-y: scroll;
height: 240px;
}
#calendar .clndr .days-container .events .events-list .event {
padding-top: 1em;
padding-bottom: 1em;
padding-left: 10px;
border-bottom: 1px solid rgba(255, 255, 255, 0.5);
-webkit-transition: background-color 0.25s;
-moz-transition: background-color 0.25s;
-ms-transition: background-color 0.25s;
-o-transition: background-color 0.25s;
transition: background-color 0.25s;
}
#calendar .clndr .days-container .events .events-list .event:hover {
background-color: #f5f5f5;
}
#calendar .clndr .days-container .events .events-list .event a {
position: relative;
font-size: 12px;
letter-spacing: 1px;
background-color: transparent;
color: #212121;
text-decoration: none;
-webkit-transition: color 0.25s;
-moz-transition: color 0.25s;
-ms-transition: color 0.25s;
-o-transition: color 0.25s;
transition: color 0.25s;
}
#calendar .clndr .days-container .events .events-list .event a:hover {
background-color: transparent;
color: #256681;
}
#calendar .clndr .days-container.show-events .days {
left: -100%;
}
#calendar .clndr .days-container.show-events .events {
left: 0;
}
/* @calendar styling end */
<script id="calendar-template" type="text/template">
<div class="controls">
<div class="clndr-previous-button">&lsaquo;</div><div class="month"><%= month %></div><div class="clndr-next-button">&rsaquo;</div>
</div>
<div class="days-container">
<div class="days">
<div class="headers">
<% _.each(daysOfTheWeek, function(day) { %><div class="day-header"><%= day %> <%= year %></div><% }); %>
</div>
<% _.each(days, function(day) { %><div class="<%= day.classes %>" id="<%= day.id %>"><span class="day-number"><%= day.day %></span></div><% }); %>
</div>
<div class="events">
<div class="headers">
<div class="x-button">x</div>
<div class="event-header">EVENTS</div>
</div>
<div class="events-list">
<% _.each(eventsThisMonth, function(event) { %>
<div class="event">
<a href="<%= event.url %>"><%= moment(event.date).format('MMMM Do') %>: <%= event.title %></a>
</div>
<% }); %>
</div>
</div>
</div>
</script>
/*********************************************************************************************************************/
/* Google-powered CLNDR.js
/*********************************************************************************************************************/
//Date.toISOString() polyfill
Date.prototype.toISOString || function() {function a(a) {return 10 > a ? "0" + a : a}Date.prototype.toISOString = function() {return this.getUTCFullYear() + "-" + a(this.getUTCMonth() + 1) + "-" + a(this.getUTCDate()) + "T" + a(this.getUTCHours()) + ":" + a(this.getUTCMinutes()) + ":" + a(this.getUTCSeconds()) + "." + (this.getUTCMilliseconds() / 1E3).toFixed(3).slice(2, 5) + "Z"}}();
//Sort by Event Start Date, not by Event Created (using underscore.js as it is already required by CLNDR.js)
function sorter(input) {
var arr = [];
var returnArr = [];
for (var i in input) {
arr.push([input[i]]);
}
arr = _.sortBy(arr, function(el) {
return Date.parse(el[0].start.date);
});
_.map(arr, function(el) {
return returnArr.push(el[0]);
});
return returnArr;
}
// Cross Reload Cookie Saving
if (JSON && JSON.stringify && JSON.parse) var Session = Session || (function() {
// Get stored cookie data
var cookie = sniffCookie();
function sniffCookie() {
var name = 'store';
var result = document.cookie.match(new RegExp(name + '=([^;]+)'));
if (result) {
return JSON.parse(result[1]);
}
return {};
}
function bakeCookie() {
var date = new Date();
var expires;
date.setTime(date.getTime() + (5 * 60 * 1000)); // 5 minute cookie
expires = 'expires=' + date;
document.cookie = 'store=' + JSON.stringify(cookie) + '; ' + expires;
}
// page unload event
if (window.addEventListener) {
window.addEventListener('unload', bakeCookie, false);
} else if (window.attachEvent) {
window.attachEvent('onunload', bakeCookie);
} else {
window.onunload = bakeCookie;
}
// public methods
return {
// set a session variable
set: function(name, value) {
cookie[name] = value;
},
// get a session value
get: function(name) {
return (cookie[name] ? cookie[name] : undefined);
},
// clear session
clear: function() {
cookie = {};
}
};
})();
function loadCalendar(e) {
if (e) {
$('#calendar').clndr({
template: $('#calendar-template').html(),
events: e,
clickEvents: {
click: function(target) {
if (target.events.length) {
var daysContainer = $('#calendar').find('.days-container');
daysContainer.toggleClass('show-events', true);
$('#calendar').find('.x-button').click(function() {
daysContainer.toggleClass('show-events', false);
});
}
}
},
adjacentDaysChangeMonth: true,
forceSixRows: true
});
}
}
if ($('#home').length || $('#entertainment').length) {
var storedEvents = Session.get('events');
if (storedEvents === undefined) {
var currDate = new Date();
var timeMin = encodeURI('&timeMin=' + (new Date([currDate.getFullYear(), ('0' + ((currDate.getMonth() * 1) + 1)).slice(-2), '01'].join('-'))).toISOString());
var googleCalendarURL = 'https://www.googleapis.com/calendar/v3/calendars/{calendar id}/events?singleEvents=true&key={API key}' + timeMin; // Only show calendar events starting from the current calendar month - repeated events displayed as individual events (singleEvents)
var calendarReq = new XMLHttpRequest();
// Add timestamp to bypass cache
calendarReq.open('GET', googleCalendarURL + ((/\?/).test(googleCalendarURL) ? '&' : '?') + (new Date()).getTime(), true);
calendarReq.onreadystatechange = function() {
if (calendarReq.readyState == 4 && calendarReq.status >= 200 && calendarReq.status < 400) {
var calendarData = JSON.parse(calendarReq.responseText);
var calendarEvents = sorter(calendarData.items);
var len = calendarEvents.length;
var events = [];
var i;
for (i = 0; i < len; i++) {
var eventStartEnd = '';
if (calendarEvents[i].start.dateTime) {
var startHour = moment(calendarEvents[i].start.dateTime).hour();
var startMinute = ('0' + moment(calendarEvents[i].start.dateTime).minute()).slice(-2);
var endHour = moment(calendarEvents[i].end.dateTime).hour();
var endMinute = ('0' + moment(calendarEvents[i].end.dateTime).minute()).slice(-2);
eventStartEnd = ' (' + startHour + ':' + startMinute + ' - ' + endHour + ':' + endMinute + ')';
}
events.push({
'date': calendarEvents[i].start.date,
'title': calendarEvents[i].summary + eventStartEnd,
'url': calendarEvents[i].htmlLink
});
}
storedEvents = events;
loadCalendar(storedEvents);
Session.set('events', storedEvents);
}
};
calendarReq.send();
} else {
loadCalendar(storedEvents);
}
}
/*********************************************************************************************************************/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment