diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e3413bb..efdd1aac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Module API: Add Visibility locking to module system. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#visibility-locking) for more information. - Module API: Method to overwrite the module's header. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#getheader) for more information. - Module API: Option to define the minimumn MagicMirror version to run a module. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#requiresversion) for more information. +- Calendar module now broadcasts the event list to all other modules using the notification system. [See documentation](https://github.com/MichMich/MagicMirror/tree/master/modules/default/calendar) for more information. ### Updated - Modified translations for Frysk. diff --git a/js/class.js b/js/class.js index 2b011b29..01a92603 100644 --- a/js/class.js +++ b/js/class.js @@ -11,24 +11,6 @@ // The base Class implementation (does nothing) this.Class = function() {}; - //Define the clone method for later use. - function cloneObject(obj) { - if (obj === null || typeof obj !== "object") { - return obj; - } - - var temp = obj.constructor(); // give temp the original obj's constructor - for (var key in obj) { - temp[key] = cloneObject(obj[key]); - - if (key === "lockStrings") { - Log.log(key); - } - } - - return temp; - } - // Create a new Class that inherits from this class Class.extend = function(prop) { var _super = this.prototype; @@ -87,5 +69,24 @@ }; })(); +//Define the clone method for later use. +//Helper Method +function cloneObject(obj) { + if (obj === null || typeof obj !== "object") { + return obj; + } + + var temp = obj.constructor(); // give temp the original obj's constructor + for (var key in obj) { + temp[key] = cloneObject(obj[key]); + + if (key === "lockStrings") { + Log.log(key); + } + } + + return temp; +} + /*************** DO NOT EDIT THE LINE BELOW ***************/ if (typeof module !== "undefined") {module.exports = Class;} diff --git a/js/module.js b/js/module.js index 17ca9595..397d4799 100644 --- a/js/module.js +++ b/js/module.js @@ -371,20 +371,6 @@ Module.create = function (name) { return; } - //Define the clone method for later use. - function cloneObject(obj) { - if (obj === null || typeof obj !== "object") { - return obj; - } - - var temp = obj.constructor(); // give temp the original obj's constructor - for (var key in obj) { - temp[key] = cloneObject(obj[key]); - } - - return temp; - } - var moduleDefinition = Module.definitions[name]; var clonedDefinition = cloneObject(moduleDefinition); diff --git a/modules/default/calendar/README.md b/modules/default/calendar/README.md index fc553095..54d318ce 100644 --- a/modules/default/calendar/README.md +++ b/modules/default/calendar/README.md @@ -106,7 +106,6 @@ The following properties can be configured: titleReplace An object of textual replacements applied to the tile of the event. This allow to remove or replace certains words in the title.

Example:
- titleReplace: {'Birthday of ' : '', 'foo':'bar'} @@ -141,6 +140,13 @@ The following properties can be configured:
Default value: 0 (disabled) + + broadcastEvents + If this property is set to true, the calendar will broadcast all the events to all other modules with the notification message: CALENDAR_EVENTS. The event objects are stored in an array and contain the following fields: title, startDate, endDate, fullDayEvent, location and geo.
+
Possible values: true, false
+
Default value: true + + diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index c2a2c851..39ea6b58 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -7,7 +7,7 @@ * MIT Licensed. */ -Module.register("calendar",{ +Module.register("calendar", { // Define module defaults defaults: { @@ -16,7 +16,7 @@ Module.register("calendar",{ displaySymbol: true, defaultSymbol: "calendar", // Fontawesome Symbol see http://fontawesome.io/cheatsheet/ displayRepeatingCountTitle: false, - defaultRepeatingCountTitle: '', + defaultRepeatingCountTitle: "", maxTitleLength: 25, fetchInterval: 5 * 60 * 1000, // Update every 5 minutes. animationSpeed: 2000, @@ -35,20 +35,21 @@ Module.register("calendar",{ "De verjaardag van ": "", "'s birthday": "" }, + broadcastEvents: true }, // Define required scripts. - getStyles: function() { + getStyles: function () { return ["calendar.css", "font-awesome.css"]; }, // Define required scripts. - getScripts: function() { + getScripts: function () { return ["moment.js"]; }, // Define required translations. - getTranslations: function() { + getTranslations: function () { // The translations for the defaut modules are defined in the core translation files. // Therefor we can just return false. Otherwise we should have returned a dictionairy. // If you're trying to build your own module including translations, check out the documentation. @@ -56,7 +57,7 @@ Module.register("calendar",{ }, // Override start method. - start: function() { + start: function () { Log.log("Starting module: " + this.name); // Set locale. @@ -73,11 +74,15 @@ Module.register("calendar",{ }, // Override socket notification handler. - socketNotificationReceived: function(notification, payload) { + socketNotificationReceived: function (notification, payload) { if (notification === "CALENDAR_EVENTS") { if (this.hasCalendarURL(payload.url)) { this.calendarData[payload.url] = payload.events; this.loaded = true; + + if (this.config.broadcastEvents) { + this.broadcastEvents(); + } } } else if (notification === "FETCH_ERROR") { Log.error("Calendar Error. Could not fetch calendar: " + payload.url); @@ -91,7 +96,7 @@ Module.register("calendar",{ }, // Override dom generator. - getDom: function() { + getDom: function () { var events = this.createEventList(); var wrapper = document.createElement("table"); @@ -110,27 +115,27 @@ Module.register("calendar",{ eventWrapper.className = "normal"; if (this.config.displaySymbol) { - var symbolWrapper = document.createElement("td"); + var symbolWrapper = document.createElement("td"); symbolWrapper.className = "symbol"; - var symbol = document.createElement("span"); + 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 = ''; + repeatingCountTitle = ""; if (this.config.displayRepeatingCountTitle) { repeatingCountTitle = this.countTitleForUrl(event.url); - if(repeatingCountTitle !== '') { + if (repeatingCountTitle !== "") { var thisYear = new Date().getFullYear(), yearDiff = thisYear - event.firstYear; - repeatingCountTitle = ', '+ yearDiff + '. ' + repeatingCountTitle; + repeatingCountTitle = ", " + yearDiff + ". " + repeatingCountTitle; } } @@ -138,24 +143,24 @@ Module.register("calendar",{ titleWrapper.className = "title bright"; eventWrapper.appendChild(titleWrapper); - var timeWrapper = document.createElement("td"); + var timeWrapper = document.createElement("td"); //console.log(event.today); var now = new Date(); // Define second, minute, hour, and day variables - var one_second = 1000; // 1,000 milliseconds - var one_minute = one_second * 60; - var one_hour = one_minute * 60; - var one_day = one_hour * 24; + var oneSecond = 1000; // 1,000 milliseconds + var oneMinute = oneSecond * 60; + var oneHour = oneMinute * 60; + var oneDay = oneHour * 24; if (event.fullDayEvent) { if (event.today) { timeWrapper.innerHTML = this.capFirst(this.translate("TODAY")); - } else if (event.startDate - now < one_day && event.startDate - now > 0) { + } else if (event.startDate - now < oneDay && event.startDate - now > 0) { timeWrapper.innerHTML = this.capFirst(this.translate("TOMORROW")); - } else if (event.startDate - now < 2*one_day && event.startDate - now > 0) { - if (this.translate('DAYAFTERTOMORROW') !== 'DAYAFTERTOMORROW') { - timeWrapper.innerHTML = this.capFirst(this.translate("DAYAFTERTOMORROW")); + } else if (event.startDate - now < 2 * oneDay && event.startDate - now > 0) { + if (this.translate("DAYAFTERTOMORROW") !== "DAYAFTERTOMORROW") { + timeWrapper.innerHTML = this.capFirst(this.translate("DAYAFTERTOMORROW")); } else { - timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); + timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); } } else { /* Check to see if the user displays absolute or relative dates with their events @@ -166,21 +171,21 @@ Module.register("calendar",{ * Note: this needs to be put in its own function, as the whole thing repeats again verbatim */ if (this.config.timeFormat === "absolute") { - if ((this.config.urgency > 1) && (event.startDate - now < (this.config.urgency * one_day))) { + if ((this.config.urgency > 1) && (event.startDate - now < (this.config.urgency * oneDay))) { // This event falls within the config.urgency period that the user has set timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); } else { timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").format("MMM Do")); } } else { - timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); + timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); } } } else { if (event.startDate >= new Date()) { - if (event.startDate - now < 2 * one_day) { + if (event.startDate - now < 2 * oneDay) { // This event is within the next 48 hours (2 days) - if (event.startDate - now < this.config.getRelative * one_hour) { + if (event.startDate - now < this.config.getRelative * oneHour) { // If event is within 6 hour, display 'in xxx' time format or moment.fromNow() timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); } else { @@ -196,7 +201,7 @@ Module.register("calendar",{ * Note: this needs to be put in its own function, as the whole thing repeats again verbatim */ if (this.config.timeFormat === "absolute") { - if ((this.config.urgency > 1) && (event.startDate - now < (this.config.urgency * one_day))) { + if ((this.config.urgency > 1) && (event.startDate - now < (this.config.urgency * oneDay))) { // This event falls within the config.urgency period that the user has set timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow()); } else { @@ -207,7 +212,7 @@ Module.register("calendar",{ } } } else { - timeWrapper.innerHTML = this.capFirst(this.translate("RUNNING")) + ' ' + moment(event.endDate,"x").fromNow(true); + timeWrapper.innerHTML = this.capFirst(this.translate("RUNNING")) + " " + moment(event.endDate, "x").fromNow(true); } } //timeWrapper.innerHTML += ' - '+ moment(event.startDate,'x').format('lll'); @@ -241,7 +246,7 @@ Module.register("calendar",{ * * return bool - Has calendar url */ - hasCalendarURL: function(url) { + hasCalendarURL: function (url) { for (var c in this.config.calendars) { var calendar = this.config.calendars[c]; if (calendar.url === url) { @@ -257,7 +262,7 @@ Module.register("calendar",{ * * return array - Array with events. */ - createEventList: function() { + createEventList: function () { var events = []; var today = moment().startOf("day"); for (var c in this.calendarData) { @@ -270,7 +275,7 @@ Module.register("calendar",{ } } - events.sort(function(a, b) { + events.sort(function (a, b) { return a.startDate - b.startDate; }); @@ -282,7 +287,7 @@ Module.register("calendar",{ * * argument url sting - Url to add. */ - addCalendar: function(url, user, pass) { + addCalendar: function (url, user, pass) { this.sendSocketNotification("ADD_CALENDAR", { url: url, maximumEntries: this.config.maximumEntries, @@ -300,10 +305,10 @@ Module.register("calendar",{ * * return string - The Symbol */ - symbolForUrl: function(url) { + symbolForUrl: function (url) { for (var c in this.config.calendars) { var calendar = this.config.calendars[c]; - if (calendar.url === url && typeof calendar.symbol === "string") { + if (calendar.url === url && typeof calendar.symbol === "string") { return calendar.symbol; } } @@ -317,10 +322,10 @@ Module.register("calendar",{ * * return string - The Symbol */ - countTitleForUrl: function(url) { + countTitleForUrl: function (url) { for (var c in this.config.calendars) { var calendar = this.config.calendars[c]; - if (calendar.url === url && typeof calendar.repeatingCountTitle === "string") { + if (calendar.url === url && typeof calendar.repeatingCountTitle === "string") { return calendar.repeatingCountTitle; } } @@ -337,9 +342,9 @@ Module.register("calendar",{ * * return string - The shortened string. */ - shorten: function(string, maxLength) { + shorten: function (string, maxLength) { if (string.length > maxLength) { - return string.slice(0,maxLength) + "…"; + return string.slice(0, maxLength) + "…"; } return string; @@ -349,8 +354,8 @@ Module.register("calendar",{ * Capitalize the first letter of a string * Eeturn capitalized string */ - - capFirst: function(string) { + + capFirst: function (string) { return string.charAt(0).toUpperCase() + string.slice(1); }, @@ -363,7 +368,7 @@ Module.register("calendar",{ * * return string - The transformed title. */ - titleTransform: function(title) { + titleTransform: function (title) { for (var needle in this.config.titleReplace) { var replacement = this.config.titleReplace[needle]; title = title.replace(needle, replacement); @@ -371,5 +376,28 @@ Module.register("calendar",{ title = this.shorten(title, this.config.maxTitleLength); return title; + }, + + /* broadcastEvents() + * Broadcasts the events to all other modules for reuse. + * The all events available in one array, sorted on startdate. + */ + broadcastEvents: function () { + var eventList = []; + for (url in this.calendarData) { + var calendar = this.calendarData[url]; + for (e in calendar) { + var event = cloneObject(calendar[e]); + delete event.url; + eventList.push(event); + } + } + + eventList.sort(function(a,b) { + return a.startDate - b.startDate; + }); + + this.sendNotification("CALENDAR_EVENTS", eventList); + } }); diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index 214e2e5a..7f142546 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -27,7 +27,7 @@ var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumbe var opts = { headers: { - 'User-Agent': 'Mozilla/5.0 (Node.js 6.0.0) MagicMirror/v2 (https://github.com/MichMich/MagicMirror/)' + "User-Agent": "Mozilla/5.0 (Node.js 6.0.0) MagicMirror/v2 (https://github.com/MichMich/MagicMirror/)" } }; @@ -77,7 +77,7 @@ var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumbe if (!isFacebookBirthday) { endDate = startDate; } else { - endDate = moment(startDate).add(1, 'days'); + endDate = moment(startDate).add(1, "days"); } } @@ -101,7 +101,7 @@ var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumbe for (var d in dates) { startDate = moment(new Date(dates[d])); - endDate = moment(parseInt(startDate.format("x")) + duration, 'x'); + endDate = moment(parseInt(startDate.format("x")) + duration, "x"); if (endDate.format("x") > now) { newEvents.push({ title: title, @@ -132,12 +132,19 @@ var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumbe continue; } - // Every thing is good. Add it to the list. + + var location = event.location || false; + var geo = event.geo || false; + + // Every thing is good. Add it to the list. + newEvents.push({ title: title, startDate: startDate.format("x"), endDate: endDate.format("x"), - fullDayEvent: fullDayEvent + fullDayEvent: fullDayEvent, + location: location, + geo: geo }); }