Calvin (Deutschbein)
3 April 2023
<!DOCTYPE html>
<html>
<body>
<p id="showEle">1</p>
<button onclick="update()">Click me</button>
<script>
let val = 1 ;
const showVar = document.getElementById("showEle") ;
function update()
{
val = 2 * val ;
showVar.innerText = val.toString() ;
}
</script>
</body>
</html>
Consider the following HTML excerpt.
<p id="showEle">1</p>
What type of thing is id
?
Consider the following HTML excerpt.
<button onclick="update()">Click me</button>
What type of thing is update()
?
Consider the following JavaScript excerpt from within the HTML document.
const showVar = document.getElementById("showEle") ;
This line:
Consider the following JavaScript excerpt from within the HTML document.
let val = 1 ;
This line:
Consider the following JavaScript function from within the HTML document.
function update()
{
val = 2 * val ;
showVar.innerText = val.toString() ;
}
Consider the first line function update()
Consider the following JavaScript function from within the HTML document.
function update()
{
val = 2 * val ;
showVar.innerText = val.toString() ;
}
Consider the line val = 2 * val ;
let
val
Consider the following JavaScript function from within the HTML document.
function update()
{
val = 2 * val ;
showVar.innerText = val.toString() ;
}
Consider the excerpt showVar.innerText
Consider the following JavaScript function from within the HTML document.
function update()
{
val = 2 * val ;
showVar.innerText = val.toString() ;
}
Consider the excerpt val.toString()
HTML elements and CSS rules are similarly vertically structured.
HTML is a
CSS is a
Write a .js hello world.
Continue with the <script>
element.
<script>alert('Hello, world!');</script>
As far as I can tell, we are supposed to use events to do IO in .js
button
is clearly an HTML element.onclick
is clearly an HTML attribute, and is the event (for some value of is)."this.innerText=Date()"
is clearly JavaScript, the value of the event.
We don't always just want buttons.
I don't know what we want to do, so I'm going to do my minimal IO example.
We once again use the canvas
HTML element.
<body onload="draw();">
<canvas id="canvas" width="400" height="400"></canvas>
</body>
This is perfect for us, because lacking a better idea, I decided to draw rectangles.
function draw()
{
const plot = document.getElementById("plot") ;
const ctx = plot.getContext("2d");
ctx.fillRect(50, 50, 50, 50) ;
}
Many of us were tricked here - this code does not work well together. Why not?
Let's make a box by finding the center of our canvas and putting a rectangle there.
There we have it!
Now we will start with a centered rectangle.
function draw()
{
const dspl = document.getElementById("display") ;
ctx = dspl.getContext("2d") ;
w = dspl.width ;
h = dspl.height ;
s = w / 8 ;
x = w / 2 - s / 2 ;
y = h / 2 - s / 2 ;
ctx.fillRect(x, y, s, s) ; // x y width height
}
This is a bit goofy because I declared variables globally for Reasons™
End-to-end, this is what we made:
Note at this time I've switched to externally rendered .png files, from internal live canvas elements.
With our lovely lil box, we can now try for some more exciting events.
var x ;
var y ;
var s ;
var ctx ;
var w ;
var h ;
I declared these as variables, and uninitialized, to make them global and have them set during the onload.
We use built-in functions to attach an event listener to the entire HTML document.
document.addEventListener('keydown', keybind);
document
refers to the special HTML element of type document.addEventListener
is a built-in .js function that takes two arguments.'keydown'
is the name of the HTML event for which the listener listens.keybind
is the name of the .js function I will write to capture keystrokes.Keybind is a variable, keydown is a keyword.
I set things up like this.
var x ;
var y ;
var s ;
var ctx ;
var w ;
var h ;
document.addEventListener('keydown', keybind);
function keybind()
{
...
When an event occurs, it generates an event
object in .js.
function keybind()
{
const key = event.key;
For keydown events, this will always be a key of some sort.
function keybind()
{
alert(event.key)
}
I decided to use the arrow keys. You can include wasd as well.
function keybind()
{
const key = event.key; // "ArrowRight", "ArrowLeft", "ArrowUp", or "ArrowDown"
I introduce (?) the switch statement.
switch (event.key)
{
case "ArrowLeft":
case "a":
x = x - s ;
break ;
...
}
This updates the global x
value to be less when the left arrow key is pressed.
Switches are commonly used in IO programming, which is okay I guess.
switch (event.key) {
case "ArrowLeft":
case "a":
x = x - s ; // this runs for a or left
break ; // this exits the switch
case "ArrowRight":
case "d":
x = x + s ; // this runs for d or right - but not a or left
break ;
Be careful!
switch (event.key) {
case "ArrowLeft":
case "a":
x = x - s ; // this runs for a or left
case "ArrowRight":
case "d":
x = x + s ; // this runs for d or right or a or left
break ;
Be careful!
switch (event.key) {
case "ArrowLeft":
case "a":
x = x - s ; // this runs for a or left
return ;
case "ArrowRight":
case "d":
x = x + s ; // this runs for d or right or a or left
return ;
}
alert(event.key) ; // this doesn't fire for arrows
Be efficient! This would be bad.
switch (event.key) {
case "ArrowLeft":
x = x - s ; // this runs for a or left
return ;
case "a":
x = x - s ; // this runs for a or left
return ;
}
Well... we can compute new x (or y) values with switch... but what good is that.
function keybind()
{
// old x value here
switch (event.key) {
// well written switch
}
// new x value here
}
This doesn't exactly doing IO - it does the I, but there's no changes to the canvas!
We need to draw rectangles - just like in the onload function!
function keybind()
{
switch (event.key) {
// well written switch
}
ctx.fillRect(x, y, s, s) ; // x y width height
}
This adds a new rectangle to the canvas!
We use another built in function to clear the old rectangle.
function keybind()
{
ctx.clearRect(0, 0, w, h);
switch (event.key) {
// well written switch
}
ctx.fillRect(x, y, s, s) ; // x y width height
}
In effect, this moves the rectangle.
But wait - we have a problem with bounds checking.
switch (event.key) {
case "ArrowLeft":
x = x - s ; // this runs for a or left
return ;
case "a":
x = x - s ; // this runs for a or left
return ;
}
What happens when the box is moved off of the canvas space?
We could write extensive if statements.
switch (event.key) {
case "ArrowLeft":
if (x - s > 0)
{
x = x - s ;
}
break ;
case "ArrowRight":
if (x + s < w)
{
x = x + s ;
}
break ;
}
Imagine how bad that looks without switch.
if (event.key == "ArrowLeft")
{
if (x - s > 0)
{
x = x - s ;
}
} else if (event.key == "ArrowRight") {
if (x + s < w)
{
x = x + s ;
}
}
Though of course there's some case combinations we can do
if ((event.key == "ArrowLeft") && (x - s > 0))
x = x - s ;
} else if ((event.key == "ArrowRight") && (x + s < w))
x = x + s ;
}
This could be an argument against switch, that said.
We can inline conditions with the "trenary operator".
switch (event.key) {
case "ArrowLeft":
case "a":
x = x - s > 0 - s ? x - s : x ;
break ;
Basically, it is
const bool = x - s > 0 ;
const someVal = x - s ;
const otherVal = x ;
x = bool ? someVal : otherVal ;
This is the same as an if statement in this simple assignment case.
Homework for Monday