Prokop Hapala
Prokop Hapala

Reputation: 2444

Body.onLoad seems to execute too early

EDIT : SORRY, PROBLEM IS DIFFERENT - It should be <textarea id="txtScene"> instead of <textarea name="txtScene">


It seems that <body onLoad="init();"> executes init(); before all HTML contend inside body is created.

I particular, have this HTML:

<script src="/home/prokop/Dropbox/MyDevSW/javascript/WebGL/shader_builder/GLSLscreen.js"></script>
<body onLoad="init_GLSLScreen();">
    <textarea name="txtScene" cols="60" rows="20" onChange="updateShader(this)">
        vec4 scene( Ray ray ){
            vec4 hit = vec4( POSITIVE_INF, vec3(0.0) );
            Sphere SURF1 = Sphere( vec3(0.0,0.0,0.0), 1.0 );
            Sphere SURF2 = Sphere( vec3(1.0,0.0,0.0), 0.75 );
            Sphere SURF3 = Sphere( vec3(0.0,1.0,0.0), 0.75 );
            vec2 ts1;
            ADD( SURF1 );
            SUB( SURF2 );
            SUB( SURF3 );
            return hit;
        } 
    </textarea>
</body>

and inside init_GLSLScreen() I need to run updateShader with textarea name="txtScene" as an argument. Like this

function init_GLSLScreen(){
    // ... some stuff ... don't care
    console.log ( document.getElementById("txtScene") );
    updateShader( document.getElementById("txtScene") );
    // ... some stuff ... don't care
}

But document.getElementById("txtScene") returns null

The problem is described here with solution to either move the javascript below HTML (I guess not possible in my case) or to run the javascript onLoad ... which I do but does not work.


Striped down code which reproduces this behaviour (if you look into web-console)

<!DOCTYPE html>
<html>
<head>
    <title>05.10 - Custom fragment shader</title>
    <style>
        body { margin: 0; overflow: hidden; }
    </style>
</head>
<script>
     function init_GLSLScreen(){
        console.log ( document.getElementById("txtScene") );
        console.log ( document.getElementById("txtScene").value );
    }
</script>
    <body>
        <textarea name="txtScene" cols="60" rows="20" onChange="updateShader(this)">
            sfsdjfskldjflj
        </textarea>
    </body>
    <script>
     init_GLSLScreen();
    </script>
</html>

Upvotes: 1

Views: 803

Answers (2)

David Nelson
David Nelson

Reputation: 31

You could always move your function execution to the bottom of the html, just before the closing body tag. This will ensure that everything is loaded in the DOM.

<script>
   init_GLSLScreen();
</script>

Upvotes: 1

Avitus
Avitus

Reputation: 15968

If you can include jquery then it's a matter of wrapping your code in $(document).ready(function() {}); see: https://learn.jquery.com/using-jquery-core/document-ready/

if you can't /don't want to include jquery then I would get the javascript that makes up the source of the .ready function in jquery that way you can duplicate the same functionality.

See here for a plan: $(document).ready() source

If you wanted to use jquery you can just do this:

<script
  src="https://code.jquery.com/jquery-1.12.4.js"
  integrity="sha256-Qw82+bXyGq6MydymqBxNPYTaUXXq7c8v3CwiYwLLNXU="
  crossorigin="anonymous"></script>
<script src="/home/prokop/Dropbox/MyDevSW/javascript/WebGL/shader_builder/GLSLscreen.js"></script>
<script>
    $(document).ready(function() {
        init_GLSLScreen();
     });
</script>
<body >
    <textarea name="txtScene" cols="60" rows="20" onChange="updateShader(this)">
        vec4 scene( Ray ray ){
            vec4 hit = vec4( POSITIVE_INF, vec3(0.0) );
            Sphere SURF1 = Sphere( vec3(0.0,0.0,0.0), 1.0 );
            Sphere SURF2 = Sphere( vec3(1.0,0.0,0.0), 0.75 );
            Sphere SURF3 = Sphere( vec3(0.0,1.0,0.0), 0.75 );
            vec2 ts1;
            ADD( SURF1 );
            SUB( SURF2 );
            SUB( SURF3 );
            return hit;
        } 
    </textarea>
</body>

Upvotes: 0

Related Questions