JavaScript is one of the most
important languages used in web development. It has many uses ranging from
checking the values submitted by forms to controlling interactive widgets, such
as tabbed panels, accordions, and flyout menus. It's also used to create photo
galleries, and to fetch new information from the web server to refresh content
without the need to reload the page—a combination of technologies commonly
known as Ajax.
Along with HTML and CSS, knowledge
of JavaScript is a key skill that anyone involved in building websites should
acquire. Yet many web designers never do. JavaScript has a reputation for being
too difficult; and graphic designers frequently insist that their role is to
design, not to program. Even if you never do any JavaScript programming
yourself, it's important to understand how the structure of your web pages
affects the job of the JavaScript programmer. What's more, JavaScript has
become easier to use thanks to code libraries such as jQuery.
This is the first in a series of
articles designed to help you get started with JavaScript and jQuery. It
describes the basic features of the language that you need to know before
diving into jQuery.
In spite of the similarity of names, JavaScript is not Java.
The languages are not related. Java is frequently used to program games, mobile
phones, and other devices, such as the Amazon Kindle. Although Java can be used
in websites, it's rarely used that way.
JavaScript, on the other hand, is a
lightweight, yet powerful language that normally runs inside a web browser. Its
role is to provide access to different elements of the page so that they can be
removed or updated. It can also create new elements, change the style of
existing elements, or extract information from them. For example, it can read
the values entered into a form, perform a calculation, and display the result.
It can also send a request to the web server for more information, and update
part of the page without needing to reload it.
JavaScript performs these tasks by
accessing the Document Object Model (DOM). The DOM is a structure similar to a
family tree. If the HTML markup of your page is invalid or too complex, the
JavaScript code can't navigate the family tree. Similarly, if you break simple
rules, such as not using the same ID more than once in any page, JavaScript
becomes confused and simply gives up.
The
importance of events
JavaScript is an event-driven language. Some events are
triggered automatically. For example the load event is triggered when the page
finishes loading in the browser, and it's frequently used to initialize flyout
menus and other widgets. Other events are triggered by the user, the most
common being the click event when the user clicks the main mouse button, or taps
on a touch-sensitive screen. Other common events include mouseover and mouseout, when the user hovers over an element, and submit, when a
form is submitted.
Events are being triggered all the
time. An event is triggered every time you move the mouse, scroll the page, or
press a key. It would be chaos if the browser had to respond to every event.
Instead, you as the developer, create functions to handle specific events, and
you associate them with the page elements that you want to respond to the
event. This is known as binding an event handler.
Event handler functions sit and
wait—or listen—for the event. When the appropriate event is triggered,
the event handler jumps into action and performs its designated task, such as
opening or closing a flyout menu, submitting a form, or changing the style of
an element.
Creating
a function
Rather than talk in abstract terms, let's look at JavaScript
in action.
As the name suggests, a function
does something. It's a series of commands that performs whatever task (or
tasks) you tell it to do. The most common way to define a function is to use the keyword function followed by the function
name, a pair of parentheses, and a block of code wrapped in curly braces. You
can give functions almost any name you like, but it must begin with a letter,
underscore (_), or the dollar sign. Also, the name must not contain any spaces
or hyphens. JavaScript is case-sensitive, so it's common to give functions
descriptive names using an uppercase letter for the second and subsequent words
("camel case"); for example, changeFontSize.
To keep the code as simple as
possible, the following example just changes the text color of an unordered
list. You can find the finished code in change_01.html in the example files,
but to give yourself a feel for writing JavaScript, I recommend that you open
Dreamweaver (or any other text editor) and type the code yourself.
1. Open change_start.html. The page contains an <h1> heading, an unordered list, and a paragraph. The unordered list has the ID fruits.
A
JavaScript function will be used to change the list's font size.
- In Code view, insert a new line just before the closing </head> tag, and add a <script> tag. The page has an HTML5 DOCTYPE, so you don't need to add type="text/javascript". Browsers automatically assume that the code inside a <script> block is JavaScript.
- Before adding the JavaScript code, it's a good idea to close the <script> block. So, leave a blank line, and then type </script>.
Note that
Dreamweaver doesn't autocomplete the tag when you type </.You need to
complete it manually. This is because the same combination of characters might
occur in the script.
- Inside the <script> block, enter the following code:
This defines a function called changeFontSize(). You often pass information as arguments to a
JavaScript function. The arguments go between the parentheses after the
function name. This function doesn't take any arguments, but the parentheses
must still be used. The body of the function goes between the curly braces.
You'll add that next.
5. Type var list = document on the line
between the curly braces. Then type a period (a full stop) immediately after
"document." As soon as you type the period, recent versions of
Dreamweaver display a list of code hints.
Dreamweaver
displays code hints for JavaScript features.
- Type g. This brings up the code hint for getElementById(). Press Enter/Return to insert the code.
Dreamweaver
CS5.5 presents code hints for available IDs.
- In Dreamweaver CS5.5, press Enter/Return to insert the fruits ID. Then type a closing parenthesis followed by a semicolon.
If you're
using another program, you need to complete the code manually. In either case,
you should now have the following code in your function definition:
The line of code you have just typed uses the keyword var
to create a variable called list, which stores a reference to the page element with the ID fruits. The reference to fruits is obtained by a JavaScript method
called document.getElementById().
Note: Methods are essentially the same as functions, except that
they belong to objects. You'll learn about objects later. Don't let the
terminology confuse you. If it helps, just think of a method as being a special
type of function.
- Insert a new line after the one you just typed, and add the following code:
If you're using a recent version of Dreamweaver, you'll have
noticed code hints popping up each time you typed a period. What this line of
code does is change the size of the text in the list element—in other words,
the unordered list with the ID
fruits.
You
probably recognize fontSize as similar to the CSS font-size property.
JavaScript doesn't allow hyphens in names. So, the hyphen is removed and the
word after the hyphen is capitalized.
The
complete function definition should now look like this:
function changeFontSize() { var list =
document.getElementById('fruits'); list.style.fontSize = '20px'; }
- Save the page and test it in a browser. Nothing happens. Although you have defined a function, it doesn't do anything until it's triggered by an event. You'll create an event handler for it shortly, but first take a look at some important features of JavaScript that this short piece of code has introduced you to.
If you have experience with other programming languages,
most of this section should be familiar. But for the benefit of complete
beginners, I'll explain the basic terminology. At first, it might seem like
jargon overload, but it will make the rest of this tutorial easier to follow.
The first line inside the changeFontSize() function definition creates a variable called list.
Variables are an important part of all programming languages. A variable
usually stores a value that you don't necessarily know in advance. The name of
the variable remains the same, but its value might change. To take an example
from everyday life, your bank balance is similar to a variable. The amount
changes frequently, but the name "balance" always remains the same.
When defining a variable inside a
function, you should always use the var keyword. Doing so tells the
JavaScript engine that you want the variable to be used only inside the
function. Omitting var can produce unpredictable results in more complex scripts.
The same rules apply to variable
names as to functions, namely:
- The name must begin with a letter, underscore, or the dollar sign.
- No spaces or hyphens are allowed.
The value is assigned to the
variable using an equal sign. The value on the right of the equal sign is
assigned to the variable on the left.
The first line in the changeFontSize() function uses document.getElementById('fruits') to assign the variable a reference to the fruits unordered
list. This introduces you to three important features of JavaScript—objects,
dot notation, and passing arguments to a function.
In simple terms, an object is
a variable that contains zero or more other values known as properties and
methods. A property is similar to variable, and a method is
essentially the same as a function. You access the properties and methods of an
object using dot notation. The object comes first,
followed by a dot or period, and then by the property or method. In this case, getElementById() is a method of the document object.
To name of getElementById() is self-explanatory: it gets a reference to an element using
the element's ID. You put the ID in quotes between the parentheses after the
method's name. This is known as passing an argument. Because the
argument is in quotes, JavaScript treats it as literal text. In programming
terms, literal text is known as a string (because it's a string of
characters). It doesn't matter whether you use single or double quotes for
strings, but the quotes must match.
The second line in the changeFontSize() function takes dot notation a step further. It accesses the
style object of the element stored in the list variable, and then accesses its fontSize property like this: list.style.fontSize.
The value assigned is a string containing the new size. In other words, the
second line sets the CSS font-size property of the fruits list to 20px.
There's one final point to notice.
Each command ends with a semicolon. Technically speaking, the semicolon is
optional, because JavaScript automatically treats the end of a line that
contains a command as the end of the command. If you accidentally break a line
of code, JavaScript treats it as a complete command, causing your script to
fail. Always ending commands with a semicolon makes errors easier to find.
That's enough theory for now. Let's
get back to the code and make the function do something.
Using the function
The simplest way to use a function
is to bind it to an element using an HTML attribute, such as onClick.
- Keep working with the previous file or use change_01.html as your starting point.
- Select the text in the final paragraph, and type javascript:; in the Link field of the Property inspector in HTML mode. This adds a dummy link to the text.
- Open Code view, and insert a space before the closing angle bracket of the opening <a> tag. Then type onClick="changeFontSize()". The final paragraph should now look like this in Code view:
- Save the page, and load it into a browser or activate Live view in Dreamweaver.
- Click the link in the last paragraph (if you're in Live
view, hold down the Ctrl key on Windows or the Command key on a Mac while
clicking). If your code is correct, the text in the list increases in
size. The JavaScript function has changed the text size in the list.
You can check your code against change_02.html in the sample files.Detecting errors when your script doesn't workWe all make mistakes, and you tend to make a lot when you're learning a new subject. If there's a problem with your code, the script usually fails without any indication of what went wrong. All recent browsers have built-in tools to help you debug your code. You can find them in the following locations:- Internet Explorer 8 or later: Press F12 to open the Developer Tools and select the Console tab.
- Firefox 4: Select Web Developer > Error Console.
- Google Chrome: Select Tools > Developer tools.
- Safari: Enable the Developer menu by selecting Edit > Preferences (Windows) or Safari > Preferences (Mac). In the Advanced tab, select "Show Develop menu in menu bar." Close Preferences. Then select Develop > Show Error Console.
- Opera: Select Tools > Advanced > Error Console.
Introduce a deliberate mistake into the changeFontSize() function to see the error message generated by the browser's error console.- Change the spelling of getElementById() to use an uppercase D like this: var list = document.getElementByID('fruits');
- Save the page, and reload it in your browser (you can't use Live view for debugging).
- Click the link in the final paragraph. The list's font size doesn't change.
- Open your browser's error console. You should
see a message similar to the one in figure.
The error console identifies the error and its location in the page.The error messages generated by your browser might be worded differently from Figure, but they all basically say the same thing: getElementByID() isn't a valid function. As a beginner, working out why an error occurs isn't always easy, but one of the most common mistakes is misspelling the name of a function or method. JavaScript is case-sensitive.
All error consoles, except the one in Opera, provide a link, which takes you to the line that contains the error.
Using conditions to make decisionsThe changeFontSize() function increases the font size, but the only way to change it back to its original size is to reload the page. To improve the function, you need to detect the current font size so that the function can decide which size to change it to.In common with other programming languages, JavaScript uses conditions to determine what action to take. You place the condition in parentheses preceded by the if keyword. The code associated with the condition is placed in a pair of curly braces after the condition. In pseudo-code, it looks like this:if (condition) { code to execute if condition is true }If the condition is true, the code is executed. If it's false, the code is ignored.
When the condition is false, you can use the else keyword to introduce alternative code. Again, in pseudo-code, it looks like this:if (condition) { code to execute if condition is true } else { code to execute if condition is false }You can also chain conditions using else if:if (first condition) { code to execute if first condition is true } else if (second condition) { code to execute if first condition is false, but second is true } else { code to execute if both conditions are false }Note: You might see scripts that omit the curly braces after a condition. This works only when there is a single command following the condition, and is not recommended. Always use curly braces. They make the logic of your script easier to understand.The condition is often a comparison, such as two values being equal, or one being larger than the other. The following table lists the main comparison operators.Table 1. Comparison operatorsNameExampleMeaning==Equalitya == ba and b both have the same value.!=Inequalitya != ba and b have different values.>Greater thana > ba is greater than b.>=Greater than or equal toa >= ba is greater than or equal to b.<Less thana < ba is less than b.<=Less than or equal toa <= ba is less than or equal to b.Let's improve the changeFontSize() function to toggle between the normal and larger font sizes.- Continue working with the same file as before, or use change_02.html.
- Using the element's style object to change the value of a CSS property has the effect of using an inline style. Because the original HTML doesn't use an inline style for the fruits unordered list, list.style.fontSize doesn't have a value when the page first loads. So, one way to write the condition is to check that list.style.fontSize is an empty string—in other words, it has no value. An empty string is a pair of quotes with nothing between them. Change the function like this:
function changeFontSize() { var list = document.getElementById('fruits'); if (list.style.fontSize == '' || list.style.fontSize == '16px') { list.style.fontSize = '20px'; } else { list.style.fontSize = '16px'; } }If list.style.fontSize has no value, it's changed to 20px. Otherwise, it's changed to 16px.Note: One of the most common mistakes is using a single equal sign instead of two when comparing values. A single equal sign assigns a value. Two equal signs compare values.- Save the page, and test it in a browser. When you click the link the first time, the text size increases. Click it again to restore the original font size.
- Click the link again. Nothing happens. Why? It's because list.style.fontSize is no longer an empty string. It's 16px. The simple way to fix this is to use the inequality operator (see Table 1) like this:
function changeFontSize() { var list = document.getElementById('fruits'); if (list.style.fontSize != '20px') { list.style.fontSize = '20px'; } else { list.style.fontSize = '16px'; } }If list.style.fontSize is not 20px, it's set to 20px. Otherwise, it's set to 16px.- Save the file and test it again. This time, clicking the link toggles the font size between 16px and 20px. The completed code is in change_03.html.
Using logical operators with conditionsAlthough there was a simple solution to the problem with the condition in changeFontSize(), it's often necessary to test multiple conditions. You do so using logical operators, which are listed in Table 2.Table 2. Logical operatorsNameDescription&&Logical ANDBoth conditions must be true. If the condition on the left fails, the condition on the right is never tested.||Logical OREither condition must be true. The condition on the right is tested only if the condition on the left is false.!Logical NOTWhen placed in front of a true/false value, this reverses its meaning. So, a true value becomes "not true"—in other words, false.The changeFontSize() function has been rewritten in change_04.html to demonstrate the use of the logical OR operator. The code looks like this:function changeFontSize() { var list = document.getElementById('fruits'); if (list.style.fontSize == '' || list.style.fontSize == '16px') { list.style.fontSize = '20px'; } else { list.style.fontSize = '16px'; } }The condition now tests if list.style.fontSize is either an empty string or 16px. If you test change_04.html, you'll see it toggles the font size between 16px and 20px.Note: You need to repeat the full condition on both sides of the logical operator. You cannot just repeat the value like this:// THIS WILL NOT WORK if (list.style.fontSize == '' || '16px') {Unlike the logical AND and logical OR operators, the logical NOT operator is used with a single condition. It's extremely useful because JavaScript treats most values as implicitly true or false, as the next section explains.Understanding true and false valuesValues that are either true or false are known as Booleans (after the nineteenth century English mathematician, George Boole, whose work is considered to be the basis of modern computer logic). JavaScript has two Boolean values, the case-insensitive keywords true and false.The comparison operators in Table 1 produce a Boolean result—or to use the technical expression, they return true or false. In addition to Boolean values, JavaScript supports the concept of values that are implicitly true or false. These are sometimes referred to as truthy and falsy values.JavaScript regards the following values as implicitly false:- An undefined variable
- A variable without a value (null)
- The result of an arithmetic calculation that is not a number (NaN)
- 0 or '0'
- An empty string ('')
All other values, apart from the keyword false, are regarded as true.Note: Wrapping the keywords true and false in quotes converts them into strings. Only an empty string is false, so 'false' is treated as true. Beware!When the page with the changeFontSize() function first loads, list.style.fontSize returns an empty string, so it's implicitly false. This means that you can rewrite the version of the function in change_04.html like this (the code is in change_05.html):function changeFontSize() { var list = document.getElementById('fruits'); if (!list.style.fontSize || list.style.fontSize == '16px') { list.style.fontSize = '20px'; } else { list.style.fontSize = '16px'; } }Prefixing list.style.fontSize with the logical NOT operator (an exclamation mark) has the effect of saying "if list.style.fontSize is false treat it as true."Using the logical NOT operator with implicitly true and false values is very common in JavaScript. It's frequently used with values that you expect to be true. For example, you might have a variable called checked. You can read if (!checked) as "if not checked."Passing an argument to a functionThe changeFontSize() function is rather inflexible because the ID of the fruits unordered list is hard-coded into the first line. To reuse it with other elements, you need to pass the ID as an argument to the function.- Continue working with the same file, or use change_03.html.
- Type id between the parentheses of changeFontSize() in the function definition. This tells the function to expect an argument (or parameter) called id. A parameter is similar to a variable, so it's not wrapped in quotes and follows the same naming rules as a variable (see "JavaScript basics" earlier in this tutorial).
- In the first line inside the function definition, delete 'fruits' between the parentheses of getElementById(), and replace it with id. Make sure you delete the quotation marks, because id is being used as a variable to represent the value passed as an argument to the function. The first two lines of the function definition should look like this:
function changeFontSize(id) { var list = document.getElementById(id);This has the effect of passing to getElementById() whatever value is passed as the argument to changeFontSize().- Type 'fruits' between the parentheses of changeFontSize() in the link that triggers the onClick event. The link should look like this:
Note: The onClick attribute wraps changeFontSize() in double quotes, so you must use single quotes around fruits. When using quotes inside a string, you should always use the opposite type to the outer pair of quotes. Otherwise, the code will break. If you can't avoid using the same type of quotes, inner quotes should be preceded by a backslash.- Save the page, and test it. The function works the same as before.
- Delete the "s" at the end of fruits, save the page, and test it again. It no longer works, because the function can't find an element with the ID fruit.
- Restore the "s" at the end of fruits, and save the page. You can compare your code, if necessary, with change_06.html.
The changeFontSize() function toggles between two font sizes. The final change you'll make to it in this whirlwind tour of JavaScript is to iterate through several different sizes. To do so, you'll store the sizes as an array and use a loop to go through each size in turn. This section is more complex than before, so don't try to rush it.Creating an arrayAn array is a collection of related values that can be referred to by a single variable. There are two ways to create an array. One is to use the Array() constructor like this:The other way is to create what's known as an array literal like this:Using square brackets to create an array literal is quicker, and tends to be more widely used nowadays.Each item—or array element—is automatically numbered. To refer to an array element, you put its number in square brackets after the name of the array. However, in common with most programming languages, the numbers begin at zero. So, friends[1] refers to the second array element (Dick) rather than the first element, which is friends[0].Using a for loop with an arrayThe usual reason for storing elements in an array is to perform the same task on each one or to select a value from the set. Loops are used to iterate through each item in an array. JavaScript has several types of loops, but for the purposes of this tutorial, I'm going to use only one: the for loop.
In pseudo-code, a for loop looks like this:Between the parentheses are three statements separated by semicolons:- Initialization: This initializes one or more variables to be used in the loop. The variable (or variables) usually keep count of the number of times the loop has run.
- Condition: This sets the condition that determines how long the loop should run—usually to the end of the array.
- Increment: This increments the counter variable (or variables) each time the loop runs.
All arrays have a length property, which returns the total number of elements in the array. The following code gets the number of items in the friends array:There are three elements in the friends array. So, numFriends is 3.Because array elements are numbered from zero, you set the condition to run while the counter is less than the array length. The counter variable lets you access each array element in turn like this:for (var i = 0; i < numFriends; i++) { do something with friends[i] }The first time the loop runs, i is 0, which makes friends[i] equivalent to friends[0]. The value of i is then incremented by one, giving access to the next array element, friends[1]. Then i is incremented to 2, giving access to friends[2]. The counter is incremented again, but i is no longer less than 3, so the loop stops.Looping through an array of font sizesWith that information under your belt, it's time to tackle the final version of the changeFontSize() function. This exercise pulls together many features of JavaScript, including declaring multiple variables, creating an array literal, looping through an array, conditional logic, simple arithmetic calculation, and joining values as a string.- Continue working with the same file, or use change_06.html.
- The code that controls the font size needs to be changed considerably. So, delete the conditional if and else blocks. You should be left with the following code:
- The
function needs to use several variables. Many scripts declare variables
only when they're needed. However, this results in variable declarations
scattered through your code, making it difficult to maintain. It's
recommended to declare all your variables at the beginning of a function.
You can declare each one in separate commands beginning each command with var and ending with a semicolon. Alternatively, you can
create a comma-separated list of variable declarations. That's the
approach I'm going to take.
Delete the semicolon after getElementById(id), and replace it with a comma. Then create a new line and indent the code so that it's vertically aligned with list. Declare the new variables like this:
function changeFontSize(id) { var list = document.getElementById(id), fontSize = list.style.fontSize, sizes = [16, 20, 24, 28], len = sizes.length, i; }This stores the value of list.style.fontSize as fontSize. It then creates an array literal called sizes containing four numbers, and stores the length of the array as len. Finally, it creates the counter variable i, but doesn't assign it a value.You don't need to indent the code like this, but it makes it easier to read. This is also one of the rare occasions when inserting a new line before the semicolon doesn't break the code. The comma at the end of each line tells the JavaScript engine that it's a list of variables. You should also note that the numbers aren't in quotes. JavaScript treats numbers differently from strings.- When the page first loads, list.style.fontSize doesn't have a value. So, you need to use a separate condition to set the font size the first time the function is triggered. Amend the code like this:
function changeFontSize(id) { var list = document.getElementById(id), fontSize = list.style.fontSize, sizes = [16, 20, 24, 28], len = sizes.length, i; if (!fontSize) { list.style.fontSize = sizes[1] + 'px'; } }This uses the logical NOT operator with fontSize. If fontSize doesn't have a value, JavaScript treats it as implicitly false. The logical NOT operator reverses the meaning of a true/false value, so the code in the curly braces is executed the first time the function is triggered.JavaScript uses the plus sign (+) both for simple addition and to join text together. So, the line of code inside the braces takes the value of the second element in the sizes array (20), and adds the string 'px' to it. This value (20px) is then assigned to list.style.fontSize.You're probably wondering why you need to use list.style.fontSize when you have created fontSize as a variable. It's because fontSize only stores the existing value. To change the size of the font in the page, you need to assign the value to the unordered list's style object.- Now you need to deal with what happens when the function is triggered on subsequent occasions. The fontSize variable contains the current size. So, you need to loop through the array to find a match for the current size, and change the font to the next size up. However, when you get to the end of the array, there isn't a next size up. You need to go back to the first size again. Amend the code as shown here, and then I'll explain it in more detail:
function changeFontSize(id) { var list = document.getElementById(id), fontSize = list.style.fontSize, sizes = [16, 20, 24, 28], len = sizes.length, i; if (!fontSize) { list.style.fontSize = sizes[1] + 'px'; } else { for (i = 0; i < len; i++) { if (i == len - 1) { list.style.fontSize = sizes[0] + 'px'; } else if (fontSize == sizes[i] + 'px'){ list.style.fontSize = sizes[i + 1] + 'px'; break; } } } }The for loop inside the else code block contains another set of conditions. The first condition checks if the counter is the same as len minus one—in other words, 3. There are four elements in the sizes array. Counting from zero, the final element is sizes[3]. If it is, there are no more array elements. So, the code builds the font size from the first array element (sizes[0]).If the loop isn't at the last element in the array, the second condition is evaluated. It checks if the current array element plus 'px' matches fontSize. If it doesn't, the code is ignored, and the loop runs again until it finds a match. When it does, it builds the string from the next element in the sizes array by adding one to the value of the counter. When a match is found, the loop isn't needed any more, so the break keyword brings it to a halt.- Save the page, and test it in a browser. Each time you
click the link, the text grows in size until it reaches the maximum. The
next time, it reverts to the original size. You can check your code, if
necessary, against change_07.html CLICK HERE for backtrack 5 hacking tutorial