0

Here's a basic example of what's happening. I can understand that I'm probably calling the function in body before it's defined but then why is it so common to put javascript at the bottom of the page? I know my boss is going to say use bottom javascript so what should I do?

Also the root issue is when the page is first loaded, if there is a username from the server I need to run the CheckUsername() function. So is there a better way to do it conditionally?

<body>
    <input type="text" name="username" 
        id="username" onblur="CheckUsername()" 
        maxlength="30" value="@username"  />

    @if (username.length > 5) 
    {
         <script>
            CheckUsername(); // this is the one that's undefined
         </script>
    }  

    @section bottomjavascript
    {
        <script language="JavaScript">

            function CheckUsername() {
                // does work
            }

        </script>
    }


</body>

The actual body tags come from the master layout. But why can I use CheckUsername in the input tag, but I can't just call it on the page?

I decided to just remove the @section bottomjavascript so it wouldn't move any scripts in there below the body tag.. Not really a solution since this page no longer uses the master section for javascript but it works now

Alex
  • 141
  • 1
  • 11

4 Answers4

1

Put the function definition before the first call. When you call it the first time, the parser does not know what CheckUsername() is. So do this:

<body>
    <input type="text" name="username" id="username" onblur="CheckUsername()" maxlength="30" value="@username"  />

@section bottomjavascript
{
    <script language="JavaScript">

        function CheckUsername() {
            // does work
        }

    </script>
}
     <script>
$(document).ready(function() {
    if (@{username.length} > 5) 
    {
        CheckUsername(); // this is the one that's undefined
    }  
});
     </script>

</body>

I normally put these functions in there own js file and reference them in the head of the document. That way it is defined when I need it below.

If you put the code in document.ready, then all js files should be loaded and you will be able to run the function. To do that, you have to put your if statement from razor into js.

Nate
  • 761
  • 1
  • 8
  • 27
  • Well I figured I'd have to put it after the definition, but why does it work in the inputs onblur? And I didn't want to put it below the definition because I felt like it would get lost below all the other javascript on the page. But my main question is why does it work in onblur? – Alex Dec 02 '15 at 18:16
  • The onblur works because it is an event, and it is processed after all parsing is done. – Nate Dec 02 '15 at 18:17
  • Also there's an unexpected error that @section bottomjavascript is used in the master layout and goes below _everything_ on this cshtml page. So even when I move the call below the definition, on the actual rendered page it still ends up before it... – Alex Dec 02 '15 at 18:19
1

Make the check execute when the page is loaded, like this:

@if (username.length > 5) 
{
     <script>
        window.addEventListener("load", function() {
            CheckUsername();
        });
     </script>
}  

It does not matter where this script ends up: top, bottom, ... does not matter.

trincot
  • 317,000
  • 35
  • 244
  • 286
  • Well technically it's saying CheckUsername is undefined in that addEventListener line. I've tried putting in on top of my bottomjavascript section and below it. – Alex Dec 02 '15 at 19:14
0

Adding Javascript before the </body> tag is recommended to prevents render blocking while the scripts load and is much better for site perception head. Adding Javascript before the </body tag will also improve the site loading speed.

You can find more about this on this topic: JavaScript in <head> or just before </body>?

Community
  • 1
  • 1
Md Mazedul Islam Khan
  • 5,318
  • 4
  • 40
  • 66
0

To answer one question, script tags should be put just before </body> i.e just before the end of the document.

Why?

With stylesheets, progressive rendering is blocked until all stylesheets have been downloaded. Thats why its best to move stylesheets to the document HEAD, so they get downloaded first and rendering isnt blocked. With scripts, progressive rendering is blocked for all content below the script.

Use this:

<script>
    window.addEventListener("DOMContentLoaded", function (event){
    //do stuff
    });
</script>

This checks if the page is fully loaded before firing off your function. Libraries e.g., jQuery $(document).ready automatically does this for you.