3

I know that when you want to invoke a JavaScript function inside a HTML body section you can do it by putting <script> someFunction(); </script> inside your body tag, here is an example, I have HTML like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>

<head>
<script type="text/javascript"
    src="/Script.js"></script>
</head>

<body>
    <script>
        showAlert();
    </script>
</body>

</html>

And the javascript file like this:

function showAlert(){
    alert("This is an alert!");
}

This works fine but if I put the JavaScript file reference at the end of the body like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>

<head>
</head>

<body>
    <script>
        showAlert();
    </script>
    <script type="text/javascript"
        src="/Script.js"></script>
</body>

</html>

the function showAlert() is no longer being invoked. Can you please answer these 2 questions:

  1. Why is showAlert() not invoked in the second scenario?
  2. How (if possible) to invoke a function from a JavaScript file when it is referenced in the end of the body?

The reason why I'm asking is because I know that it is a good practice to refer your JavaScript files in the end of the body instead of the head, so that the page will be rendered first before loading all the JavaScript code.

Scimonster
  • 32,893
  • 9
  • 77
  • 89
Mykhailo Seniutovych
  • 3,527
  • 4
  • 28
  • 50
  • You can put Script files in the header as long as you make them "Asynchronous" –  Dec 18 '16 at 16:34

5 Answers5

5

1) The scripts are loaded linearly. Since the script has not yet been loaded, the function is undefined. (This is in contrast to function hoisting within a script.)

2) Simply wait till the page loads.

window.onload = function(){
    showAlert();
}

(Simply doing window.onload = showAlert won't work because of reason #1. Here you delay evaluation until such time that the function will exist.)

Scimonster
  • 32,893
  • 9
  • 77
  • 89
  • Thank you for your answer. It seems that my question was edited, I am using JSP file and I am calling `showAlert()` function only when some condition is true, like that: ` ` So I don't need to invoke `showAlert()` every time the page is loaded but only if the specified condition is true (so in HTML analogy it would be invoked only when I manually include the function call inside HTML). Do you/anyone know how can I achieve that? – Mykhailo Seniutovych Dec 19 '16 at 08:40
  • The exact same way; just wrap the `window.onload` etc in the JSP if. – Scimonster Dec 19 '16 at 09:07
  • are you suggesting that I should add JSP if inside my js file like this: ` window.onload = function showAlert(){ alert("This is an alert"); } ` because if yes then I don't think it's possible to add JSTL tags to a js file according to what I've read here [link](http://stackoverflow.com/questions/39944149/how-to-access-jstl-tag-from-javascript). If I don't add if to the js file itself and leave it like: `window.onload = function showAlert(){ alert("This is an alert"); }` showAlert will be called every time page loads no matter what's inside JSP – Mykhailo Seniutovych Dec 19 '16 at 12:19
  • @MykhailoSeniutovych No, with the whole js script tag in the JSP if tag. My solution is only to delay the execution, you can conditionally run it. – Scimonster Dec 19 '16 at 12:21
0

Javascript processes in the order given. You are trying to call showAlert before showAlert have been defined. Change to:

<body>
    <script type="text/javascript"
        src="/Script.js">
    </script>
    <script>
        showAlert();
    </script>
</body>

and all should work as intended.

aaa
  • 857
  • 4
  • 25
  • 46
0

Assuming you want to run showAlert() immediately when the page has loaded, try adding an onload() event handler to call showAlert rather than just calling it as the script loads. This can be done a few ways:

<body onload="showAlert();">

or define the window onload event programatically where your current function all is made in the html

window.onload = new function() {showAlert();}

or (and I think this is the preferred way because it won't cancel out other event handlers bound to the onload event)

window.addEventListener("load", showAlert);
hoekma
  • 793
  • 9
  • 19
  • I should also note that the addEventListener() also needs to run after the script has been defined. I like to add the addEventListener immediately after the function showAlert(){} within the same file to keep the related code together. – hoekma Dec 18 '16 at 17:31
0

By default, scripts run sequentially. Your code doesn't work because showAlert() runs before loading Script.js, so at that point the function showAlert is not defined yet.

To make it work, you must delay the showAlert call.

The load event has already been mentioned in other answers, but it will wait for all resources (like images) to load. So listening to the DOMContentLoad event is usually better, the function will be called sooner.

<script>
document.addEventListener('DOMContentLoaded', function() {
  showAlert();
});
</script>
<script src="data:text/javascript,
function showAlert() {
  console.log('Hello!')
}
"></script>
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • I think this reads more like a comment to [hoekma's answer](http://stackoverflow.com/a/41210543/3187556), or perhaps my own? (And sometimes we actually need to wait until all images load. Depends on `showAlert`'s implementation.) – Scimonster Dec 18 '16 at 16:48
  • @Scimonster And yours too – Oriol Dec 18 '16 at 16:49
0

The reason for your script isn't working is the way how a webpage is parsed..From top to bottom..Here is some link (would help to know why script added at bottom).

1) in your First case the browser loaded script when it parsed the page and when you called it in body it was available so it got invoked.

2) in Second scenario (My be typo) You have placed the call to function before loading the script that contain your function. so during page parsing browser wont find it and continue to next line where script containing function is loaded which has no effect for now as it already parsed the call.

If you still want to follow the second scenario you have to trigger the function call (after ensuring all resources being loaded ie Your script). so you can use window.load=<your function call> or in case of jQuery place it inside

$(document).ready(function(){
//call here
});
Community
  • 1
  • 1
RohitS
  • 1,036
  • 12
  • 17