All right.
So welcome back for the second part of writing the drawing logic on our web application.
The goal of this lesson really is to make sure that we only draw when we're actually clicking and dragging
rather than we're just mousing over the canvas.
So we only want to draw when the mouse button is held down and there's actually three other things we're
gonna cover in this lesson as well.
We're going to cover how to respond to touch events for tablets and phones.
We're going to introduce the programing concept of scope in JavaScript and we're also gonna learn how
to refactor and reorganize code in this code.
So to start this lesson off I'd like to pose a challenge to you.
I'd like you to implement the following functionality on this Web site.
Here's the behavior that I'm looking for.
By the time that you've finished the challenge you should be able to click and drag on the canvas in
order to draw and in the console over here you should be able to see mouse pressed when you push the
button down and you should be able to see mouse released when you lift your finger off the mouse button.
So this is what we're after for this challenge.
So in order to complete this challenge you're going to have to do three things.
First you can have to listen for one more mouse event in your code.
So I recommend you pull up the documentation from NBN or W3 schools to check what mouse event that could
be second.
You're also going into a way of tracking the state of the Web site.
Meaning is the button currently being pressed or is it not currently being pressed.
So you're gonna have to add some code around that in order to track that.
And thirdly you're going to have to change the code inside mouse down a little bit in order to get that
the behavior that we're looking for.
But I'm gonna do is I'm gonna give you a couple of seconds to pause the video and give this a go.
But if you're unsure because this is a bit more of a complex challenge I'm going to give you two hints.
So I'm going to give you the first hint after a couple of seconds and then will give you the second
hand.
After a couple of further seconds so positive.
Now if you want to tackle the challenge without any of the hints
so here's hint number one.
The event that you're looking for is called mouse up.
It's this one right here.
Now pause the video and see if you can complete the challenge.
The second hint I'm gonna give you is you're gonna have to create a variable to track if the mouse has
been pressed so I'm going to create a variable here and I'm going to call it is painting and I'm going
to store a boolean in here.
And I'm simply going to store false.
Of course you can use any name that you'd like.
But the important thing is that you're going to change the value of this variable depending on the mouse
events
all right.
So here's the solution.
The first thing I'm going to do is I'm going to add that second mass event and I'm simply going to copy
this line of code here actually.
And when I come down here and I'm going to add the mass event just above this curly brace and it's not
gonna be mass down.
It's gonna be a mouse up and I want to change the console log message here to mouse released.
And when the mouse has been released then is painting should be equal to False.
So I'm gonna make sure that the variable that I'm using to track whether the mouse is being pressed
is set to false when the button is released.
So when should is painting be equal to true.
Well of course when the mouse has been pressed down when the button has been pressed down it's in this
case that is painting should be equal to true.
So now we're able to track whether the mouse is being dragged or not.
I'm also gonna change the console log message here to mouse pressed.
Now that we're tracking whether or not we are dragging the mouse we can check against is painting to
see whether we should draw something inside.
Mouse move.
So what we want to do is we only want to execute these lines of code as long as his painting is true.
So if is painting.
So if true then execute these lines of code it's going to move these up here and then what I'll do is
I'm going to reinvent my code so I'm going to right click here and I'm going to format my document.
So if you're right clicking as well then check with the keyboard shortcut is here because you're probably
gonna be using it quite often.
So for me it's the option key shift and F but if you're in Windows just check what it is that you see
here.
All right.
Perfect.
So let's test this out.
Let's save our progress head back into chrome and let's refresh our site.
So I'm going to refresh and then I'm going to try and clicking and dragging.
But what I'm seeing here is that nothing has changed.
Nothing has changed at all.
So what's going on.
Well maybe I'm actually still getting the old version of my web site.
So one of the things you might have to do is you might have to actually clear your cache so in Chrome
go to the overflow menu and more tools and go to where it says clear browsing data.
And I'm just gonna clear the last 24 hours and then I'm going to refresh and then my changes have been
applied.
So this is a good thing to be aware of.
You can get very very confused by chrome just giving you the previous version of your Web site and not
really reflecting the changes.
So this is a good one to remember.
If you get some unexpected behavior just clear your browsing data and refresh the site again.
All right.
So clicking and dragging.
Right.
This is where we're at.
If I click in the middle of my canvas I press my mouse and I move.
Then I get this line up here from the top left corner.
And if I let go and then press again and I move I get a line appearing between the point I was last
at and where I clicked.
So why is this why is their connecting line coming in from the top left.
When I first click somewhere on my canvas Well this all has to do with the initial values of the current
X and the current Y when we click down and we move our mouse we're essentially grabbing the top left
corner and we're drawing a line to where our mouse has moved to.
So obviously we need to think very carefully about what the starting values for these two variables
should be and the place that we would ideally set this in order to avoid the strange behavior is when
we first press our mouse down it's here that we actually want to execute this line of code.
And this line of code.
So the current X and the current Y should be set to the coordinates of where we've actually clicked
with our mouse.
Let me save our changes head back into chrome refresh and just check whether this hypothesis is true.
So I'm going to click again somewhere on my canvas and the behavior is now what you would expect it
to be.
And that completes the first challenge.
So well done if you were able to solve it without the hints but no worries if you needed a couple of
hints to help you along the way.
JavaScript is something that's new after all but I think this is a good point to actually try and solve
another challenge namely how do we stop the mouse drawing when it leaves the canvas.
Here's what I mean at the moment.
If I click down and I move my mouse off the canvas and I come back then I'm still drawing.
As long as I'm still dragging my mouse.
Right now the behavior that I'm challenging you to implement would be something more like this.
You click down and if you don't release it stops drawing.
So as soon as you move off the canvas I'd like the drawing behavior to stop.
I'll give you a few seconds to pause the video and try and implement this for yourself
ready.
Here's the solution.
So if we look at the MDA documentation we see there is one event here called Mouse leave and the description
is a pointing device is moved off the element that has the listener attached.
So what does this mean.
Well let's take a look at the documentation for attaching a listener.
So this is the page on adding an event listener from MGM.
And what we see here is that the syntax looks something like this.
We have a target and then we have a dot and then we have add event listener.
So what's the target that we've been using so far.
If we look at this code we can see that our target was the entire Web site it was the entire document.
But if we want to get the behavior that monitors whether we leave the canvas what do you think the target
should be.
Well it should be the canvas right.
So let's implement this.
I'm going to come down here and I'm going to copy this bit of code here.
And I'm just going to paste it below.
I want to change it from document to canvas.
And I'm also going to change the mouse event from mouse up to mouse leave and delete this console log
statement here.
But I'm going to leave this line.
I'm going to leave his painting is equal to False because what this will do is we'll make sure that
we can no longer draw.
Once we have left the canvas with our pointer.
So let's see if this indeed works.
I'm going to save my changes.
Come back here and refresh my site once again and when I click and drag and a move off the canvas and
I come back and voila no more painting.
So this indeed works the reason I wanted to show you this is because you can actually attach an event
listener to any number of targets.
It could be the document as a whole.
It could be the canvas or it could be our button.
Right.
In fact let's go ahead and attach an event listener to our button and we actually gonna do this in the
index thought each time El file.
So down here where I've got my script I'm going to add a listener to our button.
So first I'm gonna have to get hold of my button.
It's gonna be document and then get element by I.D..
And what's the idea of the button.
Well I'm gonna go up here and just check what it is.
So I've got my button here and it has the I.D. check answer.
So that's the idea I'm going to supply its check answer and everything's case sensitive.
And it has to be spelled exactly the same of course.
And once I've got my button here I can then add an event listener.
So what event am I going to listen for.
On my button I'm going to listen for so-called click events and what do I want to happen once I click
on the button.
So what I'm thinking is we should follow through to the last step of working with the canvas namely
clearing it resetting it for the next number that we're going to draw.
So when I had my callback function here that's going to be a function.
And it's not going to have a name.
And it's also not going to have any parameters but what it will do is it will clear the canvas.
So how we're gonna do that.
Well let's call a function called Clear canvas and the semicolon at the end.
Now clear canvas actually doesn't exist yet.
I've added it here but we still have to create it and I'm going to create clear canvas inside the drawing
Dot.
J ust file.
Let me scroll up and just click the minus sign here to collapse prepare canvas.
And when I want to do is blow the closing curly brace of prepared canvas I'm going to add this function
clear canvas so function keyword and then a clear canvas and the name of the function here.
And the spelling has to match what I'm using here.
So clear canvas has to be spelled exactly the same as this one right write.
And it's gonna be the job of this function to reset everything we have on the drawing front.
So what does that involve.
Well we're gonna have to reset two things.
We're gonna have to make the canvas black again but we should also reset the coordinates that we've
been tracking.
So the current x.
The current Y and so on.
So when I take these guys up here and copy them paste them below.
And then what I'll do is I'm going to delete the keyword here because we're reusing them we're not going
to create them.
And I want to format my code so that it's indented properly.
And now what I've got is I've got four lines of code that are resetting these variables to their starting
values namely zero.
So that's step one step two is going to be making this canvas all black.
How do we do that in prepare candidates.
How do we make it all black.
We used this line of code right here.
Right.
Context thought Phil rect and then we provided the width and the height of the canvas to fill the entire
canvas with it's background color.
So let's try and copy this line here.
Paste it inside clear canvas.
So right here and then we can try and save our changes and see if this will work on our site.
So when I refresh and then when I click here draw something and then I'm gonna press the mouse button
what's going on.
Let's check.
OK.
So I've saved my changes in this file but I haven't saved my changes in the index that each terminal.
You still see that circle over here.
So I'm actually not getting any code being executed when I press the button.
So my save the changes here and then I'm going to try again.
I'm going to come back.
I'm going to refresh and I'm going to click here draw something and then press the button.
And what happens at this point we get an error.
It says on caught reference error context is not defined at Clear canvas on line number 17.
So in this code if we look down here we go to the drawing not just file.
We look at line number 70 and it's complaining about this line.
It's saying that the context is not defined.
So this thing isn't defined as no context is.
So why not.
We've created a context right.
It's right here.
So what's going on.
Why is it that it has a problem with context but it doesn't have a problem with the current Y or the
current X..
Why are these fine.
And this is not well let's collapse this function and let's collapse this function.
So what we see at this point is that we've got current X and current Y being defined outside of prepared
canvas.
So that means that we can access them inside clear canvas on the other hand.
The context was declared inside prepare a canvas with this constant keyword.
And what this means is that we can only access the context inside of prepare canvas in programming.
This has to do with something called scope but what does that mean.
Well the scope for these variables here is the entire file the entire drawing not just file.
We can use them anywhere inside but the scope for the context is only this prepare a canvas function.
In other words const context is a local variable.
It's local to prepare a canvas and var current ex up here is a global variable.
It is accessible in the entire file.
So what if we actually want to use the context and the canvas inside clear canvas.
Well we can try and promote these two guys.
We can make canvas in context global just like the current ex and the current Y.
So how would we do that.
Well we can create a canvas here and we can create a context here.
So I've created two variables.
They're global because they're outside of prepare canvas on the same hierarchy as my other variables
appear.
And what I want to do is inside prepare canvas.
I'm going to delete my keyword cons too.
And what this does is it will take the existing canvas that I've got him and it's at this point where
it gets a value.
So initially the canvas is empty and then we're storing the canvas that we're getting from the document
inside this variable on line 15 and just below the context which previously didn't have a value gets
his value from the canvas with get context.
So let's save these changes and head into chrome and refresh and let's see if we get the same error
again.
So I want to draw something here and then press the button and behold there is no error.
And also we're successfully filling the canvas with the background color so we're erasing all that was
drawn on the canvas successfully.
Brilliant.
So we're almost done.
But there's one thing we haven't thought about yet namely does everybody use a mouse when they're gonna
interact with this Web site.
Well not really right.
If you have a phone or tablet you'd use your finger instead.
You wouldn't be using a mouse.
So let's check how our Web site behaves on a phone or a tablet.
The Chrome developer tools can actually help us with this.
So do you see the symbol up here.
It says toggle device toolbar and if you click on it you get to choose a device to simulate.
So at the moment you can see that I've got responsive selected here but here I have a whole choice of
tablets and phones I can use instead.
So let's leave it on responsive for the time being.
And then if we look over here we see this menu says mobile mobile no touch desktop and desktop touch.
If you don't see this menu by the way if you're looks like this then simply go here and say ad device
type then it will appear.
So many select desktop.
And this is the desktop version of our website.
And if I click and draw I have everything working as it should.
But if I select mobile and I try to draw on my canvas.
Nothing happens.
But if I press mobile and say no touch.
So in this case it seems to be working but mobile touch doesn't work.
So why is that.
Why does my canvas not like it when I'm using it on an iPad or on a phone.
The reason is is that if I use it on an iPad I'm not using a mouse.
I'm using my fingers and and that means we're not getting a mouse event.
We're getting a touch event.
The browser will actually make this distinction.
It'll distinguish between mouse events and touch events.
But we should really make our website work on a tablet as well right.
We might want to pull us up on an iPod one day and be able to draw something on this canvas.
So how can we do that.
Well let's check what kind of touch events there are.
So if I go to the MDMA documentation again and a search for touch then I can see that there are in fact
four different kinds of touch events there's touch cancel touch and touch move and touch start.
At this point I'd like to pose a challenge to you again.
Can you use these touch events here to make our website work for the iPod.
Can you make it behave as it should on an iPod using these touch events.
That way everyone can use their fingers to draw into the canvas.
Now the code is going to be very very similar to how you were working with the mouse events before but
there's only going to be one small twist in order to get this working.
Have a google and check stack overflow for the difference in syntax on how to get the touch coordinates
versus the mouse coordinates.
I'll show you the solution in a few seconds.
All right.
So here's the solution.
I'm gonna come down into yes code on the drawing dot j ust file and I'm going to copy this bit of code
here where I'm checking for mouse down and then I'm going to paste it below.
I'm going to add a little comment here with two forward slashes that says touch events and instead of
checking the document I want to check the canvas and instead of checking for mouse down I'm going to
check for touch start and what I'll do is I'm going to log touchdown instead of mouse press.
Now if you did a little bit of research on how to get the coordinates for the finger touching the canvas
you would realize that this isn't going to work.
Instead you have to use a slightly different syntax.
You have to go and get the coordinates via something called a touch scrolling down on the site.
I can see that in order to get the coordinates from a touch you have the event and then you have top
touches and that the square brackets zero and then dot client x.
So why is that.
Why is the syntax different for the mouse events and the touch events.
Well with a mouse you've only got one mouse right.
So there's only one set of coordinates.
But with a touch there's multi touch right.
You can touch the screen with one or two or three or four fingers.
So that means that the touch events actually store the coordinates for the different fingers in something
called an array.
So you get a whole list of coordinates to choose from depending whether it was the first touch or the
second touch of the third touch and the first touch you would always get with the first item in this
list.
So if I just take what it said in the documentation and I write event dot touches square brackets zero
and I get the coordinates for the first touch which is all I care about everybody is gonna draw with
one finger not two or so I'm led to believe and I want to find my current y here as well then I can
try this out on the iPod going to save the changes and I'm going to head back here when I refresh and
then I want to click and drag.
So what am I seeing well I'm seeing this I'm seeing touchdown.
So this means that touch start is working but of course not painting it.
And the reason we're not painting it is because we have to implement the other touch events namely touch
move touch and and touch cancel so let's do that.
Let's take mouse leave and it's pasted below.
And instead of mouse leave Let's go for touch end and let's add the touch cancel as well.
So that leaves touch move.
Well let's come up here where we've got our mouse move because the logic is going to be very very similar.
And I'm going to added below I'm going to add at the bottom.
Once again I want changes to canvas so we're only listening for.
Touch move events on the canvas and then it would have to change this to touch move as per the documentation.
And of course in order to get the coordinates I'm going to have to make sure I get the coordinates for
that first finger touching down.
So for my current ex I'm gonna paste that here and from my current why when a pace that here.
So now it can save the changes head back into my browser refresh and try.
And it works.
Brilliant.
So this is the behavior that we're looking for after the challenge.
Fantastic.
So now our Web site will work on both mobile and on desktop.
You can either draw on this canvas using a mouse or you can draw on this whole thing with your finger.
Let's have a look at our drawing logic one final time what we notice at this point is that we've got
the same code pasted in two different places.
We've got these five lines of code here and we've got the same five lines of code right here.
Let me show you how to reorganize your code and simplify this whole thing a little bit.
Using this code it has some really great tools that will make this really really easy.
Instead of having the same code in two different places let's refactor our code so that we have a separate
function that's called draw and we can call that function on both the touch move and the mouse move
the way to do this.
The easiest way is to right click and go to refactor and then you're going to select extract to function
in global scope.
There's that scope word that we learned about earlier.
It's been selected.
And when I call my function draw and hit enter.
So now I've got a function call here that says draw and if I scroll down then I see this draw function
right here at the same hierarchy as clear canvas.
It's a clear canvas has global scope and draw has global scope.
And what this means is that I can come to my touch move and I can replace these five lines with a call
to my draw function.
So I think this is quite nice and makes our code quite readable if this painting set your coordinates
and then draw scrolling to the top and collapsing of three functions you can see the structure of the
entire file very very clearly.
We've got our constants appear where we're sitting a few values on how to color our canvas and how thick
the lines should be.
Then we have some global variables and then we have three functions prepare canvas where we're setting
the listeners and formatting the styling.
We have the draw function which draws our lines and we have the clear canvas function which resets everything
so that we can draw something on a blank canvas.
So that's it for the drawing logic of the Web site.
Hope you enjoyed the challenges and I'll see you in the next lesson.