Application Design Patterns -- The Modern JavaScript Bootcamp

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we're going to discuss the first application we're going to build the goal of this application is to practice your javascript skill set we're not going to be covering a lot of new features of the language instead we're going to be focusing on a lot of the stuff that we've already learned and really practicing our skill set let's take a look at some mock-ups to help you get an idea of what we're going to try to build so we're going to be making an application called movie fight the idea here is that a user is going to search for a movie on the left hand side of the screen and a different one on the right hand side of the screen so a user is going to type in some movie title and then once they search for it we're going to fetch some information about that movie and show information about it on the left hand side of the screen so in this case a user might have searched for dark knight and so i would pull up some information about the movie the dark knight this little box right here with an x represents the image or the movie poster for the dark knight movie so we're gonna show the poster for the movie right there and then some stats about the movie underneath it so for example how much money it made and it's critic critical rating and so on once a user searches for a movie on the left hand side they're then going to repeat that same process on the right hand side so we can imagine that a user might type in a different movie over here like the avengers and we will show some information about the avengers in a very similar fashion on the right hand side now here's what makes this application an actual like movie fight application for every different stat that we fetch about every different movie we're going to compare them between the two whichever movie has a higher statistic we're going to highlight in green and whichever movie has the lower statistic we're going to show in yellow so in this case the avengers made a lot more money at the box office than the dark knight so we would color that statistic as green and we would color the dark knight statistic as yellow however the dark knight might have a higher critic rating so we'll show that as green and the avengers one will be displayed as yellow instead so that's the application there is one last thing i want to mention here kind of a very specific thing because we actually are going to be spending a pretty good amount of time on this when a user searches for a movie like in these two inputs right here a user might not know exactly what movie they're looking for they might have some kind of idea of what the title is but they might only be able to remember that like has dark in the title if they are trying to find dark knight so these two inputs right here are not going to be normal inputs instead we're going to make them into kind of autocomplete inputs so whenever a user types in something like just dark or even dark knight we're going to have a little pop-up listing right here that shows a couple of different movies related to the search term that they just entered so to actually select a movie and start the comparison a user would have to click on that entry right there and that would select the dark knight that was made in the year 2008 on the left hand side of each of these movie titles we're also going to show the poster for the movie as well this is going to be a separate little auto complete widget that we put together as a part of this project we're going to build that autocomplete widget from scratch and as a matter of fact everything you see in this application is really going to be from scratch so we're going to get a really good idea of how to approach this app how to build it and eventually we're going to deploy it okay so i hope you're as excited as i am this is going to be a really fun application so let's take a quick pause right here and start working in the next video now that we have a better idea of what we're trying to build let's get started working on this application before we write any code however i want to go through a couple of different steps here to make sure that we've got a really solid plan on how we're going to tackle this application the first thing we're going to do is set up a little boilerplate for our project so attached to this video there is a zip file that has some starter files inside of it if you haven't downloaded that zip file already then pause the video and download the zip file right now i've already downloaded that zip file and i've extracted its contents onto my computer so inside of that zip file are three different files the index.html file a javascript file and a css file once you get those files on your computer make sure you also open them up inside of your code editor so i've already done that right here here's the html file the javascript file and the css one and then finally make sure you open up the index.html file inside of your browser once you do so you're going to see a initial screen like this right here okay so once we've got that all set up i want to very quickly just mention exactly what this term boilerplate is referring to when we talk about a boilerplate package we're talking about some essentially starter code for a project usually a boilerplate will have a little bit of setup already done inside of it and usually it's going to have some code or html or styling that is generally kind of repetitive between different projects so it's really just a good starter point to begin from i know that sometimes using a starter package is kind of annoying and you might prefer to write out everything from scratch so you really understand what is going on just so you know the only real setup that i've done inside of this little boilerplate package is for the most part just some styling so just some css to make sure that the end product that we end up with is going to look really nice this is a course about javascript and not css and that's why i did all the css for you up front you can of course review that css file at the end of this application and get a better idea of what's going on inside there if you want to okay so now that we've got a little bit of setup done let's take a pause right here and then identify some challenging aspects of this project in the next video whenever i start working on a new project either a personal project or a professional one i really like to sit down and identify some of the big problems that i anticipate that i'll run into as i'm working on that project so i want to do that right now really quickly we're going to identify some of the more challenging aspects of this application and get an idea on how to solve each one i've already gone through and thought up some of the big kind of challenging things that we're probably going to have to wrestle with as we build this app so we're going to talk about some of these big challenges and then go over some possible solutions to each of them as well so the first thing we need to think about is where we're going to actually get some information about different movies i want to show real data inside this application i don't want to just like make up movies or anything like that there's probably two obvious ways that we could handle getting some information about movies into our application the first obvious way and this is probably not a good one would be to write in or hard code some information about a bunch of different movies right into our javascript file so we could create a really big array and write in some movies like maybe the 100 most popular movies out there directly into that array that's not really a good solution however because it means that any time that we wanted to add in more movies we would have to make a change to the source code of our application in general that's not really a good thing to do so instead i think that we should attempt to fetch some data about movies inside of our javascript code when i say fetch i mean let's make a network request to some outside api so we should try to find some outside api or essentially a server that will give our application a list of movies that we can search over or show details from so for that we're going to be making use of an api called the omdb api this is a free api that we can use to get information about different movies i'm going to open up a new browser tab and navigate over there right away okay so you can read over the documentation here this api essentially exposes two different endpoints for us to use if we scroll down a little bit we can see parameters right here and this will describe the different ways that we can access movie information we can either search for movies so that would be reading from this by search category right here or alternatively we can look up very specific movies if we know the id or the title of a movie so these two operations match up with our application really really well just think about it for a second if we go back over to our mock-ups over here there's really two different operations that are going on around these movies inside of our application the first distinct operation is when we do a search with the autocomplete so when a user types in there we need to essentially try to find movies that match a given search term so that's really a searching operation we want to find a big list of different movies that match that particular term when a user finds the appropriate movie and clicks on it we then want to fetch some additional information about that very particular movie right there and we're going to take that additional information and show it on the screen so again it's really a two-step operation we first are going to do a search and then we're going to do a very distinct lookup now you might be curious why we have to do both a search and a lookup and not just a search by itself in other words if we're already doing a search for a bunch of movies and getting information about like 10 different movies as we are putting in results into that autocomplete can't we just use that same data that we just fetched to put on the screen well as a quick side note here the way that a lot of apis work is to give different sets of data depending upon whether you're doing a listing action or a show action or trying to get information about one record let me tell you more about what i mean so in this diagram i've got some imaginary search results from two different operations on an api on the left hand side is the set of information that we might get back if we do a search or a listing or what we refer to as an index operation so this is what we would see if we tried to get a list of different movies we might just get a very limited set of attributes about every movie like just the id of the movie and just the title so when we do an index or a search operation we very frequently don't get the full listing of information about every individual record instead if we want to get the full listing and we want to understand every attribute that a movie has we usually end up having to do a follow-up request where we say hey give me some details about the movie with id number one and then the api will probably respond with a full set of attributes essentially everything that it knows about that particular movie a very easy way to understand this is to just think about google search results when you do a google search you don't see an entire web page instead google just shows you some high-level attributes of every web page that it founds that it excuse me that it finds that matches your query if you want to actually get some details about any given web page you actually have to click it and so that would be like a selection or a show operation so it's going to be the exact same thing with the api we are using we're going to have to do initially a search to find some records that match the user search term and then a follow-up request to get information about the very particular movie that a user selected okay so that's big challenge number one don't worry the other challenges are a little bit easier to understand so the second big thing that we're going to have to do is to build an auto complete widget from scratch there's definitely some pre-completed or pre-built widgets out there online that we could download and use inside of our code however it would be a really good learning opportunity to put together our own autocomplete so i think we should do that inside of our project now i don't really have a lot to say about this challenge until we really start tackling it and writing code but i think that at least at a minimum you and i should really sit down and really agree on how an autocomplete widget works in general if we just tried to write out some autocomplete logic right away well you and i might have really different ideas about how an autocomplete works and even like you personally you might have some idea about how an autocomplete works and then you might start writing some code and then realize that the code you're writing doesn't really match up with what you thought personally about an autocomplete so in other words i think that we really just need to sit down and say this is how an autocomplete widget works so we're going to do that in a separate video okay last thing here the app would definitely look a lot better with styling in css like i mentioned the starter kit that we're using has a css a little bit of css written into it and it also makes use of a css framework called bulma css so this is stuff that has already been wired up for you we're going to have a quick discussion or two about css as it pertains to this application in particular we're going to take a little look at bulma css just really as a side topic again this is a course about javascript nonetheless you might be curious about it so we'll do a little quick aside just to understand what's happening with this thing okay so that's it that's our big challenges so let's take a pause right here now that we have a better idea of what we're trying to build we've identified some of the hard things about this project we're going to get started writing code in the next video so quick pause and i'll see you in just a minute all right my friends in this video we're going to start writing some code the first thing we're going to do is to make sure that we can reach out to the omdb api and do a search for some different movies that's a very core operation inside of our app so we should probably make sure that we can get that working right away to make use of this free api i'm going to first navigate to omdbapi.com inside my browser once here we first have to sign up for the api and get what is called an api key the api key essentially identifies us to the api whenever we make a request we can think of it as like an email and password that our code is sending over to the api to get an api key we're going to go to the very top menu and find the section that says api key it is free to generate an api key all we have to do is enter in our email address so i'm going to select the free option right here and then i will enter in my email it does have to be a valid email because they're going to email us our key so i'll put in my email my name and for use right here we're just being asked to enter a description of what we are building so i'm just going to say that this is api practice it doesn't really matter what we put in there i'll then submit this and then i'll be told that there we go i'm going to be sent a verification link to my email so you're going to now open up your email account and you're going to find an email that was just sent to you so i'm going to pull up my email really quickly here it is right here you'll see that i am given my api key that is essentially my password right there and it identifies me to the api before we can use that key we do have to click click the link at the bottom of the email so make sure that you do click that link right there now i'm told that my key has been activated okay very good so make sure you keep that key up on your screen we're going to use it in just a moment before we use the key however let's take another look at the documentation for this api and get a better idea of how we do a search operation so i'm going to go back to the main page and then scroll down a little bit so to access the api we're going to make a request to that url right there when we make the request we have to include the api key that we just signed up with in order to customize the request we're going to also pass in some number of different query string parameters remember remember parameters are essentially added on to the very end of a url we're going to be using a library that is going to add in these different parameters for us automatically so to do a search operation we'll scroll down to the search section and we are being told right here that if we add in a query string parameter called s and assign it some string that is going to be interpreted as the movie title that we are trying to search for so this documentation is not the most clear in the world but that's okay let's go back over to our code editor and we're going to start to write out some code to make a search request and this documentation will very quickly start to make sense okay so back inside my code editor i've already opened up my index.js file so i'm going to delete that console log that was inside there by default we're going to be making a network request here remember that with javascript there are many different ways we can make a network request we can use the built-in fetch function that is included inside the browser or we can make use of third-party libraries like the axios library that makes making requests just a little bit easier in this case we're going to be using axios again just because it makes our life a little bit easier than using fetch directly axios has already been wired up to this project you can find it referenced in a script tag inside of the index.html file so in order to make our request i'm going to first define a helper function that i'm going to call fetch data i'm going to want to use the async 08 syntax with this thing when we make our request so i'm going to mark the function as async and then inside the function body i will write out const response is await axios dot get so remember the first argument to the axios.git function is going to be the url that we want to retrieve whenever we make a network request that is an asynchronous operation and we essentially have to wait before we get some kind of response to continue running the lines of code directly underneath that and that's why we have the await keyword right there we're going to eventually get back a response object that is an object that represents all the information related to this request and response that we just made and inside of that response object is the data that we should be getting back from our api so as the first argument to axios.get i'm going to go back over to the api documentation i'm going to find where it says usage and i'm going to put in this url right here now really important we're not going to copy in the api key part just yet so i'm just going to get http omdbapi.com so i'm just going to copy that and then put it in as the first argument so again make sure you only have com inside there like so then to specify all the different parameters here like our api key or the search string that we want to use we're going to use some automated functionality inside of axios so we could manually type out question mark api key blah blah blah right there but instead using axios we can write this out a lot more neatly by putting in a second argument of an object inside this second argument we're going to put in a property called ramps and inside this thing we're going to list out all the different query string parameters that we want to pass along with the request so we can imagine that this object right here is going to be turned into a string and appended to the end of that url inside of params we're going to first list out our api key now really important notice that we have a lowercase key on here it is not uppercase so everything is lowercase and then i'm going to put in the api key that i just got from my email a moment ago so here's the api key right there i'm going to copy it and paste it in i'm also going to specify that s property s essentially stands for search that is the property we just looked up on the api documentation so this is going to be a string of the movie that we want to search for i'm going to first try looking for the avengers so i'll put in avengers like so okay and that should be it that should be all we need to make our request now if this preamps object right here is a little bit mysterious don't sweat it as soon as we make the request and look at it inside of our browser you're going to very quickly understand what that part is all about okay so after we make the request i'll then do a console.log of response.data again remember that whenever we make a request with axios this is an object that has a lot of different properties inside of it that describe the request and response we just issued the only property that we usually care about is the data property and that's the actual information that we just got back from that api all right so i'll save this oh one last thing let's make sure we call fetch data at the bottom so i'm going to save this now flip back over to the browser i'm going to go back to my index.html page i'm going to open up my console and then refresh and sure enough right away i see a response from that api now if you do not see a response right here if you instead see some kind of error message make sure first off that you have in fact activated your api key so that you went into your email and clicked on that link secondly make sure that you've got a lowercase api key right here make sure you've got the correct url right there and essentially just do a direct comparison of this file so inside of this response object that we got back we have a search property and inside there are all the different movies that match the search string that we just provided so i'm seeing a lot of different movies with the word avengers in the title one thing i want to point out here is that you'll notice that we are just getting back a couple of different properties about each movie so i'm only seeing the title the type whether it is a movie a tv show or something similar the year that it was released the id of the movie and then very interestingly right here a link to the image for the movie as well if i copy that and throw it into my browser really quickly i'll see the poster so this is what we're going to eventually show for each individual movie now one last thing i want to show you inside of my network request log if i open that up i can search by xhr requests and this will show me only the requests that my javascript code have issued so there's the requests that we just made to the api if i click on headers right here it will show me the full request url so you'll notice that axios took that params object that we passed in to that configuration object it took the api key property and its value and the s property and its value and it stuck them automatically into the url as a query string so again this is what is kind of nice about using axios if we were using fetch we would have to form that string by ourselves by hand not the worst thing in the world but again just a nice little benefit to using the axios library okay so now we've got some data i know this is a long video don't worry future videos will definitely be shorter for the most part so let's take a pause right here and we're going to start to investigate our data that we just fetched a little bit more i'm taking a look at the search results that we just got back from the omdb api inside of here i'm looking at the very first result and i'm noticing that we've got just a couple of different properties that represent this first search result one thing that's kind of interesting is that i don't see any information related to a lot of the stuff that we need to actually make this application work correctly so for example we want to make sure that we eventually show a short summary of the movie and the box office take the critic rating and so on but none of that information is visible inside of this search result right here this goes back to a discussion we had just two videos ago usually whenever we make use of an api like this one we got a one endpoint for doing a searching or index operation and we are just seeing a very limited set of information about every search result that we just got so if we now want to get more information about a very particular movie and get like the revenue or the rating or whatever else we have to do a follow-up request so this would be referred to as a show action or a show request or something similar when we do this show request we should hopefully be able to get a lot more information about one particular movie at a time so let's take another look at the omdp api documentation and figure out how we can do a request like the one over here on the right hand side and get all that extra information that we know that our app is going to need so i'm going to once again go back to the documentation we were looking at by search previously this time i'm going to go up to buy id or title so if we do a lookup for a single movie at a time which is essentially this section right here we're going to get a bunch of information about just one particular movie to do this request we're going to add in a new parameter called simply i lowercase i that is going to be the id of a movie that we've already found through our search request so to do this request right here we're going to go back over to our code i'm no longer going to pass in that s string anymore that was if we wanted to do a search operation i now instead want to do a lookup operation so i'm going to put in i like so and then i have to put in the id of the movie that i want to look up to get the id of a movie i'm going to go back to the search results that i was just looking at inside of my browser it looks like the id of the movie the avengers is tt08 blah blah blah right there so i'm going to copy that string and then paste it in as i like so so we no longer have an s instead we just have an i that indicates the exact movie that we want to get information about so i'll now save this i'm going to go back over to my browser once again refresh and now i get information about just the single movie and inside of here is way more information than what we got before and inside of here is definitely all the information that we really need to make our application work so remember we need to eventually get the and the search structure excuse me synopsis right here we need to get the box office value and the critic ratings and so on and so inside this result we can see plot right here that is the kind of plot summary of the movie we can see the box office take right there so that's the amount of money the movie made and i can also see a rating right there so that's essentially the critic rating there's also a medic meta score right here which is another critic rating as well so again this is the request that we're going to have to do once a user selects on an individual movie or clicks an individual movie and we want to show a lot of information about that single movie on the screen okay so now that we understand the two different types of requests we have to make let's take another pause right here we're going to start working on our ui in the next video we've now got a good understanding of how to make requests to that outside api and get some information about some different movies so we're now going to turn our focus a little bit and start to think about how we're going to put together that autocomplete widget once we understand the autocomplete we'll then be able to just about go straight from start to finish on writing out the code for this project so just one last little video here i put together a diagram on the behavior of this autocomplete widget this is a kind of confusing diagram so we're going to go through it step by step but my intent here is to really clarify exactly how this autocomplete widget is going to work once again i really recommend that on your own personal projects you go through a kind of process like what i'm about to show you to make sure that you personally are 100 aware about the requirements of the different things that you need to build inside of your application once you start building diagrams like this or you don't even have to make a diagram just to be clear once you just start thinking through it i can just about guarantee that you're going to very quickly start to realize there are corner cases that are a lot easier to solve up front as opposed to if you were just start to write code and then kind of run into some issue along the way okay so we're going to start off this diagram on the very top left hand side we're going to think about all the different ways that a user can interact with this widget this is what the widget is going to look like when a user first loads up the page we're going to show them just a simple empty input we would refer to this as the default state in other words this is what it looks like by default when the application first starts up at some point in time the user is then going to start typing inside that input as soon as the user enters in some kind of full string and stops typing we're going to take that search string and make a request off to the api we're going to do a search request to get back some list results like we just saw a moment ago we're going to take all those search results open up a little menu underneath that input and render out all the possible movies that the user might have been looking for as a quick reminder these boxes with an x in them represent an image so that would be the movie poster for the movie the dark knight made in 2012. right away there is one other case we need to be aware of here it is entirely possible that a user user will enter in a search string will do a search and not find any results whatsoever so if we don't find any results we're just going to say that we're going to close that menu entirely it might be a little bit better to show some kind of error message to the user and tell them hey sorry but we couldn't find any movies with that search term but for right now we're not going to worry about that right away so we're going to say if we don't find any results just hide the menu okay so that's kind of like step one understanding what happens in the instant that the user starts to type stuff in so now i want to kind of go further along the flow and think about the different ways that a user can then interact with a widget after we show them that menu the first thing they could do is press enter thinking that that will select some kind of record or something like that in this case we're going to require a user to actually click on an element here to select it so we want to see a user click on like that movie or that movie or that movie to indicate which one they want to select so we're going to require them to click on a movie and pressing the enter key is not going to do anything this is another one of those scenarios where you kind of have to sit down and think these things through because otherwise you might build the widget and then press the enter key expecting something to happen and see that it does nothing and be kind of surprised so i'm saying from the get go that i don't want anything to happen if a user presses the enter key the next possible interaction is that a user does what we want they might click on an entry so if they click on an entry that means that they have made their selection in that case we're going to update the text inside of the input to the exact text of the title of the movie that they just clicked on so for example if the user had searched for dark knight and then they clicked on the dark knight with proper capitalization we're going to take that full movie title right there just the title not the year it was made we're just showing the year for convenience sake for the user we're going to take that full title and stick it back into the input so that it's crystal clear exactly what movie they are looking at now there's one last possible way of interacting with this thing that we need to be aware of after a user enters the search term if they enter a term and we open up that drop down menu and show them all the options they might decide that they don't want to pick any movie they might decide yeah i'm kind of done with this i don't want to select a movie i want to work on some other part of this application or something if that's the case and they click outside the menu after it's been opened then we're going to make sure that we close the menu and do nothing else so this is one more of those scenarios where we really have to think through the life cycle of the entire widget and it's helpful to do so before we start writing any code okay so that's it that's the entire life cycle of this little autocomplete these are all the different scenarios that we really have to be thinking about now there definitely are one or two kind of other corner cases inside this widget that we need to be aware of that i kind of purposely did not add into this diagram because i want us to kind of run into these little mysterious scenarios and point them out as kind of a learning experience so we might see one or two unexpected things crop up along the way all right now that we understand what we're trying to do here and we understand the interaction with this widget let's take one more pause and start writing some code in the next video well i think that we both understand exactly how this autocomplete widget is going to work in general at least how we're going to interact with it so let's start writing out some code the first thing we're going to do or the first step is to just show a plain text input to the user anytime a user types inside there we're going to initiate a search of our api and try to find some corresponding list of movies so to get started i'm going to go back over to my code editor and find my index.html file at the very bottom i'm going to find a div inside of here with a class of container you and i are going to add all of our html inside of this div the other html that you see right above it is responsible for just showing the header and we're not going to have to mess with any of that stuff at all for this entire application so inside that container i'm going to add in an input element okay so that's pretty much it that's all the html we have to add for right now so i'll then go back over to the index.js file and inside of here we'll add in a little bit of code to select that input element then we'll add in an event listener and we'll say that anytime a user types inside there we're going to run our fetch data function and try to search for some particular movie so at the very bottom of the file i'm going to delete the fetch data function call because we no longer want to search the api automatically when our application first starts i'll then select my input and assign it to an input variable so i'll say document.queryselector input like so i'll add on my event listener so i'll do an input dot add event listener and we're going to watch for the input event the input event is triggered anytime that a user changes the text inside that input and that's exactly what we want then as a second argument i'll put in my callback function that's going to be called with some event object so now remember we can get access to the change text by referencing event.target.value that's going to be whatever the user just typed into that input so now if we want to try to search the api we can take that variable right there and pass it as an argument into fetch data we can then do a little bit of work on fetch data to make sure that it receives an argument and uses that as the query string or as the query for a search of the api so inside of my event listener i'm going to call batch data with the value from the input i'll then make sure that i receive that as an argument to this function so i'll call that how about search term like so and then we will make sure that we pass that in as a param and right now remember that we refactored this params object to look up details about a very specific movie if we want to look up a collection different movies or do an actual search then instead of an s param right there or something that i preamp we will replace it with an s and that's just straight from the documentation that we were looking at we can go back over really quickly if you want to and look at the search documentation if we want to do a search we're going to add in an s parameter so then instead of searching for that very particular movie id we'll instead search for search term and that should be it so let's save this file i'll go back over i'm going to refresh the page i see my search input i'm also going to open up the network tab inside of my chrome console so that i can see all the different requests that we're making to the api if i want to see only the requests that our javascript code are issuing we can click on the xhr button right here and that's going to filter by just requests that are being created from our javascript code i'll then start to type inside of here and we'll see what happens so i'm going to search for avengers event jurors like so okay as soon as i started typing i saw a collection of different requests being issued if i go to the very last request that was made i can click on it i'll see the query string right there inside the url says s equals avengers all right that's definitely good and if i click on preview i'll see that i definitely get some search results for the avengers movie perfect well it definitely looks like it's working out pretty well so far but there's just one little issue we're doing a search of the api for every single key press is that a problem i would say yes this is not really ideal the reason this is not ideal is that you and i only get to access the api 1000 times per day so we've got a hard cap on the number of times we can reach out to search for the avengers i made a total of like 12 requests or so i even made a little typo in there which means i had to make an additional three requests or so as i fixed the typo so i just ate up 12 out of my 1000 possible requests that i get to make for the entire day with that one single query so what would be kind of nice is if we said okay as soon as the user stops typing for a little bit of time then let's go ahead and do the search automatically so in other words if i type out avengers and then just sit here for like half a second and don't type anything more let's make a request then as opposed to doing a request for every single key press that's going to be a little bit of complicated logic let's take a quick pause right here and figure out how we will implement that in the next video in the last video we saw that we were making search requests to our api way too often so in this video we're going to figure out how to somehow fix this behavior just make sure it's really crystal clear what we're going to try to do let me show you a couple of quick diagrams so this is our current behavior right now every single time there's a key press we do a search to our api and this is not ideal this is not what we want so instead this is a little bit closer to the experience that we want to have inside of our application we want to allow the user to press the key inside that input as many times as they want and only after we go through about one second or so of nothing happening do we want to eventually call the search function so in other words let the user press as many times as they want if they then stop for one second then go ahead and call search there's two ways that we can implement this functionality we can either add in a javascript library that will do this for us automatically or we can write out some code where we will just figure out how to do it ourselves and i bet you can guess which we're going to do we're going to figure out how to implement this from scratch on our own it's actually a little bit simpler than you might think but to implement this we first need to get a little bit of background on the set timeout function chances are you've already taken a look at the set timeout and function in javascript before but i just want to give you a quick recap on how set timeout works in general so i'm going to write out a little bit of test code inside my console back over here so inside my console inside my browser i'm going to use the set timeout function i can use it by calling set timeout i'm going to pass in an arrow function to it as the first argument and inside of that arrow function i'll do a console log of hi there like so the second argument to the set timeout function is a delay that's going to specify how long we want to wait before we run that function right there the one with console log so as the second argument to set timeout i'm going to put in 1000 which means that i want to wait one second or 1000 milliseconds before executing that function so if i run that i'll wait for about a second and then i see a high there appear i can adjust it up to five seconds and now we'll wait five seconds before that function is invoked now the important thing to keep in mind around set timeout is that anytime we call it we get back an integer value so in the first case we got out of set timeout a value of one in the next case we got out a value of two these numbers are essentially identifiers and they identify the timer that we just created if we want to we can call the clear timeout function to stop that pending timer and prevent that function from being called so i'm going to set up another timeout and i'm going to give it a timeout of 10 seconds like so that's going to give me more than enough time to write out some code very quickly to clear the timer that i set up with this line of code so i'm going to run that and then very quickly write out clear timeout with three like so when i call clear timeout of three that means look at the timer that was created with the id of three so the timer that was created with an id of three was this one right here so i'm saying stop that running timer and don't call that function ever even after 10 seconds pass so that's just a quick reminder on how set timeout and clear time at work now that we we understand or have a quick reminder on that let's go back over to our code and we're going to add in a little bit of code to add in this behavior right here so back inside my index.js file i'm going to go down to where we added that event listener so the function that we kind of want to prevent from being executed is this whole function right here we want to stop that from ever running if a user is pressing on the keyboard too often so to add that in i'm going to first assign that function to a new variable i'm going to cut the function out right above i'm going to create a new variable called on input and assign that function to it i'll then pass that variable as the second argument into the event listener so on input like so what we have right here is 100 equivalent to the code we had before now we can add in some logic to actually make sure that we don't call input too often so to do so inside of on input i'm going to first right above the function declare a variable that i'll call timeout id like so we're eventually going to take one of those ids so we get from calling set timeout like the ones we saw back over here one two and three and we're going to assign one of those ids to this variable then inside this function we're going to wrap the fetch data call with a set timeout so i'll say set timeout like so i'll move my call to fetch data into the timeout function then as the second argument to set timeout i'm going to put in 1000 milliseconds so if we ran our code right now the only effect would be to make sure that we introduce a delay of 1000 seconds we'll assuming 1000 milliseconds between typing something and actually calling fetch data that's the only change that would occur right now but we want to make sure that we don't run any code until the user stops typing for some amount of time so to implement that behavior i'm going to take the timer that gets returned from calling set timeout and assign it assign it to timeout id like so now here's the magic line of code right above that so between on input and where we assign that timeout id i'm going to add in an if statement i'm going to say if timeout id then clear timeout timeout id that's the magic part right there now you can kind of imagine what is going on behind the scenes here we're going to be calling on input many many times in a row just imagine a user typing into the input like the word avengers however many characters that is we're going to call on input that number of times the very first time that on input is going to be called we're going to enter this function we're going to take a look and see if timeout id is defined the very first time that we call this function timeout id is going to be undefined so we're going to skip over this if statement entirely we're going to go down to set timeout and set up a timer and say in one second call fetch data so that's the very first key press we're then going to assign that timer to timeout id the user is then going to press on the second key on their keyboard the second time they press the key we're going to once again enter this function and now when we hit the if statement timeout id will be defined so we're going to enter the if statement and we're going to stop that pending timer so we're going to stop the existing one and we're going to set up a brand new one but the brand new one is going to have a new value that it's going to call fetch data with that process is then going to repeat itself over and over and over again until we eventually go for a full second before calling on input again in that scenario we're not going to call clear time out this time out is going to execute and fetch data will be called let's save this and test out our code and see how it's doing i'm going to go back over to the network tab over here i'm going to search for avengers again so i'll put in avengers like so and i have to wait for about a second after my last key press before i actually see a request being issued which is exactly what we want so now a user can be typing in here they can make as many typos as they want and we're not burning through all of our credits on our api that looks pretty good now the last i want to mention is that we can very easily make sure that we execute the search a little bit more quickly by just adjusting that 1000 milliseconds right there so we can instead go to 500 and now we are going to do the search twice as quickly after the user stops typing now i can put in avengers and i'll see the search up here right away okay so this looks pretty good let's take a quick pause right here and continue in the next video in the last video we added in some code to make sure that we only call our search function after the user stops pressing on their key inside that input for about one second or so this entire process right here is referred to as debouncing an input so this is when we are going to wait for some amount of time to pass after this last event before we actually run some function there's actually many different scenarios in which we might want to debounce some event inside of a web application not just for text inputs so there might be some other scenarios that we want to limit how often we call it in order for performance reasons exactly like what we just did for our api because of that i think that it might be useful to think of some way to refactor the code that we just wrote right here and make it more reusable in nature because like i just said it might turn out that we have to debounce other things inside of our application at some future point in time and i don't know about you but this code right here is kind of hard to read and hard to understand so it would be nice to make this more reusable and kind of hide the complexity or hide the implementation of the actual debouncing logic so that's exactly what we're going to do we're going to refactor this into some more reusable fashion so we don't have to think about these like really complicated set timeout and clear timeout calls and whatnot now before we start to write this code i want to show you a diagram to just help you understand how this refactor is going to work because it is going to be slightly complicated okay so here's what we're going to do right now we are essentially trying to debounce the on input event or the on input function we're saying that we don't want to receive any notifications of a change to that input after until after some amount of time occurs so we kind of want to guard access to the on input function so to make that happen we're going to create a new helper function called the debounce function this debounce function is going to be a little bit complicated for exactly one reason we're going to pass a callback or a function into this debounce function the thing that makes it complicated is that the debounce function itself is going to return a function as well that's what is complicated in my opinion maybe that's really easy to understand but i think it's kind of hard to grasp the very first time you see it now like i said we're going to pass a function into the debounce function that is something that is probably not going to be a big shock to you throughout this course we've seen several times already where we pass callback functions to other functions and heck we're already doing it back over here we are passing a function into add event listener so that on input can be called at some point in time in the future when the user inputs something into our text input so that part passing a function into another function not that bad the only hard part to understand here is understanding that debounce is going to return a new function so this green box right here represents a new function it's like a wrapper of sorts that's going to restrict calls to the original on input so this onput input right here is the same function as that one so again this green box it just restricts access to on input it might be better to visualize this using a slightly different diagram so in this diagram we still have the green box that represents kind of like a wrapper function of sorts that restricts access so you can imagine that the green function this wrapper kind of has like a shield of sorts and it's going to guard against repetitive instantaneous calls to on input so if we start to call on input very quickly several times in a row the shield is going to step in and say sorry you can't get through you have to wait some amount of time before i'm actually going to execute your call so we can imagine that maybe one second passes and we end up like down here and at that point in time the shield is going to say uh okay you know what most recent call to on input i'm going to actually let you through because one second did pass and you were the last person to call this so i'm going to let you through so again we can imagine the green function right here as being like that little shield that's going to deflect all those other calls so that's the idea so let's take a quick pause right here when we come back the next video we're going to refactor our code and build out this debounce helper function in this video we're going to define our debounce helper function so right above the timeout id i'm going to make a new function called debounce like we just discussed this thing is going to take an argument of a function i'm going to refer to that as an argument called funk short for function you could just as easily call it cb for callback or just callback itself but i'm going to call it func so then inside of here we're going to return a function like so so this function right here that is the wrapper that is the thing that is going to implement a little shield and guard how often funk can actually be invoked so what you have right here this is kind of the hardest part to understand all we have to do now to finish up the implementation of debounce is essentially take all the same code that we have down here and stick it into debounce so let's go through that step by step the first thing we're going to do just above the return statement is define let timeout id then inside of our function so this is the function that we are going to be calling possibly many times in a row we're going to first check to see if timeout id is defined and if it is we're going to clear that timeout we're going to say sorry previous execution turns out you're not going to be actually running so we're going to stop that thing in its tracks then immediately after that we're going to queue up a new execution of our underline function which we can do by calling set timeout passing it the function to run inside there we will call func like so and then as a second argument to set timeout we'll put in the delay that we want to have now we're going to make sure that when we call set timeout we take the timer that gets returned and assign it back to timeout id like so and that's pretty much it there's just one last thing we have to take care of this function right here that we pass in might need to receive some kind of arguments so we essentially need to make sure that if we ever pass any arguments to this green wrapping function that we intend to get over to on input we essentially have to take the arguments that are being passed to the green function and forward them on to on input so to do so very simply like a real straightforward way of doing it would be to say okay i'm going to take in that first argument right there that i'll call simply arg short for argument i'm going to take whatever that argument is and i'm going to pass it through to that func when it finally actually gets called like so that's a very simple and straightforward way of doing that however this approach right here will only work if we are passing in one single argument and that's possibly not always the case so to make sure that this works in all cases we're going to use a little bit more fancier code we're going to say dot dot args plural so this is going to take all the different arguments that are passed to the function then down here when we call func we're going to do func dot apply with null and args remember what the apply function does it essentially says call the function as we normally would and take all the arguments or whatever is inside of that array right there and pass them in as separate arguments to the original function so this right here like the code you see right here is a hundred percent equivalent to if we had instead i'm going to make a very quick change here like arg one r two arg three and then inside of here called funk with arg one r two r three 100 equivalent the only difference is that the apply way is going to automatically keep track of however many arguments we need to actually pass through only difference okay so i'm going to go back to that point right there okay so that is the entire debounce function so now we can use this anywhere inside of our code anytime that we need to introduce some rate limiting essentially on how often a function can be invoked so in this case we want to limit how often on input gets invoked so let's take out all the timeout code that we have inside of here right now and we're going to instead use our debounce function on it so i'll first begin by deleting timeout id i'm going to delete the if statement i'm going to delete the timeout id with set timeout and the closing brackets on there then fix up the indentation a little bit and now we're back to a very simple plain and easy to read on input function so now we can apply the debounce function right on this thing right here so we can say i want to pass in that function like so now we can imagine that this thing right here is going to be received into debounce as funk and we're going to rate limit it essentially on how often it can be invoked we're going to wait until some amount of time has passed before we actually invoke it and then the important thing to keep in mind here is that we are returning a new function so we can take whatever gets returned from debounce and still continue to assign it to on input now we just have a version of on input that can only actually be invoked once every second so we can still continue to pass that directly on through to our event listener like we were doing before just so you know there's one other way that we could have applied debounce we could have defined on input normally like we did before and instead apply de-bounce when we pass it off to the event listener so we could have used d-bounce down here as well 100 equivalent same exact thing it's just a question of where we are actually applying the d-bounce logic we would want to apply it in this way like when we actually use the function or pass it off somewhere else if we expected to call on input multiple different times from multiple different places and we only wanted to debounce it in some scenarios okay so let's save this and go do a quick test so i'll flip back over i'm going to search for avengers i'll wait for a second and then i see the response appear so it looks like it's still working as expected okay so one last little little improvement we could add inside of here at present we've got a hard-coded delay of one second and chances are we would want to allow other developers who might be using this function to adjust that more easily so an easy way to do that would be to say that we're going to take in a second argument to our debounce function that second argument might be called something like delay and that will be the number of milliseconds we want to wait so i can use that delay argument in place of 1000 right there and now whenever i make use of debounce i would just have to make sure that i pass in the number of milliseconds to wait like in this case maybe just half a second like we had before so that would definitely work one last very small optimization as well we could say that maybe we just want to have like a default delay amount and to do so we can use a defaulted argument right up here so we could say something like equals one thousand so now that means that if we ever make use of d bounce without passing in that second argument we're going to get a default delay value of 1000 milliseconds but i'm going to go with 500 because i felt like that was pretty responsive when we tested it out inside the browser okay let's save that one last quick test here i'll search for avengers and looks like we're good to go okay so that's it that is the debounce function from scratch now i want to save really quickly here if this is really confusing and chances are it is don't sweat it honestly if you're going through this course right now and you're having a hard time with this function i honestly really expect you to have a hard time with this i really really do expect this to be some challenging stuff the reason i'm showing it to you is that seeing hard code like this is how you get to be a better engineer if i just continue to show you a bunch of like baby easy code that's really easy to understand you're never going to be a better engineer you have to look at the harder stuff like this it is what is going to make you into a better engineer so if it is hard good that is a good thing you want it to be hard if it's easy hey congratulations you understand what's going on so either way don't feel bad if this is some hard stuff to understand i really really do expect it to be challenging okay so this all looks great we've got a great working d bounce function so let's take a pause right here and continue working on our app in the next video our deviance function is all done but there's one last very quick thing i want to do with it our index.js file is already getting a pretty good amount of code inside of it right now we're at just 29 lines of code and we've barely really begun to start our application so i think that we could be well served to move this debounce function out into a separate file inside my root project directory i'm going to make a new file called utils.js the idea behind this file is that i'm going to place any utility functions that i create inside of here so this is just so i can better organize the code inside of my project i'm going to go find the debounce function i'm going to cut it move it over to utils.js and paste it i then need to make sure that i include the utils.js file inside my html document so i'm going to open up the html document i'm going to go down to the very bottom of the file i'll find the existing script tag for index.js and i'm going to copy it and paste it right underneath itself i'll then find the first script tag and change the source to utils.js so now whenever we load up this html document i'm going to first load up and execute all the code inside of utils.js that will define the debounce function we'll then load up and execute index.js which has a reference to d bounce so we need to make sure that we define utils first or include that file first so that we can define the debounce function before we run it inside of index.js okay so let's save all these files and make sure all three are saved i'll then go back over to my browser do a quick refresh i'll search for avengers again and i'm just going to make sure that i still see my data getting fetched and yep i definitely do okay quick little change all good to go let's take another quick pause and continue with our app in the next video let's continue working on our autocomplete input at this point we are calling fetch data inside of the on input function let's make sure that we return some usable data from fetch data once we get some usable data back we'll then make sure that we iterate over it and for every movie we fetch we'll try to render out some content onto the screen after that we'll then start to think about how we can select a video and by actually clicking on it so to make sure that we actually get some data back from fetch data let's take a look at the fetch data implementation here it is right here right now at the very end of the function we're just console logging out our data which is not very useful instead we should probably return all the data that we have fetched but more importantly we need to make sure that we only return the actual real data that we care about let me show you what i mean by that if i go back over to my browser right now and do another search i'm going to see a console log of all the data that we get back inside of our request so this is the console.data property it is an object that has a search property inside of it that is an array of objects so you and i don't really care about the response property we don't really care about total results all you and i really care about is the search property so from fetch data we should really only be returning the search property and nothing else so i'm going to go back over i'm going to find fetch data i'm going to remove that console log and i will i will replace it with return response dot data dot search now notice i'm using a capital s right here that is definitely not standard usually in javascript we always have every variable proceeding with a lowercase letter like so the only reason i'm using an uppercase s right here is that the response that we actually get back from this api has a capital s in it and that's actually true with many of the different properties that we're going to see coming back from the api this is very much non-standard in nature so it is way more standard on any api to see all these different property names with lowercase letters so in general you should expect to see lowercase letters at the start of every property name it just happens that this api author decided to use uppercase instead so unfortunately we have to follow that same convention at some locations inside of our code okay so now whenever we call fetch data we're going to get back our array of different movies we fetched so inside of on input let's make sure that we take whatever comes out of fetch data and assign it to a variable so i'll say const movies is batch data and then right after that i'll do another console log of movies if we save this and run it we're going to very quickly see something unexpected so of course let's do that right away i'll flip back over refresh i'll run it again and now i see a console log of a promise so what's going on here i'm seeing a promise instead of an array of movies which is what i kind of expected to see well remember fetch data is an async function we marked it with the async keyword so whenever we call fetch data it's going to take some amount of time to actually process this request and then eventually return the data that we get back right now when we call fetch data we are treating it as though it were a synchronous function so if we want to somehow wait on fetch data to actually get some data and get access to the response we have to treat it as though it were an async function so in other words we need to put the await keyword right in front of it and now because we are using the await keyword inside the on input function we have to mark that function as being async as well okay so let's save this and try to run it again i refresh and put in avengers now i can see my list of different movies being printed out okay so that's definitely better all right now that we've got our data inside of on input let's take another quick pause when we come back the next video we're going to start to iterate over our list of movies and turning each one into a snippet of html and then throw it onto our document now that we have all of our data inside the on input function let's make sure that we can iterate over this list of movies right here and for every movie that we have fetched we're going to try to create a div element that kind of summarizes the movie in particular i want to take every movie that we fetch i want to get the poster printed out as an image on the screen and i want to show the title for every movie as well so let's get to it i'm going to remove that console log and i'm going to replace it with a 4 of loop so i'll say four let movie of movies like so now we can use a four of loop right here we could use a normal for loop we could use a while loop for each a map statement it's really up to you personally i rather enjoy using four of loops because they're really easy to see and pretty easy to understand as well so as we start to iterate over this list of movies right here we're going to get the movie variable inside the loop so that movie variable is going to be the same objects that we're looking at inside of our console right here so that right there is going to be the first movie variable and then we're going to go over the second movie and then so on so now inside of my loop i'm going to create a div i'm then going to set the inner html on this div so i'll say div dot inner html i'm going to use a set of backticks here like so because i want to have a multi-line string so i can nicely format my html that i want to write out make note that you are supposed to use backticks here we cannot use single quotes to form a multi-line string in javascript that would be a syntax error so make sure you have a back to character instead so then inside of here i'm going to display an image that's going to show the poster for my movie to get the url for this image or the src property let's take another quick look at the movie object that we are working with so again this is the movie object that we are currently working with right here notice that it has a poster property and that is a url to the poster image for this movie also take note that it's poster with a capital p so we'll need to make sure that we spell the property with capital p inside of our code as well so back over here i'm going to set the src on the image and remember to inject a javascript variable into a string formed with backticks we use a dollar sign curly braces like so and we'll say movie dot poster with a capital p now this right here is not quite correct there's a very small gotcha in there in order to write out a correct image tag we're supposed to write src a set of double quotes and then our link inside of there to whatever it might be right now if we ran this code right here it would just take whatever the url is and stick the url directly in without any double quotes so in other words we would end up with something like that which is not quite what we want again we want to have some double quotes around it so to make sure we get double quotes around well we have to put them in ourselves so i'm going to put double quote right there and a double quote on the other side next up i'm going to put an h1 right after it inside that h1 i'm going to try to show the title of the movie so we can get the title of the movie by referencing the title property and again notice that it has a capital t so inside the h1 i'll do dollar sign curly braces with movie dot title okay so that looks pretty good so now the last thing we need to do is take the div we just created and insert it into our dom somewhere so that we can actually see it let's go back over to our index.html and we're going to make sure that we create some element inside there that's going to list out all these different divs that we are creating so i'll go back over i'll find where we have our class container and i'm going to add in a div with an id of target this is not a really good practice right here to use an id of target because well we might end up with many different targets so to speak or things that we want to render content to inside of our application but to be honest we're going to very quickly replace this div with something else like very very soon and that's why i'm just going to use it here very temporarily so now back after we create our div we can use a query selector to select that element with id of target that we just added i'll do a document.query selector i'll look for pound target and i'll append child the div we just created okay and that should be it so i'm going to save this i'll go back over i'll refresh the page then i'll do a search for avengers and there we go so i can see my first poster right there i can see a title the next one and so on down the list so we can definitely at least show some content now however i want you to notice that while i was typing this out i also got an error over here which is kind of unexpected so let's take a quick pause it looks like everything worked but didn't quite work out quite as expected because we got an error so we'll come back in just a moment we're going to figure out why we're seeing this error message then we're going to try to fix it i was able to successfully search for some videos at the very end the last video and then show them as a list on the screen along with the title of each however as i was typing out avengers i saw a little error here at my console right here so this is an error that you might or might not be seeing right now if you're not seeing it let me show you how you can get that same error very quickly try refreshing your app and select your search bar right there and then enter in a long random string of characters as soon as you do you're probably going to see an error just like that so what's going on here we are successfully making our request you can see that if you still have your network tab open but we definitely are seeing something around movies not being iterable well let's take a look at the actual response that we're getting back inside this request then we can figure out why we're getting this error so if you select that you're going to see a response object that looks like that right there it has an air property and a response so essentially we entered in a search term for a movie that has no results whatsoever so rather than giving us some kind of response that says hey here's the list of movies that we found zero like an empty array this api chose to tell us inside of this kind of error message right here that no movies were found whatsoever so we need to make sure that we go back over to our fetch data function or somewhere inside of our code and handle this case in which we make a request and don't get any results whatsoever one other thing i want to mention at this time as well is that the search functionality with these api is not quite as great as you might expect so for example we've seen several times so we can put in avengers and get the correct result but if i only put in the word like a v n a b e n like so unfortunately well that one happened to like actually turn out there we go so if i do a v e and g so only part of the word avengers on any normal search engine or search functionality i would still expect that to give me some results of like the avengers because that's part of the word but unfortunately this api doesn't really consider partial terms like av e and g so it doesn't match that with the movie avengers and so when i put that in i still get the same kind of response that says movie not found so that's just something we need to be aware of as we are testing out our application we really do have to put in a reasonable title of a movie in order to see any kind of results whatsoever okay so let's go back over to our code and we're going to figure out some way to fix up our code and handle the case in which we don't get any results at all okay so back over here i think the most reasonable way to handle this would be to go to our fetch data function so inside of fetch data right here right after we make our request let's try to look at the response we're going to inspect response.data and we're going to see if there was an error that we're getting back when we made the request one thing i want to kind of mention here is that the errors that we're talking about right now are not like actual request errors a real request error would be like if we typed in an incorrect url and we didn't get any kind of response whatsoever that's not what is happening here in this case the request is being issued successfully we're getting back a status code of 200 which means that everything with the request went a-ok so this is not really an error in the strictest sense of the word so in my opinion this is not the best designed api nonetheless it's what we're working with so rather than handling an air in a classic sense we're just going to check to see if the response has an error property and if it does then we're just going to return an empty array and say well turns out we didn't find any results whatsoever so back over here i'm going to say if response dot data dot error like so and again notice that we have a capital e because that is what the response is giving us so if there is an error let's just return an empty array and essentially say we didn't get any movies whatsoever to show to the user okay so now let's try this again i'm going to refresh and i'm going to put in a very strange search term here so just a bunch of characters now i don't see anything on the screen and i don't have an error either so this is definitely what i would really expect if i don't get any results i don't show any content whatsoever that might seem a little bit odd but remember this is kind of the kind of system that we agreed with right here we had said that if a user finishes typing and we find no results we're just not going to show any content in a perfect world we would show the user some kind of error message and tell them that or like a warning or something like that and tell them hey we didn't find any content but for right now this is definitely good enough okay so we got that air fixed up so another quick pause right here and we'll continue in just a moment we can now show a list of movie posters and the title of each respective movie so now all we really have to do believe it or not is kind of work on the styling a little bit in particular we need to make sure that all these images are small that they show up next to their titles and that they all appear in a kind of menu directly underneath that little input right there so to do so we're going to use some css that is included inside of this project remember at the very start of this section we downloaded a boilerplate project wired up inside this project is a css framework called bulma css alma css has a collection of different css rules that allow you to very quickly style an application we're going to take a look at a component or essentially a set of css rules that are going to allow us to very quickly turn the content that we have right here into what we're really looking for so i'm going to open up a new browser tab and navigate to this documentation okay so if we go down on the left hand side just a little bit we'll see a demo of what they call a drop down now you might look at this and say steven we're not making a drop down we're making kind of an auto complete thing yes that's correct but we can kind of use some of the css that's been implemented to make this drop down to kind of leverage it for what we are trying to create so the only effective difference between what you see right here and what we are trying to make is the fact that we want to show a text input right there instead of a button they have a button we just want to have a text input so we can very easily swap that out to get something like what you see right here all we really have to do is replicate the html structure that they have over here on the right hand side now i'm not going to ask you to like read over all that css and memorize it instead let's go back over to our project we're going to write in some of the css that you see right here directly to our html file and i'll show you how quickly and easily we can replicate something that looks like that okay so back over i'm going to find my index.html file i'm going to go down to the very bottom and i'm going to find my input element right above that input element i'm going to add in a new div with a class of drop down and is dash active i'm going to put the closing div on the other side of the input so this div right here is going to wrap our input element then immediately after that i'm going to create another div with a class of drop down dash menu i'll close it off inside of there i'm going to create another div with the class of drop down dash content close that one off and then finally i'm going to make a couple of anchor tags so an anchor tag like so with a class of drop down item i'll then close off the anchor tag and inside the anchor tag i'll put in movie number one and then i'm going to copy paste that anchor tag twice like so and just update the text so all i'm doing here is using the same html that we just saw inside the bulma documentation by using the same html with the same class names all the bulma css rules that are included inside this project are going to kick in effect and try to style this block of html right here so even though we are not trying to create a drop down per se we can still leverage that set of css rules for styling our application okay so i'm going to save this i'm going to flip back over refresh and now i see at least what kind of looks like a menu right here of sorts i know it's like pushed up against the left-hand side but it kind of looks like what we're going for i've got a list of items i can kind of hover over them when i hover over them i get that nice little pointer cursor thing like with the hand with the little finger and so it's very evident to a user that i can click on this so all you and i really have to do now is instead of showing these anchor tags that say movie number one two and three we need to just take our movie images so like the poster and movie title and stick it into this anchor tag and everything should essentially show up correctly and nicely styled in our application so now we understand what our goal is in the short term let's take a quick pause because there is something to kind of think about on how we approach this problem so quick pause and we'll discuss a little interesting side topic in the next video we just added in a bunch of html directly to our index.html file so now in theory we could go back over to our javascript code try to select these different anchor elements and then update the content inside them to show the movie poster and the title in theory that would work but before we do that we kind of have a choice to make here about how we're going to implement this autocomplete widget let me show you a diagram to help you understand the decision that we have to make okay so this is option number one right here and this is kind of what the path is that we're walking down right now so right now in this kind of option we would write out all the html that is required or at least as much as possible inside of our html document so in other words we would write out that div with class drop down we would write out the input inside there then the drop down menu the content and then eventually render out all the dropdown items inside there and then inside of our index.js file we would write out some code that looks like this it would try to select probably like that div with class drop down or some like auto complete class or something like that and then set up an event listener on the input inside there and then whenever a user does a search we would then take the results generate all those options and throw all the different results like all the different anchor tags into that drop down content div and this right here might seem like a really obvious way to do it right like what other way is there well there actually is another way to approach this problem one thing i want to highlight about this is that we are making some really big assumptions between the contents of our html file and the contents of our javascript file in other words our javascript code is not going to work correctly if our html file doesn't have exactly the correct structure in other words this code this entire setup would not work correctly at all if we did not have that input element if we accidentally deleted or moved that input element our javascript code would probably not work correctly likewise if we did not have the correct spelling on this class right here of dropdown content which is where we want to put all of our anchor elements that represent each individual video if we misspelled that class name or moved it somewhere else inside of our project that's pretty much it our javascript code is no longer going to work correctly either so in other words we've got a very distinct coupling between our html document and our javascript file the two of them work very closely together and if we change either we might break our entire application with that in mind let's take a look at another way of approaching this this would be option number two okay so in option number two we are going to have way less html inside of our index.html file so to represent our entire autocomplete widget maybe we could get away with only creating one single element a div with a class of autocomplete or something like that so in this scenario we would create just the bare root of our widget inside of our html document and then instead of putting all the html inside there inside of our html document we would instead rely upon our javascript code to go through the process of creating all the html that was required for us so in other words we would try to maybe select this div right here and then we would run some code to create an input in there for us we would then handle the input like in other words deal with change events we would run our search on the api and then we would add in all the different html required to show that drop down so add in all the html for the drop down menu drop down content and so on so in this scenario we're essentially dumping all the responsibility of producing html off to the javascript side of our application that might sound like a lot more work on our side but in reality it kind of makes life a little bit easier because no longer are we going to have a strong coupling between our index.html file and the javascript file now all we have to do is make sure that we have got one div inside of here with a class of autocomplete and then we should be able to just run some code inside of our index.js file that will find that div and set up our entire autocomplete widget inside there so no expectations whatsoever about the html that's inside of that div this right here is a way more flexible approach because with this approach you and i can much more easily create reusable widgets that we can reuse between different projects it also makes it much more easy to share our code with other developers imagine sharing both these options with some friend of yours who wants to implement the same kind of autocomplete widget if you were using option number one up here you would have to tell your friend okay first you're going to go over to your html document you're going to put together this div and it has to have an input make sure as input and it has to have these two divs and they have to be nested in this very particular way just imagine trying to communicate that to some other engineer you know maybe it's as easy as just copy pasting them some snippet of html but at the end of the day that's definitely a decent amount to communicate over to them however if you were using option number two you could tell your friend oh yeah just uh create this div with a class of autocomplete and then run this javascript function run like some function called create autocomplete and boom that's it everything will be set up for that other engineer automatically so throughout this course we've largely been using option number one but as we move forward we're going to be moving towards option number two we're going to try to limit the amount of coupling between our html document and our javascript file and again the entire idea here is that it's going to lead to greater reuse of the different widgets we put together and it's also going to lead to less coupling between our different files of our project okay so now we understand like why we're going to take this kind of approach obviously it's going to require us to add in a pretty good amount of additional javascript code and we're going to have to make a couple changes to our html document but i just wanted to kind of set you up and get you to understand why we're about to write all the code that we're going to write so quick pause and i'll see you in just a minute we just spoke about the differences of creating a bunch of html to support a widget inside of our html file versus our javascript code now one thing i want to mention here is that this discussion is really about the creation of javascript heavy reusable widgets there's still going to be many times where you're going to want to create some html inside of an html document and that's totally fine we're really just thinking about moving html generation over to our javascript code when we are thinking about widgets that we want to make easily reusable between different projects or even on the same project for this autocomplete we know that we need to show two different autocompletes on the screen and so our options are to either write out all that code like one time all that html structure one time inside of our javascript file or write it out twice inside the index.html file so definitely the easier thing to do is create some javascript code that can create this widget for us as many times as we want but there's definitely going to be some other elements that we're going to throw directly into our html file for example that header element that's already visible right there that's not something that is quite appropriate to try to display from our javascript code so because that thing is like just there's only one there's not really any interactivity i don't expect to reuse it totally appropriate to create that inside of our html file okay so back over we're going to do a little bit of a refactor and move some this html generation to our javascript so that involves essentially deleting a lot of the html that we just wrote out here i know it's kind of a pain to delete some of the html that we just wrote but i wanted to write this out for two reasons first off so you understood the difference between option number one and option number two and secondly so that you just understood that if we use this html structure right here with these very particular class names all my css would kick in and style that stuff for us automatically so i apologize to delete stuff we just wrote but again that's why we did it okay so i'm going to find everything inside of class container and delete it and we're going to replace it with one single element instead i'm going to do a div with the class of auto complete like so so now we can go back over to our javascript code we're going to select that element so back over right above where we get that input i'm going to add in some code to select that thing i'm going to call it root because it kind of represents the root element of our autocomplete widget so we'll do a query selector with dot auto complete and then immediately after that we're going to do a root dot inner html and put in all the html that we need to make our autocomplete widget work so essentially we're talking about adding in all the html that we just deleted from the html file so it might seem like we're just kind of shoveling html creation from one location to another that's totally accurate that is what we're doing again the point is to reduce the coupling between these different files the html still has to be created somewhere we're just moving it over to the javascript side okay so inside of this thing we're going to add in pretty much the same structure we just had i'm going to put in one or two more elements in class names that's just going to kind of represent the final styling of this widget that we're going for so i'm going to put in a label that has a b element to bold the text in here and for the text i'll say search for a movie i'll then close off the b element and close off the label after that i'll put down the input we still need an input i'm going to give this one a class of input like so and then after that i'm going to start to show the drop down now previously we wrapped up the input with the drop down this time for like no great reason we're just going to do things slightly differently so i'm going to put the drop down right after the input element so i'll show a div with the class of drop down i'm going to close that off inside there i'll do a div with the class of drop down dash menu and close it off and then finally a div with the class of drop down content and this time around i'm also going to put in a class name of results that is just for some additional little styling just some css no other special reason for that class besides a little bit of styling okay so now we are creating all of our html on the javascript side and that means we can create as many of these autocomplete widgets as we want eventually so now we're going to go through this and we're going to select a couple of the different elements inside of here that we know that we're going to need we already have a selector for that input we're going to make sure that we also get a selector for that div right there that says drop down content because remember that's where we're going to eventually show all the different search results that we get we're also going to get a selector for this div with class of drop down as well the reason for that is that we can hide and show the drop down menu depending upon whether or not this element has a class of is dash active this is not some like magic javascript thing this is another little bit of styling from bulma css if we actually go back over to the documentation over here you'll notice that the root element in their example has is active if that element has the class is active then the drop down is going to be displayed otherwise if the class is not there the drop down will be hidden that is normal css behavior they just have a little css selector to say either apply a display of block or none to this thing to show and hide it so we're going to leave off is active because by default we want this thing to be closed but like i said we're going to get a selector to that element so we can add that class on eventually and open or close the drop down so next to our input element right here we're going to add in some more selectors to get those two other elements we just discussed one to open the thing up and one to eventually render some contents inside there so i'm going to add in a selector for drop down and that will be document.query selector dot drop-down and i'll also get a we'll call it how about results wrapper that'll be a document.queryselector or dot results and as you would guess that's that element right there i'm calling resultswrapper because essentially it's going to wrap all the rendered results that we're trying to show to the user okay so this looks good now this video is going a little bit long so let's take a quick pause right here when we come back to the next video we're going to update some of the code inside of our on input function to make sure that we render some input or some output into these particular elements so click pause and i'll see you in just a minute all right let's continue working on our widget here the last thing we have to do is make a couple updates inside of on input to refer to the elements that we just selected instead of some elements we just deleted actually so like for example right now as we loop over all of our different movies and create some divs we're trying to append them to document.queryselector id of target so that element doesn't exist anymore remember we said that we want to take all these different elements that we create and put them inside of that div right there so we just have to update a couple of different references that's all okay so to get started right before the for loop we're going to take a look at the drop down element as we just discussed in the last video to make sure that we open up the menu we have to add the is active class to that element right there so right above the for loop i'll say drop down dot class list dot add and we're going to add on the class is dash active so we're going to do that right after we fetch all of our data successfully so we're going to fetch all of our data open up the drop down and then add in all of our movies to it so then inside of our for loop as i just mentioned this element right here doesn't exist anymore instead we want to apply or append all these different divs that we create to the results wrapper and the results wrapper is that thing right there so on the query selector i'm going to delete the query selector and i will replace it with results wrapper all right just one or two more changes if we go back over to the bulma documentation you'll recall that as we show each individual item inside the drop down they're supposed to be anchor elements with a class of drop down item right now as we loop through all of our different videos or different movies we are creating a div element so that's not quite correct we need to update that to be an anchor element instead so to do so i'm going to update the document.createelement to make an anchor tag or a instead of div and then to be complete we should probably update the div variable name since we're technically not creating a div anymore a name for this could be like anchor because we are creating anchor element but that doesn't really convey the context of the code we're writing here i personally kind of like the name option option might seem a little bit weird but the idea here is that we are creating like a drop-down or an auto-complete and inside there we're going to show a lot of different options of movies that users can click to select one of these so i think the term option kind of makes sense in that context so i'm now going to go through and update div right there and right there as well to refer to the option variable since div doesn't exist anymore so i'll change that to option and on the pen child i'll change it to option as well okay just one or two more quick changes inside of the option element we currently have the image which is definitely good but we have the movie text inside of an h1 which might be just slightly too large so i'm just going to take off the h1 the opening and the closing tag all right so there should be just one last little thing to do here right above the option element as we were just looking at the bulma documentation remember i just said that we have to add in a class of drop down item to get everything to style nicely so right above where we set inner html i'm going to also do an option class list dot add drop down dash item like so okay and that should be it so i'm going to save this and we should be ready to flip back over to our browser and test this out so i'm going to go back over i'm going to refresh and right away you're going to see that this looks a lot better than how it looked before we've got the nicely bolded label and the input looks a lot better as well because we added in a class of input to that thing so now inside of here i'm going to do a search for avengers and as soon as i do so i see this nice drop down open and so i can kind of hover over each of these i get the nice kind of hover effect i got the nice finger right there all the styling that you're seeing here is coming from bulma and so i know that working with bulma and having to understand this drop-down stuff was kind of probably annoying but i think you can agree with me that this looks pretty awesome right here like this definitely looks really good now as good as it looks there's definitely still some things we have to do to make our widget work as expected in particular you might recall that we spoke about all the different ways in which our drop down is going to behave remember we had said stuff like oh yeah if a user clicks outside the drop down close the menu well right now if i click outside the drop down the thing stays open so definitely not appropriate in addition if i do another search so let's say that i look up dark knight i'm going to see as i scroll down that all those results get appended to the very end of the list so we still have a little bit of work to do so let's take a quick pause right here and continue solving a couple of these little issues in the next video okay so our autocomplete definitely looks great but like i just mentioned there's a couple more things we need to do for it so first off we need to make sure that whenever we fetch a new list of videos we clear out the existing ones inside there that's going to be pretty straightforward so let's take care of that task first so the big question here is when should we clear out the existing list well remember inside of on input we are making a request to fetch our data right here after we fetch some data we should probably clear out any existing items before we attempt to add anymore in so right above where we have drop down classlist add let's add in some code to take a look at our results wrapper remember that is the thing that is going to eventually contain all the different rendered results that we get so right above drop down class list ad i will add in results wrapper and to clear the thing out we could do a simple inner html is empty string like so let's save that i'm going to flip back over do a refresh and i'll search for avengers and i'll do a search for dark knight and there we go that's much better now one thing you might notice as i search for dark knight and you might see this or you might not it looks like the last result in here has a broken image and inside my console i also see an error as well so you might not see that it really depends upon the movie that you are searching for let's take a look at the api response that we're getting inside of our network request tab and try to understand why we are seeing a broken image there so i'm going to open up my most recent request to the api i'm going to take a look at the list of results we get back i'm going to select dark knight right there you'll notice that in this case we have a poster property of n a which means that there is no poster image available normally that poster is going to be the link to the actual image the reason that we're seeing this error is that we're essentially throwing in the string n a as an image source and we can actually confirm that by inspecting that element inspecting the image you'll see that the image very plainly has an src of n a and that's why we're seeing this nasty error down here so to get this fixed and again you might not be seeing this yet but you probably will eventually we just have to add in a check for n a essentially and make sure that we ever see it well we probably just don't want to show the image at all so to do so i'm going to go back over i'm going to find where we create the inner html for each individual option so that's where we create the image right there so all we have to do is add in a quick check beforehand to decide whether or not we want to show this image to do so right after we create the option i'm going to say const image src like so and i'm going to use a little ternary expression here so i'm going to say if item.poster remember the capital p is equal to n a then i want to assign a value of empty string to image src otherwise if it is not equal to na i want to you assign item dot capital p poster to image src instead so again this is a ternary expression we're going to first evaluate that expression right there if that is a truthy expression then we're going to return whatever is between the question mark and the colon otherwise if that is falsy we will assign item.poster over to image.src so now we can use imagesrc in place of movie.poster if we show an image element with an empty string it's essentially just not going to show up inside the dom well it's going to technically show up on the dom but it won't show up on the screen which is going to solve this issue so i'm going to put image src inside there like so all right so i'm going to refresh i'm going to look for dark knight again and it looks like i probably made a typo inside there sorry i called it item it is not item it is movie that is better my mistake okay that's better so i'll do dark knight and the last one down here don't have an image totally fine and that's life there is no image to show but we are not trying to show some like non-existing image and showing a broken image or anything like that so this definitely looks good so i think the last big thing we have to take care of is to make sure whenever a user clicks out of the input like i'm clicking over here right now we need to make sure that we close this thing up so let's figure out how we can do that in the next video the next little fix we're going to add in is to make sure that if a user searches for something and then decides they don't want to select a video and click somewhere else we want to close the menu so essentially we need to really detect when a user clicks anywhere on the screen that is not inside of that menu now believe it or not adding in some code for this is not the easiest thing in the world and it's actually kind of deceptively challenging there is a little trick to it however this trick is going to seem a little bit weird but it's probably the best and easiest way to handle this to understand the trick i'm going to first write out a little demonstration in my console so inside my console with my devtools open i'm going to right click on the label right there search for a movie and i'm going to click inspect on it that's going to open up my elements panel and select the b element whenever i click an element in this elements panel you'll see right after the html snippet i get equals equals dollar sign zero and if you hover over it you can type in dollar sign zero in the console to refer to that element so if i open up my console at the same time which by the way you can do by hitting escape we can write in at dollar sign zero and that will print out the reference to that element just you know dollar sign zero is a valid javascript identifier that is not some like magic operator or something it is a normal completely valid totally legal javascript variable name okay so now that i've got a selector to that element i want to show you the little trick i'm going to get reference to the entire document and i'm going to call document.contains and then pass in dollar sign 0. so what this checks is to see if the element that i currently have selected in this case that label right there is contained within the document element if it is contained because remember we view the dom as a sort of tree then we're going to get back true in this case the element inside the document definitely is contained but if we try to check the reverse relationship so dollar sign zero dot contains document we're going to get back false oops typo we're going to get back false like so so that means that the label does not contain the document so i just want you to keep that in your head for just a moment keep in your head we're going to go back over and write a little bit of code to handle closing that input menu or the drop down menu okay so back over here i'm going to say document.addeventlistener so this is kind of the crazy part we are adding a global event listener to our entire document we're going to watch for any time that anyone clicks on any element whatsoever now remember how events work in javascript events bubble which means that if some element contained inside the document like let's say the container right here or even the text inside of it if someone clicks on that that's going to trigger a click event on that element if it doesn't get handled right there then the event is going to essentially bubble up until it gets to the top level of our entire html document in this case the document so this event right here we can look at console.log event.target and as we start to click around we're going to see that this is going to print out a variety of different elements essentially whatever element we click on so i'm going to go back over again i'm going to refresh and now if i start to click around like on the label i'll see the label text i can click on the h1 the icon right there the header anywhere else the input whatever else and whenever i click on it i see the console log appear okay so now here's the real final conclusion of all this so we know that event target is going to tell us what gets clicked we know that we also have that contains element as well or assuming that contains method so the whole big trick here the whole kind of conclusion to all this is that we can take a look at our root element remember the root element encapsulates everything having to do with our autocomplete so we're going to check to see if the element that was clicked on is contained inside of root if it is contained inside that means that the user clicked on the label the input or the drop down and in any of those scenarios we want to keep the drop down open but if the click is not contained inside of the root then the user clicks somewhere else in the document and so we should close the drop down that's the whole conclusion i apologize in coming to it in a roundabout way but that is the trick that's how we're going to do this so inside of our event listener down here we're going to say if not root dot contains event dot target so that's saying if the root element for our little autocomplete doesn't contain the element that was just clicked on then we need to close the drop down and remember to open or close the drop down we can get a reference back to the drop down element right here which is essentially that thing right there and we can add or remove the class is dash active we just added in some code a little bit ago to add in the class is active which opens it up so to close it we're going to remove that class and that will close the dropdown okay so down here i'll do dropdown.classlist.remove is dash active like so and i'll save flip back over refresh i'll go for dark knight now i'm going to click anywhere else and the drop down closes if i do another search for let's say avengers i can click on anything inside here so i can click click click click click on the input click on the label i click on anything inside of the entire autocomplete widget and this thing stays open as we would hope all right so that definitely looks like it's working correctly so just one last little fix i want to take care of in the next video so quick pause and i'll see you in just a minute there's one last fix i want to take care of very quickly right now if we do a search for something so like i'm going to search for avengers oops i accidentally closed it there we go and then i delete this the input stays open or excuse me the dropdown stays open but with nothing inside of it which is definitely not appropriate so we just need to make sure that we do a little check inside of our code and we say that if we get back no results at all from our fetch data function we should probably close the drop down so we just spoke about how we open and close the drop down so this should be pretty straightforward back up right after we check to see if we are assuming right after we get some data let's take a look at movies and we're going to say that if there are no movies whatsoever if we didn't fetch any data let's just return early and not run anything else inside of here so i'm going to say if not movies.length so if there are no movies then let's make sure that we close the drop down so i'm going to do a drop down class list dot remove is dash active and then we're going to return entirely from this function because we don't want to try to render anything or even open the drop down back up or anything like that okay so that's pretty much it let's do a quick save and a test i'm going to once again search for avengers and i'll delete it and the drop down goes away all right well i'd say that's looking pretty good so our autocomplete widget is now in a really good state and there's really only one last major interaction we have to add we need to make sure that a user can actually click on a video to select it right now we can click on a video all day but nothing is really happening so let's take a quick pause and handle that last major interaction in the next video our autocomplete has a couple things fixed up now so we get to now start to think about adding in some additional features to it the next thing we need to do is to make sure that once a user searches for something and then clicks on an option right here we have to somehow handle that click we spoke about what to do whenever a user clicks on entry a little bit ago so remember we had said that we want to update the text inside the input so we want to update the text from whatever the user had just typed like avengers right here to the exact title of the movie that the user clicked on so instead of saying avengers it should say the avengers inside of that input in addition we need to make sure that we also close the menu finally and this isn't really in this diagram right here but the last thing we need to do as well is to make sure that whatever movie a user clicks on we need to essentially render it out really large on the left hand side of the screen because that is the end goal of this application but for right now let's just make sure that whenever we search for something and click on it we update the text and we close the drop-down so what we really need to do here is to detect a click on an individual option to do so i'm going to once again find my on input function inside of there we've got our four of loop where we create a bunch of different anchor elements we then add on some classes and set some inner html and whatnot so to detect a click on one of those options we can add in a click event handler to that option variable remember the option variable is an anchor element to add in a click event handler right underneath where we set the inner html i'm going to do an option dot add event listener and we're going to watch for a not a lick event but a click event so then inside of here we can do the two things we just discussed we want to update the value of the input and we also want to make sure that we close the drop down as well closing the drop down is something we've spoke about several times now remember to toggle whether or not the drop down is open we add or remove the class is active to the drop down element and the drop down element is that one right there let's take care of that first inside of my event listener i'll do a drop down dot class list dot remove is dash active so let's save that and do a very quick test i'll refresh avengers so now i'm going to click on the avengers and the entire drop down closes very good so now the next thing we need to do is to make sure that we update the text inside the input once again remember that we've got a reference to that input on the input variable right there so we can update the value of that text input by going back down to our event listener and we'll say input dot value that's how we can change the value inside of an existing input and we're going to update it to the title of the movie that the user just clicked on we can get the title of the movie that the user just clicked on by using the closure scope of this function right here remember the closure scope is essentially everything outside of that arrow function so right outside that function we've still got a reference to the movie variable and that is the object that has all the information about the movie that the user just clicked on so we could do movie dot title and as i've mentioned many times remember title with a capital t because this api property names are just a little bit strange so we're going to take that title shove it into input.value and that should update the text on the screen inside the input so let's do another save here i'll flip back over refresh i'll search for avengers and now if i click on any of these right here i would expect to see the text inside the input update as well and there we go very good okay so this looks like we've got something pretty good put together now i'd say that our autocomplete element is just about done so now the last thing we have to do is think about how to take the movie that the user just clicked on and render out some details about it on the screen just like we said we would do with the original mockups of this application so like this right here we want to show the image title some statistics and so on so another quick pause and we'll start to address that in the next video like we said at the end of the last video we now need to take the movie that the user just selected and show some details about it right here there's just one or two things to be aware of first off i want to remind you that the open db api that we're using has those two different endpoints that we're making use of right now we've got some results coming back from the buy search method right here and that only gives us some very limited pieces of information about every movie so when the user selects an actual movie that means that we need to do a follow-up request to the api and we need to then attempt to fetch that movie by id once we do the request by id that's going to give us a very much expanded set of information about this particular movie and it's going to give us stuff like the critic ratings and the box office take and the plot summary and so on so in other words once a user clicks on the movie and we detect it right here we need to make a follow-up request get some more information and then use that to update some content on the screen we could definitely add all that code right here inside of our event listener so we can add in a ton of code and say okay do another request get data render data and so on but i bet you could very quickly imagine that that's going to be a fair bit of code this file the index.js file that we're working on already has a lot of code inside of it and it's all kind of a hot podge of different stuff right now and so if we start to add in all this additional code directly into this event listener well this file is going to get even more challenging to read and understand so instead of tucking all that logic in right there i think that we should make some other helper function inside this file maybe something called like on movie select or something and inside of that helper function we can make sure that we attempt to do all that extra logic do the extra request render that additional content onto the screen so i'm going to imagine that we're going to define another helper function inside this file called on movie select and i'm going to call that with the movie that the user just clicked on so now let's go define this helper function and then we can put all that additional logic inside there so i'm going to go down to the bottom of the file i'm going to define on movie select it's going to be called with some movie object and for right now let's just do a console log now i'm sure i don't need to prove to you that we're going to call this function successfully like hey that's definitely going to work i don't have any reason to suspect it won't work the reason i just want to do a console.log right here is to just remind you some of the properties that we currently have access to and the properties that we're going to need to make the follow-up request to our api and get that additional amount of data okay so let's save this i'm going to go back over i will refresh i'll once again do the avengers click on it and i see that console log so again i just want to remind you that inside of the current data set that we have right here about this one very particular movie we've got that property called imdb id and notice how id is capital for both letters so that is the id that we're going to use to make our follow-up request to the api we're going to do the follow-up request we're going to pass that id in as a parameter called i and that is what is going to give us all that additional data about the movie okay so inside of here i'm going to make this into an async function so we can then go ahead and use the await syntax and axios to make our follow-up request so i will write out const response is await axios.get i'm going to go back up to the top of the file and get the url from the first request we made up here so i'm going to get that url right there just to save myself a little bit of typing and you know what i'm just going to go ahead and copy the entire axios get function because we need that params in the api key as well so i'm just going to copy all that stuff i'm going to go back down to the bottom and put it in like so then inside of here we just need to make sure that we update the params object rather than passing along a param of s which is what is used for doing a search we instead want to do an individual lookup so like we just saw we need to provide a parameter of the letter i and that is going to be the movie imdb id so i'll put in i and we want that value to come from the movie that we just selected dot imdb capital i capital d so then after that we'll do a quick console log of the data so response.data like so okay so let's try this out again just make sure we still have the data we expect so i'll do a search for the avengers i'll click on it and there we go we do the follow-up request and get all that additional data about this particular movie well now that we've got all the data we can now start to think about taking that information and rendering it out so we're going to essentially just have to write out a lot of html to build up this kind of structure right here so as you probably would guess quick pause and we'll start to write that stuff out in the next video like i just mentioned now that we've got this expanded piece of information about the movie we're going to start to write out a lot of different html to get that kind of structure right there we're going to end up printing out several different properties about the movie that are not shown inside this mock-up so in reality we're not going to only show the box office take and critic rating we're also going to show stuff like the awards that the movie won and the number of votes that it's gotten on imdb the rating on imdb and so on so couple other elements besides what is just pictured inside of here now i'm going to tell you right up front that we're going to write out a lot of html to get this structure inside this video all the html that we are about to write in all the class names are essentially taken directly from the bulma css framework remember we discussed that this project is using this framework a little bit ago so essentially i went through i looked took a look at all the documentation and i figured out some html structure and class names that would give us something that looks like this right here so i'm not making up all these class names and whatnot off the top of my head instead these are all corresponding to styling sets that are included inside of bulma okay so let's go back over here's on movie select right here that's where we just got our response with all the information about one particular movie so we're going to take that object right there pull off a ton of different properties from it and stick it into some big html snippet this is going to end up being a lot of html so rather than stuffing it all inside of on movie select i'm going to instead make another helper function called movie template i'm going to receive an argument to this function that i will call movie detail i'm calling it movie detail right here just to be clear that argument is going to be this really big object with all the specific properties of a movie just to distinguish between the movie object that we had back up here this movie object right here is more like a movie summary it just has the title the poster and like year and one or two other properties that's pretty much it so i just want to have these two different variable names movie versus movie detail to indicate that this is just like an abbreviated object of all the different movie properties this is like the detailed object about all the different movies properties then i'm going to inside of here movie template i'm going to return a multi-line string so once again set it back ticks and inside there we're going to write out a whole bunch of html and again this is all about getting that content right there on the screen so let's get to it a lot of writing so we're going to write that out rather quickly please triple check your spelling as you're going through this so i'm going to do an article with the class of media i'll close off the article i'll put in a figure with the class of media dash left close off the figure i'm going to do a paragraph element with a class of image and inside there an image with a src i'm going to put in the double quotes because remember we need those when we are trying to stick some image source inside of this tag and then we're going to get the poster property of the movie detail so here's that object that we're working with right now we want that poster property right there with a capital p so for the source i'll do dollar sign curly braces and then movie detail dot poster with a capital p and then i'll close off the image tag like so okay so that's the first block now we're going to add on something after the closing figure tag so after the closing figure tag i'll do a div with the class of media dash content close off the div inside there i'll do a div with the class of content close off the div and inside there i'll do an h1 i'm going to reference once again a javascript variable so dollar sign curly braces i'll get movie detail dot title so that's gonna be the title of the movie as usual notice the capital t for title i'll then do an h4 and inside there movie detail dot genre so that's gonna be the genre of the movie so is it an action movie a mystery horror suspense drama whatever else and then after the h4 a paragraph with dollar sign curly brace and you want just be consistent this really should be on the same or a single line so dollar sign curly braces movie dot plot that's going to be a plot summary of the movie i want to remind you that all these movie detail properties so poster title genre and plot should all have starting capital letters let's save this really quickly we're going to try to call movie template we're going to pass in our movie detail that we just got back from the api up here and then we're going to append that somewhere into the dom so we're essentially just going to test out just that snippet right there we're not done with all the html that we need but we've got enough that we should just do a very quick test to make sure that we don't have anything too crazy okay so the first thing we need to do is to make sure that we have somewhere to render this template inside of our dom so i'm going to go back into my index.html file right after my autocomplete element i'm going to put in a div with an id of summary we are going to eventually replace this element but we're just going to leave it here for now for testing purposes and then back inside of index.js i will find on movie select i'm going to delete the console log i'll do a document.queryselector and we're going to do a selector of pound and get that element that we just put in there summary and i'll say inner html will be essentially that string right there so to get that string we're going to call movie template and we'll pass in response.data which is that big movie object that we just saw at our console just a moment ago all right so let's save this we'll go back over and just do a quick test again this is just to make sure that we don't have any errors in the html that we just wrote out so i will again go for avengers click it and i think i've got a typo somewhere because it says here movie is not defined so i definitely accidentally wrote out movie instead of oh yep right there my mistake i put movie instead of movie detail that's better so i'm going to save that let's try it again avengers click it there we go all right so we've got something on the screen and it looks kind of reasonable right now kind of looks very similar or somewhat similar to what we said we were trying to build right there okay so this is good progress let's take a quick pause right here when we come back the next video we're going to start to write out another block of html to show all the stats about the movie underneath what we have so far so quick pause and i'll see you in just a minute all right let's keep writing out some html to show all the stats underneath this movie so back inside my code editor i'll find the movie template function we will go down to the bottom and we're going to add in just a little bit more html here so after the closing article element i'm going to place another article i'm going to give it a class of notification and then a space is dash primary and then close off the article then inside up here i'll do a paragraph tag with the class of title close it off and inside there we're going to reference movie detail dot awards so this is going to be a string summary of all of the different awards that this movie has won we'll see exactly what it looks like in the dom in just a second after that i'm going to put in essentially a label for this statistic so i'll do another paragraph element with the class of sub title and inside of there i'll say simply awards like so okay so this right here this article element we're going to essentially duplicate this down several times and inside of every duplicated version we're going to be referencing a different property off of movie detail and be giving each of them a different label as well so i'm going to take this article element i'm going to copy it and i'm going to copy it down four times so here's one two three and four so now we'll go through each of these and update some of the different properties i'm going to go up find the first one i'll go to the second one and i'm going to change the second one from awards right there to box office i'll change the label right underneath it to box office as well next up i'll go to number three i'm going to change that one to awards to metascore i'll change the label to metascore so again this is like a rating essentially of the movie the next one so second last one imdb rating notice how in this case i has a lowercase as opposed to all the other property names that start with the capital the label will be imdb rating so this is the rating of the movie according to the website imdb and finally on the last one we'll change it to imdb votes and imdb votes so that's the number of votes that this movie has gotten on imdb by different users of that platform okay so that's pretty much it let's save this we've got five different properties here like i said a couple added beyond just the two that we had mentioned over here back in our original mock-up so i'll save that file i will refresh i'll look for avengers click it and there we go so now i see the avengers i see the awards that this movie has won box office take meta score the rating on imdb and the number of votes that the movie has gotten on imdb as well that's pretty much it that's like stage one of our application we now have the ability to search for a movie we've got some autocomplete functionality in there once a user selects a movie we show a lot of information about it on the screen so now we essentially just have to do a lot of duplicate work we essentially need to duplicate everything we just did and show a second autocomplete on the right hand side of the screen and then once we have all the same functionality for that autocomplete we'll then just need to make sure that when we search for two different movies we compare all the different statistics and highlight the higher ones in each category okay so that's some pretty good progress let's take a pause right here and start on this next phase in the next video at the end of the last video we discussed how the phase one of our application is pretty much complete user can search for something see some statistics so normally we would now move on to phase two where we would show a second autocomplete on the right hand side allow a user to do another search and then compare some statistics between the two movies but before we do we're going to take a look at our current code base it turns out that the code that we've written so far has some kind of serious issues inside of it so i want to take a look at the code we've written so far i want to point out some really big issues with our current implementation and i want to figure out some ways that we could fix that stuff before we move on to phase 2 of our app so in other words we're going to start to do some really big refactors and the goal of these refactors is to help you get an idea of how to write some more reusable code naturally at the start of this application i could have just shown you the right way to build this application from start to finish but i think that you can learn a lot more effectively to see kind of the wrong way so to speak to build out an application which is kind of what we've done so far and then see a better way to write it now don't think that everything we've written so far is awful don't get me wrong the code we've written so far is a hundred percent a-okay and if you went to some job or like an interview or your first junior position as a javascript engineer and you wrote code like what we've done so far this would 100 percent be a-okay there's not anything that's like inherently wrong with the code that we have i just want to show you some quick changes we can make to our code base to make it even better than it currently is and it's all themed around making our code more reusable so that in mind let's take a look at some issues inside of our current code base okay so here's the current overwhelming issue with just about everything inside of our project so far i would say that just about all of our code touches everything in other words just about every function every block of code everything kind of reaches around to other variables inside the file and other functions inside the file let me give you some practical examples of this mostly focused around the autocomplete widget and you're going to get a better sense of right now how our code is just reaching around referencing a ton of different variables all over the place so a good example of that is the autocomplete widget remember the autocomplete widget was supposed to be reusable we spoke a little bit ago about how putting a bunch of html inside of our html document would lead to making it more challenging to reuse the autocomplete logic over time because if we ever wanted to reuse all this autocomplete stuff on another project we would not only have to copy over a bunch of javascript code but we would also have to copy over some html inside of our html document in other words if we had all the autocomplete html inside the html document we had that really strong coupling between those two files and again it just made it more challenging to use so as we start to think about how to make the autocomplete widget actually reusable it's going to involve the process of making sure that the code inside there doesn't touch everything again let me give you some practical examples of this the first way in which our autocomplete knowledge excuse me the first way in which the autocomplete widget kind of touches everything is that it has knowledge of exactly what a movie object is so let's go back over to our code base and let me show you that inside of the on input function right now we have a for loop right here and inside that for loop we have a couple of different lines of code that take a look at that movie object right there and in doing so specifically on line 43 it is very clear that the current implementation of our autocomplete stuff knows exactly what different properties a movie object has so on this line of code it's clear that the autocomplete stuff knows that a movie object has a poster property the autocomplete logic is going to behave very differently based on the presence and value of that poster property so i would say that if we consider all of our auto complete stuff right now like everything from const route right there all the way down to our ad event listener right there for the document if we look at just this code block we would say that this autocomplete widget knows exactly about the structure of data that it is working with now why is that bad well it's very simple again imagine that you wanted to reuse all this code on another project and let's imagine for just a second that maybe you did not want to try to have to like go into all this code right here and change a bunch of different variables or property names in order to get this code to work on another project so let's imagine that in a perfect world we could just copy paste all the stuff reuse it right away if that were the case then well having these direct references to properties inside the movie object would not be good at all because maybe our other project doesn't work with movie objects maybe instead it works with say like recipes a recipe probably would not have a poster property instead maybe a recipe object like a cooking recipe would have some property called like i don't know recipe image or something so if i wanted to reuse all this code on that other project i would have to go through it first and update all these property references that's sign number one that we don't have reusable code just yet the next instance of this is that our autocomplete has knowledge of exactly what to show for each option so again inside of our for loop right here we are setting the inner html on option so this right here this image that we're placing and the title of the movie once again means that our autocomplete code has perfect knowledge and perhaps too much knowledge of what to render or what to display for every option maybe once again if we were searching for recipes on some other project maybe we don't have any images to show at all and maybe we would not want to show that image element instead we would want to show something just like recipe dot name or something so if that were the case again we would have to come into all this code we would have to find where we set the inner html for the option and we would have to update that stuff right there so that again is another sign that our code is not reusable in order to change the way in which each option looks we have to modify the source code of our widget finally the autocomplete stuff has knowledge of what to do when a movie is clicked so again if we go back over take a look at the four of loop take a look at the click event listener that we set up on each option we have a direct reference right here to some function called on movie select again for the third time imagine that we took all this code and moved it to a new project this code would not work correctly if we did not have a function inside of our file called on movie select so again if we were working with recipes we would have to go into the source code we would have to find that function call and change it to on recipe select or something and then we would have to have some function inside this file called on recipe select if we moved all this code to another new project after that that worked with maybe i don't know blog posts we would have to change this to on blog post select so again the overriding point here the point i'm trying to make is that if we wanted to reuse all this autocomplete stuff on any other project we would have to copy paste all the code and then go around to all these different lines and update each one of them to work with this new kind of resource that we wanted to use the autocomplete with the other big issue with our code right now and specifically around the autocomplete as well is that we have have many different global variables that are referring to specific elements now the reason this is a big problem is that it's going to be really really hard right now to show a second autocomplete on the screen so let me show you why that is the case if we go back up to the top of all of our autocomplete code so about right here remember we have a query selector for some element with a class of autocomplete and then just about everything else inside this file after this is working with this root element we have many references back to the root variable so what would we do now if we wanted to show a second autocomplete on the screen well to be honest we would probably i'm going to zoom out for this just so you can see this little refactor i'm about to do don't make any changes i'm just going to give you a very quick example here in order to show the second autocomplete we would have to take all this autocomplete related code just about all of it i think all the way down to like right here or so you would have to copy all this but another code section here for like autocomplete number two do a duplicate all that stuff and then go through here in autocomplete number two section and update all these references so that the variable names wouldn't conflict with the earlier autocomplete that we defined so for example for autocomplete number two i would have to do a query selector for a totally different element like autocomplete dash two or something and then because i have all these variables that are inside of the same scope i would have to change root right here to like root two and root two dot inner html and then for these variables right here again they're defined earlier up inside the file so we'd have to do input two drop down two results wrapper two and then repeat that entire same process with all the other variables inside of here and so i bet you can imagine really quickly that this is a really really bad way to approach this problem and there's got to be some better way to tackle this than having to duplicate all the code and then just arbitrarily change all the variable names in order to just show a second autocomplete okay i'm going to delete that copy paste i just did very quickly and go back to what i had before and there we go okay so again that is the big issues with our current implementation it's essentially all revolving around our current autocomplete widget it is not at all reusable and the reasons for that is that it knows exactly what properties a movie has which means we can't reuse this with a different kind of resource it knows exactly what to show for each option which means well if we ever want to change that representation we would have to mess around with the internal source code of the autocomplete the autocomplete knows exactly what function to call whenever a movie is clicked and that means again that our source code would have to have a function called on movie select or something similar and then finally if we ever want to show multiple instances of that autocomplete well we would have to duplicate all that code and change a bunch of different variable names okay so that is the big issues with our project right now now i want to repeat one more time that the code we've written is not the worst in the world and we did not just waste like an hour of our time putting together the first implementation this project i'm just suggesting that perhaps there is a better way even better than what we've written out so far so with all this in mind now that we understand what is wrong with our project we're going to start to refactor all this stuff in some very significant ways so quick pause right here we're going to come back the next video and discuss how we can essentially solve all these issues in some really nice fashion so i'll see you in just a minute now that we understand what is going wrong inside of our project let's talk about the absolute distinct steps we're going to undergo to actually fix each of these issues so here's the idea right now we've got a lot of unreusable code inside of our index.js file we're going to start to refactor this into two separate files inside of our index.js file we're going to have some not reusable code so code that is very specific for our project examples of code that is specific to our project is the process of fetching movies or the process of deciding what an individual movie should look like inside the autocomplete and the code related to deciding what to do when an option is clicked on then we're going to have a second file called autocomplete.js inside there we're going to have some extremely reusable code that is all related to getting an autocomplete to display on the screen successfully that file should be 100 reusable between different projects and so because of that we need to make sure that everything inside that file has zero knowledge of exactly what a movie is or what a recipe is if we were building something around showing recipes or what a blog is and so on in addition we want to make sure that the code in this file can be executed several times successfully the idea there being that we want to have the ability to show several different autocompletes on the screen at the same time without having to do that crazy renaming of variables or anything like that so to make this happen we're going to create a function inside of autocomplete.js that's going to take a configuration object it's going to process the options inside that configuration object and then render an autocomplete out onto the screen so inside that configuration object that's going to be created inside of index.js we're going to have to provide all the code that is like customized for the very specific application of this autocomplete so let me tell you about what our config object might look like i think that our config object is going to have three different properties inside of it it's going to have a function that is used to find movies a function that is used to render out an individual option inside the autocomplete a function that says exactly what to do when a user clicks on an option and finally an element that designates exactly where the autocomplete should be rendered to inside of our final html document so because we are passing these three very or four very critical options inside of a config object that object right there is essentially wrapping up all the customized code specific to our application and it's going to pass it off to autocomplete.js autocomplete.js is then going to call some of those very specific functions whenever it needs to say get some data or decide how to render out each option or what to do whenever a user clicks on an option so in other words all the not reusable code gets defined inside of index.js and all the reusable code is inside of autocomplete.js then if we ever want to reuse all this stuff on another project we're going to take autocomplete.js add it to the new project come up with a new config object that has the exact same options inside of it and pass it into the same function so that's the idea that's how we're going to make our code reusable now if i am explaining this right now and it makes zero sense that is totally okay and really very much expected i really do not expect you to like look at this diagram and know exactly what is going on right away this is just your first taste of what we're going to be doing and how we're going to make all this code reusable in nature so now that we have a vague idea of what we're going to do let's take another pause right here we're going to come back the next video we're going to start to create these two separate files and then split apart all of our code into these separate different implementations so i'll see you in just a minute now that we have a better idea of how we're going to make our code more reusable let's start writing out some code now understanding this entire flow from the get go is kind of challenging so rather than trying to do this entire refactor all at once we're going to set ourselves a little bit more immediate goal we're going to try to say that rather than defining all these different options right away inside of some config object we're just going to try to pass in some root element so this is going to be some element that the autocomplete should be rendered into so the immediate goal that we're going to focus on is just having the ability to show multiple different autocompletes on the screen at the same time so we should be able to create multiple different config objects and pass each of them into some autocomplete function the autocomplete function should then create the autocomplete in those different root elements so again that's the immediate goal that's what we're going to try to do from the get go so to get started i'm going to first go back over to my editor inside of my root project directory i'll create a new file called autocomplete.js inside of here i'm going to define a function called createautocomplete so we're going to call this function multiple different times and eventually it's going to have a bunch of reusable code inside of it whenever we call this function we're going to pass in some kind of configuration object and that config object is going to have all the kind of custom functions that specify how the autocomplete should work inside of our specific application so that config object is essentially where we put all of our references to movies and how the movies should be rendered and what to do when one gets clicked and so on i'm then going to make sure that i wire up that autocomplete.js file inside of my index.html file so inside of here i'll go down to the very bottom i'm going to duplicate one of the script tags and then change the src to autocomplete so now that file will actually be executed do make sure that you've got utils and then autocomplete and then index.js if index.js is listed first then the code inside there will run first and it will try to call the autocomplete function before it has been created okay so i'll save that file then we're going to start to do the big refactor so the big refactor we're going to go into index.js and i'm going to take as much of the autocomplete related code as possible that is supposed to be reusable in nature and move it over to the autocomplete.js file that's going to start from about line 16 or so where i have const root right there i'm going to go from that line and i'm going to select everything down to the end of document add event listener that's about line 65 or so for me i'm then going to cut all of that go over to autocomplete.js and paste it into the function okay so now all we have to do is start to repair the code inside of here we're going to make sure that some of the stuff that is application specific is being taken from this config object instead of being placed directly inside this file so the first and best example of that is going to be the root element right here normally when all this code runs it assumes that our document is going to have a div or some other element with a class of autocomplete if that were the case then we would only be able to call createautocomplete exactly one time because there's probably only one element that we're going to be able to select with this statement so instead of trying to figure out what element we should be rendering into inside of this reusable function we're going to instead accept this as a configurable property so we're going to make sure that our config object has a root property and that's going to be the element that the autocomplete should be rendered into so in other words this config object right there i'm going to expect to have a root element so i'm going to destructure out a property called root like so make sure you get those curly braces because we are destructuring that property out so now because this is being provided as an option the create autocomplete function no longer on its own has to figure out where to render the autocomplete so we can now delete that first statement right there all right one or two other quick changes inside of here on lines 12 or 14 or so where we've got all those different references to input drop down and so on those are trying to find just some input in the document or some element with the class of drop down and so on we don't want that to be the case instead we want to try to find the input the drop down and results that are inside of that root element in other words that one right there that input and that results element as well so to make sure that we get those elements we can update the query selector right here instead of looking at the entire document we're going to look specifically inside of the root element so root root and root all right that's probably just about everything we have to do inside of create autocomplete for right now so now we can go back over to our index.js file and we're going to try to call create autocomplete multiple different times every single time we're going to form up a different configuration object that has a different root element to render the autocomplete into so back inside of index.js i'm going to call create autocomplete and i'll pass in my configuration object so this thing is going to have a root element let's first go back over to our index.html file and make sure that there are different elements that we can render these separate autocompletes into inside of index.html right now we've got that one div with the class of autocomplete i'm going to duplicate that down twice so i'm going to try to render three different autocompletes into my application one into that one that one and that one i need to make sure that i give them class names just to make sure that they are easier to select so on the second one i'll do autocomplete dash two and autocomplete dash three like so we'll eventually get some better class names than this but for right now that's good enough for testing purposes so finally we can go back over to index.js and i'm going to say that i want to create one instance of an autocomplete widget at a root element of document.queryselector.autocomplete and then i'm going to duplicate this down twice so one and two and i'll change the query selectors for those two other divs that we just added in so the second one right there is going to get autocomplete dash two so autocomplete dash two and then dash three and that should be it okay so let's save this we'll test it and then do a quick wrap up on the changes we made so go back over refresh and now i see the three different inputs i'll first go down to the bottom one i'll search for avengers there we go and i can click it and select it and it gets selected on the screen i'll then go to the second one i'll try searching for dark knight yep that one works as well that one gets selected on the screen now why is it getting selected here well remember right now our create autocomplete function has a reference to just one single element to show the output in it's that summary right there inside of on movie select so that is the only location right now where we can render some output to whenever a user clicks on an element and that's why we're seeing essentially the same summary element being overwritten every single time that we click on a movie so obviously that's something that's definitely going to eventually have to be fixed up but again for right now we were just worried about trying to make sure that we could show the same root element or show the same autocomplete in different root elements so finally one more test here on the first one i'll look for avengers click it and that works as well okay so that's pretty much it we can now clearly show multiple different autocomplete widgets on the screen whereas before we definitely could only show one at a time so the big summary here and the process that we're going to start to duplicate again and again in the next couple of videos as we continue the three factor is that we are trying to be able to create multiple different autocompletes and we're going to centralize all the logic around creating each one inside of index.js and inside of autocomplete.js we're going to have just the logic inside of here that is reusable between different projects so it will not have any references to movies it will have no idea what a movie object is it will have no idea of the different properties it has and so on okay so let's take a pause right here and continue our refactor in the next video our first test worked out pretty well so let's continue on with this refactor i'm inside my index.js file inside of here we've got the three create autocomplete function calls in a row we don't really need three different autocompletes i just did that for testing purposes so i'm going to delete the two right there and we're going to go back to just one call to create autocomplete i'm also going to go to my index.html file and remove those two extra divs all right so let's continue on with this refactor i want to continue to add in some additional functions to that config object that we're passing to the create autocomplete function we're then going to refactor the function to make sure that it uses the functions we had provided instead of locating all that logic directly inside of the createautocomplete function so i think the next one we should try working on is render option so this is going to be a function that is going to be called with each different option or each kind of object that we're getting back from that api we're going to pass it into this function and that function needs to return some kind of string that's going to be the html that shows up inside of the drop-down so in short if we go back over to autocomplete.js here's create autocomplete and if we go down to our for of loop right now right about here essentially where we're setting the inner html the option remember we had said that this is assuming a hundred percent that we always want to show in image and then the title right next to it but we might decide that we want our autocomplete to work in some very different way like for example maybe we won't have an image at all so right now this would be really challenging to customize because this is code that is located inside of our autocomplete file which we want to be as reusable as possible so instead i want to extract the logic that decides what this thing looks like to a helper function on that config object we're going to assume that that helper function is going to be called with each movie object we are iterating over now i know you see the variable movie inside of here quite a bit still and like i'm still using the term movie we are going to eventually refactor the terminology inside of here to not refer to movie anymore i just want to throw that out there really quickly okay so back inside of our index.js file i'm going to find where we create the autocomplete i'm going to pass in a second property into this object i'm going to call it render option we could make this a function like so we could also assign it as an arrow function no difference whatsoever we can really use either syntax so passed into this function i'm going to expect to receive some object like each individual object that represents some possible movie or whatever else and i'll just refer to it as movie then inside we're going to generate some html and return it and this will be the html that gets shown for each individual option so we're going to have to extract all the logic we had around that it's not only the html right there we also have to extract that line where we got the image src because remember in some cases the poster link was n a and we needed to make sure we handled that as well so i'm going to take the image src line right there i'm going to cut it i'm going to go paste it back inside of render option i'll then go and get the inner html that we had created right here i'm going to cut it go back over to render option i'll paste it in here and return it so now we've extracted all of our rendering logic into this render option function and it's going to be called many times automatically with each movie that the autocomplete fetches so now we just need to make sure that the create autocomplete function references this function to figure out what each option should look like so to do so we'll go back over to the other file i'm going to go up to the very top and we're going to make sure that we destructure off the render option function then we'll go back down to that same four of loop here it is right here i'll find where i left the option inner html so to generate the html to show for this option we're going to call render option with the movie that we are currently iterating over and there we go so now once again we've extracted some custom logic that is only appropriate for this movie related stuff and if we ever decide that we want the autocomplete to look very different so if you want to generate some html for each individual option we only have to update the render option function back inside of index.js so i'll now save this and do a quick test back over here i'll refresh i'll look for avengers and i still see the same thing let's try making a change to the render option function just to see how easy it is now to make a change and get something that looks slightly different as a quick reminder inside of the data that we get back from our api it contains the year that the movie was created so let's try printing out the year that the movie was created next to each option as well so to do so i no longer this is the entire key right here this is the part to like listen to in other words i no longer have to go hunting through and searching through all the source code of the create autocomplete function to figure out how to change what each individual item looks like instead i can look at my render option function right here which is very appropriately named i see that name chances are i would think to myself oh this is where we decide how to change what each individual option looks like so then inside of here right after the movie title i could put down like maybe a set of parentheses and then inside there print out using dollar sign and curly brace movie dot year so we can save that go back over refresh look for avengers again and now i see the year on there so hopefully this change is a little bit more meaningful when we start talking about all this refactoring and kind of reusable logic stuff it is the presence of this function right here that will make it really clear to other engineers how to customize and get some version of the autocomplete that works for their particular application i'm sure you can imagine that if we wanted to make even more changes to how each individual option looks we would just make some more changes to render option and that's it okay so hopefully now you're starting to get a little bit more sense of the purpose of this whole refactor so let's take a quick pause right here and continue in the next video the next refactor we're going to do is for on option select so in other words we're going to pull out all the logic that decides what function to run whenever you a user clicks on an option so to do so i'm going to go back over to autocomplete.js and we're going to find inside of here the code responsible for doing something whenever a user clicks on an option so i'm going to scroll down a little bit inside of on input inside of there is our four of loop once again and then inside of there after we create our option we attach that event listener so this right here this function is what's going to run after user clicks on the individual option now something to be aware of inside of here the first line like removing that is active class that's something that we want to have happen irregardless of what goes on in other words no matter what whenever user clicks on an option we always want to call close the drop down so we don't want to just kind of extract that function right there somewhere else instead we only want to extract some parts of it i think one part that we very definitely like probably very clearly want to extract would be on movie select right here because that is what actually decides what really happens or what goes on whenever a user clicks on the button but the line that is kind of questionable about whether we need to extract or not is where we set the input's value with the movie title half of this line in other words like that half right there is very much appropriate for keeping inside of this autocomplete file because it is related to how the autocomplete works and we probably want it to work the same way regardless of whether we're showing movies or recipes or blog posts or whatever else but the source of it in other words movie.title that part of that line or that expression is very much customized for the type of resource we're working with if we weren't working with movies then instead this line should probably be something like blog name or something like that or recipe name but in every scenario we definitely want to take whatever that value is and throw it back into the input value so this is kind of a more challenging refactor and we're going to have to think about exactly how to handle that right now it's probably pretty obvious that we definitely want to extract the callback right there so at very minimum let's make sure that we create and pass in some function called like on option select on our config object and inside there we'll make sure that we call on movie select so back inside of index.js here's create autocomplete i'm going to pass in another function called on option select i'm going to expect that this is going to be called with whatever object that the user just clicked on and i'm going to call it movie so then inside of here we can do the same exact thing that we did before where we call on movie select so i'll call on movie select and pass through the movie so then we can go back over to autocomplete.js at the very top once again we can destructure off that new function which we called on option select and then back down at the event listener that we were just looking at instead of calling on movie select right there directly instead it will be on option select now this might seem like a very insignificant change right here right like what we just changed the name of the drop down or the callback function who cares again the entire point here is that if we had some scenario where we wanted to call a different function right there if we were using our autocomplete on another application we would have had to open up the source code for our autocomplete and change that line of code which 100 not good we don't want to have to edit the source code of autocomplete.js so in doing this change we've extracted deciding what to do when a user clicks on something into this configuration option over in index.js which is going to contain all of our application specific code so i know this seems like a smaller change but it still is pretty meaningful okay so now the other thing we need to be aware of that we discussed this line right here so again the left hand side it needs to happen for every instance in which we use an autocomplete but the source of information is really well that's kind of application specific so i think that we need to pass in another helper function to our config object and i think that we need to use that to decide exactly what value to assign when a user clicks on something so back inside of index.js i'm going to add in another helper function i'm going to call it input value the goal of input value is going to be to take a movie and after a user clicks on the option we're going to call input value with the movie and we're going to return whatever value should show up inside of the input so i'm going to return movie dot title so this is how we're going to extract the logic out of autocomplete.js so now to use that we'll go back over to autocomplete.js again rather than directly referencing movie.title i will instead call input value with the movie up inside of our config object up here at the very top of the file i'll make sure that i also extract input value from the config object all right now one last thing i want to repeat really quickly here we still have many references to movie inside this file and so it might seem like we're making no progress in actually making this thing reusable again we're going to eventually come back through and replace the term movie with something else that will be a little bit more consistent okay so we got one more step forward let's do another test i'll refresh i'll search for avengers i'll click and it looks like the input value still gets updated correctly okay so that's very good let's now take one more pause and try to finish up this refactor in the next video the last thing we need to extract is fetch data so fetch data is being used inside of our autocomplete.js file right now directly so if we go to autocomplete.js find our on input callback right here we're calling fetch data when we call fetch data right here that is a reference back to the fetch data that gets defined inside of index.js so this means that we have a direct link between these two files autocomplete.js is directly referencing this function right here so if we ever deleted this function or renamed it or even just commented it out our autocomplete would no longer work correctly so we definitely do not want to have such a tight coupling between these two functions so we're just going to essentially take this function right here and we're going to throw it as another argument or another option into our create autocomplete config object we're then going to update our autocomplete file and make sure that it references the fetch data that is passed on that config object instead of over this like direct global scope between the two files so to do so i'm going to take just the function i'm going to cut it i'll delete the function name at the very top i'm going to add in a new key value pair to my configuration object i'll call it fetch data i'm going to put a set of parentheses and then paste the function now i definitely have some mistakes on syntax inside of here so i'm going to make sure that i fix those up first off we need to make sure that we mark fetch data as being async so i'm going to delete the async keyword right there and put it right in front of fetch data i'll then make sure that i take the search term and add it as the argument to fetch data and then finally i can remove the fetch data right there and the arrow and it should be good to go so make sure you triple check your syntax right there because definitely very easy to make a little typo i'm also going to do a quick change or fix to the syntax or indentation there we go okay so now we are passing the fetch data function as an argument into our create autocomplete configuration object so now if we go back over to autocomplete.js at the very top once again we will destructure out the fetch data function so now there is no direct kind of windows scope access between these two different files which is definitely a good improvement all right so i think there's just one last thing for us to take care of we need to go through our autocomplete.js file and we need to find any reference to a movie in order to actually make this code generic in nature and reusable we need to not make any big assumptions about the kind of data that we are working with so we just have to go through and change the words movie or movies to some other kind of appropriate term so inside of here i first see movie on our label it says search for a movie i'm just going to change this to just say search i'll then go down a little bit so inside of on input after we made our request we called what came back movies so again not appropriate to have the term movies inside of autocomplete.js anymore so i'm going to change the term movies throughout this file to items so this kind of reflects that we have a collection of different items that we want to show inside that drop down so now we can go through and update every reference to movies to items instead the first one is inside the if statement i'll change that to items the next one is right here on the for loop i'll change that to items and i think that is about it inside of here let me do one more search yep that's it now inside of the for loop itself we'll change the term movie to item singular so on the for loop i'll do item on render option i'll change it to item input value right here i'll change it to item on option select we'll go to item and i think that is just about it i'll do a search for movie and nothing to make sure inside of autocomplete js you do a search for movie and if you see the word movie inside of here that is wrong we should not have any references to movies anymore all right and that's pretty much it let's save this and think we're ready for one last test so i'm going to go back over to my index.html i'll refresh i'll search for avengers again and everything works correctly the search occurred and i should be able to click on that and still see something appear if you see any errors inside of your console i can just about guarantee you that you still have a reference to movie or movies somewhere inside of autocomplete.js so make sure that you find that remaining reference and update it to the appropriate term okay so at this point in time we now have a fully reusable function called create autocomplete we can take this function right here and we can use it on any other project we can think of and we'll get the exact same behavior as the one that we currently have inside of our application all we have to do is call the function and pass in these appropriate different properties so we need to specify where to render the autocomplete to how to show an individual item what to do when someone clicks on one what to kind of backfill inside of the input after a user clicks on one and then how to actually fetch the data as long as we put all that code inside there then we're going to get a fully functioning autocomplete ready to go so i know this last bit of the refactor was a little bit of a pain but i hope that at this point it's a little bit more clear why we went through this pain and i hope you can recognize that the code that we now have is quite reusable in nature so let's take a pause right here and continue with our application in the next video just to make sure it's really clear why this refactor was so significant i want to show you how quickly we could change some of the code inside these different options we're passing in and get an autocomplete that works with a very different source of data so just as a quick example you don't have to change your code here because i'm going to change my code right back again this is a very quick example i'm going to go to jsonplaceholder.typicode.com this is a fake api that can be used for testing purposes and just generally kind of messing around if i scroll down a little bit i can find a section called resources and inside there is an endpoint that will serve me up a photos collection inside there is 5000 different photos so i encourage you not to click that link because it's going to load up a ton of data and might make your browser hang nonetheless i'm going to go ahead and do it myself so if i click on it after a second or so i will see that if i make a request to the send point i'll get back an array of objects where each object represents one photo each photo has a title and a thumbnail url i'm going to try to make a request and get just 50 of these photos inside of my code and i'm going to try to render each of them into that autocomplete that we just put together if i want to only get 50 photos instead of the 5000 that it just fetched i could add on to the url question mark album id equals one and that will give me only the first 50 photos inside of here so if i scroll down i'll see that i only get 50 photos total okay so to change my autocomplete to work with this source of data instead i would take this url and again you don't have to make these changes i'm going to change my code back very quickly this is just a fast demonstration i would then go and update my fetch data function so instead of making a request to the omdb api i'm going to instead just paste that url in directly so slash photos album id equals one these params are technically not going to be used but i can still just leave them in here the request is still going to work actually i'll take them out just be sure just make sure it's really clear so i'll take those out i'll then make sure that when i get the response there is no longer a search property so i'll take out the dot search so this should work correctly to fetch the data now all we would have to do is make sure that we update how each of these gets rendered that is controlled inside of render option right here so instead of the current code i have i would instead say maybe just return an image element with a source of movie dot and let me double check the name of the actual image thumbnail url and then i'll do the title which is title so movie dot title notice i'm still calling this argument movie it now technically is like an image object but it's just not a good use of time to change the variable name okay so now i can save this flip back over refresh and now i should be able to just type anything inside of here technically there's no longer any searching operation going on and i'll see this very different source of data being used so now i've got each thumbnail which is the colored squares you see along with the title of each image showing up next to it i've got all 50 being rendered out right now so that's pretty much it that's all we would have to do to make a significant change to the autocomplete we just go back to these functions that we understand exactly what they do perfectly you know this one fetches data this one controls how each option gets rendered make those very few changes and that's it we now have a widget that works in a totally different context okay so that's just all i want to show you i'm going to very quickly undo the changes i just made and go back to working with movies and there we go so now i'll do a quick test just to make sure i'm back and still works with movies cool so again just a quick examination of how you would change things out so let's take another pause here continue the app in the next video our autocomplete widget is working out pretty well so now the last thing i want to do is to actually go back to the original application that we're working on we need to make sure that we essentially have two different autocompletes being displayed and they need to kind of show up next to each other in like two separate columns we should also make sure that when the user first loads up the app we show some kind of tutorial message on the screen as well and tell them exactly what to do so in this video we're going to change our html structure a little bit to make sure that we get these two different columns and that tutorial message so we're going to do a lot of typing inside of our index.html file so i'm going to open that up right away once again a lot of the different classes that we're going to add in here are taken directly from the bulma css library we're not going to focus too much on the class names or the styling because again class about javascript that's where we're here for yes let's get to it inside of here i'm going to first begin by deleting the two elements we have inside of class container so we're going to essentially just rewrite all the structure we have inside of class container i'm then going to create a class or div with class of columns inside there i'm going to do a div with the class of column notice there's no s on there the one before i had an s this one doesn't inside of this one i'm going to show a div with an id of left dash auto complete so as you would guess we're going to eventually use this as the root element for the autocomplete that we're going to show on the left hand side i'm using a div here just to 100 identify this thing as a very unique element inside of my application and i only ever want to have one with that id okay i'm going to close off the div with class column right there then after it i'm going to put another div with the class of column and inside there i'll do another div with an id of write dash autocomplete and i'll close it off okay so that's a good place to get started now finally after the div with class columns the closing element for that or the closing tag is right there so i'm going to find the closing tag for the class columns and after it i'm going to put in some markup to show a tutorial of sorts to the user so i'm going to do a div with a class couple class names here so we're going to have column is dash half notification notification there we go is dash primary and tutorial i'll close off that div and we're going to show some message to the user inside of here so they understand how to use our application so i'll do an h1 with the class of title and i'll say something like search for a movie on both sides and then after that i'll do a paragraph element with the class of sub title with some text like we will tell you which is best again just to help our user understand what's going on here now two things here please double check your spelling of the word notification very easy to misspell in addition overall just do a double check of all the html that we just wrote it's very easy to make several typos inside of here make sure you've got columns and then column column and column down there as well okay so i'm going to save this now we're not going to see any autocompletes appear right away because we remove the div with the class of autocomplete so in fact we're probably going to get a javascript error i just want to do a quick refresh and make sure that we see the tutorial on the screen that's what i really want to see right now so i'm going to go back over i'm going to refresh and yep i definitely see that appear so now we can go back and we can start to wire up the two different autocompletes that we want to have one that's going to be rendered into right there and the other two right there so quick pause and we're going to make sure that we render both these autocompletes in the next video all right now that we've got this better html structure we're going to go back over to our index.js file and make sure that we show two separate autocompletes one that's going to use left autocomplete as a root the other is going to use write autocomplete as a root so back inside my index.js file at the very top we are calling createautocomplete and we're passing in a reference to a div with a class of autocomplete which doesn't exist anymore so i'm going to change that query selector to pound right dash actually let's do left first left dash autocomplete i'll go ahead and save this so now if we flip back over and refresh we see one autocomplete on the left hand side so now we need to essentially do the exact same thing to create the autocomplete on the right hand side as well so you might be thinking that that means that we essentially have to duplicate all of this code right here just to have a second call to create autocomplete with a different route we don't have to we don't have to duplicate all of this config so let me show you what we're going to do at the very top of the file i'm going to create a new variable called auto complete config and i'll make it an object then we're going to go into our current autocomplete config so like this object right here and we're going to take out every option inside of here so every key value property every function that is reusable between our two different autocompletes we want to show well if we look through here every single function inside is reusable except for the root element maybe that maybe we'll go down the line and realize that it's not 100 reusable but for right now i think that we definitely can reuse just about everything except for that root element so i'm going to take render option i'll go down to the bottom of fetch data i'm going to highlight all that i'm going to cut all of it so now the only thing that's left is root i'm going to paste all of it inside of autocomplete config like so okay so now inside of the create autocomplete function call right here we're going to essentially say create a new object take all of the properties inside of autocomplete config that we defined at the top of the file and then add in this new property of root and then take that whole object and pass it off to create autocomplete so to do so we're going to write out inside of here dot dot auto complete config and then a comma so the dot dot dot right there means make a copy of everything inside that object or essentially take all the different functions inside there and throw them into this object and then add in this root property as well and that's it so what we have right here is 100 equivalent to what we had just before but now since autocomplete config is its own separate object we can repeat this process as many times as we want and create additional autocompletes with the same configuration object so to do so i'm going to make a copy of create autocomplete config or something create autocomplete just the function call paste it now all we have to do is update the query selector so instead of saying left i'm going to say write okay and that's pretty much it so i'm going to save this i'm going to go back over refresh and now i see the two separate autocompletes i'm gonna make sure i don't have any errors nope nothing inside my console now if i do a search for avengers looks like the left hand side is working and if i do a search for dark knight on the right yep that's working as well i can click that avengers click that yup looks good now if i click on those i probably going to see an error down here because we deleted the element that showed the actual summary you really call just a second ago when we were updating the html file so i think that the next obvious thing we have to do is make sure that once we search for something we need to hide this kind of tutorial element right here and show a summary on just the appropriate side of the screen so let's take care of that process in the next video the next thing we have to do is to make sure that whenever we click on a video inside of our autocomplete we should hide this tutorial right here and start to show some summary information about that movie on the appropriate side either the left side or the right side so let's first take care of making sure that we just hide this thing to do so i'm going to go back over i'm going to go up into my config object and i'm going to find where we have the callback of on option select here it is right here so i'm going to replace on option select or excuse me i'm going to add to the code inside of it i'm going to get a selector for that kind of tutorial window that we just added in so inside my html file here it is right here so i'm going to get a selector for a div with the class of tutorial and then we're going to add a class to it that's going to hide that thing on the screen so inside of on option select i'll do a document query selector with dot tutorial i'm going to look at its class list i'm going to add in a class of is dash hidden like so this is another one of those classes that is coming from the bulma css framework so by just adding on that class that div that is containing the tutorial should be hidden on the screen let's do a save and a quick test so i'll flip back over refresh look for avengers click and the thing is gone okay that was an easy one another quick pause right here and we'll continue with showing the two tutorials on both sides in just a moment all right last thing we really have to do here is to make sure that when a user selects one of those movies we show a summary on the appropriate side of the screen so the first thing we have to do is to make sure that we have some div elements to render the summaries into remember at the bottom of the index.js file we still have the movie template function so we essentially know what content we want to show we just need to make sure that we have some place to put it so inside of index.html i'm going to find where my div of left autocomplete is and right after it i'm going to add in a div with an id of left dash summary and close it off and i'll do the same thing right after the write autocomplete as well so div with an id of write dash summary like so now all we need to do is to make sure that whenever on movie select gets called we render the summary into the appropriate element either the left side or the right side so to make this happen we're probably going to have to have two versions of either on movie select or two versions of on option select up here remember right now we're using the same version of on option select between both the left hand side autocomplete and the right hand side so i think that we should probably take on option select and then throw it down into each individual call to create autocomplete and that will allow us to make a customized version for each one so to do so i'm going to go up to my autocomplete config i'm going to cut on option select out i'll then go down to my calls to create autocomplete one and two and i'm going to paste that thing in so paste and paste i'll make sure that i get a comma on the line right above otherwise i'll see an error very quickly so now this one right here is for the left hand side and this one right here is the right hand side so to make sure that we actually render the summary into the appropriate element let's make sure that when we call on movie select in both cases as a second element i'm going to pass in a reference to an element of where to render the summary to so on the first one which is responsible for the left hand side i'll get a document query selector or pound left dash summary and i'll do the same thing for the second one as well document.query selector hound write dash summary so now inside of on movie select we can receive that second argument so in addition to movie we'll receive that other argument as like how about summary target or something like that how about summary element i think that makes sense so then we're going to do that request to get more details about the selected movie and then instead of throwing the render template inside of some summary element that doesn't exist anymore instead we're going to throw it into the inner html of that summary element so i'm going to replace that query selector with summary element okay so let's save this and do a quick test go back over i'll look for avengers once again for the millionth time click it and there's my summary on the left hand side and i should be able to do dark knight click it and see the summary on the right hand side i should be able to go between both these and just make sure that they've got the appropriate values or i should just say different values to make sure that we're not accidentally leaking data from like one side to another so i'm looking through and yep it all looks good okay so now the very last thing we have to do here to really complete our application remember the last requirement of our project was to compare both the different stats and we need to make sure that we color the greater stat on each side of the screen this is going to be a little bit more challenging than it seems because in some cases comparing these things is actually kind of challenging for example how do we really compare this string right here with this string how do we compare this number right here this is a string when it comes back from the api we know it's a string because it has the dollar sign and the commas in there so how do we compare that string versus that string it's pretty clear i think that we're going to have to figure out some ways to really compare these different statistics and in some cases it might require some special logic so one last pause and we're going to figure that stuff out in the next video the last thing we have to do is make sure that we get a comparison going between all these different stats so back inside of my index.js file i'm going to find where we were just working on on movie select we're going to eventually do a request inside of here remember to get some follow-up details about a particular movie now one thing we should probably do inside of here is get a reference or store a reference to that response that comes back so we can hold on to that reference that movie in all those different statistics so we can do an easy comparison later on so right above on movie select i'm going to define two variables with the let keyword so i'll say let left movie and write movie then inside this function after we get some data back from axios let's make sure that we store the movie that we just fetched on the appropriate variable to do so we're going to need to make sure that we pass in some additional argument here to indicate whether we are receiving the movie on the left side or the right side so inside of both the functions where we call on movie select i'm going to pass in one last variable here of left as a string and right as a string so now we know the context in which on movie select is being called so inside of here i'm going to receive that as variable that i'll call simply side and then right after we set that inner html we can say something like if side equals left then let's update the left movie variable so i'll say left movie is response.data else we must be working with the right side so i'll say write movie is response.data then after we update both those variables we should add in a check to see if both the left movie and right movie are defined if both these variables are defined that means we have a movie on both sides of the screen and it's time to run the comparison so after those if else statements i'll say if movie and right movie then let's run the comparison i'm going to stick all the code for doing the comparison into a helper function called appropriately named run comparison and i'll define that as a helper function right after so then inside of here we can iterate through our two different movies run all the comparisons and then update the appropriate statistics on both sides of the screen so inside of here i'm just going to do a quick console log for right now and say time for comparison just to make sure that we are running this code at the appropriate time i'll then go back over refresh get that console open and then i'll do avengers here we go and dark knight and after i click this movie it would then be in theory time to run the comparison so i'd expect to see the console log appear at that time so i'll click there and i do in fact see time for comparison okay so it looks like we're off to a good start so now another quick pause we'll come back the next video and figure out how we're going to actually compare all these different statistics all right so in this video we're going to implement our run comparison function now as i mentioned just a moment ago implementing this function is going to be just a little bit challenging because the metrics that we're comparing here aren't always just plain numbers in this case we've got some strings so we need to figure out how to compare these different values there's actually another reason that this is kind of a challenging little problem let me tell you exactly why i want you to think about the exact logic or kind of ordering in which we would run the comparison inside this function the first statistic that we print out down here is the number of awards or that whole award string and then the box office and then the meta score so it's clear that we need to somehow reach into the dom we need to select this element on both sides of the screen because remember there's really two of these elements on the screen one for each movie we search for so we need to find this first element like the first element with the class of notification is primary and a article tag and we're going to essentially assume that that is of type awards or displaying the award stat so we might end up running some code inside of here that looks like this i'm just going to give you a very quick example maybe something like find the first article element for each movie then run a comparison on the number of awards then apply some styling to that article element the key thing here is that we're just looking for the first article for each movie then we're assuming that that first article element represents the number of awards statistic if we start to write some code like this we're going to very quickly end up in a bad spot let me tell you why if our code just looks at the first element and assumes it is awards we could break our application super quickly by going back down to our template and just changing the order of statistics so in other words i could take this first statistic block cut it and move it underneath that first one or the second one so now the award statistic is second in the list so if i ever wanted to reorder the different statistics that i'm showing here i would also have to make an update to the run comparison function because now the first article in the list represents the box office amount so i'd have to update this code to run a comparison on the box office value instead and then it kind of follows that the second comparison i would have to update from box office to instead take a look at number of awards so in other words we don't really want to encode the order of statistics here and try to read it out of our html to figure out what order we're going to compare these different statistics in so that kind of throws that approach out the window so how are we going to like actually fix this how are we going to actually approach it well i've got one kind of crazy idea that's going to kind of solve a lot of the different issues that we're going to run into up front particularly that other issue around like comparing strings versus strings i think that when we run the movie template function we should add in a data property to each of these different articles and we should make the data property a number version like an easily comparable version of each of the different statistics that we want to show so in other words i think it would be awesome whenever we run movie template for each of these different articles on the article itself i want to put in like a data value property and maybe set it to for this first box office value something like 623 million so i'll say something like data value is 623 million or so then later on we decide to run our comparison rather than trying to look at the order of articles and figure out that we first have like box office then awards then meta score or whatever we can just read that data value property and compare it against the data value property for the first article on the other side of the screen so in other words we're throwing the idea that this is like the box office statistic out the window inside the run comparison function the only thing run comparison will care about is that data value property so we can just take a look at the data value property on each pair of articles and then take a look at which one is greater and apply the appropriate class to each one to color that notification as either green or yellow this is yet another scenario where i know as i explained this it probably sounds crazy and a little bit complicated so let's once again write some code as soon as we do i think you'll get a good idea of why we're doing this so quick pause and we'll start to implement this approach in the next video alright so like i said in this video we're going to update our movie template function we're going to take a look at some of the different properties inside that movie detail object remember movie detail is an object with some expanded properties that describe a particular movie for each of the different properties or statistics that we're printing out we're going to turn each of these into some easy to represent number value and then we're going to add each of them as a data property to each of these different articles and that will make it really easy to compare these different values later on without having to worry about the order in which they are being presented or anything like that so inside of here the first thing we're going to do at the top of the function is take a look at some of the different properties on movie detail and turn them into a easy to compare number format so this is unfortunately going to be just once again a little bit challenging so the first number that we're going to try to generate is a number representation of the box office value so i'm going to assign that to dollars because that's essentially how this is being represented so i want to take a look at the box office value which currently is like that string right there you know number 623 with commas in it or 533 with commas in it and whatnot and i want to turn that into a normal integer we can compare very easily so back over inside of here i'm going to say that dollars is movie detail dot box oop capital b box office so this right here is a string and once again it's going to look something like this maybe 6 29 blah blah blah so we want to remove the dollar sign and we also want to remove any commas in there as well so to do so we can use some normal string manipulation methods on box office i'm going to call replace i'm going to find any dollar sign character and replace it with an empty string which essentially just removes it out of that string now because i'm using a dollar sign inside of a regular expression right here i do have to escape it remember what we spoke about earlier on inside the course about regular expressions dollar sign is a protected value so we just have to put a kind of backslash right in front of it so that's going to take the dollar sign out and just remove it entirely now we need to repeat that same step for all the commas in here as well so once again call replace i'm going to find all the commas and replace them with empty string that's going to take out all the commas now i just need to take this string and turn it into a number to do so i can call parse int on that entire expression that's going to parse an integer out of that string now as a quick test as usual i'll just try to do a console log of dollars so i'll save that flip back over refresh i'll look for avengers and i see a number version of 623 million up here now we're going to repeat that same process for all the different values on here we're going to essentially run some custom logic on each of them to turn them into some number that we can insert for each article element and then compare later on the next one we'll do is the metascore you might think that metascore doesn't need any work whatsoever because it looks like it is a actual number well if you go back to your network request log and look at the expanded detail request that we're making metascore actually is a string just about everything inside of here is a string so for every one of these different values we need to parse them into a number and then throw them into the dom metascore imdb rating and imdb votes all included so the next one i'll do i'm going to delete that console log and i'll do meta score that's going to be parse int out of movie detail dot meta score next one i'll do is how about imdb rating this one's a little bit more challenging notice how it can possibly have a decimal on it so in javascript there's a difference between parseint and another function called parsefloat parseint is going to prevent us from having a decimal but if we use parsefloat that can take a string that has a decimal on it or in it and turn that into a full number with a decimal so for imdb score or is it called rating where is it yep imdb rating we're going to do a parsefloat with moviedetail.imdb rating then we can do the same thing for the number of votes as well this one can use a parse int because there is no decimal on it however we do have to remove all the commas in there so i'll do imdb votes is parse int movie detail dot imdb votes it's gonna double check that property name yep that's it and imdb votes we need to make sure that we go through that thing and replace any comma we see with an empty string okay as another quick test let's count to log out meta score imdb rating and imdb votes so i'll save this refresh i'm going to once again look for the avengers i don't actually like the avengers by the way i'm a way bigger dc fan but i figure everybody out there probably knows what avengers is that's why i'm using it here just a quick side note okay so we've got the numbers 69 8 and blah blah blah so it looks like we've got all of our values out of here appropriately the last one we have to take care of is the actual value right there the number of awards now parsing a number out of here is gonna be a little bit more challenging so as usual quick pause and i'll see you in just a minute the last statistic we need to parse is the number of awards so how are we going to reduce this down to something that can be easily compared between different movies well we're just going to take all the different awards or the total number of awards here so we're going to find all the different numbers in here add them all together and we'll say whoever had the most numbers inside the statistic wins so technically one movie that has like one win but 100 nominations will beat out a movie with 10 wins in theory the movie with 10 wins and like zero nominations would be better but for our purposes or the purposes of this application we're just going to say whoever had the most numbers in this thing is the winner so let's write out some code that's going to take a look at that string and extract the total number out of it back over here inside of movie template i'm going to delete that comment up top i'm going to delete the console log and then we're going to declare a new variable called awards so for this one we'll take a look at movie detail we're going to look at the awards property which is that big long string we're going to first begin by splitting it on space this right here is going to give us an array where every element in the array is one of the different actual words or numbers in here so essentially all the spaces go away and just the element words we get inside of an array so then we're going to iterate through that array and we're going to say that for every actual number in there we're going to keep some running total and then eventually return it now we're going to write this out in two different ways we're going to write it out first with a 4 each and then we're going to refactor it to use a reduce statement instead this is a perfect location to do a reduce but just as some quick practice just to get familiar because we're already doing some hard enough things here we'll first do a 4-h so right above i'm gonna declare a variable called count and start it off with zero this is going to track the number of award values so in this case we would have like about what 118 for this movie right here that's one plus 79 plus 38. okay so on split remember that gives us an array so i'll call for each and then i'm going to take each word inside of that sentence and i first need to see if i am working with a number or not the first time that function gets called it's going to receive the word nominated that's obviously not a number so to check to see if we're working with a number or not we're going to first try to parse this thing so i'll say value is parse int with word if we try to parse an int on a string that doesn't contain any number whatsoever we're going to get back a value of not a number let's do a quick test of that inside of our console over here very quickly just to get a reminder of that behavior so over here i'll do a percent of not a number and i get back n a n which again stands for not a number so if i do parseint on say nominated yep we definitely get back not a number so that's how we're going to tell if we're working with an actual number or not value is going to be not a number so to check to see if we have a number or not we will say if is n a n like so that's how we check to see if a value is not a number or not inside of javascript that is a function that is built into the browser so we don't need to define it or anything like that so we're going to say if this value is not a number then we're just going to stop the return statement right here is just going to return from the inner function so in other words we're going to say don't try to add anything to count or anything like that otherwise we'll do count is count plus value like so okay so now at the very end i'll do a console.log of count and we'll test this thing out for that first movie i'll refresh look up avengers click it and there we go i get the 118. so again that is the one plus 38 plus 79. so we could stop there and just say oh yeah count is our variable but instead like i said let's try to refactor this for each into a reduce statement instead because this really is a perfect place to make use of reduce so with reduce remember we're going to change the for each to reduce then the second argument to the reduce function the first is the actual function we want to run the second is going to be the starting value for our reduction so in our case our starting value is zero then the first argument to that inner function is going to be the previous value and the second will be the word that we are currently iterating over so then inside of this function body we need to make sure that we return the next value for the next iteration through this loop so right here in the return case rather than just returning nothing we're going to instead return previous so if the value that we just are iterating over right here is not actually a number then just return whatever our current count is otherwise we're going to return the previous value that we got plus this new value okay so now we can delete the let count up here and just to make sure this works correctly again i'm going to do a council log now of awards i'll save that another quick test so refresh look up avengers click it and i still get the 118. all right so that is it we've now extracted some meaningful values out of all these different statistics so now the last thing we have to do is take these different values and inject them as data properties on each of these different articles once again once we do that we can then pull those values out later on when we decide that it is time to compare these different statistics okay so quick pause right here and we'll take care of that in the next video all right now that we've got all these statistics let's make sure that we add each of them to the appropriate article elements inside of our template so down here i have my first article right there that is meant to show the number of awards so on that article element i'm going to add in a data value property and i'm going to inject the value awards to it and we can repeat that same process for the other articles as well so the next one is supposed to show box office i think we called the relevant statistic dollars yeah there it is right there so i'm going to go back down there's the box office statistic on the article i'll do a data value of dollars the next one is a data value of metascore then we've got our imdb rating so data value of imdb rating and finally data value imdb votes and that should be it okay as usual we'll do a quick save and a test so the test in this case is to inspect our dom elements and just make sure that we are assigning some reasonable values to each one so i will refresh i'll look up avengers whoops i accidentally type dollar instead of dollars by mistake there we go dollars on the second one avengers again click it that's better so now i can inspect my dom i'm going to look at each of these elements and just make sure that they have the appropriate value property and there we go so i can see the list of articles there's the first one it has a data value of 118 then i've got the number value for the dollars then the meta score the imdb rating and finally the number of votes okay so that's pretty much it we can now repeat that same process for this stuff on the right hand side as well so over here i'll look up dark knight i'll do an inspect of that element right there and i get 309 awards wow that's pretty crazy then i get the about 533 million then 84 metascore and 9 imdb rating and finally 2 million votes okay so that's it it's now the very last thing we have to do inside of our compare run comparison function right here we can now iterate over all those different article elements so we're going to iterate over both them at the same time they basically get this collection on the left-hand side and this collection on the right-hand side and then we'll compare each of them one by one by looking at their data value properties whichever one is greater we're going to apply some classes to to colored as yellow otherwise we'll leave it as is and just leave it green okay so that's the idea one more quick pause and we're going to wrap this thing up in the next video all right let's get to it let's run our comparison on both sides the first thing we have to do is select all these different articles and we need to make sure that we keep the two different sets separate as a quick reminder if we open up our element inspector again the entire summary on the left hand side is enclosed inside of a div with an id of left summary so if i want to get all the articles that have a statistic inside of there i can select so document query selector id left dash summary that's going to give me essentially the entire left side and then i can find all of the elements inside there with a class of notification so i'll do inside of that a query selector of dot notification oh i don't want to do a query selector my mistake i'm going to do a query selector all that will give me all of them so there we go there's my list of five i've got all five on the left hand side just to be clear we don't actually have to run the two separate query selectors we could actually reduce that down to just one so i could do document.queryselector all and then say inside of the left summary element find all the elements with notification and that will still give me all 5 on the left hand side so that's how we're going to make sure that we get all five on the left and all five on the right okay so back over here inside of run comparison we're going to get all the elements on the left and right i'll say how about left side stats so that's like the statistics being rendered out on the left hand side will be document.queryselector all and then we want id left side what would we call it left side or left summary my mistake dot notification then we can do the same thing for right side stats and that will be document.queryselector all right dash summary dot notification all right so now we can loop over either one of these and at each step we can take the corresponding element from the other pair or essentially like the right hand side and we can do our comparison by retrieving the data set values so i'm going to try to iterate over each element inside of left side stats so i'm going to do a left side stats dot for each so i'm going to get my callback function right here i'm going to receive each article element i will call them left stat so again that represents an article element that is going to have that data set value that we really care about and i'm also going to get the index of that element inside of left side stats as well the reason i'm getting the index right there is that i can retrieve the appropriate corresponding stat from right side stats so i'll say write stat is right side stats at index and then again just to make sure we're doing everything correctly here i'll do a console log of left stat and write stat okay so i'll save go back over do the refresh i'll look for avengers dark knight and there we go we've got our console logs so we can see that each of these console log pairs are the two corresponding article elements that go with each other so like that one and that one and then the box office box office metascore metascore imdb rating and so on so then inside of here we're going to do first get the actual value property off of each of these so i'm going to say left side value is going to be left stat and to get a data set property remember we referred to data set and then the name of that data property on that element so in our case we called the data properties value so we would reference that value property with data set dot value and then we can get the right hand side with right side value is right side or something right stat dot dataset dot value as well so now inside of here we can do our comparison directly between the two again take note that this comparison process right here because we assign the stats up front inside of our movie template we don't care about the order in which these different stats occur they can occur in any different order we can have the box office value then the rating then the meta score or the totally opposite and it just doesn't matter all we have to do is make sure that we are iterating through the same properties on both sides at the same time so in other words we could not show like first awards over here and then first box office over here that's the only thing that we could not do so inside of here i'll say if right side value is greater than left side value that means the right side is greater and that means that we want to add a class to the left hand side that's going to turn it yellow instead of the default green so to make sure that we turn the left side yellow we would run left stat which remember is the actual article element i'm going to look at the class list i'm going to remove the is primary which is what makes it green again this is some class names coming from bulma css and then on the left stat class list i will add in is dash warning and that's what's going to turn it yellow so now we can repeat the same process for the opposite case as well so i'll say else write stat class list remove is primary and write stat class list add is dash warning all right so that should be it so here it is this is our moment of truth this should be like the entire application all put together let's do our final test so i will do a refresh i'm going to look for avengers look for dark knight there we go and all right that is it and it's looking pretty good so we can look through all these different stats and we should see that the stats that are in green are greater than the ones in yellow so first off we've got like 118 wins versus the like 300 and change so definitely the correct one is green well the avengers had a higher box office value so that definitely won out however dark knight has a better meta score better imdb rating and more votes as well so that's pretty much it that is the whole application well i hope you enjoyed putting this thing together let's take a quick pause right here when we come back the next video we're going to do a quick review on some of the important points around this application all right my friends in this video we're going to do a quick wrap-up of this application there's just a couple of things i want to point out really quickly that were really important to understand or none the most important thing about this application was to understand the create autocomplete function the entire goal here was to create a widget that was entirely reusable in nature and we saw a little bit earlier how we could very easily swap out a source of data with the fetch data function and the render option function as well to customize what the autocomplete looked like and that was done very easily think about how we would customize this widget if we didn't have access to this options object we would have had to go through all the code inside of here and customize each line one by one to change the source of information or change how each option was displayed so by extracting all this logic into the self separate file you can now take this file right here add it to any other project that uses the bulma css framework and ta-da you've got a working autocomplete that's pretty much it the other big thing we learned about was that whenever we wanted to create a reusable widget it was kind of important to locate all the html for that inside the widget itself as opposed to our html file again if we had tried to keep our html inside of the html document around the autocomplete you and i for every autocomplete we wanted to show would have had to put something inside of here of like input and then a div with a class of drop down and then inside there another one with drop down dash menu and so on and that would have had to have been done every single time we wanted to show it in autocomplete so we got around that by instead saying you know what inside of our html document we're going to show just the absolute minimum kind of like a placeholder to display the autocomplete it was then up to the widgets code to initialize the html inside there and so again this is what made our widget very reusable because now we don't really care about what has to be displayed inside of it we can just say create autocomplete and the widget is going to set itself up automatically the last thing we really focused on well we focused on a lot but definitely one of the bigger items was to really figure out how to run that comparison appropriately so in this scenario we realized that trying to pull stats out after the fact from our different movie objects would probably be really challenging because we would be limited to being to how often we could reorganize or reorder the different statistics so instead inside of our movie template we decided up front to extract all the relevant values and store those values inside of our dom so then we can easily pull those values out later on from the run comparison function by just finding those elements and then referencing the appropriate data set value then we can do a very easy comparison without having to worry about what we were actually comparing imagine what we would have had to write in here if we were trying to throw in like the entire awards string into each dom element we would have had to say something like left side value right here and then we would have to do some code like if left side value contains awards or something like that we've had to write some code like that to determine or try to figure out whether or not we were working with the award string so doing that after the fact would have been really challenging so instead we just did all the processing up front and that made our life down the road way easier okay so that's pretty much it for this application so let's take a quick pause right here we still have a ton to learn we'll continue in the next video
Info
Channel: Code With Sahib
Views: 275
Rating: undefined out of 5
Keywords: Application Design Patterns, Design patterns, Java EE, Enterprise applications, gdmatstaffs, software design patterns, engineer, developer, coding, java design patterns, structure of design patterns, types of design patterns, creational design pattern, structural design pattern, behavioural design pattern, jee design Pattern, factory design pattern, abstract factory pattern, singleton pattern, builder pattern
Id: sBs5A40SAL4
Channel Id: undefined
Length: 223min 52sec (13432 seconds)
Published: Sun Jan 10 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.