Tuesday, December 09, 2008

A Spry Woot-Off Tracker

Although Flex is a neat tool, good ol' Javascript has been around for quite a while, and I thought I'd try to build a Woot-Off tracker using Flex's Javascript cousin, Spry. Conveniently, there's a Woot-Off going on today.

Spry is an interesting Javascript toolkit since it focuses on data extraction and presentation and widgets. In this example, we're not using any widgets, but we are taking advantage of the Spry Dataset tools to grok the XML stream from Woot. Just like with the AIR version, we need to use a proxy to grab the Woot XML stream.

Spry's DataSet works by allowing the developer to query the data set. Since Woot is providing an RSSish feed, we use the XMLDataSet class. By using braces, the dataset's contents can be accessed using the name of the XML tag. So to grab the price, we use {woot:price}. It's relatively simple.

The challenging part is for data that's not quite perfectly formatted. In this case, the percentage needs to be multiplied by 100. We do that inside the Observer. The Observer can update the contents of the dataset. So you can simply create an observer function and change away. The description also needs to be cleaned up since its HTML entities do not provide the needed effect. We actually want to use the tags, so we unentify them.

The timer is actually easier than in Flex, since the timer comes automatically with the DataSet with the loadInterval option. The only thing we need to do is speed it up and slow it down at the appropriate time.

<!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" xmlns:spry="http://ns.adobe.com/spry">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Spry Woot Tracker</title>
<link type="text/css" rel="stylesheet" href="http://yui.yahooapis.com/2.6.0/build/reset-fonts-grids/reset-fonts-grids.css"/>
<link href="css/wootTracker.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="includes/xpath.js"></script>
<script type="text/javascript" src="includes/SpryData.js"></script>
<script type="text/javascript">
// we don't want to use cached data, and we need to reload every 30 seconds
var dsWootInfo = new Spry.Data.XMLDataSet("WootProxy", "rss/channel/item", {useCache: false, loadInterval: 30000});

var quickCheck = false; // Is the timer sped up

// Observer watches for when data changes and modifies for presentation
function wootObserver(notificationType, dataSet) {
if (notificationType == "onDataChanged") {
if (dataSet) {
var data = dataSet.getData();
var soldout = data[0]["woot:soldoutpercentage"];
data[0]["woot:soldoutpercentage"] = soldout*100;
var desc = data[0]["description"];
// Description contains HTML entities, fix them
// Something strange is going on with the formatter it's just desc not descdesc
desc = desc.replace(/&gt;/g, ">");
desc = desc.replace(/&lt;/g, "<");
desc = desc.replace(/&quot;/g, '"');
desc = desc.replace(/[\u201C\u201d]/g, '"');
data[0]["description"] = desc ;

// Determine if it's time to speed up or slow down
if (quickCheck) {
if (soldout < .95) {
quickCheck = false;
} else {
if (soldout > .95) {
quickCheck = true;


<body id="wootTracker">
<h1>This page requires JavaScript. Please enable JavaScript in your browser and reload this page.</h1>
<div id="doc" spry:region="dsWootInfo">
<h1 id="wootName"> {title} </h1>
<div style="float:left; padding-right: 10px">
<img src="{woot:thumbnailimage}" />
<h3 id="wootPrice">{woot:price} </h3>
<h4><a href="{woot:purchaseurl}" target="_blank">Buy This Woot</a></h4>
<h3 id="wootPercent">{woot:soldoutpercentage}% Sold Thus Far</h3>
<div id="description" >{description}</div>

And here's the CSS:

body {
background:#EDEDED none repeat scroll 0 0;
h1 { font-size: 182%; margin-bottom: 0.5em}
h3 {font-size:138.5%; margin-bottom: 0.5em}
h4 {font-size:123.1%; margin-bottom: 0.5em}
li {list-style-type:disc; list-style-position:inside}
strong {font-weight:bold}
p {margin-top: 1em}

This application can be run inside Tomcat or wherever you have a proxy running.

No comments: