mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-06-28 04:02:12 +00:00
Merge pull request #1116 from ConnorChristie/async-dom
DOM creation notifications in cases of async template rendering
This commit is contained in:
commit
38e0af41ce
17
CHANGELOG.md
17
CHANGELOG.md
@ -2,25 +2,24 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
## [2.3.0] - Unreleased
|
## [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
|
## [2.2.2] - 2018-01-02
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Add missing `package-lock.json`.
|
- Add missing `package-lock.json`.
|
||||||
>>>>>>> master
|
|
||||||
|
|
||||||
*This release is scheduled to be released on 2018-04-01.*
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Changed Electron dependency to v1.7.10.
|
- Changed Electron dependency to v1.7.10.
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
## [2.2.1] - 2018-01-01
|
## [2.2.1] - 2018-01-01
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
118
js/main.js
118
js/main.js
@ -19,38 +19,39 @@ var MM = (function() {
|
|||||||
* are configured for a specific position.
|
* are configured for a specific position.
|
||||||
*/
|
*/
|
||||||
var createDomObjects = function() {
|
var createDomObjects = function() {
|
||||||
for (var m in modules) {
|
modules.forEach(module => {
|
||||||
var module = modules[m];
|
if (typeof module.data.position !== "string") {
|
||||||
|
return;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
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();
|
updateWrapperStates();
|
||||||
|
|
||||||
@ -79,11 +80,11 @@ var MM = (function() {
|
|||||||
* argument notification string - The identifier of the notification.
|
* argument notification string - The identifier of the notification.
|
||||||
* argument payload mixed - The payload of the notification.
|
* argument payload mixed - The payload of the notification.
|
||||||
* argument sender Module - The module that sent 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) {
|
var sendNotification = function(notification, payload, sender, sendTo) {
|
||||||
for (var m in modules) {
|
for (var module of modules) {
|
||||||
var module = modules[m];
|
if (module !== sender && (!sendTo || module === sendTo)) {
|
||||||
if (module !== sender) {
|
|
||||||
module.notificationReceived(notification, payload, sender);
|
module.notificationReceived(notification, payload, sender);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,19 +95,53 @@ var MM = (function() {
|
|||||||
*
|
*
|
||||||
* argument module Module - The module that needs an update.
|
* argument module Module - The module that needs an update.
|
||||||
* argument speed Number - The number of microseconds for the animation. (optional)
|
* 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 updateDom = function(module, speed) {
|
||||||
var newContent = module.getDom();
|
return new Promise((resolve) => {
|
||||||
var newHeader = module.getHeader();
|
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)) {
|
if (!moduleNeedsUpdate(module, newHeader, newContent)) {
|
||||||
|
resolve();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!speed) {
|
if (!speed) {
|
||||||
updateModuleContent(module, newHeader, newContent);
|
updateModuleContent(module, newHeader, newContent);
|
||||||
|
resolve();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,16 +150,16 @@ var MM = (function() {
|
|||||||
if (!module.hidden) {
|
if (!module.hidden) {
|
||||||
showModule(module, speed / 2);
|
showModule(module, speed / 2);
|
||||||
}
|
}
|
||||||
|
resolve();
|
||||||
});
|
});
|
||||||
} else {
|
});
|
||||||
updateModuleContent(module, newHeader, newContent);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* moduleNeedsUpdate(module, newContent)
|
/* moduleNeedsUpdate(module, newContent)
|
||||||
* Check if the content has changed.
|
* Check if the content has changed.
|
||||||
*
|
*
|
||||||
* argument module Module - The module to check.
|
* 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.
|
* argument newContent Domobject - The new content that is generated.
|
||||||
*
|
*
|
||||||
* return bool - Does the module need an update?
|
* return bool - Does the module need an update?
|
||||||
@ -152,6 +187,7 @@ var MM = (function() {
|
|||||||
* Update the content of a module on screen.
|
* Update the content of a module on screen.
|
||||||
*
|
*
|
||||||
* argument module Module - The module to check.
|
* 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.
|
* argument newContent Domobject - The new content that is generated.
|
||||||
*/
|
*/
|
||||||
var updateModuleContent = function(module, newHeader, newContent) {
|
var updateModuleContent = function(module, newHeader, newContent) {
|
||||||
|
45
js/module.js
45
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.
|
* This method can to be subclassed if the module wants to display info on the mirror.
|
||||||
* Alternatively, the getTemplete method could be subclassed.
|
* 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 () {
|
getDom: function () {
|
||||||
var div = document.createElement("div");
|
return new Promise((resolve) => {
|
||||||
var template = this.getTemplate();
|
var div = document.createElement("div");
|
||||||
var templateData = this.getTemplateData();
|
var template = this.getTemplate();
|
||||||
|
var templateData = this.getTemplateData();
|
||||||
|
|
||||||
// Check to see if we need to render a template string or a file.
|
// Check to see if we need to render a template string or a file.
|
||||||
if (/^.*((\.html)|(\.njk))$/.test(template)) {
|
if (/^.*((\.html)|(\.njk))$/.test(template)) {
|
||||||
// the template is a filename
|
// the template is a filename
|
||||||
this.nunjucksEnvironment().render(template, templateData, function (err, res) {
|
this.nunjucksEnvironment().render(template, templateData, function (err, res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
Log.error(err)
|
Log.error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The inner content of the div will be set after the template is received.
|
div.innerHTML = res;
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return div;
|
resolve(div);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// the template is a template string.
|
||||||
|
div.innerHTML = this.nunjucksEnvironment().renderString(template, templateData);
|
||||||
|
|
||||||
|
resolve(div);
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/* getHeader()
|
/* getHeader()
|
||||||
|
@ -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.
|
- `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.
|
- `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)`
|
#### `socketNotificationReceived: function(notification, payload)`
|
||||||
|
Loading…
x
Reference in New Issue
Block a user