Thomas Fuchs
Hi, I'm Thomas Fuchs. I'm the author of the script.aculo.us user interface JavaScript library, a member of the Prototype core team and a Ruby on Rails core alumnus.
You're using my JavaScript work every day, even if you're not aware of it!
   Need corporate training or want me to speak at your conference? Contact me!

How we use mobile JavaScript in Freckle

October 15th, 2010

Earlier this year we launched a stylish mobile interface for Freckle Time Tracking specifically for iPhones, as these are very popular with our user base.

Instead of opting to make “small versions” of everything, we decided to optimize specifically for mobile use cases, and have the option to always switch back to the full version of the app in case you need more (the full version works great on the iPhone, too).

Here’s what we did:

Touch-optimization of in-page buttons

We use the touchstart event to make some interactions faster. For example, on our login screen, there’s a lost password? link. If you use just click events, there’s a noticeable delay when tapping, using touchstart instead makes it react immediately (in this case, there’s just an other form shown on the page, with no server roundtrip).

We also prefill the “username or email” field on the lost password form with whatever the user entered on the login screen, so you don’t have to type in stuff twice.

Fit forms into available space

The login form is just the right height to fit neatly on the screen in full when the password field is focused. Mobile Safari centers the page vertically on the screen, around the currently focused field. This way, the user can tap the “Sign in” button without having to scroll.

Always allow to use the desktop version

I hate nothing more than a “mobile theme” that breaks stuff and doesn’t allow you to use the real app or site. After all, Mobile Safari is a full-featured web browser. That’s why there’s a “desktop version” link on top of every page in Freckle. Freckle will permanently switch to the desktop version if you tap it—but fear not, in the desktop version there’s a “mobile version” link if you’re on the iPhone, so you can always go back.

Restrict to most common use cases

Mobile users of a time tracking application do two things most often: quickly log time on the go, and get an overview of what is going on. The dashboard (or “Recent”) gives you last 10 or so entries at a glance, and also allows you to log time immediately.

It’s important to optimize the experience for mobile devices, and that’s not just a reskinning. We completely rewrote our data entry code for mobile devices. Here’s how the form works:

It’s based around the idea of avoiding unnecessary taps, and really fast and efficient entering of time. For the time/minutes field, we’ve added big friendly buttons that allow you to increase to time by 1 hour, 30 minutes, 15 minutes or 5 minutes, with just one tap. They react fast (again, by using the touchstart
event), and you can just keep adding minutes or hours by tapping multiple times.

When you’re read to move on, you need to tap the iPhone built-in “Next” button. (Not being able to have your own big “next” button is actually a big gripe of mine, as you currently can’t focus fields programmatically on the iPhone, a big, big problem for designing effective user interfaces. There’s no known work-around for this, sadly).

The description text field will be focused, and you can type away! To remind you of the time you’ve entered in the previous text field, it’s shown on the bottom of the field. Tap the “Client or project” button to select a project. We show a list of projects that is made scrollable (with momentum!) by using Matteo Spinelli’s iScroll, a great addition to your mobile arsenal!

Once you’ve selected a project, hit “LOG IT” and, behold, it’s logged (without causing a page reload, we use Ajax calls for this).

Use SVG for charts

CANVAS is great, but SVG is really, really neat in some situations, and for charts, SVG just works better. Why? Because SVG scales. It’s vectors, not just pixels. The same drawing code, when used on hi-res displays, just automatically produces better quality output.

Plus, SVG is easy to do, with the great Raphaël library. Heck, the same drawing code even works on IE6 *gulp*. Plus, you get beautiful, beautiful DOM nodes that you can attach events and everything.

Don’t get me wrong, I love CANVAS, but SVG is super-awesome too.

Final thoughts

Don’t treat mobile sites or apps as just a miniature version of your website. It’s very different from what you do with a desktop app. Besides the obvious like a smaller screen and touch input instead of a mouse, the use cases tend to be very different and you’ll find some technical restrictions apply too (like no text field focusing with JavaScript).

However, if you put in enough work, you can make pretty awesome mobile apps with just HTML/CSS & JavaScript, and really give your users a great experience.

Note that the Freckle mobile site is still in beta, and we’re not yet 100% satisfied with the results yet—but it’s certainly getting there!

If you like to try out Freckle Time Tracking, all our accounts come with a 30-day free trial! Next to time tracking with no setup hassles we also have a Timer function for desktop browsers, complete invoicing with expense tracking, extensive reporting, a colorful and friendly interface, and some developer goodies like an API and easy-to-use GitHub integration!

Flipping images with just CSS

October 13th, 2010

You might have used the cool new transform CSS property to rotate, scale and move elements around already, but did you know that you can use it to flip images horizontally or vertically?

.flip-horizontal { -webkit-transform: matrix(-1, 0, 0, 1, 0, 0) }
.flip-vertical   { -webkit-transform: matrix(1, 0, 0, -1, 0, 0) }

You can add the same matrix transforms with -o-transform, -moz-transform and transform to target a wide spectrum of browsers.

Just add the flip-horizontal or flip-vertical CSS class to any element and you’re done!

See a live demo here (requires Chrome, Safari or other WebKit-based browser).

So how do you come up with those numbers?, you ask! Just check out this Wikipedia article on linear maps. Everything is explained in there (contains some maths, but nothing too hair-raising). See the examples first. The numbers in the matrices there correspond to numbers you give to the matrix function, in the order of top left, top right, bottom left, bottom right.

Learn more, much, much more at my HTML5 Mobile Pro workshop!

The long search for a terminal font is over

October 12th, 2010

I’ve looked at and used lots of fonts for programing and the command line over the years, but none ever really seemed quite right. I had a long love affair with ProFont, but unfortunately, the font has some issues such as swallowing up the sequence “l/” in Terminal.app.

But fear not, Apple bundled Menlo, a derivative of Bitstream Vera Sans Mono, with OS X 10.6 and the world of the command-line suddenly looked a lot brighter. What a nice font!

However, there are two problems I have with Menlo:

First, the shape of the number zero “0″ just isn’t right. I like my zeros dotted, not dashed:

“The zero with a dot in the center is the most common variation today. It seems to have originated as an option on IBM 3270 controllers. The dotted zero may appear similar to the Greek letter theta (particularly capital theta, Θ), but the two have different glyphs. In raster fonts, the theta usually has a horizontal line connecting, or nearly touching, the sides of an O; while the dotted zero simply has a dot in the middle.” – Wikipedia’s slashed zero article

Luckily, Robey Pointer released Mensch, a derivative of Menlo (so a derivative-derivative, hooray for open-source fonts!), which fixes that problem. Unfortunately, Robey also messed with various glyphs, most importantly the 1 and l, and the angle brackets, which is just to invasive for me.

My second gripe is line-height. If you use Menlo in Terminal.app, everything gets squished together, and there’s no setting to change that (actually, in Terminal.app there is; however not with other apps like MacVim).

Back to the drawing boards, Andre Berg released Meslo, another Menlo customization (image credits for above image go to Andre).

Meslo comes with a selection of line-height tweaks, and I decided on the M variety. It’s amazing. Only thing missing is the dotted 0.

I decided to ask Andre if he can add it (GitHub is social coding, after all. And social fonting, I suppose!) — and… to my surprise he did instantly! Thanks so much for that!

I now use Meslo LG DZ M at 13pt in both Terminal.app and MacVim. I’m finally in love with a programming and terminal font. Awesome!

If you like it too, you can download Meslo LG DZ here.

Quick and easy orientation detection for mobile sites

October 8th, 2010

Here’s one of the quick tricks we’re talking about in the HTML5 Mobile Pro workshop.

If you want to react to change in orientation of the device on mobile sites, here’s a quick and easy to use snippet, that just sets a “horizontal” or “vertical” class on the body element, so you can write some CSS to adapt your site:

document.body.onorientationchange = (function(){
  document.body.className =
    orientation % 180 == 0 ? 'vertical' : 'horizontal';
  return arguments.callee;
})();

That’s it–stick this into a script tag at the end of your page, just before the body tag closes and you’re good.

This code will set a class of “horizontal” or “vertical” on the initial load page load, depending on the orientation of the device, and will also set the class whenever the orientation changes later.

Learn the gritty details on how this works, and much, much more at my HTML5 Mobile Pro workshop.

JS1k intro: fun with CSS transforms and hardware acceleration

October 4th, 2010

Transforms and hardware acceleration are awesome. ‘Nuff said.

Watch the JS1k intro on a recent Safari or one of the hw-accelerated Chromium builds:
JS1k intro

The original presentation at JSConf.EU features a chiptune version of Eye of the Tiger. Play that in the background for ultimate geekery.

Source available on GitHub.

Help make JavaScript documentation better!

September 27th, 2010

JavaScript Reference, JavaScript Guide, JavaScript API, JS API, JS Guide, JS Reference, Learn JS, JS Documentation

JavaScript is awesome. I think we can all agree on that (or you’re reading the wrong blog, I suppose). The state of JavaScript documentation? Is not so great. Besides that we need a concerted effort to create better documentation resources and tutorials for programmers new to the language, the top hits for search terms like “JavaScript documentation” or “JavaScript tutorial” are all pointing at spammy SEO-optimized websites.

The JavaScript community is taking action now to solve this—please help us by:

1. Join Promote JS! and put up one of their generated-just-for-you banners up on your blog (best in the sidebar or footer!).
This will help getting valuable links for popular JavaScript-related search terms higher up in Google’s results, so that newbies use the Mozilla documentation and not one of the spammy websites.

2. Write posts! Articles about introductory JavaScript topics are in hot demand! Want some extra hits on your blog? High-quality articles about JavaScript are a good way to go and will help the JavaScript community as a whole!

Today’s newbies are the ones that will take over from us JavaScript gurus in the future! Let’s make it as easy as possible for them to actually learn the language and contribute!

Zepto.js, a minimalist JavaScript framework for mobile WebKit browsers

September 21st, 2010

Mobile WebKit based browsers (like those on the iPhone/iPad, Android and Palm webOS) provide really powerful DOM, JavaScript and CSS features. So why not use them in a framework, that’s specifically crafted for these modern mobile devices?

The ultimate goal really is to have a ~2k library that handles most basic dredge work for you in a nice API so you can concentrate on getting stuff done.

Say hello to Zepto.js! (grab the raw code).

Zepto.js supports jQuery-like syntax and API(including chaining) so if you used/seen that before, it’s easy to get started:

$('some CSS selector').append('<li>a new li element</li>')
  .live('touchstart', function(){ alert(this.innerHTML) });

$.getJSON('/some/service.json', function(obj){ /* do stuff */ });

Supported are basic operations like html, append, prepend, css, event delegation with live, transform-based animations with anim and ajax calls (get, post, getJSON). And all of this, thanks to WebKit’s rich features, in just 52 lines of code.

It weighs in at just half a kilobyte when minified and gzipped.

Because it’s so small, it’s easy to just stick it in a script tag directly. Of course, it’s certainly not complete yet, but what’s there already works quite nicely.

I’d love if you let me know about your ideas and feature requests about this! Please tweet @zeptojs or email me. And please go ahead and fork as much as you can on GitHub!

Go forth and use proprietary browser features

September 1st, 2010

Here’s why you shouldn’t be afraid to use proprietary browser features–especially with stuff that’s more experimental and explorative in nature:

First of all, lots of good things come from once-proprietary features. My favorite example perhaps is the .innerHTML property of DOM elements, that originated on Internet Explorer. This property is not only easier to use than (just stick any HTML string in), but also much faster than classic DOM manipulation. Now all browsers support this, no big surprise there.

Useful features will be carried over into the “browser mainstream”, and are standardized retroactively.

Almost all features available in modern browsers came from a browser vendor to scratch a specific itch, be it CSS Transitions, client-side storage and databases, extensions to the DOM such as CSS Selectors, 2D drawing surfaces, vector graphics, and so on and so forth. The list continues endlessly.

Early adopting of new features you find useful is a good way to see them broadly implemented.

Of course, some proprietary features won’t make it, or only in vastly different form (Google Gears come to mind). But mind you, it’s not that hard to adopt once things change. Client-side storage is client-side storage after all. APIs might also change (mostly in subtle ways) when they make the transition from proprietary to widely-adopted. If you do use these, you’ll probably have to check from time to time if everything works as expected on the latest browser version (if you’re serious about web development, you’re probably doing that anyway, as new browser versions can break existing, well-working code by introducing new bugs).

Most of the time, there are ways to cope with backwards-compatibility in case you need it, by falling back to other technologies (for example, a lack of WebSockets support might be worked around by using Flash). But, don’t concentrate on the problems, think about all the awesomeness you can create. Solutions to problems can always be found.

Participate on open-source wrapper libraries that are useful to more people than just you.

A great way to cope with this issue is to use libraries that wrap the proprietary APIs and can react to changes to the underlying APIs, or even use different underlying frameworks depending on the browser (for example, Raphaël uses either SVG or VML, transparently), and as a team, you can do so much more.

By developing a popular library you might even be asked to participate in the future development or standardization of the feature and contribute your experience with it.

Always watch out for new developments!

There’s always something going on. It pays to check out beta verions and nightly builds of browsers, and try out some of the wonderful features that are coming up (check out WebGL, for example!).

Don’t be shy, and don’t let yourself be told “But! You can’t do that! It’s against the Web-Gods will! No committee approved that!”

With that said, go ahead and create the next amazing thing!

So, what’s the status of hardware acceleration, really?

August 28th, 2010

It seems that Google Chrome is getting all the developer luv these days, but there are some facts that people get confused.

Here’s the deal: Google Chrome uses Apple’s WebKit HTML/CSS rendering engine that powers Safari. Google is not the creator of Webkit, Apple is.* What Chrome does is basically adding two components to the mix, Chrome’s user interface and a replacement JavaScript engine (V8, also used by node.js).

But, there are some parts of the Webkit engine that are either proprietary or are not easily ported to operating systems other than Mac OS X (or iOS). First and foremost among those parts is Safari’s ability to hardware-accelerate the compositing of web pages, including 3D CSS transformations.

These transformations and the added speed of the compositing are not available in Google Chrome (but they are on the way by means of a reimplementation). Neither are they available on Android.

Actually, regardless of what Google states in its design document about GPU accelerated compositing in Chrome (a good read otherwise, but they say hardware-acceleration is only available on Safari for Mac), there are several browsers “in the wild” that do support hardware-accelerated compositing (including 3D CSS), some of them cross-platform:

Here is the blurb from Safari’s features page:

Safari supports hardware acceleration on Mac and PC. With hardware acceleration, Safari can tap into graphics processing units to display computing-intensive graphics and animations, so standards like HTML5 and CSS3 can deliver rich, interactive media smoothly in the browser. Safari on Snow Leopard has improved hardware acceleration for plug-ins.

Tweet-sized conclusion: Hardware acceleration in (non-beta) browsers is only available on Safari (all platforms). There’s no hardware-accceleration (yet) for Chrome (or for Android).

(Other browsers will add support for hard-acceleration too, but it seems that all will be Windows-only for now, with both Firefox 4 and Internet Explorer 9 only supporting that platform.)

*WebKit was orginally created as a fork of the KTHML rendering engine. While the main development effort is done by Apple, patches come in from a lot of sources, and companies like Nokia, Google, RIM and Palm are all contributing, mainly to support their specific branches and platforms. Some of the ideas found in Google Chrome, namely the sandboxing of individual tabs, will make their way into WebKit2, a refactoring and reimplementation that is currently underway.

Creating awesome CSS3 animations

August 27th, 2010

Yarrrr!! Meet Captain Track, the awesome animated CSS3 pirate!

First, grab a WebKit-based browser, like Safari (preferably, because it supports hardware-acceleration!) or Google Chrome and head over to timebemoney.com and say “yarrrr!” to Captain Track!

Note that on the iPad and iPhone, these animations run with a full, super-smooth 60 frames per second, because of all the hardware-accelerated glory in Mobile Safari.

The best thing is that all this glory will eventually come to all browsers, so don’t get left behind and start using this awesomeness now.

Here’s the whole animation dissected:

Arm & Map

The arm & map image is a transparent 24-bit PNG (note the translucent brownish shadow).

This image is absolutely positioned, and rotated around a point on the left border of the image, a bit down from the center, so it appears that the arm is rotated around the elbow of Captain Track.

@-webkit-keyframes arm {
  from { -webkit-transform: rotate(0deg); }
  70% { -webkit-transform: rotate(9.7deg); }
  to { -webkit-transform: rotate(0deg); }
}

#arm {
  position:absolute;
  left:360px;
  bottom:0;
  width:246px;
  height:210px;
  background:url(img/arm.png);

  -webkit-transform-origin:0% 60%;
  -webkit-animation:arm 3.9s ease-in-out infinite alternate;
}

As far as special CSS3 animation tricksery goes, the -webkit-transform-origin property can be used to set the point around which to rotate in the animation.

The animation itself is defined through the use of the @-webkit-keyframes keyword. This defines an animation by providing several keyframe definitions, that specify which CSS properties should be applied at which points in time during the animation.

The magic happens through the -webkit-animation property that will take a keyframe definition with several options and then smoothly animate the frames between the keyframes, so that in this example with the rotating arm the rotation is smoothly interpolated from 0 degrees to 9.7 degrees.

The -webkit-animation property takes several arguments:

  • Name of the animation’s keyframes definition (“arm”)
  • Duration of the animation (3.9 seconds)
  • Easing setting (“ease-in-out”). This is set to ease in and out so it looks better with the “alternate” animation style, where the animation goes back and forth
  • Iteration count setting (“infinite”)
  • Direction setting (“alternate”) – the animation “rocks back and forth” between 0% and 100% of the keyframes definition

As for the specific values to use–please do experiment! The only way to get good-looking animations is to practice making them and trying to tweak settings all over the place. Of utmost importance is perhaps the duration of the animation, followed by tweaks to the keyframe timing. For example, I used a 70% keyframe so that the durations of moving the arm from 0% to 70% and from 70% to 100% differ slightly, which makes the the back-and-forth rocking more appealing (this works really great together with the “alternate” setting).

While rotating, part of the arm is masked out with a simple positioned DIV with a black background, so that only the map part of the image overlaps into the central white background area.

Clock handles

The clock face is animated by using two copies of the same clock handle image, layered on top of each other. Again, 24-bit transparent PNGs are used:

@-webkit-keyframes pointer {
  from { -webkit-transform: rotate(0deg) scaleY(1); }
  25% { -webkit-transform: rotate(-90deg) scaleY(0.9); }
  50% { -webkit-transform: rotate(-180deg) scaleY(1); }
  75% { -webkit-transform: rotate(-270deg) scaleY(0.8); }
  to { -webkit-transform: rotate(-360deg) scaleY(1); }
}

#pointer1 {
  position:absolute;
  left:257px;
  top:177px;
  width:9px;
  height:23px;
  background:url(img/pointer1.png);

  -webkit-transform-origin:5.5px 18px;
  -webkit-animation:pointer 4s linear infinite;

  -moz-transform-origin:5.5px 18px;
  -moz-transform:rotate(55deg);
  -o-transform-origin:5.5px 18px;
  -o-transform:rotate(55deg);
}

#pointer2 {
  position:absolute;
  left:257px;
  top:177px;
  width:9px;
  height:23px;
  background:url(img/pointer1.png);

  -webkit-transform-origin:5.5px 18px;
  -webkit-animation:pointer 9s linear infinite;

  -moz-transform-origin:5.5px 18px;
  -moz-transform:rotate(-45deg);
  -o-transform-origin:5.5px 18px;
  -o-transform:rotate(-45deg);
}

The interesting part here is that the clock face isn’t really a circle but an ellipse, so I’m scaling the handles down horizontally a tiny bit with scaleY so it all fits in there.

The -moz-transform and -o-transform properties will make the clock handles show up in nicer default positions on Firefox and Opera (hope those browsers will support CSS3 animations soon!).

Eye (blink!)

The Eye is perhaps the most surprising element of the animation because it’s actually using none of the amazing new features, but rather uses a buzzword of the mid-90s: animated GIFs. Yes, you read right. Animated GIFs are widely supported across browsers and a relatively easy to create with tools like Photoshop.

First, here’s the eye in all it’s glory. Just wait for a bit and you will see it blink very briefly!

To create this in Photoshop, just have two layers, one with the eye open, and one with the eye closed, and then use the “Animation” palette to create a timeline-based animation (the darker areas show when the layers are shown). Save with “Save for Web & Devices…” and you’re all done!

This can be used for more complex animations, like the “map path” that shows up further down on the page.

Yarrr! Don’t forget, Captain Track loves to help you free-lance more efficiently!

Want to know more? Learn even more at my HTML5 Mobile Pro Workshop (next one is on October 5, 2010).