2016-03-31 11:05:32 +02:00
|
|
|
/* global Module */
|
|
|
|
|
|
|
|
/* Magic Mirror
|
|
|
|
* Module: Calendar
|
|
|
|
*
|
|
|
|
* By Michael Teeuw http://michaelteeuw.nl
|
|
|
|
* MIT Licensed.
|
|
|
|
*/
|
|
|
|
|
2016-10-14 15:23:03 +02:00
|
|
|
Module.register("calendar", {
|
2016-03-31 11:05:32 +02:00
|
|
|
|
|
|
|
// Define module defaults
|
|
|
|
defaults: {
|
|
|
|
maximumEntries: 10, // Total Maximum Entries
|
2016-04-03 19:52:13 +02:00
|
|
|
maximumNumberOfDays: 365,
|
2016-03-31 11:05:32 +02:00
|
|
|
displaySymbol: true,
|
2016-05-10 11:58:05 -06:00
|
|
|
defaultSymbol: "calendar", // Fontawesome Symbol see http://fontawesome.io/cheatsheet/
|
2016-04-26 22:34:12 +02:00
|
|
|
displayRepeatingCountTitle: false,
|
2016-10-14 15:23:03 +02:00
|
|
|
defaultRepeatingCountTitle: "",
|
2016-04-03 19:52:13 +02:00
|
|
|
maxTitleLength: 25,
|
2017-04-02 15:06:58 -05:00
|
|
|
wrapEvents: false, // wrap events to multiple lines breaking at maxTitleLength
|
2016-03-31 11:05:32 +02:00
|
|
|
fetchInterval: 5 * 60 * 1000, // Update every 5 minutes.
|
|
|
|
animationSpeed: 2000,
|
2016-04-03 19:52:13 +02:00
|
|
|
fade: true,
|
2016-05-10 01:01:00 -06:00
|
|
|
urgency: 7,
|
|
|
|
timeFormat: "relative",
|
2016-11-10 17:26:29 +01:00
|
|
|
dateFormat: "MMM Do",
|
2017-05-02 21:20:35 +02:00
|
|
|
fullDayEventDateFormat: "MMM Do",
|
2016-09-04 00:05:02 +02:00
|
|
|
getRelative: 6,
|
2016-03-31 11:05:32 +02:00
|
|
|
fadePoint: 0.25, // Start on 1/4th of the list.
|
2016-11-30 21:24:04 +01:00
|
|
|
hidePrivate: false,
|
2017-01-29 00:59:38 +01:00
|
|
|
colored: false,
|
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-06-06 12:05:41 +02:00
|
|
|
"De verjaardag van ": "",
|
|
|
|
"'s birthday": ""
|
2016-04-05 10:01:54 +02:00
|
|
|
},
|
2017-03-12 11:36:40 -05:00
|
|
|
broadcastEvents: true,
|
2017-03-12 20:22:40 -05:00
|
|
|
excludedEvents: []
|
2016-03-31 11:05:32 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
// Define required scripts.
|
2016-10-14 15:23:03 +02:00
|
|
|
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.
|
2016-10-14 15:23:03 +02:00
|
|
|
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.
|
2016-10-14 15:23:03 +02:00
|
|
|
getTranslations: function () {
|
2017-03-30 22:14:11 +02:00
|
|
|
// The translations for the default modules are defined in the core translation files.
|
|
|
|
// Therefor we can just return false. Otherwise we should have returned a dictionary.
|
2016-06-04 20:32:55 -06:00
|
|
|
// If you're trying to build your own module including translations, check out the documentation.
|
2016-05-11 12:38:41 +02:00
|
|
|
return false;
|
2016-04-21 01:04:00 +02:00
|
|
|
},
|
|
|
|
|
2016-03-31 11:05:32 +02:00
|
|
|
// Override start method.
|
2016-10-14 15:23:03 +02:00
|
|
|
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);
|
|
|
|
|
2017-06-26 13:03:03 +02:00
|
|
|
switch (config.timeFormat) {
|
|
|
|
case 12: {
|
|
|
|
moment.updateLocale(config.language, {
|
|
|
|
longDateFormat: {
|
|
|
|
LT: "h:mm A"
|
|
|
|
}
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 24: {
|
|
|
|
moment.updateLocale(config.language, {
|
|
|
|
longDateFormat: {
|
2017-07-09 11:45:57 +02:00
|
|
|
LT: "HH:mm"
|
2017-06-26 13:03:03 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// If config.timeFormat was not given (or has invalid format) default to locale default
|
|
|
|
default: {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-31 11:05:32 +02:00
|
|
|
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://");
|
2017-01-30 16:26:42 -06:00
|
|
|
|
|
|
|
var calendarConfig = {
|
|
|
|
maximumEntries: calendar.maximumEntries,
|
2017-03-07 00:12:43 +01:00
|
|
|
maximumNumberOfDays: calendar.maximumNumberOfDays
|
2017-01-30 16:26:42 -06:00
|
|
|
};
|
|
|
|
|
2017-03-07 00:12:43 +01:00
|
|
|
// we check user and password here for backwards compatibility with old configs
|
|
|
|
if(calendar.user && calendar.pass){
|
|
|
|
calendar.auth = {
|
|
|
|
user: calendar.user,
|
|
|
|
pass: calendar.pass
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.addCalendar(calendar.url, calendar.auth, calendarConfig);
|
2016-03-31 11:05:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
this.calendarData = {};
|
2016-04-05 10:01:54 +02:00
|
|
|
this.loaded = false;
|
2016-03-31 11:05:32 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
// Override socket notification handler.
|
2016-10-14 15:23:03 +02:00
|
|
|
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;
|
2016-04-05 10:01:54 +02:00
|
|
|
this.loaded = true;
|
2016-10-14 15:23:03 +02:00
|
|
|
|
|
|
|
if (this.config.broadcastEvents) {
|
|
|
|
this.broadcastEvents();
|
|
|
|
}
|
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.
|
2016-10-14 15:23:03 +02:00
|
|
|
getDom: function () {
|
2016-03-31 11:05:32 +02:00
|
|
|
|
|
|
|
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");
|
2017-01-28 18:21:02 +01:00
|
|
|
|
2017-01-29 00:59:38 +01:00
|
|
|
if (this.config.colored) {
|
|
|
|
eventWrapper.style.cssText = "color:" + this.colorForUrl(event.url);
|
|
|
|
}
|
2017-01-28 18:21:02 +01:00
|
|
|
|
2016-03-31 11:05:32 +02:00
|
|
|
eventWrapper.className = "normal";
|
|
|
|
|
|
|
|
if (this.config.displaySymbol) {
|
2016-10-14 15:23:03 +02:00
|
|
|
var symbolWrapper = document.createElement("td");
|
2017-03-16 16:57:55 +01:00
|
|
|
symbolWrapper.className = "symbol align-right";
|
|
|
|
var symbols = this.symbolsForUrl(event.url);
|
|
|
|
if(typeof symbols === "string") {
|
|
|
|
symbols = [symbols];
|
|
|
|
}
|
|
|
|
|
|
|
|
for(var i = 0; i < symbols.length; i++) {
|
|
|
|
var symbol = document.createElement("span");
|
|
|
|
symbol.className = "fa fa-" + symbols[i];
|
|
|
|
if(i > 0){
|
|
|
|
symbol.style.paddingLeft = "5px";
|
|
|
|
}
|
|
|
|
symbolWrapper.appendChild(symbol);
|
|
|
|
}
|
2016-03-31 11:05:32 +02:00
|
|
|
eventWrapper.appendChild(symbolWrapper);
|
|
|
|
}
|
|
|
|
|
2016-04-26 22:34:12 +02:00
|
|
|
var titleWrapper = document.createElement("td"),
|
2016-10-14 15:23:03 +02:00
|
|
|
repeatingCountTitle = "";
|
2016-05-11 12:38:41 +02:00
|
|
|
|
|
|
|
if (this.config.displayRepeatingCountTitle) {
|
|
|
|
|
2016-05-03 11:56:24 +02:00
|
|
|
repeatingCountTitle = this.countTitleForUrl(event.url);
|
2016-05-11 12:38:41 +02:00
|
|
|
|
2016-10-14 15:23:03 +02:00
|
|
|
if (repeatingCountTitle !== "") {
|
2016-12-29 15:31:01 +01:00
|
|
|
var thisYear = new Date(parseInt(event.startDate)).getFullYear(),
|
2016-04-26 22:34:12 +02:00
|
|
|
yearDiff = thisYear - event.firstYear;
|
2016-05-11 12:38:41 +02:00
|
|
|
|
2016-10-14 15:23:03 +02:00
|
|
|
repeatingCountTitle = ", " + yearDiff + ". " + repeatingCountTitle;
|
2016-04-26 22:34:12 +02:00
|
|
|
}
|
2016-05-11 12:38:41 +02:00
|
|
|
}
|
|
|
|
|
2016-04-26 22:34:12 +02:00
|
|
|
titleWrapper.innerHTML = this.titleTransform(event.title) + repeatingCountTitle;
|
2017-01-28 18:21:02 +01:00
|
|
|
|
2017-01-29 00:59:38 +01:00
|
|
|
if (!this.config.colored) {
|
|
|
|
titleWrapper.className = "title bright";
|
|
|
|
} else {
|
|
|
|
titleWrapper.className = "title";
|
|
|
|
}
|
2017-01-28 18:21:02 +01:00
|
|
|
|
2016-03-31 11:05:32 +02:00
|
|
|
eventWrapper.appendChild(titleWrapper);
|
|
|
|
|
2016-10-14 15:23:03 +02:00
|
|
|
var timeWrapper = document.createElement("td");
|
2016-04-15 12:50:34 +02:00
|
|
|
//console.log(event.today);
|
2016-04-20 21:40:56 +02:00
|
|
|
var now = new Date();
|
2016-05-10 11:58:05 -06:00
|
|
|
// Define second, minute, hour, and day variables
|
2016-10-14 15:23:03 +02:00
|
|
|
var oneSecond = 1000; // 1,000 milliseconds
|
|
|
|
var oneMinute = oneSecond * 60;
|
|
|
|
var oneHour = oneMinute * 60;
|
|
|
|
var oneDay = oneHour * 24;
|
2016-04-15 12:50:34 +02:00
|
|
|
if (event.fullDayEvent) {
|
2016-04-20 21:40:56 +02:00
|
|
|
if (event.today) {
|
2016-09-03 00:39:46 +02:00
|
|
|
timeWrapper.innerHTML = this.capFirst(this.translate("TODAY"));
|
2016-10-14 15:23:03 +02:00
|
|
|
} else if (event.startDate - now < oneDay && event.startDate - now > 0) {
|
2016-09-03 00:39:46 +02:00
|
|
|
timeWrapper.innerHTML = this.capFirst(this.translate("TOMORROW"));
|
2016-10-14 15:23:03 +02:00
|
|
|
} else if (event.startDate - now < 2 * oneDay && event.startDate - now > 0) {
|
|
|
|
if (this.translate("DAYAFTERTOMORROW") !== "DAYAFTERTOMORROW") {
|
|
|
|
timeWrapper.innerHTML = this.capFirst(this.translate("DAYAFTERTOMORROW"));
|
2016-08-31 14:39:37 +02:00
|
|
|
} else {
|
2016-10-14 15:23:03 +02:00
|
|
|
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow());
|
2016-08-31 14:39:37 +02:00
|
|
|
}
|
2016-04-20 21:40:56 +02:00
|
|
|
} else {
|
2016-05-10 11:58:05 -06:00
|
|
|
/* Check to see if the user displays absolute or relative dates with their events
|
|
|
|
* Also check to see if an event is happening within an 'urgency' time frameElement
|
|
|
|
* For example, if the user set an .urgency of 7 days, those events that fall within that
|
|
|
|
* time frame will be displayed with 'in xxx' time format or moment.fromNow()
|
|
|
|
*
|
|
|
|
* Note: this needs to be put in its own function, as the whole thing repeats again verbatim
|
|
|
|
*/
|
2016-05-10 01:01:00 -06:00
|
|
|
if (this.config.timeFormat === "absolute") {
|
2016-10-14 15:23:03 +02:00
|
|
|
if ((this.config.urgency > 1) && (event.startDate - now < (this.config.urgency * oneDay))) {
|
2016-05-10 11:58:05 -06:00
|
|
|
// This event falls within the config.urgency period that the user has set
|
2016-09-03 00:39:46 +02:00
|
|
|
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow());
|
2016-05-10 01:01:00 -06:00
|
|
|
} else {
|
2017-04-28 23:31:07 +02:00
|
|
|
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").format(this.config.fullDayEventDateFormat));
|
2016-05-10 01:01:00 -06:00
|
|
|
}
|
|
|
|
} else {
|
2016-10-14 15:23:03 +02:00
|
|
|
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow());
|
2016-05-10 01:01:00 -06:00
|
|
|
}
|
2016-04-20 21:40:56 +02:00
|
|
|
}
|
2016-04-15 12:50:34 +02:00
|
|
|
} else {
|
2016-04-15 13:13:06 +02:00
|
|
|
if (event.startDate >= new Date()) {
|
2016-10-14 15:23:03 +02:00
|
|
|
if (event.startDate - now < 2 * oneDay) {
|
2016-05-10 01:01:00 -06:00
|
|
|
// This event is within the next 48 hours (2 days)
|
2016-10-14 15:23:03 +02:00
|
|
|
if (event.startDate - now < this.config.getRelative * oneHour) {
|
2016-05-10 11:58:05 -06:00
|
|
|
// If event is within 6 hour, display 'in xxx' time format or moment.fromNow()
|
2016-09-03 00:39:46 +02:00
|
|
|
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow());
|
2016-05-10 01:01:00 -06:00
|
|
|
} else {
|
|
|
|
// Otherwise just say 'Today/Tomorrow at such-n-such time'
|
2016-09-03 00:39:46 +02:00
|
|
|
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").calendar());
|
2016-05-10 01:01:00 -06:00
|
|
|
}
|
2016-04-19 10:34:14 +02:00
|
|
|
} else {
|
2016-05-10 11:58:05 -06:00
|
|
|
/* Check to see if the user displays absolute or relative dates with their events
|
|
|
|
* Also check to see if an event is happening within an 'urgency' time frameElement
|
|
|
|
* For example, if the user set an .urgency of 7 days, those events that fall within that
|
|
|
|
* time frame will be displayed with 'in xxx' time format or moment.fromNow()
|
|
|
|
*
|
|
|
|
* Note: this needs to be put in its own function, as the whole thing repeats again verbatim
|
|
|
|
*/
|
2016-05-10 01:01:00 -06:00
|
|
|
if (this.config.timeFormat === "absolute") {
|
2016-10-14 15:23:03 +02:00
|
|
|
if ((this.config.urgency > 1) && (event.startDate - now < (this.config.urgency * oneDay))) {
|
2016-05-10 11:58:05 -06:00
|
|
|
// This event falls within the config.urgency period that the user has set
|
2016-09-03 00:39:46 +02:00
|
|
|
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow());
|
2016-05-10 01:01:00 -06:00
|
|
|
} else {
|
2016-11-10 17:26:29 +01:00
|
|
|
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").format(this.config.dateFormat));
|
2016-05-10 01:01:00 -06:00
|
|
|
}
|
|
|
|
} else {
|
2016-09-03 00:39:46 +02:00
|
|
|
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow());
|
2016-05-10 01:01:00 -06:00
|
|
|
}
|
2016-04-19 10:34:14 +02:00
|
|
|
}
|
2016-04-15 13:13:06 +02:00
|
|
|
} else {
|
2017-04-25 23:15:34 +03:00
|
|
|
timeWrapper.innerHTML = this.capFirst(
|
|
|
|
this.translate("RUNNING", {
|
|
|
|
fallback: this.translate("RUNNING") + " {timeUntilEnd}",
|
|
|
|
timeUntilEnd: moment(event.endDate, "x").fromNow(true)
|
|
|
|
})
|
|
|
|
);
|
2016-04-15 13:13:06 +02:00
|
|
|
}
|
2016-04-15 12:50:34 +02:00
|
|
|
}
|
2016-04-23 17:40:44 +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.
|
|
|
|
*
|
2017-02-11 19:34:43 -03:00
|
|
|
* argument url string - Url to look for.
|
2016-03-31 11:05:32 +02:00
|
|
|
*
|
|
|
|
* return bool - Has calendar url
|
|
|
|
*/
|
2016-10-14 15:23:03 +02:00
|
|
|
hasCalendarURL: function (url) {
|
2016-03-31 11:05:32 +02:00
|
|
|
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.
|
|
|
|
*/
|
2016-10-14 15:23:03 +02:00
|
|
|
createEventList: function () {
|
2016-03-31 11:05:32 +02:00
|
|
|
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];
|
2016-11-30 21:09:57 +01:00
|
|
|
if(this.config.hidePrivate) {
|
|
|
|
if(event.class === "PRIVATE") {
|
2017-01-29 00:59:38 +01:00
|
|
|
// do not add the current event, skip it
|
|
|
|
continue;
|
2016-11-30 21:09:57 +01:00
|
|
|
}
|
|
|
|
}
|
2016-03-31 11:05:32 +02:00
|
|
|
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-10-14 15:23:03 +02:00
|
|
|
events.sort(function (a, b) {
|
2016-03-31 11:05:32 +02:00
|
|
|
return a.startDate - b.startDate;
|
|
|
|
});
|
|
|
|
|
2017-07-28 21:07:38 +02:00
|
|
|
return events;
|
2016-03-31 11:05:32 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
/* createEventList(url)
|
|
|
|
* Requests node helper to add calendar url.
|
|
|
|
*
|
2017-02-11 19:34:43 -03:00
|
|
|
* argument url string - Url to add.
|
2016-03-31 11:05:32 +02:00
|
|
|
*/
|
2017-03-07 00:12:43 +01:00
|
|
|
addCalendar: function (url, auth, calendarConfig) {
|
2016-04-05 14:35:11 -04:00
|
|
|
this.sendSocketNotification("ADD_CALENDAR", {
|
2016-03-31 11:05:32 +02:00
|
|
|
url: url,
|
2017-07-27 17:59:23 +02:00
|
|
|
excludedEvents: calendarConfig.excludedEvents || this.config.excludedEvents,
|
2017-01-30 16:26:42 -06:00
|
|
|
maximumEntries: calendarConfig.maximumEntries || this.config.maximumEntries,
|
|
|
|
maximumNumberOfDays: calendarConfig.maximumNumberOfDays || this.config.maximumNumberOfDays,
|
2016-09-08 17:36:30 +02:00
|
|
|
fetchInterval: this.config.fetchInterval,
|
2017-03-07 00:12:43 +01:00
|
|
|
auth: auth
|
2016-03-31 11:05:32 +02:00
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2017-03-16 16:57:55 +01:00
|
|
|
/* symbolsForUrl(url)
|
|
|
|
* Retrieves the symbols for a specific url.
|
2016-03-31 11:05:32 +02:00
|
|
|
*
|
2017-02-07 23:51:13 +01:00
|
|
|
* argument url string - Url to look for.
|
2016-03-31 11:05:32 +02:00
|
|
|
*
|
2017-03-16 16:57:55 +01:00
|
|
|
* return string/array - The Symbols
|
2016-03-31 11:05:32 +02:00
|
|
|
*/
|
2017-03-16 16:57:55 +01:00
|
|
|
symbolsForUrl: function (url) {
|
2017-02-08 00:05:28 +01:00
|
|
|
return this.getCalendarProperty(url, "symbol", this.config.defaultSymbol);
|
2016-03-31 11:05:32 +02:00
|
|
|
},
|
2017-01-28 18:21:02 +01:00
|
|
|
|
2017-01-29 00:59:38 +01:00
|
|
|
/* colorForUrl(url)
|
2017-01-28 18:21:02 +01:00
|
|
|
* Retrieves the color for a specific url.
|
|
|
|
*
|
2017-02-07 23:51:13 +01:00
|
|
|
* argument url string - Url to look for.
|
2017-01-28 18:21:02 +01:00
|
|
|
*
|
|
|
|
* return string - The Color
|
|
|
|
*/
|
|
|
|
colorForUrl: function (url) {
|
2017-02-08 00:05:28 +01:00
|
|
|
return this.getCalendarProperty(url, "color", "#fff");
|
2017-01-28 18:21:02 +01:00
|
|
|
},
|
2017-02-07 23:51:13 +01:00
|
|
|
|
2016-04-26 22:34:12 +02:00
|
|
|
/* countTitleForUrl(url)
|
|
|
|
* Retrieves the name for a specific url.
|
|
|
|
*
|
2017-02-07 23:51:13 +01:00
|
|
|
* argument url string - Url to look for.
|
2016-04-26 22:34:12 +02:00
|
|
|
*
|
|
|
|
* return string - The Symbol
|
|
|
|
*/
|
2016-10-14 15:23:03 +02:00
|
|
|
countTitleForUrl: function (url) {
|
2017-02-07 23:51:13 +01:00
|
|
|
return this.getCalendarProperty(url, "repeatingCountTitle", this.config.defaultRepeatingCountTitle);
|
|
|
|
},
|
2016-04-26 22:34:12 +02:00
|
|
|
|
2017-02-07 23:51:13 +01:00
|
|
|
/* getCalendarProperty(url, property, defaultValue)
|
|
|
|
* Helper method to retrieve the property for a specific url.
|
|
|
|
*
|
|
|
|
* argument url string - Url to look for.
|
|
|
|
* argument property string - Property to look for.
|
|
|
|
* argument defaultValue string - Value if property is not found.
|
|
|
|
*
|
|
|
|
* return string - The Property
|
|
|
|
*/
|
|
|
|
getCalendarProperty: function (url, property, defaultValue) {
|
2017-02-08 00:05:28 +01:00
|
|
|
for (var c in this.config.calendars) {
|
|
|
|
var calendar = this.config.calendars[c];
|
2017-03-16 16:57:55 +01:00
|
|
|
if (calendar.url === url && calendar.hasOwnProperty(property)) {
|
2017-02-08 00:05:28 +01:00
|
|
|
return calendar[property];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return defaultValue;
|
2016-04-26 22:34:12 +02:00
|
|
|
},
|
2016-03-31 11:05:32 +02:00
|
|
|
|
2017-07-29 16:02:53 +02:00
|
|
|
/**
|
|
|
|
* Shortens a string if it's longer than maxLength and add a ellipsis to the end
|
|
|
|
*
|
|
|
|
* @param {string} string Text string to shorten
|
|
|
|
* @param {number} maxLength The max length of the string
|
|
|
|
* @param {boolean} wrapEvents Wrap the text after the line has reached maxLength
|
|
|
|
* @returns {string} The shortened string
|
2016-03-31 11:05:32 +02:00
|
|
|
*/
|
2017-04-02 15:06:58 -05:00
|
|
|
shorten: function (string, maxLength, wrapEvents) {
|
2017-07-29 16:02:53 +02:00
|
|
|
if (typeof string !== "string") {
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wrapEvents === true) {
|
2017-04-02 15:06:58 -05:00
|
|
|
var temp = "";
|
|
|
|
var currentLine = "";
|
|
|
|
var words = string.split(" ");
|
|
|
|
|
|
|
|
for (var i = 0; i < words.length; i++) {
|
|
|
|
var word = words[i];
|
2017-07-29 16:02:53 +02:00
|
|
|
if (currentLine.length + word.length < (typeof maxLength === "number" ? maxLength : 25) - 1) { // max - 1 to account for a space
|
2017-04-02 15:06:58 -05:00
|
|
|
currentLine += (word + " ");
|
|
|
|
} else {
|
|
|
|
if (currentLine.length > 0) {
|
|
|
|
temp += (currentLine + "<br>" + word + " ");
|
|
|
|
} else {
|
|
|
|
temp += (word + "<br>");
|
|
|
|
}
|
|
|
|
currentLine = "";
|
|
|
|
}
|
|
|
|
}
|
2016-03-31 11:05:32 +02:00
|
|
|
|
2017-07-29 16:02:53 +02:00
|
|
|
return (temp + currentLine).trim();
|
2017-04-02 15:06:58 -05:00
|
|
|
} else {
|
2017-07-29 16:02:53 +02:00
|
|
|
if (maxLength && typeof maxLength === "number" && string.length > maxLength) {
|
|
|
|
return string.trim().slice(0, maxLength) + "…";
|
2017-04-02 15:06:58 -05:00
|
|
|
} else {
|
2017-07-29 16:02:53 +02:00
|
|
|
return string.trim();
|
2017-04-02 15:06:58 -05:00
|
|
|
}
|
|
|
|
}
|
2016-03-31 11:05:32 +02:00
|
|
|
},
|
|
|
|
|
2016-09-03 00:39:46 +02:00
|
|
|
/* capFirst(string)
|
|
|
|
* Capitalize the first letter of a string
|
2017-01-16 02:27:12 +01:00
|
|
|
* Return capitalized string
|
2016-09-03 00:39:46 +02:00
|
|
|
*/
|
2016-10-14 15:23:03 +02:00
|
|
|
|
|
|
|
capFirst: function (string) {
|
2016-09-03 00:39:46 +02:00
|
|
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
|
|
},
|
|
|
|
|
2016-03-31 11:05:32 +02:00
|
|
|
/* titleTransform(title)
|
|
|
|
* Transforms the title of an event for usage.
|
|
|
|
* Replaces parts of the text as defined in config.titleReplace.
|
2017-04-02 15:06:58 -05:00
|
|
|
* Shortens title based on config.maxTitleLength and config.wrapEvents
|
2016-03-31 11:05:32 +02:00
|
|
|
*
|
|
|
|
* argument title string - The title to transform.
|
|
|
|
*
|
|
|
|
* return string - The transformed title.
|
|
|
|
*/
|
2016-10-14 15:23:03 +02:00
|
|
|
titleTransform: function (title) {
|
2016-03-31 11:05:32 +02:00
|
|
|
for (var needle in this.config.titleReplace) {
|
|
|
|
var replacement = this.config.titleReplace[needle];
|
2017-01-16 02:49:08 +01:00
|
|
|
|
|
|
|
var regParts = needle.match(/^\/(.+)\/([gim]*)$/);
|
|
|
|
if (regParts) {
|
2017-01-16 02:52:50 +01:00
|
|
|
// the parsed pattern is a regexp.
|
2017-01-16 02:49:08 +01:00
|
|
|
needle = new RegExp(regParts[1], regParts[2]);
|
|
|
|
}
|
|
|
|
|
2016-03-31 11:05:32 +02:00
|
|
|
title = title.replace(needle, replacement);
|
|
|
|
}
|
|
|
|
|
2017-04-02 15:06:58 -05:00
|
|
|
title = this.shorten(title, this.config.maxTitleLength, this.config.wrapEvents);
|
2016-03-31 11:05:32 +02:00
|
|
|
return title;
|
2016-10-14 15:23:03 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
/* broadcastEvents()
|
|
|
|
* Broadcasts the events to all other modules for reuse.
|
2016-12-30 17:47:33 -03:00
|
|
|
* The all events available in one array, sorted on startdate.
|
2016-10-14 15:23:03 +02:00
|
|
|
*/
|
|
|
|
broadcastEvents: function () {
|
|
|
|
var eventList = [];
|
2017-06-11 11:53:55 +02:00
|
|
|
for (var url in this.calendarData) {
|
2016-10-14 15:23:03 +02:00
|
|
|
var calendar = this.calendarData[url];
|
2017-06-11 11:53:55 +02:00
|
|
|
for (var e in calendar) {
|
2016-10-14 15:23:03 +02:00
|
|
|
var event = cloneObject(calendar[e]);
|
2017-07-06 11:57:16 +02:00
|
|
|
event.symbol = this.symbolsForUrl(url);
|
|
|
|
event.color = this.colorForUrl(url);
|
2016-10-14 15:23:03 +02:00
|
|
|
delete event.url;
|
|
|
|
eventList.push(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
eventList.sort(function(a,b) {
|
|
|
|
return a.startDate - b.startDate;
|
|
|
|
});
|
|
|
|
|
|
|
|
this.sendNotification("CALENDAR_EVENTS", eventList);
|
|
|
|
|
2016-03-31 11:05:32 +02:00
|
|
|
}
|
2016-04-03 19:52:13 +02:00
|
|
|
});
|