0

I am trying to read data from another file and use this data in HTML (x3d, to be more precise).

In order to do that, I am using $.getJSON to read the data, and $("div").html( "*html code*" ), using variables inside the html code to display the data in a website.

The problem is that *$("div").html( "html code" )* is executed before the data is read by $.getJSON.

Here is my code:

<html> 
    <head> 
        <title>Superficie soja 63</title>           
        <script type='text/javascript' src='http://www.x3dom.org/download/x3dom.js'> </script> 
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <link rel='stylesheet' type='text/css' href='http://www.x3dom.org/download/x3dom.css'></link> 
        
    </head> 

    <body> 
        <h1>Superficie soja 63</h1> 
        
        <div></div>
        <script>
            var a = [];
            var b = [];
            var c = [];
            var tria = [];
            var trib = [];
            var tric = [];
            var str = "";
            var str_tri = "";

            $.getJSON("dados_teste.json", function(data) {
                for(var cont in data.pontos){
                        a.push(data.pontos[cont].x);
                        b.push(data.pontos[cont].y);
                        c.push(data.pontos[cont].z);

                        str += (`${a[cont]} ${b[cont]} ${c[cont]}, `);
                }
                str = str.slice(0, -2);
            });

            $.getJSON("tri_teste.json", function(data) {
                for(var cont in data.triangulos){
                    tria.push(data.triangulos[cont].tri_a);
                    trib.push(data.triangulos[cont].tri_b);
                    tric.push(data.triangulos[cont].tri_c);

                    str_tri += (`${tria[cont]} ${trib[cont]} ${tric[cont]}, `);
                }
                str_tri = str_tri.slice(0, -2);
            });

        setTimeout(() => {  console.log(str); }, 1000);
        setTimeout(() => {  console.log(str_tri); }, 2000);

        $("div").html( ` 

            <x3d width='1000px' height='1000px'> 
                <scene> 
                    <shape> 
                        <appearance>
                            <ImageTexture 
                            url='https://thumbs.dreamstime.com/b/macro-soybean-food-texture-background-top-view-96368287.jpg'/>
                        <TextureTransform
                            translation='0 0'
                            rotation='0'
                            repeats='true'
                            repeatt='true'
                            scale='80 80'/>
                        </appearance>
                        
                        <IndexedTriangleSet 
                            ccw='true' 
                            colorPerVertex='true' 
                            index='${str_tri}'
                            normalPerVertex='true' 
                            solid='false'
                            containerField='geometry'>
                            <Coordinate id="teste"
                                point='${str}'/>
                            <Viewpoint
                                position='0 0 10'
                                orientation=''
                                description='camera'/>
                        </IndexedTriangleSet>
                    </shape> 
                </scene> 
            </x3d> ` )

    </script>

    </body> 
</html>

I already tried using setTimeout() and delay() to solve this problem, but it looks like the $.html() function ignores other functions and is always executed first.

If I simply assign the data directly to the variables, it works. The problem is that I need to read a JSON file to get the data.

How can I solve this problem?

EDITED: I just found out that this problem only happens when I use X3D inside the HTML. With normal HTML, $.html() works fine. But with X3D, the function $.html() doesn't behave properly. So I am still trying to figure out how to solve this problem.

E_net4
  • 27,810
  • 13
  • 101
  • 139
  • Does this help you? https://stackoverflow.com/questions/10775787/function-wait-with-return-until-getjson-is-finished – dev55555 May 13 '21 at 19:05

3 Answers3

0

I tried making this code work in many different ways using javascript and figured out that the problem was the X3D. All the answers posted so far make sense, but they don't work when there is X3D included in the HTML code.

So I decided to use PHP instead, and now it is working!

<html> 
    <head> 
        <title>Superficie soja 63</title>           
        <script type='text/javascript' src='http://www.x3dom.org/download/x3dom.js'> </script> 
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <link rel='stylesheet' type='text/css' href='http://www.x3dom.org/download/x3dom.css'></link> 
        
    </head> 

    <body> 
        <h1>Superficie soja 63</h1> 

        <?php
            $path = "dados_teste.json";
            $file = fopen($path, "r");
            $data="";
            while(!feof($file)){
                $data .= fread($file, filesize($path));
            }
            fclose($file);
            $data= json_decode($data, true);
            $str="";
            for($cont=0; $cont < count($data["pontos"]); $cont++){
                if($cont < count($data["pontos"])-1)
                    $str .= ($data["pontos"][$cont]["x"] . " " . $data["pontos"][$cont]["y"] . " " . $data["pontos"][$cont]["z"] . ", " );
                else
                    $str .= ($data["pontos"][$cont]["x"] . " " . $data["pontos"][$cont]["y"] . " " . $data["pontos"][$cont]["z"] );
            }
            
            $path = "tri_teste.json";
            $file = fopen($path, "r");
            $data="";
            while(!feof($file)){
                $data .= fread($file, filesize($path));
            }
            fclose($file);
            $data= json_decode($data, true);
            $str_tri="";
            for($cont=0; $cont < count($data["triangulos"]); $cont++){
                if($cont < count($data["triangulos"])-1)
                    $str_tri .= ($data["triangulos"][$cont]["tri_a"] . " " . $data["triangulos"][$cont]["tri_b"] . " " . $data["triangulos"][$cont]["tri_c"] . ", " );
                else
                    $str_tri .= ($data["triangulos"][$cont]["tri_a"] . " " . $data["triangulos"][$cont]["tri_b"] . " " . $data["triangulos"][$cont]["tri_c"] );
            }

            echo "
            <x3d width='1000px' height='1000px'> 
                <scene> 
                    <shape> 
                        <appearance>
                            <ImageTexture 
                            url='https://thumbs.dreamstime.com/b/macro-soybean-food-texture-background-top-view-96368287.jpg'/>
                        <TextureTransform
                            translation='0 0'
                            rotation='0'
                            repeats='true'
                            repeatt='true'
                            scale='80 80'/>
                        </appearance>
                        
                        <IndexedTriangleSet 
                            ccw='true' 
                            colorPerVertex='true' 
                            index='${str_tri}'
                            normalPerVertex='true' 
                            solid='false'
                            containerField='geometry'>
                            <Coordinate
                                point='${str}'/>
                            <Viewpoint
                                position='0 0 10'
                                orientation=''
                                description='camera'/>
                        </IndexedTriangleSet>
                    </shape> 
                </scene> 
            </x3d>
            ";
        ?>

    </body> 
</html>

My conclusion is: if you are working with X3D, it might be better to use a back-end programming language.

-1

Im not an expert in jQuery, but by rapidly looking it up, I think you should try the .then() function after the getJSON, and then write the rest of the code inside the then brackets. An example of this is used in this question

Also, instead of .then(), you could use the .done() as specified in this link (you will have to scroll down a little to see the .done() examples)

Another alternative would be to add your $("div").html() inside the getJson call back function, like this:

 $.getJSON("dados_teste.json", function(data) {
     //your current code
     //you $("div").html() code
 }

let me know if this answer is helpful :)

mvoelcker
  • 330
  • 4
  • 8
-1

Trying to time the execution of one task with the beginning of another is called a race condition and should be avoided. Instead call your .html() AFTER you have received your variables. Because you have 2 separate dependent processes creating variables, you can just check for them in the makeDiv() function.

var str, str_tri
 $.getJSON("dados_teste.json", function(data) {
               ...
                str = str.slice(0, -2);
                makeDiv();
            });
 $.getJSON("tri_teste.json", function(data) {
               ...
                str_tri = str_tri.slice(0, -2);
                makeDiv();
            });


function makeDiv() {
 if (!str || !str_tri || str =='' || str_tri == '') return;
 $("div").html( `......`);
}
Kinglish
  • 23,358
  • 3
  • 22
  • 43
  • Well, I guess I spoke too soon. My code didn't consider that you had 2 variables you were waiting on, and as such did deserve a downvote. I revised my answer, let me know if it helps. – Kinglish May 13 '21 at 21:58
  • @LucasVoelcker - did that help at all? – Kinglish May 14 '21 at 00:31
  • I realized that your solution works for normal HTML, just like the other solutions answered here also make sense. The problem is the X3D. When I use X3D inside the HTML, the $.html() doesn't work properly. So I figured that maybe javascript is not the best language to use with X3D. I tested now with PHP and it worked! – Lucas Voelcker May 14 '21 at 13:26