Extensible CSS Interface III: Adding Ajax Interactivity

~ 20 March 2008 ~

This series is sponsored by Authentic Jobs, a freelance and full-time job board for web professionals.

This is the third article in the four-part series, “The Highly Extensible CSS Interface”. Markup and images for this article:

Part III - Adding Ajax Interactivity

This third article documents the underlying components of Ajax, examines a few examples of Ajax in the demo, and wraps up with a shout-out to resolution dependence.

Before we begin…

I repeat the disclaimers from last time: One, this interface is optimized for any browser that supports standards exceptionally well. Sorry, no IE6 support. I’m relying on you to make concessions on your own for IE6, thereby allowing this series to focus on what’s possible with browsers that support standards exceptionally well without being bogged down in the mire of those that do not. (Again, consider conditional comments for IE6 concessions.)

Two, there are a few known “bugs” in the interface for which small inconsistencies will be seen from browser to browser. These will be documented as comments in the final markup (to be provided in Part IV). For this article, be aware that IE7 ignores the negative absolute positioning on the right corner image for the Latest Community Activity and Community Snapshot headings. I welcome any suggestions for fixing this.

Lastly, another hat tip to Aaron Barker who wrote a lot of custom jQuery and Ajax scripting for this demo.

Ajax

What was penned a couple years ago as a preface to describing Ajax design terminology is still relevant today:

The line between “desktop UI” and “web UI” is gradually blurring. Love it or loathe it, “Ajax”, which originally referred to Asynchronous JavaScript + XML, has somehow become the catch-all term for describing “desktop-like” interaction on the web; more accurately, GUI interaction as seen previously only in native applications running in an operating system environment.

When I first spoke about Ajax in a workshop 18 months ago, few raised their hands when asked if they had experience developing sites and apps that employed Ajax. If asked that same question today, it’s likely half of that same audience would raise their hands. Indeed, love it or loathe it, Ajax has weaved its way into high-profile sites and weekend projects alike as the de facto standard for producing rich interactivity on the web. (It’s worth noting, however, Ajax’s position as king of the hill is increasingly challenged by emerging technologies such as Adobe Flex and Microsoft Silverlite.)

Ajax implementation typically includes at least three components: 1) asynchronous server communication, which is most commonly accomplished via XMLHttpRequest, 2) manipulation of the Document Object Model (DOM) for dynamic display and interaction, and 3) JavaScript to bind everything together. The ‘x’ in Ajax refers to XML, but Ajax can also also be accomplished with (X)HTML, the result of which is often termed AHAH.

Asynchronicity is the key component of Ajax — or any rich internet technology, for that matter — as it provides that “native app” feel within the web environment. Instead of the traditional request/response model that fetches an entire page with a full trip to the server, asynchronicity means we fetch data for only a select portion of the page, e.g. username availability when registering an account, “without interfering with the display and behavior of the existing page” (Wikipedia).

In the demo interface, we fake asynchronous server communication with a little JavaScript and by fetching data from a few static PHP pages:

  • activity.php for the Latest Community Activity section, which functions like Digg Spy with the help of jQuery Spy
  • ajaxStuff.php for mimicking the Ajax request for the bio’s edit-in-place feature in Part II (adds a spinner image and a one-second delay to mimic server retrieval)
  • search.php and jquery.autocomplete.js for the search field auto-complete (Part II)
  • project.js for the Community Snapshot and Latest Community Activity sections, edit in place, and overall scripting wizardry

Faking asynchronicity merely allows you to download the code samples and open the interface on any machine running PHP, without requiring true server communication.

As an example of how these components come together, let’s have a look at the Community Snapshot. For starters, we begin with markup: A div encloses the map as a background image, and styling sets the containing block to relative positioning:

<div id="map"></div>

#map {
  position: relative;
  margin: 0 auto;
  width: 277px;
  height: 155px;
  background: url(../img/map.gif) no-repeat center center;
  }

It’s important that the positioning be set to relative as this will allow the “n members online” boxes that fade in and out to be positioned absolutely according to the map’s containing div. To accomplish this effect, we use a list item with several elements and CSS properties:

<li class="l1" id="map1">
  <p><strong>North America:</strong> <span>n</span> members online</p>
</li>

#map li p {
  padding: 5px 0;
  line-height: 100% important;
  font-weight: bold;
  background: url(../img/maploc-bg.png) no-repeat;
  }
#map li strong {
  display: block;
  float: left;
  text-indent: -9999px;
  }
.l1 {
  background: url(../img/maploc-btm-left.png) no-repeat bottom;
  }	

Let’s break down each of these:

  • <p></p> - This is the wrapper for our content. While it’d be nice to keep our markup as lean as possible with just the li, in this instance we need to add an extra element to aid with extensibility (text resizing/translation) by breaking the box image into two, which I’ll describe in a minute. A paragraph seems the most semantic solution rather than a meaningless div.
  • <strong>North America:</strong> - Notice that for sighted users, the region text (“North America”) isn’t shown in the yellow boxes that fade in. In the spirit of extensibility, we’re considering sightless and alternate device users for whom the list item’s location relative to the map isn’t visible. Therefore, the idea here is that the location is provided in text rather than in geographical reference. So, we’re effectively “throwing” the text off the page using the text-indent property and a negative margin great enough to put the text outside the visible area of even the widest screen. display: none would accomplish the same, but some screen readers will ignore any text hidden with display: none. Of course, it’s questionable whether a screen reader would even pick up this text, as DOM refreshing isn’t always rendered properly by screen readers. (Note: The span element is a hook for jQuery to insert the number dynamically.)
  • class="l1" - We construct each yellow box with two images (top, bottom) specifically to allow for text resizing and translation. The top, maploc-bg.png, is much taller than needed for the default text. This is to accommodate a larger font size or an increased character count caused by translated text. The bottom, maploc-btm-left.png or maploc-btm-right.png, creates a nifty comment bubble thing and aligns to the bottom of the paragraph element. Depending on the box’s position on the map, class="l1" requests -left.png whereas class="l2" requests -right.png. Admittedly, class="l1", which is short for “location 1”, is not the most semantic selector declaration, but it’s arguably better than class="left" should the positioning be something other than left or right in the future. (Remember class="arial red 10" in Part I?)

Finally, markup that isn’t shown here but is shown in the demo, we set the absolute positioning of each list item:

<li class="l1" style="position: absolute; top: 10px; left: 20px;">

Recall that we set the position of #map to relative. Any element that is a child of #map, in this case li, will be positioned relative to the containing block of #map rather than the body or other parent element. Therefore, this list item is positioned 10px from the top and 20px from the left of #map. (Note: I’ve set this style inline for the sake of instruction. Ideally, you’d want to dynamically insert the positioning as each yellow box is generated.)

Once the markup is in place, we begin adding scripting that allows for Ajax magic to make a graceful entrance. Ironically, the Community Snapshot section isn’t a good demonstration of Ajax components because we’re totally faking things here by randomly creating “members online” numbers rather than pulling them from a database. Let’s shift our focus instead to the Latest Community Activity section to wrap up the discussion. But before we do, throw your mind back to Part II and take a look at the jQuery scripting we’ve added to fade the yellow boxes in/out:

function nextSnapshot(){
  ...
  $("#"+curID).hide("slow");
  ...
  $("#map"+curNum).show("slow");
  ...
  }

Look familiar?

So, the Latest Community Activity section is a better representation of Ajax as it fetches data asynchronously from a secondary source, activity.php, our pseudo database. As is the auto-complete for search (Part II), which fetches data asynchronously from search.php, another pseudo database. In both cases, we manipulate the DOM either by replacing elements in the document tree or by adding new ones. Finally, JavaScript in project.js and other files inside the /scripts directory bind everything together, rounding out the three components mentioned earlier.

I indicated in the series opener that a primary objective of this third article was the demonstration of judicious Ajax usage. While some of the interactivity demonstrated here could be discounted merely as eye candy, be aware the demo interface for this series was in fact derived from an actual project, the likes of which I’ll mention at the conclusion of the series. Some of the ideas shown here are based on actual prototype UI features, the sum of which aimed to improve the flow and speed of the interface, while others aimed to provide a very real glimpse into what was happening at that moment within a given community. Thankfully, my former client and good friend has been kind enough to allow me to repurpose certain elements for educational purposes, for which I’m appreciative and hope you are, too.

Additional Ajax reading:

Resolution Dependence & Miscellany

This third article is much lengthier than I anticipated, so I’ll try and wrap things up quickly. I can’t conclude without revisiting resolution dependence mentioned in Parts I and II, as the interface in this demo tricks out the content based on browser width. Resize your browser and watch how the arrangement of Latest Community Activity and Community Snapshot completely changes to adapt to the available screen real estate. Values that allow for this adaptation are contained in 1024.css, and re-read Part I to understand how resolution dependence works.

There’s also a couple child and adjacent selectors at play, and these are documented as comments in the HTML page and screen.css.

Finally, Mark James’ Silk Icon Set is used throughout the interface, but there are many other icon sets you should consider purchasing for your project.

Done. Please pick apart the markup, code, UI, my grammar, you name it. I’m all ears.

 

0  Comments

Veer Veer: Visual Elements for Creatives.
Stock photography, type, and killer tees. Genuinely recommended by Authentic Boredom.

Impart your wisdom

Use the form below to add comments, suggestions, and the inevitable off-topic banter (please keep to a minimum). Feel free to use HTML code (optional), and be aware that I reserve the right to edit any raw language or banter that’s too far off topic.










Remember personal info the next time you visit?

 



   

 


About

Authentic Boredom is the platitudinous web home of Cameron Moll, designer, author, and speaker. More…


Jobs
Come in, we're hiring

Full-time and freelance job opportunities. Post a job...

...view all jobs »


Recently

A selection of fine reading, available for a limited time only: