Hi! In this first example, I'm going to show you how we can use the new html5 elements for designing a graphic user interface, client side, that we will use for directly change some parameters of this very small Web application.
So as you can see, it's just a bouncing rectangle that goes from left to right and the code is here.
It's a very short piece of code, that uses exactly what you learned the last week.
So, we've got a canvas... a small canvas here, we've got an init() function that is called when the page is loaded...
The init() function is here, we get the canvas, we get the context, we set some variables... global variables... we store the width and height of the canvas.
We are setting the fillStyle, so the color of the rectangle, using a variable called currentColor that is yellow.
And finally we call an animation loop that will make the animation.
The animation loop is here and follows exactly what has been shown the previous week: first, clear the area where the shapes will be drawn, secondly draw some shapes - here we are drawing two rectangles - one filled with the currentColor that is yellow, the other one is a wireframe rectangle of the same size.
So, we are using a variable for the size, here.
This variable is 20 pixels width and 20 pixels height.
And then we move the shape by adding an increment to its X position.
We are using the incX variable for that, that has a value of 3 pixels, so at each frame, sixty times per second, the square will move 3 pixels to the right or 3 pixels to the left.
And we added a small test here, for detecting if it hits the left side or the right side.
In that case we just change the sign of the increment: instead of going 3 pixels to the right, it will go 3 pixels to the left.
So now, I'm going to show you how we can add some controls, some widgets for controlling the speed, the color or the size of the small square.
I will use for that an input type=range.
This is an addition from HTML5 and you can see that it looks like a slider.
By just sliding this small circle here, I will change the size of the rectangle.
So, I'm using an input type=range and I give a minimum value of 2 pixels for the rectangle, maximum value of 40 pixels for the rectangle, and the default value equal to the current size that is 10 pixels.
Hmmm… 10 or 20?
I don't know... 20 pixels! Ok.
A good practice is to always add a label to any input element.
And to associate the label with the input element - and this is also a good practice for accessibility - we use the ‘for’ attribute and give it the same value of the id attribute of the input field.
So here, I called the id "size" and the label is "size".
Inside the label, I just type the string that appears here... and if I click on the label, and use the arrow keys, you can see that the input element instantly got the focus.
I will also use, together with the input type=range element, an output element.
This is also a nice addition from HTML5.
It's useful for giving some visual feedback of an input element.
I just typed "output", I give it an id that will be useful later on when we will process the event using JavaScript, when the slider moves.
And I give to the output the default value, that is 20, like that.
Now, I'm going to add an event handler to the input type=range element.
I will use the simplest way to do that.
Maybe some people think it's not the best way, but really, for simple examples it's ok.
So, I will add an ‘oninput’ attribute here, and I give it, as a value, the name of the function - not the name! - I will call the function called changeSize().
I add an event to the declaration - to the call of the function, and here I write this input callback function.
‘changesize’… like that.
I can check if I properly declared the event handler, by adding console.log("size changed").
And I can check that this is ok... yes, ok, my event is processed.
So, how can I get the value? I can use this: size - this is the name of the variable we are using - = event.target - this is a handle to the element that fired the event - dot value.
Ok. Like this, it doesn't.... ah it works.
So, like this it works.
If I change the value I can see that the... something is changing here but... there is a small problem: it broke the animation.
Just because the event value... here... if I print the value... I can see it breaks somewhere... the value is printed as a string, with double quotes... and it breaks somewhere here because the value must be an integer.
So I'm using ‘parseInt’ that is a common function in JavaScript for changing string values to integer values.
And here I've got my controller.
I've got my small widget I can use.
In order to update here the output element with the current value, I can add this: document.getELementById... I give it the id of the output element that is "sizeValue", and in order to change what is displayed in the element I use the ‘innerHTML’ property, and I give it the size value, like this.
Now, I've got here a visual feedback of the current value of the slider, and I can see that my rectangle, my small square is changing its size.
Using exactly the same technique, I can add an input element for changing the color.
I'm just copying and pasting this, and instead of calling it "size", I will call it "color", the label, id=color, type=color, this changeColor, colorValue... no need for an output.
And here, you can see that I've just added a new input type=color element that is interesting because natively it will pop a color chooser.
And I don't need an output element because the widget itself here, that is displayed when you add an input type=color, has a visual feedback integrated.
So what I can do is just link it to a changeColor JavaScript function, that will be called when the value of the input field changes.
I'm just using the same approach... changeColor, color, color=... so this is not an integer value: no need to convert... I can add some trace using console.log.
I dont need that... and instead of changing the color and putting the value in a variable, I'm using context.fillStyle that is the current color.
And let's try it.
Okay.
If I change the color, you can see that the color of the small square is changing now.
By default, if I run it again, the default value is not the correct one.
It’s black.
So, I can add a value here, for the default value.... value=… and I think I cannot use "yellow" because we need to specify an hexadecimal value here.
So... as I don't know the exact hexadecimal value for "yellow », I will just use "red", and give it a default value of "red" to my rectangle.
Like this: it matches, and if I change the value, you can see the result.
I can also change the line width, that"s be very quick... the line width of the outline, here... I'm just going to copy and paste the first part, that was about changing the size of the rectangle.
And if I just use this for lineWidth, just copying and pasting the same thing... lineWidth, lineWidth, lineWidth... the line with will be from one pixel width to maybe five...current value is one... changeLineWidth, and lineWidthValue for the id of the output element.
ChangeLineWidth()... I'm going to copy this one...change...line... context.lineWidth= (typing...) lineWidthValue... (typing) and normally it should change the value of the outline width of the rectangle.
There is a small bug here... with the output element... lineWidthValue... like this it works, and I can change the value of the line width.
So, I'm going to stop here for this first example.
I think you understood the principles.
Of course, you can use CSS for better... for having a better layout, maybe add some styling, to the controllers and so on...
Hi! Okay... ready for a second video that shows how to add some controllers to a Web app.
So this is a more complicated example.
I'm not going to live code.
It's just a chart drawn in a canvas.
And you've got the canvas declared in the HTML and some JavaScript here that will row as chart bars the different values from this array here.
And you can add any value you like.
It’s all dynamic so.. you can add values and both the coordinates here with the small ticks adjust.
Also the scale of the graphics will be adjusted too.
So how can I change the values using sliders just in order to have something more dynamic? Well, the trick consists in adding here a container that will be a list with an id "sliders", like that... an empty list in which we are going programmatically, from JavaScript, to add here some inputs elements and also associate some event listeners that will update the values of this array, and call the function that draws the chart again.
This is done in the second example, you got the source code and details available in the text of the web page below.
Here is the new version.
So first, I'm going to show you the results so we can have now a very interactive chart like this where you can just move the sliders and you can see the updated values.
And it's all dynamic because if I add some values, or change the values from the array here, you can see that the number of controllers adjust by itself.
So, if I got another value here, I will have another controller here... like you see... So... how is it done? It just uses the DOM API for creating dynamically the input type=range elements here and the labels here and they are all inside a list item element.
So let's see how this can be done...
In the init() function here, we are using really basic functions from the DOM API.
I mean: once we got the handle to the canvas and the context we get the handle to the empty list we added here. id="slider"... getElementById'("slider").
So we got an empty list that is pointed by this variable here.
Then we create empty elements, and we create as many elements as we have elements in the array we want to draw.
So this is the ‘for’ loop here that does thats.
So... for the number of elements in a the "values" array here, we will create an empty list item. createElement('li') is the same as if we typed <li> somewhere in the HTML...
So we also create an empty label that will be on the left here, and we will also create an empty input element.
So we've got the empty input, the empty list item and the empty label.
And then, we try programmatically to set the default attributes.
The label will have a "for" attribute that will match the "id" attribute of the input type=range.
So here we set the value of the "for" attribute with id1, id0, id1, id2, id3, etc.
You can check here with that inspector that each id of the labels is equal to id0 or... id1 for the second one, etc.
We set the text content with a string "value0", "value1"... ...this text here.
And then we add this label that is now completely filled with the attributes we wanted.
We add it as a child of the list item.
So, the list item is not yet added in the document.
It's still here, somewhere created but not attached to any parent... and then not visible in the page.
So now we are trying to... starting to set the different attributes of the input elements.
The type of the element is input type=range, its id is "id" followed by the current index of the elements.
Like this, the id of the input element will match the ‘for’ attribute of the label element.
id + "i"... we'll have a value of "id0", "id1" and so on...
We also set the max attribute because here, we can only move from 0 to the max value that his, in our case, the value of the biggest element.
Here, it's 100.
And also the current value of the slider here is equal to the current value of the element.
The third slider here has the same value as the... ... this element here.
So we get values [i] that will correspond to 14 in this case.
Then, we'll also add an input listener.
It's the function called changeValue and we passed it a parameter equal to the index of the current element.
This function is here and we will look at it a bit later.
Finally, we add the input element to the list item.
You remember that we added to the list item the label...
Now we are adding the input... and finally, we are adding the list item to our empty list.
The list here was the list that had the id "sliders ».
It's the list that we declared here.
So this is all we can add programmatically and dynamically: elements in the HTML.
If I use the inspector once again, I can see that here, I've got the empty list - that is no more empty... it's called "sliders", it contains the list items that have two children: a label whose ‘for’ attribute matches... the second child is an input type=range with the same id.
It's important for accessibility to have the "for" attribute that matches the id attributes like this... as controls are usable using only a keyboard.
I can use the "tab" for traversal, and if I click on the label, I can use the keyboard for changing the values.
Let's give rapidly a look at changeValue(event)... the changeValue gets the current index of the slider.
So we just get the current slider value like this: getElementById, followed by the index id1 is the id used by this slider. ".value" gives the current value...
So once we got the value, we just change the value in the array.
Here ‘value’ is the array that contains the different... integer values we want to draw... so by just setting these values... of index with parseInt(value), we change that...
Once we changed the value, let's redraw the whole histogram: we clear the surface of the canvas, and call makeHistogram().
You can give it a look later... that will just make these drawings here.
I wanted to show you an example and you can study the source code...
All the examples are on JS Bin.
And finally, the last version is the one that draws three different canvases... and the code here for generating the widgets is exactly the same... and here its fun because you can change the value of the three histograms dynamically.
The only thing that changed is that, in the event listener function, instead of just calling makeHistogram() we call functions for drawing the other sort of histograms, the two other ones here...
Input elements, in particular the elements introduced by HTML5, can be used as widgets to control the behavior of a Web application. In this situation, they do not need to be inside a <form> element. We just bind event listeners to them, and we use them as client-side widgets.
GUI: Graphical User Interface
Bouncing rectangle with GUI (see screenshot at the top right of this page)
Simple chart with a GUI (see screenshot on the right)
Final version with different types of charts and a GUI (see screenshot below)