diff --git a/CHANGELOG.md b/CHANGELOG.md index b3bd5982..3815d6f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,25 +2,24 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -<<<<<<< HEAD ## [2.3.0] - Unreleased -======= + +### Added + +- Add system notification `MODULE_DOM_CREATED` for notifying each module when their Dom has been fully loaded. + +*This release is scheduled to be released on 2018-04-01.* + ## [2.2.2] - 2018-01-02 ### Added - Add missing `package-lock.json`. ->>>>>>> master - -*This release is scheduled to be released on 2018-04-01.* ### Changed + - Changed Electron dependency to v1.7.10. -### Added - -### Fixed - ## [2.2.1] - 2018-01-01 ### Fixed diff --git a/js/main.js b/js/main.js index f499da62..0e1e5239 100644 --- a/js/main.js +++ b/js/main.js @@ -19,38 +19,39 @@ var MM = (function() { * are configured for a specific position. */ var createDomObjects = function() { - for (var m in modules) { - var module = modules[m]; - - if (typeof module.data.position === "string") { - - var wrapper = selectWrapper(module.data.position); - - var dom = document.createElement("div"); - dom.id = module.identifier; - dom.className = module.name; - - if (typeof module.data.classes === "string") { - dom.className = "module " + dom.className + " " + module.data.classes; - } - - dom.opacity = 0; - wrapper.appendChild(dom); - - if (typeof module.data.header !== "undefined" && module.data.header !== "") { - var moduleHeader = document.createElement("header"); - moduleHeader.innerHTML = module.data.header; - moduleHeader.className = "module-header"; - dom.appendChild(moduleHeader); - } - - var moduleContent = document.createElement("div"); - moduleContent.className = "module-content"; - dom.appendChild(moduleContent); - - updateDom(module, 0); + modules.forEach(module => { + if (typeof module.data.position !== "string") { + return; } - } + + var wrapper = selectWrapper(module.data.position); + + var dom = document.createElement("div"); + dom.id = module.identifier; + dom.className = module.name; + + if (typeof module.data.classes === "string") { + dom.className = "module " + dom.className + " " + module.data.classes; + } + + dom.opacity = 0; + wrapper.appendChild(dom); + + if (typeof module.data.header !== "undefined" && module.data.header !== "") { + var moduleHeader = document.createElement("header"); + moduleHeader.innerHTML = module.data.header; + moduleHeader.className = "module-header"; + dom.appendChild(moduleHeader); + } + + var moduleContent = document.createElement("div"); + moduleContent.className = "module-content"; + dom.appendChild(moduleContent); + + updateDom(module, 0).then(() => { + sendNotification("MODULE_DOM_CREATED", null, null, module); + }).catch(Log.error); + }); updateWrapperStates(); @@ -79,11 +80,11 @@ var MM = (function() { * argument notification string - The identifier of the notification. * argument payload mixed - The payload of the notification. * argument sender Module - The module that sent the notification. + * argument sendTo Module - The module to send the notification to. (optional) */ - var sendNotification = function(notification, payload, sender) { - for (var m in modules) { - var module = modules[m]; - if (module !== sender) { + var sendNotification = function(notification, payload, sender, sendTo) { + for (var module of modules) { + if (module !== sender && (!sendTo || module === sendTo)) { module.notificationReceived(notification, payload, sender); } } @@ -94,19 +95,53 @@ var MM = (function() { * * argument module Module - The module that needs an update. * argument speed Number - The number of microseconds for the animation. (optional) + * + * return Promise - Resolved when the dom is fully updated. */ var updateDom = function(module, speed) { - var newContent = module.getDom(); - var newHeader = module.getHeader(); + return new Promise((resolve) => { + var newContentPromise = module.getDom(); + var newHeader = module.getHeader(); - if (!module.hidden) { + if (!(newContentPromise instanceof Promise)) { + // convert to a promise if not already one to avoid if/else's everywhere + newContentPromise = Promise.resolve(newContentPromise); + } + + newContentPromise.then((newContent) => { + var updatePromise = updateDomWithContent(module, speed, newHeader, newContent); + + updatePromise.then(resolve).catch(Log.error); + }).catch(Log.error); + }); + }; + + /* updateDomWithContent(module, speed, newHeader, newContent) + * Update the dom with the specified content + * + * argument module Module - The module that needs an update. + * argument speed Number - The number of microseconds for the animation. (optional) + * argument newHeader String - The new header that is generated. + * argument newContent Domobject - The new content that is generated. + * + * return Promise - Resolved when the module dom has been updated. + */ + var updateDomWithContent = function(module, speed, newHeader, newContent) { + return new Promise((resolve) => { + if (module.hidden || !speed) { + updateModuleContent(module, newHeader, newContent); + resolve(); + return; + } if (!moduleNeedsUpdate(module, newHeader, newContent)) { + resolve(); return; } if (!speed) { updateModuleContent(module, newHeader, newContent); + resolve(); return; } @@ -115,16 +150,16 @@ var MM = (function() { if (!module.hidden) { showModule(module, speed / 2); } + resolve(); }); - } else { - updateModuleContent(module, newHeader, newContent); - } + }); }; /* moduleNeedsUpdate(module, newContent) * Check if the content has changed. * * argument module Module - The module to check. + * argument newHeader String - The new header that is generated. * argument newContent Domobject - The new content that is generated. * * return bool - Does the module need an update? @@ -152,6 +187,7 @@ var MM = (function() { * Update the content of a module on screen. * * argument module Module - The module to check. + * argument newHeader String - The new header that is generated. * argument newContent Domobject - The new content that is generated. */ var updateModuleContent = function(module, newHeader, newContent) { diff --git a/js/module.js b/js/module.js index 464509ee..57bdde4f 100644 --- a/js/module.js +++ b/js/module.js @@ -78,34 +78,33 @@ var Module = Class.extend({ * This method can to be subclassed if the module wants to display info on the mirror. * Alternatively, the getTemplete method could be subclassed. * - * return domobject - The dom to display. + * return DomObject | Promise - The dom or a promise with the dom to display. */ getDom: function () { - var div = document.createElement("div"); - var template = this.getTemplate(); - var templateData = this.getTemplateData(); + return new Promise((resolve) => { + var div = document.createElement("div"); + var template = this.getTemplate(); + var templateData = this.getTemplateData(); - // Check to see if we need to render a template string or a file. - if (/^.*((\.html)|(\.njk))$/.test(template)) { - // the template is a filename - this.nunjucksEnvironment().render(template, templateData, function (err, res) { - if (err) { - Log.error(err) - } + // Check to see if we need to render a template string or a file. + if (/^.*((\.html)|(\.njk))$/.test(template)) { + // the template is a filename + this.nunjucksEnvironment().render(template, templateData, function (err, res) { + if (err) { + Log.error(err) + } - // The inner content of the div will be set after the template is received. - // This isn't the most optimal way, but since it's near instant - // it probably won't be an issue. - // If it gives problems, we can always add a way to pre fetch the templates. - // Let's not over optimise this ... KISS! :) - div.innerHTML = res; - }); - } else { - // the template is a template string. - div.innerHTML = this.nunjucksEnvironment().renderString(template, templateData); - } + div.innerHTML = res; - return div; + resolve(div); + }); + } else { + // the template is a template string. + div.innerHTML = this.nunjucksEnvironment().renderString(template, templateData); + + resolve(div); + } + }); }, /* getHeader() diff --git a/modules/README.md b/modules/README.md index 76973996..0b5c2d7c 100644 --- a/modules/README.md +++ b/modules/README.md @@ -230,11 +230,12 @@ notificationReceived: function(notification, payload, sender) { } ```` -**Note:** the system sends two notifications when starting up. These notifications could come in handy! +**Note:** the system sends three notifications when starting up. These notifications could come in handy! - `ALL_MODULES_STARTED` - All modules are started. You can now send notifications to other modules. - `DOM_OBJECTS_CREATED` - All dom objects are created. The system is now ready to perform visual changes. +- `MODULE_DOM_CREATED` - This module's dom has been fully loaded. You can now access your module's dom objects. #### `socketNotificationReceived: function(notification, payload)`