All modules are loaded in de `modules` folder. The default modules are grouped together in the `modules/default` folder. Your module should be placed in a subfolder of `modules`. Note that any file or folder your create in the `modules` folder will be ignored by git, allowing you to upgrade the MagicMirror² without the loss of your files.
A module can be placed in one single folder. Or multiple modules can be grouped in a subfoler. Note that name of the module must be unique. Even when a module with a similar name is placed in a different folder, they can't be loaded at the same time.
- **modulename/modulename.js** - This is your core module script.
- **modulename/node_helper.js** - This is an optional helper that whill be loaded by the node script. The node helper and module script can communicate with each other using an intergrated socket system.
- **modulename/public** - Any files in this folder can be accesed via the browser on `/modulename/filename.ext`.
- **modulename/anyfileorfolder** Any other file or folder in the module folder can be used by the core module script. For example: *modulename/css/modulename.css* would be a good path for your additional module styles.
## Core module file: modulename.js
This is the script in which the module will be defined. This script is required in order for the module to be used. In it's most simple form, the core module file must contain:
````javascript
Module.register("modulename",{});
````
Of course, the above module would not do anything fancy, so it's good to look at one of the simplest modules: **helloworld**:
````javascript
//helloworld.js:
Module.register("helloworld",{
// Default module config.
defaults: {
text: "Hello World!"
},
// Override dom generator.
getDom: function() {
var wrapper = document.createElement("div");
wrapper.innerHTML = this.config.text;
return wrapper;
}
});
````
As you can see, the `Module.register()` method takes two arguments: the name of the module and an object with the module properties.
This represents if the module is currently hidden (faded away).
####`this.config`
**Boolean**
The configuration of the module instance as set in the user's config.js file. This config will also contain the module's defaults if these properties are not over written by the user config.
Any properties defined in the defaults object, will be merged with the module config as defined in the user's config.js file. This is the best place to set your modules's configuration defaults. Any of the module configuration properties can be accessed using `this.config.propertyName`, but more about that later.
### Subclassable module methods
####`init()`
This method is called when a module gets instantiated. In most cases you do not need to subclass this method.
####`start()`
This method is called when all modules are loaded an the system is ready to boot up. Keep in mind that the dom object for the module is not yet created. The start method is a perfect place to define any additional module properties:
The getScripts method is called to request any additional scripts that need to be loaded. This method should therefore return an array with strings. If you want to return a full path to a file in the module folder, use the `this.file('filename.js')` method. In all cases the loader will only load a file once. It even checks if the file is available in the default vendor folder.
The getStyles method is called to request any additional stylesheets that need to be loaded. This method should therefore return an array with strings. If you want to return a full path to a file in the module folder, use the `this.file('filename.css')` method. In all cases the loader will only load a file once. It even checks if the file is available in the default vendor folder.
The getTranslations method is called to request translation files that need to be loaded. This method should therefore return a dictionary with the files to load, identified by the country's short name.
Whenever the MagicMirror needs to update the information on screen (because it starts, or because your module asked a refresh using `this.updateDom()`), the system calls the getDom method. This method should therefor return a dom object.
That MagicMirror core has the ability to send notifications to modules. Or even better: the modules have the possibility to send notifications to other modules. When this module is called, it has 3 arguments:
-`notification` - String - The notification identifier.
-`payload` - AnyType - The payload of a notification.
-`sender` - Module - The sender of the notification. If this argument is `undefined`, the sender of the notififiction is the core system.
**Note 1:** When a node helper send a notification, all modules of that module type receive the same notifications. <br>
**Note 2:** The socket connection is established as soon as the module sends it's first message using [sendSocketNotification](thissendsocketnotificationnotification-payload).
When a module is hidden (using the `module.hide()` method), the `suspend()` method will be called. By subclassing this method you can perform tasks like halting the update timers.
####`resume()`
When a module will be shown after it was previously hidden (using the `module.show()` method), the `resume()` method will be called. By subclassing this method you can perform tasks restarting the update timers.
Each module instance has some handy methods which can be helpfull building your module.
####`this.file(filename)`
***filename* String** - The name of the file you want to create the path for.<br>
**Returns String**
If you want to create a path to a file in your module folder, use the `file()` method. It returns the path to the filename given as the attribute. Is method comes in handy when configuring the [getScripts](#getscripts) and [getStyles](#getstyles) methods.
####`this.updateDom(speed)`
***speed* Number** - Optional. Animation speed in milliseconds.<br>
Whenever your module need to be updated, call the `updateDom(speed)` method. It requests the MagicMirror core to update it's dom object. If you define the speed, the content update will be animated, but only if the content will realy change.
As an example: the clock modules calls this method every second:
````javascript
...
start: function() {
var self = this;
setInterval(function() {
self.updateDom(); // no speed defined, so it updates instantly.
***notification* String** - The notification identifier.<br>
***payload* AnyType** - Optional. A notification payload.<br>
If you want to send a notification to all other modules, use the `sendNotification(notification, payload)`. All other modules will receive the message via the [notificationReceived](#notificationreceivednotification-payload-sender) method. In that case, the sender is automaticly set to the instance calling the sendNotification method.
***notification* String** - The notification identifier.<br>
***payload* AnyType** - Optional. A notification payload.<br>
If you want to send a notification to the node_helper, use the `sendSocketNotification(notification, payload)`. Only the node_helper of this module will recieve the socket notification.
***speed* Number** - Optional, The speed of the hide animation in milliseconds.
***callback* Function** - Optional, The callback after the hide animation is finished.
To hide a module, you can call the `hide(speed, callback)` method. You can call the hide method on the module instance itselve using `this.hide()`, but of course you can also hide an other module using `anOtherModule.hide()`.
**Note 1:** If the hide animation is canceled, for instance because the show method is called before the hide animation was finished, the callback will not be called.<br>
**Note 2:** If the hide animation is hijacked (an other method calls hide on the same module), the callback will not be called.<br>
**Note 3:** If the dom is not yet created, the hide method won't work. Wait for the `DOM_OBJECTS_CREATED` [notification](#notificationreceivednotification-payload-sender).
####`this.show(speed, callback)`
***speed* Number** - Optional, The speed of the show animation in milliseconds.
***callback* Function** - Optional, The callback after the show animation is finished.
To show a module, you can call the `show(speed, callback)` method. You can call the show method on the module instance itselve using `this.show()`, but of course you can also show an other module using `anOtherModule.show()`.
**Note 1:** If the show animation is canceled, for instance because the hide method is called before the show animation was finished, the callback will not be called.<br>
**Note 2:** If the show animation is hijacked (an other method calls show on the same module), the callback will not be called.<br>
**Note 3:** If the dom is not yet created, the show method won't work. Wait for the `DOM_OBJECTS_CREATED` [notification](#notificationreceivednotification-payload-sender).
***identifier* String** - Identifier of the string that should be translated.
The Magic Mirror contains a convenience wrapper for `l18n`. You can use this to automatically serve different translations for your modules based on the user's `language` configuration.
When adding translations to your module, it's a good idea to see if an apropriate translation is already available in the [core translation files](https://github.com/MichMich/MagicMirror/tree/master/translations). This way, your module can benefit from the existing translations.
**Note:** although comments are officially not supported in JSON files, MagicMirror allows it by stripping the comments before parsing the JSON file. Comments in translation files could help other translators.
The node helper is a Node.js script that is able to do some backend task to support your module. For every module type, only one node helper instance will be created. For example: if your MagicMirror uses two calendar modules, there will be only one calendar node helper instantiated.
**Note:** Because there is only one node helper per module type, there is no default config available within your module. It's your task to send the desired config from your module to your node helper.
This is a link to the IO instance. It will allow you to do some Socket.IO magic. In most cases you won't need this, since the Node Helper has a few convenience methods to make this simple.
### Subclassable module methods
####`init()`
This method is called when a node helper gets instantiated. In most cases you do not need to subclass this method.
####`start()`
This method is called when all node helper are loaded an the system is ready to boot up. The start method is a perfect place to define any additional module properties:
With this method, your node helper can receive notifications form your modules. When this method is called, it has 2 arguments:
-`notification` - String - The notification identifier.
-`payload` - AnyType - The payload of a notification.
**Note:** The socket connection is established as soon as the module sends it's first message using [sendSocketNotification](thissendsocketnotificationnotification-payload).
***notification* String** - The notification identifier.<br>
***payload* AnyType** - Optional. A notification payload.<br>
If you want to send a notification to all your modules, use the `sendSocketNotification(notification, payload)`. Only the module of your module type will recieve the socket notification.
The core Magic Mirror object: `MM` has some handy method that will help you in controlling your and other modules. Most of the `MM` methods are available via convenience methods on the Module instance.
The only additional method available for your module, is the feature to retrieve references to other modules. This can be used to hide and show other modules.
####`MM.getModules()`
**Returns Array** - An array with module instances.<br>
To make a selection of all currently loaded module instances, run the `MM.getModules()` method. It will return an array with all currently loaded module instances. The returned array has a lot of filtering methods. See below for more info.
**Note:** This method returns an empty array if not all modules are started yet. Wait for the `ALL_MODULES_STARTED` [notification](#notificationreceivednotification-payload-sender).
#####`.withClass(classnames)`
***classnames* String or Array** - The class names on which you want to filer.
**Returns Array** - An array with module instances.<br>
If you want to make a selection based on one ore more class names, use the withClass method on a result of the `MM.getModules()` method. The argument of the `withClass(classname)` method can be an array, or space separated string.
**Examples:**
````javascript
var modules = MM.getModules().withClass('classname');
var modules = MM.getModules().withClass('classname1 classname2');
var modules = MM.getModules().withClass(['classname1','classname2']);
````
#####`.exceptWithClass(classnames)`
***classnames* String or Array** - The class names of the modules you want to remove from the results.
**Returns Array** - An array with module instances.<br>
If you to remove some modules from a selection based on a classname, use the exceptWithClass method on a result of the `MM.getModules()` method. The argument of the `exceptWithClass(classname)` method can be an array, or space separated string.
**Examples:**
````javascript
var modules = MM.getModules().exceptWithClass('classname');
var modules = MM.getModules().exceptWithClass('classname1 classname2');
var modules = MM.getModules().exceptWithClass(['classname1','classname2']);
````
#####`.exceptModule(module)`
***module* Module Object** - The reference to a module you want to remove from the results.
**Returns Array** - An array with module instances.<br>
If you to remove a specific module instance from a selection based on a classname, use the exceptWithClass method on a result of the `MM.getModules()` method. This can be helpfull if you want to select all module instances except the instance of your module.
**Examples:**
````javascript
var modules = MM.getModules().exceptModule(this);
````
Of course, you can combine all of the above filters:
**Example:**
````javascript
var modules = MM.getModules().withClass('classname1').exceptwithClass('classname2').exceptModule(aModule);
````
#####`.enumerate(callback)`
***callback* Function(module)** - The callback run on every instance.
If you want to perform an action on all selected modules, you can use the `enumerate` function:
````javascript
MM.getModules().enumerate(function(module) {
Log.log(module.name);
});
````
**Example:**
To hide all modules except the your module instance, you could write something like:
The Magic Mirror contains a convenience wrapper for logging. Currently, this logger is a simple proxy to the original `console.log` methods. But it might get additional features in the future. The Loggers is currently only available in the core module file (not in the node_helper).