Difference between revisions of "Introduction to JavaScript Fall 2009 Class 4"

esse quam videri
Jump to: navigation, search
m
(Undo revision 17725 by Matthew.ephraim (Talk))
 
Line 1: Line 1:
 +
[[Introduction_to_JavaScript_Fall_2009|Back to Introduction to JavaScript Fall 2009]]
 +
 
== Introduction ==
 
== Introduction ==
  
Last week, I showed you how you can wrap chunks of JavaScript code up into functions that can be reused
+
This week I will talk about using some of the concepts I've shown you the last few weeks to actually
throughout your page. This week, I will explain JavaScript events and show you how you can tie JavaScript
+
start putting together a web page that uses JavaScript. I want to make sure that everyone understands
functions to different user events that happen on your page.
+
the concepts I've presented so far are making sense to everyone, so the majority of the class will
 +
be dedicated to building a simple game that tests your knowledge. ''This game will be your assignment for the week,
 +
but hopefully you will be able to finish it during class time.''
  
I will also show you how you can change an element's HTML and even change an element's styles.
+
Before starting the game, there are a few coding style issues that I'd like to cover.  
  
 
== Coding Style ==
 
== Coding Style ==
  
One thing that I haven't talked about yet is coding style. Like the English language, JavaScript has it's own
+
One thing that I haven't talked about is coding style. Like the English language, JavaScript has it's own  
 
styles that you should follow if you want to make your code readable for others (and, of course, for yourself).
 
styles that you should follow if you want to make your code readable for others (and, of course, for yourself).
  
 
The [https://developer.mozilla.org/en/docs/Javascript_Style_Guide Mozilla JavaScript Style Guide] is a comprehensive
 
The [https://developer.mozilla.org/en/docs/Javascript_Style_Guide Mozilla JavaScript Style Guide] is a comprehensive
 
list of rules that you should try to follow when writing JavaScript. Some of the rules are more important than others,
 
list of rules that you should try to follow when writing JavaScript. Some of the rules are more important than others,
and many of them might not make sense yet for a beginner class. I've listed a few of the rules that apply for this
+
and many of them might not make sense yet for a beginner class. I've listed a few of the rules that apply for this  
 
class so far.
 
class so far.
  
Line 33: Line 37:
 
This name is better because '''name''' tells you what the variable is being used for.
 
This name is better because '''name''' tells you what the variable is being used for.
  
'''Multiple Word Names'''
+
'''Multiple Word Names'''  
  
 
When your variable or function names have multiple words in them, it's JavaScript style to use '''camel case (aka camelCase)'''
 
When your variable or function names have multiple words in them, it's JavaScript style to use '''camel case (aka camelCase)'''
Line 54: Line 58:
  
 
Another important coding style is using proper indentation in your code. Just like indenting the first sentence of a paragraph
 
Another important coding style is using proper indentation in your code. Just like indenting the first sentence of a paragraph
can make text easier to read, indenting your code properly can make it easier to read as well. Typically, when you switch
+
can make text easier to read, indenting your code properly can make it easier to read as well. Typically, when you switch  
to a new ''block'' of code, you should indent 2 spaces.
+
to a new ''block'' of code, you should indent 2 spaces.  
  
 
Remember that, in JavaScript, bocks are sections of code that are surrounded by { curly brackets }. So, every time you're using
 
Remember that, in JavaScript, bocks are sections of code that are surrounded by { curly brackets }. So, every time you're using
 
an opening curly bracket, you should indent 2 spaces. The code example below doesn't use any indentation:
 
an opening curly bracket, you should indent 2 spaces. The code example below doesn't use any indentation:
 
    
 
    
   function alertMatt() {
+
   function alertMatt()
   if (name === "Matt") {
+
  {
 +
   if (name === "Matt")
 +
  {
 
   alert('hello Matt');
 
   alert('hello Matt');
   } else {
+
   }
   alert('You're not Matt!');
+
  else
 +
  {
 +
   alert('You're not Matt!');  
 
   }
 
   }
 
   }
 
   }
Line 70: Line 78:
 
Is this code easy to read? How about if it was indented:
 
Is this code easy to read? How about if it was indented:
  
   function alertMatt() {
+
   function alertMatt()
    if (name === "Matt") {
+
  {
      alert('hello Matt');
+
      if (name === "Matt")
    } else {
+
      {
      alert('You're not Matt!');
+
          alert('hello Matt');
    }
+
      }
 +
      else
 +
      {
 +
          alert('You're not Matt!');  
 +
      }
 
   }
 
   }
  
Line 82: Line 94:
 
a feature that help you properly indent your code.
 
a feature that help you properly indent your code.
  
== Coding Style Links ==
+
== Links ==
  
 
* [https://developer.mozilla.org/en/docs/Javascript_Style_Guide Mozilla JavaScript Style Guide]  
 
* [https://developer.mozilla.org/en/docs/Javascript_Style_Guide Mozilla JavaScript Style Guide]  
 
* [http://www.chromeexperiments.com/ Chrome Experiments]
 
* [http://www.chromeexperiments.com/ Chrome Experiments]
  
== Finding Elements ==
+
== Activity ==
  
Before we can start capturing events and writing our own code to handle those events, we need to be able to find
+
Today, we will be creating a simple number guessing game. The computer will pick a random number and the user will try to guess
the elements that we want to attach event handlers to. Let's say you have a ''div'' on the page and you give it an
+
what the number is. If the user guesses too low, the computer will tell them that the number is higher. If the user guesses
id of '''clickableDiv''':
+
too high, the computer will tell them that the number is lower. And if the user guesses the number correctly, the computer
 +
will tell them that they have won.
  
  <div id="clickableDiv"></div>
+
=== Step 1 ===
  
If you wanted to find the div and store it in a variable, you would use the '''document.getElementById''' function:
+
'''get the template'''
  
  var clickableDiv = document.getElementById('clickableDiv');
+
First, download the [http://mattephraim.com/intro_to_javascript/class_4/game.zip template for the game].
 +
I have already created a game board for you. The board has a few elements on it and is styled using CSS.
 +
Open up ''game.html'' and look at the html. There is a form with an ''input'' box for the number that the user will guess.
 +
There is also a ''button'' that the user can click to send their guess to the computer. Finally, there is a ''div'' at
 +
the bottom where messages from the computer will be displayed.
  
If the div was found, the function returns the element. Later on, you can use the '''clickableDiv''' variable to
+
Notice that 3 of the elements have the '''id''' attribute filled out. We are going to use those ids in our JavaScript.
attach events to the element.
 
  
== Events ==
+
=== Step 2 ===
  
In JavaScript, events are ''raised'' when a user takes some action on the page. For example, a user clicking on
+
'''test the setupGame function'''
link would ''raise'' the '''onclick''' event on the element that the user clicked on. Without JavaScript, the user
 
interacts with the page and the browser handles any events that the user might raise. Many times, the browser's
 
way of handling the events is just fine. Other times, there may be more interesting things that we can do with
 
JavaScript by capturing the events and handling them in a different way than the browser would handle the events.
 
  
What kind of ''actions'' from the user are considered events though? It depends on the browser, but, for the most part
+
Open the file called '''behavior.js''' that's in the JavaScript folder. This is the file that contain the program for our
there is a core set of events that the majority of browsers will support. So, for example, a user might click on an element
+
game. Notice that I have already created several functions in the file for you. For now, you can ignore the 2 functions
on the page. If the element is a ''button'', the browser will submit a form. If the element is an ''anchor'',
+
at the bottom of the page. We will be using these functions later on to make the game work.
the browser will go to the page that the anchor links to. Or maybe the user just clicked on a ''div'' element.
 
In that case, the browser probably wouldn't do anything. Not unless we add some JavaScript.
 
  
=== Setting Events ===
+
The 2 things that I want you to notice are the empty function called '''setupGame''' and the link that says:
  
So, let's take the div from above:
+
  window.onload = setupGame;
 
    var clickableDiv = document.getElementById('clickableDiv');
 
  
We now have the div stored in a variable called '''clickableDiv'''. Let's say we wanted to have a function that handled
+
This line is important. '''window''' is a variable for the browser window and '''onload''' lets you set a function that will run
the event that was raised when the user clicked on '''clickableDiv'''. First, we should create a function that will be used
+
when the browser window loads. So, what this line of code is saying is "call the function '''setupGame''' when the browser
to handle the event. Let's call it '''handleClick'''.
+
window loads". In other words, '''setupGame''' is the name of a function that should run as soon as the page loads.
  
   function handleClick() {
+
Right now '''setupGame''' isn't actually doing anything, because it's empty. Modify the function so that it looks like this
       console.log('hello');
+
 
 +
   function setupGame()
 +
  {
 +
       alert('this is a test');
 
   }
 
   }
  
The function will write message that says "hello" to the Firebug console when it is called. Let's make it so that the function is
+
The line we added will simply pop up a test message when the page loads. Reload '''game.html''' page to make sure it works.
called when the user clicks on '''clickableDiv'''. To do this, we'll need to use the '''clickableDiv''' variable that we
+
If everything is working you'll see a message popup when you reload the page.
the element by adding a '''dot (.)''' after the variable name and then the name of the attribute. In this case, we
 
want to modify the '''onclick''' attribute of the element, and set it to the name of the new function that we created:
 
  
  clickableDiv.onclick = handleClick;
+
=== Step 3 ===
  
Notice that we used the clickableDiv variable and we added '''.onclick''' after it and then set it equal to handleClick.
+
'''setup the random number'''
Attributes of elements work like variables, we can set them with the equals sign and even use them for comparisons later on.
 
  
=== Other Events ===
+
Also notice that the '''behavior.js''' has a variable called '''randomNumber''' declared at the top. Unfortunately, it
 +
doesn't help us at all, because it's not set to anything yet. Woudn't it would helpful if our '''setupGame''' function
 +
set that variable to a random number? I have created a function called '''getRandomNumber''' that returns a random number.
 +
Call the function and set the return value equal to the '''randomNumber''' variable.
 +
<!--
 +
  function setupGame()
 +
  {
 +
      randomNumber = getRandomNumber();
 +
  }
  
We already set the '''onclick''' event, but there are other events that we could have set as well. For example, if we wanted to
+
All you need to do is call '''getRandomNumber''' by using the function name with parentheses after it and store the return
call a function when the user pressed their mouse button down we could add a handler for the '''onmousedown''' function.
+
value in the '''randomNumber''' variable.
When the user released the mouse button, we could capture the '''onmouseup''' function:
+
-->
  
  clickableDiv.onmousedown = handleMouseDown;
+
=== Step 4 ===
  clickableDiv.onmouseup = handleMouseUp;
 
  
Or maybe we want to capture the event that happens when the user moves their mouse over an element ('''onmouseover''') or maybe
+
'''create a guess function'''
when a user doubleclicks ('''ondblclick''') their mouse:
 
  
  clickableDiv.onmouseover = handleMouseOver;
+
Earlier, I said we would be using the ids on the html elements in our JavaScript. In this step we will be finding the button
  clickableDiv.ondblclick = handleDoubleClick;
+
on the page using JavaScript and then setting the button up so that when it's clicked on, it will call a function.  
  
There are some events that apply to all elements on the page and other events (like '''onchange''') that apply specifically to
+
First, create a function called '''guess'''. This will be the function that we'll use to take a guess at what the number is.
HTML form elements. For a comprehensive list of events and which browsers support each of them, see
+
We want this function to get called the user clicks the guess button. For now, put in another test alert, so that we can  
[http://www.quirksmode.org/dom/events/index.html here].
+
test to make sure the function is getting called when we click the button.  
 
+
<!--
=== the window.onload Event ===
+
  function guess()
 
+
  {
One issue that you will run into when attaching events with JavaScript is that the code to attach your events often runs before
+
      alert('test');
the whole page has actually loaded. This can happen if you include your JavaScript in the ''head'' tag of your page. The browser
 
will load the JavaScript as soon as it encounters your ''script'' tag, but the rest of the page stil needs to load before you can
 
start attaching events to elements.
 
 
 
A common solution to this problem is to attach an event to the window's '''onload''' event. Every page has a '''window''' object
 
that represents the current browser window. When the page loads, the browser will raise the window's '''onload''' event, which you
 
can attach a handler function to.
 
 
 
So, let's say you want to run a function called '''setup''' when the page loads. You can attach the '''setup''' function to onload
 
event like this:
 
  
  function '''setup'''() {
+
      return false;
    // do some setup stuff
 
 
   }
 
   }
 
+
-->
  '''window.onload''' = '''setup''';
 
  
Any JavaScript that gets called in the setup function will be called after the page has loaded. So, you should have access to all
+
'''make the guess button work'''
of the elements on the page.
 
  
=== this Keyword ===
+
Now, we can find the guess button and make it so that when you click on the guess button the guess function gets called.
 +
JavaScript has a function called '''document.getElementById()'''. You use this function to find html elements on the page using
 +
the id that you gave them. For example, this is how you would find the guess button and store it in a variable:
  
There is a special keyword in JavaScript that I haven't mentioned yet, and you can start taking advantage of it now that you've
+
  var guessButton = document.getElementById("guess");
starting to use events. JavaScript has a special keyword called '''this''' that behaves in different ways,
 
depending on where you use it. It's often confusing, but when used with events, it's fairly straightforward.
 
Let's say that we used the following code to set an onclick handler for an element:
 
  
  clickableDiv.onclick = handleClick;
+
The '''document.getElementById()''' function takes in one parameter, which is the id of the element you want to find. If you
 
+
look at the html for the project again, you can see that there is only on html tag that has the id '''guess'''. The element
  function handleClick() {
+
with the id of '''guess''' is the one that the call to '''document.getElementById("guess")''' finds.  
    alert(this);
 
  }
 
 
 
The code looks fairly simple: it adds '''handleClick''' as an onclick handler for clickableDiv. '''handleClick''' gets called
 
when the user clicks on the div and the fuction alerts the user. But what does the user see when they get alerted? If you tried
 
to run this code, you would probably see something like the text below when you click on the div:
 
  
  object HTMLDivElement
+
Once the button is found, it gets stored in the variable called '''guessButton'''. We can use the variable to make the button
 +
do something when it's clicked on. To do this, we'll use something called an event handler. We'll talk about event handlers
 +
more in depth in another class. This week I just want to you set the '''onclick''' handler to your guess function, so that when
 +
the button gets clicked, the '''guess''' function gets called.
  
The message you are getting from the browser is telling you that '''this''' is pointing to a div element on the page. But which
+
You've already seen how to find the guessButton. The next code example shows you how to set the onclick handler on the button
div element? It's the same one that clickableDiv points to and the same element that you clicked on. In other words, '''this'''
+
you've found:
is a special keyword that points to the element that has the event handler attached to it.
 
  
The '''this''' keyword can come in handy because it will always give you a reference to the element that raised an event. It's
+
  guessButton.'''onclick''' = guess;
like having a variable that automatically gets created for the element. That way, you don't need to use document.getElementById
 
because '''this''' already gives you a reference to the element.
 
  
== JavaScript Event Links ==
+
The line of code is simply saying: ''when a user clicks '''guessButton''' call the '''guess''' function''. Take the 2 lines
 +
that find the button and set the handler and put them in your setupGame function, so that they look like this together:
  
In addition to the wiki, you may find these links helpful
+
  var guessButton = document.getElementById("guess");
 +
  guessButton.onclick = guess;
  
* [http://www.w3schools.com/js/js_events.asp JavaScript events]
+
You can also remove the test alert in the '''setupGame''' function. We won't need it anymore. If you've done everything
* [http://www.quirksmode.org/js/introevents.html quirksmode introduction to JavaScript events]
+
correctly, you should be able to reload the page and then click on the guess button. When you click on it, you should see an
* [http://www.quirksmode.org/dom/events/index.html event compatibilty tables]
+
alert box that pops up.  
  
== Modifying Elements ==
+
=== Step 5 ===
 
 
Handling events isn't the only thing you can do with elements on your page. Once you've found an element on the page you can
 
modify the element in many different ways. Two of the simplest things you can do to an element is change the HTML inside of
 
an element and change the styles applied to an element.
 
 
 
=== Changing the HTML ===
 
 
 
Once again, we'll use the clickableDiv variable from above. Let's say that we wanted to change the content inside of clickableDiv
 
to say "hello" when the div was clicked on. To do this, we would need to change the '''innerHTML''' of clickableDiv. Nearly all
 
elements have an '''innerHTML''' attribute that references the HTML inside of the element. We can use '''innerHTML''' to see
 
the content inside of the element or we can set '''innerHTML''' to a new value to change the content inside of the element to
 
something new.
 
 
 
We can create a new handler that uses the '''innerHTML''' attribute of clickableDiv to modify the content:
 
 
 
  clickableDiv.onclick = handleClick;
 
 
 
  function handleClick() {
 
    clickableDiv.innerHTML = "hello";
 
  }
 
 
 
Setting the innerHTML attribute of clickableDiv changes the content to say "hello". Notice that we used the '''clickableDiv'''
 
variable to make these changes. There's another way that we could get access to the element that clickableDiv is pointing to.
 
Remember the '''this''' keyword from above? This version of the '''handleClick''' will do the same thing as the one above,
 
but it uses the '''this''' to reference the element instead:
 
 
 
  clickableDiv.onclick = handleClick;
 
 
 
  function handleClick() {
 
    this.innerHTML = "hello";
 
  }
 
 
 
Whenever possible, use '''this''' to reference the element that raised the event from the user.
 
 
 
=== Changing the Styles ===
 
 
 
'''Changing Styles Directly'''
 
 
 
An element's HTML isn't the only thing that you can change with JavaScript. You can also change an element's styles as well.
 
For example, we might want '''clickableDiv''' to have a green border when a user puts their mouse over the div. We might also
 
want any text inside of it to turn green. We could add a '''onmouseover''' handler that captures the event when a user puts
 
their mouse over an element. The handler could use the the element's '''style''' attribute to gain access to the element's
 
css styles and then modify the element's border and font color:
 
 
 
  clickableDiv.onmouseover = handleOver;
 
 
 
  function handlerOver() {
 
        this.style.border = "1px solid green";
 
        this.style.color = "green";
 
  }
 
 
 
Every element has a collection of styles that are stored under the style attribute. Most of these styles have the same name
 
as their matching css styles. So, any style that you could set with CSS you can also set with JavaScript by using the
 
'''style''' attribute. When you modify an element's style, the browser will immediately display your changes.
 
 
 
'''Changing the Class Name'''
 
 
 
Above, we changed 2 styles on the element. More complex actions might involve a lot more typing and possible a lot more
 
repetition. How might we have handled the styles above by using CSS? We probably would have created a class that wrapped
 
up all of the styles:
 
 
 
    .highlighted {
 
        border: 1px solid green;
 
        color: green;
 
    }
 
 
 
The stylesheet is where styles belong, so it makes the most sense to put the styles there. Once we have the styles, we can
 
take advantage of them in our JavaScript. Just like every element has style attribute with a collection of styles stored under
 
it, every HTML element has a '''className''' attribute that can be set by JavaScript. So, instead of setting the CSS styles
 
manually, the onmouseover handler from above can use '''className''' attribute to set a new class on the element:
 
 
 
  function handlerOver() {
 
        this.className = "highlighted";
 
  }
 
 
 
Changing the style of the element in this way keeps the styles for the page separated from the behavior and keeps your JavaScript
 
much more compact.
 
  
== Activity ==
+
'''find the message area'''
  
In this activity we will create a 3 number combination lock. We will use a variable to store the combination that opens the lock.  
+
For the next step, you want to make it so the guess function updates the message area when the button is clicked. For now,
We will then use HTML, CSS and JavaScript to build an interface that represents the numbers for the lock and the latch for the
+
we'll just send a test message to the message area. First, remove the any other code you have in the guess function already.
lock.
 
  
A user should be able to enter the combination and open the lock. If the user hasn't entered the combination correctly yet, the  
+
If you look at the HTML for the page, you'll see that the the message area has an id of '''message-area'''. Update the  
lock shouldn't open. Once the lock has been opened, the user should be able to close it again and have the combination numbers
+
guess function so that it finds the element for '''message-area''' and stores it in a variable called '''messageArea'''.
get reset.
 
 
 
=== Step 1 ===
 
 
 
Download the template for the lock [http://www.mattephraim.com/intro_to_javascript_fall_2010/class_4/lock.zip here]. I have already created a simple template for the lock
 
numbers and the lock. Unzip the template and place the whole folder of documents on your desktop.
 
''Make sure that all of the documents are in the same folders that they were in when they were inside of the zip file.''
 
We will start by editing the '''behavior.js''' file inside of the JavaScript folder.
 
 
 
=== Step 2 ===
 
 
 
I've given a function called '''setup''' to start with. The first thing you need to do is add a line of code that will make
 
the function run as soon as the ''page loads''.
 
 
<!--
 
<!--
'''Solution'''
+
    var messageArea = document.getElementById("message-area");
 
 
  window.onload = setup;
 
 
-->
 
-->
  
If you've done it correctly, you should see an alert that says "hi" when you reload the page.
+
'''change the html for the message area'''
  
=== Step 3 ===
+
One you've found the message area and stored it in a variable called '''messageArea''', it's easy to modify the HTML that's
 +
inside of the message area using JavaScript. Every HTML element allows you to modify the HTML by setting '''innerHTML'''
 +
equal to something. For example, this is how you would update the content for '''messageArea''' to say "hello!":
  
Notice that there is a list of variables at the top of file. There are 4 variables that will be used to hold on to the elements
+
  messageArea.innerHTML = "hello!";
on the page. Modify the setup function so that instead of alerting the user it uses the id attribute to find the each of the
 
elements for numbers and the element for the lock. The function should store the elements in the variables that were created
 
at the top of the page.
 
''Make sure that you find the elements inside of the setup function though. The JavaScript won't be able to find the elements until the page has loaded''
 
  
<!--
+
Update the guess function so that it uses the '''messageArea''' variable to change message area html to say
'''solution'''
+
"the guess button was clicked!".
  
  function setup() {
+
If you've done everything correctly, you should see the message area quickly show your message, and then reload the page.  
    box1 = document.getElementById('number1');
+
The page is reloading, because the button you're clicking is automatically causing the form to reload the page. The way
    box2 = document.getElementById('number2');
+
to fix this is to put '''return false;''' at the end of your function. Now, when you click the button, you'll see the message,
    box3 = document.getElementById('number3');
+
but your page won't reload.
    lock = document.getElementById('lock');
 
  }
 
-->
 
=== Step 4 ===
 
 
 
Now that we've found the number elements, we need to find add some functionality so that the numbers do something when a user
 
clicks on them. We will eventually make the numbers change when the user clicks on them, but, first, let's just make a function
 
that handles the clicks and tie the function to the elements.
 
 
 
Call the function '''changeNumber''' because it will eventually change the number inside of the box. Then use the '''onclick'''
 
event handler to tie the function to each of the 3 box elements. Remember that setting '''onclick''' equal to a function
 
will make it so that the function gets called when the user clicks the element.
 
 
 
You can test to make sure that your '''changeNumber''' function is getting called correctly by putting a call to alert
 
inside of it. If you've set everything correctly you should see an alert when you click on one of the boxes.
 
<!--
 
'''solution'''
 
 
 
  // Sets ups the lock
 
  function setup() {
 
    box1 = document.getElementById('number1');
 
    box1.onclick = changeNumber;
 
 
 
    box2 = document.getElementById('number2');
 
    box2.onclick = changeNumber;
 
 
 
    box3 = document.getElementById('number3');
 
    box3.onclick = changeNumber;
 
  }
 
 
 
  function changeNumber() {
 
    alert('test');
 
  }
 
-->
 
=== Step 5 ===
 
 
 
The next thing we need to do is make the numbers count up when the user clicks on the boxes. The first number in each box
 
is 0. We will need to find this number and add 1 to it.
 
  
First, let's see if we can find the current number. Remember that you can access the HTML of an element by using the '''innerHTML'''
+
If you change the onclick on any elements that will cause the browser to take action, like a button or a link, you need to
attribute of the element. We used the same onclick handler for all of the elements though. How do we know which element
+
'''return false''' from the function that gets called when you click. This will tell the browser that you don't want the  
to find the HTML for when a user's clicks a box? See if you can modify '''changeNumber''' function so that it alerts the
+
browser to follow the link or continue with what the button was supposed to do. Don't worry about why this works for now,
number inside of the box that was clicked.
+
just know that returning false will let you have full control over the event that you're trying to attach a function to.
''Hint: remember how you can use the '''this''' keyword to find the element that raised the event''.
 
 
<!--
 
<!--
'''solution'''
+
   function guess()
   function changeNumber() {
+
  {
    alert(this.innerHTML);
+
      var messageArea = document.getElementById("message-area");
 +
      messageArea.innerHTML = "The guess button was clicked!";
 +
     
 +
      return false;
 
   }
 
   }
 
-->
 
-->
 
=== Step 6 ===
 
=== Step 6 ===
  
Now that you know how to get the number from the box you can change the function so that it adds 1 to the number and resets
+
'''check the user's guess'''
the HTML for the element to the new number.
 
  
The first thing you'll want to do is store the number in a variable called '''currentNumber'''. Then, once you have the number
+
The last thing we need to do is have the game check what the user's guess was. I've already created a function that returns
you can add 1 to it. Do you remember a shorthand we used last week to add 1 to a number?
+
the user's guess for you. It's called '''getUserNumber()''' and when you call it, you get the number that the user entered
 +
in the textbox before they hit the guess button.  
  
Once you've added 1 to the number, you need to set the HTML of the element so that it matches the new number. Use the
+
'''check if the random number is higher than the user's guess'''
'''innerHTML''' attribute again. This time use it to set the value of the new HTML.
 
<!--
 
'''solution'''
 
  
  function changeNumber() {
+
We want to give the user a message that tells them if their guess was lower or higher than the random number. We can use
      var currentNumber = this.innerHTML;
+
the comparison operators from last week to check the user's number versus the random number that the computer picked.  
      currentNumber++;
+
For example, the following code will check if the number they user guess was higher and show them a message:
  
       this.innerHTML = currentNumber;
+
  if (randomNumber > getUserNumber())
 +
  {
 +
       messageArea.innerHTML = "It's higher!";
 
   }
 
   }
-->
+
 
If things are working correctly the number inside of each box should go up by 1 when you click the box.
+
The if statement compares the '''randomNumber''' variable to the value from '''getUserNumber()''' using the greater than operator.
 +
It's asking '''is randomNumber greater than getUserNumber's return value?''' And if the answer to that question is true, it's
 +
setting the HTML for '''messageArea''' to "It's higher!".
  
=== Step 7 ===
+
Right now, the code only checks if the number is higher. You can use another if statement to check if the random number is
 +
lower than the user's number. But, let's use an '''else if''' statement instead, so we can chain a few things together:
  
You'll probably notice one problem with the way the numbers work right now: when you click the numbers, they just keep counting
+
  if (randomNumber > getUserNumber())
up. What we really want is for the boxes to count up to 9 and then go back to zero if the user clicks again.
+
  {
 
+
       messageArea.innerHTML = "It's higher!";
Modify the '''changeNumber''' function so that it checks if the current number is ''less than'' 9 and adds 1 to it if it is.
 
Otherwise, the function should set the number back to 0.
 
<!--
 
'''solution'''
 
 
 
  function changeNumber() {
 
    var currentNumber = this.innerHTML;
 
    if (currentNumber < 9) {
 
      currentNumber++;
 
    }
 
    else {
 
       currentNumber = 0;
 
    }
 
 
 
    this.innerHTML = currentNumber;
 
 
   }
 
   }
-->
+
  else if (randomNumber < getUserNumber())
Now, when you click on the numbers they should count up to 9 and then go back to 0.
+
   {
 
+
      messageArea.innerHTML = "It's lower!";
=== Step 8 ===
 
 
 
The numbers for the combination lock are now working correctly. The next step is to allow user to click the lock image. Add a new
 
function called '''checkLock''' that will eventually be used to check if the lock should open. Go back to the setup function
 
and add an '''onclick''' handler to the lock so that the '''checkLock''' function gets called when user clicks on the lock.
 
 
 
Again, you can check to make sure that you function works by adding an alert to the function.
 
 
 
<!--
 
'''solution'''
 
 
 
  lock = document.getElementById('lock');
 
   lock.onclick = checkLock;
 
 
 
  function checkLock() {
 
    alert('test');
 
 
   }
 
   }
-->
 
=== Step 9 ===
 
  
Now we need to check to make sure the user has correctly entered the combination for the lock and then do something if they have.
+
Now, the code will also check if random number is lower and send the user a message that says "It's lower!" if it is. The code
The user's combination will be made up of the HTML that is currently inside of each of the elements. You can store the HTML for
+
after the '''else if''' will only run if first if statement didn't run.  
all 3 of the box elements in an variable like this:
 
  
  var combination = box1.innerHTML + box2.innerHTML + box3.innerHTML;
+
Finally, we can add an extra '''else''' statement that will tell the user that they guessed the number correctly. What would
 
+
that code look like?
The '''combination''' variable should now be a string equal to the HTML for all 3 box elements. So, if the boxes are all set to 3,
 
'''combination''' will be "333".
 
 
 
Write some code that checks if '''combination''' is equal to the '''COMBINATION''' variable that represents the actual combination
 
for the lock. Alert the user if the combinations are equal to each other.
 
 
<!--
 
<!--
'''solution'''
+
   if (randomNumber > getUserNumber())
 
+
  {
   function checkLock() {
+
      messageArea.innerHTML = "It's higher!";
    var combination = box1.innerHTML + box2.innerHTML + box3.innerHTML;
 
    if (combination === COMBINATION) {
 
      alert('hello');
 
    }
 
 
   }
 
   }
-->
+
   else if (randomNumber < getUserNumber())
=== Step 10 ===
+
  {
 
+
      messageArea.innerHTML = "It's lower!";
Instead of alerting the user when the combination is correct, we want to change the lock image to one that represents an unlocked
 
lock. When you have an image element, you can change the source for the image by modifying the '''src''' attribute. The
 
'''checkLock''' function handles '''onclick''' for the lock image, which means that '''checkLock''' should have access to the
 
lock image through the '''this''' keyword. Use '''this''' to change the '''src''' for the image to "images/unlocked.png" when
 
the user clicks the lock and the combination is correct.
 
<!--
 
'''solution'''
 
   if (combination === COMBINATION) {
 
    this.src = "images/unlocked.png";
 
 
   }
 
   }
-->
+
   else
=== Step 11 ===
+
   {
 
+
      messageArea.innerHTML = "You got it!";
We now have a lock that opens, but there is no way to close the lock once it has been opened. It would be nice if we had the ability
 
to lock the lock again.
 
 
 
One thing that we should keep track of is whether or not the lock has been unlocked. Add variable to the top of the page called
 
'''unlocked''' and make sure the variable is set to '''false''' to start with:
 
 
 
   var unlocked = false;
 
 
 
In the '''checkLock''' function set this new variable equal to true at the same time that you change the lock image. Now we have
 
a way of keeping track of if the lock is still locked or not.
 
 
 
<!--
 
'''solution'''
 
   if (combination === COMBINATION) {
 
    this.src = "images/unlocked.png";
 
    unlocked = true;
 
 
   }
 
   }
 
-->
 
-->
=== Step 12 ===
 
 
Now that we can check if the lock is locked or not, we can close the lock and reset the combination if the user clicks on a lock
 
that has already been opened. To do this, we need to modify the '''checkLock''' function so that it first checks if the lock has
 
already been unclocked. If it's already been unlocked it should alert the user and say "already unlocked!". Otherwise, it should
 
do what it did before and unlock the lock.
 
 
<!--
 
'''solution'''
 
if (unlocked) {
 
unlocked = false;
 
this.src = "images/locked.png";
 
} else if (combination === COMBINATION) {
 
    this.src = "images/unlocked.png";
 
unlocked = true;
 
}
 
-->
 
=== Step 13 ===
 
  
Finally, let's write a function that resets the lock back to locked and sets all the numbers back to 0. Call the new function
+
=== Assignment ===
'''reset'''. This new function should modify the innerHTML for box1, box2, and box3, so that they are all equal to 0 again. It
 
should also modify the '''src''' on the lock element so that it's equal to "images/locked.png" again. And finally, it should
 
set the '''unclocked''' variable back to false again.
 
  
In the '''checkLock''' function you should call the '''reset''' function if the lock has already been unlocked.
+
Your assignment for this week is to complete the activity above and turn it in by Saturday, September 3rd at 10pm.
  
<!--
+
[[Category:Introduction to JavaScript Fall 2009]]
'''solution'''
 
if (unlocked) {
 
    reset(); // a new function you need to define
 
} else if (combination === COMBINATION) {
 
    this.src = "images/unlocked.png";
 
unlocked = true;
 
}
 
 
 
  // Define this function somewhere
 
  function reset() {
 
    unlocked = false;
 
    lock.src = "images/locked.png";
 
    box1.innerHTML = "0";
 
    box2.innerHTML = "0";
 
    box3.innerHTML = "0";
 
  }
 
-->
 

Latest revision as of 22:41, 28 September 2010

Back to Introduction to JavaScript Fall 2009

Introduction

This week I will talk about using some of the concepts I've shown you the last few weeks to actually start putting together a web page that uses JavaScript. I want to make sure that everyone understands the concepts I've presented so far are making sense to everyone, so the majority of the class will be dedicated to building a simple game that tests your knowledge. This game will be your assignment for the week, but hopefully you will be able to finish it during class time.

Before starting the game, there are a few coding style issues that I'd like to cover.

Coding Style

One thing that I haven't talked about is coding style. Like the English language, JavaScript has it's own styles that you should follow if you want to make your code readable for others (and, of course, for yourself).

The Mozilla JavaScript Style Guide is a comprehensive list of rules that you should try to follow when writing JavaScript. Some of the rules are more important than others, and many of them might not make sense yet for a beginner class. I've listed a few of the rules that apply for this class so far.

Variables and Functions

Clear Naming

Your variables and functions should have names that clearly indicate what the variable is being used for or what the function does. For example, the following variable is being used to store a person's name:

  var n = "Matthew Ephraim";

This is a bad variable name, because n doesn't tell you anything about what the variable is used for, so it might be confusing later on. A much better name would look like this:

  var name = "Matthew Ephraim";

This name is better because name tells you what the variable is being used for.

Multiple Word Names

When your variable or function names have multiple words in them, it's JavaScript style to use camel case (aka camelCase) to indicate that the variable names are multiple words. For example, this variable name is made up of 2 words:

  var professorname = "Matthew Ephraim";

It's 2 words, but it's also difficult to read. It can be made clearer by using camel case:

  var professorName = "Matthew Ephraim";

Notice that the N is capitalized now. This makes it easier to see where the 2 words are separated. Variables names can't have spaces in them, so this is a simple way to still use 2 words in the variable name. Longer variables names with multiple words can be used as well:

  var professorFullName = "Matthew Ephraim"; // professor full name, 3 words
  var firstClassStartTime = "6:30pm"; // first class start time, 4 words

Indentation

Another important coding style is using proper indentation in your code. Just like indenting the first sentence of a paragraph can make text easier to read, indenting your code properly can make it easier to read as well. Typically, when you switch to a new block of code, you should indent 2 spaces.

Remember that, in JavaScript, bocks are sections of code that are surrounded by { curly brackets }. So, every time you're using an opening curly bracket, you should indent 2 spaces. The code example below doesn't use any indentation:

  function alertMatt()
  {
  if (name === "Matt")
  {
  alert('hello Matt');
  }
  else
  {
  alert('You're not Matt!');   
  }
  }

Is this code easy to read? How about if it was indented:

  function alertMatt()
  {
      if (name === "Matt")
      {
          alert('hello Matt');
      }
      else
      {
          alert('You're not Matt!');   
      }
  }

Is this code easier to read? The code that goes with the function is indented several spaces, and the code that's associated with the if statement and with the else statement is also indented several spaces more. Most good text editors should have a feature that help you properly indent your code.

Links

Activity

Today, we will be creating a simple number guessing game. The computer will pick a random number and the user will try to guess what the number is. If the user guesses too low, the computer will tell them that the number is higher. If the user guesses too high, the computer will tell them that the number is lower. And if the user guesses the number correctly, the computer will tell them that they have won.

Step 1

get the template

First, download the template for the game. I have already created a game board for you. The board has a few elements on it and is styled using CSS. Open up game.html and look at the html. There is a form with an input box for the number that the user will guess. There is also a button that the user can click to send their guess to the computer. Finally, there is a div at the bottom where messages from the computer will be displayed.

Notice that 3 of the elements have the id attribute filled out. We are going to use those ids in our JavaScript.

Step 2

test the setupGame function

Open the file called behavior.js that's in the JavaScript folder. This is the file that contain the program for our game. Notice that I have already created several functions in the file for you. For now, you can ignore the 2 functions at the bottom of the page. We will be using these functions later on to make the game work.

The 2 things that I want you to notice are the empty function called setupGame and the link that says:

  window.onload = setupGame;

This line is important. window is a variable for the browser window and onload lets you set a function that will run when the browser window loads. So, what this line of code is saying is "call the function setupGame when the browser window loads". In other words, setupGame is the name of a function that should run as soon as the page loads.

Right now setupGame isn't actually doing anything, because it's empty. Modify the function so that it looks like this

  function setupGame()
  {
      alert('this is a test');
  }

The line we added will simply pop up a test message when the page loads. Reload game.html page to make sure it works. If everything is working you'll see a message popup when you reload the page.

Step 3

setup the random number

Also notice that the behavior.js has a variable called randomNumber declared at the top. Unfortunately, it doesn't help us at all, because it's not set to anything yet. Woudn't it would helpful if our setupGame function set that variable to a random number? I have created a function called getRandomNumber that returns a random number. Call the function and set the return value equal to the randomNumber variable.

Step 4

create a guess function

Earlier, I said we would be using the ids on the html elements in our JavaScript. In this step we will be finding the button on the page using JavaScript and then setting the button up so that when it's clicked on, it will call a function.

First, create a function called guess. This will be the function that we'll use to take a guess at what the number is. We want this function to get called the user clicks the guess button. For now, put in another test alert, so that we can test to make sure the function is getting called when we click the button.

make the guess button work

Now, we can find the guess button and make it so that when you click on the guess button the guess function gets called. JavaScript has a function called document.getElementById(). You use this function to find html elements on the page using the id that you gave them. For example, this is how you would find the guess button and store it in a variable:

  var guessButton = document.getElementById("guess");

The document.getElementById() function takes in one parameter, which is the id of the element you want to find. If you look at the html for the project again, you can see that there is only on html tag that has the id guess. The element with the id of guess is the one that the call to document.getElementById("guess") finds.

Once the button is found, it gets stored in the variable called guessButton. We can use the variable to make the button do something when it's clicked on. To do this, we'll use something called an event handler. We'll talk about event handlers more in depth in another class. This week I just want to you set the onclick handler to your guess function, so that when the button gets clicked, the guess function gets called.

You've already seen how to find the guessButton. The next code example shows you how to set the onclick handler on the button you've found:

  guessButton.onclick = guess;

The line of code is simply saying: when a user clicks guessButton call the guess function. Take the 2 lines that find the button and set the handler and put them in your setupGame function, so that they look like this together:

  var guessButton = document.getElementById("guess");
  guessButton.onclick = guess;

You can also remove the test alert in the setupGame function. We won't need it anymore. If you've done everything correctly, you should be able to reload the page and then click on the guess button. When you click on it, you should see an alert box that pops up.

Step 5

find the message area

For the next step, you want to make it so the guess function updates the message area when the button is clicked. For now, we'll just send a test message to the message area. First, remove the any other code you have in the guess function already.

If you look at the HTML for the page, you'll see that the the message area has an id of message-area. Update the guess function so that it finds the element for message-area and stores it in a variable called messageArea.

change the html for the message area

One you've found the message area and stored it in a variable called messageArea, it's easy to modify the HTML that's inside of the message area using JavaScript. Every HTML element allows you to modify the HTML by setting innerHTML equal to something. For example, this is how you would update the content for messageArea to say "hello!":

  messageArea.innerHTML = "hello!";

Update the guess function so that it uses the messageArea variable to change message area html to say "the guess button was clicked!".

If you've done everything correctly, you should see the message area quickly show your message, and then reload the page. The page is reloading, because the button you're clicking is automatically causing the form to reload the page. The way to fix this is to put return false; at the end of your function. Now, when you click the button, you'll see the message, but your page won't reload.

If you change the onclick on any elements that will cause the browser to take action, like a button or a link, you need to return false from the function that gets called when you click. This will tell the browser that you don't want the browser to follow the link or continue with what the button was supposed to do. Don't worry about why this works for now, just know that returning false will let you have full control over the event that you're trying to attach a function to.

Step 6

check the user's guess

The last thing we need to do is have the game check what the user's guess was. I've already created a function that returns the user's guess for you. It's called getUserNumber() and when you call it, you get the number that the user entered in the textbox before they hit the guess button.

check if the random number is higher than the user's guess

We want to give the user a message that tells them if their guess was lower or higher than the random number. We can use the comparison operators from last week to check the user's number versus the random number that the computer picked. For example, the following code will check if the number they user guess was higher and show them a message:

  if (randomNumber > getUserNumber())
  {
      messageArea.innerHTML = "It's higher!";
  }
  

The if statement compares the randomNumber variable to the value from getUserNumber() using the greater than operator. It's asking is randomNumber greater than getUserNumber's return value? And if the answer to that question is true, it's setting the HTML for messageArea to "It's higher!".

Right now, the code only checks if the number is higher. You can use another if statement to check if the random number is lower than the user's number. But, let's use an else if statement instead, so we can chain a few things together:

  if (randomNumber > getUserNumber())
  {
      messageArea.innerHTML = "It's higher!";
  }
  else if (randomNumber < getUserNumber())
  {
      messageArea.innerHTML = "It's lower!";
  }

Now, the code will also check if random number is lower and send the user a message that says "It's lower!" if it is. The code after the else if will only run if first if statement didn't run.

Finally, we can add an extra else statement that will tell the user that they guessed the number correctly. What would that code look like?

Assignment

Your assignment for this week is to complete the activity above and turn it in by Saturday, September 3rd at 10pm.