Pathfinder Blog
Topic Archive: Ajax Examples

jQuery Form and jQuery UI Tabs: Two great tastes that taste great together

I spent last week holed up writing part 4 of Ajax Overhaul, my series of articles for IBM developerWorks. Aimed squarely at Ajax beginners, the series shows how to progressively enhance Web 1.0 sites with jQuery and Ajax. Each installment starts with the pre-Ajax version of an example e-commerce application and takes readers through the steps of retrofitting it to improve and modernize the user experience. The tagline for this installment is "Streamline multi-step processes with tabs and Ajax forms," a topic that allowed me to employ two of my favorite plug-ins for the jQuery open-source Ajax toolkit:

  • jQuery Form, which gives jQuery several methods for serializing form data and submitting the results via Ajax.
  • jQuery UI Tabs, which turns a series of divs and unordered lists into a tabbed interface.

I feel like I've run on and on about my enthusiasm for jQuery on this site, but I can't help it. One of the cool thing about its plugin ecosystem is the ease with which you can cross-pollinate a couple of plugins to create novel effects. In this case, I wanted to take a series of web forms - the checkout process for my example shopping site - and turn them into a single-page, tabbed interface in which each tab represented one step of the process. The biggest additional requirement was progressive enhancement; with JavaScript absent or disabled, the checkout process has to work like it did before I retrofitted it. All it took to accomplish these goals was a judicious mix of my two plugins.

Exampleshoppingapp

Continue reading »

Grails and JSONP: How Easy is That?

Grails_logo
For all of those Java developers casting longing glances at their buddies doing Rails development, there is hope. Grails, which has just celebrated its 1.0 release, is a Rails-like "convention over configuration" framework that aims to do for the Java world what Rails has done for Ruby. Instead of Ruby, the dynamic programming language of choice is Groovy, which compiles to bytecode (no Groovy to Java translation) and integrates smoothly with just about any Java code you may be using.

I'll stop hyping Groovy and Grails in general here; there's plenty of good informational stuff on the Grails and Groovy home pages. I will note that if you run off the tracks a little bit, you can find yourself reading through 500-odd line stack traces of Groovy, Spring and Hibernate -- there's room for some improvement there.

One of the many nice things about Grails is it's support for JSON and XML. Let me put together a simple example that shows off some of Grails' power.

Continue reading »

Bjax: Make it Play MP3’s

It's nice to know you've inspired someone and it was very nice of Chris Anderson to drop us a note on his own Bookmarklet: Make it Play. Basically, this bookmarklet will scan a page for mp3 links and then insert a little semi-transparent media player interface at the bottom of the page.

It's not SongBird, but it's a good demonstration of the power of Bjax -- injecting user interface to improve an existing web interface. Based on JQuery.

Technorati Tags: , , , ,

Ajax Intervention: Comcast.com

Welcome to Ajax Intervention, in which we dissect how major websites misuse, or fail to use, Ajax to improve their user experience.

Up this time: Comcast.com, which, despite an extremely "Web 2.0" look and feel, misses the mark with its Ajax features.

Comcast is one of those companies everybody loves to hate. Yet a quick glance at the latest version of the big cable operator's web presence reveals some surprisingly up-to-date visual motifs. With its easy-to-read text, expansive white space, candy-colored visual palette and simple calls to action, Comcast is far more modern-looking than its competitors. Time Warner Cable, DirecTV and Dish Network all offer cramped, console-style interfaces that wouldn't have looked out of place five years ago. But Comcast is clearly looking to incorporate the look and feel of Web 2.0.

Comcast0_2

Disclaimer: I'm a customer of Comcast and DirecTV but not of Dish Network or Time Warner, so I'm can't speak about the password-protected areas of the latter sites. Comcast's homepage is fairly similar to the other sites', but the rest of comcast.com looks strikingly different from your typical sales-and-service site.

Or so it appears. Once you actually click around the Comcast site, it becomes clear that most of its freshness is merely visual. The functionality and user experience are just as inconsistent as we've come to expect from big corporate sites.

Problem: Wonky Login Module

The site includes two login modules: A traditional one on the homepage and an Ajax one elsewhere. When entering bad credentials into the homepage one, you get redirected to the standalone one, where a loading icon indicates an in-progress XHR. Sometimes, that XHR hangs ... forever. No graceful failure message ever appears. During the site's relatively frequent performance slowdowns, even correct login credentials can result in a permanently hanging Ajax call. That tends to confuse users. The validation scheme is even more confusing. Blank required fields earn you a JavaScript alert box, while errors from the server side get loaded via XHR into into the markup.

Comcast1
Comcast1

Solutions

  • Provide graceful failure for your asynchronous requests by setting a timeout on them. The XHR object doesn't offer this natively, but most popular libraries do.
  • Use a consistent DHTML error-reporting framework rather than a grab bag of alerts and inline messaging. In addition to being more user-friendly, it will be easier to maintain.
  • Build reusable components and, if necessary, style them differently on different pages. Don't build two overlapping components with strange dependencies.

Problem: Inconsistent Shopping Cart

When you visit the Comcast.com to shop for new service, the shopping cart utilizes a strange mixture of DHTML, Ajax, popups and traditional navigation to guide you through the process. On the first page view, before you've even added any services, a loading icon signals that an Ajax call is in progress. As it turns out, they're making an XHR just to load an empty shopping cart. As you add services from multiple tabs, Ajax is again used to update the shopping cart. But to remove items from the cart, you must click an "edit" button and do so in a popup window.

Most puzzlingly, the interface doesn't seem to validate your choices. I was able to add separate phone, cable and internet products to my cart, then add a bundled "Triple Play" phone/internet/cable package. I went very far down the checkout funnel without ever receiving a notification that I was ordering an incompatible array of products. Yet when I cleared out the cart and just played around with the standalone cable products, the interface kept me from breaking the rules. If I added cable package A, then added the mutually exclusive package B, package A disappeared from my cart. Yet there was no messaging to explain what had happened.

Comcast1
Comcast1
Comcast1

Solutions

  • Don't use Ajax for just one aspect of your component. If the user can add items inline, she should be able to remove them, too.
  • Let your users know what's going on. If you're going to use validation logic to remove things from their cart automatically, then message them when you've done so.
  • Model your GUI widgets on traditional form controls. Mutually exclusive options should behave like radio buttons; a la carte ones, like checkboxes. A laundry list of options, some a la carte and some mutually exclusive, is usually a bad idea. Group each set of logically related options into something resembling a fieldset.

Problem: Inconsistent Global Navigation

Once you're past the homepage, with its left nav column, comcast.com presents you with a consistent top nav bar: Learn, Shop, Programming, Customers, About, and a search box. But the tabs themselves aren't clickable; you have to drill down within the DHTML menus to select a specific topic. Certain topics inexplicably load new windows, often from separate subdomains, full of Flash or HTML content. The navigation on these windows is different from the main site - or totally absent.

Solutions

  • Study basic usability. The tabbed navigation metaphor has been around for ages. Follow best practices when implementing it.
  • Consolidate your content. If you can embed a Flash movie in a popup window, you can embed it in your main window. It's jarring for users to be sent off-site without warning.
  • Don't disorient your users. Your navigation doesn't need to be identical in every sub-domain, but do at least provide a consistent way to navigate back to the homepage.

Problem: Slavishly Consistent Color-Coding

Each section has its own design scheme in which headlines, buttons, links and tabs all appear in the same color. Links aren't even underlined. It's therefore impossible to tell, without mousing over an element, whether or not it's clickable. Users often have to play target practice and click on a small "go" link to get to a subsection; the headlines themselves are inconsistently clickable.

Comcast1

Solutions

  • Underline your links and make buttons look like buttons. UI design isn't art; it's science. Users know the rules and get annoyed when you break them.
  • If you must abandon underlined links, then do something to differentiate your links from other content. A pretty color palette is useless if it causes users to click continually on the wrong elements.
  • When in doubt, make it clickable. Don't just link a button when you can link the accompanying image and/or headline, too.

Problem: JavaScript Users Only

If you visit comcast.com with a JavaScript-disabled browser, almost nothing works. There's not even an old-school "please turn on JavaScript."

Solutions

  • It's 2007. Follow web standards. Use progressive enhancement. If you're not building a cutting-edge RIA with heavy client/server data exchange, there's no reason to require JavaScript. At the very least, inform your users that their browser isn't supported.

Conclusions

Most large corporate sites can't retool themselves overnight. At best, they can update their features one at a time and use fresh visual approaches to call out their new interactivity. But in doing so, they should rely on old-fashioned user exerience design, follow industry-standard UI conventions and strive for a consistent experience. Comcast's bright, big, bold design scheme is a welcome development, but it's only the first step in what could be a comprehensive UI redesign.

Technorati Tags

Ajax Intervention: Product tooltips in Amazon’s beta redesign

Welcome to Ajax Intervention, in which we dissect how major websites misuse, or fail to use, Ajax to improve their user experience.

Up this time: Amazon.com and its inconsistent new Ajax redesign.

The beta test for Amazon's new DHTML navigation has garnered plenty of perceptive commentary from the Ajax and UxD communities. (See posts from Ajaxian, Functioning Form, Jeffrey McManus and CommaDot.) Yet one puzzling bit of Ajax fuctionality hasn't gotten much notice: The inconsistent use of tooltips in item listings.

I've long bemoaned the fact that Amazon doesn't let me add an item to my cart, or to my wish list, from its search results and landing pages. To buy an item, I've always had to navigate to the item's individual product-details page. But that's all changed with the new redesign - sort of.

Homepage

When I visit the new Amazon homepage, I see a module titled "What Do Customers Buy After Viewing This Item?" It contains thumbnails and headlines for three different products related to my most recent search. Next to the name of each product, I see a little blue caret graphic. Mousing over it, I'm presented with an extremely useful microcontent popup with some basic product details and two buttons: "Add to Cart" and "Add to Wish List." I've longed for just such a feature for years. It's as if Amazon has finally read my mind.

Whatdobuy

But ... wait a minute. Directly above and below the "What Do Customers Buy ..." module, I see two similar modules: "New For You" and "More to Explore." The former contains product suggestions; the latter, products I've previously viewed, or items similar to them. But both sets of listings lack the little blue caret graphic for which I've now been trained to look. I try to mouse over various portions of each listing, but no tooltip appears. For these products, I guess I still need to navigate to a details page to purchase them.

Newforyou

Moretoexplore

How about the search results page? A quick search for "Cory Doctorow," my new favorite sci-fi writer, returns three pages of results. The very first item is the one I'm looking for: the short-story collection "Overclocked: Stories of the Future Present." Once again, Amazon is reading my mind. But try as I might, I can't find a tooltip or an "Add to Cart" button. Once again, I'm forced to load an entire new page - with several scrolls worth of extraneous data - just to purchase something I've already decided I want. This isn't so bad when I visit the site to search for a single item. But how about those times when I come with a list of 10 new tech manuals to purchase? The number of pages I need to load is twice what it should be. God forbid I don't have broadband.

I understand why this sort of thing happens on big sites. Amazon runs tons of betas, often simultaneously, to gauge the effectiveness of individual UI tweaks based on rigorous metrics. Interface refinement is about testing new ideas without re-architecting your entire site or totally confusing your existing user base. I have no doubt that the search-results page and the three upsell modules I'm testing are all maintained separately, perhaps by separate teams. If the Ajax functionality in one of them proves successful, it will eventually make its way to the others.

Still, in the meantime, users are left with a UI whose inconsistency casts doubts about the validity of any data it generates. How can a new feature win over your users if it's applied arbitrarily?

Ironically though, unliike most of Amazon's little DHTML/Ajax tweaks, I think this one is executed almost flawlessly. You can barely see it on a fast connection, but there's a nice little animated "loading" bar graph to provide status on your XHR. The telescope effect on the tooltip itself is subtle but nice. I might quibble about the rendering logic, which allows the tooltip to scroll off the page rather than shifting it fully within the viewport. Still, I know how difficult that logic can be to pull off on a templatized, highly dynamic site. Overall, this is an extremely well though-out feature that should make it faster and easier for customers to drop some cash. Let's hope it makes it onto the entire site.

Technorati Tags

Ajax Intervention: Tivo.com online scheduling

Welcome to Ajax Intervention, in which we dissect how major websites misuse, or fail to use, Ajax to improve their user experience.

Up this time: Tivo's My Tivo online scheduling tool, which could use an emergency Ajax intervention.

As much as I love my Tivo digital video recorder, it's no fun to schedule recordings on a television screen with a remote-control joystick and a virtual keyboard. But thanks to a wireless card and the online My Tivo service, I can schedule a program from any web browser as little as an hour before it's set to air. The service was originally billed as a tool for last-minute scheduling when you're away from home, but I use it even when I'm sitting in the same room as my DVR. Web interfaces are just easier than Tivo's on-screen menus.

That said, the My Tivo interface could use an update. Given the small number of ads that appear on the site - most of them 120x120 buttons with shallow inventory - it's hard to imagine Tivo is earning much money from all the extra pages its users are forced to navigate just to schedule a Season Pass of their favorite show. The process goes something like this:

  • Visit the "Online Scheduling" page in My Tivo.
  • Enter a program in the search box.
  • Receive a results page.
  • Click on a show's title.
  • Receive a program details page.
  • Click "Get a Season Pass."
  • Receive the recording-options page.
  • Choose your recording options.
  • Receive a confirmation page with no compelling content.

Picture_1_2

Picture_2_2

Picture_3

Picture_6

Picture_4

Picture_5


That's a minimum of five full pageloads just to schedule one program, without a bit of Web 2.0 goodness in sight. Sure, there are some DHTML tabs at the bottom of the program details page. But that's about it.

I'm not just talking about the lack of Ajax, either. The Tivo set-top box is all about personalization; based on your ratings of shows you've recorded, it can predict which shows you might like and predictively record these "Tivo Suggestions" for you. But any such personalization is buried in the Tivo web interface, inside a DHTML tab at the bottom of the program details page.

Click it and you'll learn, for instance, that lovers of "Buffy the Vampire Slayer" also enjoy "Angel," "Charmed" and "The X-Files." But there's nothing to suggest these canned recommendations are based on my own viewing habits; in fact, I've given "Charmed" the dreaded "three thumbs down" rating on my own Tivo box and it's still showing up here. Why on earth isn't this content specifically targeted to me? If the content were compelling, maybe it wouldn't deserve to be socked away inside a tab.

Now let's imagine how My Tivo might look with an Ajax overhaul and better personalization.

  • Visit the "Online Scheduling" page in My Tivo.
  • Enter a program in the search box.
  • Thanks to Ajax autosuggest, receive an inline list of the most likely matches. Click on the one you want.
  • Receive a program details page.
  • Click "Get a Season Pass."
  • Thanks to the power of Ajax, receive a lightboxed recording-options dialogue and choose your options without leaving the page.
  • Within the same lightbox, receive a confirmation message that includes personalized recommendations for additional shows.

By replacing three page refreshes with Ajax calls, we can reduce the process of scheduling a Season Pass down to two pages and, with better data mining on the server side, throw in personalized recommendations, too. If you've noticed that the UI I'm describing is a complete Netflix ripoff, well, duh. Why shouldn't Tivo - the company that invented the DVR market and then watched inferior operators eat away at its market share and profitability - take a page or two from the playbook of the company that's almost single-handedly decimating Blockbuster? Netflix operates like an Internet company, not an entertainment company. Tivo should follow suit.

Sure, Tivo continues to leverage wi-fi, desktop software and content partnerships into an impressive array of services. Its set-top boxes really can function as wireless entertainment hubs. But Tivo behaves, fundamentally, like a moribund hardware maker. It treats its web offerings like inferior adjuncts to the set-top experience, thereby neglecting a powerful means of product differentiation. And really, with the entire country laying odds on how long you'll stay afloat, shouldn't you pursue every possible avenue to improve your product?

Crappy cable-provider DVRs lack Tivo's intuitive UI and powerful wireless integration, but they're in a lot of homes thanks to competitive pricing and the marketing muscle of Comcast, et al. Meanwhile, true geeks can roll their own DVRs using commodity PC hardware and open-source software. Tivo's best hope for the future involves beating the cable companies on features and beating the DIY crowd on ease of use. A solid web UI would be a nice step in that direction.

Mash note: Remember the Milk

You've got to love a Web 2.0 startup manned by a dev team of 2 that manages to add every feature on your wish list just before said feature's omission really starts to bug you. That's the case with me and Remember the Milk, a to-do-list webapp developed by an Australian company and supplemented by awesome new features with astonishing regularity.

Although they're a commercial entity, they've got a beta API that's allowed the development of a handful of really cool mash-ups. They've had iCal integration and a gCal plug-in for ages. They got on the Twitter bandwagon really early. They were one of the first non-Google companies to port their application offline with Gears. Last but not least, they've got a powerful (though still not perfect) user interface. (More on that later.)

A little background: I've been an obsessive to-do-lister since high school. GTD is my mantra. During my years at Microsoft-centric companies, I used Outlook to manage my entire life. But these days I find myself on Windows, 'nix and OS X machines in disparate locations for hours or days at a time. A webapp is clearly the only way to go for my to-do needs. But after years as an Outlook power user, I need something that will slice and dice my many lists (work, play, home, shopping, whatever) with exacting precision.

I gave Apple's iCal a shot, but its list functionality was way too primitive. I need multiple lists, categories, tags, flexible sort criteria - you get the picture. Ta-Da Lists from 37signals was even more stripped-down than iCal - plus I found its interface surprisingly clunky for something developed by a well-regarded Ajax shop. I thought about todo.txt, but I'm not enough of a command-line purist to completely abandon the GUI - even after years of suffering through Outlook's hideous hidden menus. Then, about a year ago, I stumbled on Frank Gruber's Do More: Online To Do Lists Compared. I didn't agree with his conclusions, but at least he gave me several more options to explore. Luckily for me, Remember the Milk was the first one I tried.

There's a lot to love about RTM, especially its UI, so just let me gush for a minute.

  • Flexible organization: You can create multiple tabbed lists, apply arbitrary tags to your tasks, and create saved searches based on any criteria.
  • Keyboard navigation: Except for a few advanced functions, such as moving items from one list to another, you can do almost anything from the keyboard. Create tasks, set priorities and due dates, apply tags, edit multiple items ... most functions take only a single keystroke.
  • Natural language entry: You can set due dates and repeat intervals using some pretty flexible natural language. It ain't perfect, but with a little training the syntax becomes second nature.
  • SMS, IM and email reminders: The service can nag you quite effectively via a wide range of communication protocols.
  • Email, gCal, Atom and Twitter integration: You can create tasks or lists of tasks using a special email address; add or edit tasks directly from gCal and Yahoo plug-ins; and use Twitter or Atom as syndication services. The public API means that mash-ups and cross-pollination will only proliferate.
  • Built-in collaboration capabilities: There are a host of features dedicated to assigning, sharing and collaborating on tasks.
  • Serious accessibility: The main app is fast, powerful Ajax all the way, but the mobile version works just as well in a variety of more specialized user-agents.

There are a few things to hate:

  • Poor multi-list view: The main Overview page list all of your tasks that are due, overdue or due tomorrow regardless of which list they're on. But it separates the Today, Tomorrow and Overdue tasks into separate tabs. The gCal plug-in does a much better job of showing all of your most important uncompleted tasks in a single, unified view.
  • Recurring task weirdness: Delete a completed instance of a recurring task, and you've just deleted the master version of that task. After any previously spawned instances are completed, the task will no longer recur. This is a very strange user experience, especially for folks who like to purge their completed tasks every once in a while.
  • Poor sortability: Tasks are sorted by their priority. Period. This shortcoming doesn't account for the fact that a low-priority task that's a week overdue is probably a high-priority task by now.

See the strikethrough text above to see exactly what I meant about the RTM team rolling out your must-have features before the lack thereof becomes too annoying. I've been dying for flexible sortability on RTM since I started using it. But no sooner did I start this post than I noticed an RTM blog post announcing just such a feature. It would be nice if you could set your sort preference globally as well as one list at a time, but that's a minor quibble.

So what can we learn from my ramblings, besides the fact that I really, really love this platform? I think there are a few powerful lessons for developers of any RIA:

  • You don't have to sacrifice brawn for the sake of simplicity: Pleasing power users doesn't mean hopelessly confusing everybody else - at least not with smart UxD. (Apple could stand to learn that lesson, but I digress.)
  • You don't have to sacrifice accessibility in the name of Ajax: Let your mobile app function as your accessible app, too.
  • You don't have to fear Web 2.0 trendiness: Rapid adoption of emerging protocols such as Twitter can only help you differentiate your product and find new users.
  • You don't have to lock your app down, even if you're a commercial enterprise: Public APIs - and the cross-pollination they enable - can only strengthen your foothold in the marketplace. In our Googlized world, this one's kind of a *duh*, but it bears repeating.
  • You don't have to hide from your users: An active blog and well-maintained user forums are far more powerful marketing tools than terse release notes on Google Code.

I can only speculate as to the future of GTD's business model or exit strategy. Their logo carries the ubiquitous "Beta" tag, and their pages carry no ads. Where's the funding? It seems like somebody's waiting to get snapped up by a big player....

Lord knows it would be nice to have the old  Outlook/Palm OS quintet of email, calendar, contacts, notes and to-do lists available on a single web-based platform; personally, I would prefer that platform to be Google, though I can't really see them acquiring a start-up just for this one capability. Still, it would be a shame if a product as solid as Remember the Milk got lost in the shuffle or edged out by inferior offerings from bigger players. Only time will tell....

SOA meets Ajax - APIlitAx: an Alternative Interface for Google AdWords

In the deluge of social bookmarking, weather ticker, and notepad applications, it's always nice to see an application come along that isn't a toy. APIlitAx (ugly name, I know) is an alternative interface to the Google AdWords system. It seems to have been developed by some folks at google and has been released on Sourceforge. As an application, it is very different from most of the stuff coming out of Google these days, which seems focused around the GWT technology. This applications doesn't use an existing Javascript framework, i.e. it's all custom Javascript, and uses PHP on the back end to proxy requests to AdWords via the APIlity library (PHP API for AdWords).

screenshotCampaignView.png

The developers have been careful to make the application non-blocking, i.e. you can interact with parts of the interface while another part updates. This is probably an emerging best practice for Ajax apps: don't just make lots of small blocking requests. Design your apps so that you can make small, non-blocking requests.


Technorati : , , , ,

The Bonehead File - NewsIsFree Newsmap

A friend of mine pointed me at this "nifty Ajax news map" from Newsisfree. These guys have been doing stuff with RSS for a long time. If you needed an RSS feed for a publication that was so behind the times that it didn't have one, Newsisfree gave it to you. At a first glance, it looked pretty slick, with sliders, drop downs, pop-up windows and the ability to change both the language and category you're looking at, all without reloading the page.

www.newsisfree.com_newsmap.png

So I settled in to investigate. Half the fun in reviewing all of these Ajax applications is in figuring out how they work. My tool of choice for this is the Firefox extension Firebug, the "view source" of the Ajax age. (Face it, these days if you do a literal "view source," you'll have no idea of what's going on.) After loading up the news map, I popped up the debugger and took a quick glance at what JavaScript files were included. At first glance it looked promising: there were prototype.js and moo.fx.js. I prepared myself mentally for some heavy Ajax lifting.

Next some bad news. I noticed a message in the status bar that said "Applet HoneycombLoader started." What a downer, I thought, but then again people are combining Ajax and flash so why not Ajax and applet's? A few more moments of investigation revealed the awful truth: the only Ajax on this page was triggered by the two select boxes at the top -- one for category the other for language. The actual Ajax bit was a request to a PHP script that returned a JSON object that contained a URL. This URL was then used to change the content of the IFrame that held the applet. That's it. Here's the callback that does the business:

function getMapProcess(Request)
{
lightWin.hide();
try { var res = eval('('+Request.responseText+')') }
catch(e) { return hpe.error(e) }
if (res.response_code>=300) {
alert("Failed to generate map");
} else {
var f = $('mapcontainer');
f.src = res.htmlfile;
}
}

This static information could have simply been hardcoded in a JavaScript lookup table and used to change the contents of that IFrame. All that the XHR did was move that static lookup table to a PHP script on the server. All those slider and popups were part of the applet.

I hope this little bit of superfluous Ajax wasn't used to sell the product. Maybe I shouldn't be so bothered about it, but I was so looking forward to analyzing its workings. It's still and interesting app, though; it just doesn't really have anything to do with Ajax.


Technorati : ,

Using Bookmarklets to Disruptive Effect

But any big change is more likely to result if there is a disruptive event such as new technologies or platforms that have a surprising effect on market share. -- Trip Hawkins

My consulting company is relatively small, so I love disruptive technologies. I see them as opportunities to sneak up on the big boys. I suppose that if I were one of the big boys, I wouldn't be so enthusiastic about disruptive technology. But there it is. Bookmarklets and Greasmonkey are just such disruptive technologies. They let you create mashups and manipulate pages in ways that were not intended by the original authors. They are a way to make content and sites work better for you.

While Greasemonkey lets you automatically execute scripts after page has loaded and allows you to make XHR requests to other domains, it requires a user to install a plug-in that isn't easily available for all browsers. Bookmarklets, on the other hand, are as easy to install as a bookmark, but they require a user to click or select a bookmark in order to work.

Last time, we saw how to load additional JavaScript into the browser in order to exceed the size limits of the bookmarklet itself. This time we're going to hack the front page of the New York Times with our own news. First, we need a bookmarklet that will load our actual script. We simply adapt our code from last time to load our nyt.js script.

javascript:(function(){var s,d=document,a=function(o){d.body.appendChild(o)};s=d.createElement('script');s.type='text/javascript';s.src='http://labs.pathf.com/bm101/nyt.js';a(s)})();

The code simply inserts a script element that points to our JavaScript file. You can see the live link below.

Drag the following link to your toolbar or bookmark it:
NYT Hack

If you now navigate to the New York Times home page and click on the link, you should be able to see some stories about Iraq inserted above the fold.

nythack.jpg

How did I do this? Well, it's all about what I packed into that nyt.js file. What's in there? Well, first I added in JQuery, my favorite Javascript library of the moment. Since the New York Times site doesn't use Prototype or anything that declares a $ function, we don't have to take any special precautions. Next, I defined a utility function to load in a script from a URL:

// NYT Funcs

var NYTHack = new Object();

NYTHack.addScript = function(url) {    var scr = document.createElement("script");    scr.type = "text/javascript";    scr.src = url;    $("body").append(scr);}

This is the same trick as earlier. Instead of performing an XHR, we inject Javascript which is executed withing the context of the current page. And what do we inject?

NYTHack.insertYahooNews = function() {    // insert the yahoo news script tag with a callback    NYTHack.addScript('http://api.search.yahoo.com/NewsSearchService/V1/newsSearch?appid=YahooDemo&query=iraq&results=5&language=en&output=json&callback=NYTHack.callBack');}

// run me$(document).ready(function(){    NYTHack.insertYahooNews();});

We load from Yahoo's News Search Service. Why Yahoo? Because they let you specify JSON as the output format and further specify a callback function, to which the JSON object is passed as a parameter. Our callback (along with a utility function) looks as follows:

NYTHack.buildStories = function(div, json) {    var stories = json.ResultSet.Result;    for (var i = 0; i < stories.length; i++) {         div.innerHTML += '<h4><a href="' + stories[i].Url + '">' + stories[i].Title + '</a></h4><p>' + stories[i].Summary + '</p>';    }}

NYTHack.callBack = function(json) {    var div = document.createElement("div");    div.id = 'nythack';    div.style.border='1px solid #ff0000';    div.style.padding='5px';    var hl = document.createElement("h2");    hl.innerHTML = "Iraq News from Yahoo!";    div.appendChild(hl);    NYTHack.buildStories(div, json);    $("#mainTable").before(div);}

Nothing fancy. We just pull titles, summaries and url's out of the JSON object and construct a set of headlines and links. Then we insert it ahead of the main content section of the NYT home page.

Now we don't do any error checking and you can run this bookmarklet in other pages than the NYT home page. Adding those in wouldn't have been too onerous, but it would have distracted from the main focus of the bookmarklet and cluttered the code. Ideally we would check in the bookmarklet itself to see whether we had already loaded it once by looking for a hidden div element with a particular id.

Next time we will actually use the information on the page to drive what our bookmarklet does and we will use the site itself as a web service using Sarissa.

 
  Technorati : , ,

Topics: ,

Application Watch - Valoony: Ajax Enabled Comparison Shopping

The German comparison shopping site Valoony has launched three new Ajax enabled comparison shopping mini apps: one for digital cameras, another for perfume, and -- my favorite -- one for wine.

valoony.jpg


The interface allows you to adjust various numerical parameters using sliders, select brands, types and specific stores, and enter search terms, etc., all of which cause the right hand content panel to update via XHR. On Joe Walker's 4 States of Ajax Adoption, I'd say this is state #2 -- Progressive Enhancement. The interface still uses IFrames and more traditional pre-Ajax techniques. Also, you can easily get into a confused application state by using the browser's back button instead of the "Zurueck" button in the page.

From a user experience perspective, I'm not sure this particular use of Ajax improves my shopping experience or is something that couldn't have been done before with Javascript and IFrames. Then again, I don't know what the old shopping experience was like, so this may be a vast improvement. It's certainly much better than my last frustrated fumblings on CNet. Also, I got an excellent deal on a 1996 Brunello. ;-)


Technorati : ,

Topics:

Bookmarklets 101

Today I want to build the "Hello World!" of bookmarklets. Actually, I'm going to build two versions, the second of which will allow us to do bigger and better things than the first. So, what exactly is a bookmarklet? It's a bookmark that points to javascript instead of a web page -- javascript:... instead of http:.... This Javascript then runs in the context of the current page -- sort of a Greasemonkey script that you invoke by clicking or selecting a bookmark.

If you're using Firefox, this is going to be a whole lot easier than if you're using IE, Opera or Safari. In Firefox, you can drag a link to your toolbar and have it easily available for use. In IE and Opera, you can bookmark the Javascript link and have it available in your bookmarks dropdown menu. As far as Safari goes, not all bookmarklets work in it -- as we'll find out, there's not really enough space in a bookmarklet to do much cross browser support --, but this won't really be a problem for us given this bookmarklet's code and the direction we are going with the second version.

OK, here's the first version. It's about a simple as it gets:

javascript:alert("Title: " + document.title);

You can try out this bookmarklet below.

Drag the following link to your toolbar or bookmark it:
Title

IE will complain (provided your system has the latest security patches) about adding an unsafe bookmark. Browse to a different page and select the bookmarklet and you will see that it correctly displays the page's title. So far so good.

What if we want to do something more substantial, say write a bookmarklet that would inspect the DOM of a page and modify it based on some sort of algorithm? Well, bookmarklets can only be so large -- no more than 255 characters in some older browsers, a few thousand characters in the case of the newer ones. If you're going to write bookmarklets that do interesting things, where are you going to put the code? One approach, is to use an Ajax technique known as DOM-based on-demand Javascript. That's just a fancy name for inserting a script element into the DOM of the current page. There are lots of bells and whistles we will add in future examples, but for the moment we will keep it simple.

The second version looks like this:

javascript:(function(){var s,d=document,a=function(o){d.body.appendChild(o)};s=d.createElement('script');s.type='text/javascript';s.src='http://labs.pathf.com/bm101/hello.js';a(s)})();

At the top level we are declaring an anonymous function and calling it, all in one step -- (function() { .....})();. The code creates a script element, sets its type and source and appends it to the document. We've used lots of dereferencing to save characters, such as assigning d=document. Now, on the server-side, we create a little JavaScript file that contains our familiar alert statement:

alert("Title: " + document.title);

Try out our new example:

Drag the following link to your toolbar or bookmark it:
Title2

OK, so what's the big deal? Didn't we just do the exact same thing in a more complicated way? Yes and no. Yes, the new bookmarklet does exactly what the old bookmarklet did but in a different way. It included a JavaScript file into the context of the current page. Into that file we could have put as much other JavaScript as our hearts desired. We could even, with some precautions, have included our favorite Ajax library to manipulate the DOM and make asynchronous requests. The bookmarklet thus becomes just the leading wedge that allows us to load in more substantial program logic.

For a Web 2.0 example of a bookmarklet, have a look at Blummy, which allows you to share useful bookmarklets with other users. A word of warning, however, about bookmarklets: you're inviting someone else's code into your browser. Once in, they can do a great deal of mischief. When evaluating bookmarklets ask yourself, "how much do I trust this company or individual?"

Next time we'll go beyond the mere "Hello World!" and try to be a little bit more disruptive.

 
  Technorati : ,

Topics: ,

More Javascript Code Generators and Another Ajax OS

So, I missed two Javascript code generators, found the new home of a third, and found one more Ajax OS beastie. First the code generators:

  • ParenScript has a new home. This is the Lisp->Javascript code generator. An example:
    (js
    (defun foobar (a b)
    (return (+ a b))))
    

    and the Javascript:

    function foobar(a, b) {
    return a + b;
    }
    
  • ST2JS - A smalltalk to Javascript translator. Not a project overflowing with documentation and friendly explanations.
  • jsc - this is another C# (or ) to Javascript code generator.

    The compiler extracts CIL from a .net assembly. It filters out the classes which are marked with the ScriptAttribute. It selects the target language and emits the source.

    I've already blogged about this tool once before, but it does belong in any listing of Javascript code generators, so in it goes.

Next, on the heels of our entry on Atomic OS, we have another cute little command line shell toy in Ajax: JS/UIX Terminal.


jsuix.jpg

It's cute to be able to play invaders in the browser, for about 5 minutes. Under the covers, it purports to be an OS written in Javascript, implemented on top of the browser:

JS/UIX is an UN*X-like OS for standard web-browsers, written entirely in JavaScript (no plug-ins used). It comprises a virtual machine, shell, virtual file-system, process-management, and brings its own terminal with screen- and keyboard-mapping.

Cute as well, and probably an interesting learning experience. Not sure if the OS on top of the Browser is where the future of Ajax is. Abstracting services down to that level seems like overkill.


Technorati : , , , , ,

AtomicOS - Another AjaxOS

What's bigger than a framework? An Operating System. While many of the Ajax OS's that bill themselves as Operating Systems are nothing more than a pretty desktop metaphor, there is at least one project that aims to build an Ajax OS from the ground up: Atomic OS. It has a ROM and a Kernel and build itself up much like a real operating system on real hardware. The only difference is that everything is written in Javascript. It's interesting what happens when OS design principles are applied to the browser.

It's still under development. If you want an early taste, you can look at it's predecessor, WAJAX. That's already pretty impressive, so I look forward to Atomic OS.

wajax.jpg


Technorati : ,

Topics:

The Hazards of Exposing Business Logic on the Client, Part II

A double dose of "I told you so" today: as it turns out, stealing an idea is hard work, while stealing an implementation is dead easy. By that I mean that if you want to steal a server-based web application, you either have to hack in to steal the code or do the hard work of reverse engineering and coding a clone. But if you're developing client-side code in JavaScript, you are vulnerable to theft. It's the recurring theme of Ajax and Leaky Business Logic, and I'm going to keep talking about it until it doesn't happen anymore.

You remember the incident where the image editing webapp Snipshot was ripped off by Cellsea? Well it looks like it's happened again, this time with one of Emil Eklund's WebFX tools -- LiteSpellChecker -- being ripped off by SpellingCow. Emil reviews the code and appearance of his original program with the derivative one and finds several suspicious similarities. His program was a demo, but copying code whether demo or not without attribution is a big no no.

If you are going to write business logic on the client side rather than just sticking to display logic, you need to at least obfuscate your code to make maintenance and reverse engineering a headache. Better yet, stick to writing Ajax applications in server-side frameworks like Echo2 and ZK.

Update: Thanks to Doug Clinton for pointing out the update from Emil. I guess all I can add is the only thing that makes this not a ripoff is Emil's laid back attitude.


Technorati : , , ,

About Pathfinder

  • We design and build extraordinary applications for companies looking to make the next great idea a reality.
  • learn more

Topics