Friday, March 5, 2010

toString() Might Not Return a String

I was reading NCZ's JavaScript quiz, and it occurred to me that toString() is not guaranteed to return a string because it is, after all, just a method. Try to guess what is printed to the console when the following JavaScript is executed:
var obj = {
nine: 9,
toString: function() {
return this.nine;
},
valueOf: function() {
return 10;
}
};

console.log(obj.toString() === '9');
console.log('' + obj === '9');
console.log('' + obj.toString() === '9');
console.log(obj + obj);
console.log(String(obj) === '9');
Because obj.toString() returns a number, not a string, obj.toString() is the number 9, not the string '9', so the first expression is false.

In the second example, I would expect that because '' is a string, the value on the right of the + would also be coerced to a string via its toString() method, which means the result would be '9'. But I am wrong! It turns out that valueOf takes precedence, so '' + obj evaluates to '10', which means '' + obj === '9' is false. It would be true if there were no valueOf method defined on obj, though.

Because toString() is called explicitly in the third example, '' + obj.toString() becomes '' + 9, which evaluates to '9', so the expression is true.

The fourth one is interesting because '99', 18, and 20 are all reasonable guesses, but it turns out that valueOf() takes precedence again, so this evaluates to 20. If there were no valueOf() method defined on obj, then the result would be 18.

In the final example, String() is used as a function (and not as a constructor function, which you should never do!), and it does, in fact, return a string, so String(obj) === '9' evaluates to true. I always assumed that the implementation of String was something like:
function(s) {
return '' + s.toString();
};
Though a few years back, I discovered that alert.toString() throws an exception on IE6 (also alert.toString evaluates to undefined on IE6), but '' + alert and String(alert) return 'function alert() { [native code] }', as expected. At least in that case, my proposed implementation for String() would not work, though IE6 has been known to be nonstandard and buggy...

Monday, March 1, 2010

Update to Closure: The Definitive Guide

Today I'm excited to announce a significant update to Closure: The Definitive Guide. The book contains complete drafts of two new chapters that focus on the Closure Compiler: Using the Compiler and Advanced Compilation. These two chapters contribute 80 pages of new content in addition to the 167 pages that are already available.

Because I was curious, I also created a graph of my progress on the book that is automatically updated every six hours:



When I put together the original proposal for the book, I projected that it would only be 250 pages long. Clearly, that was an underestimate. This presents quite the opportunity for you, the reader, since I'd argue that the book is now underpriced as you can preorder the print version for only $25.99. For only $14 more, you can also get online and PDF access to the book today. If you do, I strongly encourage you to provide feedback on O'Reilly's web site. Remember, the book is still in draft form, so if you have suggestions on how the book could be improved, make them now so they can be included in the final version!

Sunday, February 21, 2010

New Firefox Extension: Fullscreen Tasks in Gmail

I know that when you have a lot of things to do, using Tasks in the cramped space within Gmail or Calendar may seem frustrating. There is actually a great workaround, which is to use the fullscreen version of the Tasks iGoogle gadget available at https://mail.google.com/tasks/canvas. Unfortunately, few people seem to know about it even though it was posted on the Gmail blog back in October.

My new extension simply adds a link in the sidebar that makes it possible to bring up the fullscreen version of Tasks in an iframe without leaving Gmail:



You can download the extension from http://bolinfest.com/chickenscratch/fullscreen-tasks-in-gmail.xpi. For some reason, you need to install it by first downloading it and then using the File -> Open File... menu in Firefox to open it up and install it. The traditional method of installing, which is just going to the URL in Firefox, does not seem to work for some reason: I get some nonsense about it not being a valid install package.

Because I thought this was going to be a short script, I originally tried to write it in Greasemonkey because I feel like it is easier to get users to install Greasemonkey scripts than separate extensions these days. Initially I tried using the Gmail Greasemonkey API, but unfortunately it is super-busted: many of the methods in the API do not work right now.

Then I considered looking under the hood of Gmail and trying to use XPaths, but those were nightmarish and would be likely to break, so I decided that I really needed some of the primitives in Chickenfoot to grab the appropriate DOM elements. For example, to display Tasks, I need to hide the threadlist and insert my iframe. In Chickenfoot, I came up with a fairly good heuristic:
  var n1 = find('first select all').element;
var n2 = find('second select all').element;
if (!n1 || !n2) {
return false;
}
ancestor = goog.dom.findCommonAncestor(n1, n2);
dom = goog.dom.getDomHelper(ancestor);

This essentially finds the DOM element for each of the "Select: All" controls that appear above and below the threadlist, and uses their common ancestor as the node to hide to make room for my Tasks iframe.

If you are interested, the code for the Chickenfoot script is also available. In creating the extension, I ended up fixing some bugs in Chickenfoot, but also added some new features, so when Chickenfoot 1.0.8 is released, it will be possible to run my script as-is. One new feature is that Closure Lite will be available as a library in Chickenfoot, so with the include('closure-lite.js') call in Chickenfoot, lots of goog goodness will be readily available, which made the development of this script go so much faster.

For a script that should be so easy to write, it may be surprising that it is over 100 lines long. Much of this is because I tried to include a number of features that should make the extension easier to use:
  • Keyboard shortcut that works when either the threadlist or the Tasks iframe have focus.
  • Tooltip to make the keyboard shortcut more discoverable.
  • Logic to ensure that the style of the "Full Tasks" link matches that of your Gmail theme.
  • Focus is given back to the threadlist when exiting fullscreen Tasks.
  • The Tasks iframe is resized when the browser window is resized.
  • Timing logic to account for the fact that many things in Gmail are loaded asynchronously.
I bring this up not just to toot my own horn, but to comment on something that I recently read about in Coders at Work that Kushal recently touched upon on his blog as well, which is the idea of the "empathy gene". (Some bloggers misattribute the phrase to Josh Bloch because he brings it up in his interview in Coders at Work, but Bloch actually attributes the phrase to Kevin Bourrillion during the interview.)

I think it's particularly relevant in this example because most userscripts that I have looked at are pretty hacky pieces of code. This is partially because most userscripts are viewed as hacks in the first place, though there is nothing about writing userscripts that forces them to be that way. For example, with my new extension, there are a million ways I could have chosen to jam a Tasks iframe into Gmail, most of which would have taken many fewer lines of code. But to make something reliable, thoughtful, and usable took a lot more code than that. I like to think that this is my empathy gene at work.

An even better example of non-hacky Greasemonkey scripts are those written by Mihai. Mihai clearly has the empathy gene, which is one of the reasons why Google Reader is such a great product. (Though even an empathetic guy like Mihai has been known to ruin Christmas every once in awhile -- oops!)

Finally, although I enjoyed creating this extension and am glad that I also made improvements to Chickenfoot in the process, I would be even happier if this feature (or something like it) were made available in Gmail (I'm looking at you, Mountain View!). Though if Tasks were able to "graduate" into the navigation bar in the top of the page that is available across all apps, that would solve most of my problems. It may be time to update iGoogleBar to do exactly that!

Tuesday, January 26, 2010

I'm a Semi-Published Author! (Closure: The Definitive Guide)

Today, I am officially a semi-published author in that the half of the book I am working on is available (for pay) online as part of O'Reilly's Rough Cuts program! The title is Closure: The Definitive Guide, and as you may have guessed, the aim is to create an (invaluable!) manual for the Closure Tools suite. When I am finished, the book will cover the Library, Templates, the Compiler, the Testing Framework, and the Inspector, though the six chapters that are available today are only on the Library. However, if you purchase the book through Rough Cuts, you will get the updates to the book as I publish them there, so it is more like buying a subscription than a book.

I am extremely excited about the Rough Cuts program because it allows me to get information out to you, the web developer, much faster than I could if I forced you to wait for the print version. It also gives you the opportunity to provide me with feedback to help ensure that the Guide contains the information that you need.

For those of you who have purchased a book via Rough Cuts before, you may be surprised to see how "rough" my book is compared to the other offerings. This is a fairly new program at O'Reilly, so the first books to go through Rough Cuts were not made available until a nearly complete draft of the book was done. By comparison, my book is half done and has gone through neither copy edit nor technical review. So when providing feedback, please bear in mind the staff at O'Reilly will ultimately help with things like the misuse of parallel structure, but I need your help in determining when something merits a code sample or more explanation.

The material that is currently available is:
  • Preface
  • Chapter 1: Introduction to Closure
  • Chapter 2: Annotations for Closure JavaScript
  • Chapter 3: Closure Primitives
  • Chapter 4: Common Utilities
  • Chapter 5: Classes and Inheritance
  • Chapter 6: Event Management
  • Appendix A: Inheritance Patterns in JavaScript
  • Appendix B: Frequently Misunderstood JavaScript Concepts
Although there is nothing that requires me to write the chapters in order, I was encouraged to start out that way in order to have something that would be well-connected for Rough Cuts readers. This meant that I had to draft the introduction earlier than I would have liked, but I am actually quite happy with what is there right now. Among other things, it contains a complete "Hello World" example that shows how to use all of the tools together, which is something I have yet to see on any blogs or even as part of Google's own documentation.

Currently, I am taking a break from writing more on the Library and am skipping a few chapters ahead to start focusing on the Compiler. As an active member of the Closure Google Groups, it is pretty clear to me that developers need more help in that area, so I hope to make that information available soon.

I also hope to improve Closure in the process of writing this book. When I run into things that I feel are hard to explain, sometimes I end up filing bugs or feature requests against Closure with proposed changes. It is so much easier to write a few paragraphs to report a bug than it is to draft several pages to explain away a quirk!

With 150 pages of content, I suspect I have given you enough to chew on while I put together more information on the Compiler. Please take a look and let me know what you think.

Update: Changed the book link from http://techbus.safaribooksonline.com/9781449381882 to http://my.safaribooksonline.com/9781449381882 where it is actually possible to purchase the book! There is a button that says "Purchase Options" on the upper-right.

Saturday, January 2, 2010

google.com uses AJAX to update search results in place?

My Gmail account appears to be in an experiment where searches from google.com update in place. That is, a search for bolinfest takes me to:

http://www.google.com/#hl=en&source=hp&q=bolinfest&aq=f&aqi=g10&oq=&fp=cbc2f75bf9d43a8f

Rather than the classic:

http://www.google.com/search?hl=en&source=hp&q=bolinfest&aq=f&oq=&aqi=g-p1g2

Apparently this was first reported in January 2009. There was immediately an outcry because the fragment (with includes the keywords used in the Google search) was not included in the referrer, so sites who analyze their traffic using that information were at a loss.

In my version of the experiment, this is no longer an issue because the search results use a URL redirector (which I do not believe is a new practice). Although the first search result is for www.bolinfest.com/, and when I hover over the link in Firefox, the status bar says http://www.bolinfest.com/, the actual destination of the link is:

http://www.google.com/url?sa=t&source=web&ct=res&cd=1&ved=0CAoQFjAA&url=http%3A%2F%2Fwww.bolinfest.com%2F&rct=j&q=bolinfest&ei=kYU_S8nZAdC0lAeJ0fmVBw&usg=AFQjCNEgHH2q8kppSggtQt45aSSazDTynA&sig2=G54nS0q_UtfEChH7icC_NA

When I follow the link and run javascript:alert(document.referrer) in the address bar, I see the same thing:

http://www.google.com/url?sa=t&source=web&ct=res&cd=1&ved=0CAoQFjAA&url=http%3A%2F%2Fwww.bolinfest.com%2F&rct=j&q=bolinfest&ei=kYU_S8nZAdC0lAeJ0fmVBw&usg=AFQjCNEgHH2q8kppSggtQt45aSSazDTynA&sig2=G54nS0q_UtfEChH7icC_NA

Note that this URL contains the query in the URL parameter q=bolinfest, which should appease those who are concerned with keyword tracking.

What is interesting is that the AJAX request to load the search results appears to be an ordinary GET request to:

http://www.google.com/search?hl=en&q=bolinfest&aq=&aqi=g2&oq=bolinfest&fp=cbc2f75bf9d43a8f

The content of that URL is an HTML page with 21 <script> tags in the <head> and an empty <body> tag.

Also, copying and pasting http://www.google.com/#hl=en&source=hp&q=bolinfest&aq=f&aqi=g10&oq=&fp=cbc2f75bf9d43a8f into the address bar of a new tab works as expected (though I do get a JavaScript error when I paste the URL into a new tab that I do not get when doing the initial search from google.com).

It's hard to say what this really means, if anything. Presumably, Google's objective is to make search results load faster without pissing off advertisers. As I'm not in the SEO racket, I'm not terribly interested in the latter, but I am curious whether Google is on to a new technique for loading web content faster!

Monday, December 21, 2009

Closure Lite - Just in time for Christmas!

When I was an undergrad at MIT, the end of the fall semester meant I had about 5 weeks of freedom to hack on stuff before the start of the spring semester. At MIT, instead of starting classes back up in January, they have what is called the Independent Activities Period (IAP). Although IAP is optional, many students return for it (except the Hawaiians I knew, who generally decided to stay home in their tropical paradise during one of the coldest months in Boston) because there are so many great opportunities: you can get scuba certified, do research, or my personal favorite -- engage in programming competitions!

For you holiday hackers who haven't found the time to play around with Closure yet, I've tried to make it a little easier to get started by creating Closure Lite. Closure Lite is a single JavaScript file that you can include on a web page to start using a subset of the Closure Library. This is similar to the approach used by other popular JavaScript libraries such as jQuery. But as the Closure Lite documentation explains, although Closure Lite is a good way to start learning the Library, it is recommended to learn and use the Closure Compiler on your production JavaScript.

I hope that both Closure and Closure Lite are useful to MIT students who are competing in 6.470 this IAP!

Wednesday, December 9, 2009

Check out Speed Tracer (it's not just for GWT applications!)

Last night, Google hosted a Campfire One event introducing Google Web Toolkit (GWT) 2.0. The Campfire event is divided into six segments that are all available on YouTube.



If you do not feel like watching the entire presentation (it's a little over an hour), I recommend watching Parts 3 and 5. In Part 3, Bruce Johnson discusses GWT's JavaScript compiler (which is different from the Closure Compiler) and GWT 2.0's new code splitting feature. From the presentation, it sounds like the GWT compiler has added some of the optimizations that the Closure Compiler has had for some time. (I've heard of instances of the Closure Compiler reducing compiled code from GWT by 20%, so clearly there was room for improvement.) Historically, the GWT and Closure compilers were separate codebases because one was open-sourced and the other was not, but since that is no longer the case, perhaps we will see some convergence in the future. I wouldn't hold my breath, though.

But what was more impressive was the ease with which GWT was able to introduce code-splitting. That is, dividing up a large JavaScript file into smaller files, the majority of which get loaded asynchronously by the application as the features that depend on them are accessed. The Closure Compiler has support for such a feature, but it is undocumented and requires a bit of work by the developer, even if he knows what he is doing. The code-splitting feature in GWT 2.0 (introduced about 10 minutes into Part 3) is much more elegant and straightforward. I hope that the Closure Tools suite evolves to make this just as simple.

Then in Part 5, Kelly Norton introduces Speed Tracer, which is a Chrome extension that gives an unprecedented amount of insight into what Chrome is doing when it runs a web application. It is more similar to dynaTrace than it is to Firebug. Page Tracer is informative and so snappy that you might not believe the UI is written in HTML5 -- try it out!

However, my one gripe with the Campfire presentation is that you might come away from it believing that Speed Tracer works only with GWT applications, but that is not the case at all! Although its documentation lives under GWT on code.google.com and Speed Tracer was written using GWT, it can be downloaded and used completely independently from GWT. This morning, I installed it to explore the performance of some webapps I used to work on (which were written using Closure), such as Google Tasks. (I found some areas for improvement which I forwarded to the team.) I strongly recommend evaluating your own web applications using Speed Tracer as you may be surprised at what you discover.

Also, if you're like me, you may not notice the links to additional Speed Tracer documentation because they appear below the fold on the landing page. Under the Tools heading in the left-hand-nav, there are links to Hints, the Data Dump Format, and the Logging API.

If you stop and think about it, this level of tool support is essential for the Chrome OS initiative to succeed. If the browser is going to substitute for the desktop as a platform, then it must be fast (which is where Chrome comes in), it needs to have a kickass API (which is where HTML5 comes in), and it needs to have best-of-breed developer tools (which is where GWT, Closure, and Speed Tracer come in) so it is possible to build web applications that can compete with (and ideally exceed) desktop applications. When Chrome OS was originally announced, I was a naysayer, but now that more of the pieces are starting to come together, I'm getting a bit more optimistic.