| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | /* global  Log, Loader, Module, config, defaults */ | 
					
						
							| 
									
										
										
										
											2016-07-14 11:48:37 +02:00
										 |  |  | /* jshint -W020 */ | 
					
						
							| 
									
										
										
										
											2014-02-19 16:45:36 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | /* Magic Mirror | 
					
						
							|  |  |  |  * Main System | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * By Michael Teeuw http://michaelteeuw.nl
 | 
					
						
							|  |  |  |  * MIT Licensed. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2014-02-19 16:45:36 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | var MM = (function() { | 
					
						
							| 
									
										
										
										
											2014-02-19 16:45:36 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 	var modules = []; | 
					
						
							| 
									
										
										
										
											2014-02-24 16:35:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 	/* Private Methods */ | 
					
						
							| 
									
										
										
										
											2014-02-19 16:45:36 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 	/* createDomObjects() | 
					
						
							| 
									
										
										
										
											2016-04-03 19:52:13 +02:00
										 |  |  | 	 * Create dom objects for all modules that | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 	 * are configured for a specific position. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	var createDomObjects = function() { | 
					
						
							|  |  |  | 		for (var m in modules) { | 
					
						
							|  |  |  | 			var module = modules[m]; | 
					
						
							| 
									
										
										
										
											2016-04-03 19:52:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-05 14:35:11 -04:00
										 |  |  | 			if (typeof module.data.position === "string") { | 
					
						
							| 
									
										
										
										
											2014-02-26 14:14:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 				var wrapper = selectWrapper(module.data.position); | 
					
						
							| 
									
										
										
										
											2016-03-29 13:28:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				var dom = document.createElement("div"); | 
					
						
							|  |  |  | 				dom.id = module.identifier; | 
					
						
							|  |  |  | 				dom.className = module.name; | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-05 14:35:11 -04:00
										 |  |  | 				if (typeof module.data.classes === "string") { | 
					
						
							|  |  |  | 					dom.className = "module " + dom.className + " " + module.data.classes; | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				dom.opacity = 0; | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 				wrapper.appendChild(dom); | 
					
						
							| 
									
										
										
										
											2014-02-24 16:35:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-05 14:35:11 -04:00
										 |  |  | 				if (typeof module.data.header !== "undefined" && module.data.header !== "") { | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 					var moduleHeader = document.createElement("header"); | 
					
						
							|  |  |  | 					moduleHeader.innerHTML = module.data.header; | 
					
						
							| 
									
										
										
										
											2016-09-20 17:22:24 +02:00
										 |  |  | 					moduleHeader.className = "module-header"; | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 					dom.appendChild(moduleHeader); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				var moduleContent = document.createElement("div"); | 
					
						
							|  |  |  | 				moduleContent.className = "module-content"; | 
					
						
							|  |  |  | 				dom.appendChild(moduleContent); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-01 17:49:43 +02:00
										 |  |  | 				updateDom(module, 0); | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-24 16:35:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-12 20:03:56 +01:00
										 |  |  | 		updateWrapperStates(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-05 14:35:11 -04:00
										 |  |  | 		sendNotification("DOM_OBJECTS_CREATED"); | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2014-04-21 16:51:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 	/* selectWrapper(position) | 
					
						
							|  |  |  | 	 * Select the wrapper dom object for a specific position. | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * argument position string - The name of the position. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	var selectWrapper = function(position) { | 
					
						
							| 
									
										
										
										
											2016-04-05 14:35:11 -04:00
										 |  |  | 		var classes = position.replace("_"," "); | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 		var parentWrapper = document.getElementsByClassName(classes); | 
					
						
							|  |  |  | 		if (parentWrapper.length > 0) { | 
					
						
							| 
									
										
										
										
											2016-04-05 14:35:11 -04:00
										 |  |  | 			var wrapper =  parentWrapper[0].getElementsByClassName("container"); | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 			if (wrapper.length > 0) { | 
					
						
							|  |  |  | 				return wrapper[0]; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2014-02-19 17:02:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 	/* sendNotification(notification, payload, sender) | 
					
						
							|  |  |  | 	 * Send a notification to all modules. | 
					
						
							|  |  |  | 	 * | 
					
						
							| 
									
										
										
										
											2016-11-24 00:26:40 -03:00
										 |  |  | 	 * argument notification string - The identifier of the notification. | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 	 * argument payload mixed - The payload of the notification. | 
					
						
							|  |  |  | 	 * argument sender Module - The module that sent the notification. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	var sendNotification = function(notification, payload, sender) { | 
					
						
							|  |  |  | 		for (var m in modules) { | 
					
						
							|  |  |  | 			var module = modules[m]; | 
					
						
							|  |  |  | 			if (module !== sender) { | 
					
						
							|  |  |  | 				module.notificationReceived(notification, payload, sender); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* updateDom(module, speed) | 
					
						
							|  |  |  | 	 * Update the dom for a specific module. | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * argument module Module - The module that needs an update. | 
					
						
							|  |  |  | 	 * argument speed Number - The number of microseconds for the animation. (optional) | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	var updateDom = function(module, speed) { | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 		var newContent = module.getDom(); | 
					
						
							| 
									
										
										
										
											2016-09-20 17:22:24 +02:00
										 |  |  | 		var newHeader = module.getHeader(); | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (!module.hidden) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-20 17:22:24 +02:00
										 |  |  | 			if (!moduleNeedsUpdate(module, newHeader, newContent)) { | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (!speed) { | 
					
						
							| 
									
										
										
										
											2016-09-20 17:22:24 +02:00
										 |  |  | 				updateModuleContent(module, newHeader, newContent); | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			hideModule(module, speed / 2, function() { | 
					
						
							| 
									
										
										
										
											2016-09-20 17:22:24 +02:00
										 |  |  | 				updateModuleContent(module, newHeader, newContent); | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 				if (!module.hidden) { | 
					
						
							|  |  |  | 					showModule(module, speed / 2); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2016-09-20 17:22:24 +02:00
										 |  |  | 			updateModuleContent(module, newHeader, newContent); | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* moduleNeedsUpdate(module, newContent) | 
					
						
							|  |  |  | 	 * Check if the content has changed. | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * argument module Module - The module to check. | 
					
						
							|  |  |  | 	 * argument newContent Domobject - The new content that is generated. | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * return bool - Does the module need an update? | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2016-09-20 17:22:24 +02:00
										 |  |  | 	var moduleNeedsUpdate = function(module, newHeader, newContent) { | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 		var moduleWrapper = document.getElementById(module.identifier); | 
					
						
							| 
									
										
										
										
											2016-09-20 17:22:24 +02:00
										 |  |  | 		var contentWrapper = moduleWrapper.getElementsByClassName("module-content"); | 
					
						
							|  |  |  | 		var headerWrapper = moduleWrapper.getElementsByClassName("module-header"); | 
					
						
							| 
									
										
										
										
											2016-03-29 13:28:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-20 17:22:24 +02:00
										 |  |  | 		var headerNeedsUpdate = false; | 
					
						
							|  |  |  | 		var contentNeedsUpdate = false; | 
					
						
							| 
									
										
										
										
											2016-03-29 13:28:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-20 17:22:24 +02:00
										 |  |  | 		if (headerWrapper.length > 0) { | 
					
						
							| 
									
										
										
										
											2016-10-25 12:30:24 +02:00
										 |  |  | 			headerNeedsUpdate = newHeader !== headerWrapper[0].innerHTML; | 
					
						
							| 
									
										
										
										
											2016-09-20 17:22:24 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		var tempContentWrapper = document.createElement("div"); | 
					
						
							|  |  |  | 		tempContentWrapper.appendChild(newContent); | 
					
						
							|  |  |  | 		contentNeedsUpdate = tempContentWrapper.innerHTML !== contentWrapper[0].innerHTML; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return headerNeedsUpdate || contentNeedsUpdate; | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 	/* moduleNeedsUpdate(module, newContent) | 
					
						
							|  |  |  | 	 * Update the content of a module on screen. | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * argument module Module - The module to check. | 
					
						
							|  |  |  | 	 * argument newContent Domobject - The new content that is generated. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2016-09-20 17:22:24 +02:00
										 |  |  | 	var updateModuleContent = function(module, newHeader, newContent) { | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 		var moduleWrapper = document.getElementById(module.identifier); | 
					
						
							| 
									
										
										
										
											2016-09-20 17:22:24 +02:00
										 |  |  | 		var headerWrapper = moduleWrapper.getElementsByClassName("module-header"); | 
					
						
							|  |  |  | 		var contentWrapper = moduleWrapper.getElementsByClassName("module-content"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		contentWrapper[0].innerHTML = ""; | 
					
						
							|  |  |  | 		contentWrapper[0].appendChild(newContent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if( headerWrapper.length > 0 && newHeader) { | 
					
						
							|  |  |  | 			headerWrapper[0].innerHTML = newHeader; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 	/* hideModule(module, speed, callback) | 
					
						
							|  |  |  | 	 * Hide the module. | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * argument module Module - The module to hide. | 
					
						
							|  |  |  | 	 * argument speed Number - The speed of the hide animation. | 
					
						
							|  |  |  | 	 * argument callback function - Called when the animation is done. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2016-10-13 15:00:59 +02:00
										 |  |  | 	var hideModule = function(module, speed, callback, options) { | 
					
						
							|  |  |  | 		options = options || {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// set lockString if set in options.
 | 
					
						
							|  |  |  | 		if (options.lockString) { | 
					
						
							| 
									
										
										
										
											2016-10-14 17:42:07 +02:00
										 |  |  | 			// Log.log("Has lockstring: " + options.lockString);
 | 
					
						
							| 
									
										
										
										
											2016-10-13 15:00:59 +02:00
										 |  |  | 			if (module.lockStrings.indexOf(options.lockString) === -1) { | 
					
						
							|  |  |  | 				module.lockStrings.push(options.lockString); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 		var moduleWrapper = document.getElementById(module.identifier); | 
					
						
							|  |  |  | 		if (moduleWrapper !== null) { | 
					
						
							|  |  |  | 			moduleWrapper.style.transition = "opacity " + speed / 1000 + "s"; | 
					
						
							|  |  |  | 			moduleWrapper.style.opacity = 0; | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-08 17:27:02 +02:00
										 |  |  | 			clearTimeout(module.showHideTimer); | 
					
						
							|  |  |  | 			module.showHideTimer = setTimeout(function() { | 
					
						
							| 
									
										
										
										
											2016-04-01 10:25:54 +02:00
										 |  |  | 				// To not take up any space, we just make the position absolute.
 | 
					
						
							| 
									
										
										
										
											2016-10-13 15:00:59 +02:00
										 |  |  | 				// since it's fade out anyway, we can see it lay above or
 | 
					
						
							| 
									
										
										
										
											2016-04-01 10:25:54 +02:00
										 |  |  | 				// below other modules. This works way better than adjusting
 | 
					
						
							|  |  |  | 				// the .display property.
 | 
					
						
							| 
									
										
										
										
											2016-10-16 17:24:21 +02:00
										 |  |  | 				moduleWrapper.style.position = "fixed"; | 
					
						
							| 
									
										
										
										
											2016-04-01 10:25:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-08 20:07:31 +01:00
										 |  |  | 				updateWrapperStates(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-05 14:35:11 -04:00
										 |  |  | 				if (typeof callback === "function") { callback(); } | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 			}, speed); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* showModule(module, speed, callback) | 
					
						
							|  |  |  | 	 * Show the module. | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * argument module Module - The module to show. | 
					
						
							|  |  |  | 	 * argument speed Number - The speed of the show animation. | 
					
						
							|  |  |  | 	 * argument callback function - Called when the animation is done. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2016-10-13 15:00:59 +02:00
										 |  |  | 	var showModule = function(module, speed, callback, options) { | 
					
						
							|  |  |  | 		options = options || {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// remove lockString if set in options.
 | 
					
						
							|  |  |  | 		if (options.lockString) { | 
					
						
							|  |  |  | 			var index = module.lockStrings.indexOf(options.lockString) | 
					
						
							|  |  |  | 			if ( index !== -1) { | 
					
						
							|  |  |  | 				module.lockStrings.splice(index, 1); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Check if there are no more lockstrings set, or the force option is set.
 | 
					
						
							|  |  |  | 		// Otherwise cancel show action.
 | 
					
						
							|  |  |  | 		if (module.lockStrings.length !== 0 && options.force !== true) { | 
					
						
							|  |  |  | 			Log.log("Will not show " + module.name + ". LockStrings active: " + module.lockStrings.join(",")); | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-28 12:26:52 +01:00
										 |  |  | 		module.hidden = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 15:00:59 +02:00
										 |  |  | 		// If forced show, clean current lockstrings.
 | 
					
						
							|  |  |  | 		if (module.lockStrings.length !== 0 && options.force === true) { | 
					
						
							|  |  |  | 			Log.log("Force show of module: " + module.name); | 
					
						
							|  |  |  | 			module.lockStrings = []; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 		var moduleWrapper = document.getElementById(module.identifier); | 
					
						
							|  |  |  | 		if (moduleWrapper !== null) { | 
					
						
							|  |  |  | 			moduleWrapper.style.transition = "opacity " + speed / 1000 + "s"; | 
					
						
							| 
									
										
										
										
											2016-04-01 10:25:54 +02:00
										 |  |  | 			// Restore the postition. See hideModule() for more info.
 | 
					
						
							| 
									
										
										
										
											2016-04-05 14:35:11 -04:00
										 |  |  | 			moduleWrapper.style.position = "static"; | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 			moduleWrapper.style.opacity = 1; | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-08 20:07:31 +01:00
										 |  |  | 			updateWrapperStates(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-08 17:27:02 +02:00
										 |  |  | 			clearTimeout(module.showHideTimer); | 
					
						
							|  |  |  | 			module.showHideTimer = setTimeout(function() { | 
					
						
							| 
									
										
										
										
											2016-04-05 14:35:11 -04:00
										 |  |  | 				if (typeof callback === "function") { callback(); } | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 			}, speed); | 
					
						
							| 
									
										
										
										
											2016-04-01 10:25:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-08 20:07:31 +01:00
										 |  |  | 	/* updateWrapperStates() | 
					
						
							|  |  |  | 	 * Checks for all positions if it has visible content. | 
					
						
							|  |  |  | 	 * If not, if will hide the position to prevent unwanted margins. | 
					
						
							| 
									
										
										
										
											2016-11-24 00:26:40 -03:00
										 |  |  | 	 * This method schould be called by the show and hide methods. | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * Example: | 
					
						
							| 
									
										
										
										
											2016-11-08 20:07:31 +01:00
										 |  |  | 	 * If the top_bar only contains the update notification. And no update is available, | 
					
						
							|  |  |  | 	 * the update notification is hidden. The top bar still occupies space making for | 
					
						
							| 
									
										
										
										
											2016-11-24 00:26:40 -03:00
										 |  |  | 	 * an ugly top margin. By using this function, the top bar will be hidden if the | 
					
						
							|  |  |  | 	 * update notification is not visible. | 
					
						
							| 
									
										
										
										
											2016-11-08 20:07:31 +01:00
										 |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var updateWrapperStates = function() { | 
					
						
							|  |  |  | 		var positions = ["top_bar", "top_left", "top_center", "top_right", "upper_third", "middle_center", "lower_third", "bottom_left", "bottom_center", "bottom_right", "bottom_bar", "fullscreen_above", "fullscreen_below"]; | 
					
						
							| 
									
										
										
										
											2016-11-24 00:26:40 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-08 20:07:31 +01:00
										 |  |  | 		positions.forEach(function(position) { | 
					
						
							| 
									
										
										
										
											2016-11-24 00:26:40 -03:00
										 |  |  | 			var wrapper = selectWrapper(position); | 
					
						
							| 
									
										
										
										
											2016-11-08 20:07:31 +01:00
										 |  |  | 			var moduleWrappers = wrapper.getElementsByClassName("module"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var showWrapper = false; | 
					
						
							| 
									
										
										
										
											2016-11-24 00:26:40 -03:00
										 |  |  | 			Array.prototype.forEach.call(moduleWrappers, function(moduleWrapper) { | 
					
						
							| 
									
										
										
										
											2016-11-12 20:03:56 +01:00
										 |  |  | 				if (moduleWrapper.style.position == "" || moduleWrapper.style.position == "static") { | 
					
						
							| 
									
										
										
										
											2016-11-08 20:07:31 +01:00
										 |  |  | 					showWrapper = true; | 
					
						
							| 
									
										
										
										
											2016-11-24 00:26:40 -03:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2016-11-08 20:07:31 +01:00
										 |  |  | 			}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			wrapper.style.display = showWrapper ? "block" : "none"; | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 	/* loadConfig() | 
					
						
							|  |  |  | 	 * Loads the core config and combines it with de system defaults. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	var loadConfig = function() { | 
					
						
							| 
									
										
										
										
											2016-04-05 14:35:11 -04:00
										 |  |  | 		if (typeof config === "undefined") { | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 			config = defaults; | 
					
						
							| 
									
										
										
										
											2016-04-05 14:35:11 -04:00
										 |  |  | 			Log.error("Config file is missing! Please create a config file."); | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-26 15:33:10 +01:00
										 |  |  | 		config = Object.assign({}, defaults, config); | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 	/* setSelectionMethodsForModules() | 
					
						
							|  |  |  | 	 * Adds special selectors on a collection of modules. | 
					
						
							| 
									
										
										
										
											2016-04-03 19:52:13 +02:00
										 |  |  | 	 * | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 	 * argument modules array - Array of modules. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	var setSelectionMethodsForModules = function(modules) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* withClass(className) | 
					
						
							| 
									
										
										
										
											2017-02-07 23:51:13 +01:00
										 |  |  | 		 * calls modulesByClass to filter modules with the specified classes. | 
					
						
							| 
									
										
										
										
											2016-04-03 19:52:13 +02:00
										 |  |  | 		 * | 
					
						
							| 
									
										
										
										
											2016-11-24 00:26:40 -03:00
										 |  |  | 		 * argument className string/array - one or multiple classnames. (array or space divided) | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 		 * | 
					
						
							|  |  |  | 		 * return array - Filtered collection of modules. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		var withClass = function(className) { | 
					
						
							| 
									
										
										
										
											2017-02-07 23:51:13 +01:00
										 |  |  | 			return modulesByClass(className, true); | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* exceptWithClass(className) | 
					
						
							| 
									
										
										
										
											2017-02-07 23:51:13 +01:00
										 |  |  | 		 * calls modulesByClass to filter modules without the specified classes. | 
					
						
							| 
									
										
										
										
											2016-04-03 19:52:13 +02:00
										 |  |  | 		 * | 
					
						
							| 
									
										
										
										
											2016-11-24 00:26:40 -03:00
										 |  |  | 		 * argument className string/array - one or multiple classnames. (array or space divided) | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 		 * | 
					
						
							|  |  |  | 		 * return array - Filtered collection of modules. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		var exceptWithClass  = function(className) { | 
					
						
							| 
									
										
										
										
											2017-02-08 00:05:28 +01:00
										 |  |  | 			return modulesByClass(className, false); | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-07 23:51:13 +01:00
										 |  |  | 		/* modulesByClass(className, include) | 
					
						
							|  |  |  | 		 * filters a collection of modules based on classname(s). | 
					
						
							|  |  |  | 		 * | 
					
						
							|  |  |  | 		 * argument className string/array - one or multiple classnames. (array or space divided) | 
					
						
							|  |  |  | 		 * argument include boolean - if the filter should include or exclude the modules with the specific classes. | 
					
						
							|  |  |  | 		 * | 
					
						
							|  |  |  | 		 * return array - Filtered collection of modules. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		var modulesByClass = function(className, include) { | 
					
						
							| 
									
										
										
										
											2017-02-08 00:05:28 +01:00
										 |  |  | 			var searchClasses = className; | 
					
						
							|  |  |  | 			if (typeof className === "string") { | 
					
						
							|  |  |  | 				searchClasses = className.split(" "); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var newModules = modules.filter(function(module) { | 
					
						
							|  |  |  | 				var classes = module.data.classes.toLowerCase().split(" "); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				for (var c in searchClasses) { | 
					
						
							|  |  |  | 					var searchClass = searchClasses[c]; | 
					
						
							|  |  |  | 					if (classes.indexOf(searchClass.toLowerCase()) !== -1) { | 
					
						
							|  |  |  | 						return include; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				return !include; | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			setSelectionMethodsForModules(newModules); | 
					
						
							|  |  |  | 			return newModules; | 
					
						
							|  |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2017-02-07 23:51:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 		/* exceptModule(module) | 
					
						
							|  |  |  | 		 * Removes a module instance from the collection. | 
					
						
							| 
									
										
										
										
											2016-04-03 19:52:13 +02:00
										 |  |  | 		 * | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 		 * argument module Module object - The module instance to remove from the collection. | 
					
						
							|  |  |  | 		 * | 
					
						
							|  |  |  | 		 * return array - Filtered collection of modules. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		var exceptModule = function(module) { | 
					
						
							| 
									
										
										
										
											2016-07-14 11:48:37 +02:00
										 |  |  | 			var newModules = modules.filter(function(mod) { | 
					
						
							|  |  |  | 				return mod.identifier !== module.identifier; | 
					
						
							|  |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			setSelectionMethodsForModules(newModules); | 
					
						
							|  |  |  | 			return newModules; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* enumerate(callback) | 
					
						
							|  |  |  | 		 * Walks thru a collection of modules and executes the callback with the module as an argument. | 
					
						
							| 
									
										
										
										
											2016-04-03 19:52:13 +02:00
										 |  |  | 		 * | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 		 * argument callback function - The function to execute with the module as an argument. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		var enumerate = function(callback) { | 
					
						
							| 
									
										
										
										
											2016-07-14 11:48:37 +02:00
										 |  |  | 			modules.map(function(module) { | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 				callback(module); | 
					
						
							| 
									
										
										
										
											2016-07-14 11:48:37 +02:00
										 |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-05 14:35:11 -04:00
										 |  |  | 		if (typeof modules.withClass === "undefined") { Object.defineProperty(modules, "withClass",  {value: withClass, enumerable: false}); } | 
					
						
							|  |  |  | 		if (typeof modules.exceptWithClass === "undefined") { Object.defineProperty(modules, "exceptWithClass",  {value: exceptWithClass, enumerable: false}); } | 
					
						
							|  |  |  | 		if (typeof modules.exceptModule === "undefined") { Object.defineProperty(modules, "exceptModule",  {value: exceptModule, enumerable: false}); } | 
					
						
							|  |  |  | 		if (typeof modules.enumerate === "undefined") { Object.defineProperty(modules, "enumerate",  {value: enumerate, enumerable: false}); } | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 	return { | 
					
						
							|  |  |  | 		/* Public Methods */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* init() | 
					
						
							|  |  |  | 		 * Main init method. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		init: function() { | 
					
						
							| 
									
										
										
										
											2016-04-05 14:35:11 -04:00
										 |  |  | 			Log.info("Initializing MagicMirror."); | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 			loadConfig(); | 
					
						
							| 
									
										
										
										
											2016-05-11 12:38:41 +02:00
										 |  |  | 			Translator.loadCoreTranslations(config.language); | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 			Loader.loadModules(); | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* modulesStarted(moduleObjects) | 
					
						
							|  |  |  | 		 * Gets called when all modules are started. | 
					
						
							|  |  |  | 		 * | 
					
						
							|  |  |  | 		 * argument moduleObjects array<Module> - All module instances. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		modulesStarted: function(moduleObjects) { | 
					
						
							|  |  |  | 			modules = []; | 
					
						
							|  |  |  | 			for (var m in moduleObjects) { | 
					
						
							|  |  |  | 				var module = moduleObjects[m]; | 
					
						
							|  |  |  | 				modules[module.data.index] = module; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-05 14:35:11 -04:00
										 |  |  | 			Log.info("All modules started!"); | 
					
						
							|  |  |  | 			sendNotification("ALL_MODULES_STARTED"); | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			createDomObjects(); | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* sendNotification(notification, payload, sender) | 
					
						
							|  |  |  | 		 * Send a notification to all modules. | 
					
						
							|  |  |  | 		 * | 
					
						
							|  |  |  | 		 * argument notification string - The identifier of the noitication. | 
					
						
							|  |  |  | 		 * argument payload mixed - The payload of the notification. | 
					
						
							|  |  |  | 		 * argument sender Module - The module that sent the notification. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		sendNotification: function(notification, payload, sender) { | 
					
						
							|  |  |  | 			if (arguments.length < 3) { | 
					
						
							| 
									
										
										
										
											2016-04-05 14:35:11 -04:00
										 |  |  | 				Log.error("sendNotification: Missing arguments."); | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-05 14:35:11 -04:00
										 |  |  | 			if (typeof notification !== "string") { | 
					
						
							|  |  |  | 				Log.error("sendNotification: Notification should be a string."); | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (!(sender instanceof Module)) { | 
					
						
							| 
									
										
										
										
											2016-04-05 14:35:11 -04:00
										 |  |  | 				Log.error("sendNotification: Sender should be a module."); | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// Further implementation is done in the private method.
 | 
					
						
							|  |  |  | 			sendNotification(notification, payload, sender); | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* updateDom(module, speed) | 
					
						
							|  |  |  | 		 * Update the dom for a specific module. | 
					
						
							|  |  |  | 		 * | 
					
						
							|  |  |  | 		 * argument module Module - The module that needs an update. | 
					
						
							|  |  |  | 		 * argument speed Number - The number of microseconds for the animation. (optional) | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		updateDom: function(module, speed) { | 
					
						
							|  |  |  | 			if (!(module instanceof Module)) { | 
					
						
							| 
									
										
										
										
											2016-04-05 14:35:11 -04:00
										 |  |  | 				Log.error("updateDom: Sender should be a module."); | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-04-03 19:52:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 			// Further implementation is done in the private method.
 | 
					
						
							|  |  |  | 			updateDom(module, speed); | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-31 17:06:39 +02:00
										 |  |  | 		/* getModules(module, speed) | 
					
						
							|  |  |  | 		 * Returns a collection of all modules currently active. | 
					
						
							|  |  |  | 		 * | 
					
						
							|  |  |  | 		 * return array - A collection of all modules currently active. | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2016-03-31 17:05:35 +02:00
										 |  |  | 		getModules: function() { | 
					
						
							|  |  |  | 			setSelectionMethodsForModules(modules); | 
					
						
							|  |  |  | 			return modules; | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* hideModule(module, speed, callback) | 
					
						
							|  |  |  | 		 * Hide the module. | 
					
						
							|  |  |  | 		 * | 
					
						
							|  |  |  | 		 * argument module Module - The module hide. | 
					
						
							|  |  |  | 		 * argument speed Number - The speed of the hide animation. | 
					
						
							|  |  |  | 		 * argument callback function - Called when the animation is done. | 
					
						
							| 
									
										
										
										
											2016-10-13 15:00:59 +02:00
										 |  |  | 		 * argument options object - Optional settings for the hide method. | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2016-10-13 15:00:59 +02:00
										 |  |  | 		hideModule: function(module, speed, callback, options) { | 
					
						
							| 
									
										
										
										
											2016-04-01 10:44:17 +02:00
										 |  |  | 			module.hidden = true; | 
					
						
							| 
									
										
										
										
											2016-10-13 15:00:59 +02:00
										 |  |  | 			hideModule(module, speed, callback, options); | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* showModule(module, speed, callback) | 
					
						
							|  |  |  | 		 * Show the module. | 
					
						
							|  |  |  | 		 * | 
					
						
							|  |  |  | 		 * argument module Module - The module show. | 
					
						
							|  |  |  | 		 * argument speed Number - The speed of the show animation. | 
					
						
							|  |  |  | 		 * argument callback function - Called when the animation is done. | 
					
						
							| 
									
										
										
										
											2016-10-13 15:00:59 +02:00
										 |  |  | 		 * argument options object - Optional settings for the hide method. | 
					
						
							| 
									
										
										
										
											2016-03-31 19:15:58 +02:00
										 |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2016-10-13 15:00:59 +02:00
										 |  |  | 		showModule: function(module, speed, callback, options) { | 
					
						
							| 
									
										
										
										
											2017-01-28 12:26:52 +01:00
										 |  |  | 			// do not change module.hidden yet, only if we really show it later
 | 
					
						
							| 
									
										
										
										
											2016-10-13 15:00:59 +02:00
										 |  |  | 			showModule(module, speed, callback, options); | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | })(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-18 20:03:12 +02:00
										 |  |  | // Add polyfill for Object.assign.
 | 
					
						
							| 
									
										
										
										
											2016-05-03 19:09:38 -04:00
										 |  |  | if (typeof Object.assign != "function") { | 
					
						
							|  |  |  | 	(function() { | 
					
						
							|  |  |  | 		Object.assign = function(target) { | 
					
						
							|  |  |  | 			"use strict"; | 
					
						
							|  |  |  | 			if (target === undefined || target === null) { | 
					
						
							|  |  |  | 				throw new TypeError("Cannot convert undefined or null to object"); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			var output = Object(target); | 
					
						
							|  |  |  | 			for (var index = 1; index < arguments.length; index++) { | 
					
						
							|  |  |  | 				var source = arguments[index]; | 
					
						
							|  |  |  | 				if (source !== undefined && source !== null) { | 
					
						
							|  |  |  | 					for (var nextKey in source) { | 
					
						
							|  |  |  | 						if (source.hasOwnProperty(nextKey)) { | 
					
						
							|  |  |  | 							output[nextKey] = source[nextKey]; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return output; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 	})(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-04-18 20:03:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-24 17:19:32 +01:00
										 |  |  | MM.init(); |