Archive for the ‘Software’ Category

Simply JavaScript: The Three Layers of the Web

Tuesday, September 4th, 2007

“Once upon a time, there was … ‘A king!’ my little readers will say right away. No, children, you are wrong. Once upon a time there was a piece of wood …”
The Adventures of Pinocchio

You can do a lot without JavaScript. Using Hypertext Markup Language (HTML — throughout this article, we’ll refer to HTML and XHTML as just HTML. Which you choose is up to you, and doesn’t have a much to do with JavaScript. In case it matters to you, the HTML code we’ll present in this article will be valid XHTML 1.0 Strict), you can produce complex documents that intricately describe the content of a page — and that content’s meaning — to the minutest detail. In this chapter from the new Simply Javascript (you can also download this article, along with two others, as a PDF), I’ll show you that by using Cascading Style Sheets (CSS), you can present that content in myriad ways, with variations as subtle as a single color, as striking as replacing text with an image.

No matter how you dress it up, though, HTML and CSS can only achieve an animatronic monstrosity that wobbles precariously when something moves nearby. It’s when you wheel in the JavaScript that you really can breathe life into your Pinocchio, lifting you as its creator from humble shop clerk to web design mastery!

But whether your new creation has the graceful stride of a runway model, or the shuffling gait of Dr. Frankenstein’s monster, depends as much on the quality of its HTML and CSS origins as it does on the JavaScript code that brought it to life.

Before we learn to work miracles, therefore, let’s take a little time to review how to build web sites that look good both inside and out, and see how JavaScript fits into the picture.

Keep ‘em Separated

Not so long ago, professional web designers would gleefully pile HTML, CSS, and JavaScript code into a single file, name it index.html (or default.htm, if they had been brainwashed by Microsoft), and call it a web page. I’ve conceptualized this as something like Figure 1. You can still do this today, but be prepared for your peers to call it something rather less polite.

Figure 1. A single-file mess (click to view image)

Somewhere along the way, web designers realized that the code they write when putting together a web page does three fundamental things:

  • It describes the content of the page.
  • It specifies the presentation of that content.
  • It controls the behavior of that content.

They also realized that keeping these three types of code separate, as depicted in Figure 2, “Separation of concerns,” made their jobs easier, and helped them to make web pages that work better under adverse conditions, such as when users have JavaScript disabled in their browsers.

Computer geeks have known about this for years, and have even given this principle a geeky name: the separation of concerns.

Figure 2. The separation of concerns (click to view image)

Now, realizing this is one thing, but actually doing it is another — especially if you’re not a computer geek. I am a computer geek, and I’m tempted to do the wrong thing all the time.

I’ll be happily editing the HTML code that describes a web page’s content, when suddenly I’ll find myself thinking how nice that text would look if it were in a slightly different shade of gray, if it were nudged a little to the left, and if it had that hee-larious photocopy of my face I made at the last SitePoint office party in the background. Prone to distraction as I am, I want to make those changes right away. Now which is easier: opening up a separate CSS file to modify the page’s style sheet, or just typing those style properties into the HTML code I’m already editing?

Like behaving yourself at work functions, keeping the types of code you write separate from one another takes discipline. But once you understand the benefits, you too will be able to summon the willpower it takes to stay on the straight and narrow.

Three Layers

Keeping different kinds of code as separate as possible is a good idea in any kind of programming. It makes it easier to reuse portions of that code in future projects, it reduces the amount of duplicate code you end up writing, and it makes it easier to find and fix problems months and years later.

When it comes to the Web, there’s one more reason to keep your code separate: it lets you cater for the many different ways in which people access web pages.

Depending on your audience, the majority of your visitors may use well-appointed desktop browsers with cutting-edge CSS and JavaScript support, but many might be subject to corporate IT policies that force them to use older browsers, or to browse with certain features (like JavaScript) disabled.

Visually impaired users often browse using screen reader or screen magnifier software, and for these users your slick visual design can be more of a hindrance than a help.

Some users won’t even visit your site, preferring to read content feeds in RSS or similar formats if you offer them. When it comes time to build these feeds, you’ll want to be able to send your HTML content to these users without any JavaScript or CSS junk.

The key to accommodating the broadest possible range of visitors to your site is to think of the Web in terms of three layers, which conveniently correspond to the three kinds of code I mentioned earlier. These layers are illustrated in Figure 3, “The three layers of the Web.”

Figure 3. The three layers of the Web (click to view image)

When building a site, we work through these layers from the bottom up:

  1. We start by producing the content in HTML format. This is the base layer, which any visitor using any kind of browser should be able to view.
  2. With that done, we can focus on making the site look better, by adding a layer of presentation information using CSS. The site will now look good to users able to display CSS styles.
  3. Lastly, we can use JavaScript to introduce an added layer of interactivity and dynamic behavior, which will make the site easier to use in browsers equipped with JavaScript.

If we keep the HTML, CSS, and JavaScript code separate, we’ll find it much easier to make sure that the content layer remains readable in browsing environments where the presentation and/or behavior layers are unable to operate. This “start at the bottom” approach to web design is known in the trade as progressive enhancement.

Let’s look at each of these layers in isolation to see how we can best maintain this separation of code.

HTML for Content

Everything that’s needed to read and understand the content of a web page belongs in the HTML code for that page — nothing more, nothing less. It’s that simple. Web designers get into trouble when they forget the K.I.S.S. principle (Keep It Simple, Stupid) and cram non-content information into their HTML code, or alternatively move some of the page’s content into the CSS or JavaScript code for the page.

A common example of non-content information that’s crammed into pages is presentational HTML — HTML code that describes how the content should look when it’s displayed in the browser. This can include old-fashioned HTML tags like <b>, <i>, <u>, <tt>, and <font>:

<p>Whatever you do, <a href="666.html"><font color=”red”>don’t
click this link</font></a>!</p>

It can take the form of inline CSS applied with the style attribute:

<p>Whatever you do, <a href="666.html" style=”color: red;”>don’t
click this link</a>!</p>

It can also include the secret shame of many well-intentioned web designers: CSS styles applied with presentational class names:

<p>Whatever you do, <a href="666.html" class=”red”>don’t click
this link</a>!</p>

Presentational Class Names? If that last example looks okay to you, you’re not alone, but it’s definitely bad mojo. If you later decide you want that link to be yellow, you’re either stuck updating both the class name and the CSS styles that apply to it, or living with the embarrassment of a class named “red” that is actually styled yellow. That’ll turn your face yellow — er, red!

Rather than embedding presentation information in your HTML code, you should focus on the reason for the action — for example, you want a link to be displayed in a different color. Is the link especially important? Consider surrounding it with a tag that describes the emphasis you want to give it:

<p>Whatever you do, <em><a href=”evil.html”>don’t click this
link</a></em>!</p>

Is the link a warning? HTML doesn’t have a tag to describe a warning, but you could choose a CSS class name that conveys this information:

<p>Whatever you do, <a href="evil.html" class=”warning”>don’t
click this link</a>!</p>

You can take this approach too far, of course. Some designers mistake tags like <h1> as presentational, and attempt to remove this presentational code from their HTML:

<p class="heading">A heading with an identity crisis</p>

Really, the presentational information that you should keep out of your document is the font, size, and color in which a heading is to be displayed. The fact that a piece of text is a heading is part of the content, and as such should be reflected in the HTML code. So this code is perfectly fine:

<h1>A heading at peace with itself</h1>

In short, your HTML should do everything it can to convey the meaning, or semantics of the content in the page, while steering clear of describing how it should look. Web standards geeks call HTML code that does this semantic markup.

Writing semantic markup allows your HTML files to stand on their own as meaningful documents. People who, for whatever reason, cannot read these documents by viewing them in a typical desktop web browser will be better able to make sense of them this way. Visually impaired users, for example, will be able to use assistive software like screen readers to listen to the page as it’s read aloud, and the more clearly your HTML code describes the content’s meaning, the more sense tools like these will be able to make of it.

Best of all, however, semantic markup lets you apply new styles (presentation) and interactive features (behavior) without having to make many (or, in some cases, any!) changes to your HTML code.

CSS for Presentation

Obviously, if the content of a page should be entirely contained within its HTML code, its style — or presentation — should be fully described in the CSS code that’s applied to the page.

With all the work you’ve done to keep your HTML free of presentational code and rich with semantics, it would be a shame to mess up that file by filling it with snippets of CSS.

As you probably know, CSS styles can be applied to your pages in three ways:

inline styles:
<a href="evil.html" style=”color: red;”>
Inline styles are tempting for the reasons I explained earlier: you can apply styles to your content as you create it, without having to switch gears and edit a separate style sheet. But as we saw in the previous section, you’ll want to avoid inline styles like the plague if you want to keep your HTML code meaningful to those who cannot see the styles.

embedded styles:
<style type="text/css">
.warning {
color: red;
}

</style>
&#8942;
<a href=”evil.html” class=”warning”>

Embedded styles keep your markup clean, but tie your styles to a single document. In most cases, you’ll want to share your styles across multiple pages on your site, so it’s best to steer clear of this approach as well.

external styles:
<link rel="stylesheet" href="styles.css" />
&#8942;
<a href="evil.html" class=”warning”>
Example 1.1. styles.css

.warning {
color: red;
}

External styles are really the way to go, because they let you share your styles between multiple documents, they reduce the amount of code browsers need to download, and they also let you modify the look of your site without having to get your hands dirty editing HTML.

But you knew all that, right? We’re dealing with a JavaScript book, after all, so let’s talk about the JavaScript that goes into your pages.

JavaScript for Behavior

As with CSS, you can add JavaScript to your web pages in a number of ways.

You can embed JavaScript code directly in your HTML content:
<a href="evil.html" onclick=”JavaScript code here”>

You can include JavaScript code at the top of your HTML document in a <script> tag:
<script type="text/javascript"><!--//--><![CDATA[//><!--
JavaScript code here
//–><!]]></script>
&#8942;
<a href=”evil.html” class=”warning”>

CDATA? If you’re wondering what all that gobbledygook is following the <script> tag and preceding the </script> tag, that’s what it takes to legitimately embed JavaScript in an XHTML document without confusing web browsers that don’t understand XHTML (like Internet Explorer).

If you write your page with HTML instead of XHTML, you can get away with this much simpler syntax:
<script type="text/javascript">
JavaScript code here
</script>

You can put your JavaScript code in a separate file, then link to that file from as many HTML documents as you like:
<script type="text/javascript" src="script.js"></script>
&#8942;
<a href="evil.html" class=”warning”>
Example 1.2. script.js (excerpt)
JavaScript code here

Guess which method you should use.

Writing JavaScript that enhances usability without cluttering up the HTML document(s) it is applied to, without locking out users that have JavaScript disabled in their browsers, and without interfering with other JavaScript code that might be applied to the same page, is called unobtrusive scripting.

Unfortunately, while many professional web developers have clued in to the benefits of keeping their CSS code in separate files, there is still a lot of JavaScript code mixed into HTML out there. By showing you the right way to use JavaScript, we hope to help change that.

The Right Way

So, how much does all this stuff really matter? After all, people have been building web sites with HTML, CSS, and JavaScript mixed together for years, and for the majority of people browsing the Web, those sites have worked.

Well, as you come to learn JavaScript, it’s arguably more important to get it right than ever before. JavaScript is by far the most powerful of the three languages that you’ll use to design web sites, and as such it gives you unprecedented freedom to completely mess things up.

As an example, if you really, really like JavaScript, you could go so far as to put everything — content, presentation, and behavior — into your JavaScript code. I’ve actually seen this done, and it’s not pretty — especially when a browser with JavaScript disabled comes along.

Even more telling is the fact that JavaScript is the only one of these three languages that has the ability to hang the browser, making it unresponsive to the user.

Therefore, we’ll do our darnedest to show you the right way to use JavaScript, not just because it keeps your code tidy, but because it helps to keep the Web working the way it’s meant to — by making content accessible to as many people as possible, no matter which web browser they choose to use.

JavaScript Libraries

As I mentioned, one of the benefits of keeping different kinds of code separate is that it makes it easier to take code that you’ve written for one site and reuse it on another. Certain JavaScript maniacs (to be referred to from this point on as “people”) have taken the time to assemble vast libraries of useful, unobtrusive JavaScript code that you can download and use on your own web sites for free.

Throughout Simply Javascript, we build each of the examples from scratch — all of the JavaScript code you need can be found right there. Since there isn’t always time to do this in the real world, however, and because libraries are quickly becoming an important part of the JavaScript landscape, we’ll also look at how the popular JavaScript libraries do things whenever the opportunity presents itself.

Here are the libraries that we use in the book:

Not All Libraries are Created Equal Watch out for sites offering snippets of JavaScript code for you to copy and paste into your web pages to achieve a particular effect. There is a lot of free code out there, but not all of it is good. In general, the good libraries come in the form of JavaScript (.js) files that you can link into your pages unobtrusively, instead of pasting JavaScript directly into your HTML code. If you don’t feel confident to judge whether a particular JavaScript library is good or bad, ask for some advice in the SitePoint Forums, or just stick with the libraries I just mentioned — they’re all very good.

Let’s Get Started!

Enough preaching — you checked out this article to learn JavaScript, right? Clean HTML and CSS are nice and all, but it’s time to take the plunge into the third layer of the Web: behavior. The chapters of Simply Javascript that follow the one from which this article is reproduced deal in greater depth with this topic — and because we’re feeling generous, we’ve decided to throw them in for your delectation! So don’t forget to download this chapter as a PDF, as well as Chapter 2: Programming with JavaScript and Chapter 3: Document Access.

In Chapter 2, you’ll learn that as JavaScript is a programming language, you must get your head around the way computer programs work — which to some extent means learning to think like a computer — in order to use it most effectively. The simple concepts introduced in this chapter — statements, variables, expressions, loops, functions, and objects — are the building blocks for every JavaScript program you’ll ever write.

And Chapter 3? While certain people enjoy writing JavaScript code for its own sake, you wouldn’t want to run into them in a dark alley at night. As a well-adjusted web developer, you’ll probably want to use JavaScript to make changes to the contents of your web pages using the Document Object Model (DOM). Lucky for you, we wrote a whole chapter to show you how!

Then, of course, there’s more…

Get ready to start using some cool (and unobtrusive) JavaScript!

Nifty Navigation Using CSS

Tuesday, September 4th, 2007

Unless you limit yourself to one-page web sites, you’ll need to design navigation. In fact, navigation is among the most important parts of any web design, and requires a great deal of thought if visitors are to move around your site easily.

Making site navigation easy is one area in which CSS really comes into its own. Older methods of creating navigation tended to rely on lots of images, nested tables, and JavaScript — all of which can seriously affect the usability and accessibility of a site. If your site cannot be navigated using a device that doesn’t support JavaScript, for example, not only are you blocking users who have turned JavaScript off, but you’re also locking out text-only devices such as screen readers and search engine robots — they’ll never get past your home page to index the content of your site. If your design clients don’t care about accessibility, tell them their clunky menu is stopping them from achieving a decent search engine ranking!

CSS allows you to create attractive navigation that, in reality, is no more than text — text that can be marked up in such a way as to ensure that it’s both accessible and understandable by all those who can’t physically see your design, but still want to get to your content. In this chapter, we’ll look at a variety of solutions for creating CSS-based navigation. Some are suited to implementation on an existing site, to make it load more quickly, and boost its accessibility by replacing an old-fashioned, image-based navigation. Others are more suited to incorporation within a pure CSS layout.

Before you begin, you might want to download this article in PDF format, so you can use it offline, at your leisure. The PDF also includes other chapters from The CSS Anthology: 101 Essential Tips, Tricks and Hacks on using CSS with images, and accessibility and alternative devices.

But now, on with the show.

How do I style a structural list as a navigation menu?

For new sites, you’re likely to be trying to avoid using tables for layout, or using them only where absolutely necessary. Therefore, a navigation solution that doesn’t involve tables is useful; also, by eradicating table elements, you’ll find that your page contains far less markup.

Solution

A navigation system is simply a list of places that users can visit on the site. Therefore, an unordered list is the ideal way to mark up your navigation. The navigation in Figure 1 is marked up as a list, and styled using CSS, as you can see.

Creating navigation by styling a list (click to view image)
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” lang=”en-US”>
<head>
<title>Lists as navigation</title>
<meta http-equiv=”content-type”
content=”text/html; charset=utf-8″ />
<link rel=”stylesheet” type=”text/css” href=”listnav1.css” />
</head>
<body>
<div id=”navigation”>
<ul>
<li><a href=”#”>Recipes</a></li>
<li><a href=”#”>Contact Us</a></li>
<li><a href=”#”>Articles</a></li>
<li><a href=”#”>Buy Online</a></li>
</ul>
</div>
</body>
</html>
#navigation {
width: 200px;
}
#navigation ul {
list-style: none;
margin: 0;
padding: 0;
}
#navigation li {
border-bottom: 1px solid #ED9F9F;
}
#navigation li a:link, #navigation li a:visited {
font-size: 90%;
display: block;
padding: 0.4em 0 0.4em 0.5em;
border-left: 12px solid #711515;
border-right: 1px solid #711515;
background-color: #B51032;
color: #FFFFFF;
text-decoration: none;
}

Discussion

To create navigation based on an unordered list, first create your list, placing each navigation link inside a li element:

<ul>
<li><a href="#">Recipes</a></li>
<li><a href="#">Contact Us</a></li>
<li><a href="#">Articles</a></li>
<li><a href="#">Buy Online</a></li>
</ul>

Next, wrap the list in a div with an appropriate ID:

<div id="navigation">
<ul>
<li><a href="#">Recipes</a></li>
<li><a href="#">Contact Us</a></li>
<li><a href="#">Articles</a></li>
<li><a href="#">Buy Online</a></li>
</ul>
</div>

As Figure 2 shows, this markup looks fairly ordinary with the browser’s default styles applied.

A very basic, unstyled list (click to view image)

The first thing we need to do is style the container in which the navigation sits — in this case, #navigation:

#navigation {
width: 200px;
}

I’ve given #navigation a width. If this navigation system were part of a CSS page layout, I’d probably add some positioning information to this ID as well.

Next, we style the list:

#navigation ul {
list-style: none;
margin: 0;
padding: 0;
}

As Figure 3 illustrates, the above rule removes list bullets and the indented margin that browsers apply, by default, when displaying a list.

Viewing the list after indentation and bullets are removed (click to view image)

The next step is to style the li elements within #navigation, to give them a bottom border:

#navigation li {
border-bottom: 1px solid #ED9F9F;
}

Finally, we style the link itself:

#navigation li a:link, #navigation li a:visited {
font-size: 90%;
display: block;
padding: 0.4em 0 0.4em 0.5em;
border-left: 12px solid #711515;
border-right: 1px solid #711515;
background-color: #B51032;
color: #FFFFFF;
text-decoration: none;
}

Most of the work is done here, creating CSS rules to add left and right borders, remove the underline, and so on. The first property declaration in this rule sets the display property to block. This causes the link to display as a block element, meaning that the whole area of each navigation “button” is active when you move the cursor over it — the same effect you’d see if you used an image for the navigation.

Can I use CSS and lists to create a navigation system with subnavigation?

Sometimes, more than one navigation level is necessary — but is it possible to create multi-leveled navigation using styled lists in CSS?

Solution

The perfect way to display subnavigation within a navigation system is to create a sublist within a list. The two levels of navigation will be easy to understand when they’re marked up in this way — even in browsers that don’t support CSS.

To produce multi-level navigation, we create a nested list and style the colors, borders, and link properties of the new list’s items:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
<head>
<title>Lists as navigation</title>
<meta http-equiv="content-type"
content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="listnav_sub.css" />
</head>
<body>
<div id="navigation">
<ul>
<li><a href="#">Recipes</a>
<ul>
<li><a href="#">Starters</a></li>
<li><a href="#">Main Courses</a></li>
<li><a href="#">Desserts</a></li>
</ul>
</li>
<li><a href="#">Contact Us</a></li>
<li><a href="#">Articles</a></li>
<li><a href="#">Buy Online</a></li>
</ul>
</div>
</body>
</html>

#navigation {
width: 200px;
}
#navigation ul {
list-style: none;
margin: 0;
padding: 0;
}
#navigation li {
border-bottom: 1px solid #ED9F9F;
}
#navigation li a:link, #navigation li a:visited {
font-size: 90%;
display: block;
padding: 0.4em 0 0.4em 0.5em;
border-left: 12px solid #711515;
border-right: 1px solid #711515;
background-color: #B51032;
color: #FFFFFF;
text-decoration: none;
}
#navigation li a:hover {
background-color: #711515;
color: #FFFFFF;
}
#navigation ul ul {
margin-left: 12px;
}
#navigation ul ul li {
border-bottom: 1px solid #711515;
margin:0;
}
#navigation ul ul a:link, #navigation ul ul a:visited {
background-color: #ED9F9F;
color: #711515;
}
#navigation ul ul a:hover {
background-color: #711515;
color: #FFFFFF;
}

The result of these additions is shown in Figure 4.

The CSS list navigation containing subnavigation (click to view image)

Discussion

Nested lists are a perfect way to describe the navigation system that we’re working with here. The first list contains the main sections of the site; the sublist under Recipes shows the subsections within the Recipes category. Even without any CSS styling, the structure of the list is still clear and comprehensible, as you can see in Figure 5.

The navigation remaining logical without the CSS (click to view image)

The HTML that we use to mark up this list simply nests the sublist inside the li element of the appropriate main item:

<ul>
<li><a href="#">Recipes</a>
<ul>
<li><a href="#">Starters</a></li>
<li><a href="#">Main Courses</a></li>
<li><a href="#">Desserts</a></li>
</ul>
</li>
<li><a href="#">Contact Us</a></li>
<li><a href="#">Articles</a></li>
<li><a href="#">Buy Online</a></li>
</ul>

With this HTML, and without any changes to the CSS, the menu will display as shown in Figure 6, “The sublist taking on the styles of the main navigation”, where the li elements inherit the styles of the main menu.

The sublist taking on the styles of the main navigation (click to view image)

Let’s add a style rule for the nested list to communicate visually that it’s a submenu, and not part of the main navigation:

#navigation ul ul {
margin-left: 12px;
}

This rule will indent the nested list so that it’s in line with the right edge of the border for the main menu, as demonstrated in Figure 7.

The indented subnavigation (click to view image)

Let’s add some simple styles to the li and a elements within the nested list to complete the effect:

#navigation ul ul li {
border-bottom: 1px solid #711515;
margin: 0;
}
#navigation ul ul a:link, #navigation ul ul a:visited {
background-color: #ED9F9F;
color: #711515;
}
#navigation ul ul a:hover {
background-color: #711515;
color: #FFFFFF;
}

How do I make a horizontal menu using CSS and lists?

So far, we’ve dealt with vertical navigation — the kind of navigation that will most likely be found in a column to the left or right of a site’s main content area. However, site navigation is also commonly found as a horizontal menu close to the top of the document.

Solution

As Figure 8 shows, this type of menu can be created using styled lists in CSS. The li elements must be set to display inline so that each list item does not display on its own line.

Using CSS to create horizontal list navigation (click to view image)

Here’s the HTML and CSS that creates this display:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” lang=”en-US”>
<head>
<title>Lists as navigation</title>
<meta http-equiv=”content-type”
content=”text/html; charset=utf-8″ />
<link rel=”stylesheet” type=”text/css” href=”listnav_horiz.css” />
</head>
<body>
<div id=”navigation”>
<ul>
<li><a href=”#”>Recipes</a></li>
<li><a href=”#”>Contact Us</a></li>
<li><a href=”#”>Articles</a></li>
<li><a href=”#”>Buy Online</a></li>
</ul>
</div>
</body>
</html>

#navigation {
font-size: 90%;
}
#navigation ul {
list-style: none;
margin: 0;
padding: 0;
padding-top: 1em;
}
#navigation li {
display: inline;
}
#navigation a:link, #navigation a:visited {
padding: 0.4em 1em 0.4em 1em;
color: #FFFFFF;
background-color: #B51032;
text-decoration: none;
border: 1px solid #711515;
}
#navigation a:hover {
color: #FFFFFF;
background-color: #711515;
}

Discussion

To create the horizontal navigation, we start with a list that’s identical to the one we created for our vertical list menu:

<div id="navigation">
<ul>
<li><a href="#">Recipes</a></li>
<li><a href="#">Contact Us</a></li>
<li><a href="#">Articles</a></li>
<li><a href="#">Buy Online</a></li>
</ul>
</div>

We style the #navigation container to apply some basic font information, as we did with the vertical navigation. In a CSS layout, this ID would probably also contain some additional styles that determine the navigation’s position on the page:

#navigation {
font-size: 90%;
}

In styling the ul element, we remove the list bullets and default indentation applied to the list by the browser:

#navigation ul {
list-style: none;
margin: 0;
padding: 0;
padding-top: 1em;
}

The property that transforms our list from a vertical to a horizontal display is applied to the li element:
#navigation li {
display: inline;
}

After we set the display property to inline, the list looks like Figure 9.

Displaying the list menu horizontally (click to view image)

All that’s left for us to do is to style the links for our navigation:

#navigation a:link, #navigation a:visited {
padding: 0.4em 1em 0.4em 1em;
color: #FFFFFF;
background-color: #B51032;
text-decoration: none;
border: 1px solid #711515;
}
#navigation a:hover {
color: #FFFFFF;
background-color: #711515;
}

If you’re creating boxes around each link, as I have here, remember that, in order to make more space between the text and the edge of its container, you’ll need to add more left and right padding to the links. To create more space between the navigation items, add left and right margins to the links.

How do I create button-like navigation using CSS?

Navigation that appears to be composed of clickable buttons is a feature of many web sites. This kind of navigation is often created using images to which effects are applied to make the edges look beveled and button-like. Often, some JavaScript code is used to swap in another image, so the button appears to depress when the user holds the cursor over it or clicks on the image.
Is it possible to create such button-like navigation systems using only CSS? Absolutely!

Solution

Creating a button effect like that shown in Figure 10 is possible, and fairly straightforward, using CSS. The effect’s success hinges on your use of the CSS border properties.

Building button-like navigation with CSS (click to view image)

Here’s the code you’ll need:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
<head>
<title>Lists as navigation</title>
<meta http-equiv="content-type"
content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="listnav_button.css"
/>
</head>
<body>
<div id="navigation">
<ul>
<li><a href="#">Recipes</a></li>
<li><a href="#">Contact Us</a></li>
<li><a href="#">Articles</a></li>
<li><a href="#">Buy Online</a></li>
</ul>
</div>
</body>
</html>

#navigation {
font-size:90%
}
#navigation ul {
list-style: none;
margin: 0;
padding: 0;
padding-top: 1em;
}
#navigation li {
display: inline;
}
#navigation a:link, #navigation a:visited {
margin-right: 0.2em;
padding: 0.2em 0.6em 0.2em 0.6em;
color: #A62020;
background-color: #FCE6EA;
text-decoration: none;
border-top: 1px solid #FFFFFF;
border-left: 1px solid #FFFFFF;
border-bottom: 1px solid #717171;
border-right: 1px solid #717171;
}
#navigation a:hover {
border-top: 1px solid #717171;
border-left: 1px solid #717171;
border-bottom: 1px solid #FFFFFF;
border-right: 1px solid #FFFFFF;
}

Discussion

To create this effect, we’ll use the horizontal list navigation described in the section called “How do I make a horizontal menu using CSS and lists?” However, to create the button look, we’ll use different colored borders at the top and left than we use for the bottom and right sides of each button. By giving the top and left edges of the button a lighter colored border than we assign to the button’s bottom and right edges, we create a slightly beveled effect:

#navigation a:link, #navigation a:visited {
margin-right: 0.2em;
padding: 0.2em 0.6em 0.2em 0.6em;
color: #A62020;
background-color: #FCE6EA;
text-decoration: none;
border-top: 1px solid #FFFFFF;
border-left: 1px solid #FFFFFF;
border-bottom: 1px solid #717171;
border-right: 1px solid #717171;
}

We reverse the border colors for the hover state, which creates the effect of the button being pressed:

#navigation a:hover {
border-top: 1px solid #717171;
border-left: 1px solid #717171;
border-bottom: 1px solid #FFFFFF;
border-right: 1px solid #FFFFFF;
}

Try using heavier borders, and changing the background images on the links, to create effects that suit your design.

How do I create tabbed navigation with CSS?

Navigation that appears as tabs across the top of the page is a popular navigation choice. Many sites create tabs using images. However, this approach suffers from the problems associated with text contained in images, which we discussed in the section called “How do I replace image-based navigation with CSS?” However, it is possible to create a tab effect by combining background images and text styled with CSS.

Solution

The tabbed navigation shown in Figure 11 can be created by styling a horizontal list.

Using CSS to create tabbed navigation (click to view image)

Here’s the HTML and CSS that creates this effect:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” lang=”en-US”>
<head>
<title>Lists as navigation</title>
<meta http-equiv=”content-type”
content=”text/html; charset=utf-8″ />
<link rel=”stylesheet” type=”text/css” href=”tabs.css” />
</head>
<body id=”recipes”>
<div id=”header”>
<ul id=”tabnav”>
<li class=”recipes”><a href=”#”>Recipes</a></li>
<li class=”contact”><a href=”#”>Contact Us</a></li>
<li class=”articles”><a href=”#”>Articles</a></li>
<li class=”buy”><a href=”#”>Buy Online</a></li>
</ul>
</div>
<div id=”content”>
<h1>Recipes</h1>
<p>Lorem ipsum dolor sit amet, … </p>
</div>
</body>
</html>

body {
font: .8em/1.8em verdana, arial, sans-serif;
background-color: #FFFFFF;
color: #000000;
margin: 0 10% 0 10%;
}

#header {
float: left;
width: 100%;
border-bottom: 1px solid #8DA5FF;
margin-bottom: 2em;
}

#header ul {
margin: 0;
padding: 2em 0 0 0;
list-style: none;
}

#header li {
float: left;
background-image: url("images/tab_left.gif“);
background-repeat: no-repeat;
margin: 0 1px 0 0;
padding: 0 0 0 8px;
}

#header a {
float: left;
display: block;
background-image: url("images/tab_right.gif");
background-repeat: no-repeat;
background-position: right top;
padding: 0.2em 10px 0.2em 0;
text-decoration: none;
font-weight: bold;
color: #333366;
}

#recipes #header li.recipes,
#contact #header li.contact,
#articles #header li.articles,
#buy #header li.buy {
background-image: url("images/tab_active_left.gif");
}

#recipes #header li.recipes a,
#contact #header li.contact a,
#articles #header li.articles a,
#buy #header li.buy a {
background-image: url("images/tab_active_right.gif");
background-color: transparent;
color:#FFFFFF;
}

Discussion

The tabbed navigation approach I’ve used here is a basic version of Douglas Bowman’s Sliding Doors of CSS method, which is a tried and tested technique for creating a tabbed interface. The structure that I’ve given to the navigation menu is the same kind of simple unordered list that we’ve worked with so far, except that each list item is assigned a class attribute that describes the link it contains. We’ve also wrapped the entire list in a div with an id of header. The technique takes its name from the two images used to implement it — one overlaps the other, and the images slide apart as the text size increases.

You’ll need four images to create this effect: two to create the regular tab color, and two to use when the tab is the currently selected (highlighted) tab. The images I’ve used in this example are shown in Figure 12. As you can see, they’re far wider and taller than would generally be necessary for a tab?this provides plenty of space for the tab to “grow” if the user’s browser is configured to display text at a very large size.

The image files used to create the tabs (click to view image)

Here’s the basic list of navigation items:

<div id="header">
<ul id="tabnav">
<li class="recipes"><a href="#">Recipes</a></li>
<li class="contact"><a href="#">Contact Us</a></li>
<li class="articles"><a href="#">Articles</a></li>
<li class="buy"><a href="#">Buy Online</a></li>
</ul>
</div>

The first step is to style the container that surrounds the navigation. We’re going to give our header a simple bottom border for the purposes of this exercise, but on a real-world site this container may hold other elements in addition to our tabs (such as a logo or search field):

#header {
float: left;
width: 100%;
border-bottom: 1px solid #8DA5FF;
margin-bottom: 2em;
}

As you’ll have noticed, we float the header to the left. We’ll also float the individual list items; floating the container that houses them ensures that they remain contained once they’re floated, and that the border will display below them.

Next, we create a style rule for the ul element inside the header:

#header ul {
margin: 0;
padding: 2em 0 0 0;
list-style: none;
}

This rule removes the bullets and alters the margin and padding on our list — we’ve added two ems of padding to the top of the ul element. Figure 13 shows the results of our work so far.

Displaying the navigation after styling the /#c#/ul/#ec#/ element (click to view image)

Now we need to style the list items:

#header li {
float: left;
background-image: url("images/tab_left.gif");
background-repeat: no-repeat;
margin: 0 1px 0 0;
padding: 0 0 0 8px;
}

This rule uses the float property to position the list items horizontally while maintaining the block-level status of each. We then add the first of our “sliding door” images — the thin left-hand side of the tab — as a background image. A single-pixel right margin on the list item creates a gap between one tab and the next. Figure 14 shows that the left-hand tab image now appears for each tab.

The navigation tabs reflecting the new styles (click to view image)

Next, we style the links, completing the look of our tabs in their unselected state. The image that forms the right-hand side of the tab is applied to each link, completing the tab effect:

#header a {
float: left;
display: block;
background-image: url("images/tab_right.gif");
background-repeat: no-repeat;
background-position: right top;
padding: 0.2em 10px 0.2em 0;
text-decoration: none;
font-weight: bold;
color: #333366;
}

The results are shown in Figure 15.

Styling the navigation links (click to view image)

If you increase the text size in the browser, you can see that the tabs neatly increase in size too. In fact, they do so without overlapping and without the text protruding out of the tab — this is because we have used images that allow plenty of room for growth.

To complete the tab navigation, we need to highlight the tab that corresponds to the currently displayed page. You’ll recall that each list item has been assigned a unique class name. If we assign to the body element an ID that has a value equal to the value of each list item class, CSS can do the rest of the work:

<body id="recipes">

Although it looks like a lot of code, the CSS code that styles the tab matching the body ID is relatively straightforward. The images I’ve used are exact copies of the left and right images that we applied to the tabs, but they’re a different color, which produces the effect of one tab appearing to be highlighted.

Here’s the CSS:

#recipes #header li.recipes,
#contact #header li.contact,
#articles #header li.articles,
#buy #header li.buy {
background-image: url("images/tab_active_left.gif");
}

#recipes #header li.recipes a,
#contact #header li.contact a,
#articles #header li.articles a,
#buy #header li.buy a {
background-image: url("images/tab_active_right.gif");
background-color: transparent;
color: #FFFFFF;
}

With these rules in place, specifying an ID of recipes to our body will cause the Recipes tab to be highlighted, specifying contact will cause the Contact Us tab to be highlighted, and so on. The results of this work are shown in Figure 16.

Identifying a Useful Technique
The technique of adding an ID to the body element can be very useful. For example, you may have different color schemes for different sections of your site, to help the user identify which section they’re using. You can simply add the section name to the body element and make use of it within the style sheet, as we did in this example.

Highlighting the Contact Us tab (click to view image)

How do I create rollovers in CSS without using JavaScript?

CSS-based navigation can provide some really interesting effects, but there are still some effects that require the use of images. Is it possible to enjoy the advantages of text-based navigation and still use images?

Solution

It is possible to combine images and CSS to create JavaScript-free rollovers. This solution is based on a technique described at WellStyled.com. Here’s the code you’ll need:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” lang=”en-US”>
<head>
<title>Lists as navigation</title>
<meta http-equiv=”content-type”
content=”text/html; charset=utf-8″ />
<link rel=”stylesheet” type=”text/css” href=”images.css” />
</head>
<body>
<ul id=”nav”>
<li><a href=”#”>Recipes</a></li>
<li><a href=”#”>Contact Us</a></li>
<li><a href=”#”>Articles</a></li>
<li><a href=”#”>Buy Online</a></li>
</ul>
</body>
</html>

ul#nav {
list-style-type: none;
padding: 0;
margin: 0;
}
#nav a:link, #nav a:visited {
display: block;
width: 150px;
padding: 10px 0 16px 32px;
font: bold 80% Arial, Helvetica, sans-serif;
color: #FF9900;
background: url("peppers.gif“) top left no-repeat;
text-decoration: none;
}
#nav a:hover {
background-position: 0 -69px;
color: #B51032;
}
#nav a:active {
background-position: 0 -138px;
color: #006E01;
}

The results can be seen in Figure 17, but to enjoy the full effect I suggest you try it for yourself. Don’t forget to click on a link or two!

Using images to advantage in the completed menu (click to view image)

Discussion

This solution offers a means of using images in your navigation without having to resort to preloading lots of separate files.

The navigation has three states, but these states aren’t depicted using three separate images. Instead, we use one large image that contains images for all three states, as shown in Figure 18.

The pepper image containing images for all three rollover states (click to view image)

The navigation is marked up as a simple list:

<ul id="nav">
<li><a href="#">Recipes</a></li>
<li><a href="#">Contact Us</a></li>
<li><a href="#">Articles</a></li>
<li><a href="#">Buy Online</a></li>
</ul>

We control the display of the background image within the declaration block for the navigation links. However, because the image is far bigger than the area required for this element, we only see the yellow pepper at first:

#nav a:link, #nav a:visited {
display: block;
width: 150px;
padding: 10px 0 16px 32px;
font: bold 80% Arial, Helvetica, sans-serif;
color: #FF9900;
background: url("peppers.gif") top left no-repeat;
text-decoration: none;
}

When the :hover state is activated, the background image moves up the exact number of pixels required to reveal the red pepper. In this example, I had to move it by 69 pixels, but this figure will vary depending on the image that you use. You could probably work it out mathematically, or you could do as I do and simply increment the background position a few pixels at a time, until it appears in the right location on hover:

#nav a:hover {
background-position: 0 -69px;
color: #B51032;
}

When the :active state is activated, the background image shifts again, this time to display the green pepper when the link is clicked:

#nav a:active {
background-position: 0 -138px;
color: #006E01;
}

That’s all there is to it! The effect can fall apart if the user resizes the text in the browser to a larger font, which allows the edges of the hidden images to display. You can anticipate this eventuality to some degree by leaving quite a large space between each of the three images — keep this in mind when preparing your images.

Image Flickering in Internet Explorer
This technique sometimes causes the navigation to “flicker” in Internet Explorer. In my tests, this only tends to be a problem when the image is larger than the ones we’ve used here; however, if your navigation items flicker, a well-documented remedy is available.

How can I create pure CSS drop-down menus?

In the previous section, we learned to create image- and JavaScript-free rollovers. Can the same be achieved for drop-down menus?

Solution

The answer is yes … but the resulting menus don’t work in Internet Explorer 6! Nevertheless, Figure 19 illustrates this interesting technique, which will become more useful as Internet Explorer 7 gains market share.

Creating a CSS-only drop-down menu (click to view image)

Here’s the markup used for this example:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
<head>
<title>CSS Flyout menus</title>
<meta http-equiv="content-type"
content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="menus.css" />
</head>
<body>
<ul id="nav">
<li><a href="#">Starters</a>
<ul>
<li><a href="">Fish</a></li>
<li><a href="">Fruit</a></li>
<li><a href="">Soups</a></li>
</ul>
</li>
<li><a href="#">Main courses</a>
<ul>
<li><a href="">Meat</a></li>
<li><a href="">Fish</a></li>
<li><a href="">Vegetarian</a></li>
</ul>
</li>
<li><a href="#">Desserts</a>
<ul>
<li><a href="">Fruit</a></li>
<li><a href="">Puddings</a></li>
<li><a href="">Ice Creams</a></li>
</ul>
</li>
</ul>
</body>
</html>

And here are the style rules to implement this effect:

body {
font: 1em Verdana, Arial, sans-serif;
background-color: #FFFFFF;
color: #000000;
margin: 1em 0 0 1em;
}
#nav, #nav ul {
padding: 0;
margin: 0;
list-style: none;
}
#nav li {
float: left;
position: relative;
width: 10em;
border: 1px solid #B0C4DE;
background-color: #E7EDF5;
color: #2D486C;
font-size: 80%;
margin-right: 1em;
}
#nav a:link, #nav a:visited {
display: block;
text-decoration: none;
padding-left: 1em;
color: #2D486C;
}
* html #nav a {
width: 100%;
}
#nav ul {
display: none;
position: absolute;
padding: 0;
}
#nav ul li {
border: 0 none transparent;
border-bottom: 1px solid #E7EDF5;
border-top: .5em solid #FFF;
background-color: #F1F5F9;
font-size: 100%;
margin-bottom: -1px;
margin-top: 1px;
padding: 0;
}
#nav li:hover ul {
display: block;
}

Discussion

Though this attractive and easy effect will not work in Internet Explorer 6, it is supported by several other, newer browsers. This solution allows you to create a drop-down menu without using any JavaScript at all. The technique is based on the Suckerfish Dropdowns solution detailed on A List Apart.

The menus themselves are based on simple unordered lists. The top-level menu items consist of one main list; the items that fall under each main item are contained in nested lists:

<ul id="nav">
<li><a href="#">Starters</a>
<ul>
<li><a href="">Fish</a></li>
<li><a href="">Fruit</a></li>
<li><a href="">Soups</a></li>
</ul>
</li>
&#8942;

As you can see in Figure 20, when styles aren’t applied to the menu, the page displays as a logically structured, unordered list with subsections that are easy to spot.

Displaying lists logically in browsers that don’t support CSS (click to view image)

To begin with, we style the top-level menu, removing its list style. We also float the list items to the left so that they stack horizontally. The list items are given a position value of relative so that we can position our fly-out menus within them later on:

#nav, #nav ul {
&#8942;
list-style: none;
}
#nav li {
float: left;
position: relative;
width: 10em;
&#8942;
margin-right: 1em;
}

We coerce the links in the menu to display as blocks, so they fill the rectangular areas defined by the menu items. Internet Explorer 6 (and earlier) doesn’t recognize this; however, setting the width of each link to 100% ensures that our clickable region expands to fill the containing block.

#nav a:link, #nav a:visited {
display: block;
&#8942;
}
* html #nav a {
width: 100%;
}

Next, we style the nested lists that constitute our fly-out menus so that, by default, they are not displayed (display: none). We do, however, specify that absolute positioning is to be used when they are displayed, so that they don’t affect the flow of the rest of the document:

#nav ul {
display: none;
position: absolute;
&#8942;
}

To prevent our fly-out menu list items from being floated horizontally the way the main menu items are, we need to set their float property to none:

#nav ul li {
float: none;
&#8942;
}

Finally, we use the :hover pseudo-class to display the fly-out menu within any main menu item when the cursor is moved over it:

#nav li:hover ul {
display: block;
}

With these basic CSS rules in place, the menus display as shown in Figure 21.

Altering the menu display with the addition of basic CSS (click to view image)

This code initially sets the nested lists to display: none. When the user hovers the cursor over a main menu list item, the property of the nested list within that list item is set to display: block, and the menu appears. However, this approach doesn’t work in Internet Explorer, as in that browser the :hover pseudo-class works only on links — not on any other element.

The rest of the CSS simply applies visual styles to make the menus look good.

Falling Between the Cracks
When a fly-out menu opens, the user must move the cursor down to the fly-out menu items to select one. If, in this motion, the cursor moves outside of the list item that opened the fly-out menu, the menu will close immediately, as the :hover pseudo-class will no longer be in effect.

Looking at the style rules for this page, you can see that we use absolute positioning to display the nested list over the top of the rest of the page content without disturbing it.

In theory, we should be able to leave a little space between the top-level menu item and the fly-out menu simply by adding margin to the top of the list; however, in Internet Explorer 7 the fly-out menu will disappear if the cursor passes over a margin area, rendering the menu unusable. Instead, I’ve created the effect by applying a white border to the top of the menu.

I’ve also added a very small margin to the top of each list item, and a negative margin of the same amount to the bottom. This has the effect of shifting our menu down by one pixel — just enough to ensure that our white border doesn’t cover up the bottom of our top-level menu item.

#nav ul li {
border: 0 none transparent;
border-bottom: 1px solid #E7EDF5;
border-top: .5em solid #FFF;
background-color: #F1F5F9;
font-size: 100%;
margin-bottom: -1px;
margin-top: 1px;
padding: 0;
}

Accessibility Concerns
When you’re using any drop-down menu — with or without JavaScript — make sure that users who don’t see the full effect of the menus are still able to move around your site.

In the case of this example, users who don’t have CSS support will see the expanded nested lists, and will be able to navigate through the site. Anyone who uses a browser that doesn’t support the display of the submenus, such as Internet Explorer 6, will still be able to navigate so long as the pages to which the top-level menu items link contain links to all the pages in that section’s submenu.

Any menu system that prevents users whose browsers don’t support it from navigating the site is bad news.

Summary

This chapter has discussed a range of different ways in which we can create navigation using structurally sound markup, and provided examples that can be used as starting points for your own experiments.

On existing sites where a full redesign is not possible, introducing a CSS-based navigation system can be a good way to improve the site’s accessibility and load speed without affecting its look and feel in a big way.

Where to next? Download this article in PDF format, and you’ll also receive two other chapters:

  • Chapter 3, CSS and Images, which demonstrates the basics of working with images and answers common image-related questions
  • Chapter 8, Accessibility and Alternative Devices, which moves through the basics of separating content from presentation before dealing with questions of alternative style sheets and addressing users’ particular accessibility needs

And don’t forget to check out the Table of Contents for more on what’s in The CSS Anthology: 101 Essential Tips, Tricks and Hacks.

Developing with the Facebook Platform and PHP

Tuesday, September 4th, 2007

At the end of May this year, the Facebook team announced major changes to the package’s developer tools, known as the Facebook Platform. Although the platform itself had been available for several months prior to this release, a host of new features were announced at f8, the Facebook developer event in San Francisco. This launch generated a lot of press coverage — from the Wall Street Journal to TechCrunch. But the important question is: why should you care?

The face of Facebook (click to view image)

According to Alexa, Facebook is one of the top 20 sites on the Web, and it has some impressive statistics:

  • The site’s growth is around 3% per week, which equates to 100,000 new users per day.
  • 50% of registered users visit the site every day.
  • The site attracts more traffic than eBay: 40 billion page views per month, which equates to an average of 50 pages per user, per day.

Just looking at these statistics should start you thinking about the ways in which you can leverage this level of traffic to benefit your own web site. If you could tap into the Facebook userbase, you could very easily and quickly increase the audience’s awareness of your brand, product, service, or web site.

Let’s consider a real-world example. I’m currently working on welovelocal.com, a UK directory that allows its users to find and review businesses. While this isn’t necessarily a new idea, the site adds a social element whereby users can view reviews from their friends to find out about businesses that other users with similar interests are reviewing. And by leveraging Facebook, a site like this can significantly increase its exposure to a given user’s network of friends.

For example, if Stacy, a welovelocal user, writes a review about a restaurant, that review will be published to Stacy’s Facebook news feed. All of Stacy’s friends on Facebook will be able to see that she’s written a new review, and can click through to welovelocal to read it.

Can you see the potential?

You can work with the Facebook Platform in many ways, including creating apps that exist just within Facebook itself. However, I feel that the greatest potential lies with integrating Facebook into an existing site, and that’s what I’ll cover in this article.

The news feed is perhaps the most important element of the platform, as it adds a real viral element to any kind of notification you send out — being able to reach the entire network of friends for any of your users is certainly a great feature. But there are many other avenues by which content can be communicated to users. For example, you can:

  • Add a link to your own site from the left-hand menu bar of a user’s Facebook profile page, as shown below.

A link has been added to a Facebook sidebar (click to view image)

  • Add to a user’s profile a content box that contains whatever content you like. With welovelocal, we use this to display the user’s latest five reviews, complete with ratings and links back to the actual reviews on our site, as shown here.

A content box displaying a user’s last five reviews (click to view image)

  • Send requests to users to perform certain actions. For example, you could retrieve a list of your users’ friends, and send a request to all of them to add your app to their Facebook profiles.
  • Upload photos, create albums, get photos, and manage photos within Facebook. One use for this might be to access the photos a user has added to their Facebook account and pull them into your site, or to push photos that have been uploaded to your site back to Facebook.
How Do I Use It?

In this article, we’ll walk through the basics of using the Facebook platform using PHP 5. If you’re interested in integrating your site with Facebook using another language, there is plenty of information on the Facebook developers’ wiki:

I was fortunate (or unfortunate) to develop the welovelocal application prior to the official platform release in May. This meant that I had to write my own code to call the functions. There is an official PHP 5 library as well as an unofficial PHP 4 version (see the PHP link above) that you can probably use to get up and running more quickly and easily than I did. However, in order to gain a proper understanding of how the platform works, it’s worth looking at the raw interactions that take place.

First Steps

You must register for an API key before you can access the Facebook Platform. To do this, you’ll need to sign up for a Facebook account, then add the “Developer” application to your Facebook account. You can do so by following the very simple instructions at www.facebook.com/developers. Once it’s added, you’ll find that the Developer application is very much like a normal Facebook group, but it has an additional link near the top of the page called “My Applications” which, when clicked, will display a list of all the Facebook applications that you have registered.

Once you’ve registered, you need to generate a key. Click the Apply for another key link and you’ll be walked through the process of creating a Facebook application. There are a number of fields that you can provide optional information to, all of which are explained in the quick start guide on the Facebook Developers site.

Your application is actually now ready to be used, although it won’t do anything! Depending on what you want your application to do, your users may need to perform a number of steps to install your app into their Facebook accounts. The process usually consists of them clicking an Install link, then confirming the request, as shown here.

Adding an application to a Facebook account (click to view image)

Once the application is added, it will appear in the user’s news feed and on their mini-feed, both of which are viewable by all their friends — your first bit of free publicity!

Authentication

Your application is ready to be used, but of course you’ll want to provide some content for your user. The two most important features for web site owners are:

  • the ability to publish items to the news feed
  • the ability to add a profile box

Before you can use either of these pieces of functionality, you need to authenticate the current user with the Facebook platform.

Each call to the Facebook Platform API requires a session key that identifies the user who’s logged in and is using the system. To obtain this key, you must make a call to the Facebook API that redirects the user to log in to the Facebook web site and authorize the request.

One hurdle here is that this authorization provides a session key that only lasts for a certain period of time — around 24 hours. A key that didn’t expire would be much more useful. Fortunately, we can obtain such a key by following these two steps, which I’ll explain in more detail in a moment:

  1. First, ask the user to authorize your application so that it can access the user’s account on Facebook. This returns auth token 1, which generates a session key that expires after 24 hours.
  2. Then, ask the user to generate auth token 2, which they should then paste into a form on your web site. With this token in place, you’ll be able to generate a session key that never expires.

Once you have the final token, you can request a permanent session key by calling the facebook.auth.getSession function.

But first, allow me to elaborate on those two steps.

Step 1 - Obtaining Auth Token 1

From your web site, direct your user to Facebook using a URL appended with your API key, like this: www.facebook.com/login.php?api_key=APIKEY (where APIKEY should be replaced with your own API key). If the user is not currently logged in, they’ll be asked to do so.

The user will then be asked to accept any terms of service you set, and will be redirected to the callback URL that you specified when creating the application. This can be changed by editing your application through the Developer link in Facebook’s sidebar.

With the redirect in place, Facebook will append ?auth_token=TOKEN to the URL, using an actual authentication token. You can use this token with the facebook.auth.getSession function; it’s available as a GET variable in PHP.

However, because we want to get an infinite session, that auth token is actually irrelevant — we need to get another token that we can use to get a permanent session key. If we were not interested in an infinite session, this is where we would stop. We could use the auth token with the facebook.auth.getSession function below.

Step 2 - Obtaining Auth Token 2

Once your user has returned to your site after logging into Facebook, you’ll need to send them to www.facebook.com/code_gen.php?api_key=APIKEY. Back on the Facebook site, the user will be asked to generate a token that will be displayed to them. They must then copy and paste it into a form on your web site — it’s not passed through via GET/POST. It’s up to you to create a form that accepts this token from your user.

Once the user has submitted this second token to your site, you’ll need to call the facebook.auth.getSession function, passing the token as a parameter. This will finally return a session key that you can use continuously to authenticate that user; this key could, for example, be stored in the database alongside the user’s account for easy retrieval in the future.

It’s important to note that, should the user delete your application from their Facebook account, they’ll need to repeat this authentication process in order to use your Facebook application. You should therefore provide the option for the user to reset their Facebook integration and set it up again. If you’re storing the user’s session key in the database, this task would simply involve deleting that session key and taking the user through the two-step authentication process above.

Calling facebook.auth.getSession

Now that you have an authentication token, you’ll need to get yourself a session key for the current user. This key is passed to every other Facebook API call, to identify the user upon which your application is conducting an action.

Because we’re not using a library provided by Facebook, we’ll need to manually construct the HTTP query that we’ll send to Facebook, and write some code to process the response. With every call, you must provide three required values, as described on the Facebook web site:

  • method - The first parameter is the method name. The method must be one of those exposed by the API documentation, or the API will return error code 3 (with message Unknown method).
  • api_key - The vendor-specific API key corresponding to the site making the API call. This is the same key that we used in the login request, as provided to you when you registered your application.
  • sig - The signature for the method call.

The signature is generated as described by this pseudocode:

args = array of args to the request, formatted in arg=val pairs
sorted_array = alphabetically_sort_array_by_keys(args);
request_str = concatenate_in_order(sorted_array);
signature = md5(concatenate(request_str, secret))

Rather than having to do this manually every time you need to perform an HTTP query, I’ve written a short do_facebook_request() function that is available for download. This takes the optional parameters that are to be sent for a specific API function, as well as the name of that function. It constructs and sends the request, then returns the result:

do_facebook_request.php
<?php
/**
* Sends an API request to Facebook
*
* @param array $parameters Array of parameters to send
* @param string $method The API function to call
* @return array Returns array of data returned
*/
function do_facebook_request($parameters, $method)
{
if (empty($parameters) || empty($method))
{
return false;
}

// Build Facebook args
// http://developers.f8.facebook.com/documentation.php?v=1.0&doc=auth
$data['api_key'] = 'API KEY';
$data['method'] = $method;
$data['v'] = '1.0';

// Loop through and set as array
foreach ($parameters as $key => $value)
{
$data[$key] = $value;
}

// Sort
ksort($data);

$args = '';

foreach ($data as $key => $value)
{
$args .= $key.'='.$value;
}

$data['sig'] = md5($args.'secret');

// Get a Facebook session
$response = do_post_request('http://api.facebook.com/restserver.php', $data);

// Handle XML
$xml = simplexml_load_string($response);

return $xml;
}

/**
* Sends a POST request with necessary parameters
* Code based on http://netevil.org/node.php?nid=937
* We use HTTP here. See http://uk2.php.net/manual/en/wrappers.http.php
*
* @param string $url The URL to perform the POST on. Include http://
* @param array $data The data to POST in array format
* @param array $optional_headers Any HTTP headers. See http://www.php.net/manual/sv/function.header.php or http://www.faqs.org/rfcs/rfc2616
* @param string $method The method for the request. Defaults to POST
* @return string The response
*/
function do_post_request($url, $data, $optional_headers = NULL, $method = ‘POST’)
{
// Just defining some parameters for the request here
// See http://uk2.php.net/manual/en/wrappers.http.php#AEN268663 for additional context options
$params = array(’http’ => array(’method’ => $method, ‘content’ => http_build_query($data)));

if ($optional_headers !== NULL) // Add in any additional headers
{
$params[’http’][’header’] = $optional_headers;
}

// Makes it easier to add additional parameters such
// as any optional HTTP headers as set above
$context = stream_context_create($params);

$fp = @fopen($url, ‘rb’, false, $context);

if (!$fp)
{
return false;
}

$response = @stream_get_contents($fp);

if ($response === false)
{
fclose($fp);
return false;
}

fclose($fp);

return $response;
}
?>

The code is part of a class I wrote for the welovelocal application, and is based on the code provided in Wez Furlong’s blog. You’ll need to replace the API_KEY on line 20 with your own key, as well as the secret on line 40 to generate the signature. The secret is a string generated by Facebook, and is displayed underneath your API key on the My Applications section of the Developer application within Facebook.
Here’s an example in which we’re calling the do_facebook_request function:

$xml = do_facebook_request(array('auth_token' => $token), 'facebook.auth.getSession');

After the request has been processed, the $xml variable will contain something that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<auth_getSession_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd">
<session_key>5f34e11bfb97c762e439e6a5-8055</session_key>
<uid>8055</uid>
<expires></expires>
</auth_getSession_response>

This is the session_key that you can store and use for all subsequent requests. See the auth.getSession documentation for detailed information.

The User Profile Box

Displaying contributed content as part of users’ profiles is a great way for users to show off the work they’ve done on your web site. With welovelocal, we let people list their latest reviews on their profile, so that their friends can read what they’ve been writing. This concept could be extended for photos, news articles, game high scores — almost anything, really.

Facebook uses its own subset of the HTML language to allow you to put rich content in a user’s profile without opening security issues or destroying the layout of a site. This markup language is called FBML — Facebook Markup Language — and is well documented on the Facebook developer web site.

Pushing the content to a profile is very simple — you generate the FBML within your code, then send it to the API, which makes the content live. The function is called facebook.profile.setFBML and requires you to provide both the session key we obtained earlier and the actual FBML you want to display.

Creating FBML is very straightforward and is well explained in the official documentation, so I won’t go into any detail here. You can use the FBML test console to see a preview of what the output will look like.

Once you’ve written the FBML, you can use the do_facebook_request() function to send it to Facebook’s API:

$xml = do_facebook_request(array('session_id' => 'idhere', 'call_id' => microtime(), 'markup' => $markup), 'facebook.profile.setFBML');

You’ll notice a call_id as the final parameter that we passed to the do_facebook_request function. This is a unique ID for the request. Facebook recommends that you use the current time in milliseconds, which is available via the microtime() function.

And that’s it — the profile content will appear immediately!

News Feeds

The news feed in Facebook is a summary of everything that’s going on with your friends — it’s something of a history of their interactions with the site. Through a friend’s news feed, you can:

  • find out what they’re doing with status updates (like Twitter)
  • learn who they’ve become friends with
  • see when they’ve updated their profiles

… as well as almost anything else that happens to them on Facebook. I’m sure you’ll agree that being able to post items to all of a user’s friends is a great way to publicize activity that’s occurring on your own web site.

You can publish a news item to the feed of a single user, or to the feeds of all the friends of a specific user. Next up, we’re going to look at the latter task — using the feed.publishActionOfUser function — as this is the most useful for notifying people about things that are happening on your own site.

While the feed.publishActionOfUser function allows you to send up to four images (which is ideal for sites that use graphical content), to keep things simple, I’ll keep this example to the simple task of sending text.

When sending a news item you must specify a title (max. 40 characters), but you can also optionally provide body text. The title will be displayed in bold, and the body text in regular paragraph styling. The body text is usually used to elaborate on the details contained in the title.

Facebook allows the use of certain tags in the title and body. These tags allow you to display context-sensitive information, such as the name of the user and a link to the profile. So, if I were to send the following request to post information to my friends:

<fb:userlink uid="profileowner"/> wrote a new review.

It would show up as:

David Mytton (Network Name) wrote a new review.My name would be linked to my Facebook profile, and the Network Name would be replaced with the network through which the person viewing the news feed knows me (for example, university name, club name, or the like).

To prevent spamming, Facebook imposes limits on the number of times you can send out news items. This is explained in detail in the developer documentation.

As we saw earlier, you can also use the do_facebook_request function to send out a news feed, like so:

$params['call_id'] = microtime();
$params['session_id'] = 'idhere';
$params['title'] = '<fb:userlink uid="profileowner"/> wrote a new review';
$params['body'] = '<a href="http://www.welovelocal.com/business/'.$business['url_company'].'/#r'.$review_id.'">Read the full review...</a>';
do_facebook_request($params, 'facebook.feed.publishActionOfUser');

Spreading your Wings

We’ve touched on just a few of the key Facebook Platform functions in this article, but there are plenty of other features that you could utilize to push more content out to Facebook.

User Data - Documentation

Once you’ve authenticated the user, you can grab almost all of their profile data (though the data available may be limited depending on their privacy settings). Of course, one should use this data responsibly — one approach that comes to mind is to use it to pre-populate a lot of the fields on your own site, to save the user having to enter the same data twice.

Events - Documentation

As any given user tends to connect with many friends on Facebook, the site is often used to organize social events. The Facebook API allows you to tap into this and return a list of all the events that a user can see, based on certain criteria. The criteria by which you can filter this data include start and end dates, and whether the user has indicated that they will attend the event.

You could use this feature to present a calendar to your users, so that they can plan other events around other commitments they have in place with their friends.

Groups - Documentation

Similar to the ways in which you can use events data, you can use the Facebook API to find out which groups a user belongs to, and retrieve a list of members of those groups. This could be useful to combine with the notifications API, for example, to send requests to all users in a group to join your web site. Of course, this approach could be seen as spamming, so you would definitely need to ensure that the content you broadcast is relevant.

Photo Uploads - Documentation

Facebook has over 60 million photos uploaded every week, and 160TB of photo storage is currently available, which makes it an extremely popular way to share photos. Using the API, you can:

  • create a new album to store photos
  • retrieve a list of the existing albums, to choose which one to upload photos to
  • upload photos to the site
  • retrieve photos from a specific album, or from all photos across the entire site to which the current user has access

This means that you could present a user with a list of their Facebook photos, and provide them with the ability to display them on your own site. They could also do the reverse: copy photos from your site to Facebook, thereby allowing all their friends to see them.

Summary

This article looked at some of the ways in which you can integrate your web site with Facebook. Whether you choose to utilize only one small aspect of the Web’s fastest growing community, or embrace it with open arms, the Facebook API is a powerful tool both to enhance the experience for existing users, and to attract new users by driving traffic to your site

Easy Ajax with jQuery

Tuesday, September 4th, 2007

Ajax is changing web applications, giving them a responsiveness that’s unheard of beyond the desktop. But behind all the hype, there’s not much to Ajax — (X)HTML, JavaScript, and XML are nothing new, and in this tutorial, I’ll show you how to simplify the process of adding Ajax to your application even further with the help of jQuery, a popular JavaScript library.

What’s Ajax?

You’ve probably heard about Ajax before, or at least used an Ajax-based application — Gmail, for instance. Quite simply, Ajax is a technique for handling external data through JavaScript asynchronously, without reloading the entire page. SitePoint offers a good introduction to Ajax. Jesse James Garrett is credited with coining the term in this article.

Unfortunately, in-depth tutorials on practical ways to enter the world of Ajax are few and far between. To add to the problem, the XMLHttpRequest class used by Ajax isn’t very easy for beginning web developers to use. Luckily, a number of JavaScript libraries offer an easier way. Today I’ll show you how jQuery — one of these libraries — allows you to easily add Ajax to your application.

What’s jQuery?

jQuery is another mature JavaScript library that offers some features that the others do not. Admittedly, it’s not exactly as lightweight as some of the other offerings: jQuery comes in at 19kb, while moo.fx is only 3kb. You can read more about jQuery at The JavaScript Library World Cup for a comparison of a few other JavaScript libraries that offer similar functionality.

Assumed Knowledge

To complete this tutorial, you’ll need some basic JavaScript knowledge. If you know any C-style languages, you’ll get the hang of JavaScript in no time. Just think curly braces, function declarations, and optional semicolons at the end of each line (they’re not optional with jQuery, though). If you’re keen to get started with JavaScript, see this excellent, concise JavaScript tutorial designed for programmers. Also, since we’re talking about web applications, a basic knowledge of HTML is required.

jQuery 101

Let’s walk through a quick introduction to jQuery. To be able to use it in your pages, you’ll first need to download the library. You can download the latest version — 1.1.2 at the time of writing. jQuery’s methodology is simple: find things, do stuff. We select elements from the document (via the DOM) using the jQuery function, aliased as $(). This handy function acts just like document.getElementById(), except that instead of only supporting IDs, it supports CSS selectors and some XPath selectors; and, instead of returning one element, it can return an array of elements. Okay, so maybe a better description of $() is that it’s like document.getElementById() on steroids.

We then use functions to perform actions on our selections. For example, to append the text “Hello World!” to all divs with the class 'foo', then set the color to red, we’d use the following code:

$("div.foo").append("Hello World!").css("color","red");

Easy! Normally, this task would require two lines of code, like so:

$("div.foo").append("Hello World!");
$("div.foo").css("color","red");

jQuery’s chainable methods allow us to write much more compact code than other JavaScript libraries. There are functions in jQuery that don’t need an object, as they work independently, and many of the Ajax functions fall into this group. For example, the post function, which we will soon make use of, is called by typing $.post(parameters). For more jQuery functions, check the online documentation or visualjquery.com.

Example 1 - Our First Ajax Application

As an example, we’re going to make an interactive concept generator. Basically, this involves our selecting two terms at random from a list, then combining them to create a phrase. For this exercise, we’ll use web 2.0 buzzwords (’Mashup’, ‘Folksonomy’, ‘Media’ and so on), and normally we’d fetch these terms from a flat file. To save you from downloading every single combination (or at least every element) in JavaScript, we’re going to generate it on the fly at the server end, and fetch it for the client with jQuery. jQuery integrates perfectly with normal JavaScript, so you’ll find it an easy task to work it into your code.

Server-side Code (PHP)

To keep it simple, we’ll use the basic code below to create our concept generator. Don’t worry about how it works, just look at what it does: it outputs a randomised quote. Note that this code doesn’t output XML — it merely outputs raw text:

<?php
header("Cache-Control: no-cache”);
// Ideally, you’d put these in a text file or a database.
// Put an entry on each line of ‘a.txt’ and use $prefixes = file(”a.txt”);
// You can do the same with a separate file for $suffixes.
$prefixes = array(’Mashup’,'2.0′,’Tagging’,'Folksonomy’);
$suffixes = array(’Web’,'Push’,'Media’,’GUI‘);
// This selects a random element of each array on the fly
echo $prefixes[rand(0,count($prefixes)-1)] . ” is the new ”
. $suffixes[rand(0,count($prefixes)-1)];
// Example output: Tagging is the new Media
?>

Here, I’ve used the Cache-Control header response because Internet Explorer has a habit of caching pages that have the same URL, even if the content between the pages differs. Obviously, that defeats the purpose of our script — the production of a new quote on every load. We could have used jQuery to include a random number in the URL that would then be discarded, but it’s easier to address this caching issue on the server side than the client side.

Client-side Code (HTML)

Let’s start creating the HTML for the front end, then work our Ajax into it. All we need on the page is a button that users can click to request another quote, and a div into which we’ll put the quote once we’ve received it from the server. We’ll use jQuery to select this div and load the quote into it, and we’ll reference the div by its id. If we wanted to, we could use jQuery to load the quote into multiple elements, with the help of a class, but an id is all we need for now. Let’s make this the content of our body element:

<input type="submit" id="generate" value="Generate!">
<div id="quote"></div>

We can put the quote itself inside the div. Normally, we’d have a lengthy onSubmit event for the button (the input with the id 'generate'). Sometimes, we’d have an onSubmit event handler that called a JavaScript function. But with jQuery, we don’t even need to touch the HTML — we can separate behaviour (the event handler) from the structure (the page HTML) with ease.

Client-side Code (jQuery)

It’s time to bring our back end together with our front end using jQuery. I mentioned earlier that we can select elements from the DOM with jQuery. First, we have to select the button and assign an onClick event handler to it. Within the code for this event, we can select the div and load the content of our script into it. Here’s the syntax for the click event handler:

$("element expression").click(function(){
// Code goes here
});

As you probably already know, if we were to select this element in CSS, the # would identify that we were making our selection using the element’s id attribute. You can use exactly the same syntax with jQuery. Therefore, to select the button with the id 'generate' (which we gave it above), we can use the element expression #generate. Also, be aware that this syntax defines our event handler as an anonymous function within the event itself.

Mark Wubben’s JavaScript Terminology page offers a great explanation of anonymous functions, if you’d like to know more.

We’re going to use one of jQuery’s higher level Ajax functions, load(). Let’s assume that our generator script is saved as script.php. Let’s integrate it with our client side with the help of the load() function:

$("#generate").click(function(){
$("#quote").load("script.php");
});

That’s it: three lines of code, and we have fully functioning Ajax random quote generator! Well, almost.

The problem with JavaScript is that code that’s not within a function is executed as soon as the browser reaches it during rendering — not once the page has finished rendering. As such, this code will try to attach to an element that has not yet loaded. Normally, we’d use window.onload to deal with this issue. However, the limitation with that approach is that window.onload is called once everything has finished loading — images and all. We’re not interested in waiting for those images — it’s just the DOM that we want access to.

Fortunately, jQuery has $(document).ready(), which, as its name suggests, is executed when the DOM is ready to be manipulated.

The Complete Code

Here’s the complete code, including the $(document).ready wrapper and some basic HTML and CSS:

<html>
<head>
<title>Ajax with jQuery Example</title>
<script type="text/JavaScript" src="jquery.js"></script>
<script type="text/JavaScript">
$(document).ready(function(){
$("#generate").click(function(){
$("#quote p").load("script.php");
});
});
</script>
<style type="text/css">
#wrapper {
width: 240px;
height: 80px;
margin: auto;
padding: 10px;
margin-top: 10px;
border: 1px solid black;
text-align: center;
}
</style>
</head>
<body>
<div id="wrapper">
<div id="quote"><p> </p></div>
<input type="submit" id="generate" value="Generate!">
</div>
</body>
</html>

This code is also included in this downloadable zip file. Remember, this code assumes the jQuery library has been saved as jquery.js in the same folder as the PHP script and the HTML front end. Now that you’re familiar with jQuery, let’s move on to something more complicated: form elements and XML handling. This is true Ajax!

Example 2 - Chat with jQuery

To demonstrate the true power of jQuery, we’re going to make a fully featured Ajax chat application. This will allow users to post messages, and automatically update itself — all without any page refreshes. As we’re now dealing with a slightly more complex application, I’ll also take you deeper into jQuery, demonstrating other handy functions.

First, we’ll plan out the application. We won’t need much for this app — a front end, a back end, and the jQuery library. However, there will be a fair bit of code for both the back and front ends of the app, so our basic plan will let you know what to expect from the system.

Planning the Server Side

The back end of our application needs to process message submissions and output the messages. With this in mind, let’s put together a rough outline of the back-end code:

  • connect to database
  • if a message was submitted
    • insert message into database
    • delete old messages
  • fetch messages from the database and display as XML

As you can see, it’s all very simple and straightforward. You can use this plan as a guide if you have to write a back end in another language.

Planning the Client Side

The front end has to call the back end using Ajax, similarly to the approach we used in the first example. It has to handle the submission of the message-posting form, and update the chat window with newly submitted messages at regular intervals. However, we’re going to add another feature here — we’ll use the current UNIX timestamp to determine which messages have already been downloaded, and only fetch the new messages, reducing bandwidth usage and server load. Here’s a rough outline of the front-end code:

  • on page load
    • set current timestamp to 0 (all messages will be posted after this, i.e. all messages will be fetched)
    • call function to fetch new messages
  • function: fetch new messages
    • send request to server using POST
    • call function to parse XML response
    • add a timer to call this function after a second (increase frequency if server load is too high)
  • function: parse XML of new messages
    • set current timestamp as specified in the XML
    • if status code returned is ‘2′, no new messages, so end the function call
    • else, for each message in the response, add this to the top of the message window in this format:
      • author: message
  • on form submit:
    • send request to server using POST, specifying:
      • author name (user-specified)
      • message text (user-specified)
      • action noting that this is a post request
      • timestamp of the last request to the server
    • empty content of the message input box so that the user can start typing another message
    • call function to parse XML response (so that message posted is visible immediately)

This plan may seem far more complex than the back end, but thanks to jQuery, the code involved is fairly short.

Planning the Database

We’ll use a MySQL database to store the messages (although any SQL database will work, with a few tweaks to the code). We need a table with four columns: a column for the id of each message, two text columns to store the author of the message and the message itself, and a numerical timestamp column for our UNIX timestamps. Here’s the query that creates the table:

CREATE TABLE `messages` (
`id` int(7) NOT NULL auto_increment,
`user` varchar(255) NOT NULL,
`msg` text NOT NULL,
`time` int(9) NOT NULL,
PRIMARY KEY  (`id`)
);

Because we can’t tell what length the message will be, we’ll use a text field for now.

Server-side Code (XML)

In building the back end, let’s first decide what the back end should output (to determine the interface between the back end and front end), and work backwards from there. Here’s a simple XML structure:

<?xml version="1.0"?>
<response>
<status>1</status>
<time>1170323512</time>
<message>
<author>John Citizen</author>
<text>Hello world!</text>
</message>
<message>
<author>John Citizen</author>
<text>Hello world again!</text>
</message>
</response>

Notice that I’ve added the tag 'status', with the value of '1'. As I mentioned above, a status code of 1 will represent a successful request with new messages, 2 as successful without new messages. Each instance of the message tag includes the author and his or her message.

Server-side Code (PHP)

Now, to the back end. I’ll have to do this in PHP, but because the output is XML you can write the back end in any language — Perl, ASP, whatever you like. Let’s start it logically by defining some configuration values so that we can easily change them later. We need database connection details, the number of messages we want to store in the database (databases can handle thousands of rows, so this figure can be set fairly high), and the number of messages to display when the user enters the chat. Here’s the code:

$dbhost = "localhost“;
$dbuser = “root”;
$dbpass = “”;
$dbname = “chat”;
$store_num = 10;
$display_num = 10;

Now we need to get on to the basics of the back end itself. A database connection is required, but we also need to make sure that Internet Explorer doesn’t cache the request, and that the output is treated as XML. To make sure we’re able to identify any errors in the code, we’ll set error reporting to “all errors”. And to easily work with the request data, we’ll set a variable for every parameter in the request; each variable will take as its value the value of the request parameter. These few lines do the trick:

error_reporting(E_ALL);
header("Content-type: text/xml");
header("Cache-Control: no-cache");
$dbconn = mysql_connect($dbhost,$dbuser,$dbpass);
mysql_select_db($dbname,$dbconn);
foreach($_POST as $key => $value)
$$key = mysql_real_escape_string($value, $dbconn);

The foreach line looks through all the POST data, and creates a variable for every parameter and assigns it a corresponding value (e.g. path/to/file.php?variable=value would set $variable to "value"). This simplifies the process of grabbing request data, as we don’t have to specify it manually.

Next we get to the main functionality. It’s at this point that we handle the insertion of messages into the database, and the retrieval of the latest few messages based on the number of messages to be displayed, as defined in $display_num. I mentioned when we planned the front end that we would specify an action stating that a message was being submitted. We now need to check for this action — let’s assign the parameter 'action' a value of 'postmsg' to specify that we’re performing this check and insert the data as a new row in the database; we’ll insert the current UNIX timestamp in the database while we’re at it.

However, we also need to clean out the database. Depending on your database space limits, you may want to restrict the number of posts stored. Generally, logging of messages is frowned upon, so I’ve decided to store ten messages by default. We’ll use a function to grab the id of the last inserted row, and determine the rows to delete based on the value of that id. For example, if we insert the eleventh message, we’ll subtract the number of stored messages (10) from the id of the latest one (11) which gives us the id threshold (in this case, 1). We can then delete all messages that have an id equal to or less than that threshold, which in this example would result in us deleting the first message. And, thanks to SQL, we can do this all in one query.

Here’s the snippet that checks for the 'postmsg' action, inserts the message into the database, and cleans it out on the fly as well:

if(@$action == "postmsg")
{
mysql_query("INSERT INTO messages (`user`,`msg`,`time`)
VALUES ('$name','$message',".time().")");
mysql_query("DELETE FROM messages WHERE id <= ".
(mysql_insert_id($dbconn)-$store_num),$dbconn);
}

Developers using other server side technologies should be able to write equivalent code easily enough. Notice that we call the time function to grab the current UNIX timestamp. We can safely assume that the value that time returns will probably not change during script execution (even on a slow server, this script executes in under one hundredth of a second). So when we return a timestamp to the front end later, we can just call the time function again and the value should still be reliable.

The code that’s left handles the job of fetching the latest messages from the database and outputting them as XML. This is where the XML I outlined above comes into play. However, the bulk of the code lies in the MySQL query. We utilize the power of SQL to handle most of the processing tasks, so that script execution time isn’t affected. Here are the requirements for our SQL query:

  • It should fetch only the author and text of each message.
  • It should only fetch messages that have not been downloaded before — the client has a timestamp of the latest request, so this timestamp can be inserted into the SQL query.
  • It should order the messages so that the latest comes last, allowing them to be output in reverse order.
  • It should limit the number of messages fetched to the number defined in the configuration.

Anyone who’s familiar with SQL will agree that this is all fairly simple stuff. For the rest of us, here’s the code that does the trick. First, the query:

$messages = mysql_query("SELECT user,msg
FROM messages
WHERE time>$time
ORDER BY id ASC
LIMIT $display_num",$dbconn);

The rest of the code is elementary. If no results are returned, set the status code to 0; otherwise, set it to 1. Output the initial XML, the XML for each message, and the final XML. That’s all! Here’s the code:

if(mysql_num_rows($messages) == 0) $status_code = 2;
else $status_code = 1;

echo "<?xml version=\"1.0\"?>\n";
echo "<response>\n";
echo "\t<status>$status_code</status>\n";
echo "\t<time>".time()."</time>\n";
while($message = mysql_fetch_array($messages))
{
echo "\t<message>\n";
echo "\t\t<author>$message[user]</author>\n";
echo "\t\t<text>$message[msg]</text>\n";
echo "\t</message>\n";
}
echo "</response>";

The final code is all in the attached zip file, so don’t worry about copying this into your text editor. Now that the back end is finished, we can move on to the fun work — the HTML and jQuery!

Client-side Code (HTML)

Before we head into the jQuery, we need to prototype the HTML of the page. This way, when we have to work out which elements we are selecting to fetch or update using jQuery, we know what to do. We won’t need much: a wrapper div, a paragraph for the messages, and a form with fields for the user’s name and message, along with a Submit button. A briefly displayed loading message would add a final touch — we can remove this at the appropriate time using jQuery. Here’s the HTML:

<div id="wrapper">
<p id="messagewindow"><span id="loading">Loading...</span></p>
<form id="chatform">
Name: <input type="text" id="author" />
Message: <input type="text" id="msg" />
<input type="submit" value="ok" /><br />
</form>
</div>

Client-side Code (jQuery)

Now, on to the jQuery front end. First, we need to declare the timestamp of the current message as 0, and call the function that loads the messages from the server:

timestamp = 0;
updateMsg();

Next, we’ll write the code for the form submission. jQuery allows us to add an event hook for the form’s submit event, as though we were adding an onSubmit event within the HTML itself, except that we don’t have to touch the HTML. Here’s the submit event:

$("form#chatform").submit(function(){ /* Code */ });

Here we’re using CSS selector syntax to refer to the form element with an id of 'chatform'. As soon as we’re into the form submission code, we can fire off a POST request to the server using jQuery’s $.post. Within the call to $.post, we can select the values of the form elements on the page on the basis of their ids, as we determined earlier. With this in mind, we can dive into our Ajax call:

$.post("backend.php“,{ message: $(”#msg”).val(),
name: $(”#author”).val(), action: “postmsg”, time: timestamp }, function(xml) {

Notice that the array of parameters to be passed in the request is enclosed with curly braces. If you have more parameters, simply separate them with commas and use the format presented here, JSON-style. You can also use jQuery’s Ajax functions to send a GET request that expects a JSON-style response, and have jQuery convert the response text into an easy-to-use format. Bear in mind, though, that this capability is only available for the GET request type, not the POST request type we use for our chat system. As such, we’ll stick with plain XML for the moment.

Now, let’s look at handling the XML response. Since we’re all for code reuse, we’ll create a function that handles the XML and call it now:

addMessages(xml);

We’ll write this function later so that we can finish off the form submission event code. The code we’ve written so far is all we need for our $.post callback function, so we can close it off and add a return false; line. This line fails using the standard browser form submission error code. The browser doesn’t send the user to another page to submit the form — we’ve already handled the form submission, so the browser doesn’t need to. Here’s the event code in its entirety:

$("form#chatform").submit(function(){
$.post("backend.php",{
message: $("#msg").val(),
name: $("#author").val(),
action: "postmsg",
time: timestamp
}, function(xml) {
addMessages(xml);
});
return false;
});

Now, let’s get back to the addMessages() function, which handles the response xml. It’s quite simple, making use of jQuery’s DOM manipulation and traversing functions. Remember that I mentioned the status code before? Now’s the time to handle it:

if($("status",xml).text() == "2") return;

I haven’t mentioned context in jQuery yet. The XML in this function call tells jQuery to look not inside the document HTML, but in the XML that the server sent us.

That line of code checks for a status code of 2, representing a successful request that resulted in us having no new messages to add to the window. The 'return' keyword terminates the function call. Next, we set the timestamp to the timestamp in the XML:

timestamp = $("time",xml).text();

Again, this fetches the text value of the <time> tag in the XML.

Now we can move on to jQuery’s array iteration function, each(). jQuery has an interesting way of handling array iteration. We use a standard selector statement, and the each() function is passed one parameter — a function to handle each instance of the matched elements. In this case, the elements are the instances of the <message> tag in the server response, each instance representing a message to be displayed. One parameter — the id of the instance — is passed to the function. We can use this, with jQuery’s get() function, to grab a new context — the actual XML of the <message> tag. This is how we select it:

$("message",xml).each(function(id) {
message = $("message",xml).get(id);

We can then select elements by passing the context 'message' to the jQuery / $ function. Now that we have all the data we need, we must add it to the top of the message window on the page. The message window has the id 'messagewindow', so we select it using $("#messagewindow") and use the prepend() function to add our data:

$("#messagewindow").prepend("<b>"+$("author",message).text()+
"</b>: "+$("text",message).text()+
"<br />");

That’s all there is to it! Putting it all together, here’s the code for the function:

function addMessages(xml) {
if($("status",xml).text() == "2") return;
timestamp = $("time",xml).text();
$("message",xml).each(function(id) {
message = $("message",xml).get(id);
$("#messagewindow").prepend("<b>"+$("author",message).text()+
"</b>: "+$("text",message).text()+
"<br />");
});
}

Finally, we need the updateMsg function we called at the very beginning of our code. This function has to query the server for new messages, and call the above addMessages function with the response. It also has to set a timeout to call itself after a set period of time, which makes the chat window update automatically. To begin, we don’t need to submit anything to the server besides a timestamp, so this is our $.post call:

$.post("backend.php",{ time: timestamp }, function(xml) {

As I noted before, we also need to remove the loading message at this point, so we call jQuery’s remove function on the span:

$("#loading").remove();

Then, we’ve received our xml response in the object 'xml', so we pass it to our addMessages function:

addMessages(xml);

We round it off with a call to the JavaScript setTimeout() function, which executes specified code after a specified interval. Here’s the whole function put together:

function updateMsg() {
$.post("backend.php",{ time: timestamp }, function(xml) {
$("#loading").remove();
addMessages(xml);
});
setTimeout('updateMsg()', 4000);
}

Putting it All Together

Now we can put all of the pieces of the puzzle together. The code is, as I mentioned, available in this downloadable zip file. However, you can peruse it here, where I’ve added a bit of HTML and CSS for layout:

<html>
<head>
<title>Ajax with jQuery Example</title>
<script type="text/JavaScript" src="jquery.js"></script>
<script type="text/JavaScript">
$(document).ready(function(){
timestamp = 0;
updateMsg();
$("form#chatform").submit(function(){
$.post("backend.php",{
message: $("#msg").val(),
name: $("#author").val(),
action: "postmsg",
time: timestamp
}, function(xml) {
$("#msg").empty();
addMessages(xml);
});
return false;
});
});
function addMessages(xml) {
if($("status",xml).text() == "2") return;
timestamp = $("time",xml).text();
$("message",xml).each(function(id) {
message = $("message",xml).get(id);
$("#messagewindow").prepend("<b>"+$("author",message).text()+
"</b>: "+$("text",message).text()+
"<br />");
});
}
function updateMsg() {
$.post("backend.php",{ time: timestamp }, function(xml) {
$("#loading").remove();
addMessages(xml);
});
setTimeout('updateMsg()', 4000);
}
</script>
<style type="text/css">
#messagewindow {
height: 250px;
border: 1px solid;
padding: 5px;
overflow: auto;
}
#wrapper {
margin: auto;
width: 438px;
}
</style>
</head>
<body>
<div id="wrapper">
<p id="messagewindow"><span id="loading">Loading...</span></p>
<form id="chatform">
Name: <input type="text" id="author" />
Message: <input type="text" id="msg" />
<input type="submit" value="ok" /><br />
</form>
</div>
</body>
</html>

So, with 22 lines of JavaScript, eight lines of HTML, and around 50 lines of PHP, we now have a fully functional Ajax web application. Try it out, and integrate it into your own site. Build your own Ajax application, using these techniques and your own ideas. Take this code and modify it to build something new. If you aren’t comfortable with generating and handling XML, stick with using your web application to generate HTML, and using load() to bring it to the client. Then, once you get the hang of it, try out an application that utilises the full power of XML using tag attributes and jQuery’s attr() function — you’ll be amazed at just how powerful Ajax with jQuery can be.

Whip Up a Yahoo! Mashup Using PHP

Tuesday, September 4th, 2007

So, you want to create your own mashup? Great! Mashups — web applications that grab information from different external sources and mix it together in new and exciting ways — are fun to build, popular with users, and oh-so-very Web 2.0.

Web services, a collection of standards and data formats that enable web applications to communicate with each other and share data, are the core technology behind mashups. They allow developers to directly feed data from databases without having to resort to messy screen-scraping, and enable developers to build rich content applications that make information more useful to users.

These days, numerous companies publish public APIs for their various web services. In this article, I’ll show you how to use the powerful collection of Yahoo! APIs to build a mashup with PHP 5. First we’ll take a look at what APIs are, and the various offerings from Yahoo! that we can take advantage of. I’ll demonstrate how to search the web using Yahoo!’s entire database with only three lines of code, then take you through the process of building an entire application to search for ‘Pizza’ in ‘Palo Alto, CA’ with only 25 lines of PHP code.

This tutorial assumes a decent knowledge of PHP 5 — specifically, that you’re comfortable with the basic syntax, classes and objects, and have some basic background on web services. Take a look at the Wikipedia article on web services and SitePoint’s other PHP tutorials if you think you may have trouble with these.

The Yahoo! Developer Network

The Yahoo! Developer Network is the central reference site for all Yahoo! APIs and a way of connecting with developers and enabling them to provide Yahoo!-powered services in their applications. Check it out for more in-depth reference information.

Available APIs

A quick glance through the sidebar of the developer network homepage reveals just how many APIs Yahoo! provides. Many of the standard Yahoo! services have public APIs available, such as Search, Maps and Answers, and each API has its own set of documentation. A number of startups acquired by Yahoo! also provide APIs to their services, including del.icio.us, Flickr and Upcoming.org, although each of these APIs is handled differently — check their documentation for details. Here’s a quick summary of the most popular ones.

Flickr

One of the most popular APIs available from Yahoo!, the Flickr web services offer access to all the photos on Flickr, photo meta data, tags and more. Popular uses of the API include visualizing locations on maps, galleries, posters and games. You can find links to examples on the Flickr services page including Retrievr, an image search engine that allows you to search for images matching your hand-drawn sketch.

Searching for images on retrievr.com (click to view image)

Yahoo! Maps

The Yahoo! maps API is extremely powerful and allows you to create interactive maps with high quality geographic imagery, adding the power of visual location to your web application. Popular applications of the API include mapping journeys and locating users. Runningmap.com is an excellent example of the Yahoo! Maps API, allowing you to plot your exercise routes and check your distances and other interesting statistics.

A map on Runningmap.com (click to view image)

Yahoo! Search

Want to build a search function for your web site, or add related links to your web application? One of the more traditional APIs from Yahoo!, the Search API allows powerful querying of the Yahoo! web search database. Christian Langreiter offers a comparison of Yahoo and Google search results in one of his mashups.

The application compares Yahoo! and Google results (click to view image)

Each API has different usage restrictions, so check the relevant guidelines before you begin to develop an application. Some APIs have rate limiting — for example, the Web Search API is restricted to 5000 queries per IP address per 24 hour period. In addition, not all APIs can be used for commercial purposes. Yahoo! requires developers to register their applications with the developer network to receive an application ID, and include this application ID in each request they make to an API. While this data doesn’t affect rate limiting, it allows Yahoo! to monitor API usage and contact developers if needed. You can get an application ID — and you’ll need one to try out the sample code in this article.

Consuming the Yahoo! APIs

All the standard Yahoo! APIs are RESTful in nature; data is accessed via standard HTTP requests, where query parameters are passed to the API through the URL. What this means is that you can fetch data from the API as easily as you would fetch the HTML source of any web page, and you can test requests using any browser that will render XML. Take this sample URL:

http://api.search.yahoo.com/WebSearchService/V1/webSearch?
appid=YahooDemo&query=SitePoint&results=2

Try it out — visit the URL in your browser and take a look at the XML output. Since the output is XML, however, we need to parse the response XML with PHP in order to make use of it. A number of classes and XML parsing functions are readily available for PHP, but Yahoo! goes a step further: it provides an option to get all the output data in serialized form. This means that you can quickly fetch the data, run it through the unserialize function and start working with the data immediately. To get PHP serialized output, just append &output=php to the query string. Here’s a simple script that searches the web for “SitePoint” using the web search API, all in three effective lines of code:

<?php
$output = file_get_contents(
'http://api.search.yahoo.com/WebSearchService/V1/'.
'webSearch?appid=your-app-id-here'.
'&query=SitePoint'.
'&results=2'.
'&output=php'
);
$output = unserialize($output);
echo '<code>'.print_r($output,TRUE).'</code>';
?>

Examining this snippet, we see that we first fetch the data in PHP format using the file_get_contents function, then convert it to an associative array with unserialize, before outputting a dump of the array with print_r. I should note here that to be able to use file_get_contents to open a URL requires the allow_url_fopen setting to be enabled in php.ini. Check with your host if you’re not sure if this setting is in place. Let’s take a look at the output. $output['ResultSet']['Result'] contains the data we’re looking for. Here’s a snippet of the first search result:

[Title] => SitePoint : New Articles, Fresh Thinking for Web Developers and Designers
[Summary] => Network of sites that provice information, tools, and resources for internet-focused businesses and web developers, including WebmasterBase.com, eCommerceBase.com, and PromotionBase.com.
[Url] => http://www.sitepoint.com/

Compare this with the first result for the term “SitePoint” on the official Yahoo! Search site and you’ll see it’s the same.

Result for a search on (click to view image)

All the data you would normally get through a Yahoo! search is available through the API! Forget messy screen scraping — Yahoo! makes it easy to get the search results directly. With another few lines of code, we can turn our array into a full search results page. You can probably already see how to make a search engine with the Yahoo! web search API here — it’s that simple! Building your own search engine from scratch would usually involve buying a data centre and spending years spidering the web, but Yahoo! provides all the data free of charge (with usage restrictions, of course). You may have heard of rollyo.com, a site that lets you create your search engine. Well, Rollyo is built using the Yahoo! APIs. With just a few lines of PHP, we can query the Yahoo! web search API, parse the API output, extract the data, format it and output it — that’s a lot of power to have available at your fingertips.

Most of the Yahoo! APIs are just as easy to use as Web Search, and Yahoo! provides a guide to constructing REST queries if you need further information about fetching data from the APIs. Each API method has a documentation page outlining the parameters available, return values, possible output formats (XML, PHP, etc.) and potential errors. It should be noted that all parameters are URL encoded, so php code should become php+code, or the API may return unexpected output. PHP’s inbuilt urlencode function is sufficient for this task. As a general guide, each service has a base URL something like the following:

http://api.search.yahoo.com/WebSearchService/V1/webSearch

Each service requires certain parameters, one of which will be your application ID, and most services will have a query parameter. In the previous example search, we use the parameters appid, query, results and output. In this case, appid is the application ID, query is what we are searching for (”SitePoint”) and output is the format we want the API output in (php for serialized PHP form, optional). The results parameter is optional, however I use it here to limit the output to two search results in order to reduce server load. If you don’t need the standard 10 results, limiting the output through the results parameter is highly advisable. We append a question mark and the parameters to the URI, separating each parameter with an ampersand (&) and using the standard option=value format, just like any other HTTP request.

So now that you’ve had a gentle introduction to the usage of Yahoo! APIs, how they behave and what they provide access to, let’s take things up a notch and look at how we can actually put these APIs to good use.

PHP 5 and the Yahoo! APIs

PHP 5 has a number of features that help us make effective use of the Yahoo! APIs. PHP 5’s improved internal OOP support enables developers to efficiently build applications, and we can take advantage of this by using classes to rapidly develop libraries that make use of the Yahoo! APIs. The introduction of the file_get_contents function allows easy querying of the APIs, and as I mentioned before, PHP has the added advantage of receiving serialized output from most of the APIs with inbuilt parsing functions. Even though the HTTP extension is available in PHP 5, we won’t need it for low-end API consumption. PHP 5 developers can easily query the APIs, parse the output, deal with errors and make use of the data without too much trouble.

Quick and Easy Mashups

To demonstrate the power of the Yahoo! APIs, we’re going to put together a very simple, practical application using PHP 5 and various Yahoo! APIs. What we want to do is query the local search API for data from Yahoo! Local, where users discuss and rate local attractions, businesses and so on. Then we’ll place that data on a map, showing geographically where those attractions are located.

YahooAPI Client Class in PHP 5

To make our lives easier, we’re going to use a PHP class that helps us to query the Yahoo! APIs. The base class needs to have the following functionality:

  • Set the web service to be used.
  • Add parameters to the request.
  • Execute the call to the remote API.
  • Fetch the output.

I’ve built a very simple, extensible class to do just this, called YahooAPI — take a look in the code archive for this article. While I won’t go into the details of the YahooAPI class, using it is very easy. In the previous example we searched for “SitePoint” on the Web. The same task can be achieved very easily with the class:

$api = new YahooAPI();
$api->setAppID('your-app-id-here');
$api->setService('http://api.search.yahoo.com/WebSearch
Service/V1/'.
'webSearch');
$api->setParam('output','php');
$api->setParam('query','SitePoint');
$api->setParam('results','2');
$output = $api->doAPICall();

This is exactly the same as the previous search example, except that now we use the client class. In this case, using the class is more verbose, but with more complex and repeated calls to the API, using the class can save time and simplify maintenance.

Manipulating Data from API Calls

Now that we have everything we need to get to work, I’ll show you how to easily manipulate data from the Yahoo! APIs.

Let’s use our new YahooAPI class to search for ‘Pizza’ in ‘Palo Alto, CA’ using the Local Search API. Take a look at the documentation page for the latest version of the local search API. This is the base URL for the service:

http://local.yahooapis.com/Local
SearchService/V3/localSearch

So we’ll call the setService method of the YahooAPI class and give it the base URL. Looking through the request parameters in the documentation, we’ll need to submit the 'appid', 'query' and 'location' parameters. After we set the required application ID, we then need to choose a location — we’ll use a city and state for now — and a query. Let’s say we’re searching for ‘Pizza’ in ‘Palo Alto, CA’. In simple, procedural PHP code using the YahooAPI class, the search would look something like this:

$api = new YahooAPI();
$api->setService('http://local.yahooapis.com/LocalSearch
Service/V3/'.
'localSearch');
$api->setAppID('your-app-id-here');
$api->setParam('output','php');
$api->setParam('query','pizza');
$api->setParam('location','Palo Alto, CA');
$output = $api->doAPICall();

The call to the API here is the same as fetching

http://local.yahooapis.com/LocalSearch
Service/V3/localSearch?appid=your-app-id-here&
query=pizza&location=Palo+Alto,+CA

through any method, so take a look at that URL in your web browser. Clearly the information we’re looking for is within each <Result> node, and all <Result> nodes are within one big <ResultSet> node. The PHP version that we’re fetching has exactly the same structure as the XML, except that it’s in an easily usable array. After fetching all that data into the $output variable, all we have to do is iterate over the $output['ResultSet']['Result'] elements and fetch the data we need. Try it out — add the following code after the previous example and run it on your web server:

foreach($output['ResultSet']['Result'] as $result) {
echo $result['Title'].'<br/>';
}

You should receive something like the following output:

Patxi's Chicago Pizza
Papa Murphys Pizza Take & Bake
New York Pizza
Round Table Pizza Palo Alto
Domino's Pizza
California Pizza Kitchen
Pizza My Heart
Ramonas Pizza
Round Table Pizza Palo Alto
Spot A Pizza

LocalSearch Client Class in PHP 5

Now let’s extend the YahooAPI class to query the Yahoo! Local Search API. We can easily create a class that manages all this work for us. Instead of the previous procedural code, if we extend the YahooAPI class and create some appropriately-named methods — for example locationSearch($query, $location) — we can further simplify the process of interacting with the APIs.

I’ve written an example class that generally covers everything we need for interacting with the Local Search API. It has three main methods: locationSearch, positionSearch and extractResults. Here’s the code:

<?php
require_once('yahooapi.class.php');
class LocalSearch extends YahooAPI
{

The constructor method sets the basic properties we’ll always need for each Local Search API request:

 public function __construct()
{
$this->setParam('output','php');
$this->setService('http://local.yahooapis.com/'.
'LocalSearchService/V3/localSearch');
$this->setAppID('your-app-id-here');
}

The two search methods represent different ways of performing a search, depending on whether or not we have a location name or exact GPS coordinates. They simply set the required parameters and call the doAPICall method of the parent YahooAPI class:

 public function locationSearch($query,$in_location)
{
$this->setParam('query',$query);
$this->setParam('location',$in_location);
return $this->doAPICall();
}

public function positionSearch($lat,$long)
{
$this->setParam('query','*');
$this->setParam('latitude',$lat);
$this->setParam('longitude',$long);
return $this->doAPICall();
}

The extractResults method saves us entering ['ResultSet']['Result'] all the time when we want to output the results, because the data we need will always be within that part of the returned array:

 public function extractResults()
{
$return = $this->getResults();
$return = $return['ResultSet']['Result'];
return $return;
}
}
?>

You’ll find a copy of the code in the archive for the article. Keep it handy because we’ll be using it in our example mashup. We’ll also build a similar class for the Maps API later, as it has some slightly different requirements.

Our example “pizza” search, executed using our new LocalSearch class, now looks like this:

require_once('localsearch.class.php');

$localSearch = new LocalSearch();
$localSearch->locationSearch('Pizza','Palo Alto, CA');
$output = $localSearch->extractResults();

That’s much easier, don’t you think?

Yahoo! Maps AJAX API

Perform a quick web search and you could find the web sites for these pizza places, each of which would list the restaurant’s address. But why would you go to all that trouble when Yahoo! provides all this data in the returned array — as well as latitude and longitude information? Here’s an example of the data returned:

[Title] => Patxi's Chicago Pizza
[Address] => 441 Emerson St
[City] => Palo Alto
[State] => CA
[Phone] => (650) 473-9999
[Latitude] => 37.445265
[Longitude] => -122.163432

Now that we have the location information, we need to figure out how to plot it on a map. Yahoo! provides a map image API, offering raw images of maps in PNG format, and (in theory) we could use GD to draw markers on the map. However, since we’re building a web application, we can instead use the Maps AJAX API to generate a UI-friendly, interactive Yahoo! maps display. We can then add markers to the map in preset positions, using the bundled functions. (Note that the Maps AJAX API isn’t really an Ajax API! In fact, there isn’t any real Ajax at all — that is, there are no XMLHttpRequest calls — but due to the fact that the term Ajax has come to represent any web page technology that uses JavaScript and doesn’t need to reload the web page to update itself, Ajax would be the best way to describe it.)

Unlike the other Yahoo! APIs, the Maps AJAX API isn’t a REST-based web service. Instead, you have to include a JavaScript file on your page, create an instance of the map in a container on the page (usually a <div>) and manipulate it through JavaScript calls. Luckily, the HTML and JavaScript required are quite simple. Take a look at the mapoutput.php example in the code archive. This is all the JavaScript you’ll need to generate the map:

var ymap = new YMap(document.getElementById('mC'),YAHOO_MAP_REG);
var mPoint = new YGeoPoint(37.4041960114344,-122.008194923401);
ymap.drawZoomAndCenter(mPoint, 3);
var marker = new YMarker(mPoint);
marker.addLabel('A');
marker.addAutoExpand('<div class="mp">Some Text</div>');
ymap.addOverlay(marker);

The first line creates a new instance of the YMap class, and assigns it to the element on the page with an ID of 'mC'. The second argument represents the desired map type, in this case a regular map rather than satellite imagery, YAHOO_MAP_SAT, or a hybrid of the two, YAHOO_MAP_HYB. The second line creates a YGeoPoint object, a point on the map based on latitude and longitude coordinates, while the third line calls the map object and tells it to centre itself on this new point and display the map, at a zoom level of 3.

The final three lines of JavaScript create a YMarker object, a visual map marker that expands to reveal some extra content when it’s moused over. Our challenge is to generate all this with PHP, and to make the job easy, we’re going to build a class that generates all the code for us.

Mashup Time!

Now that we’ve sorted out how to query the APIs and deal with the data, it’s mashup time! As I mentioned before, we’ll create a simple application that finds places with the local search API and, using the latitude and longitude coordinates from the returned search data, marks the exact locations of these places on a map from the maps API. And of course we’ll wrap all the functionality up in a simple PHP class. The AJAX map API uses JavaScript code, so we’ll use our PHP class to generate the required JavaScript based on the returned search data.

First, we’ll start by querying the Maps API. I’ll use the client class for the local search API, which I demonstrated earlier, to execute this sample query: ‘Pizza’ in ‘Palo Alto, CA’. We need an instance of the LocalSearch class, and we’ll use its locationSearch method to execute the API query. The extractResults method will give us the data that we want to work with. Now that we’ve built our client classes, all this can be achieved in three lines of code:

$localSearch = new LocalSearch();
$localSearch->locationSearch('Pizza','Palo Alto, CA');
$apiOutput = $localSearch->extractResults();

Let’s take a step back for a moment and call print_r($apiOutput) to see what we have. The array $apiOutput now contains a number of sub-arrays, each of which is a single search result and contains (among other things) a ‘Title’, ‘Latitude’ and ‘Longitude’. That’s all we need for the moment, so let’s quickly extract this information and delete the rest:

foreach($apiOutput as $id => $result)
{
$points[$id] = array($result['Title'],
$result['Latitude'],
$result['Longitude']);
}

Here are some sample values from our newly defined $points array:

[0] => Array
(
[0] => Patxi's Chicago Pizza
[1] => 37.445265
[2] => -122.163432
)

[1] => Array
(
[0] => Papa Murphys Pizza Take & Bake
[1] => 37.433243
[2] => -122.129291
)

For each marker we want to put on our map, we need to know its position, and we need some summary text that we can have appear when the user mouses over it. In this case, when visitors mouse over one of our markers, we’ll show them the name of the place.

Now that we have all our locality information, we come to the tricky bit — generating the map HTML and JavaScript. Basically, our map code consists of two distinct sections — the <head> HTML and CSS (for the map container), and the <body> HTML and JavaScript. The <body> includes the container <div> for the map and some JavaScript for the Maps AJAX API. For each marker we want to add to the map, we need a JavaScript YGeoPoint object to define its position, and a YMarker object to be the marker itself. We then customise the marker through the addLabel and addAutoExpand methods (many more are documented here) before placing it on the map using the map object’s addOverlay method. We’ll now create a PHP class that takes care of generating all of this JavaScript code, and call it AjaxMap.

Here’s a summary of the methods our class will have:

  • getHeadHTML for generating <head> code
  • getMapScript for generating <body> code
  • initMarker for generating code for each marker

We’ll also add some helper methods for customising the map:

  • setMapType for choosing between maps, satellite images, and hybrids
  • setMapContainer for setting the ID of the map container <div>
  • addMarker for adding markers to the map

Let’s begin our AjaxMap class:

<?php
require_once(’yahooapi.class.php’);
class AjaxMap
{
private $mapContainer;
private $mapType;
private $markers = array();
public $showZoom;
public $showPan;

We begin by including the YahooAPI class, which we’ll use to generate the Yahoo! API calls. Our class has three private properties: $mapContainer will contain the ID of the HTML element acting as the map container, $mapType will represent the type of map desired and must be one of YAHOO_MAP_REG, YAHOO_MAP_SAT or YAHOO_MAP_HYB, and the final private property, $markers will contain an array of map location markers. The API offers the ability to add zoom and pan controls, so we’ll add the public properties $showZoom and $showPan, which can be set to true when required.

So, first to the easy methods: getHeadHTML, the set functions and addMarker. All the getHeadHTML method needs to do is return a <script> tag referencing the Yahoo! AJAX Map API:

public function getHeadHTML()
{
return '<script type="text/javascript” ‘.
’src=”http/api.maps.yahoo.com/ajaxymap?v=3.0&appid=your-app
-id-here”>’.
“</script>\n”;
}

The set functions are just as simple — they act as wrapper methods for modifying private properties. Here’s the code:

 public function setMapContainer($id)
{
$this->mapContainer = $id;
}
public function setMapType($type)
{
$this->mapType = $type;
}

The addMarker method will add a new map marker entry to the private $markers array and takes a latitude value, a longitude value and description text as its arguments:

 public function addMarker($lat,$long,$descr)
{
$this->markers[] = array($lat,$long,$descr);
}

initMarker is a private method called for each of the desired map markers and generates the JavaScript code required for the marker:

 private function initMarker($id,$lat,$long,$descr,$init_geo = TRUE)
{
$js = '';
if($init_geo) $js .= "\nvar mPoint$id = ".
"new YGeoPoint($lat,$long);\n";
$js .= "var currmarker = new YMarker(mPoint$id);\n";
$js .= "currmarker.addLabel('$id');\n";
$js .= "currmarker.addAutoExpand('<div class=\"mp\">".
addslashes($descr)."</div>');\n";
$js .= "ymap.addOverlay(currmarker);\n\n";
return $js;
}

initMarker takes all the information about the marker — latitude and longitude for position, a short description and some notes, plus a unique 'id' parameter — and generates the JavaScript we need in order to draw the marker. The $init_geo parameter for initMarker indicates whether or not we need to create a YGeoPoint object for the marker; this may already have been done.

All that’s left to do is bring everything together within the main JavaScript block. The getMapScript method will generate this JavaScript and assign it to the $js variable:

 public function getMapScript()
{
$js = '';

First, we have to initialise a YMap object. This is our main map object which will handle the drawing and customisation of the map. The first part is simple — we output the code required to create a new YMap object:

   $js .= 'var ymap = new YMap(document.getElementById(\''.
$this->mapContainer.'\'),'.$this->mapType.");\n";

In this instance, the properties $mapContainer and $mapType include the relevant information about the map, so setMapType and setMapContainer should be called before getMapScript.

Next, we output the JavaScript to add the zoom and pan controls if $showZoom and $showPan are set to true. To add a zoom control in JavaScript, we use the addZoomShort method of the YMap object, and addPanControl for a pan control:

   if($this->showZoom) $js .= "ymap.addZoomShort();\n";
if($this->showPan) $js .= "ymap.addPanControl();\n";

We may have a number of markers to display, but the map can only be centred on one of them. To keep it simple, we’ll remove the last marker from the main set of markers, centre the map on it and draw it on the map before proceeding to draw the remaining markers. Obviously, none of this is needed if no markers are to be drawn on the map, so we check that markers exist here too. Here’s the code that outputs the JavaScript required for centring the map on the last marker, and drawing that marker:

   if(count($this->markers) > 0)
{
$lastmarker = array_pop($this->markers);
$js .= 'var mPoint'.count($this->markers).' = new YGeoPoint('.
$lastmarker[0].','.$lastmarker[1].");\n";

$js .= 'ymap.drawZoomAndCenter(mPoint'.count($this->markers).
", 3);\n";

$js .= $this->initMarker(count($this->markers), $lastmarker[0],
$lastmarker[1], $lastmarker[2],
FALSE);

First we check if there are more than 0 markers (that is, we see if any have been set), and if so, extract the last of these markers and use that marker’s data to write the JavaScript required to create a new YGeoPoint object. We then output the JavaScript required to draw the map, centre it on our last marker and set the zoom level to 3. In JavaScript, we do this via the drawZoomAndCenter method of the YMap object. We then call our initMarker function to generate the rest of the JavaScript, and through its last parameter, tell it not to output the JavaScript to create a YGeoPoint object, as we’ve already taken care of it.

Finally, we generate the code for each remaining marker by quickly iterating over the markers array, calling initMarker for each one and returning the $js string variable:

     foreach($this->markers as $id=>$obj)
{
$js .= $this->initMarker($id,$obj[0],$obj[1],$obj[2],TRUE);
}
}
return $js;
}
}
?>

That also represents the end of our AjaxMap class!

Now we just have to use our local search class and AjaxMap class in a proper application. I’ve put together a quick demonstration. First we need to include our two classes:

<?php
require_once('localsearch.class.php');
require_once('ajaxmap.class.php');

Next, we use our local search class to search for “pizza”. We collect the locations from our search results and store them in an array called $points:

$localSearch = new LocalSearch();
$localSearch->locationSearch('Pizza','Palo Alto, CA');
$apiOutput = $localSearch->extractResults();

foreach($apiOutput as $id => $result)
{
$points[$id] = array($result['Title'],
$result['Latitude'],
$result['Longitude']);
}
unset($apiOutput);

We then create a new AjaxMaps object and add to it all our locations:

$ajaxMap = new AjaxMap();
$ajaxMap->setMapContainer('mC');
$ajaxMap->setMapType('YAHOO_MAP_REG');
$ajaxMap->showPan = true;
$ajaxMap->showZoom = true;

foreach($points as $point)
{
$ajaxMap->addMarker($point[1],$point[2],$point[0]);
}
?>

Now that all our location markers have been added to our AjaxMap object, the only task that’s left to do is write the page HTML and output the JavaScript:

<!DOCTYPE html public "-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<?php echo $ajaxMap->getHeadHTML(); ?>
<style>
#mC {
height: 500px;
width: 500px;
}
.mp {
width:160px;
height:50px;
}
</style>
</head>
<body>
<div id=”mC”></div>
<script type=”text/javascript”>
<?php echo $ajaxMap->getMapScript(); ?>
</script>
</body>
</html>

The entire script is available in the code archive. Set your application IDs, load it up on your web server, and with any luck you should see something like this:

Our app in action! (click to view image)

Congratulations! You’ve just built a mashup using the Yahoo! APIs. With a bit of tweaking, you could add search functionality, allowing the user to look for more than just ‘Pizza’ in ‘Palo Alto, CA’. You could even integrate the functionality into an existing application (although be aware of the terms of use for both APIs). The possibilities are endless.

Where to From Here?

As you can see, exploiting the Yahoo! APIs with PHP5 to create useful mashups is a piece of cake, and there are many interesting applications that can be built with the data. Rasmus Lerdorf himself has written a similar article, taking a more in depth look at the Yahoo! Geocoding API, and how to easily use it with PHP5. It’s also worth noting that while we’ve used the output=php parameter throughout this article, most of the APIs also offer JSON output for use via Ajax. The Yahoo! Developer Network’s PHP Developer Center has an excellent collection of tutorials, code samples and other resources for consuming the APIs with PHP5.

Also check out Yahoo’s Application Gallery for inspiration and to see some great web apps built with various Yahoo! APIs, If you build an interesting application, submit it to the gallery for some excellent exposure and useful feedback

Entries (RSS)