Showing results for 
Search instead for 
Did you mean: 

Show and disable local script(ThreeJS)

Show and disable local script(ThreeJS)

Established Member

Hello All,

I have made a local script containing a simulation in Threejs.

This works pretty good when only using the local script. However, now I want to show this local script inside a window inside my 'main' HMI. The issue I have is that I cannot correctly show the ThreeJS visualisation inside this window.

When I switch to this screen, the visualisation appears underneath the screen, not inside the container. 

And when I switch screens, the visualisation remains to be visiable under the screen. But it should be closed. 



I am not too familiar with javascript. Is there anything I am doing wrong?





WebIQ does not have any "Window" widget - are you talking about a dialog?

In any case this looks more like a general JavaScript question or ThreeJS question than a WebIQ question to me.

With the limited given information: you are probably rendering ThreeJS inside the wrong HTML element.


You are right. What I meant to say is that I created a screen. The screen contains a container. And inside this container I call the local script.

I agree that this is a more general question. I am fairly new with programming in Javascript so sometimes it's a little hard to differentiate webiq and javascript. I based the script on this WebIQ - Render a 3D model ( tutorial. 

I will look for more information on this subject online, 

Thank you anyway. 



I did some furter investigating. And you are absolutely right.

The threejs script is rendered in a seperate HTML element like this:

        // Add 3D rendering div to document
        var body = document.body;
        let container = document.createElement( 'div' );
        body.appendChild( container );
After opening the screen with the local script, the newly created div appears underneat the HTML created by web-iq.
I would like to render it in the container called: threejs_script.


I tried doing it like this: body = document.getElementsByName("threejs_script") but this does not work. 

When I log the shmi.ctrl(".threejs_script") it appears that the object does exist.



 I am aware that this has noting to do with webiq. But I am a bit lost.

Is there a way to render the threejs script inside the container I created via webiq?

Thank you so much!

1. document.getElementsByName("threejs_script") is looking for an HTML element that has an attribute with the name "threejs_script" - please see

2. shmi.ctrl(".threejs_script") - we are working with modern web technology here which is asynchronous so the script might not have been loaded. In any case this would not help as you have to change where the script renders the element - changing the position of the LocalScript will not make any difference here.

3. "Is there a way to render the threejs script inside the container I created via webiq?" - it all comes down to an HTML element where you have to insert the ThreeJS element. As WebIQ is completely web-based a container is simply a <div> HTML tag.

I can't help you any further as it is impossible to know what your code does without seeing the code utilizing ThreeJS


This is the code containing the threejs objects. 
But I think you would need my full project. Is there an easy way to share this?


Nevermind, I have solved it with your hint "simply a <div> HTML tag".

I was thinking too complicated. I insterted a HTML widget with a new DIV. And inside the script I use this DIV. 

Easy as that.

Thank you for your help and time. Much appreciated. 




The code does exactly what you're telling it to do: append the ThreeJS object to the end of the HTML document. I highly recommend getting to know JavaScript better - there are lots of free resources available, otherwise you'll run into such issues over and over again probably.

Remove this code:

let container = document.createElement( 'div' );
body.appendChild( container );

Wrap all of your code inside the method (excluding the self.onDisable code) inside this code:

        controls: {
            cont: ".YOUR_CONTAINER_NAME"
    }, function (resolved) {
        const myContainer = resolved.controls.cont,
            container = myContainer.element;

            // Put all your code in here (except onDisable)!
            // ...
            // ....


Name your container where you want to add it YOUR_CONTAINER_NAME.

Your code also causes memory leaks as you're always creating a new listener when the LocalScript is executed and storing it in the variable tok, but never unsubscribe. Rename tok to subscriptionToken to fix this issue (see onDisable!)

As I wrote before everything is executed asynchronously so we have to wait until our container widget has been initialized! Only then ThreeJS can actually find the HTML element we want to use.

I haven't tested the code above, but it should work.

This code can wreak havoc - you now have created invalid HTML code - you cannot have two <body> elements in your HTML code! However, browsers are extremely tolerant, unfortunately. Whatever happens here is undefined. However, removing the <body></body> should work.

Also, this might work or might not work all depending on timings - this means that it might work on your (fast) system, but it might not work on other systems or only intermittently.

Therefore you should always use shmi.onReady to wait for widgets!