javascript - a client-side scripting language
Wikipedia U.
Sites like Wikipedia are great for autodidactic training. You can find pages such as javascript syntax references, general information, and even a wikibook.
HTML and XHTML pages by themselves are not interactive - they just present information to the user and can be styled for better appearance. Good web pages provide a lot more than this, and users have come to expect this. They want database connectivity and interactive pages that change based on their input. Scripting languages such as Perl/CGI and PHP serve well for server-side scripting, where information is sent by the user to the server which performs calculations and returns the results back to the user in static form. Using only server-side technologies, information must be sent back and forth between the user and the server each time the page changes. Not only is this often slow but the constant page reloading prevents any sort of elegant and fluid interactivity.
Javascript allows us to do client-side scripting, which is just a tech-y term scripts that execute locally on the user's machine rather than sending data back and forth between the browser and the server. This means you can change the page as the user interacts with it without page reloads. Traditionally this has been used for trivial (though important) things such as form validation or popping up warnings.
Quite frankly I'm going to skip as much of the traditional and boring stuff that javascript is used for and jump into the fun stuff as soon as possible. I do so partly because that stuff is tedious and boring, but more so because there are thousands of tutorials out there already for doing things like form validation and I don't really have anything new there to contribute. I'm going to introduce a few short introductory concepts of javascript and then we're going to dive right into some examples you can use to make your pages more interesting. When you're going through this, it's not really important to memorize the examples themselves, though I hope they can be helpful in their own right. What's important is that you can see what concepts the example introduces and use your imagination to apply them your own way.
a very short history lesson
Javascript is not Java. Flash back to the early days of the internet as we know it (way, way back to 1995) when Netscape Navigator was the king of the browsers. Support for a new thing called Java applets had been added but Netscape wanted a simpler language that would make them more accessible. So Brendan Eich created LiveScript, which eventually became the poorly-named Javascript and was released in late 1995. Developers pretty quickly abandoned its intended use once they learned how to use it to change the contents of a page and create interesting (and sometimes annoying) visual effects.
Plagued by the same standards and browser compatibility issues as CSS, web developers usually have a love/hate relationship with Javascript. Rather than go into detail about the merits and problems with the language, it is enough to know that unless you want to code your entire site in Flash you're only going to get client-side interactivity using Javascript. If you're interested in more history, this article from O'Reilly is an excellent resource.
example 1: expandable info box
What better way to learn something than dive right into an example! So long as you have the patience for brief explanations of all the new stuff as we go along you'll benefit from starting with useful examples rather than mundane Hello world scripts. This first example demonstrates a method of initially hiding some content on a page and letting the user expand or hide those areas at will.
the early roman emperors
The following are the first 10 Roman Emperors; it's a common misconception that Julius Caesar was the first. He was named dictator, tribune of the plebs, even High Priest, but never emperor.
- Augustus
- Tiberius
- Caligula
- Claudius
- Nero
- Galba
- Otho
- Vitellius
- Vespasian
- Titus
This is a pretty easy way to tuck data into a page which the user can view when they want. You can imagine that it might be useful to stack several of these rows on top of one another, perhaps adding "middle roman emperors" and "late roman emperors" as consecutive expandable rows. Let's take a closer look at the code for this one. We'll start with the HTML:
the content
<div id='emperors'> <div id='emperors_header'> <img id='emperors_arrow' onclick='toggleExpandableBox("emperors")' src='../images/arrow_right.gif'> the early roman emperors </div> <div id='emperors_body'> <p> The following are the first 10 Roman Emperors; it's a common misconception that Julius Caesar was the first. He was named dictator, tribune of the plebs, even High Priest, but never emperor. </p> <ul id='emperor_list'> <li>Augustus</li> <li>Tiberius</li> <li>Caligula</li> <li>Claudius</li> <li>Nero</li> <li>Galba</li> <li>Otho</li> <li>Vitellius</li> <li>Vespasian</li> <li>Titus</li> </ul> </div> </div>
Here we have a properly marked up section of HTML that well describes it content. The entire logical section is wrapped in a container div which we've assigned an id of 'emperors'. It contains two divs, a header and body. The header contains a label and arrow image which the user clicks on to expand or hide the body. The body contains the unordered list of the first 10 Roman emperors.
We make the image clickable by adding an onclick event as one of the attributes of the image (highlighted in the code above.) We've made it's value a Javascript function, which we'll discuss in a moment. For now, the attribute can be read like "when the 'emperors_arrow' img is clicked toggle the 'emperors' expandable box." Again, we'll talk about how this works below. Now, the CSS:
the style
div#emperors { padding: 0 50px 0 50px; } div#emperors_header { border-bottom: 1px solid rgb(150,150,255); font-weight: bold; } div#emperors_body { padding: 5px 20px 20px 20px; display: none; } ul#emperor_list li { padding: 1px; list-style-image: url('/web_class/images/link.gif'); } img#emperors_arrow:hover { cursor: pointer; }
pseudo classes and elements
CSS provides pseudo-classes and pseudo-elements, both of which allow CSS control of things that were previously only possible using Javascript. Sadly, some of the most useful ones are not yet supported by Internet Explorer.
There's not much significant here expect for visual declarations such had padding, borders and font weights. The few things that are new are highlighted. First is the display property. It has three possible values: 'block', 'inline', and 'none'. We learned in the content section that there are block-level and inline elements. Using this CSS property, you can transform any element into one type or another. You can also make an element completely disappear from the page by using the value 'none'. We do so here because we want the body of our 'emperors' block to be invisible at first. The user will have to click the image if they want it to appear.
This brings us to our second new item: the cursor property allows you to control the appearance of the user's mouse icon. Because most people are used to clickable objects changing their mouse to a pointer of some kind rather than an arrow, we can use the value 'pointer'. Javascript isn't necessary to make this change because we used the hover pseudoclass on the arrow image. When this is used on a selector, the declarations of the rule are applied only while the user is hovering their mouse over the specified element.
Now that we see the structure of the HTML and CSS, we can bring in the functionality. While you can include Javascript directly in the page's <head> element, as you can with CSS, it is in the best interest of content separation to put it in an external file. I've created a Javascript file called expandable_boxes.js and included it in my document by putting this line inside the <head> element.
the functionality
<script type="text/javascript" src="expandable_boxes.js"></script>
This file contains only a single Javascript function:
1. function toggleExpandableBox( box_id ) { 2. var box_body = document.getElementById(box_id + "_body"); 3. 4. // is it hidden? 5. if ( box_body.style.display == 'block' ) { 6. box_body.style.display = 'none'; 7. document.getElementById(box_id + '_arrow').src = '../images/arrow_right.gif'; 8. 9. } else { 10. box_body.style.display = 'block'; 11. document.getElementById(box_id + '_arrow').src = '../images/arrow_down.gif'; 12. } 13. }
I've added line numbers to this example which are not part of the real code. They are only added to make it easier to discuss the section. Your code will not work if you type these numbers into it.
As we discussed above, we put an 'onclick' attribute on the arrow image. This defines what should happen when that event occurs. In this case, the javascript toggleExpandableBox function is called and the value 'emperors' is passed, meaning that we send that value to the function and ask for it to perform some action. To define a function, use the function keyword followed by a space and then a name. After that you put a list of its arguments/parameters in parentheses. Finally, the code that is part of the function is enclosed in a block with the { and } symbols. The general form then is like this:
function someName( param1, param2, param3 ) { CODE HERE }
Here we show an example function that accepts 3 parameters, but our toggleExpandableBox function only accepts one. Whatever you pass to a function will be stored in the variables within the parentheses. When we called ours we pass the value 'emperors', which gets stored within the 'box_id' variable inside the function. A variable in Javascript is used to store a value or a reference to something. You can also create variables whenever you want by using var as we did on line 2. This line creates a variable called 'box_body' which stores a reference to the 'augustus_body' element.
When you want to modify an HTML element within Javascript you have to first access it with a reference. This can be done using the document.getElementsById function. If you pass this function the element's id it will return a reference to the element. You can store that reference in a variable, as we did on line 2, or you can use it directly, as we did on lines 7 and 11. If you are going to use it directly multiple times you can save yourself some typing by storing it into a variable and then using the variable, as we did on lines 6 and 10.
Within the function we check to see if the display property of the box_body is 'block' (whether it is visible.) If so, we hide it by setting it to 'none'. We also change the image to a right arrow. If it was already hidden, we do the exact opposite - change its display property to 'block' and change the arrow back to the 'down' version.
Using this generic syntax, we can pass the name of any container div to this function to make it expandable, so long as it has a few standard children. If the name of the container is 'foo', for example, it would have to have 'foo_body' and 'foo_arrow'. Intentionally making this generic means that we can reuse it for any other elements we want to be expandable, not just this roman example.
Next we'll explore another example of using Javascript to manipulate the style definition of a page. We'll also show how to use cookies to give your pages memory.
