1 00:00:00,000 --> 00:00:04,780 [MUSIC] 2 00:00:04,780 --> 00:00:09,159 So far other JavaScript we've been writing is being loaded at the bottom of the file. 3 00:00:09,159 --> 00:00:13,484 So let's move the script tag to the top into the head section and 4 00:00:13,484 --> 00:00:17,420 see if it has any effect on our application. 5 00:00:17,420 --> 00:00:22,600 I'll switch over to the browser, and refresh and the check box disappeared. 6 00:00:22,600 --> 00:00:25,050 So now I'll submit a name. 7 00:00:25,050 --> 00:00:29,700 We see that the browser refreshes, and if I open the console. 8 00:00:29,700 --> 00:00:34,200 I see that the browser can't find a query selector of null on line 2. 9 00:00:35,510 --> 00:00:38,090 So let's go back, and look at line 2 of our code. 10 00:00:39,530 --> 00:00:44,084 And here we see that query selector is being 11 00:00:44,084 --> 00:00:48,773 called on form which our error says is null. 12 00:00:48,773 --> 00:00:52,858 Well, on line 1 form was declared by calling 13 00:00:52,858 --> 00:00:56,629 getElementById on the document object. 14 00:00:56,629 --> 00:01:00,357 But this was apparently unsuccessful because the constant form holds 15 00:01:00,357 --> 00:01:01,760 a null value. 16 00:01:01,760 --> 00:01:03,960 Now switching over to index.html, 17 00:01:03,960 --> 00:01:08,610 we see that there's definitely a form with the ID registrar. 18 00:01:08,610 --> 00:01:11,630 So the reason it's failing to select the form 19 00:01:11,630 --> 00:01:15,640 is because we've moved this script tag to the top. 20 00:01:15,640 --> 00:01:18,560 You see, when the browser loads index.html, 21 00:01:18,560 --> 00:01:22,890 it reads it from top to bottom assembling it as it goes. 22 00:01:22,890 --> 00:01:26,490 The browser runs the JavaScript file before it even looks at the body element 23 00:01:26,490 --> 00:01:30,300 much less anything inside the visible portion of the DOM. 24 00:01:30,300 --> 00:01:34,098 So none of the elements even exist at the time app.js looks for them. 25 00:01:34,098 --> 00:01:38,970 Now when app.js was at the bottom of the document, this was not an issue 26 00:01:38,970 --> 00:01:44,390 because all the HTML had loaded before the browser ran into the JavaScript code. 27 00:01:44,390 --> 00:01:49,107 So you may not always have control over when your JavaScript code is loaded. 28 00:01:49,107 --> 00:01:51,278 For example you might be working on a team and 29 00:01:51,278 --> 00:01:55,320 are asked to write a JavaScript library to handle some form validation. 30 00:01:55,320 --> 00:01:59,070 That code is given to another developer who adds it to the top of the page instead 31 00:01:59,070 --> 00:02:00,680 of the bottom of the HTML. 32 00:02:00,680 --> 00:02:04,770 Well, fortunately, you can program defensively, preparing your scripts for 33 00:02:04,770 --> 00:02:07,390 this type of problem, pretty easily. 34 00:02:07,390 --> 00:02:10,270 We can make a minor modification to our code, so 35 00:02:10,270 --> 00:02:14,100 it makes no difference where the HTML loads app.js. 36 00:02:14,100 --> 00:02:17,170 The DOMContentLoaded browser event 37 00:02:17,170 --> 00:02:21,460 triggers when all of the DOM has been parsed and loaded into the browser. 38 00:02:21,460 --> 00:02:25,270 That event signals that it's safe to select elements, manipulate them or 39 00:02:25,270 --> 00:02:26,880 set listeners on them. 40 00:02:26,880 --> 00:02:31,685 So we can wrap all the code we've written so far inside a listener for 41 00:02:31,685 --> 00:02:33,972 this DOMContentLoaded event. 42 00:02:33,972 --> 00:02:37,820 And the browser will load our code, after the DOM is fully loaded. 43 00:02:39,190 --> 00:02:41,360 Switching over to app.js, 44 00:02:41,360 --> 00:02:45,750 I'm going to insert a listener at the very top of the page. 45 00:02:45,750 --> 00:02:51,000 Now the document object always exists even if it doesn't contain 46 00:02:51,000 --> 00:02:52,920 all the parsed HTML yet. 47 00:02:52,920 --> 00:02:57,160 So we can call document, and then add an event listener to it. 48 00:02:58,820 --> 00:03:03,866 The event is DOM content loaded, so I'll enter that string as a first 49 00:03:03,866 --> 00:03:10,421 argument, Then for the second argument, 50 00:03:10,421 --> 00:03:13,530 I want to wrap all the code in the file into a callback function. 51 00:03:16,860 --> 00:03:20,160 So I'll leave the curly brace open here, and 52 00:03:20,160 --> 00:03:23,362 scroll all the way to the bottom of the file to close it. 53 00:03:23,362 --> 00:03:26,300 Then I'll close the parentheses. 54 00:03:27,910 --> 00:03:31,005 Now let's indent all the code inside this new listener. 55 00:03:35,249 --> 00:03:38,200 We'll save our file and switch back to the browser. 56 00:03:39,330 --> 00:03:45,560 Now when we reload the page, we see that the check-box is back and 57 00:03:45,560 --> 00:03:50,446 entering a name and clicking on the buttons works. 58 00:04:02,450 --> 00:04:06,216 So what's happening now is the browser is loading the code but 59 00:04:06,216 --> 00:04:11,680 it's waiting until the page is loaded before running our code against it. 60 00:04:11,680 --> 00:04:16,090 Now our script can be placed anywhere on the page and it will always work. 61 00:04:16,090 --> 00:04:21,730 But I'm going to move the script tag back down just before the closing body tag. 62 00:04:21,730 --> 00:04:26,400 Generally it's better if JavaScript is loaded after HTML and CSS. 63 00:04:26,400 --> 00:04:30,020 Because on slow connections users will still be able to see the app sooner. 64 00:04:30,020 --> 00:04:32,790 Which is a better experience than staring at a blank page while 65 00:04:32,790 --> 00:04:33,870 the JavaScript loads.