Hi. In this session, we're going to look at how to get more complex input into your web app. So far, we've only been able to do this by clicking on a button, but we'll look at more complex methods in this session. What we're going to do is make a simulation tool. This will help us to understand a complex graphical concept and we're going to use that as an example to allow us to have some more complicated input into the program to adjust the way that the simulation works. We're going to allow you to have input boxes that you can type values into and sliders as well. Those new values coming in will adjust what we can see on the screen. There's plenty of other input options to explore as well, but these will be a good template to start with and give you an idea of what's possible. The context is going to be exploring a Bezier curve. These curves are used quite often in computing graphics systems to allow you to draw really nice, smooth flowing curves. There are basically two parts to one of these curves. There's the line itself, that's the line drawn in red here in the diagram, which might be initially straight, but then becomes a curve under the influence of the control points. The control points are two small white squares towards the top of the diagram, and they influence the shape of the curve. Each point is associated with one end of the curve and mathematically the line between the end of the curve and a control point forms a tangent to the curve that actually then comes from that point. Then the way those two curves work with the relative tangents and the way they can join up creates the full curve, as you see here, the red curve going all the way around. What we're going to do is create a tool that helps us just to play with these curves, to see how the control points influence the shape of the curves that we end up with. It's an interactive tool where we're going to be able to move those control points around and then we can immediately see the result. For example, say we had here the two endpoints. If they're sitting at 50, 50, and 150, 50, then if you had the values opposite, these are the x, y values for the two control points. One up at the top, also 50 and one up at the top of 150 and so straight above the two ends, just as they're drawn here with the small red circles, then you would end up with a curve, something like the one that's just shown here. If we went in and interactively changed the values in these boxes, then we'd want to see the curve changing. That's the idea behind the tool. It just lets us play around to see how the curve changes as we move those points around. Can we draw Bezier curves in SVG? We can. This is the format of them here. We have a path and it's just a particular kind of path. You can see in the string under the D attribute here, we're moving to the absolute position 50, 50. That's the left-hand end of that curve. Then capital C indicates that we're going to have a Bezier curve at this point. The left-hand end or the first end of the curve is wherever the pen is right now. We've just moved to 50, 50. One end of the curve is going to be at 50, 50. Then the next two numbers are the first control point. That's 50 and zero, so at C 50, 0. That's the first control point. The next two numbers are the second control point, so that's 150 and zero. Then the final two numbers, are the endpoint of the curve. Remember, the start point is wherever I am now, the endpoint is the last two numbers, and then the two pairs of numbers in the middle are the first and second control point. If we indeed had that curve here and we were controlling it via these boxes and you can see we've got the first control point, 50, 0 in control 1x and 1y. Then 150, 0 in the other two boxes control 2x and 2y. How are we going to go about creating this as a simulation using HTML, SVG, and JavaScript? Well, first, we're going to need to draw an initial state of the curve, so we need some HTML to draw that. We want the lines as well to the control points. Let's not worry about all these circles, that's just going to add to the complexity, but let's just have straight lines and then the end of the line is going to be the control point. Then we're going to add some input boxes, that's new as well, so we'll be able to type into those. Then if we press "Enter" inside the box, what we want to happen is that the curve automatically changes. We'll add IDs to all the necessary components that we want to either read from or update because you can imagine in order to make this work, whenever somebody makes a change to one of these boxes, we're going to need to read that new value out of the box, so we're going to do some reading. But then we're going to need to write the relevant values into the HTML objects in the DOM object. Then that'll automatically cause the Bezier curve we see to change, but we'll also need to change the control point lines as well because we've got these two control point lines for the beginning and end of the curve. Finally, we'll write a callback function that does that work so that'll get called whenever a value in a box is changed. As I say, it'll be accessing the document object model to get the relevant HTML object out. Then back into the HTML, we'll make sure that there's appropriate event handler calls to this function in the elements that create the boxes. Well, here's some code to draw the curve and the control point lines. You can see we've got our usual setup, put an SVG container. Then the first path is the Bezier curve, the one we just looked at, and then the second two paths are the control point lines themselves, so they're just two straight lines. We can see we've got the control point lines are in red. We probably don't want the Bezier curve to look quite like that. Let's just run that up here to see that we get the same thing, if we run that. There we go. So we probably don't want that curve to be filled like that, so let's do a bit of adjusting there. Let's change that so that we've filled it with white and then we'll just do the stroke of it in black, so let's just do that. I'll put that in under the d there, fill equals white, and stroke equals black. I hope you can see how consistent all of these is, the same attributes appear in many different HTML objects. There's a great consistency here between these, so let's have a look at that. That's better. Now we get our line as we were expecting. That's good. Right now, we want the input boxes. Let's just deal with the first control point to start with. Let's not worry about both of them. We've got a couple of items here for each control line point for each of x and y. You'll see that we're constructing both a label and an input element. We're going to label element and an input element. The label is just a text that you see there, ctrl1x. The input element gives us the actual box. If we provide a value attribute here, that outputs an initial value into the box for us. You can see that all of this has been wrapped up in a paragraph element p and the slash p there, beginning and end of a paragraph. That just makes sure that these get lined up one upon another. Let's put those in. We'll see what that all looks like. Let's pull it out. I'll just show you what happens if we don't put those paragraph elements in. Now this for attribute that I'm putting in, you'll see what this is required for in a little while. But it helps just to connect up the label with the box. It turns out to be quite useful to put that in there. Then we're going to have an input element with the initial value 50. We'll just put that like that for a moment. Let's just copy that. Copy, paste. I seem to have forgotten the input. There we go. That'll be 1y and 1y there and we'll make the initial value. The initial value should be zero, not 125. There we go. We've got our two boxes. Let's just run that. Whoops. You see they've appeared all over the place. What you're really seeing, now if you look at it carefully, and this is a bit of machine side thinking, tech surface task machine, what we've now got is we've got the header Bezier curve simulator. That's the H1 tag up there, the H1 element. Then we've got the drawing area and that's 200 by 100. It's 100 deep, which is double the height of the drawing you can see because the drawing and it goes down to 50, so there's another 100 for that drawing area. What's then happened is that the label and the input box have just been plunked down next, as it were in a line just straight across, and then the next label, CTRL 1y, and then there wasn't space for the final box. That's just float over on to the next line. To make that look at least a little bit neater, let's put the paragraph element around it. We don't want the rest of that that you see. Sometimes it's not useful the way JSFiddle add stuff in for us. But sometimes it does add things in healthfully, so it's rough and smooth really. When you're actually writing from scratch, it's useful if you're just trying to add stuff in later, it can be not quite so useful. There we go. Let's try running that. We've got a paragraph marks in there. Well, that's certainly looking a bit better. One of the things that wasn't so good looking about that is the way the two boxes. We're only going to put small numbers in there, but they're huge boxes going all the way across. You'll always find ways in which you can make the styling of things look a bit nicer. We still want some input box, but maybe we don't want quite such a big input box. We can do that with a little style marker here with the property width and the value being put in is 3em, and em is a unit matching the current font size. What we're specifying here is what we want to have a width of about three times the current font size. You can play around with this. This seems to be a suitable amount, so let's just pop those two in because it does make it look a bit nicer. Style equals, okay, so it's inside the quotes. Then we're going to have 3em cases for that one. Then down here to style equals width. That's not quite right. I was wondering why it wasn't coloring issue. You can always tell you've made a mistake when things aren't being colored correctly. Can you see the reason? The reason is because I've not put this inside the input tag, so it should be there. Now that's working fine. Let's just move that one inside as well. Now, in these last few videos you'll have seen, I've made quite a number of mistakes as I've gone along. It's just to let you know that it happens all the time. We all make little mistakes playing this game, so don't beat yourself up if you find you're making little mistakes quite often. But just always look carefully to see what's going on, what you can see in front of you and you'll pick them out, but it's completely natural. We all do it all the time. It's very tricky to get this really precise language exactly right first time every time. That's why it's so useful to have checkers that check it for us. In this case, the coloring often tells you when something's gone wrong. You can now see that now, that's run we've got some slightly smaller boxes, so they look a bit more appropriate. Just to say about the tech surface and stuff on these input boxes and exactly what's going on. If we put an ID label in the input box with that same label that we've got here in the four-part, then that connects up the label to the input, and that can be quite useful because then if you select the label, you're also selecting the textbook. Let's just see that in action. We've got the input. Let's give the input the same name as that for attribute ctrl1x. I'm sorry, you can't see this. I'm doing this up here. I'll do the same here. ID equals ctrl1y. There we go. Now we've connected the label to the input through that name. Then we can go ahead and run that. Now what you see is if I click on control, you see I can click anywhere around here and it selects the right thing I can do in the box or outside the box. That's often very useful to help your user not make a mess. Now you'll see these boxes are active. I can click on them. I can change the values. Nothing actually happens when I do that, but I can do it. From the point of view of the HTML side, things are active and working, but I've not set anything to happen when these boxes actually get pressed. Just to confirm that this does in fact work as we expect. If I take that ID back out again, and then so I've done that for the y1, you can see now when I click on 1y nothing happens, but if I click on 1x, it selects the box. You can see that there is value in putting a little four label in there, and putting the ID in front of style. Put that back in. There we go. Otherwise, yes, I think it's clear how this is working. There are many different kinds of input that you can have. This one here, as I say that by default, you just get a little text box like this. We'll see a bit later on, we'll see sliders, but you can have radio buttons and choice boxes. There's a number of different ways in which you can get input into your programs. We've just done that. Let's now write some code to make something happen when those values change. What we're going to do is we're going to add IDs to all the components that we need to either read from or update. Because we're going to be writing JavaScript code and we're going to have to get to all of these elements. If you think about it, we're going to need to read from, I think I've got that wrong way round. That should say, write to those ones and read from these hunts. We're going to need to read from the input boxes, and we're going to need to write to the three that I've written there, the curve and the two lines. Because those are going to get outdated as we change the value. I've just made a silly mistake there. That should say write to these for the three green ones and read from these for the two red ones. We need to put those names in. Let's go ahead and do that. We just can pop them in straight after the start of the path tag, so ID equals busy. Of course, you can give these any names you like. It's helpful to give them slightly meaningful names, so that you can read your code more easily, but the computer doesn't really care what you give them as long as you use them consistently. Well, it doesn't even care about that. But for your program to work, you're probably quite well advised to use them consistently anyway. Sorry, I've got to say ID there. When you're talking away it's easy to just make little mistakes. There we go. We've got these two down here already, because I've put them in for the label lines to connect everything up. We've got all of our elements labeled appropriately. Now we'll write the JavaScript function that's going to handle the event. We just need something like an update and give this any name you like, but we'll call it update. We're only actually working on one line here, and we're just going to work on the left line, because we've just got the left control point line, because we're only really working with the left control point at the moment. We need to get those. Those are the things that are going to be updated. Once again, we use document.getElementByID to actually use that method to actually get those two objects. Then we also we want to get the two input boxes for the x and y value of the first control point. We get those, but then we also get the current value out of them. You can see we can do that with just dot value, gets us directly to the actual value that we want. That'll actually be whatever is being typed into those two boxes. Then we go ahead and set the attribute for the Bezier curve because the curve itself is going to change now that the control point is changed, but the control point line needs to be updated as well. You can see that in both cases there, we're actually constructing a new string to go with the D attribute that takes account of the new values that were typed into the boxes. Let's do that. Let's put all of that in. We're basically creating ourselves a new function. I'll just talk through it as I do it. We're going to be getting the Bezier curve, document.getElementByID, and we're going to call it Bezier. Above there you can see that CID that was given to that one. Then we've got the second, we'll call this one line left. It's not one, it's a small L line left and that is to get line elephant. That was a name we gave that up above as well. We need two more of these and we need to get the x and y boxes. This will be box1x, this will be box1y. Then what are we getting? What are the names up above for this control 1x, isn't it control 1y? Control 1x, 1y. We've got all the pieces we need. What we've got, we've got all the elements we need, but now we're going to get the value out of each box 1xVal. We're just pulling this out now. Box1X.value and then that box1Yval equal box1Y.value. Great. We've done all the reading. We've got access to all four objects that we're going to work with. We've read out the two values we need from the x and y boxes and we're ready now to update the Bezier curve and that first control point line. Let's do the updating. The Bezier curve, we're going to set the attribute of it. This is us just getting the method or a function that we need. The bit that we're setting is the D attribute and we're going to give that a new string. It's going to be largely the same as it was before, you can see it just straight above. B50, 50 that's moving to the beginning of the line. Then make sure you put enough spaces into this string. I've put a space there. You'll see there's a space. Then I know what I'm going to add on. Now I'm actually changing the control point using the two values from the boxes, but I'm putting another space in there look because we're going to need that between the two values. Then here's the box1Yval that I've just read out of the box1Y. There's a small v. I think I used, wasn't it? Yeah. Got to make sure everything's consistent here. Then once I've done that, I can just add in the rest of the data from above because at the moment we're not controlling the second control points. I'll just leave that as 150, zero. Then the end of the line is 150 50, right? That's everything I need to control, to set that sorry. You can see I've taken a two values out of the box and I've put them into that string. Then we've got the left line. That's the other object I'm updating it's the other path set attribute. I'm not put a round bracket and that's why that hadn't gone colored. Whenever things don't go colorful, when you expect them to, something's up. Set attribute, D, M50. This first control point starts at 50. I think 50 starts the same point as a line does, but we want it to finish. We want it to go to whatever control point I've put in, into the boxes. I've done a capital L to say. I just want a straight line going from the first end of the Bezier curve and that's 50 50 so I've moved to that point, and then I simply have a move to the absolute position provided in the boxes, that were typed into the boxes. If I just put them here, then that should be fine, and I need to add in a space between them. Then one y val, there we go. I think that should be everything we need. First two lines we've accessed the two lines the Bezier curve and the straight line. The next two lines we've accessed the boxes and then we've read the values out in the next two and then we're doing the updates. That looks correct. Let's just try running that. We can't run it yet, because we've written a function, but there's nothing connecting the code above to this function. We've got this name update here, but there's no name update anywhere up here, so we have to somehow connect these two together. Let's just look at that part. We've got all the code setup ready. Now I need to call back functions and these are using a slightly different. Remember we've seen on-click before. The appropriate attribute here is on change. If we call on-change, and then every time we type Enter when we're user, when a program is running, when we type Enter into one of those boxes, then we'll see this change. The change event will get code. Let's put those in, so they're going into these input here. Make sure I put it inside this time on-change equals update. We need to again find there's a lot of repetitive and similar typing goes on with all of this, scenario does again. Now, you see done the same thing I've done before. Put it in the wrong place. It goes inside the angle bracket, otherwise it doesn't get colored. It wouldn't be syntactically correct. Now we have connected up the HTML through to the JavaScript. Let's see if that works now. I've run it. We've got control 50 across. Let's make that now a 100 across, and see what happens. There we go. Well, somethings work correctly in that the control point line has gone correctly, but the Bezier curve has not. I've just made a mistake with that Bezier curve. Let's just have a quick look. Taking a look back at the code we've written here. Here's the Bezier curve line, this one here, BC.set attribute. Got D, we've got the M50 50, and then can you see we're going in and putting the rest of the Bezier curve, and can you see where the problem is? If you look above, can you see how the Bezier curve is specified? When you look here, what you might spot is, we haven't actually got quite the right syntax for a Bezier curve because we've not gotten a capital C. We've actually updated it with slightly the wrong string because it didn't have the curve string. In fact, you could see how it was working. We had in 50, 50. It moved to that starting position. But then it was a bit uncertain what to do and now this thing gave it the n position. I suspect it drew the black line underneath that red line, but then of course, I then drew a red line straight over it and so it just didn't quite work. Well, let's run that again. Here we are. Let's try changing it to a 100 again. That's better. Look at that. Now I can change this one down here. Maybe control1y. Let's put that right down below. Let's make that 150. You can see, you can just mess around as you wish. Now, we're only able to control that left control point line at the moment, but you could put whatever you want in here. As we go, let's make that 0,0. That's just an easy way of just messing around and seeing how that works. That was one example there on the slide. It's a bit tedious to type those numbers in. It'd be nicer if we had something that was a little bit more direct manipulation. Perhaps, we could change what we've got for a slider instead of typing in those boxes. Let's see if we can put a slider in there to make that a bit easier to use. A slider is just a different kind of input element. You can see here, we specify using the type attribute. By default, the type is text. That means a text box. But here, we're going to have a range. Range is the word that gets used for slider. You can see, we again have value. We can still put an initial value in as well as a minimum and maximum value that the slider represents. If the slider is at the minimum point, the value is going to be naught, if the slider is at the maximum point of the slider, the value is going to be 200. Let's just add that in. This is just telling us. Let's put this in. We'll do this just for the x value to start with. Let's put it inside the paragraph marker. We'll just have it on a line coming straight after so input and then the type is going to be range. Didn't need to worry with the type before because we were just using the default. The id is going to be control point 1 for x, and then it's r because it's a range. That's my naming there. The initial value is going to be 50. The minimum possible value of this slider is naught and the max value is 200. Well, that's straightforward enough. Just need to close that, like that. Let's run that. See, we get a slider, it's operating, I can move that around. It's me just dragging it about. Nothing happens because again, we haven't put any kind of event handler on there. Let's just look at that for a second. We need to have an event handle, so we need to create one of those. Let's go ahead and do that. We need to create something that will actually read the value out of the slider. We can do that much as we've been doing the other pieces. What we've added is a function, r1x. What we do is we get the value out of the range object here. You can see, I've just done this in one line this time, document.getElementById c1xr. Now I've got the range object and then I've just added dot value on the end. That's effectively saying, well look, I've got a document. Now, I've got the current value of the range object. Then what I'm doing is, I'm basically setting the value. Text box. What I'm going to do is I'm going to get the value of the slider, I'm going to put that value into the text box, and then I'm going to call a normal update function we had before to make sure everything gets redrawn so just keeps it simple. You can see I can do that updating of the text box simply by getting the text box. Remember it was called CTRL1X. Then I can just go dot value and just like our variable update, I can just update it to be the value I just picked out. Let's just go and type that in. Here we go. We're putting a new function into a JavaScript function. R1X range for 1X that's the naming I'm using for that, and just let R1X file. This is quite a long line, we're going to get a document. We're going to get the range element ,C1XR is name of the range element. Total range, the range element. What I'm going to do is I'm going to get the value out of that. That's me got the value. Then I'm going to update the text box, so document get element by ID type by quite a bit. This is CTRL1X. Then we're going to get the value out of that. Sorry, we're not getting the value we're updating the value in it, because this is like an assignment statement and I'm doing R1X file like that. R1X file and that's the value I just got out of the slider having got loose too old and just call the update function. Now that the text box has been updated to wherever the slider is moved to, then it should all work smoothly. Fingers crossed. Let's run that again, and let's have a look. As I now change this course, nothing's going to happen just yet. Have immediately you say, look I can move this whole I like and still nothing is happening. That is because why is it? Any ideas? I've not actually put in a connection up here in the HTML. I've not put a connection up there to make sure that this new function I've written is actually called. This time it's yet another new on thing. It's not on train, just not on click. This one is on input, and that ensures that each tiny movement of the slider is actually picked up. Every time they move at a slightly, just a little bit, then this R1X function is going to get called. That's what's going on up here on input, basically call the R1X function, which is down here in the JavaScript. Then that does it's stuff, and then calls the update function. Let's try that one. See if we've got a yet, on your right. You ready? Fingers crossed. We go to concerns I move that around. We get that nice little movement there and you can see how as I move it around a control 1X box. The text box there is changing its value from naught, which is what we said. It should be all the way up to 200 at that end, and you can see that the thing is being perfectly redrawn as we do that. There's the full code for reference if you want to use it for anything these slides will be attached to the video so you can always pick that code out, and you could copy that into JSFiddle. Just to summarize all of that, we've started to use different input elements which gives us more exciting ways to actually interact with our program. We've just seen being able to type in text or numbers or use a slider as well to do that. We've seen how to interactively respond to the input as it comes in. We've created event handler functions. We've made sure we've connected those event handler functions into the interaction objects in the HTML so as changes happen in those objects, the correct event handlers are called. In the exercises, you'll be able to have some practice with some more of this just to become more comfortable and familiar with it. Best of luck with that.