views:

194

answers:

7

so I have an external javascript file, lets call it something.js and i document.write it to the document. For some reason, I cant access the function in Safari or FireFox.

It goes a little something like this:

<script type="text/javascript">
    document.write(decodeURI("%3Cscript src='something.js' type='text/javascript'%3E%3C/script%3E"));
    myFunction();
</script>

so this tells me myFunction is null, but if i put that same function call at the end of something.js, it works. Now this isnt the exact scenario, so I am aware that for this particualr case, this is not the best way to go about it.

+2  A: 

I think this happens because myFunction(); is called before the whole .js file that contains it loaded in the browser, try to delay myFunction(); call few seconds and test again to make sure that this is the problem.

Amr ElGarhy
if i delay it for 2 seconds, will it delay my page from loading for 2 seconds?
Russ Bradberry
it may, yes! ...
Cheeso
yes specially if this script code exists in the beginning of your page code
Amr ElGarhy
then that really isnt a viable solution as i cannot keep the page form loading.
Russ Bradberry
You can use a settimeout javascript function and call the function again after few seconds if the previous call failed
Amr ElGarhy
or check if a variable inside the .js filed got a value and not = undefined
Amr ElGarhy
A: 

After you print the script inclusion tag using document.write the browser continues execution (trying to invoke myFunction()) before it loads external script. So, your script is not available yet.

Marko Dumic
+3  A: 

Here's how I do it:

<script type="text/javascript" language='javascript'>
  document.write('<script type="text/javascript" id="contentloadtag" defer="defer" src="something.js"><\/script>');
  var contentloadtag=document.getElementById("contentloadtag");
  contentloadtag.onreadystatechange=function(){
    if (this.readyState=="complete") { myFunction(); }
  }
</script>

Really, this makes sense only at page load time. If you are repeatedly downloading script in a dynamic fashion, you probably want to take a different approach, namely JSONP.

Cheeso
This is better than accepted answer because you can not guarantee that any fixed amount of seconds is enough for a script to load.
Marko Dumic
yes this is better and more complete than my accepted answer
Amr ElGarhy
this works great and seems much more solid than checking every 2 seconds
Russ Bradberry
A: 
  1. Put your dynamic script block in the head of your document (if it isn't already)
  2. Remove the myFunction() call.
  3. Put myFunction() call in a different script block somewhere lower on the document.

Step 1 is a best practice, but I don't think any browser will choke if you dynamically include the JS file at some other point in the document.

The key point is that you can't make use of included JS code from within the same script block that does the inclusion.

This works in Firefox, I can't vouch for Safari.

<html>
    <head>
        <script type="text/javascript">
            document.write(decodeURI("%3Cscript src='something.js' type='text/javascript'%3E%3C/script%3E"));
        </script>
    </head>
    <body>
        <script type="text/javascript">
            myFunction();
        </script>
    </body>
</html>
E-man
A: 

I wouldn't normally write two separate answers, but this a very different answer, that's just as likely to work.

Put a call to something_ready() at the bottom of something.js. Don't define something_ready() in something.js, define it in your html document.

So no timers, no unneeded checking.

    <script type="text/javascript">
        document.write(decodeURI("%3Cscript src='something.js' type='text/javascript'%3E%3C/script%3E"));

        function something_ready(){
            myFunction();
        }
    </script>

That will work, it just assumes that you have access to something.js, which you may not. If not, the other answer I provided will work.

E-man
A: 

Does this work?

<script type="text/javascript">
document.write(unescape("%3Cscript src='something.js' type='text/javascript'%3E%3C/script%3E"));
document.write("<"+"script type='text/javascript>myFunction();<"+"/script>");
</script>
Tracker1
A: 

The easiest way to do this is to write two <script> blocks.

<script type="text/javascript">
    document.write(decodeURI("%3Cscript src='something.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
    myFunction();
</script>

When document.write is used, the text is written directly into the document, right after the <script> tag. Because of this, when a browser encounters a <script> tag, it waits for the script to finish loading before continuing down the page. Any document.write that happens in the loaded script might affect the rest of the page (for example, if you do "document.write('<div>')", it will affect the rest of the layout).

So, if you use two <script> tags, the first one is encountered by the browser, and it uses document.write to output a new <script> tag. As soon as that <script> tag is finished, the browser continues down the page, and immediately encounters the new, dynamically added <script> tag. This <script> tag tells the browser to load your external Javascript. The browser will wait to execute the second original <script> tag until this <script> tag has finished loading. Then your function myFunction will be available.

The reason doing it all in one <script> tag doesn't work is because document.write doesn't happen until after the <script> has finished running (myFunction isn't available yet). The reason it works with two <script> tags is because the browser waits until each <script> tag runs in succession, and document.write puts a new <script> tag in line.

thirdender