Complete Intro to Web Development, v2 Complete Intro to Web Development, v2

JavaScript, HTML, and CSS Solution, Part 2

Check out a free preview of the full Complete Intro to Web Development, v2 course:
The "JavaScript, HTML, and CSS Solution, Part 2" Lesson is part of the full, Complete Intro to Web Development, v2 course featured in this preview video. Here's what you'd learn in this lesson:

Brian continues the walk through the solution to the JavaScript, HTML, and CSS Exercise by coding the programming functionality to the calculator.

Get Free Access Now

Transcript from the "JavaScript, HTML, and CSS Solution, Part 2" Lesson

[00:00:00]
>> Brian Holt: Calculator.js, so next we're gonna come into this index.html. Shut up, yarn, I don't care, okay.
>> Brian Holt: I'm gonna come in here and say at the bottom, right before the end of the body, I'm gonna put script. And src = './calculator.js', like that. Now, you might ask, why am I putting my script tag there?

[00:00:30] Always put your script tags at the end, right before the end of body. The reason why is you want everything to load, you want all of your CSS and all of your HTML to load first. And then you wanna load your JavaScript. If I put this at the top, it's gonna make everything else wait for my JavaScript to load, and that's not necessary.

[00:00:50] You wanna show your users something as fast as possible so that your website feels faster. Despite the fact that it would load in exactly the same amount of time, or at least a relatively similar amount of time. You want them to see something first, because if they see something, then it feels fast to them.

[00:01:06] And this is as much a psychology game as it is a technical game, to make your site load fast. Cuz imagine I'm on like some really slow phone, out in the middle of the Australian bush, and I'm trying to like load this. It'll load this page and I can see the calculator.

[00:01:22] Despite the fact that the calculator has not actually finished loading its JavaScript first, I can see it. And I can start making a decision in my brain what I wanna do next. By the time I actually, okay, I'm gonna type, I forgot a row in here [LAUGH]. Yeah, we just don't need 1, 2, and 3.

[00:01:41]
>> Speaker 2: [LAUGH]
>> Brian Holt: Anyway, I'm gonna finish my spiel first.
>> Speaker 2: Or the plus sign.
>> Brian Holt: Plus, not important.
>> Speaker 2: [LAUGH]
>> Brian Holt: Least important part of HTML, just kidding, or of math. Anyway, so I'm looking at this, I've decided that I wanna press 2, which is not there. And by the time I make that decision and I go to press it, by that time, the JavaScript will have loaded, right, hopefully.

[00:02:08] So I click on it and then it will happen, right? Whereas doing the inverse, I have to wait for the JavaScript. When I load the page, it will be perfectly interactive and ready to go. But it'll take me that much longer cuz I have to wait for it to load and then I have to make the decision and press the button.

[00:02:24] So that's why you load in that order. The reason why you load CSS first is because you don't want it to load this.
>> Brian Holt: I wonder if I could just show you what that would look like?
>> Brian Holt: If I do this, when I come in here and I say, let's do that, and then we wanna do this like low-end mobile.

[00:02:52] And I refresh my page, no, it's not gonna really show you, okay.
>> Brian Holt: Network, okay, gotta remember how to do this, it's been a while since I've done this.
>> Brian Holt: No, I don't wanna do that either, okay, doesn't matter. So anyway, it would load bare HTML, so it'd be white and black text, right, like what we were looking at before.

[00:03:23] Before we loaded our CSS, and then it would flash and upgrade to this nice-looking style. That's called FOUT, flash of unstyled content, or FOUC, rather. And you generally try to avoid that, you wanna just load the first time something nice to look at.
>> Brian Holt: Great class by Steve Kinney on more performance-oriented things for JavaScript and frontend development in general, so check that out.

[00:03:50] Okay, let's go back to, there we go, so where did I go wrong? I thought I had enough of everything but I guess I don't, so let's just add one more of these.
>> Brian Holt: And we're gonna do 1, 2, 3, and +.
>> Brian Holt: So what is nice about the way that we did this, I just added another row of HTML, and guess what?

[00:04:21] It was already styled, it already worked, I didn't have to do anything else, and I think that's a pretty big win. So when they invent new numbers, they can put another row in there and it's gonna be great. I mean, I guess you could just make this a hexadecimal calculator, I don't know why you'd want to, but you could [LAUGH].

[00:04:39] And then you have more rows. Okay, we're back to base ten math now, so I have to make a calculator. And the way I'm gonna make a calculator is, I'm gonna have kind of three things going on at once. I'm gonna have some sort of running total, cuz that's the way a calculator works.

[00:05:01] Right, I add a bunch of numbers together, I subtract things and multiply things, I have some sort of running total. So I'm gonna say let runningTotal at the beginning = 0. Right, then as a user types in numbers, I have to keep a track of what they're typing in.

[00:05:19] Okay, so that's going to be, let buffer, that's what I'm gonna call that, like a buffer that's kind of waiting for user input. And that's gonna be string 0. And the reason why is, what's out here is a string, right, so I'm just gonna make it a string to begin with.

[00:05:37] Okay, then I'm gonna have something called previousOperator,
>> Brian Holt: What that's gonna be is, if I do 12 and I hit plus, right, the user hit plus previously. And I have to keep track on what they previously pressed. Right, so I hit 12, then I hit plus, 15, equals, I have to keep track that the last thing that they pressed was plus.

[00:06:04] Right, cuz I'm gonna display to them 27, but I have to keep track that the last thing that they pressed is plus, we follow? So that's what previousOperator's gonna be.
>> Brian Holt: So first thing I'm gonna do is, I'm gonna bind up my event listener.
>> Brian Holt: Which is going to be, where do I have it on here?

[00:06:33]
>> Brian Holt: I'm gonna have a document.querySelector.
>> Brian Holt: .calc-buttons. So I'm gonna listen at the top level at the container level. And then I'm gonna say, addEventListener, it's gonna be click, and get rid of that, function, it's gonna take in.
>> Brian Holt: That's why that probably doesn't work, event, that's actually exactly.

[00:07:17] I have no idea how this is working.
>> Brian Holt: That is fascinating, so I don't know how this is working right here because that is wrong. Okay, cool, it fixed itself.
>> Speaker 2: What's wrong with it?
>> Brian Holt: So if we go in here and look at my HTML or my, let's go through all of them.

[00:07:39] If we go and look at my JavaScript, inspect, and look at the JavaScript.
>> Brian Holt: Network, you look at this calculator.js, wherever that comes in.
>> Brian Holt: calculator.js.
>> Brian Holt: I guess I can click up here on the JavaScript. Well, let's just look at, it's right there. 404, remember you can't refresh.

[00:08:14] That's a fun bug, so Project.
>> Brian Holt: Go down here to calculator.
>> Brian Holt: This one, response, whatever. Let's just do, calculator.js,
>> Brian Holt: Right here.
>> Brian Holt: So, it does click here right button click event.target.enter text, right? That makes sense, but I am not tracking the event, like I did not accept the event parameter right there.

[00:08:57] I have no idea how that's working, that is mysterious. [LAUGH] It works, and it works in Chrome, it does not work in Firefox, and I'm sure that's breaking in Firefox.
>> Speaker 3: Something built-in that's figuring out.
>> Brian Holt: You probably a moron, so this is what we're doing. Thanks, Chrome, you are right.

[00:09:18] So I can not argue with that. Okay, use event there, I guess it does work. It's optional, just kidding, it's not. Okay, absolutely not optional, you have to put it in there. Okay, so I'm gonna call a function called ButtonClick{event.target.value).
>> Brian Holt: Okay,, and then I'm gonna write a function called button click.

[00:09:55]
>> Brian Holt: It doesn't really matter whether you put this in function, buttonClick and this takes in some sort of value.
>> Brian Holt: So I wanna do two different things.
>> Brian Holt: If it's a number, I wanna go down a different code path. If it's a symbol, I want to go down a different code path, right?.

[00:10:23] So, I need to ask, is value a number or not? And how can I do that? There's several ways, there's a function called isNotANumber.
>> Brian Holt: So if I do isNaN, like that,
>> Brian Holt: Let's see. Let's show you here in the browser, and then you can kinda see how this works.

[00:10:51]
>> Brian Holt: Let's get rid of the filter, filter go away. Clear, and there we go, okay? So, you remember our friend parseInt? If I give it 5, it gives me 5. If I give it C, it gives me Nan. Which is a specific in JavaScript which means not a number.

[00:11:17] The thing that you gave me is not a number. Or if I do like five divided by zero, it's infinity. Okay so there's a couple of them, how do you get that to work? Or like c plus five, edit five plus c. It's gonna do coercion, anyway. Nonetheless not a number, so you get not a number out of paseInt.

[00:11:47] So I can ask, is not a number, and another thing, this is a weird thing about JavaScript, so NaN, not a number.
>> Brian Holt: Not a number is not equal to not a number. Which like through the mathematics of it like two not a number, are could very definitely be very different things.

[00:12:12]
>> Brian Holt: So they could be separate types of not a number. So that's why there's a function of is not a number. It's nonsensical like let's not get too much into it but We can take advantage of this fact to say is parseInt value. So if this is not a number, it's a symbol, right?

[00:12:31] So right here I can say, handleSymbol with value and here I can say handleNumber With value, okay? Does that kind of make sense how I broke that down into two different things?
>> Brian Holt: So now I'm gonna write two functions here.
>> Brian Holt: handleNumber, which is going to take in value.

[00:13:01] And function. handleSymbol, which is gonna take in a value as well.
>> Brian Holt: So hopefully, you're kind of starting to see my thought process of decomposing this larger, gross problem into smaller, solvable problems.
>> Brian Holt: So numbers is pretty easy. If the buffer is triple equal to zero,
>> Brian Holt: You replace it, right.

[00:13:39] Because of it's zero, do I have it up here so you can actually see it. Clear. If I hit 5 while the buffer is 0, then it just turns into 5, right? You don't append, otherwise you start appending. So what that means is, if that didn't buffer it's just equal to value.

[00:13:59]
>> Brian Holt: Else, buffer You're going to append on the end of it, so I'm gonna say += value.
>> Brian Holt: Right? So again, if someone hits 7 and then you hit 5, you expect that 5 to go on the end of it, right? So that's what that += is doing.

[00:14:23]
>> Brian Holt: Then, down here at the bottom, I need to write buffer out to here, right? It needs to be written out there. If I don't write it, then it's not gonna get out there. So I'm gonna make a function called rerender.
>> Brian Holt: I'm just gonna call that any time that anything's changed that I need to rerender, so function rerender is gonna be really easy.

[00:14:44]
>> Brian Holt: All it's gonna do, let me just make sure I get this right. Yeah, I'm gonna write something like screen.innerText = buffer,
>> Brian Holt: And I'm gonna say const screen. This is a signed document that queryselector.screen. Okay, I have a code formatted that every time I click save it just reformats my code to be a little nicer.

[00:15:20] I quite like it, because then I don't have to think about formatting very much, but if that's what, if you see code shifting around, that's what's happening. It's called Prettier, if you're interested in it, okay? So now at least, I think if I hit 2, nothing will happen.

[00:15:41]
>> Brian Holt: Let's get rid of that. Smaller and make this go to the bottom, and please make this not be a mobile phone, okay.
>> Brian Holt: Have you gotten this far?
>> Brian Holt: handleNumber(value)function value, handleNumber, and I'm including this at the bottom, right? Okay,
>> Brian Holt: Screen. At the top I'm doing the document chris calc buttons.

[00:16:22] That's what that's called, right? Calc buttons, yeah, should be. Just console log here, console.log here. I do this all the time, console.log here. I think every web developer does. Just to make sure like stuff is, so you can see down here it's happening. It says here down there, so that function is happening, okay?

[00:16:53] It's calling button click. So if I get down here, is it going to in to handle number?
>> Brian Holt: It's not getting the handle number, okay?
>> Brian Holt: So why is that?
>> Brian Holt: console.log value, and we'll see what's being passed in here.
>> Brian Holt: Nothing is being passed in there, that is a problem.

[00:17:30] So why is that happening? event.target.value, so what is console.log(event.target.value)?
>> Brian Holt: Nothing, what's event.target?
>> Brian Holt: I don't want value, I want event.target.innerText, don't I? I do, value.innerText. That's what I'm interested in, right? I'm interested what the button is.
>> Brian Holt: Now you can see it's adding things to my buffer at the top and its re-rendering correctly, but I'm so used to typing event.target.value cuz that's usually what you do.

[00:18:20] You're usually not reading from the inner text, you're usually reading from an input and you get with value. So that's an easy thing to mess up, but now the numbers work, that's a plus, pun intended. I didn't even get a laugh. [LAUGH] That was bad, okay? I'm sorry, so handleSymbol.

[00:18:52]
>> Brian Holt: So what I could do here is I could do a bunch of if this, then this, else if this, else if this, else if this. There's a thing that's even better for that. It's called a switch statement, so I'm gonna say switch Value. So I'm gonna switch different code blocks based on value, and the first one I'm gonna be worried about, is case C, so if it's equal to C, then do this.

[00:19:20] Buffer is assigned zero, runningTotal Is assigned 0. This should be a string,
>> Brian Holt: And break. Break, you do have to put break;, that basically means I'm the end of this case, okay? Then I'm gonna do case equals, so if its equal to that, if, so what the switch is saying is like, take this expression, so value.

[00:19:52] If it's equal to C, then do this, if it's equal to equals then do this, so on and so forth. So first you need to say, if there is nothing, if there is no previous operator
>> Brian Holt: Yeah, so let's do this. If previous operator is assigned to null, you need to know about null.

[00:20:15] I was trying to kinda not talk about it but it is a useful thing to talk about. So null is different than zero. Null is the absence of anything, right? So in this case, we're actually gonna make previous operator up here initially signed a null. It means nothing has been previously assigned here.

[00:20:35]
>> Brian Holt: So if nothing has been previously assigned, previous operator here should as well be null. When you're clearing everything out
>> Brian Holt: So that's what null is. Null is just like the black hole. Nothing has been there. It's not zero, it's null. Other languages call this other things, like I think Ruby calls it nil.

[00:20:57] There's other names for it. Here it is called null. So if a previous operator is null, it means that you should do nothing, right? If you just keep pressing equals on a calculator it does nothing. So what you're going to do here is you just say, hey, return.

[00:21:14] Like skip the rest of this function, just get out of here. That's what return is going to do here.
>> Brian Holt: Otherwise you're gonna do something, I'm gonna call it flush operation, which is gonna mean, I have some sort of previous operator, I want you to now do that.

[00:21:30] I want you to commit to that operation that you were holding onto, okay? So flush operation with parseInt buffer. So I'm gonna turn buffer into a number and pass it into flushOperation. I'm gonna set previousOperator = null. I'm gonna set buffer =
>> Brian Holt: runningTotal.
>> Brian Holt: And I'm gonna start running total equal to 0.

[00:22:08] Break. So I'm gonna set buffer equal to running totals so that next time that I call re render that buffer is going to be Actually even better than making that, I'm gonna make this.
>> Brian Holt: So if I put these double quotes here, and this is doing string concatenation.

[00:22:35] So I'm gonna turn running total into a string by doing it. This way right. And we're keeping offer a string the entire time. So it's a good idea to keep something the same type. You don't wanna be switching types back and fort really don't you. Okay and then break that we're done.

[00:22:52] Then I'm gonna do case back arrow
>> Brian Holt: Back arrow. Maybe it's left arrow.
>> Brian Holt: Just called arrow. Let's see what happens. And which one did I use? This is a problem? I think that's the one.
>> Brian Holt: Even better we'll just copy from the index additional. Then we definitely get the right arrow.

[00:23:37] It was up here.
>> Brian Holt: So that case we're gonna call, if (buffer === 1), buffer that length rather.
>> Brian Holt: So, if it's 5, then it's gonna be 0. If it's 0, it's still gonna be 0 whenever someone does a backspace. The buffer is going to be assigned just 0, else buffer is going to be assigned buffer.

[00:24:16] We've talked about substring a little bit, 0 to buffer.length minus 1.
>> Brian Holt: So you're gonna take one off of it, and then break.
>> Brian Holt: Lastly, we're gonna default which is the default thing that you want it do if none of these other cases match, which means it's some sort of operator at this point.

[00:24:42] We've covered every other case, so we're gonna say handleMath(value) break.
>> Brian Holt: Okay, good so far? Please.
>> Speaker 4: When you do the 0.
>> Speaker 4: Type, isn't that supposed to be buffered out, length equals to one? Okay, got it. You just said like buffer length, so it doesn't matter. Got it.

[00:25:15]
>> Brian Holt: Yep.
>> Brian Holt: Good question though. So, 35 now, I can hit clear and nothing happens. Neat, why is that? Clear. You have to call rerender after all of this, right? Where do I call rerender in here?
>> Brian Holt: Yeah, I call it in button clicks, so let's just move this from handleNumber up here, cuz you should always rerender after every single time.

[00:25:57] So now if I refresh and say 28 and I say clear, it goes back to 0. Or 36 and I hit delete, it knocks off the 3. If I hit delete again, it hits 0. And I can hit backspace as much as I want now, because 0 is length 1 so it does nothing, right?

[00:26:15] Okay. Now down to the handleMath part.
>> Brian Holt: So handleMath, function handleMath with value.
>> Brian Holt: So const intBuffer, I'm gonna now coerce this into a number. So I'm gonna say parse. Int value, sorry not value, but buffer. This is a representation of what's on the screen now.
>> Brian Holt: Okay, and.

[00:27:01]
>> Brian Holt: If runningTotal,
>> Brian Holt: What am I doing, not there.
>> Brian Holt: If (runningTotal === 0) then runningTotal = intBuffer;
>> Brian Holt: Else FlushOperation of intBuffer, okay? So if someone does a math operation, and, so if I come in here and I say clear 25 times, and I click times, I should be storing 25.

[00:27:47] That's actually now my new running total. So that's why I keep that inside of running total. Otherwise, I have to go do some sort of mathematics to get the new value. So that's why I'm gonna do flushOperation there, okay? Then previousOperation, we know if we're in handleMath, that previousOperation is some sort of operator.

[00:28:06] So, we're going to store our value in there. And then buffer, is assigned 0, right? Because we're ready for the next number to come in. So that's how handleMath is happening here.
>> Brian Holt: Okay, I think the last thing we need to do now, is the committing of math, right?

[00:28:26] So, function, flushOperation, it's gonna have some sort of IntBuffer in here, that's going to take in. And in other words we could do this with a switch statement or you could do this with an if statement. Let's do it with an if statement just so you know what that looks like, previousOperator === +.

[00:28:50]
>> Brian Holt: And we're gonna say runningTotal += intBuffer. And the rest of these look exactly the same. So else, and we can even just copy and paste this. If it's equal to minus, right, then you minus equal into buffer.
>> Brian Holt: And if it's equal to, I'm gonna just copy this out of here, if it's equal to multiplication, then you're going to times equal it.

[00:29:35] And you could say else equals to this. But we're just gonna say else cuz everything else would be division, right? So divide equals.
>> Brian Holt: Refresh. Now let's try 25 plus 5 equals nothing, shit. Did I not? I just didn't handle the equals case did I? I did, it should work.

[00:30:10] Case equals.
>> Brian Holt: FlushOperation(parseInt(buffer)) previousOperator = null. Buffer = "", runningTotal's that.
>> Brian Holt: What did I have in here? I think I had this.
>> Brian Holt: Interesting, okay. So let's see what's going on here. Case, so let's make sure we're actually getting into this case.
>> Brian Holt: So I'm not, I see, +3 =, and I am getting there.

[00:30:55] So that's good. So we get down to flushOperation. Make sure we're getting into that.
>> Brian Holt: So we're never getting into flushOperations, let's figure out why we're not getting into flushOperation.
>> Brian Holt: Where is the other console.log, let's get rid of that, it's kind of noisy. Okay, so handleSymbol, case here, so we're getting here.

[00:31:56]
>> Brian Holt: And the math const intBuffer here,
>> Brian Holt: So let's make sure that this,
>> Brian Holt: console.log,
>> Brian Holt: previousOperation, previousOperator. That's probably right there, previousOperator.
>> Brian Holt: And this should be previousOperator, previousOperator right here. So I had this as previousOperation, it needs to be previousOperator.
>> Brian Holt: Easy to mess up. 25 plus 3 equals 28, hooray, times by 6, divide by 2, minus 6, awesome, any questions?

[00:33:03]
>> Speaker 4: Why does it keep turning to zero?
>> Brian Holt: Sorry?
>> Speaker 4: Why does it keep on turning to zero?
>> Brian Holt: When I hit like minus, I did that on purpose. The reason being, let's get rid of that, is cuz I set the buffer to zero right there. I had pulled out my calculator and that's what it does, so that's what I emulated.

[00:33:24] You could totally,
>> Brian Holt: So if I did that 65 plus 3, I gotta refresh the page, 65 plus, and it just stays like that, right, 3, equals. You kinda need to because on the next time when someone clicks something. So 65 plus, right now it's in plus mode, but I'd have to otherwise delete the number to enter a new number so that's why I did that.

[00:33:57]
>> Brian Holt: Laziness, I think the answer to your question is laziness, any other questions?
>> Brian Holt: Do you understand, do you feel you understand what happened there? I think it's pretty cool, you now have the skill set after a day and a half of working at this to build a functional, nice-looking calculator.

[00:34:21] Most JavaScript applications can be a lot simpler than this. Building a website can definitely be simpler than this.