Chapter 3. Javascript Events: Reacting to your users

image with no caption

Sometimes you need your code to react to other things going on in your web application... and that’s where events come into the picture. An event is something that happens on your page, in the browser, or even on a web server. But it’s not enough to just know about events... sometimes you want to respond to them. By creating code, and registering it as an event handler, you can get the browser to run your handler every time a particular event occurs. Combine events and handlers, and you get interactive web applications.

It all started with a downward-facing dog...

Marcy’s just opened up a new yoga studio that caters to programmers and techies. She wants a website that shows the different levels of classes she offers, the times they’re available, and provides new customers a way to enroll in a class... all in a cool, intuitive package. But she doesn’t have a clue how to build that kind of site.... that’s where you come in.

To give you an idea of what she’s looking for, Marcy worked up a quick sketch of what a page on her site needs to show her customers:

image with no caption

Try not to rely on any toolkit unless you understand the code behind that toolkit. That way, when things don’t work the way you want, you can fix the problems yourself.

image with no caption

Ajax IS mostly JavaScript, events, and lots of boring scripting!

Most apps that use asynchronous requests have a lot more code that deals with web pages, objects on that page, and doing basic JavaScript tasks. The actual request object code may only be a callback function and a few lines in an event handler.

But you really can’t break an application up into “JavaScript” and “Ajax” and “CSS.” It all works together. So even though you’ll be spending a lot of time in this chapter working with XHTML and CSS and event handlers, you’re really building Ajaxian applications: responsive, user-friendly, modern web apps.

The more you know about JavaScript, XHTML, and CSS, the more effective and usable your Ajax apps will be.

Ajax apps are more than the sum of their parts

Ajax apps are really just a combination of lots of pretty simple technologies: XHTML, CSS, JavaScript, and things like the DOM, which you’ll get to in a few chapters. In fact, if you take a close look at Marcy’s app, most of the work is not Ajax-specific. It’s XHTML, CSS, and JavaScript... with a little asynchronous requesting added in just when it’s needed.

image with no caption

Here’s Marcy’s XHTML...

Below is the XHTML for Marcy’s page... it’s already got a few references to the JavaScript files we’ll need and several <div>s representing the different parts of the page. Go ahead and download this page, along with the rest of the Chapter 3 examples, from the Head First Labs web site.

image with no caption

Events are the key to interactivity

Marcy’s page needs to react to her customers. She wants a different schedule and description to appear when a customer clicks on a class, and we could even highlight a menu item by using context-specific graphics.

Note

Context-specific graphics is just a fancy term for changing a graphic when the customer moves their mouse over a menu option.

All this adds up to an interactive web page. In programming terms, “interactive” means that your page responds to specific events. And events are just things that happen. Those things can be triggered by the user, your code, the browser, or even a server:

image with no caption

Lots of things trigger events, and you can register handlers in your code that respond to those events.

Connect events on your web page to event handlers in your JavaScript

You’ve already used the window.onload event to trigger lots of setup work on web pages, and the onclick event to handle users clicking on an image. We can use these events, as well as the onmouseover event, to connect different parts of Marcy’s yoga page to JavaScript functions we’ll write.

image with no caption

Use the window.onload event to initialize the rest of the interactivity on a web page

You’ve already used window.onload twice to initialize a page. We need to do the same thing in Marcy’s yoga page because...

image with no caption

Assigning event handlers programmatically is one more way to separate content from behavior.

Anytime you can keep your JavaScript separate from your XHTML, you should. The same goes for XHTML and CSS: keep them separate.

The best way to assign event handlers is by using properties of the elements in your XHTML page, and doing that assignment in a function that runs before the user gets control of a page. window.onload is the perfect event for just that.

Brain Power

How do you like this user interface? Is there anything you would change?

image with no caption

If a web page is confusing to YOU, it will almost certainly be confusing to your users.

When you design and implement a site, you know how the site is supposed to act. If the site’s confusing to you, then users—without the benefit of the information you have—will probably be even more confused.

Even when you don’t get to control the design of a site, like with Marcy’s yoga page, you should still try and make the site as unconfusing as possible. If that means turning some images into buttons to avoid users clicking on those images endlessly, then do it!

image with no caption

Sometimes you have to make a choice between okay and better.

If you’re not in control of a site’s design, you’re often stuck making the best decisions based on an existing layout. With Marcy’s site, she liked the design with tabs and images.

Note

This can even happen when you design a site that a customer loves. Later on, you realize there are some problems, but the customer doesn’t want to make any changes because they like what they’ve already seen.

Your job, then, is to make the best decisions based on what you’ve got. In this case, that means two forms of navigation to avoid user-confusion. Otherwise, non-clickable images on the left might be construed as buttons.

Change those left-side images to be clickable

It’s a piece of cake to make the images on the left-hand side of Marcy’s page clickable. In fact, all we need to do is remove code:

image with no caption
image with no caption

Use your XHTML’s content and structure

showHint() is called when a user rolls their mouse over a tab or image. But how do we know which tab or image is being rolled over? For that, we need to take another look at Marcy’s XHTML:

image with no caption

Every XHTML element is accessible in your JavaScript code as an object

You’ve been using getElementById() to access the images in Marcy’s XHTML page. That works because each element in the XHTML is represented by the browser as an object you can manipulate in your JavaScript.

Even better, all the attributes on an element are stored as properties on the JavaScript object that represents that element. Since Marcy’s images have titles, we can use those titles to figure out which image or tab was selected and show the right hint.

Add the code for hideHint(), too

The code for hideHint() is simple once showHint() is done. You just need to grab the content pane, and set the hint text back to the default:

image with no caption

Tabs: an optical (and graphical) illusion

Marcy likes the look and feel of tabs on her yoga page. While there are lots of fancy toolkits that let you create tabs, a simple graphical trick is all we need.

On the yoga page, we’ve got a main content pane that’s dark green. So that color basically becomes the “active” color. The Welcome tab starts out that color, and the other tabs are a lighter color, the “inactive” color:

image with no caption

To make a tab active, we need to change the tab’s background to the “active” color

All we need to do to make a different tab active is change it to the active color. Then, we can make the old active tab inactive by changing it to the inactive color.

So suppose we’ve got two graphics for each tab: one with the tab against an active background, and another with the tab against an inactive background:

image with no caption

We’ve already got a showTab() function. So the first thing that function should do is change the tab image for the clicked-on tab.

image with no caption

Use a for... loop to cycle through the images

You’ve already used the title property of the image objects in showHint() to change the hint text. We need to do something similar in showTab(): figure out which tab should be active, and change that tab to the active image. For all the other tabs, we just want the inactive image.

image with no caption
image with no caption

This event handler has a LOT of presentation-specific details.

showTab() now works directly with image names, and it actually builds those image names dynamically! So not only does showTab() mix behavior with presentation (the images), but it actually is depending on the content of the XHTML page—the title of each image—to figure out what presentation to use.

There’s a real problem here. But what would you do to fix the problem? Think about how you would separate content, presentation, and behavior before you turn the page.

CSS classes are the key (again)

Marcy likes the look and feel of tabs on her yoga page. While there are lots of fancy toolkits that let you create tabs, a simple graphical trick is all we need.

For each tab, there are two possible states: active, which is the darker color that matches the content pane, and inactive, which is the lighter, unselected color. So we can build two CSS classes for each tab: one active, and one inactive.

Open up yoga.css in your app’s css/ directory, and add these lines:

image with no caption

Ummm... but the tabs aren’t < a >’s !

Did you notice what element the CSS is styling? #tab indicates a <div> with an id of “tab.” That’s okay. But then, the CSS indicates it’s styling <a> tags, with ids of “welcome,” “beginners,” and so on. That doesn’t match Marcy’s XHTML page at all.

But that’s no big deal... we can change all the images on the XHTML page to <a> tags to separate one more layer of content from presentation.

image with no caption

This broke our JavaScript, too, didn’t it?

We’ve got a nice, clean XHTML page and some CSS that truly controls the presentation of the page. But now all that JavaScript that depended on <img> elements isn’t going to work. That’s okay, though, because even though it worked before, it mixed images in with behavior... a real problem.

Let’s fix up our script, and separate all that presentation from the behavior of the yoga page.

image with no caption
image with no caption
image with no caption

The earlier you separate your content from your presentation and behavior, the easier that separation will be.

With Marcy’s site, we didn’t really think about content or presentation early on, and it’s only when we were a few functions into our behavior (the JavaScript) that we saw problems. If we’d planned from the start to keep images out of our code, and let our CSS handle all the presentation, we’d have fewer changes to make to our JavaScript.

Still, even if you find problems late in the process, it’s almost always better to do the work to really separate out content, presentation, and behavior. Your app will be a lot better for the work you put into it.

image with no caption

Jill: You mean X-HTML, right?

Joe: Well, yeah.

Frank: As an entire page? That’s no good... we don’t want to recreate all the tabs and stuff for each class, do we?

Joe: Well, then how about an XHTML fragment. Like, just the elements and text for the actual schedule and class description.

Jill: Yeah, because there’s no way we want all that content in our JavaScript. And if we use XHTML, we can use the same CSS styles as in the main page.

Frank: But how do we load up that... what? XHTML fragment—

Joe: Sure.

Frank: —okay, right. So how do we load it?

Joe: Well, the tabs are <a> elements. Maybe we put the fragments in the href attributes instead of those # symbols?

Frank: But that would replace the entire page. That’s no good. Besides, it seems sort of slow...

Jill: Guys, what about using a request object?

Joe: What do you mean?

Jill: What if we use a request object to get the XHTML fragment, and just set the content pane’s innerHTML to the returned page?

Frank: Can you even do that?

Jill: Why not? Instead of requesting a server-side program, we’ll just request the XHTML fragment we want.

Joe: And we can do it asynchronously, so there’s no waiting or page refreshing!

Use a request object to fetch the class details from the server

The server doesn’t need to do any processing for Marcy’s page, but we can still use a request object to grab the XHTML fragments for each class. This is a request to the server, but it’s just for a page rather than a program. Still, the details are the same as you’ve already seen.

We’ll build the code the same way we always do, using the createRequest() function from utils.js and a callback to display the results in the content pane. Here’s what we need:

image with no caption

Brain Power

Make these changes to schedule.js, and try out the improved web page. Is everything working? Are there any changes you’d make?

Be careful when you have two functions changing the same part of a web page

There’s a bug! Class schedules show up okay, but mousing over another tab or button image hides the class schedule and replaces the content pane with hint text. That doesn’t seem too intuitive...

image with no caption

Get it!

Make sure you have the class XHTML fragments.

XHTML fragments for each class are included in the examples download from Head First Labs. Make sure they’re named beginner.html, intermediate.html, and advanced.html. They should be in the same directory as your main page, classes.html.

image with no caption

Marcy wants the images on the left to change when users roll their mouse over the image

It’s too bad Marcy didn’t let us know about this earlier, but this still shouldn’t be too hard. So when the page loads, the images should look one way, but each time a user rolls their mouse over the button, the image should change.

image with no caption

When you need to change images in your script, think “change CSS classes” instead

Here’s another case where separation of presentation and behavior can be a big issue. Before changing any code, think, “Is this a case where I’m going to have to mix my behavior (my code) and my presentation (like images)?”

If it is, it’s time to restructure some things. The image buttons are really just like the tabs. They just look like buttons instead of tabs. So let’s add some new CSS classes for both button states: the normal button and the active button.

image with no caption

Links in XHTML are represented by <a> elements

Here’s another place where we can make some improvements to our XHTML. Currently, the images are represented by <img> tags, but they really are functioning as linking buttons: you can click on one to get a class schedule.

Let’s change each button to an <a>, which better represents something you can click on to get to a different destination, in this case a class schedule and description.

image with no caption

We need a function to show an active button and hide a button, too

Before we change any of schedule.js, let’s add two functions we know we’ll need. First, we need a buttonOver() function to show the active image for a button. That’s just a matter of changing a CSS class:

image with no caption

In JavaScript, an element is represented by an object. That object has a property for each event that can occur on the element that it represents.

We can do just the opposite for when a user’s mouse rolls out of the button’s area. We just need to change back to the default state, which is no CSS class:

image with no caption

When you initialize the page, you need to assign the new event handlers

Now we need to assign the new functions to the right events. buttonOver() should get assigned to a button’s onmouseover event, and buttonOut() gets assigned to a button’s onmouseout event.

We can also update the code to use the new <a> elements that represent buttons instead of the older <img> elements.

image with no caption
image with no caption

What happened to the hints that were attached to the button’s onmouseover and onmouseout events?

What would YOU do to make sure that Marcy’s customers get cool interactive buttons AND helpful hints?

When you’ve got an idea, turn over to Chapter 4, and let’s see how to take your event handling skills to the next level (literally).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.19.244.187