/* global Module */ /* Magic Mirror * Module: Calendar * * By Michael Teeuw http://michaelteeuw.nl * MIT Licensed. */ Module.register('calendar',{ // Define module defaults defaults: { maximumEntries: 10, // Total Maximum Entries displaySymbol: true, defaultSymbol: 'calendar', // Fontawsome Symbol see http://fontawesome.io/cheatsheet/ maxTitleLength: 25, fetchInterval: 5 * 60 * 1000, // Update every 5 minutes. animationSpeed: 2000, fade: true, fadePoint: 0.25, // Start on 1/4th of the list. calendars: [ { symbol: 'calendar', url: 'http://www.calendarlabs.com/templates/ical/US-Holidays.ics', }, ], titleReplace: { 'De verjaardag van ' : '' } }, // Define required scripts. getStyles: function() { return ['calendar.css', 'font-awesome.css']; }, // Define required scripts. getScripts: function() { return ['moment.js']; }, // Override start method. start: function() { Log.log('Starting module: ' + this.name); // Set locale. moment.locale(config.language); for (var c in this.config.calendars) { var calendar = this.config.calendars[c]; calendar.url = calendar.url.replace('webcal://', 'http://'); this.addCalendar(calendar.url); } this.calendarData = {}; }, // Override socket notification handler. socketNotificationReceived: function(notification, payload) { if (notification === 'CALENDAR_EVENTS') { if (this.hasCalendarURL(payload.url)) { this.calendarData[payload.url] = payload.events; } } 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); } else { Log.log('Calendar received an unknown socket notification: '+notification); } 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) { wrapper.innerHTML = "Loading events ..."; 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"); titleWrapper.innerHTML = this.titleTransform(event.title); titleWrapper.className = "title bright"; eventWrapper.appendChild(titleWrapper); var timeWrapper = document.createElement("td"); timeWrapper.innerHTML = moment(event.startDate,'x').fromNow(); 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 = []; for (var c in this.calendarData) { var calendar = this.calendarData[c]; for (var e in calendar) { var event = calendar[e]; event.url = c; events.push(event); } } events.sort(function(a,b) { 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) { this.sendSocketNotification('ADD_CALENDAR', { url: url, maximumEntries: this.config.maximumEntries, 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]; if (calendar.url === url && typeof calendar.symbol === 'string') { return calendar.symbol; } } return this.config.defaultSymbol; }, /* 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) + "…"; } 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; } });