314 lines
8.3 KiB
JavaScript
Raw Normal View History

2016-03-31 11:05:32 +02:00
/* global Module */
/* Magic Mirror
* Module: Calendar
*
* By Michael Teeuw http://michaelteeuw.nl
* MIT Licensed.
*/
2016-04-05 14:35:11 -04:00
Module.register("calendar",{
2016-03-31 11:05:32 +02:00
// Define module defaults
defaults: {
maximumEntries: 10, // Total Maximum Entries
maximumNumberOfDays: 365,
2016-03-31 11:05:32 +02:00
displaySymbol: true,
2016-04-05 14:35:11 -04:00
defaultSymbol: "calendar", // Fontawsome Symbol see http://fontawesome.io/cheatsheet/
displayRepeatingCountTitle: false,
defaultRepeatingCountTitle: '',
maxTitleLength: 25,
2016-03-31 11:05:32 +02:00
fetchInterval: 5 * 60 * 1000, // Update every 5 minutes.
animationSpeed: 2000,
fade: true,
2016-03-31 11:05:32 +02:00
fadePoint: 0.25, // Start on 1/4th of the list.
2016-04-05 14:35:11 -04:00
calendars: [
2016-03-31 11:05:32 +02:00
{
2016-04-05 14:35:11 -04:00
symbol: "calendar",
url: "http://www.calendarlabs.com/templates/ical/US-Holidays.ics",
2016-03-31 11:05:32 +02:00
},
],
titleReplace: {
2016-04-05 14:35:11 -04:00
"De verjaardag van ": ""
},
2016-03-31 11:05:32 +02:00
},
// Define required scripts.
getStyles: function() {
2016-04-05 14:35:11 -04:00
return ["calendar.css", "font-awesome.css"];
2016-03-31 11:05:32 +02:00
},
// Define required scripts.
getScripts: function() {
2016-04-05 14:35:11 -04:00
return ["moment.js"];
2016-03-31 11:05:32 +02:00
},
2016-04-21 01:04:00 +02:00
// Define required translations.
getTranslations: function() {
return {
en: "translations/en.json",
de: "translations/de.json",
nl: "translations/nl.json"
2016-04-21 01:04:00 +02:00
};
},
2016-03-31 11:05:32 +02:00
// Override start method.
start: function() {
2016-04-05 14:35:11 -04:00
Log.log("Starting module: " + this.name);
2016-03-31 11:05:32 +02:00
// Set locale.
moment.locale(config.language);
for (var c in this.config.calendars) {
var calendar = this.config.calendars[c];
2016-04-05 14:35:11 -04:00
calendar.url = calendar.url.replace("webcal://", "http://");
2016-03-31 11:05:32 +02:00
this.addCalendar(calendar.url);
}
this.calendarData = {};
this.loaded = false;
2016-03-31 11:05:32 +02:00
},
// Override socket notification handler.
socketNotificationReceived: function(notification, payload) {
2016-04-05 14:35:11 -04:00
if (notification === "CALENDAR_EVENTS") {
2016-03-31 11:05:32 +02:00
if (this.hasCalendarURL(payload.url)) {
this.calendarData[payload.url] = payload.events;
this.loaded = true;
2016-03-31 11:05:32 +02:00
}
2016-04-05 14:35:11 -04:00
} else if (notification === "FETCH_ERROR") {
Log.error("Calendar Error. Could not fetch calendar: " + payload.url);
} else if (notification === "INCORRECT_URL") {
Log.error("Calendar Error. Incorrect url: " + payload.url);
2016-03-31 11:05:32 +02:00
} else {
2016-04-05 14:35:11 -04:00
Log.log("Calendar received an unknown socket notification: " + notification);
2016-03-31 11:05:32 +02:00
}
this.updateDom(this.config.animationSpeed);
},
// Override dom generator.
getDom: function() {
var events = this.createEventList();
var wrapper = document.createElement("table");
wrapper.className = "small";
if (events.length === 0) {
2016-04-21 01:04:00 +02:00
wrapper.innerHTML = (this.loaded) ? this.translate("EMPTY") : this.translate("LOADING");
2016-03-31 11:05:32 +02:00
wrapper.className = "small dimmed";
return wrapper;
}
for (var e in events) {
var event = events[e];
var eventWrapper = document.createElement("tr");
eventWrapper.className = "normal";
if (this.config.displaySymbol) {
var symbolWrapper = document.createElement("td");
symbolWrapper.className = "symbol";
var symbol = document.createElement("span");
symbol.className = "fa fa-" + this.symbolForUrl(event.url);
symbolWrapper.appendChild(symbol);
eventWrapper.appendChild(symbolWrapper);
}
var titleWrapper = document.createElement("td"),
repeatingCountTitle = '';
if (this.config.displayRepeatingCountTitle) {
repeatingCountTitle = this.countTitleForUrl(event.url)
if(repeatingCountTitle != '') {
var thisYear = new Date().getFullYear(),
yearDiff = thisYear - event.firstYear;
repeatingCountTitle = ', '+ yearDiff + '. ' + repeatingCountTitle;
}
}
titleWrapper.innerHTML = this.titleTransform(event.title) + repeatingCountTitle;
2016-03-31 11:05:32 +02:00
titleWrapper.className = "title bright";
eventWrapper.appendChild(titleWrapper);
var timeWrapper = document.createElement("td");
//console.log(event.today);
var now = new Date();
if (event.fullDayEvent) {
if (event.today) {
2016-04-21 01:04:00 +02:00
timeWrapper.innerHTML = this.translate("TODAY");
} else if (event.startDate - now < 24 * 60 * 60 * 1000 && event.startDate - now > 0) {
2016-04-21 01:04:00 +02:00
timeWrapper.innerHTML = this.translate("TOMORROW");
} else {
timeWrapper.innerHTML = moment(event.startDate,"x").fromNow();
}
} else {
2016-04-15 13:13:06 +02:00
if (event.startDate >= new Date()) {
2016-04-19 10:34:14 +02:00
if (event.startDate - now > 48 * 60 * 60 * 1000) {
// if the event is no longer than 2 days away, display the absolute time.
timeWrapper.innerHTML = moment(event.startDate,"x").fromNow();
} else {
timeWrapper.innerHTML = moment(event.startDate,"x").calendar();
}
2016-04-15 13:13:06 +02:00
} else {
2016-04-21 01:04:00 +02:00
timeWrapper.innerHTML = this.translate("RUNNING") + ' ' + moment(event.endDate,"x").fromNow(true);
2016-04-15 13:13:06 +02:00
}
}
//timeWrapper.innerHTML += ' - '+ moment(event.startDate,'x').format('lll');
//console.log(event);
2016-03-31 11:05:32 +02:00
timeWrapper.className = "time light";
eventWrapper.appendChild(timeWrapper);
wrapper.appendChild(eventWrapper);
// Create fade effect.
if (this.config.fade && this.config.fadePoint < 1) {
if (this.config.fadePoint < 0) {
this.config.fadePoint = 0;
}
var startingPoint = events.length * this.config.fadePoint;
var steps = events.length - startingPoint;
if (e >= startingPoint) {
var currentStep = e - startingPoint;
eventWrapper.style.opacity = 1 - (1 / steps * currentStep);
}
}
}
return wrapper;
},
/* hasCalendarURL(url)
* Check if this config contains the calendar url.
*
* argument url sting - Url to look for.
*
* return bool - Has calendar url
*/
hasCalendarURL: function(url) {
for (var c in this.config.calendars) {
var calendar = this.config.calendars[c];
if (calendar.url === url) {
return true;
}
}
return false;
},
/* createEventList()
* Creates the sorted list of all events.
*
* return array - Array with events.
*/
createEventList: function() {
var events = [];
2016-04-05 14:35:11 -04:00
var today = moment().startOf("day");
2016-03-31 11:05:32 +02:00
for (var c in this.calendarData) {
var calendar = this.calendarData[c];
for (var e in calendar) {
var event = calendar[e];
event.url = c;
2016-04-05 11:20:47 +02:00
event.today = event.startDate >= today && event.startDate < (today + 24 * 60 * 60 * 1000);
2016-03-31 11:05:32 +02:00
events.push(event);
}
}
2016-04-05 14:35:11 -04:00
events.sort(function(a, b) {
2016-03-31 11:05:32 +02:00
return a.startDate - b.startDate;
});
return events.slice(0, this.config.maximumEntries);
},
/* createEventList(url)
* Requests node helper to add calendar url.
*
* argument url sting - Url to add.
*/
addCalendar: function(url) {
2016-04-05 14:35:11 -04:00
this.sendSocketNotification("ADD_CALENDAR", {
2016-03-31 11:05:32 +02:00
url: url,
maximumEntries: this.config.maximumEntries,
maximumNumberOfDays: this.config.maximumNumberOfDays,
2016-03-31 11:05:32 +02:00
fetchInterval: this.config.fetchInterval
});
},
/* symbolForUrl(url)
* Retrieves the symbol for a specific url.
*
* argument url sting - Url to look for.
*
* return string - The Symbol
*/
symbolForUrl: function(url) {
for (var c in this.config.calendars) {
var calendar = this.config.calendars[c];
2016-04-05 14:35:11 -04:00
if (calendar.url === url && typeof calendar.symbol === "string") {
2016-03-31 11:05:32 +02:00
return calendar.symbol;
}
}
return this.config.defaultSymbol;
},
/* countTitleForUrl(url)
* Retrieves the name for a specific url.
*
* argument url sting - Url to look for.
*
* return string - The Symbol
*/
countTitleForUrl: function(url) {
for (var c in this.config.calendars) {
var calendar = this.config.calendars[c];
if (calendar.url === url && typeof calendar.repeatingCountTitle === "string") {
return calendar.repeatingCountTitle;
}
}
return this.config.defaultRepeatingCountTitle;
},
2016-03-31 11:05:32 +02:00
/* shorten(string, maxLength)
* Shortens a sting if it's longer than maxLenthg.
* Adds an ellipsis to the end.
*
* argument string string - The string to shorten.
* argument maxLength number - The max lenth of the string.
*
* return string - The shortened string.
*/
shorten: function(string, maxLength) {
if (string.length > maxLength) {
return string.slice(0,maxLength) + "&hellip;";
}
return string;
},
/* titleTransform(title)
* Transforms the title of an event for usage.
* Replaces parts of the text as defined in config.titleReplace.
* Shortens title based on config.maxTitleLength
*
* argument title string - The title to transform.
*
* return string - The transformed title.
*/
titleTransform: function(title) {
for (var needle in this.config.titleReplace) {
var replacement = this.config.titleReplace[needle];
title = title.replace(needle, replacement);
}
title = this.shorten(title, this.config.maxTitleLength);
return title;
}
});