Thomas Fuchs
Hi, I'm Thomas Fuchs. I'm the author of Zepto.js, of script.aculo.us, and I'm a Ruby on Rails core alumnus. With Amy Hoy I'm building cheerful software, like Noko Time Tracking and Every Time Zone and write books like Retinafy.me.
   Want me to speak at your conference? Contact me!

This Flash is dead

August 20th, 2010

A user enters a web site.

User: ‘Ello, I wish to register a complaint.
(The owner does not respond.)

User: ‘Ello, Miss?
Adobe: What do you mean “miss”?

User: I’m sorry, I have a cold. I wish to make a complaint!
Adobe: We’re closin’ for lunch.

User: Never mind that, my lad. I wish to complain about this Flash what I purchased not half an hour ago from this very boutique.
Adobe: Oh yes, the, uh, the 10.1…What’s,uh…What’s wrong with it?

User: I’ll tell you what’s wrong with it, my lad. It’s dead, that’s what’s wrong with it!
Adobe: No, no, it’s uh,…he’s resting.

User: Look, matey, I know a dead plugin when I see one, and I’m looking at one right now.
Adobe: No no it’s not dead, it’s, it’s restin’! Remarkable plugin, the 10.1, idn’it, ay? Beautiful plumage!

User: The plumage don’t enter into it. It’s stone dead.
Adobe: Nononono, no, no! It’s resting!

User: All right then, if it’s restin’, I’ll wake it up! (shouting at the sandbox) ‘Ello, Mister Polly Flash! I’ve got some lovely fresh hardware acceleration for you if you show…
(owner hits the sandbox)
Adobe: There, it moved!

User: No, it didn’t, that was you hitting the sandbox!
Adobe: I never!!

User: Yes, you did!
Adobe: I never, never did anything…

User: (yelling and hitting the sandbox repeatedly) ‘ELLO POLLY!!!!! Testing! Testing! Testing! Testing! This is your nine o’clock alarm call!
(Takes Flash out of the sandbox and thumps its head on the counter. Throws it up in the air and watches it plummet to the floor.)

User: Now that’s what I call a dead plugin.
Adobe: No, no…..No, ‘e’s stunned!

User: STUNNED?!?
Adobe: Yeah! You stunned him, just as he was wakin’ up! Flash stuns easily, major.

User: Um…now look…now look, mate, I’ve definitely ‘ad enough of this. That plugin is definitely deceased, and when I purchased it not ‘alf an hour ago, you assured me that its total lack of movement was due to it bein’ tired and shagged out following a prolonged squawk.

Adobe: Well, he’s…he’s, ah…probably pining for the fjords.
User: PININ’ for the FJORDS?!?!?!? What kind of talk is that?, look, why did he fall flat on his back the moment I got ‘im home?

Adobe: The 10.1 prefers keepin’ on it’s back! Remarkable plugin, id’nit, squire? Lovely plumage!
User: Look, I took the liberty of examining that plugin when I got it home, and I discovered the only reason that it had been sitting on its perch in the first place was that it had been NAILED there.

(pause)

Adobe: Well, o’course it was nailed there! If I hadn’t nailed that plugin down, it would have nuzzled up to those bars, bent ’em apart with its beak, and VOOM! Feeweeweewee!
User: “VOOM”?!? Mate, this plugin wouldn’t “voom” if you put four million volts through it! It’s bleedin’ demised!

Adobe: No no! It’s pining!
User: It’s not pinin’! It’s passed on! This plugin is no more! It’s has ceased to be! It’s expired and gone to meet its maker! It’s a stiff! Bereft of life, it rests in peace! If you hadn’t nailed it to the perch it’d be pushing up the daisies! It’s metabolic processes are now ‘istory! It’s off the twig! It kicked the bucket, it shuffled off its mortal coil, run down the curtain and joined the bleedin’ choir invisibile!! THIS IS AN EX-PLUGIN!!

(pause)

Adobe: Well, I’d better replace it, then. (he takes a quick peek behind the counter) Sorry squire, I’ve had a look ’round the back of the shop, and uh, we’re right out of plugins.
User: I see. I see, I get the picture.

Adobe: I got Flash lite.

(pause)

User: Pray, does it talk?
Adobe: Nnnnot really.

User: WELL IT’S HARDLY A BLOODY REPLACEMENT, IS IT?!!???!!?
Adobe: N-no, I guess not. (gets ashamed, looks at his feet)

User: Well.

(pause)

Adobe: (quietly) D’you…. d’you want to come back to my place?
User: (looks around) Yeah, all right, sure.

When does JavaScript trigger reflows and rendering?

August 17th, 2010

Browsers are single-threaded beasts* but your JavaScript can still cause very expensive reflows and rendering if you’re not careful.

The important thing is to always remember that reflowing and rendering HTML is the single most expensive operation browsers do. If your page feels sluggish it’s most likely a problem with rendering. While the easiest way to optimize is to get rid of as many nodes as you can, and trying to have simpler CSS rules, sometimes JavaScript is the culprit.

You ask, what’s so expensive about reflowing? Have a look at this video—it shows how a browser renders a popular page (Wikipedia), and though that page is actually quite simple, you see that a lot is going on:

Now, if you change the CSS style of some element on the page with JavaScript, the browser doesn’t immediately apply this change, but rather waits for either of two things happening:

1. The execution of your JavaScript ends (for example, your event handler is done) or 2. You query something that triggers a reflow. Obviously you can’t do much about the reflows that happen when your JavaScript execution ends, so we’ll look at the second, and sometimes overlooked trigger.

someElement.style.fontSize = "14px";
if(someElement.offsetHeight>100){ /* ... */ }
someElement.style.paddingLeft = "20px";
if(someElement.offsetWidth>100){ /* ... */ }

In this code, the calls to offsetHeight and offsetWidth cause expensive reflows. You could write this as:

someElement.style.fontSize = "14px";
someElement.style.paddingLeft = "20px";
if(someElement.offsetHeight>100){ /* ... */ }
if(someElement.offsetWidth>100){ /* ... */ }

And you will trigger only one reflow, which probably doubles the execution speed of this block of code. So what happens here?

Browsers batch apply CSS changes. They wait until either your code exits or they need to recalculate the layout (reflow). In case of the second example, the call to offsetHeight triggers the reflow, but in the next line, because there haven’t been any style changes, no new reflow is necessary—and querying offsetWidth happens pretty much instantly.

Of course, style changes are not the only thing the cause reflows, obviously adding or removing stuff from the DOM does too. You can often achieve better performance by batching those operations in one big chunk at the end of the block of code you’re executing.

*some browsers like Chrome isolate tabs, but in the same tab, it’s still a single execution thread

Loop unrolling in JavaScript

August 16th, 2010

One of the historically more popular optimizations is loop unrolling. Instead of a for or while loop, just “unroll” the loop:

// classic for loop
for (var i = 0; i < 100; i++) a++;

// unrolled loop
a++;
a++;
a++;
a++;
a++;
a++;
a++;
a++;
// etc. etc. etc.

// unrolled loop (in 1 statement)
a++, a++, a++, a++, a++, a++, a++, /* ...etc... */ a++;

Try the test on jsPerf yourself.

Note that due to the lack of a goto statement, loop unrolling has a bit of a limited appeal in JavaScript, but it’s still a useful technique in some cases, though you can use return to return early from an unrolled loop (if the overhead of a function call is not too much).

…and here are results of the Austrian jury (on a 3.06GHz Core Duo):

Safari 5 (Mac): 3,228,374 ops/sec for the unrolled loop (22% faster than for loop)
Chrome 5 (Mac): 2,688,656 ops/sec for the unrolled loop (31% faster than for loop)
Firefox 3.6 (Mac): 42,890 ops/sec for the unrolled loop (for loop is 30x faster!)
IE 6 (XP): 60,235 ops/sec for the unrolled loop (1 statement version) (5x faster than for loop)
IE 8 (Win 7): 124,878 ops/sec for the unrolled loop (1 statement version) (5x faster than for loop)

The verdict is, that on modern JavaScript engines, unrolled loops give you a modest performance increase, and on Internet Explorer you can expect a major boost. On Firefox, normal for or while loops are better.

Mind you, NEVER OPTIMIZE PREMATURELY. Only optimize if you have to—but if so, this technique is actually quite useful, especially if you deal with iterative algorithms like in visualizations (something I sometimes have to deal with).

Find this technique and more in JavaScript Performance Rocks!, my ebook on JavaScript Peformance.

JavaScript snippets performance

August 14th, 2010

When working on performance optimization fine-tuning, it’s great to have some help in the form of benchmarks of various strategies to achieve your code goals. Mathias Bynens has come up with a slick site to do just that, meet jsPerf!

First take a look at the various test cases that are already in there.

Here’s a test case I wrote out of interest comparing various strategies to test if a given property exists in an object (view it on jsPerf):

// for a given object
var obj = {
   a: 1
};

// test which is fastest
// variant 1: in operator
if ('a' in obj) {};
if ('b' in obj) {};

// variant 2: boolean value (might yield wrong results with certain values!)
if (obj.a) {};
if (obj.b) {};

// variant 3: hasOwnProperty
if (obj.hasOwnProperty('a')) {};
if (obj.hasOwnProperty('b')) {};

Perhaps not surprisingly, variant 2 is fastest (at least on Safari 5.0.1). Note that this particular way to test for properties might yield wrong results (a property with a value of false wouldn’t be detected, for example).

JsPerf is double-awesome! While it is of course great to test the performance of code, most importantly your findings are shared with other developers (and they can suggest new solutions!). Be sure to browse through the test cases—a great way to learn about alternative ways to code JavaScript.

How to add the official Tweet Button to WordPress

August 12th, 2010

I use WordPress, and I use Twitter, so here’s how to add the awesome new offical Tweet Button to your WordPress blog:

Inside your Main Index template (index.php), add the first line inside the posts loops (above/below/whereever you want it!). You can add additional parameters, and don’t forget to change the data-via attribute!

Then, add the script line at the end of your page (for example in the footer!)—you only need to include the script tag once!

That’s it, cute little Tweet Buttons like the one right below this article (try it out!).

Optimizing images for hardware-acceleration on the iPhone and iPad

August 12th, 2010

I found that big progressive JPEG images can cause performance problems when used with hardware accelerated CSS transforms, so here’s what I do to makes things work better (with ImageMagick):

convert somefile -interlace none somefile_for_ipad.jpg

The -interlace none option saves the image as a non-progressive JPEG, and Safari doesn’t attempt to render progressive intermediate steps when downloading the file (and thus saving it from creating textures for each intermediate step).

A useful command to find out if a JPEG file is progressive or not is:

identify -verbose filename.jpg

This will spit out tons of information about the file (more than you ever wanted to know), but somewhere in there it should say Interlace: None.

Note that if you’re NOT using hardware-acceleration, it’s probably best to have progressive JPEGs (show up faster and compress slightly better in most cases). Use -interlace JPEG to create those.

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

Pragmatic HTML & CSS

August 10th, 2010

With all those great new features coming in CSS3 people are tempted to invent the “ultimate reset.css” stylesheet. But what’s the point? The default CSS rules are sensible and make sense (for example, they format unordered lists correctly). You’ll end up with less CSS to write, and less code to maintain, fewer lines of code all in all, if you DON’T use those those templates.

The best code is code that you don’t have to write.

In fact, here’s the HTML(5) template I use for new projects:

<!DOCTYPE html> 
<html>
<head>
  <title></title>
  <style></style>
</head>
<body>
</body>
</html>

And that’s it: be pragmatic about this, and don’t overengineer. Whenever you use something like…

<!--[if IE 7]>
<link rel="stylesheet" href="really/long/path/to/small/css/screen/patches/win-ie7.css" media="all" />
<![endif]-->

…a kitten dies somewhere. In most cases, the win-ie7.css file is probably empty or contains only a handful of special rules.

There are perfectly good CSS hacks that you can use, like:

* html div.blah { /* something for IE6 */ }
*+html div.blah { /* something for IE7 */ }
div.blah { color: #0FC\0/; /* IE8 */ }

Yeah, not quite beauties either, but at least they keep your HTML clean from those super-ugly, totally weird conditional comments, which quite mess up your code. Just stick those rules at the end for your stylesheet file or inline ’em, if you have a short stylesheet or a one-pager.

Why do that? The stylesheet declaration above alone takes up 129 precious, precious bytes. It’s for just one version of that browser-like software that is called “Internet Explorer”. That’s more bytes than all of those three hacks combined (including the comments)—and they support 3 versions of IE.

At the end of the day, no one will judge your web sites and apps by how beautiful you include IE workarounds, but they will by how fast it loads.

Be pragmatic.

Go nuts at the JS1k JavaScript demo contest

August 7th, 2010

Peter van der Zee started the JS1K JavaScript demo contest for real coders! What can you code in just 1024 bytes of JavaScript? What can you do in a tweets’ length of JavaScript? Find out what others are up to and submit your own awesome tiny little JavaScript demos!

I’m a juror at this demo contest—please impress me by submitting really awesome demos!

Here are the rules:

  1. Create a fancy pancy Javascript demo
  2. Submissions may be up to 1k. (And not crash)
  3. Externals are strictly forbidden, unlike “some” contests. (Good luck minifying jQuery though!)
  4. Must work on current fx, sa, ch and o. (Let’s level the playing field)
  5. Minification and hacks allowed. (Go nuts)
  6. Bonus points if your submission fits in one tweet 😉
  7. Last day to submit is 10 September 2010

The winners will be announced at http://jsconf.eu/.

I’m not allowed to compete, but here’s a fun little tweet-friendly quine (put everything on one line):

alert((function(){return"alert(("+arguments.callee.toString()
.replace(/s/g,"")+")());";})());

Oh yeah, there are prizes to be had, among them free tickets to an upcoming HTML5 Mobile Pro Workshop andJavaScript Performance Rocks! ebooks and lots more!

HTML5 buzzwords in action

August 5th, 2010

Amy and I have made a version of the PepsiCo Zeitgeist for BlogHer 2010 (Safari 5 highly recommended to view in full glory!), and updated the visualization technology we use to the latest and greatest buzzwords in the process.

What is the Zeitgeist? It visualizes what attendees at the BlogHer conference are tweeting about, what the most important topics are, and how the attendees are connected (who is talking to who).

Big thanks to PepsiCo at this point, they’re doing some awesome things! Cheers!

But you’re here to read about buzzwords and if they are really applicable, so let’s have a look!

Hardware acceleration and scripty2

Sounds great, but is all the trouble good for something? Yes, it is. By using hardware-accelerated CSS animations, much smoother and less CPU-intensive animation is possible, plus you get ultra-smooth 50fps animation on iOS devices (iPhone, iPad). The Zeitgeist is not optimized for the iPhone, but if you have an iPad, be sure to check it out. It’s completely and utterly smooth.

We’re using mainly for the tweets visualization, but also for the bubbles on the connections page.

How does it work? Instead of animating standard CSS positioning properties like left, use -webkit-transform instead. Using that the browser has no need to recalculate the layout or do a complete rendering of the page for each animation step, instead the element is just a texture and is moved around with the facilities of the GPU, which is optimized for just that. The best thing is, it comes for free if you already use Scripty2—it does all the hard work for you of rewriting your “traditional” animations to hardware-accelerated ones.

It’s pretty new however, and right now only Safari 4+ (Mac), and Safari 5 (Mac & PC) support hardware-acceleration fully (no, Chrome doesn’t support it either). It seems that other browsers will catch up very soon, with at least Firefox and IE having announced hardware acceleration already (and when those are released, all that is needed is an update to Scripty2).

One big drawback: from time to time you hit some memory limitations and bugs, and these can be hard to reproduce. Keep in mind that it’s a very new technology and one that tries to push the edge of what web browsers can do! One thing that often helps is forcing the browser into making more elements into textures (try this first if you hit strange visual bugs like flickering):

body {
  -webkit-transform-style: preserve-3d;
  -webkit-transform: perspective(-900);
}

someelement {
  -webkit-transform: translate3d(0,0,0);  /* force texture */
}

Dean Jackson from Apple writes me:

In essence, any transform that has a 3D operation as one of its functions will trigger hardware compositing, even when the actual transform is 2D, or not doing anything at all (such as translate3d(0,0,0)). Note this is just current behaviour, and could change in the future (which is why we don’t document or encourage it). But it is very helpful in some situations and can significantly improve redraw performance.

The big payoff is the performance on mobile devices. There’s no other way to do this than using -webkit-transform and you get super-smooth, super-awesome animations, and your clients will want to have your babies.

CSS3 gradients

Oh my god, these save so much work. We’re using a background composition with a pattern (provided as 24-bit transparent PNG, left/bottom aligned), two overlaying gradients for the blue background, and 4 gradients for the vignetting effect. The whole CSS block looks like this:

background: #2b4e94 url(../images/bg-pattern.png) left bottom no-repeat;
  
background:
  url(../images/bg-pattern.png) left bottom no-repeat,
  -webkit-gradient(linear, left top, left bottom, from(rgba(0,0,0,0.24)), color-stop(0.1, rgba(0,0,0,0)), to(rgba(0,0,0,0))),
  -webkit-gradient(linear, left bottom, left top, from(rgba(0,0,0,0.24)), color-stop(0.1, rgba(0,0,0,0)), to(rgba(0,0,0,0))),
  -webkit-gradient(linear, left top, right top, from(rgba(0,0,0,0.24)), color-stop(0.1, rgba(0,0,0,0)), to(rgba(0,0,0,0))),
  -webkit-gradient(linear, right top, left top, from(rgba(0,0,0,0.24)), color-stop(0.1, rgba(0,0,0,0)), to(rgba(0,0,0,0))),
  -webkit-gradient(linear, left top, left bottom, from(rgba(0,0,0,0.1)), color-stop(0.6, rgba(0,0,0,0)), to(rgba(0,0,0,0.1))),
  -webkit-gradient(linear, left top, left bottom, from(#1c4088), to(#3c639d));
    
background:
  url(../images/bg-pattern.png) left bottom no-repeat,
  -moz-linear-gradient(-90deg, rgba(0,0,0,0.24), rgba(0,0,0,0) 10%, rgba(0,0,0,0)),
  -moz-linear-gradient(90deg, rgba(0,0,0,0.24), rgba(0,0,0,0) 10%, rgba(0,0,0,0)),
  -moz-linear-gradient(0deg, rgba(0,0,0,0.24), rgba(0,0,0,0) 10%, rgba(0,0,0,0)),
  -moz-linear-gradient(180deg, rgba(0,0,0,0.24), rgba(0,0,0,0) 10%, rgba(0,0,0,0)),
  -moz-linear-gradient(-90deg, rgba(0,0,0,0.1), rgba(0,0,0,0) 60%, rgba(0,0,0,0.1)),
  -moz-linear-gradient(-90deg, #1c4088, #3c639d);

You do have to have two definitions for Webkit- and Mozilla-based browsers. I kind of like Mozilla’s syntax more, but it’s really a matter of taste.

No JavaScript code and nothing else is required, the background automatically adjusts to the window size (be sure to set html,body{height:100%;}, too). These gradients are even great if you don’t want to use them for a production site—you can use them while prototyping your page to quickly try out variations, settle on one and then do it the “traditional” way (i.e. cut out graphics with Photoshop).

Next to the background, we’re also using gradients for the navigation buttons.

On IE and other browsers that don’t support these gradients, we just use a solid background color and the pattern. Looks fine too.

SVG

There are many graphics technologies that come with HTML5 (well, two), but there’s only one SVG. And SVG is awesome, because you get real, manipulatable nodes in your DOM tree. Animation is really easy, especially if you use the Raphaël JavaScript library, which works great with whatever other libraries you are using (in my case Prototype and Scripty2).

If you don’t know Raphaël (you should!), it provides a JavaScript API to generate vector graphics, using SVG on HTML5-supporting browsers, and VML on IE. It makes this transition largely painless, and forces you to learn some SVG in the process (notably, the SVG path string syntax, which can come in quite handy to understand the generated output).

We’re using it to draw and animate the lines that connect the nodes. It works everywhere, although SVG is not the fastest on mobile devices—we can get away with that with the specific animation we’re doing in this case.

Prototype.js

Prototype is the secret weapon in my arsenal, and I wouldn’t want to trade it with anything else. It’s superbly powerful when it comes to data crunching and munging.

var popular = data.words.map(function(word,idx){
  return { w:word.word.word, r:parseInt(word.word.hits) };
}).sortBy(function(w){ 
  return w.r;
}).reverse().slice(0,10).sortBy(Math.random); // *

What’s best about it is if you use Ruby in the backend, it makes for a quite seamless transition between Ruby and JavaScript coding. I like stuff that doesn’t get in the way.

It’s also quite well suited to implement prototypes (ha!) of more complicated algorithms, like the iterative algorithm used for placing the nodes of the connections graph (basically works with nodes & connecting edges and shifts stuff around based on “attraction” between nodes). However, iterative algorithms like these are one of the few things that actually require going in and doing some heavy-duty performance optimizations (like minimizing function calls, unrolling loops, precalculating stuff, etc.).

Conclusion

Buzzwords reign supreme! It’s not all just a senseless arms race between browser vendors, it’s actually useful for something! Now would be a good time to get up to speed with all those cool new buzzwords (and learn how to integrate them with your existing knowledge, of course!).

Plus, you can make it work cross-browser without too much effort. We support IE7, IE8, Safari 4+, Firefox 3.5+, Chrome and Opera. There are almost no hacks required for this broad compatibility.

By the way, we have some more tickets left for our HTML5 Mobile Pro Workshop, where I will share even more details about these and other awesome things you can do! Hint!

Update August 6, 2010: Added quote from Dean Jackson (Apple) about how hardware compositing is triggered.

*I know that sometimes I should use longer variable names

JavaScript Master Class September 29 & 30

August 4th, 2010

Announcing another one of of Amy Hoy’s and my Virtual JavaScript Master Classes!

The next class is scheduled for September 29 & 30, and is scheduled to be AWESOME. It’s split in two half-days so you get to breathe (and maybe do some of the homework!) between the parts. The class is timed US-friendly, beginning at 9am PT (12pm ET), but it works great for you european peeps too (6pm-10pm each day, or 5pm-9pm London time).

What do our new JavaScript ninjas say about the class? (and you WILL be a JavaScript ninja too after this intense experience, believe me!)

  • “Help & clarifications on the side [in the chat] = AWESOME team”
  • “Never thought we’d have on-demand examples, you guys are spoiling us!”
  • “JavaScript Master Class worth every cent. Tons of docs, answers, insights, fun & encouragement. Highly recommended, super friendly.”
  • “Enjoyed it, learnt a lot and the online format worked very well.”
  • “Completely Impressed”

You still need a browser with Flash installed (sadly HTML5 doesn’t really support video streaming), so we can stream live to you and you can interactively ask questions for more information and on-demand code on just about anything about JavaScript (we know a lot!)…

The class is totally framework agnostic, and concentrating on the pure essence of JavaScript programming itself (but it will help you understand that weird jQuery method or the Prototype.js idiom you have been wondering about).

Head over to our JavaScript Master Class site to learn more and sign up (right now, we still have early bird pricing on, but not for long– you save a cool $70 with the early bird pricing!).