Problem:I am trying to create a project using 3 HTML widgets or 3 Custom Elements on the same screen. The code that these 3 widgets or custom elements would contain (HTML canvas and container div’s and toggle buttons, etc., JS and CSS, plus src to additional external script.js and link to additional external css) depend on coding that can access elements in all these 3, so need to correctly specify element names/id’s (for example, <div id= ______), so the getElementById in the code will work. So, far, even when getting the id from the web developer inspector, while code successfully is able to call functions in HTML_widget1 or custom element 1, code is not successfully calling scripted functions in the second or third widget/custom element. Since the code has been tested and works in a different app, I think I must be coding incorrectly or not successfully identifying div id’s, or maybe 3 widgets/custom elements cannot exist or work together on the same screen in Saola Animate? BTW checking the web developer messages, there are no error messages when I publish to HTML and run. Any suggestions would be appreciated to help me get this project working. Thank you in advance.
Thank you for sending the package. We’ve reviewed it and have some suggestions to help make it work properly.
To enable communication between HTML Widgets, please use the postMessage mechanism. Below is the code for sending and receiving messages between widgets:
Code for sending messages:
function sendToWidget2() {
const message = {
type: 'callFunction', // Message type
target: 'widget2', // Target widget ID
functionName: 'showMessage', // Function to call
params: ['Hello from Widget 1!'] // Parameters (array)
};
// Send directly to all sibling iframes
if (parent.frames) {
for (let i = 0; i < parent.frames.length; i++) {
try {
parent.frames[i].postMessage(message, '*');
} catch(e) {}
}
}
}
Code for receiving messages:
// Listen for messages from other widgets
window.addEventListener('message', function(event) {
// Check message type
if (event.data.type === 'callFunction') {
// Check if this message is for THIS widget
if (event.data.target === 'widget2') {
// Call the requested function
if (event.data.functionName === 'showMessage') {
// Execute with parameters
// showMessage(event.data.params[0]);
}
}
}
});
Please refer to the sample project below for your reference and apply the same approach to your project.
Apologies: I think I was not clear in my request for code. I have an external script.js that (1) includes JS code for a listener for a canvas element in the HTML_Widget_2 and (2) includes and calls a JS code function that targets that same canvas element in the HTML_Widget_2. I would usually identify the canvas element in the widget by using document.getElementById(“canvas element’s name”). How would I code the external script.js file function to identify and run this script function for a canvas element created (<div id=”canvas element’s name”) and styled ( within the HTML-Widget_2?
An element inside an HTML Widget cannot be called using document.getElementById() from an external script, because essentially an HTML Widget is an <iframe> that wraps the code. To work with it, you have to use a message-sending and receiving mechanism (as mentioned above).
If you want to access an element directly from outside, try using a Custom Element instead. This allows you to create inline HTML. However, even in this case, you still can’t use getElementById() because the ID changes. To access its DOM from an external script, use the following syntax:
window.AtomiSaola.topDocs[0].getElement(“your custom element name”).dom;
For details about these functions, refer to the JavaScript APIs section from page 163 in the manual.
Thank you again, Hang. When I add a test button and the function:
function elementEventHandler(doc, e) {
var tester=window.AtomiSaola.topDocs[0].getElement(‘Custom_2’).dom;
alert(tester);
}
My alert is:
[object HTMLDivElement]
Now if I add the name of the div element within Custom_1, which is “crossGaugeContainer”:
function elementEventHandler(doc, e) {
var tester=window.AtomiSaola.topDocs[0].getElement(‘Custom_1.crossGaugeContainer’).dom;
alert(tester);
}
and then click the test button, I do not get any alert message, but I get an error message: TypeError: can’t access property “dom”, window.AtomiSaola.topDocs[0].getElement(…) is undefined.
So, I must be coding this incorrectly? Any help appreciated. Thank you again.
Please let me continue from what Miss Hang has been supporting you with.
If you are running the script within a Saola element, you do not need to call topDocs[0] anymore. Since you are using the elementEventHandler(doc, e) function, you can simply use doc.getElement.
You cannot use getElement('Custom_1.crossGaugeContainer') to retrieve a <div> nested inside a Saola element. Instead, you should retrieve the DOM of the parent element and then use a standard JavaScript querySelector to select the internal <div>.
Like this
function elementEventHandler(doc, e) {
var tester=doc.getElement(‘Custom_1’).dom;
// if crossGaugeContainer is a class name
var crossGaugeContainer = tester.querySelector('.crossGaugeContainer');
// if crossGaugeContainer is an id
// var crossGaugeContainer = tester.querySelector('#crossGaugeContainer');
alert(crossGaugeContainer);
}