The HTML structure of webmail interfaces: Gmail, Hotmail, and Yahoo Mail

As part of the Zentact project I’ve been working on, we were asked to integrate with various webmail clients. This makes it easy to manage your contacts while sending email.

Doing this was a bit of a pain. Since all code is minified, and they all use Javascript events differently, there was a good bit of working to figure out the details. I wanted to share this info in a blog post for programmers who come along in the future. If you don’t know/care about HTML, Javascript events, the DOM, YUI, or AJAX, this post is not for you. Please enjoy one of my other fine posts, perhaps this post on military code names.

Before I begin: there was a ton of info learned (and already forgotten) about this process. This is not a complete guide, but is mostly a brain dump from implementing UI integration on three different webmail interfaces.

  • Gmail uses 6-character strings, [A-Za-z0-9] for all its classes. These classes remain the same from load-to-load, but I believe that they may change over time with minification. IDs are not as constant, and many are dynamically assigned. These start with a colon.
  • When you’re working with events, you may get inconsistent results. Some events are not fully propagated, they get captured and you can’t find out about them. If onclick doesn’t work, try listening for onmousedown or onmouseup. One of them may get you notified of the event you want. Same advice goes for onkeydown, onkeyup, and onkeypress. That being said, once you get into these, be sure to realize that these three events will occur in particular orders. Make sure you’ll be getting notified at the right time.
  • All of the webmail UIs use iframes. This lets them keep their code for loading the UI separate from the code to display the UI. I know there’s some cross-site scripting implications in this, but I’m not sure of all the details. Gmail’s loading screen (the loading bar they show you) is a different iframe than the one that shows you the inbox. All of these iframes are at the root of the document, and there’s nothing else in there.
  • You could use Firebug break points to pause the code and examine what’s going on, but nearly all JS is minified. Since breakpoints can only be set by line, and there’s multiple functions defined per line, it ends up not being helpful.
  • For its UI, Yahoo seems to use YUI, plus some other stuff on top of that. There’s some weird results because of this. The body of the email editor is a group of DIVs, some are invisible, some are for border decoration, and others are for the background of the editor.
  • When we inserted elements into Yahoo Mail using regular DOM operations, they would appear behind other page elements, until another part of the UI was interacted with, when the screen would redraw and then they would bump into place. YUI seems to have its own redraw/repaint functionality, and it won’t play nice with DOM manipulations.
  • Hotmail is strangely one of the less-exotic interfaces. They use consistent IDs. I don’t think they’re hand-coded, however, because they submit to a naming scheme that seems too machine-generated. But still, they are there, and you should take advantage of them.
  • When you’re using events, and you get notified of an event, use the event.originalTarget property to find out where in the DOM you are. That’s useful information when you’re dealing with a DOM tree of nonsense class names and IDs.
  • When you’re trying to figure out where in a DOM tree you are, don’t hesitate to go up several levels and check a great grandparent node, or a “cousin” node. Once you get a single point of reference, you can generally work out where everything else is, relative to it.
  • Some UIs open each message in its own iframe, which means that IDs are consistent since they’re in their own namespace.

Also, thanks to Nate Koechley for helping me get through some of the Yahoo details.

If you’ve got other questions, shoot me an email. I remember more stuff, but might need a good question to shake it loose.

Code reviews

I’ve been quoted in a series of articles at CIO.com on code reviews. The two particular ones I’m in are

Neat!

The author of the articles is Esther Schindler, who has also written articles like “Four Non-Obvious Things Pink Floyd Can Teach Your Team“. I <3 analogies.

acts_as_presenter

Hey kids! Guess who’s presenting at Acts as Conference, 2009! These guys! Also, some guy with a big nose.

I’m giving a talk on OAuth, the greatest way to protect your APIs while keeping your users secure. Simple, easy, fun, and it might even get you laid. The amazing, spectacular, splendiforous OAuth! Yea. It’s gonna be that good.

And now, for the official marketing:

Acts as Conference 2009 is a two-day Rails conference that will make you a more competitive Rails developer by learning from those driving the innovation that is fueling the Rails community. Held February 6th and 7th in Orlando, Florida, Acts as Conference features a great speaker lineup, free food, a chance to meet with Rails innovators, and a live via video Q&A session with David Heinemeier Hansson. At $125 dollars and limited to 175 attendees, the conference will sell out fast, perhaps faster than last year. Register today at http://www.actsasconference.com. See you there!

Zentact reaches out to web and says hi. Web waves back.

It’s official, Zentact is live. This is the product that Cloudspace has been building for the past several months for John Sampson, Eric Marcoullier, and Jared Brandt (who also makes some damn fine wine).

The skinny of Zentact is that it’s an address book with a Firefox extension that lets you know when someone in your address book might be interested in the page you’re viewing. Go to the site and give it a whirl.

It has been an exciting day. Watching the comments roll in on Twitter is awesome, and so is watching the emails go out from Zentact.

Mashable loves us. So do the fine folks at ReadWriteWeb and VentureBeat. And finally, an excellent review of Zentact from Mr Howard Lindzon. Also, coverage from some unbiased sources, like Cloudspace. 😀

You should check it out. You’ll need a invite code, and you can use TIMZEN. Or, just sign up with this link, which magically includes the Zentact invite code. Let me know what you think.

A Javascript debugging tip for Firebug (or “Stop using alert()!”)

Did you know that if you’ve got Firebug for Firefox installed, you can use it for debugging your own code? By calling

console.log("Here's a message!");

Firebug will print the message to it’s internal message log. Neat!

Firebug message console

Now, that’s all good. But let’s say you’re on a project that’s not using a Javascript preprocessor to minify and strip debugging code — which would be the best option. You want the benefits of debugging, but not having to constantly remove debugging code for deployment. If a user doesn’t have Firebug installed, they won’t have a console object. So obviously leaving your debug code in is going to cause an error.

Or will it?

Try adding this code before any of your other Javascript. It will set up a fake console so that if Firebug is not installed, there won’t be any errors.

if(!console || !console.log) {
var console = new Array();
console.log = function () {}
}

Bonus idea! If you combine the idea shown here, with my previous post about debugging Firefox extensions, you can see how to prevent extension debugging from getting in the way of your users.

if(!Firebug || !Firebug.Console || !Firebug.Console.log) {
var Firebug = new Array();
Firebug.Console = new Array();
Firebug.Console.log = function () {}
}

How to use Extension Developer’s Extension in Firefox 3

Here’s a tip for developing Firefox Extensions in FF3.

You might have heard of the Extension Developer’s Extension (EDE). EDE is an extension that provides useful settings and features for people who are writing their own extensions. For example, EDE makes it easy to activate Javascript debug settings, interactively debug Javascript, and a few other goodies.

My personal favorite feature is the “Extension Builder” — it that lets you install a development copy of the extension . That is, you can run an extension from your working copy/dev folder. Without EDE, you’d have to — uninstall an extension, restart Firefox, install, restart — every time you wanted to test a change. With it, you can just restart Firefox one time, and your dev extension is reloaded. When doing heavy development, I have personally saved over an hour per day from this one feature.

The sad part is that this feature does not work in FF3. The option is just grayed out. But, there’s a workaround. Load up FF2 with the same profile that you use for FF3. Use EDE to install the extension from disk like you normally would. Then, quit FF2, and launch FF3. Since the extension is tied to your profile, FF3 will load your extension from your dev folder, just like in FF2.

Win!

Gregg’s “Speeding up Ruby, without the Rails” Presentation

Gregg’s “Speeding up Ruby, without the Rails” Presentation

He points out that the C library stuff is going to cause blocking, because Ruby’s threading manager doesn’t know when it can stop execution. He demos this with mysqlplus, showing 10 queries with the blocking driver, and then showing mysqlplus which is the non-blocking driver. 10x speedup.

He points out dbslayer, which sits between processes and MySQL, and passes JSON out to the processes.

Starling (which uses memcached) is a good tool for job queueing. Looks like it sits on a single server, and serves up jobs when requested. He demoed putting integers into the job stack, could we put whole objects into the stack?

“What if I can’t find a C library to do what I want?” — use Ruby Inline. It lets you embed C code *directly* into Ruby.

Also, he is talking about ruby-prof, which is for profiling Ruby code.

gem install ruby-prof

Very nice stuff, but interpreting the output definitely requires some knowledge. One neat trick is that if you

require ‘ruby-prof’

You can start and stop the profiling so that you only get data from the parts of the code you’re interested in. Also, with this technique, you can easily output HTML formatted and linked code.

Interesting optimizing trick

“#{@var1} #{@var2}”

is faster than

@var + ” ” + @var2

because method calls are expensive, and the plus signs are method calls.

Another pro-tip: if you’re doing a switch-case, put the most common option at the top of the list — it cuts down on the number of compares that it will take to find the desired option.

In Rails 2.2, there’s a new function called “memoize”, which will automatically handle memoizing, so you don’t have to do a

@result ||=

Don't use .nil? calls, because method calls are slow.

if !value

or better

unless value

are better choices.

a, b = b, a # Nice trick for swapping two values

Link love for Gregg: http://www.envycasts.com His presentation style is excellent, and I guarantee you will learn at least one thing you didn't know before.

http://www.railsenvy.com/rubyconf/ This link has more info from his presentation, and source material

RubyConf 2008 Keynote by Matsumoto

Thursday AM Keynote by Matz

This is Matz: http://en.wikipedia.org/wiki/Yukihiro_Matsumoto

He’s talking about his love of languages, and why he got into Ruby.

He’s addressing some of the criticisms, that it’s slow, poorly implemented, embedding issues…he says the list of complaints goes on forever.

But, now he’s talking about why is Ruby good. He says people say it’s enjoyable, that Ruby made programming fun again.

He says he got into BASIC in 1980, and is talking about his problems with it. He says that one thing was the lack of being able to define data types. Everything is predefined, and you can’t change much.

He is talking a bit about LISP, and says some good things about it. He then complains about the parentheses in LISP, then puts up a slide that just says “No.”

He says he likes the aristocracy, as long as he is in power. BASIC gives you no power, LISP gives you full power. But, the problem is that at both ends of the spectrum, we lose popularity. It’s all about balance. You don’t want to go off the cliff of power with LISP, but you want to be able to be near the edge of the cliff — where BASIC isn’t.

He’s talking about why people choose Ruby. When he asks how many people choose Ruby because of Rails, about 60-70% of the room raises their hand. Matz points out that Rails is basically just a DSL for turning Ruby into a web language. He also points out that they are not at RailsConf, they are at RubyConf. This gets a laugh.

Again, talking about LISP, he says it’s a good DSL.

“There are under one million professional Ruby developers now, and we’re projecting there will be four million plus by 2013” — Mark Driver, Gartner analyst

Matz says “The future is bright…too bright maybe. Beware commercial success” He says, right now, we have the community and enthusiasm. In the coming years, we’ll have more money and more job titles. With these resources, come better implementations of Ruby. He says some of these are here now, but there will be more to make Ruby faster, more feature rich, and providing more satisfaction to us, the developers. He also says one of the great things will be all the new developers who are coming to Ruby, and he says “Welcome them, nourish them”. He says there are people who learn Ruby as a first language, and they go on to become great programmers. [Tim: I wonder what happens to people who start in Ruby, and then see C++]

He says he loves us all.

Arduino Follow-up

As a follow-up to yesterday’s post about Matt Williams’s presentation on Ruby and Arduino, here are some videos, slides, and notes from the ORUG site.

You absolutely must check this out. The field of robotics is going to play such a massive role in all of our lives over the next few years, and this is the ground floor.

*Going up?*