<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8112154</id><updated>2012-01-25T15:20:31.078+05:30</updated><title type='text'>blog.rakeshpai.me</title><subtitle type='html'>Random ramblings of a frontend web developer</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default?start-index=101&amp;max-results=100'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>220</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8112154.post-3976028566982598968</id><published>2011-06-07T12:33:00.002+05:30</published><updated>2011-06-07T14:19:23.103+05:30</updated><title type='text'>Announcing AceSeller.com</title><content type='html'>&lt;p&gt;It's been some time now that I've been working on solving &lt;a href="http://sandeep.shetty.in/2011/06/stumbling-upon-problem.html"&gt;an interesting problem&lt;/a&gt;, and I think it's time to start talking about it.&lt;/p&gt;&lt;p&gt;&lt;a href="http://aceseller.com/"&gt;AceSeller.com&lt;/a&gt; is a cloud-hosted service that aims to make it real easy for businesses to start selling products on their websites. It is targeted at small and mid-sized businesses that want to start selling online, but don't know how to. It is, from what we've seen, already the simplest to use and cleanest application that does this.&lt;/p&gt;&lt;p&gt;I'm doing this together with &lt;a href="http://sandeep.shetty.in/"&gt;Sandeep Shetty&lt;/a&gt; and &lt;a href="http://www.linkedin.com/in/jineshmehta"&gt;Jinesh Mehta&lt;/a&gt;. Between the three of us, we've got a great deal of experience with almost every aspect of running ecommerce sites. We are good friends, have tremendous respect for each other, and share a common passion for technology, simplicity, great user experiences and online businesses. This passion has already started reflecting in AceSeller.&lt;/p&gt;&lt;p&gt;We're working very closely with some businesses who have agreed to use our platform for launching their web-stores, and we are very excited about the great feedback we've been getting. One of these stores has already gone live on the AceSeller platform and is already processing orders, while several more are in the pipeline.&lt;/p&gt;&lt;p&gt;AceSeller is currently not open for sign-ups. We are working fervently on getting the little details right. However, if you want early access to AceSeller, &lt;a href="http://aceseller.com/"&gt;please leave your email address with us&lt;/a&gt;, and we'll get back to you as soon as possible.&lt;/p&gt;&lt;p&gt;Our plans with AceSeller are huge. We've barely scratched the surface of what we want to offer, and this post doesn't do justice to even that little bit that we've already accomplished.&lt;/p&gt;&lt;p&gt;The amount of things we've learnt over the last couple of weeks alone is tremendous; I can't wait to start sharing that knowledge. There's so much to talk about - everything from the challenges we've faced in getting businesses online, to the user experience we want to provide, to how our technology choices came about and how we managed to race ahead to get AceSeller live. I'll keep churning out more details as frequently as possible. Stay tuned.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-3976028566982598968?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/3976028566982598968/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=3976028566982598968' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/3976028566982598968'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/3976028566982598968'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2011/06/announcing-acesellercom.html' title='Announcing AceSeller.com'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-1948899447995826582</id><published>2011-05-10T19:56:00.005+05:30</published><updated>2011-05-11T10:27:18.473+05:30</updated><title type='text'>Thoughts On Taking the Entrepreneurship Plunge</title><content type='html'>&lt;p&gt;tldr; &lt;a href="#tldrplunge"&gt;Jump to the bottom ↓&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I found myself at a time in my career when I had to look back and reflect, and decide what I want to do next. Remain an employee? Or leave it all and become an entrepreneur. It's hard to make purely logical decisions about these things, in part because your life and well-being might be affected, but mostly because you need to make projections into the future and the future presents itself as a hazy picture at best. A lot of this decision is based on gut feel. This post outlines my thoughts.&lt;/p&gt;&lt;h4&gt;Financial aspects&lt;/h4&gt;&lt;p&gt;This was obviously the most important thing that I was thinking about. Salaried jobs give you a decent amount of financial stability. This is in sharp contrast to starting up, which has near-zero financial security, at least at the outset.&lt;/p&gt;&lt;p&gt;However, financial &lt;em&gt;growth&lt;/em&gt; in a salaried job is not in your control at all. Your salary increments depend on a lot of factors: What is the &lt;q&gt;industry standard&lt;/q&gt; paycheck being given out, what's the salary of your peers and bosses, what's the revenue of the company, what's the funding status of the company, etc. Yes, your performance does matter, but even with excellent performance you have an abysmal salary increase every year. What's worse, no boss will ever tell you that your performance has constantly exceeded all set expectations. They'll always find some cop-out; things like: "Your performance has been good, but you should take on more responsibility."&lt;/p&gt;&lt;p&gt;That's an awfully bad deal &amp;mdash; the factors that affect my financial growth are not in my control, good performance pays very little, and there are text-book methods to even reduce the payout for excellent performance! I've tried fighting this at all my past jobs, and I've always lost. It's a system designed to make you lose every time.&lt;/p&gt;&lt;p&gt;It's very easy to take this negatively. When you realize that your performance doesn't matter anymore, the quality of your work suffers. You start going to work simply because you are obliged to. You start hating Mondays, and look forward to Fridays.&lt;/p&gt;&lt;p&gt;I am not like that though. More than anything else, I have a strong primal urge to create stuff. I never let my obviously slow and completely-out-of-my-control financial growth affect my quality of work. Fortunately, this kept me in the good books of my bosses and my employers at all times. That makes everything fine, right? It does, except when you stop to think: &lt;q&gt;Where is all this going?&lt;/q&gt;, and discover that you don't really know. You realize that if you could instead use your zeal, energy and passion elsewhere where the promise of financial growth is higher, you could maybe make a lot more money for the stuff you are doing.&lt;/p&gt;&lt;p&gt;May be, I should start up.&lt;p&gt;Of course, the promise of financial growth is just that &amp;mdash; a promise. There's a huge possibility that it will not work at all, and I will have failed. But then I realized that if I fail, it'll be of my own doing. It will be &lt;em&gt;my&lt;/em&gt; mistake that stalls (or negatively impacts) my financial growth. That's a lot more control than I've been used to! I only need to be able to learn from my mistakes and change what I'm doing wrong quickly enough. I should be very cognizant about what might be mistakes, and reduce possible risks from those mistakes. Easier said than done of course, but at least &lt;em&gt;I&lt;/em&gt; would be in control.&lt;/p&gt;&lt;h4&gt;Creating something&lt;/h4&gt;&lt;p&gt;Let's now talk about that &lt;i&gt;primal urge to create&lt;/i&gt; that I mentioned above. It's one of the reasons I work with technology &amp;mdash; it's very easy to create things seemingly out of thin air, with very little effort at nearly no cost. It's an awesome feeling when you build something and watch the world use it. This, I now understand, is why programming is argued to be an art &amp;mdash; you are always creating. I have that creative urge in me, and I intend to never let go of it. It's the single most important character trait that I will treasure and nurture.&lt;/p&gt;&lt;p&gt;So, how do you create stuff when you are an employee? Turns out, it's nearly impossible. Firstly, there are the business goals of the company, and you have to &lt;em&gt;align personal goals with business goals&lt;/em&gt;. For most people, &lt;q&gt;personal goals&lt;/q&gt; just means &lt;q&gt;making money&lt;/q&gt;. But that's not the case when your biggest passion is to create things. What it means then is that you have to compromise. You end up doing things that might not be fun to do, because the business requires it. Like most other people, this is what I have been doing.&lt;/p&gt;&lt;p&gt;Secondly, on those occasions when you &lt;i&gt;do&lt;/i&gt; get to create, you are not in control of the decisions taken. There are several stakeholders in practically anything you do. Their opinions have to be factored in as well. By itself, the idea rocks &amp;mdash; creating stuff is a form of collaborative art in some sense. However, in practice it never ends up that way; people's egos, unclear vision, different motivations, etc. get in the way of the quality of the product. You end up creating something that is not as good as it could be.&lt;/p&gt;&lt;p&gt;So, creativity at work practically doesn't exist. As a creative person, how do you deal with this? What I used to do was wait to get back home, and then I'd work on my own little side projects. Most of these projects have never seen the light of day. There have been all kinds of projects I've worked on on the side over the last couple of years: creating protocols, implementing protocol clients, writing some funky server-modules, and building stuff on the bleeding-edge of web tech. These products were meant to be given out for free, and I could've built a business model around it in the future if I wanted to. Actually, it didn't even matter that I didn't get these live; I was happy enough to have satisfied my urge to create. On some days, I have found myself working on my side projects till the wee hours of the morning, getting very little sleep, spending time at work because I had to, only to come back home and continue having fun on my side projects till the morning. It was exhausting, but I enjoyed it because I could finally create.&lt;/p&gt;&lt;h4&gt;Starting up&lt;/h4&gt;&lt;p&gt;If I could channelize this energy, focus on something that can actually see the light of day, and get it to generate enough revenue for me, I could maybe survive on this. I'll be working just as hard, and will have more fun doing it.&lt;/p&gt;&lt;p&gt;It's an unsettling thought process that's been eating into me for several months now, and I've been meaning to act upon it. I've been discussing this with several people, and there's a lot I've learnt. There are several factors to be considered and risks involved. It hasn't been an easy decision. I would be leaving my cushy job to take on what would be my biggest risk ever. And then I realized something.&lt;/p&gt;&lt;p&gt;Starting up is not a risk at all.&lt;/p&gt;&lt;p&gt;What is the worst that will happen? Even if I fail, I'm only losing my financial security. That's a reasonably easy problem to fix. I could always take loans from friends and family. Or I could secure investment to buy me more time. I'd have to have a revenue model that will start generating money from get-go, and that in itself will reduce the risk significantly. There are several solutions, but the fact remains that &lt;i&gt;it's an easy problem to fix&lt;/i&gt;. If all else fails, I'll still be at least as employable as I am right now. I'd end up doing a salaried job like I have been doing, as much as I wouldn't like it.&lt;/p&gt;&lt;p&gt;&lt;em&gt;The worst that will happen is that I'll end up where I am right now.&lt;/em&gt; That's hardly a risk!&lt;/p&gt;&lt;a name="tldrplunge"&gt;&lt;/a&gt;&lt;p&gt;Last Friday was my last day as an employee. I've never been more anxious and excited. I've finally taken the first steps towards doing what I wanted to always: fully control my financial growth, create what I want the way I want to, and do this at minimal risk of my financial security. At the risk of sounding overly dramatic: last Friday was the first day of the rest of my life.&lt;/p&gt;&lt;p&gt;Watch this space for more announcements coming soon!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-1948899447995826582?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/1948899447995826582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=1948899447995826582' title='30 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/1948899447995826582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/1948899447995826582'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2011/05/thoughts-on-taking-entrepreneurship.html' title='Thoughts On Taking the Entrepreneurship Plunge'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>30</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-1194795543334888215</id><published>2011-01-21T19:15:00.007+05:30</published><updated>2011-01-21T21:14:50.128+05:30</updated><title type='text'>The Impact of HTML5^H: Feature Detection</title><content type='html'>&lt;p&gt;Ian Hickson posted a day or two ago that &lt;a href="http://blog.whatwg.org/html-is-the-new-html5"&gt;the WhatWG has decided to drop the version number&lt;/a&gt; from HTML.  On the face of it, it seems like a knee jerk reaction to fight an old rival that just &lt;a href="http://www.w3.org/QA/2011/01/an_html5_logo.html"&gt;announced the HTML5 logo&lt;/a&gt;, but it's a lot more than that. In Hixie's words:&lt;/p&gt;&lt;blockquote&gt;The WHATWG HTML spec can now be considered a "living standard". It's more mature than any version of the HTML specification to date, so it made no sense for us to keep referring to it as merely a draft. We will no longer be following the "snapshot" model of spec development, with the occasional "call for comments", "call for implementations", and so forth.&lt;/blockquote&gt;&lt;p&gt;What does this mean for us developers? It means that the spec will &lt;em&gt;never&lt;/em&gt; be finished &amp;mdash; the &lt;q&gt;living standard&lt;/q&gt; bit &amp;mdash; so there's no point waiting for an announcement saying that &lt;q&gt;HTML5 is ready&lt;/q&gt; or anything to that effect. But that's just on the surface.&lt;/p&gt;&lt;p&gt;For front-end developers it means one more very important thing. It means that feature detection is more important than ever before. It'll be the only reliable way for us to determine browser support for features. Of course, we always knew that but rarely did we ever practice it. You think you might have, but the libraries you have been using didn't actually do this. Until very recently that is. jQuery &lt;a href="http://docs.jquery.com/Release:jQuery_1.3#No_More_Browser_Sniffing"&gt;removed all browser sniffing in jQuery 1.3&lt;/a&gt; and the guys from Dojo have launched &lt;a href="http://badassjs.com/post/1217357060/hasjs"&gt;a project called has.js&lt;/a&gt; meant for library authors to incorporate feature detection. Of course, &lt;a href="http://www.modernizr.com/"&gt;Modernizr&lt;/a&gt; has been around for a long time now, and its list of detectable features keeps growing.&lt;/p&gt;&lt;p&gt;But detecting features alone isn't enough. You need a way to work around them. This is where &lt;a href="http://remysharp.com/2010/10/08/what-is-a-polyfill/"&gt;polyfills&lt;/a&gt; come in the picture. As Remy Sharp describes it,&lt;/p&gt;&lt;blockquote&gt;A polyfill, or polyfiller, is a piece of code (or plugin) that provides the technology that you, the developer, expect the browser to provide natively. Flattening the API landscape if you will.&lt;/blockquote&gt;&lt;p&gt;That way, feature detection happens at a lower level than the developer, and the developer can continue coding to the WhatWG/W3C specs. If this works as well as it says on the can, I think we can all move forward, and not worry about little pains like IE6.&lt;/p&gt;&lt;p&gt;What are the factors to be considered when creating a way to download a polyfill? The first is that there has to be a way to declare a dependency on a browser feature. Depending on browser feature detection, one or more polyfills might be downloaded for that browser. Secondly, the download of the polyfill will necessarily be asynchronous and the coding paradigm will have to take that into account. Thirdly, ideally the download of the polyfill itself shouldn't slow down the experience. This is impossible to do, but at least we should employ whatever techniques we have to reduce the impact of the download.&lt;/p&gt;&lt;p&gt;How would such an API look? CommonJS has been doing some great work with the &lt;a href="http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition"&gt;Asynchronous Module Definition spec&lt;/a&gt; to help solve the general problem of dependencies in JavaScript. Maybe we can look at their API for help. To define a module, you'd generally write code that looks like the following (from their own example):&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;pre&gt;define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {&lt;br /&gt;    exports.verb = function() {&lt;br /&gt;        return beta.verb();&lt;br /&gt;    }&lt;br /&gt;});&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;That looks simple enough. The first parameter of &lt;code&gt;define&lt;/code&gt; is the name of the module, the second is a list of external dependencies that the module has, and finally it's the declaration of the module itself. Using &lt;a href="http://requirejs.org/"&gt;RequireJS&lt;/a&gt;, the way to use such a module would be, (again, &lt;a href="http://requirejs.org/docs/start.html"&gt;from their own examples&lt;/a&gt;)&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;pre&gt;require(["helper/util"], function() {&lt;br /&gt;    //This function is called when scripts/helper/util.js is loaded.&lt;br /&gt;});&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;That's a simple enough API. Unfortunately, we can't use this directly for our polyfills, since we'll need to only download the dependencies if the browser doesn't already support them. So, maybe for our purposes, we'll need to have an API that looks like this:&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;pre&gt;require(["our/polyfill/helper"], function() {&lt;br /&gt;    requirePolyfills(["localStorage", "geolocation"], function() {&lt;br /&gt;        // Polyfills have been downloaded and applied now if necessary.&lt;br /&gt;        // We can code straight to the WhatWG/W3C APIs without worrying about browser differences.&lt;br /&gt;    });&lt;br /&gt;})&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;The &lt;code&gt;requirePolyfills&lt;/code&gt; function is responsible for downloading the polyfills necessary depending on browser support in an async manner, and then calling the function passed in to hand over control to the developer. The developer then doesn't have to worry about browser differences and can write simple code completely devoid of browser specific hacks. It gets me excited just to think of how awesome it will be to program once we've got browser differences out of the way.&lt;/p&gt;&lt;p&gt;Taking this a level further, this could be done by library authors itself, to ensure that the footprint of the library is as small as possible. This way Chrome users will have an excellent experience since there's no polyfill to be downloaded, while IE6 users will have the worst experience since many polyfills will have to be downloaded. If you think that's worse than the state of affairs today, consider that Chrome users currently have to download all the browser hacks for dealing with IE6 that exist in the library, and then the code-path never hits them. Wasted download, and the worst possible experience for all users thanks to IE6.&lt;/p&gt;&lt;p&gt;Libraries are slowly migrating towards the CommonJS AMD spec. &lt;a href="http://docs.dojocampus.org/releasenotes/1.6#id10"&gt;Dojo just announced partial support for it&lt;/a&gt; in their latest version. The landscape is bound to get better. If polyfills were to be part of the library itself, it would be awesome. That way, we ensure that the library has the smallest footprint possible.&lt;/p&gt;&lt;p&gt;That leaves us with two more problems. First: we need to develop a public repo of polyfills that are very well tested. The quality of polyfills is not something that library developers should be fighting over. Also, there's no reason for a polyfill to be tied into a library's APIs. And there's no reason why one shouldn't be able to use a polyfill without a library. The second problem is slightly more tricky. The problem is that of network latency. You wouldn't want to download a bunch of polyfills over slow network connections. Ideally, it should be just one file containing all the polyfills required for that browser. This might necessitate a change the API I've mentioned above. Feature detection obviously happens on the client, but then the client issues only one request for the polyfills file. The request could look something like: &lt;code&gt;http://example.com/polyfills?include=localStorage,geolocation&lt;/code&gt;. The server basically just concats the polyfills the client has requested, and sends them down in one file. Awesome.&lt;/p&gt;&lt;p&gt;Unfortunately here I've added a server component which suddenly makes this far less appealing to library authors, and for good reason. I don't know of a clean way to fix this, except saying that there should be publicly maintained servers that do this for everyone. Something like Google's CDN. This solution isn't ideal for several reasons, but it might be a good stop gap. Of course, there's also the possibility that open source implementations of such &lt;q&gt;polyfill servers&lt;/q&gt; can be developed for several languages, maybe even just web servers &amp;mdash; I'm thinking &lt;code&gt;mod_polyfill&lt;/code&gt; or something similar.&lt;/p&gt;&lt;p&gt;The best solution is not clear yet, but we have an idea of what it might look like. We'll have to see how things evolve in the coming few months to get clarity on this. Meanwhile, what do you think about this? Do you think there might be a better way to solve this problem?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-1194795543334888215?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/1194795543334888215/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=1194795543334888215' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/1194795543334888215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/1194795543334888215'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2011/01/impact-of-html5h-feature-detection.html' title='The Impact of HTML5^H: Feature Detection'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-27474329370145749</id><published>2010-10-16T16:48:00.011+05:30</published><updated>2010-10-17T16:53:09.883+05:30</updated><title type='text'>Practical CSS3 Media Queries and Mobile Browsers</title><content type='html'>&lt;style&gt;.photo {float: right;border: 1px solid #ddd; margin: 5px; padding: 5px;}.photo div{font-size: 10px; color: #888;text-align: right;}&lt;/style&gt;&lt;p style="background: #eee; border: 1px solid #666; padding: 7px;"&gt;&lt;strong&gt;tl;dr&lt;/strong&gt;: Jump to the &lt;a href="#wrapUp"&gt;end of this post &amp;darr;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I've been working on-and-off on a little project on the side, and have been trying to make it as buzzword-compliant as possible, because, you know, that's what all the cool kids are doing. Making it buzzword compliant meant that I had to use persistant connections to the server for &lt;a href="http://en.wikipedia.org/wiki/Real-time_web" title="The real-time web"&gt;real-time data exchange&lt;/a&gt;, use &lt;a href="http://en.wikipedia.org/wiki/Asynchronous_I/O" title="Asynchronous I/O"&gt;non-blocking I/O&lt;/a&gt;, I just &lt;em&gt;had&lt;/em&gt; to use &lt;a href="http://nodejs.org/"&gt;node.js&lt;/a&gt;, and throw in generous portions of &lt;a href="http://en.wikipedia.org/wiki/NoSQL" title="NoSQL"&gt;NoSQL&lt;/a&gt;. So I did all of that, and now my server is worthy of a &lt;a href="http://www.google.com/images?hl=en&amp;q=new+starburst&amp;biw=1536&amp;bih=843"&gt;&lt;q&gt;new&lt;/q&gt; starburst sticker&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Now that the server was mostly ready, I shifted attention to the client. Clearly, I had to use &lt;a href="http://diveintohtml5.org/"&gt;HTML5&lt;/a&gt; and &lt;a href="http://www.css3.info/"&gt;CSS3&lt;/a&gt;, think heavily about &lt;a href="http://developer.yahoo.com/performance/rules.html"&gt;Web Performance Optimization&lt;/a&gt;, and ensure that the usability trolls don't get a chance to make me look bad. That was the easy part, since I have been doing these things for years. The fun started when I decided to flirt with an idea I had never played with before.&lt;/p&gt;&lt;h2&gt;The Mobile Web&lt;/h2&gt;&lt;div class="photo"&gt;&lt;img src="http://farm5.static.flickr.com/4016/4294483304_3316fe0d3b_m.jpg" /&gt;&lt;div&gt;CC: &lt;a href="http://www.flickr.com/photos/trippchicago/4294483304/"&gt;-Tripp-&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Mobile devices, it seems, have finally arrived. We have forever dreamt of an always-connected world, and mobile devices seem to be delivering on that dream. Indeed, we are on the verge of having more traffic from mobile devices to the web than from desktop browsers&lt;sup&gt;[citation needed]&lt;/sup&gt;. In such a scenario, it's impossible to ignore mobile devices.&lt;/p&gt;&lt;p&gt;The problem is that no one knows what &lt;q&gt;the mobile web&lt;/q&gt; means. In such a case, it's absolutely fine to interpret it the way you want to, and that's what I did. So, here's what the mobile web means to me.&lt;/p&gt;&lt;blockquote&gt;The mobile web is that part of the web that works well on mobile devices.&lt;/blockquote&gt;&lt;p&gt;Pure genius of a definition, isn't it? I know. Thank you. There's an ambiguity in the definition there though &amp;mdash; what does it mean to &lt;em&gt;work well&lt;/em&gt;? Turns out, no one knows that either. But there are some hints:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;It should work fine in the mobile browser &amp;mdash; no native apps, no downloads.&lt;/li&gt;&lt;li&gt;Context is king. The site should provide the right amount of data that is needed in a mobile user's use-case at that time.&lt;/li&gt;&lt;li&gt;The site should be touch friendly, meaning take care about hit areas and stuff because some people have fat fingers. Not me &amp;mdash; my fingers are beautiful. Just thought you'd like to know.&lt;/li&gt;&lt;li&gt;Lightweight and fast. Because I want my data quickly, and I'm paying by the byte. This is true of the desktop as well, but especially true of the mobile web, because network operators try to suck as much as possible out of the wallet by giving as little as possible.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So, how do we go about building such a site? Generally speaking, this necessitates building a separate version of the site just for mobile browsers. Trust me, this effort is worth it. Don't believe all those standardistas who say &lt;q&gt;change your CSS file, and everything will be magically fine&lt;/q&gt;. Their latest mantra is &lt;q&gt;use CSS3 media queries and everything will be magically fine.&lt;/q&gt; Like most other things in life, nothing is that simple.&lt;/p&gt;&lt;p&gt;But there are times when that actually works. And this post is about those times. This post is only useful if:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Your site is already light enough and tightly focussed enough that the markup for your desktop version is going to be the same as that of your mobile version.&lt;/li&gt;&lt;li&gt;There's not really too much contextual data you need to provide to your mobile users, so again the markup is the same.&lt;/li&gt;&lt;li&gt;Your site is styled primarily with CSS. You are doing that already, aren't you?&lt;/li&gt;&lt;li&gt;You are lazy, and don't want to create multiple versions of the same content, otherwise known as maintainability or code reuse.&lt;/li&gt;&lt;/ul&gt;&lt;div class="photo"&gt;&lt;img src="http://farm4.static.flickr.com/3341/3600542728_c01d5b0766_m.jpg" /&gt;&lt;div&gt;CC: &lt;a href="http://www.flickr.com/photos/lcledward/3600542728/"&gt;Edward L&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;I'm definitely lazy, and I'm proud of it. I'd rather not write any code at all. If I have to write any code whatsoever, I'd rather write it such that (a) I never have to look at it again, (b) I keep using the same thing over and over again so I don't write the same thing ever again, and (c) I should write as little as possible. Fortunately, these are all considered good practices &amp;mdash; maintainability, reuse and conciseness. I bet whoever said these were good practices was lazy. But as long as the rest of the world doesn't find out, this can be our little secret.&lt;/p&gt;&lt;p&gt;There's a problem with being lazy though. You have to work hard to be lazy. How ironic is that! And hard work is, well, hard. So, there's where I was, wanting to be lazy, tinkering with the idea of the mobile web, and looking at CSS3 media queries from the corner of my eye. Being lazy, before I wrote a single line of code, I wanted to know everything about challenges for mobile phones and media queries. I'll cut a long story short, and tell you my findings.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;There's no standard screen size for the mobile.&lt;/strong&gt; If you plot a graph of &lt;a href="http://answers.google.com/answers/threadview?id=439967"&gt;mobile screen sizes&lt;/a&gt;, the graph is going to be all over the place. That basically means you have to design for all screen sizes! This is going to be fun. Not.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Media queries let you target styles to different ranges of screen sizes.&lt;/strong&gt; Awesome. Seems like a right fit for the job. So, we can have a different CSS file targeted to small screens, a different ones for medium sized screens (like the iPad), and the &lt;q&gt;full of crap&lt;/q&gt; ones for desktop browsers. Neat. Except...&lt;/li&gt;&lt;li&gt;&lt;strong&gt;CSS3 media queries don't work in most mobile browsers and IE!&lt;/strong&gt; Bam! Just when we thought we had a solution. Well, to be fair, it does work in some mobile phones &amp;mdash; the iPhone's and Android's WebKit browsers being good examples, but both these browsers put together are such a small percentage of mobile users, it's not even funny. Blackberry's horrid browser, Opera Mobile and Symbian's native browser have the largest market share of all mobile browsers. We can't just ignore them, can we! Just like we reluctantly show love to IE, we'll have to show some love to these browsers as well. It's that kind of a relationship. (BTW, I think Opera Mini does support CSS3 media queries. I haven't tested this.)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So, I was going to throw the idea of media queries completely out the door, you know, baby and bath water and all that. This is when I saw &lt;a href="http://www.lukew.com/ff/entry.asp?1137"&gt;an excellent talk by Luke Wroblewski&lt;/a&gt;. What he is advocating is that we should build for mobile sites &lt;em&gt;first&lt;/em&gt;, and for desktops later. His arguments are mostly non-technical and about usability, design and innovation, but he underscores the importance of designing for the mobile. I get that, but it doesn't help me be lazy. Well, it could, but I didn't know how. It still looked like double the effort. Except, he had planted an idea in my head. You know, much like Inception. Come to think of it, Luke does look a little bit like DiCaprio, doesn't he? Cool!&lt;/p&gt;&lt;h2&gt;Mobile First&lt;/h2&gt;&lt;div class="photo"&gt;&lt;img src="http://farm3.static.flickr.com/2509/3799729875_16098fe242_m.jpg" /&gt;&lt;div&gt;CC: &lt;a href="http://www.flickr.com/photos/mrs_logic/3799729875/"&gt;Mrs Logic&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;So far, I was thinking of making separate CSS files for mobile and desktop, and doing so in parallel. That mostly meant I'd do the desktop version first, and the mobile version next. Then I'd target different screen sizes with media queries (which I discovered wouldn't fly) and voila it would work everywhere. Instead, Luke's talk got me thinking: what if I design for the mobile first, and then &lt;em&gt;target desktop browsers with media queries&lt;/em&gt;. This would theoretically work, since most mobile browsers are old, and they get the vanilla CSS files. For newer mobile browsers and most desktop browsers since they are new as well, I'd serve the &lt;q&gt;full&lt;/q&gt; css file targeting them with media queries. Newer mobile browsers will understand it's not for them, so they'll ignore it. Older mobile browsers won't understand it at all, and hence ignore it. Most desktop browsers would know that the CSS file is for them, and hence apply it. This leaves our old nemesis Internet Explorer, but we're used to that already. We'll solve that problem later.&lt;/p&gt;&lt;p&gt;Now, about actually pulling it off. I found &lt;a href="http://dev.opera.com/articles/view/safe-media-queries/"&gt;this document at Dev.Opera&lt;/a&gt; that goes into a fair amount of detail about media query parsing differences between browsers, old and new. This doc would definitely help. Now, I needed to figure out how to structure the CSS. Remember my laziness? This meant that there should be as little repetition between the mobile version and the desktop version. What would generally be the things that remain common across the two types of browsers? There's actually quite a bit. There's color schemes, there's some type information, and possibly some CSS niceties like rounded corners, gradients and effects. What's going to be different? It's mostly going to be font-sizes and layout. Sounds good so far, let's start implementing it.&lt;/p&gt;&lt;h2&gt;The code&lt;/h2&gt;&lt;p&gt;Since we've decided to work only with mobile browsers first, and serve it CSS like it's the 1990s, the following markup should do it.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;link rel="stylesheet" type="text/css" href="narrow.css" /&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I actually went ahead with this and built the whole mobile version of the site, and tested it in Mobile Webkit on Android and iPhone and in Opera Mini, which are the two browsers I had access to on a couple of devices. I kept the layout fluid, since I didn't know the screen size before hand, and didn't want the site to break in screen sizes I didn't have control over. I strongly recommend that you go with fluid width layouts for narrow screens as well. I even tried it in a couple of emulators and it all looked fine. Of course, some of the fancy CSS rules didn't work on some browsers, but that was ok &amp;mdash; things still looked reasonably pretty and it looked mobile-web-optimized. Awesome. Now, I turned my attention to the desktop. This was when the Dev.Opera doc came in handy. This is what my markup looked like:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;link rel="stylesheet" type="text/css" href="narrow.css" /&amp;gt;&lt;br /&gt;&amp;lt;link rel="stylesheet" type="text/css" media="all and (min-width: 400px)" href="wide.css" /&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;See that media attribute there that says &lt;code&gt;media="all and (min-width: 400px)"&lt;/code&gt;? That's the media query. It means &lt;q&gt;target this CSS to &lt;em&gt;all&lt;/em&gt; media that have a &lt;em&gt;min-width&lt;/em&gt; of &lt;em&gt;400px&lt;/em&gt;&lt;/q&gt;. Why all media? Because I was being lazy and didn't want to work on a print version at the moment. Also, it seemed like the most reliable media type to target from Opera's documentation. Why base this on min-width? Because that's the best way to target different device sizes. Why 400px? Because in portrait mode it would apply the narrow.css (screen widths are generally 320px for devices that support orientation), but in landscape mode or for most desktop browsers, it would apply the wide.css file. This suited me, since I wanted to utilize the extra width in landscape mode better. YMMV, and you should play with this number to suit your tastes.&lt;/p&gt;&lt;p&gt;Also, since I was applying both the files and hence cascading their rules, I could already go with most of the stuff defined in narrow.css. wide.css only had to override some properties &amp;mdash; mostly font sizes, block positioning and layout. Tested this, and it continued to work with all the mobile devices I was testing in as it was before, and worked on desktop browsers with the wide.css layout. I just had to add &lt;del&gt;a few extra divs&lt;/del&gt; &lt;ins&gt;some HTML5 semantic markup&lt;/ins&gt; to get some extra styling hooks. Success! And I'm continuing to be lazy since I'm reusing as much code as possible. There is a disadvantage to this technique though. It requires the download of two files. I could have combined them into one file, but that would've introduced some hacks as described in the Dev.Opera document. I am consoling myself by saying that wide.css is actually a very small file, and CSS files are downloaded in parallel anyway, so the impact shouldn't be huge. But that said, it is something to think about.&lt;/p&gt;&lt;h2&gt;&lt;a name="wrapUp"&gt;&lt;/a&gt;Wrapping it up&lt;/h2&gt;&lt;p&gt;That just leaves us with one beast &amp;mdash; the old nemesis &amp;mdash; Internet Explorer. We've gone through all this trouble to support all sorts of crappy old mobile browsers, it only makes sense that we don't leave IE behind. Now, IE doesn't understand media queries, so how do we serve it wide.css? Turns out, we can use IE against IE, thanks to it's own conditional comments! The final markup looked like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;link rel="stylesheet" type="text/css" href="narrow.css" /&amp;gt;&lt;br /&gt;&amp;lt;!--[if lt IE 9 ]&amp;gt;&lt;br /&gt;&amp;lt;link rel="stylesheet" type="text/css" href="wide.css"&amp;gt;&lt;br /&gt;&amp;lt;![endif]--&amp;gt;&lt;br /&gt;&amp;lt;!--[if (gte IE 9)|!(IE)]&amp;gt;&amp;lt;!--&amp;gt;&lt;br /&gt;    &amp;lt;link rel="stylesheet" type="text/css" media="all and (min-width: 400px)" href="wide.css"&amp;gt;&lt;br /&gt;&amp;lt;!--&amp;lt;![endif]--&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="photo"&gt;&lt;img src="http://farm3.static.flickr.com/2205/2164396242_73db0b94ed_m.jpg" /&gt;&lt;div&gt;CC: &lt;a href="http://www.flickr.com/photos/bluesmuse/2164396242/"&gt;Simon Zirkunow&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Let's dissect that. Firstly, serve the old narrow.css the way it was being served. No change there. Next, detect if the browser is IE and the version is less than 9. Why 9? Because MS is promising that IE9 has got media query support, so we'd rather use that over blindly serving the file to IE. If it is less than IE9, serve it wide.css no questions asked. If the IE version is 9 or greater, or if it's a non-IE browser, serve it wide.css with the media query.&lt;/p&gt;&lt;p&gt;This post is bound to be outdated before it's even out, since MS is launching Windows Mobile 7 or whatever it is called with a very uninteresting version of  IE which is purportedly somewhere between 7 and 8. But I don't know yet how the browser is identifying itself, and hence can't exclude wide.css from it. If you find out, please leave me a comment, and I'll update my post with your findings.&lt;/p&gt;&lt;h2&gt;In the end&lt;/h2&gt;&lt;p&gt;We've successfully managed to:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Target mobile phones, new and old.&lt;/li&gt;&lt;li&gt;Match device orientation for newer phones.&lt;/li&gt;&lt;li&gt;Apply different CSS to desktop browsers.&lt;/li&gt;&lt;li&gt;Get it working even for the thing that is IE.&lt;/li&gt;&lt;li&gt;Keep Luke happy.&lt;/li&gt;&lt;li&gt;Done all of this without using any pesky JavaScript or server-side UA sniffing.&lt;/li&gt;&lt;li&gt;Continued to be lazy.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;This has not been without drawbacks:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Two CSS files are downloaded to &lt;q&gt;wide&lt;/q&gt; clients. To make things worse, some parts of narrow.css are overridden in wide.css, making the double-download even more painful.&lt;/li&gt;&lt;li&gt;Mobile IE gets the wide version, mostly because I don't know too much about it.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;This works for me for the moment though. Would love to hear your thoughts.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;em&gt;Like this post? I blabber on a lot about this kind of stuff on the twitters. &lt;a href="http://twitter.com/rakesh314"&gt;Follow me there&lt;/a&gt; if you like.&lt;/em&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-27474329370145749?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/27474329370145749/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=27474329370145749' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/27474329370145749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/27474329370145749'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2010/10/practical-css3-media-queries-and-mobile.html' title='Practical CSS3 Media Queries and Mobile Browsers'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm5.static.flickr.com/4016/4294483304_3316fe0d3b_t.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-8601383328926626714</id><published>2010-04-11T13:12:00.008+05:30</published><updated>2010-04-11T21:27:51.732+05:30</updated><title type='text'>Section 3.3.1 of iPhone SDK License Agreement</title><content type='html'>&lt;style type="text/css"&gt;.photo {float: right;border: 1px solid #ddd; margin: 5px; padding: 5px;}.photo div{font-size: 10px; color: #888;text-align: right;}&lt;/style&gt;&lt;div class="photo"&gt;&lt;img src="http://farm4.static.flickr.com/3235/2830319467_634c5c8316_m.jpg" /&gt;&lt;div&gt;CC: &lt;a href="http://www.flickr.com/photos/williamhook/2830319467/"&gt;William Hook&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;It has been an interesting week for iPhone developers. iPhone just released the developer preview of the &lt;a href="http://www.apple.com/iphone/preview-iphone-os/"&gt;iPhone OS 4&lt;/a&gt;, which has got features that are exciting to both developers and users. However, &lt;a href="http://daringfireball.net/2010/04/iphone_agreement_bans_flash_compiler"&gt;John Gruber discovered&lt;/a&gt; that Apple made a change to their iPhone SDK Licence Agreement with this release.&lt;/p&gt;&lt;blockquote&gt;3.3.1 — Applications may only use Documented APIs in the manner prescribed by Apple and must not use or call any private APIs. Applications must be originally written in Objective-C, C, C++, or JavaScript as executed by the iPhone OS WebKit engine, and only code written in C, C++, and Objective-C may compile and directly link against the Documented APIs (e.g., Applications that link to Documented APIs through an intermediary translation or compatibility layer or tool are prohibited).&lt;/blockquote&gt;&lt;p&gt;This amendment has far-reaching effects. The effects are so powerful that the FUD surrounding it over-shadowed the excitement of the OS upgrade itself. There's no doubt that there's evilness in this amendment to the ToS. The question is what part of it is evil, and how should we react to it. Let's analyze this amendment, and see what it potentially means.&lt;/p&gt;&lt;h2&gt;On APIs&lt;/h2&gt;&lt;blockquote&gt;Applications may only use Documented APIs in the manner prescribed by Apple and must not use or call any private APIs.&lt;/blockquote&gt;&lt;p&gt;This seems reasonable to me. It's Apple's platform, and they expose a bunch of APIs, and they only want developers to use those APIs. However, it stinks of potential anti-trust cases. However, this is not what got people pissed off for, so let's skip past this statement.&lt;/p&gt;&lt;h2&gt;On language of choice&lt;/h2&gt;&lt;blockquote&gt;Applications must be originally written in Objective-C, C, C++, or JavaScript as executed by the iPhone OS WebKit engine, and only code written in C, C++, and Objective-C may compile and directly link against the Documented APIs&lt;/blockquote&gt;&lt;div class="photo"&gt;&lt;img src="http://farm4.static.flickr.com/3046/3070394453_7d56b111bd_m.jpg" /&gt;&lt;div&gt;CC: &lt;a href="http://www.flickr.com/photos/shanegorski/3070394453/"&gt;Shane Gorski&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;This is plain stupid, and only serves to push developers away. Everyone knows that the choice of programming language hardly matters in any meaningful way, and&lt;a href="http://www.joelonsoftware.com/items/2006/09/01.html"&gt; what the developer is comfortable with is what s/he should ultimately use&lt;/a&gt;. This clause doesn't allow for that, and there's no good reason why it shouldn't. Just plain stupid.&lt;/p&gt;&lt;p&gt;This kills the soon-to-be-released &lt;a href="http://labs.adobe.com/technologies/flashcs5/appsfor_iphone/"&gt;CS5 Flash-to-iPhone compiler&lt;/a&gt;, &lt;a href="http://monotouch.net/"&gt;the MonoTouch project&lt;/a&gt; which compiles C# and .Net to the iPhone, and &lt;a href="http://unity3d.com/unity/"&gt;the Unity3D project&lt;/a&gt; that let you program 3D games in C#.&lt;p&gt;However, also consider that without asking you for your source code, how can Apple guess which programming language you used for development? It's all compiled anyway. It just doesn't make sense. I don't see how Apple can enforce this. We'll have to see how this develops.&lt;/p&gt;&lt;h2&gt;On compatibility layers&lt;/h2&gt;&lt;blockquote&gt;(e.g., Applications that link to Documented APIs through an intermediary translation or compatibility layer or tool are prohibited).&lt;/blockquote&gt;&lt;p&gt;This is the big one, and is the reason most people are pissed off, because it's implications are far reaching.&lt;/p&gt;&lt;p&gt;Firstly, consider the case where I want to build an iPhone app using Ruby, and I use a library that has wrappers on top of the Objective-C APIs. This is like the point above, where I should be able to choose my language and program in it. And like I said above, there's no reason to restrict this, and it's stupid on Apple's part to do this.&lt;/p&gt;&lt;p&gt;The other case is that of &lt;a href="http://en.wikipedia.org/wiki/Compatibility_layer"&gt;compatibility layers&lt;/a&gt;, where I code to an API much like above, but the compiler is designed to cross-compile to multiple platforms, not just the iPhone. This is the big one, and is what makes the future of platforms like &lt;a href="http://www.appcelerator.com/"&gt;Titanium&lt;/a&gt; and &lt;a href="http://phonegap.com/"&gt;PhoneGap&lt;/a&gt; unclear. This means that as a developer, I only need to write once and the environment let's me compile and run anywhere. As we all know the write-once-run-anywhere dream &lt;a href="http://en.wikipedia.org/wiki/Cross-platform#Challenges_to_cross-platform_development"&gt;has eluded us all the time&lt;/a&gt; &amp;mdash; Java, Air and Flash being great examples of it. A look at applications like &lt;a href="http://www.eclipse.org/screenshots/"&gt;Eclipse&lt;/a&gt;, &lt;a href="http://www.openoffice.org/screenshots/"&gt;Open Office&lt;/a&gt;, etc., and virtually anything developed using Flash, and you'll see that it feels nothing like a native application on all platforms. This is neither the fault of the language nor the compiler, but that of the platform APIs (like &lt;a href="http://en.wikipedia.org/wiki/Swing_(Java)"&gt;Swing&lt;/a&gt; in Java's case). The problem is that since the platform API, which serves as a &lt;q&gt;compatibility layer&lt;/q&gt; in these cases, tries to expose APIs that can work everywhere, they are forced to do a bad job of it.&lt;/p&gt;&lt;p&gt;Let me illustrate this with an example, to drive the point home. The Mac doesn't have a UI for combo-boxes, whereas both Windows and Linux do. What would a compatibility layer do in such a case? There are four possibilities:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;If the API makes it possible to use combo-boxes everywhere, it'll not feel native on the Mac, because the OS itself doesn't do these kinds of UIs. The platform will have to fake it.&lt;/li&gt;&lt;li&gt;If it doesn't let you use combo-boxes anywhere, it'll seem less powerful on Windows for developers, and will provide a bad UX for users.&lt;/li&gt;&lt;li&gt;It can choose to present completely custom UIs, which falls in neither camps, and hence fails.&lt;/li&gt;&lt;li&gt;They could also say that you can use combo-boxes in Windows and not on the Mac, but that'll only make the programming experience horrible for developers.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;So which approach is the least bad? Swing decides to compromise on UX. Flash goes the route of custom UIs.&lt;/p&gt;&lt;p&gt;An interesting case to consider is that of &lt;a href="http://www.google.com/chrome"&gt;Google Chrome&lt;/a&gt;, which has done the absolute right thing. The core engine is C/C++, and UIs are coded separately for different OSs. However, this is clearly expensive to do, and only someone with Google's resources can pull it off.&lt;/p&gt;&lt;div class="photo"&gt;&lt;img src="http://farm4.static.flickr.com/3238/2997298827_a8e3a21e88_m.jpg" /&gt;&lt;div&gt;CC: &lt;a href="http://www.flickr.com/photos/flickrohit/2997298827/"&gt;Rohit Gowaikar&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Of course, there's also the possibility that Apple just wants to make it hard for developers to build apps that can run anywhere, by creating a lock-in. However, I don't think this is the case, because they are still allowing JS to run, and their browser is one of the best browsers ever that a developer can work with. This browser itself can be looked at as a compatibility layer that works across platforms. I've actually tried it &amp;mdash; fairly complex applications built for the iPhone work just fine in Android-based touch phones with zero effort to port it. This is because when you develop for the iPhone browser, you are actually developing for Mobile WebKit, and has nothing to do with the iPhone Objective-C APIs per-se.&lt;/p&gt;&lt;p&gt;Aside: I've just negated my own point. I've criticized cross-compilers, and then said that the browser is a great environment to code because you are platform independent. However, I think that you should &lt;q&gt;think different&lt;/q&gt; (pun intended) about browsers. This is because the browser is a sandbox that &lt;q&gt;runs the Internet&lt;/q&gt; from the user's perspective, and it's expected that the UIs on web pages will be platform independent. That's not the case with native applications. Besides, the browser doesn't just run applications &amp;mdash; they are also content distribution channels.&lt;/p&gt;&lt;p&gt;From the point of view of the UX of applications built using a cross-compiler compatibility layer, I sympathize with what Apple's done. Do I think such apps should be banned completely? I'm sitting on the fence on this one. I think the best thing to do would be to &lt;a href="http://news.ycombinator.com/item?id=1251017"&gt;let the application fail in the market&lt;/a&gt;, rather than disallowing such applications outright. But then, &lt;a href="http://daringfireball.net/2010/04/why_apple_changed_section_331"&gt;I can see why Apple would ban it&lt;/a&gt; as well. Apple has always been a stickler for the UX of applications on their platforms. On the other hand however, they enforced this on the Mac OS &lt;a href="http://developer.apple.com/Mac/library/documentation/UserExperience/Conceptual/AppleHIGuidelines/XHIGIntro/XHIGIntro.html"&gt;by giving guidelines&lt;/a&gt;, not by disallowing such applications. So this thought is full of contradictions.&lt;/p&gt;&lt;div class="photo"&gt;&lt;img src="http://farm4.static.flickr.com/3083/2539111053_578248a6eb_m.jpg" /&gt;&lt;div&gt;CC: &lt;a href="http://www.flickr.com/photos/nataliemaynor/2539111053/"&gt;Natalie Manyor&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Then there's the case of &lt;a href="http://www.apple.com/iphone/apps-for-iphone/"&gt;the app store&lt;/a&gt;. The idea of a market place is awesome, but &lt;a href="http://joehewitt.com/post/innocent-until-proven-guilty/"&gt;Apple's moderation is just stupid&lt;/a&gt;. Other issues apart (and there are several), it's a model that simply doesn't scale. Maybe Apple did this 3.3.1 thing just to ensure that they can moderate lesser apps and make their moderation generally easier to do? If that's the case, Apple is just reducing their problems and moving it to all their developers. Just another reason why Apple's moderation is stupid. Why Apple moderates is beyond me. No other platform that I know of does this, including Apple's own desktop OSs.&lt;/p&gt;&lt;h2&gt;History repeats itself, sort of&lt;/h2&gt;&lt;p&gt;There's a bigger concern I've got. Let me put it this way. I used to be a VB developer back in the day. When the Internet started becoming interesting, I found out that I could take my VB knowledge and port it to the web to build ASP programs. It was awesome, and I loved how Microsoft had made it easy for devs to move to the web as a platform. However, when the .Net framework was released, MS told developers like me that ASP was not cool anymore, and that we should choose either C# or VB.Net. VB.Net, for those who don't know, is nothing like VB. It's an entirely new language. Besides, MS seemed to put it's weight behind C#. Most developers were convinced that they should move to C#.&lt;/p&gt;&lt;p&gt;Not me. I was filled with FUD. I couldn't let a company decide what programming language I should use. What if I pick up C# and a couple of years later, just as I'm getting comfortable with it, they tell me that C# is not cool anymore? Am I shooting a moving target?&lt;/p&gt;&lt;p&gt;That was the time when I picked up my bags, and moved from the MS platform to open platforms. I picked up PHP because it's programming model resembled ASP, so the learning curve would be smooth. Of course, I still had to learn a new language, but at least this time it wasn't controlled by a company and I could use it just because there was community support. And PHP had (and still has) great community support. I had immunized myself from what companies have to say about my development tool chain. I was free!&lt;/p&gt;&lt;p&gt;&lt;em&gt;In hindsight, this was the single most important decision I've taken that transformed my career. Not that I was any good at PHP. But the world of open platforms and open standards based development made me a better programmer.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Though the situation is not exactly the same in Apple's case, it's not too different. Here's a company screwing it's developers up because of what they think is the ideal vision for the platform. It's not a democratic decision &amp;mdash; neither MS nor Apple consulted me when they were making this change. If I was now an Apple developer, I would hear alarm bells ringing, and would refuse to work in such a totalitarian environment.&lt;/p&gt;&lt;h2&gt;But the iPhone is where my target demographic is!&lt;/h2&gt;&lt;p&gt;Sure. I still think despite all of this that the iPhone is still a cool gadget, and users will continue to be attracted to it. And developers go where the users are. What's the point developing applications for platforms where there are no users! So, you want to build for the iPhone, but you don't want to build for the iPhone. How do you fix this?&lt;/p&gt;&lt;div class="photo"&gt;&lt;img src="http://farm4.static.flickr.com/3514/3248366114_04ca0e3064_m.jpg" /&gt;&lt;div&gt;CC: &lt;a href="http://www.flickr.com/photos/vitroids/3248366114/"&gt;Masakazu Matsumoto&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The solution is simple. Move to an open platform. I'm not saying that you should stop building for the iPhone, and move to Android. That'd be stupid. I'm saying that you build for the browser, and serve both iPhone and Android users in one go. As a long-time web developer and currently exploring the mobile-WebKit browser, I can tell you that the mobile-WebKit browser is the best thing to happen to web development in a long time. It has imbibed standards support like no other browser has, even on desktop computers. HTML5 provides access to APIs that are mostly sufficient to build rich mobile applications. You've got excellent control on layout etc, since the CSS support is one of the best in the browser landscape. In fact, the browser in the latest phones is so good, I find it difficult to understand why I'd ever build a native application.&lt;/p&gt;&lt;p&gt;Here's a listing of some APIs that are available in the iPhone's and Android's browsers, that you probably didn't know existed. Yes, you can use all of these APIs today!&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.w3.org/TR/geolocation-API/"&gt;APIs to get the users location&lt;/a&gt; using the GPS or cell-tower triangulation&lt;/li&gt;&lt;li&gt;APIs to make the application &lt;a href="http://developer.apple.com/safari/library/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/OfflineApplicationCache/OfflineApplicationCache.html"&gt;work offline&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Local storage in the form of: &lt;ul&gt;&lt;li&gt;&lt;a href="http://developer.apple.com/safari/library/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/Name-ValueStorage/Name-ValueStorage.html#//apple_ref/doc/uid/TP40007256-CH6-SW1"&gt;key-value stores&lt;/a&gt;, or&lt;/li&gt;&lt;li&gt;&lt;a href="http://developer.apple.com/safari/library/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/UsingtheJavascriptDatabase/UsingtheJavascriptDatabase.html#//apple_ref/doc/uid/TP40007256-CH3-SW1"&gt;relational ACID compliant DBs&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Awesome &lt;a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html"&gt;drawing APIs&lt;/a&gt; and &lt;a href="http://www.w3.org/TR/SVG11/"&gt;vector graphics APIs&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Of course, there are cases where you need to build a native application. Like if you want access to the camera. Or if you want to use the user's contact list. Or access the accelerometer. I'd still go native for those kinds of applications. However, very soon, that's likely to change as well, with the upcoming &lt;a href="http://dev.w3.org/2009/dap/camera/"&gt;Capture API&lt;/a&gt; and &lt;a href="http://www.w3.org/TR/2010/WD-contacts-api-20100121/"&gt;Contacts API&lt;/a&gt; that are being spec'd. And I'm sure WebKit will one of the first browsers to adopt it.&lt;/p&gt;&lt;p&gt;On the whole, there's very little reason now to build native applications for the iPhone. Do it only if you know what you are doing, and you absolutely need to. Ask yourself before you start if you absolutely must go native. You'll discover that in most cases you won't need to. The browser is good enough. And you'll have supported other touch-phones while you are at it, for free, at its very least. At best, you've supported the entire mobile browser landscape, though that's a hard one, and realistically speaking you will compromise on the user experience.&lt;/p&gt;&lt;p&gt;One last concern remains. What if Apple decides to somehow ban browser based applications? Technologically speaking, I don't see how they can do that without reducing the power of the browser itself. One of the reasons the iPhone took off was because it shipped with a &lt;q&gt;real browser&lt;/q&gt;. If they reduce the power of the browser, they reduce the usefulness of the phone itself. I don't see that happening. Secondly, the browser engine is actually developed independently of Apple &amp;mdash; in fact &lt;a href="http://techcrunch.com/2010/02/06/google-apple-webkit/"&gt;Google contributes more to WebKit than Apple does&lt;/a&gt;. Unless Apple decides to revert to an older version of WebKit, or cherry-pick features from the public builds, they'll have to continue shipping the public builds of WebKit or feature-freeze on the current build. If anyone thinks Apple will (or can) control browser based applications, they're just plain wrong. The web is far too big for Apple to make such a move.&lt;/p&gt;&lt;p&gt;These are my thoughts. I'd be extremely interested in knowing what you think. Are you affected by this change? Are you going to move to the browser?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-8601383328926626714?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/8601383328926626714/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=8601383328926626714' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/8601383328926626714'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/8601383328926626714'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2010/04/section-331-of-iphone-sdk-license.html' title='Section 3.3.1 of iPhone SDK License Agreement'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm4.static.flickr.com/3235/2830319467_634c5c8316_t.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-1289249588622178405</id><published>2009-10-18T01:03:00.002+05:30</published><updated>2009-10-18T01:09:46.053+05:30</updated><title type='text'>geocitieslycostripod.com</title><content type='html'>&lt;p&gt;Just deployed a new site to display my HTML5 learnings so far.&lt;/p&gt;&lt;p&gt;The idea is to demonstrate the proper use of the section, article, time, header and footer tags. I might have used a couple others. I've also used some CSS3 text-shadow rules for the first time ever in a production website. I hope to get positive comments from you about the site.&lt;/p&gt;&lt;p&gt;So go to my new site: &lt;a href="http://geocitieslycostripod.com"&gt;http://geocitieslycostripod.com&lt;/a&gt; for the full glory of HTML5.&lt;/p&gt;&lt;p&gt;PS. Hey, I didn't say anything about Web 1.0 or Web 2.0 or anything!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-1289249588622178405?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/1289249588622178405/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=1289249588622178405' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/1289249588622178405'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/1289249588622178405'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2009/10/geocitieslycostripodcom.html' title='geocitieslycostripod.com'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-3388846403042600239</id><published>2009-08-22T16:04:00.001+05:30</published><updated>2009-08-22T16:37:29.113+05:30</updated><title type='text'>Songs In Code</title><content type='html'>&lt;p&gt;&lt;a href="http://twitter.com/codepo8/"&gt;Christian Heilmann&lt;/a&gt; of YDN fame, started a meme on twitter for writing songs in code, within the 140 char limit of course. Participation was simple: simply add a hashtag of &lt;a href="http://search.twitter.com/search?q=%23songsincode"&gt;#songsincode&lt;/a&gt; to the tweet. Quite soon, it became a trending topic on twitter. One way to look at it is that people on twitter have nothing to do, but the more likely one is that geeks found something to kill time with on a Friday.&lt;/p&gt;&lt;p&gt;Of course, quite a few gems came out of it. I'm listing a couple of my favourites below:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;!my.isLover(billyJean) &amp;&amp; billyJean.claims(my.theOne) &amp;&amp; !my.isSon(theKid)&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;while (countdown &gt; FINAL)&lt;br /&gt;&amp;nbsp;&amp;nbsp;countdown--;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;public void setShirt(Shirt s){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw new ImTooSexyException(s);&lt;br /&gt;}&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;if (this.streets.name == undefined) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_root.where = this&lt;br /&gt;}&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;SELECT person WHERE AGE &gt; 12 AND AGE &lt;20 AND SMELLS LIKE '%SPIRIT%&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;&amp;lt;span style="color:#f00"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;span style="color:#f00"&amp;gt;wine&amp;lt;/span&amp;gt;&lt;br /&gt;&amp;lt;/span&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;if(me.crazy.go()){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;you.call(meSuperman)&lt;br /&gt;};&lt;br /&gt;function meSuperman(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return '?' //Kryptonite&lt;br /&gt;}&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;.clowns{float:left;}&lt;br /&gt;.jokers{float:right};&lt;br /&gt;#me_you{position:fixed;margin:0 auto;width:100%}&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;var i = {shot:{sheriff:true,deputy:false}}&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;try{if(money&gt;0 &amp;&amp; work=='' &amp;&amp; chicks=='free'){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw 'that ain\'t working'&lt;br /&gt;}}&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;class HotelCalifornia { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void checkOut () {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;canLeave=false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;while(1){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Britney.Sing();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} catch (Exception ex) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw new Exception("Oops");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;UPDATE people SET parent_occupation = 'preacher man' WHERE has_pleased = 1&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;["step", "move"].forEach(i.watchingYou);&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;(defun get (x) (if (neq x 'satisfaction) (error)))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(get (not satisfaction)) ;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;99.times {Ballon.new(:red)}&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-3388846403042600239?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/3388846403042600239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=3388846403042600239' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/3388846403042600239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/3388846403042600239'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2009/08/songs-in-code.html' title='Songs In Code'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-8288633186397270993</id><published>2009-03-20T16:12:00.009+05:30</published><updated>2009-08-27T19:27:39.520+05:30</updated><title type='text'>Downloading JavaScript Files in Parallel</title><content type='html'>&lt;p style="border: 1px solid #666; background: #ddd; padding: 5px;"&gt;&lt;strong&gt;Update: &lt;/strong&gt; There were some bugs in the code here, which have been fixed. If you were using the older version of this script on your site, you should update it.&lt;br /&gt;Also, a lot of people have got back to me about them getting undefined symbols, so I've highlighted parts of this post that are absolutely critical for it's functioning.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.stevesouders.com/"&gt;Steve Souders&lt;/a&gt;, creator of &lt;a href="http://developer.yahoo.com/yslow/"&gt;YSlow&lt;/a&gt;, author of the book &lt;q&gt;&lt;a href="http://www.amazon.com/dp/0596529309?tag=stevsoud-20&amp;camp=14573&amp;creative=327641&amp;linkCode=as1&amp;creativeASIN=0596529309&amp;adid=1S1KP4EV129EN37422C0&amp;"&gt;High Performance Web Sites&lt;/a&gt;&lt;/q&gt;, is back in action writing a book titled &lt;q&gt;&lt;a href="http://www.amazon.com/Even-Faster-Websites-Essential-Knowledge/dp/0596522304/"&gt;Even Faster Websites&lt;/a&gt;&lt;/q&gt;. In it he details what one can do after the &lt;a href="http://stevesouders.com/examples/rules.php"&gt;14 YSlow rules&lt;/a&gt; (laws?) have been implemented, and you still want better better performance.&lt;/p&gt;&lt;p&gt;6 days ago, Steve gave a talk at &lt;a href="http://sxsw.com/interactive/"&gt;SXSW Interactive&lt;/a&gt;, the &lt;a href="http://www.slideshare.net/souders/sxsw-even-faster-web-sites"&gt;slides of which are available on Slideshare&lt;/a&gt;. In it, he goes on to suggest (slide 27), that we should &lt;q&gt;load scripts without blocking&lt;/q&gt;. To me, this seems like a very interesting idea, and based on his hints in the next few slides, I started experimenting.&lt;/p&gt;&lt;p&gt;Let me back up a little. When browsers download scripts, they block all other resources from downloading until such time that the script has finished downloading. When I mean all other resources, it includes even other CSS files and images. There are several ways to &lt;em&gt;reduce the impact of serial script download&lt;/em&gt;, and the &lt;q&gt;High Performance Websites&lt;/q&gt; book makes a couple of good suggestions.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Rule 1 - Make Fewer HTTP Requests&lt;/li&gt;&lt;li&gt;Rule 5 - Put Stylesheets at the Top&lt;/li&gt;&lt;li&gt;Rule 6 - Put Scripts at the Bottom&lt;/li&gt;&lt;li&gt;Rule 8 - Make JavaScript and CSS External&lt;/li&gt;&lt;li&gt;Rule 10 - Minify JavaScript&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;There are several others, mostly around caching strategies and reducing HTTP overhead, but these alone reduce the impact of serial script download significantly.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Now, if you haven't already taken care of these rules of optimization, my suggestion will be hard to implement, or will reap no benefits&lt;/strong&gt;. You can stop reading now, and go back to your site to optimize your code.&lt;/p&gt;&lt;h2&gt;Regular &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags:&lt;/h2&gt;&lt;p style="text-align: center"&gt;&lt;a href="http://www.flickr.com/photos/rakesh/3370655064/" title="Serial script download by Rakesh Pai, on Flickr"&gt;&lt;img src="http://farm4.static.flickr.com/3617/3370655064_16f81f38cf_o.png" width="750" height="160" alt="Serial script download" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;See that &lt;q&gt;waterfall pattern&lt;/q&gt; of file downloads? Nothing else is downloaded when a script is being downloaded, not even other scripts. The time gap between successive downloads is the time taken to evaluate the script, roughly proportional to the size of the script. Notice also that this takes in excess of 600ms even when the files are being served from my local machine, effectively having near-zero network latency.&lt;/p&gt;&lt;h2&gt;With script parallelization&lt;/h2&gt;&lt;p style="text-align: center"&gt;&lt;a href="http://www.flickr.com/photos/rakesh/3369833031/" title="Parallel script download by Rakesh Pai, on Flickr"&gt;&lt;img src="http://farm4.static.flickr.com/3552/3369833031_630615b831_o.png" width="753" height="155" alt="Parallel script download" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Now, this looks much better, doesn't it? Not only has everything downloaded in parallel, it has taken less than half the time for the same size of files. In fact, you will notice that some noise when recording this data made the files take &lt;em&gt;longer&lt;/em&gt; to download in this case, yet the total time was &lt;em&gt;less than half&lt;/em&gt; of the pervious case.&lt;/p&gt;&lt;p&gt;So, how did I do this? Read on...&lt;/p&gt;&lt;h2&gt;One script tag to rule them all&lt;/h2&gt;&lt;p&gt;Reading into Souders' suggested techniques (If you still have &lt;a href="http://www.slideshare.net/souders/sxsw-even-faster-web-sites"&gt;that slideshow&lt;/a&gt; open, go to slide 26), I decided that what I wanted was:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;I want the browser busy indicators to show,&lt;/li&gt;&lt;li&gt;I want a script that doesn't care if I'm downloading from the same domain or not, and&lt;/li&gt;&lt;li&gt;I wanted to preserve the evaluation order in case of interdependent scripts.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So, I came up with the following little script:&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;pre&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;    (function() {&lt;br /&gt;        var s = [&lt;br /&gt;            "/javascripts/script1.js",&lt;br /&gt;            "/javascripts/script2.js",&lt;br /&gt;            "/javascripts/script3.js",&lt;br /&gt;            "/javascripts/script4.js",&lt;br /&gt;            "/javascripts/script5.js"&lt;br /&gt;        ];&lt;br /&gt;&lt;br /&gt;        var sc = "script", tp = "text/javascript", sa = "setAttribute", doc = document, ua = window.navigator.userAgent;&lt;br /&gt;        for(var i=0, l=s.length; i&amp;lt;l; ++i) {&lt;br /&gt;            if(ua.indexOf("Firefox")!==-1 || ua.indexOf("Opera")!==-1) {&lt;br /&gt;                var t=doc.createElement(sc);&lt;br /&gt;                t[sa]("src", s[i]);&lt;br /&gt;                t[sa]("type", tp);&lt;br /&gt;                doc.getElementsByTagName("head")[0].appendChild(t);&lt;br /&gt;            } else {&lt;br /&gt;                doc.writeln("&amp;lt;" + sc + " type=\"" + tp + "\" src=\"" + s[i] + "\"&amp;gt;&amp;lt;/" + sc + "&amp;gt;");&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    })();&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;It's a little ugly: There's a user-agent sniff happening in there and I've written it so as to use the least number of bytes possible (save for the indentation), but it works, and has no dependencies on any library. Just modify the array on top to place your list of scripts you wish to include, and let the rest of the script do the dirty work. If you need to include scripts from another domain, just use an absolute path.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;This code was written keeping in mind that this should be the only piece of on-page inline JavaScript.&lt;/strong&gt; This can then go on and fetch the script required in parallel, and those in turn can unobtrusively do their thing.&lt;/p&gt;&lt;p&gt;This works as advertised in IE and FF. &lt;del&gt;I haven't tested the parallelization in other browsers, but at least it fails gracefully and preserves script execution order.&lt;/del&gt; &lt;ins&gt;This has now been tested in Safari, Chrome and Opera as well, and works as advertised everywhere.&lt;/ins&gt;&lt;/p&gt;&lt;hr /&gt;&lt;em&gt;Find this interesting? Follow me on twitter at &lt;a href="http://twitter.com/rakesh314"&gt;@rakesh314&lt;/a&gt; for more.&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-8288633186397270993?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/8288633186397270993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=8288633186397270993' title='20 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/8288633186397270993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/8288633186397270993'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2009/03/downloading-javascript-files-in.html' title='Downloading JavaScript Files in Parallel'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>20</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-3866634575837877689</id><published>2009-01-21T19:20:00.003+05:30</published><updated>2009-01-22T01:33:18.267+05:30</updated><title type='text'>JsMemcached.js - A Jaxer client for memcached</title><content type='html'>&lt;p&gt;Two days ago, on a lazy evening, I started work on my first solid &lt;a href="http://www.aptana.com/jaxer/"&gt;Jaxer&lt;/a&gt; project &amp;mdash; building a memcached client. As a testimony to the elegance of JavaScript, it took me less than 2 hours to get a basic memcached client up and running.&lt;/p&gt;&lt;p&gt;What is memcached, you ask? From the &lt;a href="http://www.danga.com/memcached/"&gt;memcached website&lt;/a&gt;:&lt;/p&gt;&lt;blockquote&gt;memcached is a high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load.&lt;/blockquote&gt;&lt;p&gt;What it does is, lets you use excess RAM on your server machines as temporary stores of data, so that you can avoid going to your DB when you want frequently accessed data. Needless to say, accessing data from RAM is much faster. Since the creation of memcached for &lt;a href="http://www.livejournal.com/"&gt;LiveJournal.com&lt;/a&gt;, memcached has become the cheapest and fastest way to scale a website.&lt;/p&gt;&lt;p&gt;Now, my implementation is not feature complete, nor at peak performance, but I aim to take it there. Even so, I decided to get my code out and available for everyone to see, so that people can tell me what they think of it.&lt;/p&gt;&lt;p&gt;You can go to the &lt;a href="http://code.google.com/p/jsmemcached-client/"&gt;Google code page for the JsMemcached-client project&lt;/a&gt;, or &lt;a href="http://jsmemcached-client.googlecode.com/files/jsMemcached.js"&gt;download the code&lt;/a&gt; right away. Though limited in features and with a possible bug in an edge case in the get call, you can start using this already.&lt;/p&gt;&lt;p&gt;This is my first open-source project, so please don't be too harsh in your feedback.&lt;/p&gt;&lt;p style="border: 1px solid red; background: pink; padding: 5px;"&gt;&lt;strong&gt;Help needed:&lt;/strong&gt; I need to figure out how to performance-optimize this code. Either I need to get rid of that loop in the &lt;code&gt;get&lt;/code&gt; call, or I need to write a wrapper around &lt;a href="http://tangent.org/552/libmemcached.html"&gt;&lt;code&gt;libmemcached&lt;/code&gt;&lt;/a&gt;. I would prefer the latter, since I have to add more features for feature-completeness. Any idea on how I can get Jaxer to talk with &lt;code&gt;libmemcached&lt;/code&gt; (or any other such out-of-process thing)?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-3866634575837877689?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/3866634575837877689/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=3866634575837877689' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/3866634575837877689'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/3866634575837877689'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2009/01/jsmemcachedjs-jaxer-client-for.html' title='JsMemcached.js - A Jaxer client for memcached'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-6517290904637743323</id><published>2008-12-29T19:51:00.004+05:30</published><updated>2008-12-29T21:58:43.782+05:30</updated><title type='text'>Function declaration vs. function assignment in JavaScript</title><content type='html'>&lt;p&gt;I'm surprised how much I learn about JavaScript every single day.&lt;/p&gt;&lt;p&gt;It all started with a &lt;a href="http://nedbatchelder.com/blog/200812/internet_explorer_mystery_1376.html"&gt;post that's wrongly titled to indicate a bug in Internet Explorer&lt;/a&gt;. The comments are an interesting read, where people go ahead to suggest that this "bug" exists in all browsers except Firefox. Then, they discover that it's actually a bug in Firefox, and not the other way round. Then &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=468096"&gt;a bug report is filed with Firefox&lt;/a&gt;. Brendan Eich comes along and resolves it as an invalid bug, with a brief explanation.&lt;/p&gt;&lt;p&gt;To explain, here's what's happening:&lt;/p&gt;&lt;p&gt;Ned Batchelder (the poster of that blog post) came across this piece of code that worked differently in IE and Firefox.&lt;/p&gt;&lt;code&gt;&lt;pre&gt;function really() { alert("Original"); }&lt;br /&gt;if (0) {&lt;br /&gt;    alert("No");&lt;br /&gt;    function really() { alert("Yes, really"); }&lt;br /&gt;}&lt;br /&gt;really();&lt;/pre&gt;&lt;/code&gt;&lt;p&gt;The explanation is pretty simple. A function &lt;code&gt;really&lt;/code&gt; is defined which alerts "Original". Inside an &lt;code&gt;if&lt;/code&gt; block which should never get called, the &lt;code&gt;really&lt;/code&gt; function is redefined to alert "Yes, really". Since the code block is inside an &lt;code&gt;if&lt;/code&gt; that should never get called, the assumption would be that the function shouldn't get redefined. This is how Firefox behaves. However, not so with IE, which redefines the function. Weirdly, the alert("No"); is never executed, even though the function gets redefined.&lt;/p&gt;&lt;p&gt;Turns out, IE is not the only one doing this. All webkit browsers and Opera also exhibit this behavior. &lt;a href="http://askawizard.blogspot.com/"&gt;Kris Kowal&lt;/a&gt; was the first to suggest that this is a bug in Firefox for the right reasons. So, a bug report was created and BE closed it. Here's his explanation:&lt;/p&gt;&lt;blockquote&gt;ECMA-262 Edition does not specify functions in sub-statements, only at top level in another function or a program (see the normative grammar). Therefore this bug is invalid as summarized.&lt;br /&gt;&lt;br /&gt;Moreover, we have extended ES3 (as allowed by its chapter 16) for ~ten years to support "function statements" whose bindings depend on control flow. So this again is invalid. There's a bug to dup against, if someone finds it feel free to change resolution accordingly.&lt;br /&gt;&lt;br /&gt;/be&lt;/blockquote&gt;&lt;p&gt;For those who didn't understand, here's a simpler version of what BE said.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;function really() { ... }&lt;/code&gt; is a &lt;em&gt;function declaration&lt;/em&gt;.&lt;/li&gt;&lt;li&gt;Function declarations can only exist at the top level, or inside other functions. They cannot be inside the &lt;code&gt;if&lt;/code&gt; statement.&lt;/li&gt;&lt;li&gt;If the browser finds that it is inside the &lt;code&gt;if&lt;/code&gt; block, the browser is not allowed to throw an error. Instead, it should handle it gracefully.&lt;/li&gt;&lt;li&gt;There's no spec that defines how such situations should be handled, so browsers are free to do what they want to.&lt;/li&gt;&lt;li&gt;All browsers except Firefox first scan the code at load time to find function declarations. When doing so, they look at the function first, and then it's redefinition. In this case, the original function should be discarded, and the new function should be used.&lt;/li&gt;&lt;li&gt;Firefox does this at runtime, evaluating the functions when the code execution sees it. Hence Firefox doesn't redefine the function at all.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So, BE's explanation that this is not a bug is valid. This is a gray area in the spec, and the browser is free to implement it the way it wants.&lt;/p&gt;&lt;p&gt;Also, and more interestingly, BE brings up &lt;em&gt;function statements&lt;/em&gt; which do not follow this rule. A function statement would look like this:&lt;/p&gt;&lt;code&gt;var really = function() { ... };&lt;/code&gt;&lt;p&gt;Now, the spec very clearly says that function &lt;em&gt;statements&lt;/em&gt; should be evaluated at runtime based on control flow - stuff like that &lt;code&gt;if&lt;/code&gt; statement. Ned wouldn't have run into this problem if he was using function statements.&lt;/p&gt;&lt;p&gt;I learn new things about JavaScript every day!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-6517290904637743323?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/6517290904637743323/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=6517290904637743323' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/6517290904637743323'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/6517290904637743323'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2008/12/function-declaration-vs-function.html' title='Function declaration vs. function assignment in JavaScript'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-7133876630860479610</id><published>2008-11-21T22:22:00.004+05:30</published><updated>2008-11-22T03:40:16.732+05:30</updated><title type='text'>HTTP cache optimization</title><content type='html'>&lt;p&gt;You know what else Twitter is good for? Quotations. As good friend and colleague, &lt;a href="http://pranjan.blogspot.com/"&gt;Piyush Ranjan&lt;/a&gt; &lt;a href="http://twitter.com/piyush_ranjan/status/1015227467"&gt;said&lt;/a&gt;:&lt;/p&gt;&lt;blockquote&gt;Recession is [a] good time for innovation. Best innovation happens in crunch situations. Otherwise people just throw money at the problem!&lt;/blockquote&gt;&lt;p&gt;At &lt;a href="http://www.cleartrip.com/"&gt;Cleartrip&lt;/a&gt;, as with any other company, we're always looking for ways to reduce our costs. Now with the travel industry in India hit hard, and the general economic slowdown, it's very interesting for us techies to innovate in ways that will help us cut costs.&lt;/p&gt;&lt;p&gt;One the recent things we've been working on, and the stuff I want to talk about here, is the area of bandwidth savings. The benefits of bandwidth savings are usually twofold. Firstly and obviously, it reduces our bills. Secondly, it usually manifests itself as a better experience for the user, since he doesn't have to wait as long for stuff to transfer from our servers to his browser every time he moves between pages.&lt;/p&gt;&lt;p&gt;Now, our site is a fairly dynamic site. Almost every page in the site (well, the significant ones at least), are so dynamic, they cannot even be cached for a couple of minutes. So, caching HTML doesn't suit us. What we &lt;i&gt;can&lt;/i&gt; cache is everything else - images, CSS and JavaScripts. Also, since we try to adhere to web standards as much as possible while being as &lt;i&gt;Web 2.0&lt;/i&gt; as possible (whatever that means), our use of CSS and JavaScripts is pretty heavy.&lt;/p&gt;&lt;h2&gt;Phase 1&lt;/h2&gt;&lt;p&gt;So, a couple of months ago, we made our first set of optimizations. We noticed that our images change very rarely - some of them hadn't changed since we first made them. There was no point sending down copies of the images to our users frequently. These could be cached pretty aggressively. We decided on an arbitrary time of 1 month for the caching of images.&lt;/p&gt;&lt;p&gt;Next came the JavaScript and the CSS. This posed a considerable problem. We keep doing JS and CSS changes very frequently on our site - as frequently as a couple of times a day. We couldn't afford to have them aggressively cached at the client end. We needed the agility to update our users' cache with the new versions of our code. Again, arbitrarily, we decided that the cache time for JS and CSS files would be 2 hours. That way, it wouldn't be in users' cache very aggressively, while remaining in his cache for about the length of his usage session. At the same time, it would take at most 2 hours for our changes to propagate to all users.&lt;/p&gt;&lt;p&gt;So, with this configuration change rolled out (it's not at all hard to do if you &lt;a href="http://tomayko.com/writings/things-caches-do"&gt;understand caches&lt;/a&gt; well) we sat back and monitored our savings. Turns out, the savings were pretty amazing. Hrush, our founder, even &lt;a href="http://blog.cleartrip.com/journal/2008/11/19/cache-basics.html"&gt;blogged&lt;/a&gt; about how our data center providers were surprised to the extent that they said that it was "just not possible" that we have such low bandwidth consumption for the traffic we get!&lt;/p&gt;&lt;h2&gt;The problems&lt;/h2&gt;&lt;p&gt;How ironic our data center guys said that, because just around that time, we were looking at how we can optimize bandwidth usage even more. And why did we decide to optimize further?&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Because you can&lt;/li&gt;&lt;li&gt;Some of our files never changed at all - core JS libraries, for example. Why bother downloading them again after 2 hours?&lt;/li&gt;&lt;li&gt;Because this setup was hard to work with. Remember I said we patch stuff to production very frequently? That it takes two hours to propagate meant that if it was a bug fix, it might be broken for two hours even after we've put up the patch.&lt;/li&gt;&lt;li&gt;Because it gets very hard to make changes that have dependencies with other resources. For example, if the JS needs certain CSS changes, and certain markup changes, in what order do you put the changes up on the server?&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;This usually meant that we had to plan in advance and we would still have some backwards-compatibility cruft in our JS to manage this 2 hour transition. Sometimes it would take an entire day to make even a minor patch since it had to be batched with breaks of two hours. One quick-fix would be to rename the file and all references to it, but it's easy to see how painful that is to do on a file-by-file basis, not to mention that we'd run out of file names pretty soon!&lt;/p&gt;&lt;h2&gt;Phase 2&lt;/h2&gt;&lt;p&gt;One thing for sure, though. If we could somehow manage the file name issue, we can solve all the problems I listed out. That's because every time we made a patch with a different file name, it would instantly be available to all users, irrespective of their cache status. This gives rise to another interesting possibility: we didn't have to restrict ourselves to the 2 hour window anymore. We could potentially increase our cache expires time to 20 years for all that matters. That should give us MUCH more saving than we get currently, and our users will download as little as necessary.&lt;/p&gt;&lt;p&gt;Except, we didn't know yet how to solve the file name problem gracefully. Ideally, there shouldn't be a human being deciding which files have changed, what the file names are, and going all over the place and changing them. That would make it tedious and error prone, not to mention boring. Then of course you have to think about how these file name modifications would work with source control. You don't want to mess up your clean source code management history.&lt;/p&gt;&lt;p&gt;The solution to the source control mess thing was rather easy. We fake the file name. Here's what we do. We take a file name and append a random number to it. This will make the client believe that the file name has changed, and will negotiate with the server for the file. Meanwhile, at the server, we could have a rewrite rule that transforms the file name to something that maps to a real file on our server. Sounds simple enough. Tried it, and it worked like a charm.&lt;/p&gt;&lt;p&gt;Now, to crack the real problem - how do we generate these numbers in a sensible way. The number essentially had to be such that it would never repeat (at least for any given file), it would be global in that two pages shouldn't be using different numbers for the same resource, and when the number changes it should instantly reflect site wide. Now that we knew how the number should behave, the quest was on to come up with a mechanism to generate these numbers.&lt;/p&gt;&lt;h2&gt;The solution&lt;/h2&gt;&lt;p&gt;After a lot of thinking, we had a shameful duh moment, and it suddenly all made sense. We didn't need to invent these numbers at all. We just needed to use our source-control revision numbers! The revision numbers match all the characteristics of the number we want. Why bother with complex systems to generate and track numbers when it was already available, even if very disguised.&lt;/p&gt;&lt;p&gt;I'll save you the implementation details about how we made this available site wide, and how we made it possible to have instant global changes to this number. That definitely wasn't the tough part, and I'm sure you'll figure out the details. Who knows, maybe Piyush might just release a plugin for Rails to do it automatically for you. However what surprises me is that it's very hard to find such gems of knowledge on the net. I'm now beginning to think that maybe this design pattern should be used for distribution of all static resources on the web. We're definitely not the first to &lt;q&gt;invent&lt;/q&gt; this pattern - why is no one else talking about it?&lt;/p&gt;&lt;p&gt;We've only just rolled this out on &lt;a href="http://www.cleartrip.com/"&gt;cleartrip.com&lt;/a&gt; and are still to get a decent sample of data to see how it has impacted our bandwidth consumption. But any fool could guess that our bills should reduce significantly with this change.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-7133876630860479610?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/7133876630860479610/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=7133876630860479610' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/7133876630860479610'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/7133876630860479610'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2008/11/http-cache-optimization.html' title='HTTP cache optimization'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-4341999019405675305</id><published>2008-11-12T14:48:00.003+05:30</published><updated>2008-11-12T14:57:51.108+05:30</updated><title type='text'>Joel on Project Managers</title><content type='html'>&lt;p&gt;This quote is long, in typical &lt;a href="http://www.joelonsoftware.com/"&gt;Joel On Software&lt;/a&gt; style. He said this in his &lt;a href="http://blog.stackoverflow.com/2008/11/podcast-28/"&gt;latest podcast&lt;/a&gt; over at &lt;a href="http://www.stackoverflow.com/"&gt;Stack Overflow&lt;/a&gt; with &lt;a href="http://www.codinghorror.com/"&gt;Jeff Atwood&lt;/a&gt;. I've ripped it off the &lt;a href="https://stackoverflow.fogbugz.com/default.asp?W25972"&gt;transcript wiki&lt;/a&gt;. Definitely worth a read.&lt;/p&gt;&lt;blockquote&gt;Here's my feeling about project managers:&lt;br /&gt;&lt;p&gt;One of the things that is interesting is that project managers, traditionally, are brought on because you have a team of yahoos - and this is just as true in construction, or in building an oil rig, or in any kind of project as it is in the making of anything - making a new car at general motors, or designing the new Boeing 787 dream liner - as it is in the software industry.  Project managers are brought in because management says:  "Hey, you yahoos! You're just working and working and working and never get the thing done and nobody knows how long it's going to take."  If you don't know how long something's going to take and you can't control that a little bit then this really sucks from a business perspective.  I mean; if you think of a typical business project - you invest some money and then you make some money back.  The money you make back - the return on investment - might be double the amount of money you invest and then it's a good investment.  But if the investment doubles because it took you twice as long to do this thing as you thought it would then you've lost all your profit on the thing.  So this is bad for businesses to make decisions in the face of poor information about how long the project is going to take and so keeping a project on track and on schedule is really important.&lt;/p&gt;&lt;p&gt;It's so important that they started hiring people to do this and they said:  "OK, you're the project manager - make sure that we're on track."  These project managers were just bright college kids with spreadsheets and Microsoft project and clipboards. They pretty much had to go around with no authority what so ever and walk around the project and talk to the people and find out where things were up to and they spent all their time creating and maintaining these gigantic gantt charts - which everybody else ignored. So the gantt charts, and the Microsoft project, and all those project schedules, and all that kind of stuff, was an artifact created by a kind of low level person.  Although it might be accurate depending on how good that low level person was, but it was still an output only thing from the current project:  Where are we up to?  What have we done?  How much time have we spent?  What's left?  Who is working on what?&lt;/p&gt;&lt;p&gt;Then, for some reason, these relatively low level people, who were not actually domain experts, (if they were at Boeing they don't know anything about designing planes, if they were on the software team they're not programmers - they're project managers, and they don't know anything about writing code) they start getting blame when things went wrong and they started clamoring for more responsibility, more authority to actually make changes and to actually influence things and say:  "Hey, Joe's taking too long here - we should get Mary to do this task, she's not busy."  The truth is that they started getting frustrated because they were low level secretarial-like members of their teams and they wanted to move their profession up the scale so they created the project management institute - or whatever it's called - and they created this thing called...  ah, I don't even know!  But they created a whole professional way to learn to be a professional project manager and they decided to try to make it something a little bit fancier than just the kid with the clipboard that has to maintain these gantt charts all day long.  You can tell this is what happened because the first thing project managers will tell you about their profession is that the most important thing is that they have the authority to actually change things and that they are the ones that actually have all the skills that can get a project back on track, or to keep a project on track, and therefore they need to have the authority to exercise these skills otherwise they'll never get anything done, they'll never be able to keep the project on track, they don't just want to be stenographers writing things down.&lt;/p&gt;&lt;p&gt;The trouble is, they don't actually have the domain skills - that's why they are project managers.  If you are working on a software project you know how to bring it in on time and you've got to cut features, and you know which features to cut, becuase you understand software intrinsically and you know what things are slow and what things are fast and where you might be able to combine two features into one feature, where you might be able to take a shortcut.  That's the stuff a good developer knows, that's not the stuff a project manager knows.  In a construction project it's the architects and the head contractors who know where shortcuts can be taken and how to bring a project in on time not the project manager.  The project managers don't have any of the right skills to affect the project and so they inevitably get really frustrated and everybody treats them like secretaries, or treats them like 'annoying boy with clipboard', when they really don't have a leadership role in the project - and they're not going to be able to because they don't have the domain expertise.  No matter how much they learn about project management, no matter how many books they read, or how many certificates they get, no matter how long they've been doing project management: if they don't know about software, and software development, if they don't have that experience, they are always going to be second class citizens and they're never going to be able to fix a broken project.&lt;/p&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-4341999019405675305?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/4341999019405675305/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=4341999019405675305' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/4341999019405675305'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/4341999019405675305'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2008/11/joel-on-project-managers.html' title='Joel on Project Managers'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-199343369966684924</id><published>2008-10-08T21:46:00.010+05:30</published><updated>2008-10-10T02:13:31.541+05:30</updated><title type='text'>Understanding eval scope. Spoiler: It's unreliable!</title><content type='html'>&lt;p&gt;Today, I ran some tests to help me understand the scope in which an eval runs. Turns out, like so many things in the browser world, it's very unpredictable and exhibit different behaviors in different browsers.&lt;/p&gt;&lt;p&gt;Let's start with the following snippet of code. I've added comments to demarcate areas in the code, which I will be changing with each iteration.&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;var foo = 123;&lt;br /&gt;var bar = {&lt;br /&gt;    changeFoo: function() {&lt;br /&gt;        // We'll keep changing the following snippet&lt;br /&gt;        alert(this);&lt;br /&gt;        eval("var foo = 456");&lt;br /&gt;        // Changing snippet ends&lt;br /&gt;    }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;bar.changeFoo();&lt;br /&gt;alert(foo);&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;A little explanation of the code above. &lt;code&gt;foo&lt;/code&gt; is a variable in the global scope, and it's value is set to 123. An object &lt;code&gt;bar&lt;/code&gt; is created with a single method &lt;code&gt;changeFoo&lt;/code&gt; which does an &lt;code&gt;eval&lt;/code&gt;. The &lt;code&gt;eval&lt;/code&gt; creates a local variable (thanks to the &lt;code&gt;var&lt;/code&gt;) &lt;code&gt;foo&lt;/code&gt;, and sets it's value to 456. &lt;code&gt;bar.changeFoo&lt;/code&gt; is called, and the value of the global &lt;code&gt;foo&lt;/code&gt; is &lt;code&gt;alert&lt;/code&gt;ed.&lt;/p&gt;&lt;p&gt;The aim is to test the scope in which &lt;code&gt;eval&lt;/code&gt; runs. If &lt;code&gt;eval&lt;/code&gt; is in the global scope, the global variable &lt;code&gt;foo&lt;/code&gt; should change it's value. If &lt;code&gt;eval&lt;/code&gt; is in the local scope, the global &lt;code&gt;foo&lt;/code&gt; should be unaffected. Then there are various things we can do inside the &lt;code&gt;changeFoo&lt;/code&gt; method which should keep altering the scope of &lt;code&gt;this&lt;/code&gt;, so we are also alerting &lt;code&gt;this&lt;/code&gt; to see what happens.&lt;/p&gt;&lt;p&gt;The findings are listed below:&lt;/p&gt;&lt;table width="100%" style="text-align: center;"&gt;&lt;thead style="background: #bbb;"&gt;&lt;tr&gt;&lt;th style="text-align: center;"&gt;&amp;nbsp;&lt;/th&gt;&lt;th style="text-align: center;"&gt;Changed snippet&lt;/th&gt;&lt;th colspan="2"&gt;Internet Explorer&lt;/th&gt;&lt;th colspan="2"&gt;Safari 3.x&lt;/th&gt;&lt;th colspan="2"&gt;Firefox&lt;/th&gt;&lt;th colspan="2"&gt;Google Chrome&lt;/th&gt;&lt;th colspan="2"&gt;Safari Nightlies&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th style="text-align: center;"&gt;&amp;nbsp;&lt;/th&gt;&lt;th style="text-align: center;"&gt;&amp;nbsp;&lt;/th&gt;&lt;th style="text-align: center;"&gt;foo&lt;/th&gt;&lt;th style="text-align: center;"&gt;this&lt;/th&gt;&lt;th style="text-align: center;"&gt;foo&lt;/th&gt;&lt;th style="text-align: center;"&gt;this&lt;/th&gt;&lt;th style="text-align: center;"&gt;foo&lt;/th&gt;&lt;th style="text-align: center;"&gt;this&lt;/th&gt;&lt;th style="text-align: center;"&gt;foo&lt;/th&gt;&lt;th style="text-align: center;"&gt;this&lt;/th&gt;&lt;th style="text-align: center;"&gt;foo&lt;/th&gt;&lt;th style="text-align: center;"&gt;this&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td valign="top"&gt;1&lt;/td&gt;&lt;td&gt;&lt;code&gt;&lt;pre style="text-align: left"&gt;alert(this);&lt;br /&gt;eval("var foo=456");&lt;/pre&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;/tr&gt;&lt;tr style="background: #eee;"&gt;&lt;td valign="top"&gt;2&lt;/td&gt;&lt;td&gt;&lt;code&gt;&lt;pre style="text-align: left"&gt;alert(this);&lt;br /&gt;window.eval("var foo=456");&lt;/pre&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;456&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;456&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top"&gt;3&lt;/td&gt;&lt;td&gt;&lt;code&gt;&lt;pre style="text-align: left"&gt;alert(this);&lt;br /&gt;this.eval("var foo=456");&lt;/pre&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;error&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;error&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;error&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;error&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;error&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;/tr&gt;&lt;tr style="background: #eee;"&gt;&lt;td valign="top"&gt;4&lt;/td&gt;&lt;td&gt;&lt;code&gt;&lt;pre style="text-align: left"&gt;alert(this);&lt;br /&gt;eval("var foo=456", window);&lt;/pre&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;456&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top"&gt;5&lt;/td&gt;&lt;td&gt;&lt;code&gt;&lt;pre style="text-align: left"&gt;(function() {&lt;br /&gt;    alert(this);&lt;br /&gt;    eval("var foo=456");&lt;br /&gt;})();&lt;/pre&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;window&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;window&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;window&lt;/td&gt;&lt;/tr&gt;&lt;tr style="background: #eee;"&gt;&lt;td valign="top"&gt;6&lt;/td&gt;&lt;td&gt;&lt;code&gt;&lt;pre style="text-align: left"&gt;(function() {&lt;br /&gt;    alert(this);&lt;br /&gt;    window.eval("var foo=456");&lt;br /&gt;})();&lt;/pre&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;window&lt;/td&gt;&lt;td&gt;456&lt;/td&gt;&lt;td&gt;window&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;456&lt;/td&gt;&lt;td&gt;window&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top"&gt;7&lt;/td&gt;&lt;td&gt;&lt;code&gt;&lt;pre style="text-align: left"&gt;with(window) {&lt;br /&gt;    alert(this);&lt;br /&gt;    eval("var foo=456");&lt;br /&gt;}&lt;/pre&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;456&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;456&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;456&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;456&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;456&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;/tr&gt;&lt;tr style="background: #eee;"&gt;&lt;td valign="top"&gt;8&lt;/td&gt;&lt;td&gt;&lt;code&gt;&lt;pre style="text-align: left"&gt;with(window) {&lt;br /&gt;    alert(this);&lt;br /&gt;    window.eval("var foo=456");&lt;br /&gt;}&lt;/pre&gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;456&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;456&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;456&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;456&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;456&lt;/td&gt;&lt;td&gt;object&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;What I think of these results&lt;/strong&gt;: &lt;ul&gt;&lt;li&gt;I don't know what Firefox is doing in case 2, and for some reason Safari Nightlies seem to be following it. Maybe it's just beyond my understanding, but case 2 is not supposed to be different from case 1. Why does case 2 operate in global scope? If &lt;code&gt;window.eval&lt;/code&gt; is different from &lt;code&gt;eval&lt;/code&gt;, case 3 shouldn't all have given errors. Someone please help me understand that $hit.&lt;/li&gt;&lt;li&gt;Case 4 makes sense, but that's a non-standard behavior in Firefox. Understandable that no one else exhibits it.&lt;/li&gt;&lt;li&gt;IE baffles me in case 5, and Chrome seems to ape it. In this scenario, the anonymous function is supposed to have the global scope - so, in this case, &lt;code&gt;this&lt;/code&gt; should point to the window. WTF is happening here!&lt;/li&gt;&lt;li&gt;Consistent with case 2 above, Firefox and Safari Nightlies continue to display weird behavior in case 6. For some reason, in these two cases, the &lt;code&gt;eval&lt;/code&gt; operates in the global scope.&lt;/li&gt;&lt;li&gt;Now, I have no idea why, but only cases 8 and 9 seem to really work at all. This is despite Doug Crockford going on and on about not using &lt;code&gt;with&lt;/code&gt; constructs. It's also despite being beyond (my) understanding about why the &lt;code&gt;with&lt;/code&gt; should make any difference to the &lt;code&gt;eval&lt;/code&gt;, since &lt;code&gt;eval&lt;/code&gt; is part of the window object.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;All in all, if you are going to be &lt;code&gt;eval&lt;/code&gt;ing JavaScript (not JSON), and you want the eval'd code to run in the global scope, you should use the &lt;code&gt;with&lt;/code&gt; block around the JavaScript snippet. Or else, you can lose a lot of hair handling cross-browser issues.&lt;/p&gt;&lt;p&gt;Hope you don't lose as much hair as me.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-199343369966684924?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/199343369966684924/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=199343369966684924' title='19 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/199343369966684924'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/199343369966684924'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2008/10/understanding-eval-scope-spoiler-its.html' title='Understanding eval scope. Spoiler: It&apos;s unreliable!'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>19</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-5090030003741492640</id><published>2008-09-17T23:28:00.002+05:30</published><updated>2008-09-17T23:42:44.961+05:30</updated><title type='text'>Housekeeping</title><content type='html'>&lt;p&gt;I've done a couple of minor changes to this blog's UI. Nothing dramatic, but I thought I should draw your attention to it, especially if you are one reading only from my &lt;a href="http://piecesofrakesh.blogspot.com/feeds/posts/default" title="My Atom Feed"&gt;Atom&lt;/a&gt;/&lt;a href="http://piecesofrakesh.blogspot.com/feeds/posts/default?alt=rss" title="My RSS Feed"&gt;RSS&lt;/a&gt; feed.&lt;/p&gt;&lt;p&gt;The first change came from realizing that my posts are longer than they should be. Somehow, I can't seem to compress them beyond what I already do. Long pages are a pain the wrong spots to read, so I decided to expand Douglas Bowman's original layout to a fluid width page, so that my posts consume lesser vertical space. (I just noticed that &lt;a href="http://steve-yegge.blogspot.com/" title="Stevey's blog"&gt;Steve Yegge&lt;/a&gt; has done similar fixes - I'm flattered.)&lt;/p&gt;&lt;p&gt;Secondly, and sort of to compensate for my lowered rate of posting on this blog, I've included two new feeds you can subscribe to on this blog. You can find latest updates to these feeds in the right sidebar. First is &lt;a href="http://del.icio.us/rss/rakeshpai/"&gt;my feed from del.icio.us&lt;/a&gt;, which happens to be my bookmarking service of preference. Secondly, is &lt;a href="http://www.google.com/reader/public/atom/user/14713094510129037345/state/com.google/broadcast"&gt;my list of shared RSS feeds from my Google Reader&lt;/a&gt;. Both of these feeds get updated more frequently than my blog itself, so you might find these interesting.&lt;/p&gt;&lt;p&gt;This way, not only do you keep in touch with what I'm writing, you can also keep in touch with the stuff I'm reading. Expect to find some tech humor in these feeds too ;). Here's the rule of the thumb: The two new feeds reflect what I'm thinking strongly about, but I do not necessarily have an opinion about. My blog is my list of opinions. That's the difference.&lt;/p&gt;&lt;p&gt;I've been testing these thingies on my blog for some time now, so if you've been around here recently, you might have already noticed these changes. I just thought I'd wait a bit before I can announce these new things - turns out Google is doing a reasonable job of ensuring these things work, after all. ;)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-5090030003741492640?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/5090030003741492640/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=5090030003741492640' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/5090030003741492640'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/5090030003741492640'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2008/09/housekeeping.html' title='Housekeeping'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-7582116265285219818</id><published>2008-09-03T14:25:00.004+05:30</published><updated>2008-09-03T16:55:20.432+05:30</updated><title type='text'>JavaScript for Linux Hackers</title><content type='html'>&lt;p&gt;Two weekends ago (24 August), I gave a talk about JavaScript at the &lt;a href="http://www.ilug-bom.org.in/"&gt;Indian GNU/Linux Users Group of Mumbai (ILUG-BOM)&lt;/a&gt; - A small gathering of Linux hackers from around the city. The talk was held at the &lt;a href="http://www.hbcse.tifr.res.in/"&gt;Homi Bhabha Centre for Science Education (HBSCE)&lt;/a&gt;, &lt;abbr title="Tata Institute of Fundamental Research"&gt;TIFR&lt;/abbr&gt;, Mumbai.&lt;/p&gt;&lt;p&gt;It was very weird having to explain JavaScript to kernel hackers and sysadmins. It entails a different approach - one where you have to assume that the audience knows a lot already, probably more than you in some respects. They are not one to get wowed by browser effects and visual fanciness. Also I know very little about Linux systems, so we had very little in common. It's very challenging preparing for such an audience.&lt;/p&gt;&lt;p&gt;I spoke about the language, it's history, it's expressiveness, the type system, variable casting, objects, marshaling objects, it's lambda nature, and several language constructs, especially functions. What I didn't cover was things like the DOM, inheritance patterns and constructor functions, but there has to be something for next time, right? ;)&lt;/p&gt;&lt;p&gt;I think it went pretty well. Well enough for them to invite me for another session where we could cover the left-out topics. I'm sorry - I would have put my slides on slideshare or something, but honestly, when I was running through my slideshow the day before the presentation, I nearly dozed off. So I decided that I'd just do the presentation without the slides - just me talking, and a JavaScript console on the screen.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-7582116265285219818?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/7582116265285219818/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=7582116265285219818' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/7582116265285219818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/7582116265285219818'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2008/09/javascript-for-linux-hackers.html' title='JavaScript for Linux Hackers'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-4883532777406747456</id><published>2008-08-29T20:48:00.005+05:30</published><updated>2008-08-29T21:44:41.047+05:30</updated><title type='text'>element.hasFocus? document.activeElement!</title><content type='html'>&lt;p&gt;Today at work, in some code I was writing, I wanted to know if a given &lt;code&gt;input&lt;/code&gt; box has focus or not. Turned out, this is surprisingly difficult. The input element doesn't have any &lt;code&gt;hasFocus&lt;/code&gt; or similar property! No wonder working with the DOM keeps tripping people up!&lt;/p&gt;&lt;p&gt;Turns out, from quite some time now, Internet Exploder has been supporting a proprietary property - &lt;code&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms533065(VS.85).aspx"&gt;document.activeElement&lt;/a&gt;&lt;/code&gt; - which tells you which element is current focussed. Exactly what I needed. Except this is proprietary - I tried in Firefox 2, and it didn't work as expected. However, fortunately, turns out &lt;a href="http://www.whatwg.org/specs/web-apps/current-work/#focus-management"&gt;the HTML 5 spec has now incorporated this new property&lt;/a&gt; of the &lt;code&gt;document&lt;/code&gt; object, and all future browsers should support it. &lt;a href="http://developer.mozilla.org/En/DOM:element.activeElement"&gt;Firefox 3 already supports &lt;code&gt;document.activeElement&lt;/code&gt;&lt;/a&gt;. I've read that Opera supports it, but haven't tried. Safari does not, but the latest nightlies support it as well. Of course IE6 and IE7 support it perfectly well - IE invented it after all. So, of the big browsers, only Firefox 2 and Safari are problematic.&lt;/p&gt;&lt;p&gt;Since my code was not super critical, I've decided to skip support for just this bit for Firefox 2 and Safari. In any case, I'm hoping (against hope?) that both these browsers have a faster upgrade cycle than others, so they'll be outdated pretty soon.&lt;/p&gt;&lt;p&gt;Just in case you were thinking that the focused element can easily be 'discovered' by using the onblur and onfocus events, think again. Firstly, according to the specs, &lt;a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html"&gt;the focus and blur events don't bubble&lt;/a&gt;, so you can't use &lt;a href="http://www.google.co.in/search?q=javascript+event+delegation&amp;ie=utf-8&amp;oe=utf-8&amp;aq=t&amp;rls=org.mozilla:en-US:official&amp;client=firefox-a"&gt;event delegation&lt;/a&gt; to capture all focus/blur events on the document. In any case, if you could use event delegation, putting these event handlers in an external script would mean that the script will kick in after a little delay - either after the script has loaded if the script tag is placed at the bottom, or after the page load happens if you are waiting for the DOM to be ready before you can use it, which in my case wasn't acceptable. The only other solution is to have a script include or a inline script tag that declares a function before the DOM is loaded, and then have inline onblur and onfocus event handlers &lt;a href="http://en.wikipedia.org/wiki/DOM_Events#DOM_Level_0"&gt;DOM Level 0 style&lt;/a&gt;. That's just plain ugly. None of these solutions are either workable or graceful.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-4883532777406747456?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/4883532777406747456/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=4883532777406747456' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/4883532777406747456'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/4883532777406747456'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2008/08/elementhasfocus-documentactiveelement.html' title='element.hasFocus? document.activeElement!'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-5776836521573239900</id><published>2008-08-13T21:28:00.003+05:30</published><updated>2008-08-13T21:43:42.169+05:30</updated><title type='text'>Brendan Eich on code translation to JavaScript</title><content type='html'>&lt;p&gt;I've always hated the idea of some server-side language (like ASP.Net, GWT, RoR, what-have-you) generating JS code to run on the client. I'm glad at least Eich agrees with me, as is published in &lt;a href="http://www.computerworld.com.au/index.php/id;243672124;fp;;fpid;"&gt;this interview&lt;/a&gt;. (Jump to &lt;a href="http://www.computerworld.com.au/index.php/id;243672124;pp;3;fp;;fpid;"&gt;page 3&lt;/a&gt; for this excerpt.)&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;I did not intend JS to be a "target" language for compilers such as Google Web Toolkit (GWT) or (before GWT) HaXe and similar such code generators, which take a different source language and produce JS as the "object" or "target" executable language.&lt;/p&gt;&lt;p&gt;The code generator approach uses JS as a "safe" mid-level intermediate language between a high-level source language written on the server side, and the optimized C or C++ code in the browser that implements JS. This stresses different performance paths in the JS engine code, and potentially causes people to push for features in the Ecma standard that are not appropriate for most human coders.&lt;/p&gt;&lt;p&gt;JS code generation by compilers and runtimes that use a different source language does seem to be "working", in the sense that JS performance is good enough and getting better, and everyone wants to maximize "reach" by targeting JS in the browser. But most JS is hand-coded, and I expect it will remain so for a long time. &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;That said, I think Eich doesn't highlight some of the other problems with server-generated JavaScript: ability to debug, potentially unoptimized output, and potentially inefficient code. I've worked with server-generated JavaScript in ASP.Net and RoR, and I know what a pain it can be.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-5776836521573239900?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/5776836521573239900/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=5776836521573239900' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/5776836521573239900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/5776836521573239900'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2008/08/brendan-eich-on-code-translation-to.html' title='Brendan Eich on code translation to JavaScript'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-7465724156843362073</id><published>2008-06-20T14:59:00.004+05:30</published><updated>2008-06-20T15:25:39.686+05:30</updated><title type='text'>IE Congratulates Firefox</title><content type='html'>... on shipping Firefox 3.0.&lt;br /&gt;&lt;div style="text-align: center"&gt;&lt;a href="http://www.flickr.com/photos/robceemoz/2587912633/"&gt;&lt;img src="http://farm4.static.flickr.com/3122/2587912633_9084fecde4.jpg?v=0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The comments from around the web are hilarious:&lt;ul&gt;&lt;li&gt;Don't eat it.&lt;/li&gt;&lt;li&gt;Is it not poisoned?&lt;/li&gt;&lt;li&gt;That cake will give you CSS rendering errors, in your colon.&lt;/li&gt;&lt;li&gt;Moments later the cake hit a knife/plate standard it wasn't compliant with.&lt;/li&gt;&lt;li&gt;It must have been hard for them to put "love" on the cake &lt;/li&gt;&lt;li&gt;As you eat away the icing, you'll see that the cake is blue... little by little, it's becoming clear... it's the blue screen of death!&lt;/li&gt;&lt;li&gt;Congratulations on shitting the IE7 Team &lt;/li&gt;&lt;li&gt;...did it come with an End User License Agreement...?&lt;/li&gt;&lt;li&gt;There should be some bugs inside the cake.&lt;/li&gt;&lt;li&gt;...it's probably half baked too!&lt;/li&gt;&lt;li&gt;I guess that box was rendered in quirks mode.&lt;/li&gt;&lt;li&gt;Sheesh, even their cake has box model bugs.&lt;/li&gt;&lt;li&gt;I was wondering what the IE team had been doing for the past 3 years...&lt;/li&gt;&lt;li&gt;There's actually an IE team?&lt;/li&gt;&lt;li&gt;[Apple] snuck their cake through during the last Quicktime update.&lt;/li&gt;&lt;li&gt;And if you didn't like the candles, you had to replace the whole cake.&lt;/li&gt;&lt;li&gt;...that the cake tasted pretty good, but as they started to dig in, they sadly realized that instead of a whole cake, they had actually gotten a thin layer of cake on top of a cake-shaped support structure made of toothpicks and glue.&lt;/li&gt;&lt;li&gt;Turns out they forgot to add sugar to the cake. That will be added on Patch Tuesday.&lt;/li&gt;&lt;li&gt;Good luck getting the recipe for that cake.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-7465724156843362073?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/7465724156843362073/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=7465724156843362073' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/7465724156843362073'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/7465724156843362073'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2008/06/ie-congratulates-firefox.html' title='IE Congratulates Firefox'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-7020704411901059286</id><published>2008-06-10T19:24:00.003+05:30</published><updated>2008-06-10T19:49:56.950+05:30</updated><title type='text'>Simply use HTML. Not XHTML.</title><content type='html'>&lt;p&gt;The good 'ol argument about HTML vs. XHTML seems to have resurfaced on the &lt;a href="http://en.wikipedia.org/wiki/Internets"&gt;Internets&lt;/a&gt;. I have been firmly &lt;a href="http://piecesofrakesh.blogspot.com/2004/09/economics-of-xhtml.html"&gt;in the XHTML camp&lt;/a&gt; at one time, but I had made a mention &lt;a href="http://piecesofrakesh.blogspot.com/2007/09/much-deserved-update.html"&gt;in a previous post&lt;/a&gt; about why I think that there was no point in fighting this battle anymore. There is a clear winner - HTML.&lt;p&gt;&lt;p&gt;Of the lot of recent posts out there about which is better than the other, this little &lt;a href="http://diveintomark.org/archives/2004/01/14/thought_experiment"&gt;thought experiment&lt;/a&gt; echoes my sentiments about XHTML vs. HTML.&lt;/p&gt;&lt;blockquote&gt;You pore through the raw source code of the page and find what you think is the problem, but it’s not in your content. In fact, it’s in an auto-generated part of the page that you have no control over. What happened was, someone linked to you, and when they linked to you they sent a trackback with some illegal characters (illegal for you, not for them, since they declare a different character set than you do). But your publishing tool had a bug, and it automatically inserted their illegal characters into your carefully and validly authored page, and now all hell has broken loose.&lt;br /&gt;&lt;br /&gt;The emails are really pouring in now. You desperately jump to your administration page to delete the offending trackback, but oh no! The administration page itself tries to display the trackbacks you’ve received, and you get an XML processing error. The same bug that was preventing your readers from reading your published page is now preventing you from fixing it!&lt;/blockquote&gt;&lt;p&gt;The fact is today's web is one where content might pour in from various locations, many of which you might not have control over. It is important to inter-operate with these kinds of content sources. Expecting strictness from an external source is not only overkill, it's folly to do so.&lt;/p&gt;&lt;p&gt;I had faced this problem when I had worked on the &lt;a href="http://www.nba.com/kings/"&gt;Sacramento Kings website&lt;/a&gt;. The content was coming from various sources, some even as trustworthy (for them at least) as the NBA. However, content encoding and ill formed markup issues were huge enough to get &lt;a href="http://piecesofrakesh.blogspot.com/2007/02/ies-unknown-runtime-error-when-using.html"&gt;the JavaScript all crazy&lt;/a&gt;. I can't even imagine the amount of problems I'd have faced if we'd have decided to use a XHTML strict, or even transitional, doctype for this job. How can we force a content author to ensure that his content validates, and that the reference validation for your site and the reference validation for the content author is the same?&lt;/p&gt;&lt;p&gt;Simply use HTML. Let the onus of making sense of the content lie with the browser. It's not a human's job to make content appealing to a computer. If a computer cannot understand it, it should work hard. Not the human.&lt;/p&gt;&lt;p&gt;Just for the humor, check out this page that a friend happened to hit when pulling up &lt;a href="http://www.w3.org/"&gt;W3.org&lt;/a&gt; the other day. I know I'm being harsh when I say this, but the guys who made the standard can't seem to respect it.&lt;/p&gt;&lt;div style="text-align: center"&gt;&lt;a href="http://www.flickr.com/photos/rakesh/2567088677/" title="W3 Parsing Error by Rakesh Pai, on Flickr"&gt;&lt;img src="http://farm3.static.flickr.com/2302/2567088677_57540dea3d.jpg" width="500" height="133" alt="W3 Parsing Error" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-7020704411901059286?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/7020704411901059286/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=7020704411901059286' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/7020704411901059286'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/7020704411901059286'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2008/06/simply-use-html-not-xhtml.html' title='Simply use HTML. Not XHTML.'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm3.static.flickr.com/2302/2567088677_57540dea3d_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-1222785052059133998</id><published>2008-06-03T15:48:00.004+05:30</published><updated>2008-06-03T15:56:41.855+05:30</updated><title type='text'>Goa</title><content type='html'>Just got back from a trip to Goa with colleagues. Here are some of the pics:&lt;br /&gt;&lt;p style="text-align: center"&gt;&lt;a href="http://www.flickr.com/photos/rakesh/2544698170/" title="Dog and Chair by Rakesh Pai, on Flickr"&gt;&lt;img src="http://farm3.static.flickr.com/2153/2544698170_073a441528_m.jpg" width="240" height="180" alt="Dog and Chair" /&gt;&lt;/a&gt;&lt;a href="http://www.flickr.com/photos/rakesh/2544697988/" title="Altar by Rakesh Pai, on Flickr"&gt;&lt;img src="http://farm4.static.flickr.com/3009/2544697988_53502a08c2_m.jpg" width="240" height="180" alt="Altar" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/rakesh/2543868947/" title="Resort by Rakesh Pai, on Flickr"&gt;&lt;img src="http://farm3.static.flickr.com/2169/2543868947_1d609428bf_m.jpg" width="240" height="180" alt="Resort" /&gt;&lt;/a&gt;&lt;a href="http://www.flickr.com/photos/rakesh/2543868849/" title="Anurag by Rakesh Pai, on Flickr"&gt;&lt;img src="http://farm3.static.flickr.com/2162/2543868849_7a9895ca2b_m.jpg" width="240" height="180" alt="Anurag" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://flickr.com/search/show/?q=goa&amp;w=29609190%40N00"&gt;Head over to Flickr&lt;/a&gt; for all the pics.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-1222785052059133998?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/1222785052059133998/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=1222785052059133998' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/1222785052059133998'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/1222785052059133998'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2008/06/goa.html' title='Goa'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm3.static.flickr.com/2153/2544698170_073a441528_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-5456549130998915087</id><published>2008-04-21T15:50:00.002+05:30</published><updated>2008-04-21T16:15:17.190+05:30</updated><title type='text'>Getting iSync to work with the Nokia N91 8GB</title><content type='html'>&lt;p&gt;My phone is a &lt;a href="http://www.nokia-asia.com/A4417199"&gt;Nokia N91 8GB&lt;/a&gt;, and my primary OS these days is the Mac OSX 10.4.11. When I followed instructions I could find anywhere on the web - the simple connect, launch, sync instructions - it simply didn't work. iSync kept complaining that it couldn't sync with my device.&lt;/p&gt;&lt;p&gt;That just meant it's time to get under the hood and do some hacking! If you ever face this problem, here's how you solve this issue.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Quit iSync if you already have it open.&lt;/li&gt;&lt;li&gt;Go to your applications folder, right-click on the iSync application icon, and select "Show Package Contents".&lt;/li&gt;&lt;li&gt;Keep clicking through to the following path: Contents/PlugIns/ApplePhoneConduit.syncdevice/Contents/Plugins/Nokia-N91.phoneplugin/Contents/Resources.&lt;/li&gt;&lt;li&gt;Once there, duplicate the MetaClasses.plist file just to have a backup. You can do that by right-clicking the file, and selecting "Duplicate".&lt;/li&gt;&lt;li&gt;Now, open the file with a text editor - I used TextWrangler, and search for the line that says &lt;code&gt;&amp;lt;key&amp;gt;com.nokia.n91&amp;lt;/key&amp;gt;&lt;/code&gt;. A little lower, you should find a &amp;lt;key&amp;gt;Identification&amp;lt;/key&amp;gt;. Right below that should be a &amp;lt;dict&amp;gt; XML node.&lt;/li&gt;&lt;li&gt;Edit it to look as follows:&lt;br /&gt;&lt;pre style='color:#000000;background:#ffffff;'&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;dict&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;key&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;com.apple.usb.vendorid-modelid&lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;key&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;string&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;0x0421/0x042F&lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;string&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;key&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;com.apple.gmi+gmm&lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;key&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;array&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;string&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;Nokia+Nokia N91-1&lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;string&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style='color:#a65700; '&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;string&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;Nokia+Nokia N91-2&lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;string&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;array&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style='color:#a65700; '&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#5f5035; '&gt;dict&lt;/span&gt;&lt;span style='color:#a65700; '&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;That's it - you are set. Now, launch iSync and it should now be able to work with your N91 8GB as advertised.&lt;/p&gt;&lt;p&gt;The key here is that the N91 8GB model is identified as Nokia+Nokia N91-2, which isn't available in the supported devices list by default - the regular N91 is identified as Nokia+Nokia N91-1 or simply Nokia+Nokia N91, which is supported. The hack just adds support for the N91 8GB by telling iSync to treat it as the Nokia+Nokia N91-1 for all practical purposes.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-5456549130998915087?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/5456549130998915087/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=5456549130998915087' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/5456549130998915087'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/5456549130998915087'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2008/04/getting-isync-to-work-with-nokia-n91.html' title='Getting iSync to work with the Nokia N91 8GB'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-4867150438034599881</id><published>2008-02-28T14:08:00.002+05:30</published><updated>2008-02-28T14:37:30.783+05:30</updated><title type='text'>Web 2.0 Professionals</title><content type='html'>Got this job offer in my mail today:&lt;br /&gt;&lt;blockquote&gt;COMPANY: [Company Name] ...with a reputation of being a leading supplier of networking equipment and network management for the Internet.&lt;br /&gt;&lt;br /&gt;LOCATION: Bangalore&lt;br /&gt;&lt;br /&gt;JOB OVERVIEW: We are looking for &lt;strong&gt;Senior Web.20 professionals&lt;/strong&gt; on a very Urgent basis. Person with good relavant experience is most preferable.&lt;br /&gt;&lt;br /&gt;EXPERIENCE: Min. 4 yrs to 12 yrs&lt;br /&gt;&lt;br /&gt;POSITION: Permanent&lt;br /&gt;&lt;br /&gt;If you a are looking for a change then plz fwd your updated word formatted (*.doc) CV to me ASAP with following details:&lt;br /&gt;&lt;br /&gt;[snip]&lt;br /&gt;&lt;br /&gt;5. Experience in Web 2.0&lt;br /&gt;&lt;br /&gt;[snip]&lt;br /&gt;&lt;/blockquote&gt;&lt;p&gt;Typos and poor language apart, can someone please explain what a &lt;i&gt;&lt;q&gt;Web 2.0 Professional&lt;/q&gt;&lt;/i&gt; is? What does he do? How in the world is he supposed to have 4 to 12 years experience? And how can he give &lt;q&gt;details&lt;/q&gt; of his &lt;q&gt;Experience in Web 2.0&lt;/q&gt;? Not to mention, I am very curious about how Web 2.0 is relevant to &lt;q&gt;a leading supplier of networking equipment and network management for the Internet&lt;/q&gt;.&lt;/p&gt;&lt;p&gt;I guess this just shows that we are at the peak of the hype.&lt;/p&gt;&lt;p&gt;Some where in a board room:&lt;br /&gt;&lt;q&gt;How do we boost sales of our NICs and routers?&lt;/q&gt;&lt;br /&gt;&lt;q&gt;What we really need is some Web 2.0 action going for us.&lt;/q&gt;&lt;br /&gt;&lt;q&gt;What is that?&lt;/q&gt;&lt;br /&gt;&lt;q&gt;Don't you know? Everyone's talking about it. It's the greatest thing to have happend!&lt;/q&gt;&lt;br /&gt;&lt;q&gt;Ok. Get HR to find a Web 2.0 Professional. Make sure he has a decent amount of experience.&lt;/q&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-4867150438034599881?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/4867150438034599881/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=4867150438034599881' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/4867150438034599881'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/4867150438034599881'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2008/02/web-20-professionals.html' title='Web 2.0 Professionals'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-7643781036212661251</id><published>2008-01-29T13:01:00.000+05:30</published><updated>2008-01-29T13:14:22.244+05:30</updated><title type='text'>On X-UA-Compatible</title><content type='html'>&lt;p&gt;There's been so much said about this...&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Chris Wilson &lt;a href="http://blogs.msdn.com/ie/archive/2008/01/21/compatibility-and-ie8.aspx"&gt;spells out the need for it&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Aaron Gustafson &lt;a href="http://www.alistapart.com/articles/beyonddoctype"&gt;explains the details on A List Apart (!)&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Eric Meyer &lt;a href="http://www.alistapart.com/articles/fromswitchestotargets"&gt;welcomes it&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://snook.ca/archives/browsers/version_targeting_ie8/"&gt;So does Jonathan Snook&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Anne Van Kesteren thinks &lt;a href="http://annevankesteren.nl/2008/01/ie-lock-in"&gt;it's an IE lock-in all over again&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Mozilla devs &lt;a href="http://weblogs.mozillazine.org/roc/archives/2008/01/post_2.html"&gt;have questions&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;PPK &lt;a href="http://www.quirksmode.org/blog/archives/2008/01/the_versioning.html"&gt;observes quitely&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;WaSP guys clarify that &lt;a href="http://www.webstandards.org/2008/01/22/microsofts-version-targeting-proposal/"&gt;they were not necessarily involved, though MS claims so&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Jeremy Keith thinks &lt;a href="http://adactio.com/journal/1402/"&gt;MS's got it backwards&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Andy Budd thinks &lt;a href="http://www.andybudd.com/archives/2008/01/has_internet_ex/"&gt;IE just shot itself in the foot&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Jeffery Zeldman &lt;a href="http://www.zeldman.com/2008/01/22/in-defense-of-version-targeting/"&gt;defends the idea anyway&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;John Resig thinks &lt;a href="http://ejohn.org/blog/meta-madness/"&gt;the trouble is worthless&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Dean Edwards &lt;a href="http://dean.edwards.name/weblog/2008/01/quotes/"&gt;sits on the fence and snickers&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Roger Johansson is &lt;a href="http://www.456bereastreet.com/archive/200801/standards_mode_is_the_new_quirks_mode/"&gt;not convinced that it's a good idea&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Rachel Andrew thinks &lt;a href="http://www.rachelandrew.co.uk/archives/2008/01/22/ie8-and-the-future-of-the-web/"&gt;this is a step backwards&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Safari says &lt;a href="http://webkit.org/blog/155/versioning-compatibility-and-standards/"&gt;they are not going to implement it&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Ian Hickson thinks &lt;a href="http://ln.hixie.ch/?start=1201080691&amp;count=1"&gt;MS is going to be in trouble&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Mike Davies says that &lt;a href="http://www.isolani.co.uk/blog/standards/EndOfLineInternetExplorer"&gt;it's the end of the line for IE&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;... that if I write an opinion piece, it will go unnoticed.&lt;/p&gt;&lt;p&gt;So, what do I think anyway? If this is MS's only chance at fixing the web, I love the idea. However, this is a drastic step, and MS cannot botch this up. If they do, no one will want to work for their browser anymore. If no sites are written for their browser, users won't use their browser anymore. As a front-end developer, having to cater to three different browser types (IE6, IE7 and good browsers) with HUGE differences between them, is already a pain in the wrong spots. Adding one more to the mix will only worsen the situation. But if IE8 starts actually behaving like the good browsers, we can finally hope that all our problems will vanish with IE6 and IE7 - whenever that happens.&lt;/p&gt;&lt;p&gt;So, if MS thinks that this is the solution to all their problems, so be it. The world will comply this one last time. This is a lot of trouble. It better be worth it. If this ends up having a less-than-desirable result, MS is doomed. IE is doomed. And the web will be a better place anyway, IE or otherwise.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-7643781036212661251?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/7643781036212661251/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=7643781036212661251' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/7643781036212661251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/7643781036212661251'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2008/01/on-x-ua-compatible.html' title='On X-UA-Compatible'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-9045552968411587659</id><published>2008-01-24T21:27:00.000+05:30</published><updated>2008-01-24T21:28:52.968+05:30</updated><title type='text'>Bill G Has Left The Building</title><content type='html'>&lt;div style="align: center"&gt;&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/Xr5w3X4R8b4&amp;rel=1"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/Xr5w3X4R8b4&amp;rel=1" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-9045552968411587659?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/9045552968411587659/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=9045552968411587659' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/9045552968411587659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/9045552968411587659'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2008/01/bill-g-has-left-building.html' title='Bill G Has Left The Building'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-6878858996806403022</id><published>2007-12-11T15:34:00.000+05:30</published><updated>2008-01-29T21:31:21.766+05:30</updated><title type='text'>A Movie About Coffee</title><content type='html'>&lt;div style="text-align: center"&gt;&lt;a href="http://www.dilbert.com/comics/dilbert/archive/dilbert-20071115.html"&gt;&lt;img src="http://hsirkel.net/dilbert/dilbert20071115.gif" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-6878858996806403022?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/6878858996806403022/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=6878858996806403022' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/6878858996806403022'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/6878858996806403022'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2007/12/movie-about-coffee.html' title='A Movie About Coffee'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-6394477207194013716</id><published>2007-11-20T01:30:00.000+05:30</published><updated>2007-11-20T21:16:24.842+05:30</updated><title type='text'>How To Build A Read/Write JavaScript API</title><content type='html'>&lt;a href="http://digg.com/submit?phase=2&amp;url=http://piecesofrakesh.blogspot.com/2007/11/how-to-build-readwrite-javascript-api.html" target="_blank" style="float: right"&gt;&lt;img border="0" alt="Digg my article" src="http://digg.com/img/badges/91x17-digg-button.gif"/&gt;&lt;/a&gt;&lt;p&gt;I've learnt most of this primarily by reading through &lt;a href="http://code.google.com/apis/gdata/client-js.html"&gt;Google Calendar's JavaScript Client Library&lt;/a&gt; code. I've also picked up clues from &lt;a href="http://www.xucia.com/CrossSafe/readme.html"&gt;lots&lt;/a&gt; of &lt;a href="http://www2007.org/program/paper.php?id=801"&gt;other&lt;/a&gt; &lt;a href="http://www.youtube.com/watch?v=ZvFVs92Fydw"&gt;material&lt;/a&gt; around the Internet. There are also some minor improvements I've added.&lt;/p&gt;&lt;p&gt;So, here's the use-case: You probably already have a &lt;a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm"&gt;&lt;abbr title="Representational State Transfer"&gt;REST&lt;/abbr&gt;&lt;/a&gt; (or similar) &lt;abbr title="Application Programming Interface"&gt;API&lt;/abbr&gt; for server to server communication. Having a JavaScript API would be a great idea (after all, JavaScript is the most deployed programming language available on almost every platform in the form of a browser runtime). This poses many problems. Most significantly, browsers are very strict about the &lt;a href="http://en.wikipedia.org/wiki/Same_origin_policy"&gt;same origin policy&lt;/a&gt;. You are aware of &lt;a href="http://snook.ca/archives/javascript/cross_domain_aj/"&gt;certain hacks out there to use JavaScript across domains&lt;/a&gt;, but at best they give you read access or rely on browser plugins. You can do writes using query string parameters, but you know that &lt;a href="http://www.w3.org/2001/tag/doc/whenToUseGet.html"&gt;that's just plain wrong&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Whatever be your solution to this problem, you want to play within the browser's security model, and not depend on any browser-specific security loopholes. Another very important thing you want to achieve is to ensure that your API users do not have to do any setup at their end – be it in terms of installing a &lt;a href="http://ajaxpatterns.org/archive/Cross-Domain_Proxy.php"&gt;server-side proxy&lt;/a&gt;, or jumping through hoops of any other kind. If a setup is unavoidable, it should be very simple to do, requiring little or no effort. You might also add additional requirements of user authentication (after all, you are letting them do writes), preferably at your domain – &lt;a href="http://openid.net/"&gt;OpenID&lt;/a&gt; style – and have access to your cookies even when your application is being used from another domain entirely.&lt;/p&gt;&lt;p&gt;People might point out solutions like &lt;a href="http://www.xucia.com/CrossSafe/readme.html"&gt;CrossSafe&lt;/a&gt; and &lt;a href="http://www2007.org/program/paper.php?id=801"&gt;Subspace&lt;/a&gt;. From what I gather of both these ideas, their goal is to &lt;a href="http://blog.360.yahoo.com/blog-TBPekxc1dLNy5DOloPfzVvFIVOWMB0li?p=715"&gt;secure your site&lt;/a&gt; from any third-party script snippet. That is not a necessary goal in our case. Also, both these techniques rely very heavily on some form of setup at the API consumer's end (which aren't very easy to do either – may even be impossible for say shared hosting environments), which we don't want to have. The technique I'm suggesting here is very similar in it's operation to both Subspace and CrossSafe, but eliminates (or reduces drastically) the need for any setup at the user's end.&lt;/p&gt;&lt;p&gt;&lt;a href="http://json.org/JSONRequest.html"&gt;The JSONRequest specification&lt;/a&gt; also needs mentioning. Unfortunately, the spec itself is rather new. Needless to say, there's no native working implementation of it as of this writing. CrossSafe comes rather close as an implementation, but &lt;a href="http://www.xucia.com/CrossSafe/readme.html#limitations"&gt;it's not complete&lt;/a&gt;. (To make matters worse, completing the implementation will require even more server-side co-operation at the API consumer's end.) That said, I don't know why Doug Crockford has decided to keep PUT and DELETE methods out of the spec, among others. I guess it might be for simplicity. However, I think in today's RESTful days not having those methods supported is not a good idea. If Crockford's spec ever becomes the standard, I will be a little unhappy that the additional methods are not supported. The API creation technique I'm mentioning here supports all the HTTP methods that the browser supports for HTML forms (which is &lt;a href="http://www.w3.org/TR/html401/interact/forms.html#h-17.13.1"&gt;only GET and POST&lt;/a&gt; for all major browsers to the best of my knowledge), but at least it's a browser limitation – not one imposed by this technique.&lt;sup&gt;&lt;a href="#moreMethods"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;&lt;p&gt;So, let's get started. Here's what you require to get cross-domain read write JavaScript APIs to work.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;The "setup" required at the client's end is that he should have at least one static cacheable resource embedded in the page where he's consuming the API, which is loaded from the same domain as his page. This could be in the form of a static CSS file, or an image. If the page doesn't have either, it will be required to insert one – maybe in the form of a 1px image hidden away by using inline style attributes. This is usually not too much to ask for, considering that pages are either made up of spacer GIFs or CSS documents, usually loaded from within the same domain. The static resources I mentioned could even be from a different sub-domain within the same domain, but it might complicate scripts slightly to have it set up that way. If this setup is not possible at all (oh, come on!), you could still find a work around&lt;sup&gt;&lt;a href="#domainResourceWorkaround"&gt;2&lt;/a&gt;&lt;/sup&gt;, but I think that this is the easiest way to get things up and running.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;You will need to do some setup at your end, if you are the creator of the API. In particular, you will need to setup a "proxy" page that intercepts the requests from the JavaScript client API, conditions the data, and passes it along to the REST API. This proxy page also reads the response from the REST API, conditions the data to suit the client, and flushes it down to the JavaScript.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Now, let's go over the process of actually orchestrating the communication.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;The API client library is included on the page by means of a script tag pointing to your domain (your domain being the host of the client library). This is similar to &lt;a href="http://www.google.com/apis/maps/documentation/index.html#AJAX_Loader"&gt;including the Google Maps API&lt;/a&gt; on the page.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Once included, the script scans the page for the static resource mentioned above. This is done by walking the DOM looking for &lt;code&gt;link&lt;/code&gt; or &lt;code&gt;img&lt;/code&gt; tags, and checking the value of the &lt;code&gt;href&lt;/code&gt;/&lt;code&gt;src&lt;/code&gt; attribute to ensure it lies within the same domain as the calling page. The URL of this resource is stored for use later. At this point, if required, the client library can signal to the developer that it is ready for communication with the server. If the resource is not found, the client-library should throw an error and terminate.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;When a request requires to be made, the client library takes the request parameters and prepares the markup for a form. This form can have any &lt;code&gt;method&lt;/code&gt; attribute value, and should have it's &lt;code&gt;action&lt;/code&gt; attribute set to the proxy page on your domain. The parameters to be sent to the server should be enumerated as hidden fields within the form. The client library also specifies the resource (in a RESTful sense) that needs to be acted upon. Also, the name of the static resource we had hunted down earlier is  passed on to the server. This form is not appended to the document yet. This markup is then wrapped into &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; tags. The body tag should have &lt;code&gt;onload=”document.forms[0].submit();”&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The client library then creates a 0px x 0px iframe, without setting the &lt;code&gt;src&lt;/code&gt; attribute, and appends it to the page's DOM. This makes the browser think that the iframe exists in the same domain as the calling page. Then, by using the iframe document object's &lt;code&gt;open()&lt;/code&gt;, &lt;code&gt;write()&lt;/code&gt; and &lt;code&gt;close()&lt;/code&gt; methods the markup created in the previous step is dumped into the iframe. As soon as the close method is called, the form gets submitted to the proxy page on your domain because of the &lt;code&gt;onload&lt;/code&gt; in the body tag. Also note that this gives the server access to any cookies it might have created from within it's domain, letting you do things like authentication. In this way one part of the communication is complete, and the data has been sent to the server across domains. However, the iframe's &lt;code&gt;document.domain&lt;/code&gt; has now switched to point to your domain. The browser's security model now prevents any script access to most parts of the iframe.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The proxy page sitting on your server now queries your REST API – basically doing it's thing – and gets the response. Response in hand, the proxy is now ready to flush the response to the client.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;If the response is rather large in size, as might be the case with a huge GET call for instance, the proxy breaks it up into chunks of not more than say 1.5k characters&lt;sup&gt;&lt;a href="#urlLengthRestriction"&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The proxy is now ready to flush the response. The response consists of iframes – one iframe for each of these 1.5k chunks. The iframe's &lt;code&gt;src&lt;/code&gt; attribute is set to the static resource we had discovered earlier. It is for exactly this purpose that we had hunted the resource down and passed on the URL to the server. At the end of each of these URLs, the proxy appends one of the chunks of the response, after a “#” symbol, so that it works as a &lt;a href="http://www.w3.org/Addressing/URL/4_2_Fragments.html"&gt;URL fragment identifier&lt;/a&gt;. Also, the iframe tags are each given a &lt;code&gt;name&lt;/code&gt; attribute, so that the client script can locate them.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Meanwhile, the client-side code is where it had left off at the end of step 4 above. The script then starts polling the iframe it created to check for the existance of child iframes. This check of iframes will need to based on the iframe name the server will be sending down. It will look something like this: &lt;code&gt;window.frames[0].frames[“grandChildIframeName”]&lt;/code&gt;. Since the static resource we have loaded into the grandchild iframe is of the same domain as the parent page, the parent page now has access to it, even the intermediate iframe is of a different domain.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The client script now reads the &lt;code&gt;src&lt;/code&gt; attributes of the iframe, isolates the URL fragments (&lt;code&gt;iframe.location.hash&lt;/code&gt;), and reassembles the data. This data would typically be some JSON string. This JSON can then be eval'd and passed on to a success handler. This completes the down-stream communication from the server to the client, again across domains.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;With the entire process complete, the client-library can now perform some cleanup actions, and destroy the child iframe it created. Though leaving the iframe around is not a problem, it is not necessary and simply adds to junk lying around in the DOM. It's best to get rid of it.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;This was simply the outline of the process, and there are several additions/improvements that can be done. For example, better control on reading/writing HTTP headers, having a reliable &lt;a href="http://www.devguru.com/technologies/xmldom/quickref/document_readyState.html"&gt;readyState&lt;/a&gt; value, error handling in case of HTTP errors (4xx, 5xx errors), handling of HTTP timeouts, etc. are all desired. However, this should be enough to get you started.&lt;/p&gt;&lt;p&gt;If you haven't already realized the significance of this, we should now be able to build much more sophisticated mashups that do much more than the current breed of mashups on the web. It opens up the floodgates to entirely new kind of applications on the Internet – applications we haven't seen as yet.&lt;/p&gt;&lt;p&gt;Let's enable better mashups! Nothing should now stop you from being able to give open secure access to your site's functionality in JavaScript.&lt;/p&gt;&lt;hr /&gt;&lt;ol style="font-size: 0.9em"&gt;&lt;li&gt;&lt;a name="moreMethods"&gt;&lt;/a&gt;A little creative thinking will let you circumvent the problem of browser-restricted HTTP methods when querying your REST API. Send an extra parameter to the proxy page when you are creating the form to specify which method to use. Let the proxy page then hit your REST API with the specified method.&lt;/li&gt;&lt;li&gt;&lt;a name="domainResourceWorkaround"&gt;&lt;/a&gt;The work around to not having any same-domain static resource would be to ask the API user to have a blank HTML page on his domain, the URL for which should be manually provided by the user to the client script. I don't think this is a great idea since it is an extra step that the API user has to do. However this can be used for one of those if-all-else-fails situations.&lt;/li&gt;&lt;li&gt;&lt;a name="urlLengthRestriction"&gt;&lt;/a&gt;This 1.5k restriction is to overcome a &lt;a href="http://support.microsoft.com/kb/208427"&gt;URL length restriction in Internet Explorer&lt;/a&gt;, though most other browsers allow much more. Note, HTTP itself does not impose any restriction on the URL length.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-6394477207194013716?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/6394477207194013716/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=6394477207194013716' title='19 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/6394477207194013716'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/6394477207194013716'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2007/11/how-to-build-readwrite-javascript-api.html' title='How To Build A Read/Write JavaScript API'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>19</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-3144660280491317742</id><published>2007-11-09T18:57:00.000+05:30</published><updated>2007-11-09T19:13:02.621+05:30</updated><title type='text'>Pics from Kerala</title><content type='html'>&lt;p&gt;Finally managed to get some time today to upload my &lt;a href="http://www.flickr.com/photos/rakesh/sets/88409/"&gt;pics from my trip to Kerala&lt;/a&gt; to Flickr. Here are some of my favorites from that list.&lt;/p&gt;&lt;br /&gt;&lt;p style="text-align:center"&gt;&lt;a href="http://www.flickr.com/photos/rakesh/1933152812/" title="Photo Sharing"&gt;&lt;img src="http://farm3.static.flickr.com/2089/1933152812_60febec46e_m.jpg" width="240" height="180" alt="Police Orders" /&gt;&lt;/a&gt;&lt;a href="http://www.flickr.com/photos/rakesh/1932339525/" title="Photo Sharing"&gt;&lt;img src="http://farm3.static.flickr.com/2326/1932339525_87664ee7ba_m.jpg" width="240" height="180" alt="Attack!" /&gt;&lt;/a&gt;&lt;a href="http://www.flickr.com/photos/rakesh/1933187076/" title="Photo Sharing"&gt;&lt;img src="http://farm3.static.flickr.com/2331/1933187076_5ef90f62f3_m.jpg" width="240" height="180" alt="Sunset at the Cape" /&gt;&lt;/a&gt;&lt;a href="http://www.flickr.com/photos/rakesh/1933190826/" title="Photo Sharing"&gt;&lt;img src="http://farm3.static.flickr.com/2384/1933190826_5b78bba71e_m.jpg" width="240" height="180" alt="Suchindram Gopuram" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Head over to Flickr to &lt;a href="http://www.flickr.com/photos/rakesh/sets/88409/"&gt;see the complete photo set&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-3144660280491317742?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/3144660280491317742/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=3144660280491317742' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/3144660280491317742'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/3144660280491317742'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2007/11/pics-from-kerala.html' title='Pics from Kerala'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm3.static.flickr.com/2089/1933152812_60febec46e_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-2655419899414611564</id><published>2007-10-18T21:30:00.000+05:30</published><updated>2007-10-18T21:27:09.533+05:30</updated><title type='text'>Dojo, Flash, SWFObject, Packer, IE's "Click here to activate and use this control" and Eval Contexts</title><content type='html'>&lt;p&gt;Boy, that's a long title!&lt;/p&gt;&lt;p&gt;Solving this problem I had at hand took a good day and a half. What I discovered seems obvious in hindsight, but it wasn't obvious to me until I had solved it. So that no one ever goes through the pain, here's what happened.&lt;/p&gt;&lt;p&gt;There is this thing I'm working on at work that required the use of &lt;a href="http://blog.deconcept.com/swfobject/" title="SWFObject"&gt;SWFObject&lt;/a&gt; class simply to get around the IE "Click here to activate and use this control" nuisance when inserting flash files into the page.&lt;/p&gt;&lt;p&gt;Now, the reason why that message comes up is &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=182027#182027"&gt;pretty shitty&lt;/a&gt;, but the problem and solution is &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/overview/activating_activex.asp"&gt;very well documented&lt;/a&gt;. SWFObject is supposed to solve this problem. So, rather than re-inventing the proverbial wheel, we decided to use SWFObject. However, needless to say, IE would still keep throwing the message.&lt;/p&gt;&lt;p&gt;Now, a bit about the setup we have. We are using &lt;a href="http://dojotoolkit.org/"&gt;Dojo&lt;/a&gt; for this particular thing. I have written a wrapper around SWFObject so that I don't have to bother passing it all the stuff it needs every time I need to use it. Also, on a test machine, we host built versions of the code, which used &lt;a href="http://dean.edwards.name/packer/"&gt;Packer&lt;/a&gt; to compress the JavaScript. We were using Packer more as a compresser than as an obfuscator, since Packer gave us a considerable improvement in the compression ratios over anything else. On my local machine, I use the unbuilt version of the code.&lt;/p&gt;&lt;p&gt;Irrespective of where the code ran from, we used to get the nasty message in IE.&lt;/p&gt;&lt;p&gt;For those who don't know yet, here's how you get around the message - it's pretty simple. Create the object/embed tag from an &lt;em&gt;external&lt;/em&gt; JavaScript file, and insert it into the HTML document. It's that simple.&lt;/p&gt;&lt;p&gt;Now, going by unobtrusive principles, our JavaScript always lies in external files (unless there's &lt;em&gt;very&lt;/em&gt; good reason to not do so). So, why was this message showing up? There were two scenarios here:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;My dev machine:&lt;/strong&gt; Because of the way I had layered the files in Dojo for ease of maintenance, Dojo would dynamically pull in the references on the fly. This is very convenient and makes for easy to organize code. The way Dojo does this is by making an XHR call to the server to fetch the .js file, and then &lt;code&gt;eval&lt;/code&gt;ing the code. Now, these evals are run in the context of the window, effectively making them inline scripts. IE thus thought the code was inline, and showed the error message.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;The test machine:&lt;/strong&gt; So, even if it doesn't run on my machine, that's fine if we can get it to run on a test machine correctly. On this test machine we always house the built version of the Dojo file. With a properly written build profile, Dojo might not have to go around and pull in references as required since they would already be baked into the built files. So, that would make the SWFObject code external, and IE shouldn't have a problem with it, right? Almost. Packer requires an eval of the code it has obfuscated to make sense of it. Again, the eval is run in the context of the browser, and IE treats the resultant code as inline, again showing the error.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So, in both the cases, the problem was the context of the eval, though in entirely different scenarios. It could also be concluded that SWFObject cannot ever be compressed using Packer. It was just painful to track down and fix this bug. I hope no one ever has to go through this pain again.&lt;/p&gt;&lt;p&gt;If you need to know, we had to switch to &lt;a href="http://dojotoolkit.org/docs/shrinksafe"&gt;ShrinkSafe&lt;/a&gt; to avoid the eval that Packer does. There are definitely better ways to compress, but this should do for now. The code-size increase wasn't too significant, so we were fine with using ShrinkSafe. Ideally, I would use ShrinkSafe for SWFObject and packer for everything else, giving the best of compression and avoiding the implicit eval. This doesn't solve the problem on my local dev machine (since the code is unbuilt), but that doesn't really matter.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-2655419899414611564?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/2655419899414611564/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=2655419899414611564' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/2655419899414611564'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/2655419899414611564'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2007/10/dojo-flash-swfobject-packer-ies-click.html' title='Dojo, Flash, SWFObject, Packer, IE&apos;s &quot;Click here to activate and use this control&quot; and Eval Contexts'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-6899720193461747515</id><published>2007-10-16T11:52:00.000+05:30</published><updated>2007-10-16T12:53:35.741+05:30</updated><title type='text'>Client-Side Performance Optimization of Ajax Applications</title><content type='html'>&lt;p&gt;There has a lot been said about server-side performance optimization. But a recent report from Yahoo concluded that the server accounted for less than 5% of the time for a user to view a web page. Here's how you can performance optimize the client-side code. Note that this article is targeted towards pretty advanced JavaScript programmers, working with pretty client-heavy applications.&lt;/p&gt;&lt;h1&gt;Network performance&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;This feels just stupid to say: Reduce the amount of source-code you've written. There are several ways of doing this. The first is to simply not write any JavaScript at all. But that might not be an option for you. Another way is to lazy load code - don't download code unnecessarily on the client. This is especially true of single page applications. Another thing you simply must do is pass your code through a good compressor - like &lt;a href="http://alex.dojotoolkit.org/shrinksafe/" title="ShrinkSafe"&gt;Dojo's Shrinksafe&lt;/a&gt;, &lt;a href="http://www.crockford.com/javascript/jsmin.html" title="Doug Crockford's JSMin"&gt;Crockford's JSMin&lt;/a&gt;, &lt;a href="http://dean.edwards.name/packer/" title="Dean Edwards' Packer"&gt;Edwards' Packer&lt;/a&gt; or the &lt;a href="http://www.julienlecomte.net/blog/2007/08/13/introducing-the-yui-compressor/ " title="YUI Compressor"&gt;YUI Compressor&lt;/a&gt; (or even a combination of those).&lt;/p&gt;&lt;p&gt;Another thing that I've heard most people recommend is that gzipping of JavaScript files helps reduce network latency. While this is entirely true, &lt;a href="http://support.microsoft.com/kb/871205"&gt;a bug in a rather prevelent version of IE&lt;/a&gt; makes me wonder if I should do that. If anyone can prove me wrong, I'll only be glad.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;In all popular browsers today, JavaScript files are always sequentially downloaded. It doesn't matter if HTTP says you can have 2 connections open. It doesn't matter that CDNs on different domains can serve files in parallel. It doesn't matter that Firefox always disregards the HTTP restriction and downloads multiple files all the time. When it comes to JavaScript, all files are always downloaded sequentially.&lt;/p&gt;&lt;p&gt;This only makes sense, since script should be executed in the order in which they appeared in the markup. Reduce the number of files to be downloaded. This can be done by using a build process, something similar to what the Dojo build system does - combining the JavaScript files into one file.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Cache Ajax responses. The network is undoubtedly the weakest link in the chain. Avoid making requests. A request once made should never be made again. Implement cache invalidation if you need. Even then don't fetch data just because the cache is now invalid. Wait till it is actually required. If you never end up needing it, you've saved another hit.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h1&gt;Perceived performance&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Reduce the amount of source-code you've written. I know this sounds like a repeat of a point above, but I had to bring this up from a perception point of view too. It seems that the more JavaScript that's downloaded, the more time it requires for the browser to interpret it, increasing at an exponential rate (not linear). Which means that even after your code has been downloaded, the browser will just sit there doing (apparently) nothing for some time. Usually, this is a problem above say 500 kb of code.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;In any case, if you are downloading 500k of JavaScript on the load of the page, there better be a very good reason for it. You should be able to have much faster download times by splitting up these files into &lt;em&gt;modules&lt;/em&gt;, which you can download at a later time - maybe on demand.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Get something downloaded and displayed as soon as possible. This might be something as simple as markup with the UI skeleton for the application, and simple "Loading..." indicators. It helps a great deal in reducing the frustration in working with an application.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;If you can help it, put your JavaScript includes at the bottom of the page. This gives the browser enough time to download and render most of the page before even starting to mess with your scripts. Considering that JavaScript downloads sequentially, and doesn't let any other resource be downloaded at that time, you should only download JavaScript once you already have something to show the user.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h1&gt;JavaScript performance&lt;/h1&gt;&lt;p&gt;There's a lot that can be said here. I've started getting a lot of kicks lately in trying to milk every millisecond of performance from a browser. So here's what I've learnt so far.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;If you are writing a function that returns an array, you usually want to pass in a callback as a parameter of that function. This will improve the performance by &lt;em&gt;at least&lt;/em&gt; a 100%.&lt;/p&gt;&lt;p&gt;Instead of:&lt;code&gt;&lt;pre&gt;&lt;br /&gt;    var anArrayOfData = getAnArrayOfData();&lt;br /&gt;    for(var i=0; i&amp;lt;anArrayOfData.length; i++) {&lt;br /&gt;        // do something with anArrayOfData[i]&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Do the following:&lt;code&gt;&lt;pre&gt;&lt;br /&gt;    getAnArrayOfData(function(item) {&lt;br /&gt;        // do something with item&lt;br /&gt;    });&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;This is better because you usually loop inside the function anyway to build the array. Having to loop through the returned array again is a waste of processing time.&lt;/p&gt;&lt;p&gt;Instead of:&lt;code&gt;&lt;pre&gt;&lt;br /&gt;    function getAnArrayOfData() {&lt;br /&gt;        var returnData = [];&lt;br /&gt;  &lt;br /&gt;        for(var i=0; i&amp;lt;largeSetOfData.length; i++) {&lt;br /&gt;            // Some code...&lt;br /&gt;            if(condition === true) {&lt;br /&gt;                returnData.push(largeSetOfData[i]);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;  &lt;br /&gt;        return returnData;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Do:&lt;code&gt;&lt;pre&gt;&lt;br /&gt;    function getAnArrayOfData(callback) {&lt;br /&gt;        var returnData = [];&lt;br /&gt;        &lt;br /&gt;        for(var i=0; i&amp;lt;largeSetOfData.length; i++) {&lt;br /&gt;            // Some code...&lt;br /&gt;            if(condition === true) {&lt;br /&gt;                returnData.push(largeSetOfData[i]);&lt;br /&gt;                if(callback) {&lt;br /&gt;                    callback(largeSetOfData[i]);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;  &lt;br /&gt;        return returnData;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;This way, the callback parameter is optional, and you still return the returnData, but you could also provide the callback function and avoid another external loop to iterate through the return data. I've changed all the getElementsBySelector methods in my libraries to use this approach, for example. It only seems logical - if I get an array, I will usually need to iterate through it.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Use native functionality whenever possible. Case in point: forEach iterators. This is very helpful, and &lt;a href="http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:forEach"&gt;part of the 1.6 standard&lt;/a&gt;, but the most popular browser in the world can't do forEach loops. Most people either live with it, write their own forEach iterator using simple for statements, or use a library that already has this built in. If you are the second type of person, you aren't achieving much except code readability, which is not a bad thing. Most frameworks' forEach loops also take much the same approach. However, there's a better way.&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;    function myForEach(array, callback) {&lt;br /&gt;        if(array.forEach) {&lt;br /&gt;            array.forEach(callback);&lt;br /&gt;        } else {&lt;br /&gt;            for(var i=0; i&amp;lt;array.length; i++) {&lt;br /&gt;                callback(array[i]);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;In almost all browsers, the block in the if statement will be executed, giving the best possible performance, since you are using native functionality. However in less modern browsers that happen to be more popular and which you have to support but can't do much more about optimization, the else block will still work. Think of it as being the graceful degradation principles of CSS being applied to performance.&lt;/p&gt;&lt;p&gt;Now, I haven't done it above, but I strongly recommend that you stick to the JavaScript standards when deciding the function signatures of both the &lt;code&gt;myForEach&lt;/code&gt; and the &lt;code&gt;callback&lt;/code&gt; functions. This is because if the world does become a better place one day, and the most popular browser in the world actually learns how to be modern, you code will work such that it uses the most optimum features in the browser, without you having to change a single line of code.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Don't build too much of scaffolding code to make JavaScript behave like classical object oriented programming languages. Usually, you will not end up with much more than helper functions. A lot of the paradigms of classical OO don't apply to JavaScript. Learn to use JavaScript for what it can do. Don't make it what you want it to be.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Use threads. Ok, JavaScript doesn't really do threads at all. However, you can kinda simulate the effect of threads. What you achieve by doing this is that you hand over control back to the browser for a brief instant before proceeding with your code. This gives the browser time to react to any other user action that might have happened, make any updates to the DOM that you had asked for, bypass that nasty &lt;q&gt;The script on this page is unresponsive&lt;/q&gt; warning, etc. So, how do you do this?&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;    // some code&lt;br /&gt;    setTimeout(function() {&lt;br /&gt;        // some more code&lt;br /&gt;    }, 0);&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;If you don't understand how exactly this works, this could be a source for a lot of bugs. Use this with caution. However, I've used to get a very high apparent performance very successfully.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Cache function results. If for a given set of parameters a function will always return the same results, you really only need to calculate it the first time. Once calculated, save the data in a variable, and read from that variable hence forth. For example:&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;    var squaresCache = {};&lt;br /&gt;    function getSquare(number) {&lt;br /&gt;        if(!squaresCache[number]) {&lt;br /&gt;            squaresCache[number] = number * number;&lt;br /&gt;        }&lt;br /&gt; &lt;br /&gt;        return squaresCache[number];&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;The example above isn't very good for at least two reasons. Firstly, using this pattern for computing squares is just plain stupid. Secondly, it seems (though it need not be) that &lt;code&gt;squaresCache&lt;/code&gt; is a global variable, which is plain evil in any programming language. However, I hope it illustrates the idea of populating the cache the first time the function executes and subsequently reading from the cache instead of re-calculating the data.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Strings in JavaScript, like in many other languages are immutable. So, for lots of string concatenation operations, you need to use the string builder pattern in JavaScript too. The simplest way to do that is to declare an array instead of a string, push strings into that array instead of concatenating, and finally call &lt;code&gt;array.join("");&lt;/code&gt; to get the concatenated string.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Do not use eval. Eval is painfully slow. But why do you need to use eval? Other than converting a JSON string to an object, I never write any code that needs to be eval'ed. Remember the other cousins of eval - &lt;code&gt;new Function(someString)&lt;/code&gt; and &lt;code&gt;setTimeout(someString, ms)&lt;/code&gt;. You don't need the Function constructor at all, and you don't need to pass strings into setTimeout at all. Instead, in both cases, you can use anonymous functions. Thus, the implicit eval is avoided. Using anonymous functions give the added benefit of retaining variable scope through the creation of the closure. The eval is always carried out in the global scope.&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;q&gt;Unfold&lt;/q&gt; your if statements. This is particularly useful for code that checks for browser features. For example, instead of:&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;    function addEvent(element, eventName, callback) {&lt;br /&gt;        if(element.addEventListner) {&lt;br /&gt;            // add the event one way&lt;br /&gt;        } else {&lt;br /&gt;            // add the event another way&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Do the following:&lt;code&gt;&lt;pre&gt;&lt;br /&gt;    if(element.addEventListner) {&lt;br /&gt;        function(element, eventName, callback) {&lt;br /&gt;            // add the event one way&lt;br /&gt;        }&lt;br /&gt;    } else {&lt;br /&gt;        function(element, eventName, callback) {&lt;br /&gt;            // add the event another way&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;This unfolding of ifs applies even to loops, for example. So, if you can keep if statements outside a loop, do that. It doesn't make for readable code, but it's significantly faster. Bonus points to you if you just thought to yourself that my forEach example can be improved using this technique.&lt;/li&gt;&lt;/ul&gt;&lt;h1&gt;DOM Performance&lt;/h1&gt;&lt;p&gt;Of all the parts making up client script, DOM manipulations are the slowest. So, you have to take the most care here.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Use innerHTML. Don't be too much of a purist. Being a purist won't make your application faster. You wouldn't believe how much faster your code is if you use innerHTML.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Never update the DOM. Ok, if that's not possible, at least do it as infrequently as possible. Bunch up your updates to the DOM and save them for a later time. Realize that it is not the size of the update but the high frequency of updates that's slow. Doing &lt;code&gt;appendChild&lt;/code&gt; in a loop is updating the DOM frequently. Caching the markup in a string, and then setting the &lt;code&gt;innerHTML&lt;/code&gt; in the end is batching and updating infrequently. The second is much faster.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;However, the technique above is mostly only useful if you are adding new stuff to the DOM. What if you are updating existing elements on the DOM? How do you keep updates to a minimum when you want to change style, class names, content and children of a node that already exists? Simple. Clone the node you want to work with. Now you will be working with a clone of the real node, and the cloned node doesn't exist in the DOM. Updating the cloned node doesn't affect the DOM. When you are done with your manipulations, replace the original node with the cloned node. However, note that the performance problems here are because of the content and rendering reflow that the browser has to do. You might get similar benefits by simply hiding the element first, making the changes, and then showing it. Though I haven't tried this, it should work in theory.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Keep track of events. For me, this is the worst part of working with the DOM. This is important because when your application (or any DOM nodes) are being unloaded or destroyed, you will have to manually unregister the events from the nodes BEFORE you destroy the elements. Yes, this is the garbage collector's job, and that's supposed to be the job of the environment your code runs in, but guess which browser is the offender here. Internet Explorer doesn't free all the references &lt;em&gt;even when the user leaves your web page&lt;/em&gt;. Unless you want your web app to earn the reputation of being responsible for many a crashed browser, and a horrid browsing experience for &lt;em&gt;other&lt;/em&gt; websites too, count your references.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;If you are going to iterate through a node list to attach event handlers, you are probably wasting processor time. Instead, simply attach the event handler to some parent of the node list and read from the event object to know what was clicked on. You save the cycles required to iterate over the nodes this way.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Avoid calls to functions like getElementsBySelector, where there's lot of DOM walking involved. If you cannot, then make sure you work on as small an area of the DOM as possible. If your favourite version of getElementsBySelector lets you send in a root node under which to search, do that. Otherwise, provide a very high specificity, starting with a "#someId" so that the function can narrow down the search. Also, understand how these functions work internally. For example, you could use a getElementsByClassName to find divs with the class "foo", and the implementation of getElementsByClassName will probably be just three lines, However, using getElementsBySelector("div.foo") will be faster in almost all frameworks, even though it might have a hundred lines of code in it's implementation, since it has less DOM walking to do.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Sorry for the kinda horrible organization of this post. I should also say that not all of these ideas are my original - I found a lot of these by reading many sites scattered across the web. However, I hope you found this post useful.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-6899720193461747515?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/6899720193461747515/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=6899720193461747515' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/6899720193461747515'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/6899720193461747515'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2007/10/client-side-performance-optimization-of.html' title='Client-Side Performance Optimization of Ajax Applications'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-8956493884898545477</id><published>2007-09-21T10:55:00.000+05:30</published><updated>2007-09-21T11:24:42.103+05:30</updated><title type='text'>Much Deserved Update</title><content type='html'>&lt;p&gt;It's been an eternity since I wrote to this blog, so an update is in order. I fear this update will seem very similar to &lt;a href="http://piecesofrakesh.blogspot.com/2005/12/back-in-action.html" title="Back In Action"&gt;a pervious post&lt;/a&gt;. Also, please bear with me if this post seems too long.&lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Much in the vein of that previous post, I've quit my job again. &lt;a href="http://www.iventa.com/" title="Iventa Corporation"&gt;Iventa&lt;/a&gt; was a great place to work at (Notice, I didn't say that about my employer before Iventa), and it has let me learn, explore and part with (and thus expand) my knowledge more than any other place I've worked at before.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;I'm now with &lt;a href="http://www.cleartrip.com/" title="Cleartrip.com"&gt;Cleartrip.com&lt;/a&gt;. One of the top travel portals today in India, Cleartrip could easily be mistaken to be &lt;q&gt;just a travel thing out there&lt;/q&gt;. Truth is, outside of the &lt;a href="http://www.iitb.ac.in/" title="IIT Bombay"&gt;&lt;abbr title="Indian Institute of Technology"&gt;IITs&lt;/abbr&gt;&lt;/a&gt; - an organization I used to interact with regularly - this is one place where I've seen more innovations happen more frequently than any other place. All the people you meet at Cleartrip are gurus in their areas of work. I can only consider myself to be lucky to be in the company of such a congregation of sheer genius.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;I've joined Cleartrip as a JavaScript developer guy. If you look at that from a organizational chart perspective, this is a slight demotion in rank for me. But that was completely intentional. I was starting to move towards managing people at Iventa, and I think I had still not had enough of playing with technology. I guess that only means that I want to grow some more in the area of technology, and not in the area of management. Tech is where I get my kicks from, and I don't see that changing at least for some time.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The management at Cleartrip was kind enough to allow me a short vacation between jobs. I took the opportunity to go to Kerala - this time not because it's my home town, but because I had never been to a place of such scenic beauty as a tourist. I've got very interesting stories (including one where I'm chased by a wild elephant trying to protect her kid from me, since I was armed with a camera), but I've got even more interesting photographs. I shall be uploading them soon. Which brings me on nicely to the next two points.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The reason I've not uploaded any pics so far is because my beloved Hangy is dead. Again. This time, it seems that the moisture from the Mumbai rains got to her chipset on the motherboard, and AFAIK there's no one who can fix that. So, my only option is to replace the board, but I'm reconsidering that in favor of a huge upgrade. I've meanwhile asked my computer-fixit-guy to come up with an alternative - probably a second-hand motherboard I can buy from him. Let's see what he comes up with.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;So, assuming I get ready to post pics online to share, which service is really the better? I like Google, so Picassa seems to be an interesting option, but I've not found that to be reason enough to change from Flickr yet. Any opinions for or against either of these? Please enlighten me.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;This post would be incomplete without some more important information.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;This blog is NOT dead. I really mean to post much more. In fact, since Hangy's dead, I got my MacBook Pro from work home today so that I can compose this post. (Which incidentally makes this the first post on this blog written on a Mac. I wouldn't be surprised if the next one is written in Emacs on Ubuntu, or something!)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;That said, this blog is going to deviate a bit in its direction. So far this blog has largely been about markup and style. However, &lt;abbr title="In my humble opinion"&gt;IMHO&lt;/abbr&gt;, all that had to be said about markup and style has been said, either here or elsewhere. The subject is so beaten now, that a new acronym had to be invented in hopes of reviving interest. (&lt;a href="http://microformats.org/wiki/posh" title="Plain old semantic HTML"&gt;&lt;abbr title="Plain Old Semantic HTML"&gt;POSH&lt;/abbr&gt;&lt;/a&gt;, for God's sake!) Meanwhile, I've decided to move on. I need to give a better explanation of why I'm moving on, and I think that's a topic for another post. I really want to share my thoughts about why I think all the fuss about markup and style is not worth it - at least in the connotations it started to carry. That would be an ironic post, since &lt;a href="http://piecesofrakesh.blogspot.com/2004/09/economics-of-xhtml.html" title="The Economics of XHTML"&gt;the most popular post on my blog so far&lt;/a&gt; has vehemently promoted XHTML! I guess I had to go through all of it to learn how unimportant it is.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;I've moved on to JavaScript, if you haven't guessed already from my last few posts. I've been hungrily learning so much about JavaScript these days, that I can easily claim to know much more than some of the good JS coders out there. I know that's a tall claim, but on more than one occasion I've realized that some of these gurus' arguments don't make sense. I guess that's a good sign.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Which nicely brings me on to the last point I want to share. This blog is going to turn from a primarily web standards promotion blog to a primarily JavaScript hacking blog. I shall now discuss lessons I've learned in JavaScript, application architectures from a JavaScript thick-client perspective, interesting hacks and tricks in JavaScript that I've picked up along the way, and occasionally the stupid browser nuances (you know which browser I'm talking about) I come across. Expect posts talking about JavaScript as a language (one of the most modern - old as it is - and among the richest most expressive languages in the entire computer industry IMHO, and already available on your desktop!) for all the cool things it can do, and JavaScript from a more serious application design point of view, being an important part of application architecture design sitting at the top-most layer, ensuring that users have a great experience. This particular topic about JavaScript being a serious thick-client programming language has been of particular interest to me lately, and the few forays  I've had are very promising. So, expect me to talk a lot about these kinds of topics now on.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-8956493884898545477?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/8956493884898545477/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=8956493884898545477' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/8956493884898545477'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/8956493884898545477'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2007/09/much-deserved-update.html' title='Much Deserved Update'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-2002879912497978588</id><published>2007-06-18T16:48:00.000+05:30</published><updated>2007-06-20T00:28:11.520+05:30</updated><title type='text'>URI fragment identifiers and HTTP</title><content type='html'>I came across an interesting problem today with how &lt;abbr title="HyperText Transfer Protocol"&gt;HTTP&lt;/abbr&gt; handles &lt;abbr title="Uniform Resource Identifiers"&gt;URI&lt;/abbr&gt; fragment identifiers. Here's the spoiler - it does not!&lt;br /&gt;&lt;br /&gt;Here's the long story. If you are on a page which has a URL that looks like this:&lt;br /&gt;http://www.domain.com/page.html#fragment&lt;br /&gt;&lt;br /&gt;Now, #fragment is known as the URI fragment identifier. This particular thing has got very popular lately with it's potential uses in Ajax applications, since it can be easily (mis)used to let client-side code perform many actions.&lt;br /&gt;&lt;br /&gt;This also helps take care of some back-button problems with Ajax. For example, let's say you are on page.html. Then, you perform some client-side operation that appends #fragment to the URL. Now, let's say you navigate to page2.html and press the back button, you would land up on page.html#fragment. Then, the JavaScript on the page could read the #fragment and perform an Ajax action to restore the page to the state you had left it at.&lt;br /&gt;&lt;br /&gt;However, I just discovered when working on this one project that the #fragment is never sent to the server as part of the request headers. The HTTP specification says nothing about handling URI fragment identifiers, and sure enough most browsers do nothing with them.&lt;br /&gt;&lt;br /&gt;So, if you ever have to read the #fragment on a server, remember that you can't! That's just one more of the problems that we have to deal with as &lt;abbr title="Rich Internet Application"&gt;RIA&lt;/abbr&gt; developers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-2002879912497978588?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/2002879912497978588/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=2002879912497978588' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/2002879912497978588'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/2002879912497978588'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2007/06/uri-fragment-identifiers-and-http.html' title='URI fragment identifiers and HTTP'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-7438602893641573007</id><published>2007-06-12T20:59:00.000+05:30</published><updated>2007-06-12T21:04:27.802+05:30</updated><title type='text'>Safari for Windows</title><content type='html'>Yes, that's right. It has finally happened. &lt;a href="http://www.apple.com/safari/" title="Safari for Windows"&gt;Safari for Windows&lt;/a&gt; is now available as a free download.&lt;br /&gt;&lt;br /&gt;There are still some questions unanswered - my number one question is if it uses the same rendering engine as the Mac version. I hope it does.&lt;br /&gt;&lt;br /&gt;On a side note, I wonder what will happen to &lt;a href="http://try.swift.ws/"&gt;Swift&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-7438602893641573007?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/7438602893641573007/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=7438602893641573007' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/7438602893641573007'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/7438602893641573007'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2007/06/safari-for-windows.html' title='Safari for Windows'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-4876740584347786161</id><published>2007-02-20T06:48:00.000+05:30</published><updated>2007-02-20T06:58:26.150+05:30</updated><title type='text'>Web 2.0 ... The Machine is Us/ing Us</title><content type='html'>I find it very hard sometimes to explain, even to techies, that I work on JavaScript, CSS and markup. They just don't get that it involves an entirely different approach as opposed to old-school web programming. Hopefully &lt;a href="http://www.youtube.com/watch?v=6gmP4nk0EOE&amp;eurl="&gt;this beautifully made video&lt;/a&gt; will explain what it means to work on those technologies.&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="350"&gt;&lt;param name="movie" value="http://www.youtube.com/v/6gmP4nk0EOE"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/6gmP4nk0EOE" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-4876740584347786161?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/4876740584347786161/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=4876740584347786161' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/4876740584347786161'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/4876740584347786161'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2007/02/web-20-machine-is-using-us.html' title='Web 2.0 ... The Machine is Us/ing Us'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-2899672071801251260</id><published>2007-02-01T10:32:00.001+05:30</published><updated>2010-12-11T14:16:32.963+05:30</updated><title type='text'>IE's Unknown Runtime Error When Using innerHTML</title><content type='html'>IE never fails to surprise me. Look at the following code for example.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;    &amp;lt;body&amp;gt;&lt;br /&gt;        &amp;lt;p id="someId"&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;        &amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;            document.getElementById("someId").innerHTML = "&amp;lt;li&amp;gt;Some content&amp;lt;/li&amp;gt;";&lt;br /&gt;        &amp;lt;/script&amp;gt;&lt;br /&gt;    &amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This code has surprising results in Internet Explorer and Firefox, and I haven't found a decent explanation on the Internet of what exactly happens, so I'm posting this out of utter surprise.&lt;br /&gt;&lt;br /&gt;First thing you'd notice is that someId is a paragraph (p) tag. Secondly we are inserting a list item (li) into this paragraph, without having a unordered list (ul) as a parent element of this list item. If you are really the kind of markup nazi that I am, you'll notice that the p tag doesn't allow any block-level tags within it, and both LI and UL are block level tags, which is not permitted by the W3C rules.&lt;br /&gt;&lt;br /&gt;So, how do browsers react to this?&lt;br /&gt;&lt;br /&gt;Firefox does some code cleanup (I guess), and renders what looks and behaves like a list item, complete with a bullet and stuff. (Interestingly, it assumes that it is an unordered list and not an ordered list. Wonder why that's the case.)&lt;br /&gt;&lt;br /&gt;IE's JavaScript on the other hand breaks with an "Unknown runtime error"! I agree completely that this is not a good error message at all, but really, IE is enforcing correct W3C block/inline tag recommendations here - something Firefox is not doing. To demonstrate this, change the p to a ul, and the code will work in IE.&lt;br /&gt;&lt;br /&gt;IE's not 100% percent correct, though. It looks like it only enforces block/inline tags and not really tag semantics. Which means if you change the p to div, the code will execute correctly, since the div element allows other block-level tags within it. So, IE doesn't seem to be perfect, but seems to be kinda stricter than Firefox. Which may or may not be a good thing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-2899672071801251260?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/2899672071801251260/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=2899672071801251260' title='63 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/2899672071801251260'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/2899672071801251260'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2007/02/ies-unknown-runtime-error-when-using.html' title='IE&apos;s Unknown Runtime Error When Using innerHTML'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>63</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-7995488381947940605</id><published>2006-11-30T00:11:00.000+05:30</published><updated>2006-11-30T00:38:12.401+05:30</updated><title type='text'>America Calling</title><content type='html'>Within the coming week, I shall be leaving for Los Angeles, California for (at least) a three month period. I'm going to be there to do the ground-work towards the launch a product that has been very close to my heart for the last year, and has been taking up all my time. Finally, it looks like the product has now matured enough for real people with real businesses to start playing with.&lt;br /&gt;&lt;br /&gt;I'm also looking forward to catching up with old friends, and other bloggers in and around LA. If there's anyone staying around the LA area, please leave me a comment, or email me, and we can take it from there.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-7995488381947940605?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/7995488381947940605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=7995488381947940605' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/7995488381947940605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/7995488381947940605'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2006/11/america-calling.html' title='America Calling'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-114001684949274179</id><published>2006-02-15T20:05:00.000+05:30</published><updated>2006-10-21T20:12:04.544+05:30</updated><title type='text'>Interviewing UI Designers</title><content type='html'>Since we are in the process of building a team of &lt;abbr title="User Interface"&gt;UI&lt;/abbr&gt; designers at &lt;a href="http://www.iventa.com/" title="Iventa"&gt;work&lt;/a&gt;, I have been assigned the task of conducting interviews to decide on potential candidates. Today, I held my first few rounds of interviews. Until today, I have never realized how entertaining an interview can be.&lt;hr /&gt;&lt;span class="Speaker"&gt;Me:&lt;/span&gt; So, on a scale of 1 to 10, how do you rate your CSS skills?&lt;br /&gt;&lt;span class="Speaker"&gt;She:&lt;/span&gt; 6, at least. (smile)&lt;br /&gt;&lt;span class="Speaker"&gt;Me:&lt;/span&gt; Nice. 6 is not bad. So, what does CSS stand for?&lt;br /&gt;&lt;span class="Speaker"&gt;She:&lt;/span&gt; Cascading Style Sheets&lt;br /&gt;&lt;span class="Speaker"&gt;Me:&lt;/span&gt; Ok. Why are they called 'cascading' style sheets?&lt;br /&gt;&lt;span class="Speaker"&gt;She:&lt;/span&gt; Because you can cascade it onto multiple pages.&lt;hr /&gt;&lt;span class="Speaker"&gt;Me:&lt;/span&gt; So, I need to write a JavaScript snippet that can read a user's inputs in a form, prepare a text file, and save it on the user's desktop. Can I do this using JavaScript?&lt;br /&gt;&lt;span class="Speaker"&gt;Him:&lt;/span&gt; Sure!&lt;br /&gt;&lt;span class="Speaker"&gt;Me:&lt;/span&gt; (understandably surprised) Can you show me the code?&lt;br /&gt;&lt;span class="Speaker"&gt;Him:&lt;/span&gt; Sure! (starts scribbling something down, but gets stuck)&lt;br /&gt;&lt;span class="Speaker"&gt;Me:&lt;/span&gt; (probing) Are you sure this can be done using JavaScript again?&lt;br /&gt;&lt;span class="Speaker"&gt;Him:&lt;/span&gt; Yeah, I'm pretty sure.&lt;br /&gt;&lt;span class="Speaker"&gt;Me:&lt;/span&gt; Have you seen any examples of this before?&lt;br /&gt;&lt;span class="Speaker"&gt;Him:&lt;/span&gt; Yeah. We have used similar things in our previous organization.&lt;hr /&gt;&lt;span class="Speaker"&gt;Me:&lt;/span&gt; How do I add a style sheet to my HTML document?&lt;br /&gt;&lt;span class="Speaker"&gt;Him:&lt;/span&gt; Simple. You click on 'Insert' on the menu bar, and click on "Style sheet".&lt;br /&gt;&lt;span class="Speaker"&gt;Me:&lt;/span&gt; No, I meant by hand-coding in markup&lt;br /&gt;&lt;span class="Speaker"&gt;Him:&lt;/span&gt; Yeah. You can do it that way too.&lt;br /&gt;&lt;span class="Speaker"&gt;Me:&lt;/span&gt; Yeah, that's what I'm asking. How do you do it?&lt;br /&gt;&lt;span class="Speaker"&gt;Him:&lt;/span&gt; You should use the right tag for that purpose.&lt;br /&gt;&lt;span class="Speaker"&gt;Me:&lt;/span&gt; Which is the right tag for this purpose?&lt;br /&gt;&lt;span class="Speaker"&gt;Him:&lt;/span&gt; (thinks for some time, but can't come up with anything)&lt;br /&gt;&lt;span class="Speaker"&gt;Me:&lt;/span&gt; (trying to help him out) Are you familiar with the link and style tags? What do they do?&lt;br /&gt;&lt;span class="Speaker"&gt;Him:&lt;/span&gt; You use the style tag for attaching style sheets, and the link tag for creating links.&lt;hr /&gt;&lt;span class="Speaker"&gt;Me:&lt;/span&gt; Allright, how good are you at JavaScript?&lt;br /&gt;&lt;span class="Speaker"&gt;She:&lt;/span&gt; Very good.&lt;br /&gt;&lt;span class="Speaker"&gt;Me:&lt;/span&gt; That's quite a relief. So, what is the DOM?&lt;br /&gt;&lt;span class="Speaker"&gt;She:&lt;/span&gt; (thinks for some time) I'm not really sure. I've heard that for the first time.&lt;hr /&gt;&lt;span class="Speaker"&gt;Me:&lt;/span&gt; Is JavaScript an Object Oriented language, or is it a Procedural language? Or is it some weird mix of both? Or is it neither?&lt;br /&gt;&lt;span class="Speaker"&gt;Him:&lt;/span&gt; I did not understand the question. Could you please tell me what is 'Object Oriented'?&lt;hr /&gt;&lt;span class="Speaker"&gt;Me:&lt;/span&gt; So, about image editing, when would you use the GIF format, and when would you use the JPG format?&lt;br /&gt;&lt;span class="Speaker"&gt;She:&lt;/span&gt; I'll use the GIF format for making animations, and the JPG for static images.&lt;br /&gt;&lt;span class="Speaker"&gt;Me:&lt;/span&gt; I meant static images itself. Which format will you use, and on what basis will you decide?&lt;br /&gt;&lt;span class="Speaker"&gt;She:&lt;/span&gt; Static images? I'll use the JPG format.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-114001684949274179?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/114001684949274179/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=114001684949274179' title='17 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/114001684949274179'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/114001684949274179'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2006/02/interviewing-ui-designers.html' title='Interviewing UI Designers'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-113810586435604289</id><published>2006-01-24T17:52:00.000+05:30</published><updated>2006-10-21T20:12:04.462+05:30</updated><title type='text'>Say Hi To JSON</title><content type='html'>&lt;p&gt;At least one good thing about getting low site hits is that every small spike in traffic is noticeable. One such spike I got recently was from &lt;a href="http://discuss.joelonsoftware.com/default.asp?off.9.294825.28"&gt;the Off Topic forum at Joel On Software&lt;/a&gt;. &lt;a href="http://www.whispersinthedark.com/"&gt;Mark Warner&lt;/a&gt; agrees that using JavaScript as the return value of an Ajax call is a great way to exchange data between the server and client.&lt;/p&gt;&lt;p&gt;At &lt;a href="http://www.iventa.com/"&gt;Iventa&lt;/a&gt;, I'm currently working with a team of very talented individuals in developing a next-generation Web 2.0 application that does some really cool stuff. Needless to say, Ajax technologies are an important part of our interface design. Even if we don’t realize it, we have turned out to use exactly the same architecture that &lt;a href="http://www.adaptivepath.com/publications/essays/archives/000385.php"&gt;Jessie James Garret had talked about&lt;/a&gt; some time ago in his now-famous article. With one significant difference, though. We are still not using XML for transferring data. We don't need the X in Ajax!&lt;/p&gt;&lt;p&gt;What we are using, though, is &lt;abbr title="JavaScript Object Notation"&gt;JSON&lt;/abbr&gt;. JavaScript Object Notation might not be new to most people here, and it isn't rocket science either. Unfortunately, there's not enough information on the Internet that talks about using JSON well. So, well, here goes: &lt;strong&gt;A short tutorial on using JSON for Ajax&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;We are using ASP.Net 2.0 as the core server-side technology. Personally, I hate anything to do with Microsoft, but I guess business decisions prevail over personal preferences. However, this blog is mine, and I will talk about whatever the hell I like to talk about, and I hate Microsoft, so we are not going to talk about ASP.Net here. We shall just talk about the JavaScript side of things here.&lt;/p&gt;&lt;p&gt;That said, the server is just as important in an Ajax call as the client. Usually, one would use a framework that would let one make "client callbacks" on the server, but this is not necessarily the only way to transmit Ajax data. One could use a more barebones language like PHP directly without any frameworks to do just that – in fact if your site uses very few Ajax calls it is probably better to avoid an Ajax framework anyway.&lt;/p&gt;&lt;p&gt;Back to JSON. So, when we make an Ajax call using JavaScript, the server side script fetches the data we have requested (which could be from a database or from XML files, or any other kind of storage medium). The next step would be to convert it to a format that we can use on the client. This is where JSON kicks in.&lt;/p&gt;&lt;p&gt;Here’s how a typical JSON string would look. I’ve added line-breaks for clarity.&lt;/p&gt;&lt;code&gt;{&lt;br /&gt;&amp;nbsp;"UserInfo": {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;"id": "100",&lt;br /&gt;&amp;nbsp;&amp;nbsp;"firstName": "Rakesh",&lt;br /&gt;&amp;nbsp;&amp;nbsp;"lastName": "Pai",&lt;br /&gt;&amp;nbsp;&amp;nbsp;"emailAddress": "spamme@spammer.net"&lt;br /&gt;&amp;nbsp;},&lt;br /&gt;&amp;nbsp;"MembershipInfo": {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;"JoinDate": "2/31/2006",&lt;br /&gt;&amp;nbsp;&amp;nbsp;"MemberType": "3"&lt;br /&gt;&amp;nbsp;}&lt;br /&gt;}&lt;/code&gt;&lt;p&gt;Now, let’s say that I have a JavaScript function defined on the client, already available in a JavaScript include that uses this function as a parameter. Most frameworks will let you define which function will be called. If not, an approach similar to &lt;a href="http://piecesofrakesh.blogspot.com/2005/01/why-xml-in-xmlhttprequest.html"&gt;what I had talked about before&lt;/a&gt; can be used.&lt;/p&gt;&lt;p&gt;So, the function will look as follows:&lt;/p&gt;&lt;code&gt;function showUserDetails(serializedObject) {&lt;br /&gt;&amp;nbsp;objResponse = eval("(" + serializedObject + ")");&lt;br /&gt;&lt;br /&gt;&amp;nbsp;// objResponse can now be used as an object with its properties set.&lt;br /&gt;&amp;nbsp;alert("User’s first name is " + objResponse.UserInfo.firstName);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;// Process the object as required&lt;br /&gt;&amp;nbsp;...&lt;br /&gt;}&lt;/code&gt;&lt;p&gt;See how easy it is to use the data coming from the server? JSON makes it amazingly easy to get the data down from the server, create a neat object out of the data that has come in, and consume it the way you want to. The object, of course, can be rather complex, allowing for exchange of very complex data between the server and the browser.&lt;/p&gt;&lt;p&gt;This might not be the most efficient way of doing things. The comments are open for opinions.&lt;/p&gt;&lt;div class="Previously"&gt;Previously&lt;ul&gt;&lt;li&gt;&lt;a href="http://piecesofrakesh.blogspot.com/2005/01/why-xml-in-xmlhttprequest.html" title="Why XML In XMLHttpRequest"&gt;Why XML In XMLHttpRequest&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-113810586435604289?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/113810586435604289/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=113810586435604289' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/113810586435604289'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/113810586435604289'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2006/01/say-hi-to-json.html' title='Say Hi To JSON'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-113557671048702215</id><published>2005-12-26T11:10:00.000+05:30</published><updated>2006-10-21T20:12:04.380+05:30</updated><title type='text'>Back In Action</title><content type='html'>&lt;blockquote&gt;For the record, I never stopped blogging. I just took a three and a half month vacation.&lt;/blockquote&gt;&lt;p&gt;There has been a lot going on in the last couple of weeks. I've missed blogging so much, but it has been hard to even get to see how my blog looks lately. My incoming links have not increased at the same pace as it used to. My hit count has hit an all time low. Google is the only one hitting my site (other than a few guys who come from blogs where I leave an odd comment). The good times had stopped rolling.&lt;/p&gt;&lt;p&gt;All of that is about to change. I shall now, as a rule, dish out posts more frequently, and try to remain focussed on the topic. (Did you notice that none of my recent posts had anything to do with web design?)&lt;/p&gt;&lt;p&gt;To start, here's a (partial) list of things that have happened to me over the last couple of months.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;I've quit my job at &lt;a href="http://www.hsbcinvestments.co.in/"&gt;HSBC Asset Management&lt;/a&gt;. I don't want to say bad things about my previous employer here right now. I might change my mind.&lt;/li&gt;&lt;li&gt;I've joined a small company called &lt;a href="http://www.iventa.com/"&gt;Iventa Corporation&lt;/a&gt; as a &lt;q&gt;Team Lead - User Interface Design and Integration&lt;/q&gt;.&lt;/li&gt;&lt;li&gt;I've never thought that work can be as much fun, thanks to a great team and an awesome work culture at Iventa. (And I'm not just saying this because my employer might be watching this blog right now.)&lt;/li&gt;&lt;li&gt;I've started growing a paunch. It's hard work, but it seems to be working.&lt;/li&gt;&lt;li&gt;My computer - Hangy - has died multiple times, and has usually come back alive. She has been asking for a lot of my attention lately.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;There's so much more I could add to that list. The last couple of months have been action-packed. But the point of this post is to remind you that this blog is not dead. It has, in fact, just sprung back to life!&lt;/p&gt;&lt;p&gt;PS: Thank you for all those lovely mails asking me to get back to writing. Your mails mean a lot to me. Thank you again. (You know who you are.)&lt;/p&gt;&lt;p&gt;PPS: Almost forgot! Wish you a Merry Christmas and a great New Year! Keep Partyin'!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-113557671048702215?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/113557671048702215/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=113557671048702215' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/113557671048702215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/113557671048702215'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/12/back-in-action.html' title='Back In Action'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-112593989632589423</id><published>2005-09-19T21:40:00.000+05:30</published><updated>2006-10-21T20:12:04.105+05:30</updated><title type='text'>Google Indexes The Future</title><content type='html'>I love Google, if you haven't gathered from my blog already. But now I love it even more. If you haven't checked out &lt;a href="http://desktop.google.com/"&gt;Google Desktop&lt;/a&gt;, you should. What is really cool about it, is that it even indexes files you haven't created yet, so that you can search through it. It makes for a really powerful search, since you can get documents from the future today. Take a look at the screenshot of the indexing status if you don't believe me.&lt;br /&gt;&lt;br /&gt;&lt;a href='http://photos1.blogger.com/img/77/1572/1024/Google-searches-the-future.jpg'&gt;&lt;img border='0' style='border:1px solid #AAAAAA; margin:2px' src='http://photos1.blogger.com/img/77/1572/400/Google-searches-the-future.jpg'&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Google Indexes the Future&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-112593989632589423?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/112593989632589423/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=112593989632589423' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/112593989632589423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/112593989632589423'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/09/google-indexes-future.html' title='Google Indexes The Future'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-112593988165779870</id><published>2005-09-05T22:34:00.000+05:30</published><updated>2006-10-21T20:12:04.019+05:30</updated><title type='text'>Yellow Sun, Yellow Plastic</title><content type='html'>&lt;a href='http://photos1.blogger.com/img/77/1572/1024/Yellow-Sun%2C-Yellow-Plastic1.jpg'&gt;&lt;img border='0' style='border:1px solid #AAAAAA; margin:2px' src='http://photos1.blogger.com/img/77/1572/400/Yellow-Sun%2C-Yellow-Plastic1.jpg'&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Yellow Sun, Yellow Plastic&lt;/p&gt;I was in Goa a couple of days ago for a "official trip". Though the trip was largely hectic, I did manage to get a shot or two.&lt;br /&gt;&lt;br /&gt;This pic was shot at a desolate stretch of beach at Canaconam, Goa.&lt;br /&gt;&lt;br /&gt;And sorry for the corny title. Creativity eludes me at the end of a tiring day.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-112593988165779870?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/112593988165779870/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=112593988165779870' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/112593988165779870'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/112593988165779870'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/09/yellow-sun-yellow-plastic_05.html' title='Yellow Sun, Yellow Plastic'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-112540620808163924</id><published>2005-08-30T18:19:00.000+05:30</published><updated>2006-10-21T20:12:03.845+05:30</updated><title type='text'>One Year...</title><content type='html'>...and counting.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-112540620808163924?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/112540620808163924/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=112540620808163924' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/112540620808163924'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/112540620808163924'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/08/one-year.html' title='One Year...'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-112473186549131809</id><published>2005-08-22T22:46:00.000+05:30</published><updated>2006-10-21T20:12:03.760+05:30</updated><title type='text'>When Referrals Are Funny</title><content type='html'>Rather frequently, people enter weird things in the search-box in search engines. Very rarely some of those results point to my site. Almost always I note down those search terms. Here’s a partial compilation of the funny search terms that have landed people on this blog.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;MSN:&lt;/strong&gt; Man converting lions to Christianity – &lt;em&gt;And a man with a lot of time at hand.&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Yahoo:&lt;/strong&gt; Apologize for electing Bush – &lt;em&gt;What kind of search string is that!&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Yahoo:&lt;/strong&gt; Why you always feel smarter after a couple of beers&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Google:&lt;/strong&gt; Google hacks Jaipur – &lt;em&gt;And I thought Google was not an evil empire.&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Google:&lt;/strong&gt; Picture of devil – &lt;em&gt;for some reason, Google repeatedly thinks that I’m some authority in pics of the devil.&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Google:&lt;/strong&gt; Kitchen designer in Mumbai – &lt;em&gt;Why on earth is Google sending this guy to my site?&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Google:&lt;/strong&gt; Censored Marathi sex articles – &lt;em&gt;I can understand where this guy comes from, but it’s where he comes to that surprises me.&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Google:&lt;/strong&gt; Attack of the nerds – &lt;em&gt;yes, I use my site primarily to congregate nerds so that we can take over the world.&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Google:&lt;/strong&gt; Parvathi Goddess MP3 – &lt;em&gt;Wow! I didn’t know she was into modern music delivery formats.&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Google:&lt;/strong&gt; Haven Pai – &lt;em&gt;I have no clue what that means.&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Google:&lt;/strong&gt; Buildings with CSS in Mumbai – &lt;em&gt;Yeah. It’s CSS that makes buildings look good.&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Google:&lt;/strong&gt; Web page not responsive in the cash – &lt;em&gt;Well, ever considered having a business model?&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Google:&lt;/strong&gt; What is the search string to turn up camera feeds on Google – &lt;em&gt;someone actually typed this. In Google. A search for a search. Cool, huh?&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Google:&lt;/strong&gt; Food preparation using microwave oven and Tamil fonts – &lt;em&gt;Should make for a spicy meal.&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Google:&lt;/strong&gt; Rakesh is God – &lt;em&gt;I know that already.&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Google:&lt;/strong&gt; Illegal Rakesh – &lt;em&gt;Please read the point above.&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Yahoo:&lt;/strong&gt; Gravitation cannot be held responsible for people falling in love – &lt;em&gt;Of course. Only stupidity can.&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Yahoo:&lt;/strong&gt; Atlanta booty shake – &lt;em&gt;Sorry to disappoint you on my site, mate.&lt;/em&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-112473186549131809?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/112473186549131809/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=112473186549131809' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/112473186549131809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/112473186549131809'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/08/when-referrals-are-funny.html' title='When Referrals Are Funny'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-112256284133312069</id><published>2005-07-28T20:30:00.000+05:30</published><updated>2006-10-21T20:12:03.650+05:30</updated><title type='text'>Mumbai Under Water</title><content type='html'>Mumbai is recovering fast from &lt;a href="http://info.indiatimes.com/pg/Floods/home.htm"&gt;the downpour two days ago&lt;/a&gt;. You may want to &lt;a href="http://www.flickr.com/photos/36343456@N00/29200230/"&gt;see&lt;/a&gt; &lt;a href="http://www.flickr.com/photos/46798425@N00/29028154/"&gt;pics&lt;/a&gt; &lt;a href="http://www.flickr.com/photos/trayser/sets/652012/"&gt;of&lt;/a&gt; &lt;a href="http://www.flickr.com/photos/greyarea/tags/floods/"&gt;it&lt;/a&gt; &lt;a href="http://www.flickr.com/photos/70715945@N00/sets/647485/"&gt;at&lt;/a&gt; &lt;a href="http://www.flickr.com/photos/28713479@N00/tags/rains/"&gt;flickr&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;It took me two days to come back home, but I'm fine. Thanks everyone for those mails. Everyone I know is fine too. I hope everyone you know is fine.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-112256284133312069?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/112256284133312069/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=112256284133312069' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/112256284133312069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/112256284133312069'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/07/mumbai-under-water.html' title='Mumbai Under Water'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-112132917600531892</id><published>2005-07-14T13:21:00.000+05:30</published><updated>2006-10-21T20:12:03.545+05:30</updated><title type='text'>Not Jobless Anymore</title><content type='html'>I just picked up my offer letter from &lt;a href="http://www.hsbcinvestments.co.in/"&gt;HSBC Asset Management&lt;/a&gt; yesterday, for the position of &lt;q&gt;Executive - Web Design&lt;/q&gt;.&lt;br /&gt;&lt;br /&gt;I still get to continue doing my freelance projects as I was, though an immediate slow-down is inevitable. I've been doing it for more than two years now, and simply quitting would be impossible.&lt;br /&gt;&lt;br /&gt;I am still to settle down at the new job with the new work timings (I'll &lt;em&gt;actually&lt;/em&gt; have to get up in the morning), new bunch of work-related problems (for starters, I'll have to make an hour long train commute to work everyday) and new dress code (I understand I can't code in my underwear anymore). I start the routine on Monday.&lt;br /&gt;&lt;br /&gt;I hope this means that I'll get a lot more time at hand to do more reading (my feed reader indicates that I have more than 4000 unread items in my box), and writing (and you thought I had plans to wrap up this blog soon). I will also hopefully get more material on and exposure to real-world web-based issues.&lt;br /&gt;&lt;br /&gt;Anyway, for now, it's time for celebrations. Time for hitting that bottle of beer. Again. After all, it's a new excuse.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-112132917600531892?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/112132917600531892/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=112132917600531892' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/112132917600531892'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/112132917600531892'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/07/not-jobless-anymore.html' title='Not Jobless Anymore'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-111962275055808326</id><published>2005-06-24T19:49:00.000+05:30</published><updated>2006-10-21T20:12:02.259+05:30</updated><title type='text'>Chainsaw In Red And Blue</title><content type='html'>&lt;a href='http://photos1.blogger.com/img/77/1572/1024/Chainsaw.jpg'&gt;&lt;img border='0' style='border:1px solid #AAAAAA; margin:2px' src='http://photos1.blogger.com/img/77/1572/400/Chainsaw.jpg'&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Chainsaw in blue plastic wraps&lt;/p&gt;So, two days ago at 3 in the morning, the huge tree opposite my house came crashing down with the wind and rain, breaking a compound wall, shattering a couple of windows in my apartment, and crushing two cars among other things. Fortunately, other than one really dumb guy who ran toward the broken glass to see what happened, no one was hurt. The fire-brigade was there in minutes and chainsawed the tree into managable chunks to clean the place up.&lt;br /&gt;&lt;br /&gt;I got this pic when they were busy planning their strategies.&lt;br /&gt;&lt;br /&gt;For those interested, I have a &lt;a href="http://www.flickr.com/photos/rakesh/tags/fallentree/"&gt;couple of more pics on Flickr&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-111962275055808326?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/111962275055808326/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=111962275055808326' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111962275055808326'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111962275055808326'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/06/chainsaw-in-red-and-blue.html' title='Chainsaw In Red And Blue'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-111840462540278431</id><published>2005-06-10T17:42:00.000+05:30</published><updated>2006-10-21T20:12:02.174+05:30</updated><title type='text'>On The Edge Of The World</title><content type='html'>&lt;div style="text-align: center;"&gt;&lt;a href='http://photos1.blogger.com/img/77/1572/1024/The-Edge-Of-The-World.jpg'&gt;&lt;img border='0' style='border:1px solid #AAAAAA; margin:2px' src='http://photos1.blogger.com/img/77/1572/400/The-Edge-Of-The-World.jpg'&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class="ImageCaption"&gt;The Edge Of The World&lt;/p&gt;The funny thing about computer games is that every &lt;q&gt;map&lt;/q&gt; has an edge. It's called &lt;q&gt;The Edge Of The World&lt;/q&gt;. It always looks like a hazy area fading into blackness. An area you just can't access.&lt;br /&gt;&lt;br /&gt;If I was living my life in a computer game as a game character, I'd know it wasn't real if I came to The Edge Of The World.&lt;br /&gt;&lt;br /&gt;This pic was shot in Podanur, not too far from where &lt;a href="http://piecesofrakesh.blogspot.com/2005/05/communication.html"&gt;this pic&lt;/a&gt; was shot.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-111840462540278431?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/111840462540278431/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=111840462540278431' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111840462540278431'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111840462540278431'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/06/on-edge-of-world.html' title='On The Edge Of The World'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-111796769726580903</id><published>2005-06-05T16:04:00.000+05:30</published><updated>2006-10-21T20:12:02.086+05:30</updated><title type='text'>What Would You Do?</title><content type='html'>Let's say you are a freelancing web developer and designer. You take pride in the quality and technology of the stuff you deliver. You like to work on the bleeding edge of web technology.  You will go out of your way if necessary, to implement solutions that are apt for the client's business. You like to study their way of working and the goals of their site, and prepare a solution that makes good sense for their business, both technologically and economically.&lt;br /&gt;&lt;br /&gt;You are just starting out with your career. You have no money. You are almost completely broke. You could do with any project that will bring in money.&lt;br /&gt;&lt;br /&gt;A prospective client from a wealthy country approaches you with a great deal. He is willing to pay you outrageous amounts of money for getting his website developed. There's only one hitch.&lt;br /&gt;&lt;br /&gt;The site contains sexually suggestive content.&lt;br /&gt;&lt;br /&gt;What Would You Do?&lt;br /&gt;&lt;br /&gt;PS. If you are wondering, I bailed out. I might be the century's biggest fool, but sometimes money isn't everything, I guess. Let's just say I didn't do it because of &lt;q&gt;ideological issues&lt;/q&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-111796769726580903?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/111796769726580903/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=111796769726580903' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111796769726580903'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111796769726580903'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/06/what-would-you-do.html' title='What Would You Do?'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-111753196378085338</id><published>2005-05-31T15:10:00.000+05:30</published><updated>2006-10-21T20:12:02.013+05:30</updated><title type='text'>Gone Fishing</title><content type='html'>&lt;a href='http://photos1.blogger.com/img/77/1572/1024/Gone-Fishing.jpg'&gt;&lt;img border='0' style='border:1px solid #AAAAAA; margin:2px' src='http://photos1.blogger.com/img/77/1572/400/Gone-Fishing.jpg'&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Gone Fishing&lt;/p&gt;This photograph, shot at a beach in Mahe, Kerala, is a panorama composed of 3 photographs arranged in a row. To the extreme right, is a fisherman grabbing his catch for the day.&lt;br /&gt;&lt;br /&gt;I was wondering how the panorama would turn out, because of varying exposures in the different frames, the dynamic nature of the sea and the waves, a slight haze in the air, and no real subject. I'll let you judge that, though.&lt;br /&gt;&lt;br /&gt;(Yes, I know I could have done a better job of stitching them together, but I wanted to give the Adobe Photoshop CS's Photomerge function a shot. It took all of 5 minutes to stitch them together.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-111753196378085338?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/111753196378085338/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=111753196378085338' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111753196378085338'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111753196378085338'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/05/gone-fishing.html' title='Gone Fishing'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-111685774061267179</id><published>2005-05-27T18:00:00.000+05:30</published><updated>2006-10-21T20:12:01.942+05:30</updated><title type='text'>The Real Problem With Ajax</title><content type='html'>The real problem with &lt;abbr title="Asynchronous JavaScript And XML"&gt;Ajax&lt;/abbr&gt; is that you have to stop thinking of the process of getting information as a linear sequential process, and start thinking of the browser as a true application platform.&lt;br /&gt;&lt;br /&gt;Now, only if &lt;em&gt;that&lt;/em&gt; problem was easy to solve.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-111685774061267179?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/111685774061267179/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=111685774061267179' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111685774061267179'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111685774061267179'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/05/real-problem-with-ajax.html' title='The Real Problem With Ajax'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-111677125719618658</id><published>2005-05-22T19:44:00.000+05:30</published><updated>2006-10-21T20:12:01.860+05:30</updated><title type='text'>Communication</title><content type='html'>&lt;div style="text-align: center"&gt;&lt;a href='http://photos1.blogger.com/img/77/1572/1024/Communication-In-Solitude.jpg'&gt;&lt;img border='0' style='border:1px solid #AAAAAA; margin:2px' src='http://photos1.blogger.com/img/77/1572/400/Communication-In-Solitude.jpg'&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class="ImageCaption"&gt;Communication&lt;/p&gt;&lt;br /&gt;This image was shot in a small town called Podanur, about 15 minutes drive from Coimbatore, Tamil Nadu.&lt;br /&gt;&lt;br /&gt;By the way, I wanted to know what tools you use to correct spherical aberrations. Could you please leave me suggestions in the comments? Thanks.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-111677125719618658?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/111677125719618658/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=111677125719618658' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111677125719618658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111677125719618658'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/05/communication.html' title='Communication'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-111599277996418778</id><published>2005-05-13T19:25:00.000+05:30</published><updated>2006-10-21T20:12:01.760+05:30</updated><title type='text'>You Know When It Happens...</title><content type='html'>Today I was at the barbers, and he said that he wouldn't cut my hair too short, because "it would show".&lt;br /&gt;&lt;br /&gt;You know when it happens...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-111599277996418778?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/111599277996418778/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=111599277996418778' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111599277996418778'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111599277996418778'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/05/you-know-when-it-happens.html' title='You Know When It Happens...'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-111592206521341546</id><published>2005-05-12T23:51:00.000+05:30</published><updated>2006-10-21T20:12:01.684+05:30</updated><title type='text'>Back From God's Own Country</title><content type='html'>&lt;a href='http://photos1.blogger.com/img/77/1572/1024/Kerala-backwaters.jpg'&gt;&lt;img border='0' style='border:1px solid #AAAAAA; margin:2px' src='http://photos1.blogger.com/img/77/1572/400/Kerala-backwaters.jpg'&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Kerala Backwaters&lt;/p&gt;Just got back from Kerala, so I'm making a quick post. This image was shot at the backwaters in Kerala somewhere about an hour's drive from Ernakulam.&lt;br /&gt;&lt;br /&gt;Oh, I had a great trip too, if you have to ask. Kinda tired. I'll post something more soon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-111592206521341546?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/111592206521341546/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=111592206521341546' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111592206521341546'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111592206521341546'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/05/back-from-gods-own-country.html' title='Back From God&apos;s Own Country'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-111518172265729672</id><published>2005-05-04T10:08:00.000+05:30</published><updated>2006-10-21T20:12:01.615+05:30</updated><title type='text'>I'll Be Right Back</title><content type='html'>As if I haven't been ignoring this blog enough, I'll be taking a 10 day break to go to my home-town, Kerala.&lt;br /&gt;&lt;br /&gt;When I'm back, I promise to have LOADS of photographs, website design talk and other tech stuff. It's been sitting in my mind/drafts for a long time now, but time has not been a good friend lately.&lt;br /&gt;&lt;br /&gt;Until next time!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-111518172265729672?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/111518172265729672/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=111518172265729672' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111518172265729672'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111518172265729672'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/05/ill-be-right-back.html' title='I&apos;ll Be Right Back'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-111349590826519228</id><published>2005-04-14T21:55:00.000+05:30</published><updated>2006-10-21T20:12:01.544+05:30</updated><title type='text'>Two Women And A Kid</title><content type='html'>&lt;a href='http://photos1.blogger.com/img/77/1572/1024/Two-women-and-a-kid.jpg'&gt;&lt;img border='0' style='border:1px solid #AAAAAA; margin:2px' src='http://photos1.blogger.com/img/77/1572/400/Two-women-and-a-kid.jpg'&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Two women and a kid&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-111349590826519228?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/111349590826519228/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=111349590826519228' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111349590826519228'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111349590826519228'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/04/two-women-and-kid.html' title='Two Women And A Kid'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-111295257458352538</id><published>2005-04-08T15:35:00.000+05:30</published><updated>2006-10-21T20:12:01.476+05:30</updated><title type='text'>What Extensions Do You Use?</title><content type='html'>I have quite a few extensions installed for my Firefox, some of which I cannot do without, and some others that make me wonder what I was thinking when I installed them. Here's a list, in no particular order.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;For the surfer in me&lt;/strong&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;GMail Notifier&lt;/em&gt; - I've almost substituted this by a Konfabulator widget that does a much better job, but this is still rather useful.&lt;/li&gt;&lt;li&gt;&lt;em&gt;Bloglines Toolkit&lt;/em&gt; - Because I'm such a Bloglines fan.&lt;/li&gt;&lt;li&gt;&lt;em&gt;Mouse Gestures&lt;/em&gt; - I admit I'm lazy. And that this is really cool.&lt;/li&gt;&lt;li&gt;&lt;em&gt;LiveLines&lt;/em&gt; - I never really liked LiveBookmarks anyway.&lt;/li&gt;&lt;li&gt;&lt;em&gt;Dictionary Search&lt;/em&gt; - Cause my English sucks.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;strong&gt;For the web-developer in me&lt;/strong&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;DOM Inspector&lt;/em&gt; - Always nice to have this around, though I've still to learn to use this well.&lt;/li&gt;&lt;li&gt;&lt;em&gt;ieview&lt;/em&gt;- Saves me a lot of URL copy-pasting to check my designs in IE.&lt;/li&gt;&lt;li&gt;&lt;em&gt;Web Developer&lt;/em&gt; - Simply indespensible. It's probably the single most important reason to develop for Firefox, second only to the whole standards thing. This is probably more important than even a good code editor!&lt;/li&gt;&lt;li&gt;&lt;em&gt;ColorZilla&lt;/em&gt; - For the times when I've forgotten my color codes, or am too lazy to go through that dreaded CSS file again. Or when you just want to steal that cool color. (Wait. Did I just say that?)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;strong&gt;For I-don't-know-what&lt;/strong&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;Google-Preview&lt;/em&gt; - I actually liked this at one time, and was actually using it, until realization dawned upon me that this takes up more bandwidth than it deserves.&lt;/li&gt;&lt;li&gt;&lt;em&gt;Mozilla Calendar&lt;/em&gt; - It's really cool. For what?&lt;/li&gt;&lt;li&gt;&lt;em&gt;BugMeNot&lt;/em&gt; - I haven't tried, but does this work with my pr0n sites?&lt;/li&gt;&lt;li&gt;&lt;em&gt;SpellBound&lt;/em&gt; - Neat idea, but I only wish it wasn't so clunky.&lt;/li&gt;&lt;li&gt;&lt;em&gt;fireFTP&lt;/em&gt; - I almost fell in love with Firefox all over again thanks to this extension, until I found a bug that didn't let me see my .htaccess file. And, boy, do I need to play with my .htaccess a lot!&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Which are your favourite extensions? Maybe I should use some that you are using to simplify my work? Share your list in the comments.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-111295257458352538?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/111295257458352538/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=111295257458352538' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111295257458352538'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111295257458352538'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/04/what-extensions-do-you-use_08.html' title='What Extensions Do You Use?'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-111250726865081406</id><published>2005-04-03T11:09:00.000+05:30</published><updated>2006-10-21T20:12:01.336+05:30</updated><title type='text'>Call Center Chaos</title><content type='html'>I was on the floor laughing when I saw this video of an episode of &lt;q&gt;The Tonight Show&lt;/q&gt; with Conan O'Brian. It is funny enough to devote an entire post to it, even if short, so go &lt;a href="http://methodshop.com/tech/articles/conan/conan2.shtml"&gt;download yourself a copy&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I find it interesting that people are finding humor in this now, as opposed to the initial hatred towards these jobs.&lt;br /&gt;&lt;br /&gt;On a side note, I picked up this video from &lt;a href="http://vikramtalks.blogspot.com/"&gt;a very close friend's blog&lt;/a&gt;. Vikram has only just started his blog, and promises to keep it good. Go over and say hi!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-111250726865081406?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/111250726865081406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=111250726865081406' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111250726865081406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111250726865081406'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/04/call-center-chaos.html' title='Call Center Chaos'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-111169167818399058</id><published>2005-03-25T00:44:00.000+05:30</published><updated>2006-10-21T20:12:01.264+05:30</updated><title type='text'>Lunch</title><content type='html'>&lt;a href='http://photos1.blogger.com/img/77/1572/1024/Lunch.jpg'&gt;&lt;img border='0' style='border:1px solid #AAAAAA; margin:2px' src='http://photos1.blogger.com/img/77/1572/400/Lunch.jpg'&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Lunch&lt;/p&gt;Lunch seemed interestingly photogenic today.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-111169167818399058?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/111169167818399058/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=111169167818399058' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111169167818399058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111169167818399058'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/03/lunch.html' title='Lunch'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-111142457038476958</id><published>2005-03-21T22:25:00.000+05:30</published><updated>2006-10-21T20:12:01.185+05:30</updated><title type='text'>Protesting To The Gods</title><content type='html'>After what seems like ages, I turned on television today, and happened to stop by at the local cable channel. The screen, instead of showing the latest Bollywood movie, showed scrolling text on a black background.&lt;br /&gt;&lt;blockquote&gt;Due to the sad demise of Mr. Sanjay Gupta (Cable Operator / Distributor) of New Bombay. We will unanimously keeping the cable channel shut in protest.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-111142457038476958?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/111142457038476958/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=111142457038476958' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111142457038476958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111142457038476958'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/03/protesting-to-gods.html' title='Protesting To The Gods'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-111031590440305209</id><published>2005-03-09T02:14:00.001+05:30</published><updated>2006-10-21T20:12:01.107+05:30</updated><title type='text'>Firefox's USP</title><content type='html'>During an idle conversation with a friend this afternoon:&lt;br /&gt;&lt;br /&gt;&lt;span class="Speaker"&gt;She&lt;/span&gt;: You know, these days I get pop-ups with Firefox.&lt;br /&gt;&lt;span class="Speaker"&gt;Me&lt;/span&gt;: Yeah I know. Those darn advertising guys. They've found a way around the pop-up blocker.&lt;br /&gt;&lt;span class="Speaker"&gt;She&lt;/span&gt;: But the pop-up blocker was the greatest thing about Firefox. I'm afraid there's not much difference left between Internet Explorer and Firefox this way.&lt;br /&gt;&lt;br /&gt;I considered starting an argument about standards, and how Firefox is going to save the world, but I knew that was futile. For the lay-person, Firefox gave a better experience when surfing. And now, that experience is threatened.&lt;br /&gt;&lt;br /&gt;She is terrifyingly correct.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-111031590440305209?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/111031590440305209/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=111031590440305209' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111031590440305209'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111031590440305209'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/03/firefoxs-usp_09.html' title='Firefox&apos;s USP'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-111022053990801330</id><published>2005-03-08T00:05:00.000+05:30</published><updated>2006-10-21T20:12:00.967+05:30</updated><title type='text'>Script Tag In Internet Explorer</title><content type='html'>After a sleepless night or two, I just discovered this bug in Internet Explorer the hard way.&lt;br /&gt;&lt;br /&gt;I was bascially including a JavaScript file in my &lt;abbr title="eXtensible HyperText Markup Language"&gt;XHTML&lt;/abbr&gt; document. The scripts in this file were meant to attach to my XHTML elements unobtrusively, and this file was a unit by itself. So I didn't have any JavaScript within my &lt;code&gt;script&lt;/code&gt; tags. This is how my tag looked.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;script language="javascript" type="text/javascript" src="script.js" /&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This works like a dream everywhere, except in the world's most popular browser. In &lt;abbr title="Internet Explorer"&gt;IE&lt;/abbr&gt;, the entire page is just blank! The markup is downloaded properly (I can see it when I view source), even my &lt;abbr title="Cascading Style Sheet"&gt;CSS&lt;/abbr&gt; &lt;code&gt;background-color&lt;/code&gt; is applied to the page, but there's absolutely nothing on it! I blamed my content-negotiation scripts first (I am serving &lt;abbr title="HyperText Markup Language"&gt;HTML&lt;/abbr&gt; Transitional to IE and XHTML everywhere else), and then on IE's support for CSS (I thought I made a grave little mistake somewhere). However, on removing this tag, everything worked fine in IE.&lt;br /&gt;&lt;br /&gt;Turns out, IE doesn't like the &lt;code&gt;script&lt;/code&gt; tags if they are using element minimization. I got the page rendering just as I intended by changing the tag to look like this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;script language="javascript" type="text/javascript" src="script.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Doing some research, I came across &lt;a href="http://lists.evolt.org/archive/Week-of-Mon-20020304/105951.html"&gt;this post in theList by Eric Vitiello&lt;/a&gt; which clarifies this more. Apparently the &lt;abbr title="Document Type Declaration"&gt;DTD&lt;/abbr&gt; declaration for the &lt;code&gt;script&lt;/code&gt; tag says &lt;code&gt;&amp;lt;!ELEMENT script (#PCDATA)&amp;gt;&lt;/code&gt;, and the XHTML specs says (&lt;a href="http://www.w3.org/TR/xhtml1/#guidelines"&gt;under Appendix C. 3&lt;/a&gt;): &lt;blockquote&gt;Given an empty instance of an element whose content model is not &lt;code&gt;EMPTY&lt;/code&gt; (for example, an empty title or paragraph) do not use the minimized form (e.g. use &lt;code&gt;&amp;lt;p&amp;gt; &amp;lt;/p&amp;gt;&lt;/code&gt; and not &lt;code&gt;&amp;lt;p /&amp;gt;&lt;/code&gt;).&lt;/blockquote&gt;So, I guess this isn't really a bug in IE. I'd think instead, that this is a bug in the DTD itself. The script tag doesn't &lt;em&gt;have&lt;/em&gt; to contain &lt;code&gt;#PCDATA&lt;/code&gt; (in fact, I consider it graceful if it doesn't), and forcing it is, well, stupid.&lt;br /&gt;&lt;br /&gt;For now, I am explicitly closing the script tag with a seperate closing tag, and everything seems to be working well. Does anyone have any idea about handling this better, preferably with minimized element closures?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-111022053990801330?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/111022053990801330/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=111022053990801330' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111022053990801330'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111022053990801330'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/03/script-tag-in-internet-explorer.html' title='Script Tag In Internet Explorer'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-111020601725455712</id><published>2005-03-07T20:03:00.000+05:30</published><updated>2006-10-21T20:12:00.896+05:30</updated><title type='text'>Knopfler Leaves A Mark</title><content type='html'>&lt;a href='http://photos1.blogger.com/img/77/1572/1024/Mark-Knopfler.jpg'&gt;&lt;img border='0' style='border:1px solid #AAAAAA; margin:2px' src='http://photos1.blogger.com/img/77/1572/400/Mark-Knopfler.jpg'&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Knopfler Leaves A Mark&lt;/p&gt;It was one hell of a night. We had to smuggle in the &lt;a href="http://www.mumbai-masala.com/hotspicy/vadapav.html"&gt;Vada Pavs&lt;/a&gt; and the Bacardis and the Wills and the matches and the ... well, you get the idea. But they managed to catch us when we were smuggling the water in. Damn! Had to waste a whole bottle!&lt;br /&gt;&lt;br /&gt;Anyway. I was hoping that he'd play some more of the Dire Straits and atleast one little song of &lt;a href="http://www.amazon.com/exec/obidos/redirect?tag=piecesofrakes-20&amp;amp;path=ASIN/B000002LKU/qid%3D1110205303/sr%3D11-1/ref%3Dsr%5F11%5F1/"&gt;The Notting Hillbillies&lt;/a&gt;, but I had to be happy with about 40% of his solos and the rest almost exclusively from Brothers In Arms and Money For Nothing. But who's complaining!&lt;br /&gt;&lt;br /&gt;Sorry for the cheezy pic. I &lt;em&gt;had&lt;/em&gt; clicked pics at the show, of course. (I had smuggled my cam in too.) But let's just say that the shots turned out to be a little shaky.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-111020601725455712?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/111020601725455712/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=111020601725455712' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111020601725455712'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/111020601725455712'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/03/knopfler-leaves-mark.html' title='Knopfler Leaves A Mark'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110987873006324862</id><published>2005-03-04T01:08:00.000+05:30</published><updated>2006-10-21T20:12:00.820+05:30</updated><title type='text'>Help Me Escape This!</title><content type='html'>&lt;a href='http://photos1.blogger.com/img/77/1572/1024/Help-Escape.jpg'&gt;&lt;img border='0' style='border:1px solid #AAAAAA; margin:2px' src='http://photos1.blogger.com/img/77/1572/400/Help-Escape.jpg'&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Help Me Escape!&lt;/p&gt;Yup, today is one of those days. I spent my last 10 minutes staring at my text editor, thinking that the syntax highlighting looked trippy. Then I got up to drink some water. When I came back I checked and double checked if my white-space and indenting was correct and consistent. Then I thought I'll get some chips from the kitchen. When I got back I started thinking how I can add more comments to the code to make it readable. Then I was deciding if asterisks work better than slashes as the thing you put before and after a line of comment in the code.&lt;br /&gt;&lt;br /&gt;I guess it's fair to say that I am having an utterly unproductive day today. Do you have such unproductive days too? What do you find yourself doing on such days?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110987873006324862?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110987873006324862/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110987873006324862' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110987873006324862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110987873006324862'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/03/help-me-escape-this.html' title='Help Me Escape This!'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110957105928937688</id><published>2005-02-28T11:38:00.000+05:30</published><updated>2006-10-21T20:12:00.744+05:30</updated><title type='text'>MotorShow @ Mumbai</title><content type='html'>Here are some of my &lt;a href="http://www.flickr.com/photos/rakesh/sets/139063/"&gt;pics from Flickr abouts the Motor Show&lt;/a&gt; I had been to recently in Bandra Kurla Complex, Mumbai.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align:center"&gt;&lt;a href="http://www.flickr.com/photos/rakesh/5520501/" title="Photo Sharing"&gt;&lt;img src="http://photos3.flickr.com/5520501_6981a670a3_m.jpg" width="240" height="180" alt="Skoda" /&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Skoda&lt;/p&gt;&lt;a href="http://www.flickr.com/photos/rakesh/5520464/" title="Photo Sharing"&gt;&lt;img src="http://photos3.flickr.com/5520464_3731921eb2_m.jpg" width="240" height="180" alt="Crazy Mod" /&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;One hell of a crazy mod&lt;/p&gt;&lt;a href="http://www.flickr.com/photos/rakesh/5520542/" title="Photo Sharing"&gt;&lt;img src="http://photos3.flickr.com/5520542_a2a9ee3300_m.jpg" width="240" height="180" alt="Vintage" /&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Isn't she beautiful!&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110957105928937688?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110957105928937688/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110957105928937688' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110957105928937688'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110957105928937688'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/02/motorshow-mumbai.html' title='MotorShow @ Mumbai'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110906084661087665</id><published>2005-02-22T13:44:00.000+05:30</published><updated>2006-10-21T20:12:00.666+05:30</updated><title type='text'>The Future, Now In Russian</title><content type='html'>One of my previous posts titled "&lt;a href="http://piecesofrakesh.blogspot.com/2005/01/web-applications-wave-of-future.html"&gt;Web Applications - The Wave Of The Future&lt;/a&gt;" has been &lt;a href="http://www.webmascon.com/topics/technologies/12a.asp"&gt;translated to Russian by Alexander Kachanov&lt;/a&gt;. I myself don't know Russian, but I think it's pretty cool to be able to read a post in a language of your choice after it has gone through a human translation.&lt;br /&gt;&lt;br /&gt;So, Russian audiences, head to his site if you prefer to read my post in Russian.&lt;br /&gt;&lt;br /&gt;Though I've been getting referals from non-english sites discussing my posts, this would be the first time that one of my posts has been translated to a non-english language.&lt;br /&gt;/me swells chest.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110906084661087665?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110906084661087665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110906084661087665' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110906084661087665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110906084661087665'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/02/future-now-in-russian.html' title='The Future, Now In Russian'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110841097840751227</id><published>2005-02-15T01:26:00.000+05:30</published><updated>2006-10-21T20:12:00.585+05:30</updated><title type='text'>Google and Flash</title><content type='html'>&lt;div style="text-align:center"&gt;&lt;a href='http://photos1.blogger.com/img/77/1572/1024/Google-Flash.jpg'&gt;&lt;img border='0' style='border:1px solid #AAAAAA; margin:2px' src='http://photos1.blogger.com/img/77/1572/400/Google-Flash.jpg'&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Google And Flash&lt;/p&gt;&lt;/div&gt;Now, this is toally surprising to me. I always thought that Flash was &lt;strong&gt;bad&lt;/strong&gt; for &lt;abbr title="Search Engine Optimization"&gt;SEO&lt;/abbr&gt;, but this search result has proved me completely wrong. I was doing a random &lt;a href="http://www.google.com/search?&amp;q=all%20your%20base%20are%20belong%20to%20us&amp;sourceid=firefox"&gt;search for "All your base are belong to us"&lt;/a&gt;, and the &lt;em&gt;first hit&lt;/em&gt; turned out to be a Flash file!&lt;br /&gt;&lt;br /&gt;I didn't know that Google indexes swf files at all. In fact, I always recommended &lt;em&gt;against&lt;/em&gt; using Flash for a site primarily for SEO reasons. Since when did Google start indexing Flash files?&lt;br /&gt;&lt;br /&gt;Even more interstingly, the little line below the main hit result link shows a link to "View as &lt;abbr title="HyperText Markup Language"&gt;HTML&lt;/abbr&gt;". Unfortunately, when I tried, none of these links worked. Looks like Google is broken there.&lt;br /&gt;&lt;br /&gt;This is really interesting. Not only is Google able to spider and index swf files, it is also able to potentially convert them to HTML files! How can Google access the content of the swf file? How can it sensibly convert that data to an HTML file? (Can someone please have a look at those "View as HTML" links and tell me what you see?) Has this been going on for some time now?&lt;br /&gt;&lt;br /&gt;Check it out for yourself. &lt;a href="http://www.google.com/search?hl=en&amp;lr=&amp;c2coff=1&amp;q=swf&amp;btnG=Search"&gt;Google swf&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Update:&lt;/strong&gt; It appears that I spoke too soon without adequate research. &lt;a href="http://google.blogspace.com/archives/001219.html"&gt;Google has been indexing Flash files&lt;/a&gt; for almost a year now. &lt;a href="http://www.google.com/search?q=skip+intro+filetype%3Aswf"&gt;Check it out&lt;/a&gt;! Even so, don't you think this Google-Flash thing deserves more attention? How come no one has been talking about it? Can someone shed some light on the topic?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110841097840751227?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110841097840751227/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110841097840751227' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110841097840751227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110841097840751227'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/02/google-and-flash.html' title='Google and Flash'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110802648795981921</id><published>2005-02-10T14:38:00.000+05:30</published><updated>2006-10-21T20:12:00.505+05:30</updated><title type='text'>Flowery Fuzz</title><content type='html'>&lt;a href='http://photos1.blogger.com/img/77/1572/1024/Distorted-Flower.jpg'&gt;&lt;img border='0' style='border:1px solid #AAAAAA; margin:2px' src='http://photos1.blogger.com/img/77/1572/400/Distorted-Flower.jpg'&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Flowery Fuzz&lt;/p&gt;I apologize for not posting too frequently anymore. There is a lot of work piled up, and for once I am running short of time.&lt;br /&gt;&lt;br /&gt;This post is just my way of saying that this blog is not dead, though it might seem like it at first sight. It is just one of those slow-downs. There are a lot of things I have planned out for this blog, and I'll start doling them out as soon as I am sure I can get it out of the drafts.&lt;br /&gt;&lt;br /&gt;P.S. I have entered this photo in the &lt;a href="http://www.photofriday.com/"&gt;Photo Friday&lt;/a&gt; challenge this week, for the theme "Distorted". If you have nothing better to do, please go over and drop me a vote. If I win, I promise you and your entire family GMail Invites. I've got lots! I know that using GMail invites as bribe doesn't work anymore, but I can't afford too much more.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110802648795981921?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110802648795981921/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110802648795981921' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110802648795981921'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110802648795981921'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/02/flowery-fuzz.html' title='Flowery Fuzz'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110723871179258783</id><published>2005-02-01T11:50:00.000+05:30</published><updated>2006-10-21T20:12:00.434+05:30</updated><title type='text'>Google Hitting Me Hard</title><content type='html'>One would think that the number of visitors to a blog would drop, considering that it is not updated frequently.&lt;br /&gt;&lt;br /&gt;However, in my case, my hits have been steadily increasing over the last two weeks. One of the largest source of these hits (about 14%!) is &lt;a href="http://images.google.com/"&gt;Google Image Search&lt;/a&gt;, pointing to &lt;a href="http://piecesofrakesh.blogspot.com/2004/09/beautiful-flower.html"&gt;an old post&lt;/a&gt; and &lt;a href="http://photos1.blogger.com/img/77/1572/1024/Flower-in-farmhouse.jpg"&gt;its pic&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Now, that pic is one of my all time favourites. I had clicked that pic just casually, and the uploaded version is un-touched-up. It is also one of my first macro shots ever. That pic will remain a special one for me.&lt;br /&gt;&lt;br /&gt;What makes me curious is, how come I have such a sudden surge of visitors going to see that pic? Unfortunately, the &lt;a href="http://images.google.com/imgres?imgurl=http://photos1.blogger.com/img/77/1572/1024/Flower-in-farmhouse.jpg&amp;imgrefurl=http://piecesofrakesh.blogspot.com"&gt;Google Image Search referrer URL&lt;/a&gt; doesn't give me any details of the search string, or their referrers. I tried doing basic searches at Google Images, but that didn't turn up my pic for the keywords I could come up with.&lt;br /&gt;&lt;br /&gt;If anyone has come here from Google Image Search, could you please tell me &lt;em&gt;how&lt;/em&gt; you got here?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110723871179258783?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110723871179258783/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110723871179258783' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110723871179258783'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110723871179258783'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/02/google-hitting-me-hard.html' title='Google Hitting Me Hard'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110678148658739337</id><published>2005-01-27T04:42:00.000+05:30</published><updated>2006-10-21T20:12:00.362+05:30</updated><title type='text'>Thoughts on XMLHttpRequest</title><content type='html'>&lt;div class="summary"&gt;Some more thoughts on XMLHttpRequest, from my recent experiences with the tool.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://piecesofrakesh.blogspot.com/2005/01/thoughts-on-xmlhttprequest.html"&gt;Continue Reading...&lt;/a&gt;&lt;/div&gt;&lt;div class="fullpost"&gt;I was going through my referrer list today, and come across another user who came to me through Eric Meyer’s post about (and in response to my older post) the &lt;a href="http://piecesofrakesh.blogspot.com/2004/09/economics-of-xhtml.html"&gt;Economics of &lt;abbr title="eXtensibe HyperText Markup Language"&gt;XHTML&lt;/abbr&gt;&lt;/a&gt;, where he (Eric) talks about &lt;a href="http://meyerweb.com/eric/thoughts/2004/09/13/standards-savings/"&gt;how the savings in bandwidth appreciates the value of the site&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;These days, I have moved away from talks about markup (as most of you must have noticed), mostly for two reasons.&lt;ol&gt;&lt;li&gt;XHTML is too stringent. It is so stringent, it is not practical.&lt;/li&gt;&lt;li&gt;There are other ways to save bandwidth.&lt;/li&gt;&lt;/ol&gt;I have to explain. Though I’ve been talking about standards frequently on my site, only recently have I decided to get my hands dirty with a project that talks in XHTML and respects it (which is more difficult that it seems at first glance) at least when talking to browsers that can handle it well.&lt;br /&gt;&lt;br /&gt;Reasonable digress: Of late, I have been damn busy. I guess everyone goes through these phases where he thinks that he’s reading too much &lt;abbr title="Really Simple Syndication"&gt;RSS&lt;/abbr&gt;, but I’ve just stopped keeping myself updated because I don’t have the time anymore. However, I still take the time to comment on the odd good article.&lt;br /&gt;&lt;br /&gt;One such post was Roger Johansson’s. He talked about &lt;a href="http://www.456bereastreet.com/archive/200501/the_perils_of_using_xhtml_properly/"&gt;how XHTML can be made easier to use&lt;/a&gt;, but in his comments (though he tried hard not to), the discussion shifted to whether XHTML is really worth the effort or not. &lt;a href="http://www.456bereastreet.com/archive/200501/the_perils_of_using_xhtml_properly/#comment2615"&gt;I maintained&lt;/a&gt; that though XHTML is a good way to learn, it is probably not what we’ll use in practice.&lt;br /&gt;&lt;br /&gt;That apart, here’s why I am making this post.&lt;br /&gt;&lt;br /&gt;I’ve been working on a lot of DHTML these days. Not in the traditional sense – I probably have to call it DOM Scripting &lt;a href="http://adactio.com/journal/display.php/20050114024033.xml"&gt;to be politically correct&lt;/a&gt;. XMLHttpRequest has been my most interesting toy. I’ve been playing with it like a baby boy plays with his first toy truck. He just rides it all over the place. He runs it over terrains that the toy couldn’t possibly take on, just because somewhere in his heart he’s confident that it’ll hold out. XMLHttpRequest has been my toy, and the web is my terrain.&lt;br /&gt;&lt;br /&gt;Here are my lessons, good and bad, listed out, while working with XMLHttpRequest.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;I think this is the most important issue. Using XMLHttpRequest doesn’t change the &lt;abbr title="Uniform Resource Locator"&gt;URL&lt;/abbr&gt;. Think about this. Eric said that a page that loads faster is good for business, and XMLHttpRequest does that for you in more ways than one. But XMLHttpRequest doesn’t respect URL resources, as seen by the address bar. If you use XMLHttpRequest, your page’s URL remains the same, whatever else you do. Do you need permalinks for your content? XMLHttpRequest can't deliver.&lt;/li&gt;&lt;li&gt;Using XMLHttpRequest involves a lot of DOM Scripting (especially if you think I am correct when I say that &lt;a href="http://piecesofrakesh.blogspot.com/2005/01/why-xml-in-xmlhttprequest.html"&gt;data should be passed as JavaScript over XMLHttpRequest&lt;/a&gt;). This is a problem for me, mostly because I use XMLHttpRequest in conjunction with XHTML. A command as simple as &lt;code&gt;&lt;em&gt;element&lt;/em&gt;.innerHTML&lt;/code&gt; &lt;a href="http://www.quirksmode.org/bugreports/archives/2004/11/innerhtml_in_xh.html"&gt;won’t work with XHTML&lt;/a&gt;. You’ll have to get into the mess of &lt;code&gt;document.createElement&lt;/code&gt;, &lt;code&gt;&lt;em&gt;element&lt;/em&gt;.setAttribute&lt;/code&gt; and &lt;code&gt;&lt;em&gt;element&lt;/em&gt;.appendChild&lt;/code&gt; way too often. There are a couple of tutorials on the web to explain these concepts, but mostly you are on your own.&lt;/li&gt;&lt;li&gt;XMLHttpRequest doesn’t come without its differences between browsers and their implementations. I don’t mean to scare the one’s who are starting – it’s really not that difficult. But just don’t expect one piece of code to work everywhere. We haven’t reached markup, styling and scripting nirvana yet.&lt;/li&gt;&lt;li&gt;I’ve come across a lot of browser bugs in the implementation of XHTML and XMLHttpRequest scripting. I use Firefox, and (ok, probably after Opera) I think Firefox’s support for standards is pretty good. Yet, Firefox catches me off guard sometimes. And don’t get me started about other browsers yet, including &lt;a href="http://www.microsoft.com/ie/"&gt;the most popular one&lt;/a&gt;. (By the way, for the uninformed, XMLHttpRequest is NOT part of the standard – probably why Opera hadn’t supported it until recently.)&lt;/li&gt;&lt;li&gt;In the end, probably in a nerdy sort of way, XMLHttpRequest is fun. It makes entire page-loads unnecessary. It makes information easier and faster to get to. It makes the user happy. It doesn’t involve too many UI issues. (I thought a user will never be comfortable unless he sees a page refresh when he clicks on a link in the browser. Obviously, I am wrong.) If well planned, XMLHttpRequest rocks!&lt;/li&gt;&lt;li&gt;XMLHttpRequest is tempting to overuse. This not such a problem from the developer’s point of view. However, I am not so sure if it’ll really save you bandwidth in the long run. The problem is that, since users find it so responsive, users will like to pamper themselves with more data than they’d otherwise need. XMLHttpRequest makes it easy, and fast. Just what the users need to have a good experience. I think all those talks about XMLHttpRequest saving the developers’ bandwidth needs to be re-thought. I have no math to back me up, but this is what my hunch tells me.&lt;/li&gt;&lt;li&gt;Did I say yet that XMLHttpRequest rocks? It’s the best thing that happened to the web since the invention of HTTP itself. It’s the stuff that’s going to direct the development of the Internet itself for the next half decade. But like every other intoxicating substance, it could be a life-saver or a poison depending on how you use it.&lt;/li&gt;&lt;/ul&gt;I guess I have no point to make in the end – I am probably too drunk to conclude. (I’ve been celebrating a VERY close friend’s wedding engagement tonight.) But I hope I’ve put across the point that XMLHttpRequest is good and yet bad, in it’s own ways. And that is so much like every other programming tool.&lt;br /&gt;&lt;br /&gt;It’s just a matter of what suits the job best. Flying a jet to work is too much power in your hands, but walking down to work is too little, if you know what I mean. You just have to use the right tool at the right time. XMLHttpRequest is just a tool – you have to decide when it’d be good and when it’d be impractical.&lt;br /&gt;&lt;br /&gt;For those who are in doubt, XMLHttpRequest is a tool you are not going to be able to do without. I think that web-developers who still work with old style HTML are already on their way to losing out, but now web-developers who haven’t mastered XMLHttpRequest are on their way to meeting the same fate. Yet, it’s a tool like any other – it has to be used at the right time for the right purpose. Every other time, it’s probably more effort than it’s worth.&lt;br /&gt;&lt;br /&gt;&lt;div class="Previously"&gt;Previously:&lt;ul&gt;&lt;li&gt;&lt;a href="http://piecesofrakesh.blogspot.com/2005/01/why-xml-in-xmlhttprequest.html"&gt;Why XML in XMLHttpRequest&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110678148658739337?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110678148658739337/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110678148658739337' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110678148658739337'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110678148658739337'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/01/thoughts-on-xmlhttprequest.html' title='Thoughts on XMLHttpRequest'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110653644036397608</id><published>2005-01-24T08:57:00.000+05:30</published><updated>2006-10-21T20:12:00.290+05:30</updated><title type='text'>Jazz By The Gateway</title><content type='html'>&lt;a href='http://photos1.blogger.com/img/77/1572/1024/Gateway-Show.jpg'&gt;&lt;img border='0' style='border:1px solid #AAAAAA; margin:2px' src='http://photos1.blogger.com/img/77/1572/400/Gateway-Show.jpg'&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Jazz By The Gateway&lt;/p&gt;This pic was taken at the Gateway of India, during a jazz show as part of the Mumbai Festival. Performing at the show were some of the &lt;q&gt;greatest living exponents of the art of jazz&lt;/q&gt; - Al Jarreau, George Duke, Ravi Coltrane and Earl Klugh along with members of The Thelonious Monk Institute of Jazz.&lt;br /&gt;&lt;br /&gt;I didn't go for the show, if you had to ask. (I'd probably have got better pics if I had, but I was too late to get the tickets.) This is a Hail Mary shot taken from outside.&lt;br /&gt;&lt;br /&gt;For readers who do not understand photography jargon, Hail Mary shots are where the photograph is taken with the camera held above your head, like in a crowd, without looking through the viewfinder. The camera settings have to be adjusted beforehand, and the frame is just plain guessed.&lt;br /&gt;&lt;br /&gt;In this case, I was outside a barracade containing the show. I couldn't see this frame - I had a sheet of asbestos between me and the Gateway. I only held my cam above that barracade and shot.&lt;br /&gt;&lt;br /&gt;(Ok, I promise that's the last post about &lt;a href="http://piecesofrakesh.blogspot.com/2005/01/lights-camera-arches.html"&gt;the Gateway&lt;/a&gt;, &lt;a href="http://piecesofrakesh.blogspot.com/2005/01/reflections.html"&gt;its waters&lt;/a&gt;, or of &lt;a href="http://piecesofrakesh.blogspot.com/2005/01/mumbai-fest-some-pics.html"&gt;the Mumbai Festival&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;&lt;div class="Previously"&gt;Previously:&lt;ul&gt;&lt;li&gt;&lt;a href="http://piecesofrakesh.blogspot.com/2005/01/mumbai-fest-some-pics.html"&gt;Mumbai Fest - Some Pics&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://piecesofrakesh.blogspot.com/2005/01/lights-camera-arches.html"&gt;Lights, Camera, Arches!&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://piecesofrakesh.blogspot.com/2005/01/reflections.html"&gt;Reflections&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110653644036397608?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110653644036397608/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110653644036397608' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110653644036397608'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110653644036397608'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/01/jazz-by-gateway.html' title='Jazz By The Gateway'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110653533190828626</id><published>2005-01-24T08:20:00.000+05:30</published><updated>2006-10-21T20:12:00.223+05:30</updated><title type='text'>Blog Of The Day</title><content type='html'>This is probably not a big feat, but the excitement is because this is a first.&lt;br /&gt;&lt;br /&gt;This blog has been featured as the &lt;a href="http://india.blogstreet.com/bsibin/botddate.py?syear=2005&amp;smon=01&amp;sday=24"&gt;Blog of the Day&lt;/a&gt; for today, on &lt;a href="http://india.blogstreet.com/"&gt;BlogStreet India&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Cheers!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110653533190828626?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110653533190828626/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110653533190828626' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110653533190828626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110653533190828626'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/01/blog-of-day.html' title='Blog Of The Day'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110612023841409082</id><published>2005-01-19T13:03:00.000+05:30</published><updated>2006-10-21T20:12:00.154+05:30</updated><title type='text'>Mumbai Fest - Some Pics</title><content type='html'>There was a huge collaborative street art project at Kala Ghoda, Mumbai as part of the 10-day Mumbai Fest. I happened to be around, and get some pics. (The pics link to Flickr)&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align:center"&gt;&lt;a href="http://www.flickr.com/photos/rakesh/3532307/" title="Pic 1"&gt;&lt;img src="http://photos1.flickr.com/3532307_163775e79c_m.jpg" width="187" height="240" alt="Pic 1" /&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Pic 1&lt;/p&gt;&lt;/div&gt;&lt;div style="text-align:center"&gt;&lt;a href="http://www.flickr.com/photos/rakesh/3532336/" title="Pic 2"&gt;&lt;img src="http://photos1.flickr.com/3532336_1a61ae5168_m.jpg" width="240" height="239" alt="Pic 2" /&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Pic 2&lt;/p&gt;&lt;/div&gt;&lt;div style="text-align:center"&gt;&lt;a href="http://www.flickr.com/photos/rakesh/3532322/" title="Pic 3"&gt;&lt;img src="http://photos2.flickr.com/3532322_14899ae91f_m.jpg" width="240" height="180" alt="Pic 3" /&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Pic 3&lt;/p&gt;&lt;/div&gt;&lt;div style="text-align:center"&gt;&lt;a href="http://www.flickr.com/photos/rakesh/3532349/" title="Pic 4"&gt;&lt;img src="http://photos2.flickr.com/3532349_b735d9efec_m.jpg" width="240" height="180" alt="Pic 4" /&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Support drugs. Do good karma.&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110612023841409082?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110612023841409082/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110612023841409082' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110612023841409082'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110612023841409082'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/01/mumbai-fest-some-pics.html' title='Mumbai Fest - Some Pics'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110604243267830699</id><published>2005-01-18T14:32:00.000+05:30</published><updated>2006-10-21T20:12:00.083+05:30</updated><title type='text'>Illegal To Display Feeds?</title><content type='html'>I came across (and I must say this) &lt;a href="http://trademark.blog.us/blog/2005/01/14.html#a1530"&gt;a really stupid post at The Trademark Blog&lt;/a&gt;, where the author accuses &lt;a href="http://www.bloglines.com/"&gt;Bloglines&lt;/a&gt; for &lt;em&gt;illegally&lt;/em&gt; reproducing his site's content.&lt;br /&gt;&lt;blockquote&gt;It was brought to my attention that a website named Bloglines was reproducing the Trademark Blog, surrounding it with its own frame, stripping the page of my contact info.  It identifies itself as a news aggregator.  It is not authorized to reproduce my content nor to change the appearance of my pages, which it does.&lt;/blockquote&gt;I think this kind of thoughts either stem from a poor understanding of feeds, or maybe this guy is just looking for legal issues to talk about (he's a lawyer, after all), or both.&lt;br /&gt;&lt;br /&gt;Bloglines might be putting their ads next to my content and earning money out of it. I don't think that constitutes "commercial use" of my content. They are providing a service, for which they are going to need money to run, and ads are a good way to get that done. The ad money I make off my site is barely anything, anyway. I don't mind if I lose an additional $2.05 to Bloglines, considering that my user-base is actually increasing thanks to services like Bloglines. I could think of it as paying them to keep my audience coming.&lt;br /&gt;&lt;br /&gt;Besides, it's not like Bloglines is running a site that makes money thanks to my content being published there. The users of Bloglines &lt;em&gt;choose&lt;/em&gt; to put a feed in their reader, and Bloglines just provies a means to read that feed easily. Bloglines makes money because they provide a great way for users to read a site's content, grabbing what the site's authors have willingly distributed for just that purpose.&lt;br /&gt;&lt;br /&gt;Personally, I read a lot of feeds too, a lot of which I prefer to read in Bloglines and not on the original sites. This is because, with Bloglines, I can strip off the clutter on a site, and grab just the content of the site, in a font, style and layout that I am comfortable with, and that works with all the other 130 sites in my feeds list, consistently.&lt;br /&gt;&lt;br /&gt;I did come across a similar problem recently, where a blogger had published &lt;a href="http://piecesofrakesh.blogspot.com/2005/01/why-xml-in-xmlhttprequest.html"&gt;one of my recent posts&lt;/a&gt; on his site, even though he gave me full credit for the post. I just sent him a friendly mail asking him to get my content off his site, and instead link to me if my articles are really important to his site's audience. Promptly, he removed that entire section off his site. (Apparently, it was his personal link blog, and he has now put that behind an authentication system ensuring that he's the only one reading it.) I am ok with him reading my feeds, really. I guess it would be a problem if he publishes my posts without asking me first. Publishing my post on his site, and reading my feeds are two different things, though. Obviously this blogger respected that when I brought it to his notice, and did the needful to correct the mistake.&lt;br /&gt;&lt;br /&gt;In the end, is it illegal to view/display/publish feeds from a site? No, it isn't, considering that the site's author willingly distributed the feeds. Is it illegal to publish one single article on a site without the author's permission? It probably is, but more than that, it's unethical, and should be refrained from doing. Is it illegal to make money by providing a service that reads feeds? Definitely not!&lt;br /&gt;&lt;br /&gt;I think I am thankful to Bloglines for making sure that I get a consistent flow of people reading my content, even if they don't ever visit my site. If I don't like Bloglines' idea of reading feeds, I should probably just stop publishing feeds. But that'll just crash my audience-size. In fact, I like the idea of Bloglines displaying my feeds so much, that I had written &lt;a href="http://piecesofrakesh.blogspot.com/2004/08/using-feeds.html"&gt;a post&lt;/a&gt; earlier recommending that people read my feeds through Bloglines, and I even &lt;a href="http://piecesofrakesh.blogspot.com/2004/10/two-small-changes.html"&gt;added&lt;/a&gt; a permanent link on my sidebar making it easier for people to &lt;a href="http://www.bloglines.com/sub/http://piecesofrakesh.blogspot.com/atom.xml"&gt;subscribe to my feeds with Bloglines&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;How about that, Mr. Lawyer?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110604243267830699?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110604243267830699/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110604243267830699' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110604243267830699'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110604243267830699'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/01/illegal-to-display-feeds.html' title='Illegal To Display Feeds?'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110585883541610595</id><published>2005-01-16T13:30:00.000+05:30</published><updated>2006-10-21T20:12:00.001+05:30</updated><title type='text'>Lights, Camera, Arches!</title><content type='html'>&lt;a href='http://photos1.blogger.com/img/77/1572/1024/Inside-the-Gateway.jpg'&gt;&lt;img border='0' style='border:1px solid #AAAAAA; margin:2px' src='http://photos1.blogger.com/img/77/1572/400/Inside-the-Gateway.jpg'&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Lights, Camera, Arches!&lt;/p&gt;Shot the other day at the Gateway of India. I had to clean up the monument a lot with my copy of Photoshop, because the government hadn't done a good job. (Thanks Kaushik, for patiently showing me how to play with Photoshop.)&lt;br /&gt;&lt;br /&gt;&lt;div class="Previously"&gt;Previously:&lt;ul&gt;&lt;li&gt;&lt;a href="http://piecesofrakesh.blogspot.com/2005/01/reflections.html"&gt;Reflections&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110585883541610595?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110585883541610595/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110585883541610595' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110585883541610595'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110585883541610595'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/01/lights-camera-arches.html' title='Lights, Camera, Arches!'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110552096667298229</id><published>2005-01-12T14:35:00.000+05:30</published><updated>2006-10-21T20:11:59.896+05:30</updated><title type='text'>I Graduated!!!</title><content type='html'>News has just come in. I am finally a graduate.&lt;br /&gt;&lt;br /&gt;Bachelor of Engineering (Electrical and Electronics). Aaaah! That feels good!&lt;br /&gt;&lt;br /&gt;Meet me at my local watering hole tonight to join in the celebrations.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110552096667298229?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110552096667298229/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110552096667298229' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110552096667298229'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110552096667298229'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/01/i-graduated.html' title='I Graduated!!!'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110551771284302335</id><published>2005-01-12T13:44:00.000+05:30</published><updated>2006-10-21T20:11:59.822+05:30</updated><title type='text'>Why XML in XmlHTTPRequest?</title><content type='html'>The XmlHTTPRequest function was designed so that the client can get small pieces of information from the server without having to do a page refresh. Obviously, the developers thought that &lt;abbr title="eXtensible Markup Language"&gt;XML&lt;/abbr&gt; will be the format of choice for this data exchange.&lt;br /&gt;&lt;br /&gt;Thank God they didn’t make XML validation necessary!&lt;br /&gt;&lt;br /&gt;I say this because XML will not be the format of choice for this data exchange. Let’s see why. &lt;div class="summary"&gt;&lt;a href="http://piecesofrakesh.blogspot.com/2005/01/why-xml-in-xmlhttprequest.html"&gt;Read on...&lt;/a&gt;&lt;/div&gt;&lt;div class="fullpost"&gt;&lt;br /&gt;Firstly, let’s see how the data flow will be in the case of XML over XmlHTTPRequest. A typical scenario is where the data lies in a database on the server, and the data is requested by the client. The steps in the process will be:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Server reads the request, extracts the data from the database.&lt;/li&gt;&lt;li&gt;Server prepares an XML document using this data.&lt;/li&gt;&lt;li&gt;This XML is sent to the client.&lt;/li&gt;&lt;li&gt;Client validates the XML for well-formed-ness.&lt;/li&gt;&lt;li&gt;Client extracts data from the XML markup.&lt;/li&gt;&lt;li&gt;Client calls functions/triggers events which use this data as parameters in some way or other.&lt;/li&gt;&lt;/ol&gt;For several reasons, this model is not optimum. The questions that come to the mind immediately are:&lt;ul&gt;&lt;li&gt;Is it necessary to prepare an XML document (step 2 above)? Isn’t that an extra step that is probably not necessary?&lt;/li&gt;&lt;li&gt;Client validation is necessary (step 4 above) to ensure that the XML parser can parse the XML. This puts heavy processing requirements on the client. Is this really necessary?&lt;/li&gt;&lt;li&gt;The data from the XML will then have to be extracted (step 5 above). This isn’t really a necessary step either if the data is not marked up as XML. So, then, is it really necessary to use XML?&lt;/li&gt;&lt;/ul&gt;Then there are more problems. In web applications, where XmlHTTPRequest is most likely to be used, speed is of utmost importance, and optimizing for fast response times will be imperative. In such cases, the amount of time taken for any kind of operation, especially if it happens over the network or the internet, has to be minutely scrutinized and optimized. In such cases, XML is probably not the best suited format for data exchange. XML files are heavy as far as sizes go. A simple text like “Hello World” (11 characters) can be transmitted over XmlHTTPRequest as 11 bytes of data. Marking this up as XML will increase this at least 4 fold (say, and that’s still a conservative estimate) even if whitespaces are stripped off the document, increasing download sizes four times, and reducing response by a factor of 4. Point is, XML comes with its overheads which cannot be tolerated in a web application.&lt;br /&gt;&lt;br /&gt;So, in what format will data be transferred over XmlHTTPRequest? The simplest way is as a plain old string of data. This will be the most efficient as far as download speeds are concerned. You will download only 11 bytes where 11 bytes of download is required, not more. Besides, there won’t be any XML parsing or validation in the picture, making the application that much faster.&lt;br /&gt;&lt;br /&gt;However, somehow, I don’t see data flowing over XmlHTTPRequest in the form of plain strings of data either. Instead, I think it’ll flow in the form of JavaScript code.&lt;br /&gt;&lt;br /&gt;Let me use an example from &lt;a href="http://serversideguy.blogspot.com/2004/12/google-suggest-dissected.html"&gt;the guy who deconstructed&lt;/a&gt; Google Suggest, and the way XmlHTTPRequest works there. According to him, the code returned by Google when you hit a keystroke looks like this.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sendRPCDone(frameElement, "fast bug", new Array("fast bug track", "fast bugs", "fast bug", "fast bugtrack"), new Array("793,000 results", "2,040,000 results", "6,000,000 results", "7,910 results"), new Array(""));&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Basically, what this code does is call a function, with a bunch of parameters. The function called, &lt;code&gt;sendRPCDone&lt;/code&gt;, is defined in &lt;a href="http://www.fastbugtrack.com/misc/google/ac.js"&gt;client side JavaScript code&lt;/a&gt;. The parameters are generated depending on server side processing (probably from Google’s cached searches). Then, later in the code, this response text is run through an &lt;code&gt;eval&lt;/code&gt; function to execute the function on the client side (&lt;code&gt;eval(_xmlHttp.responseText);&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;I think the eval function is really a boon here. It makes JavaScript as the language of choice over XML for XmlHTTPRequest. For who don’t know what eval does, it basically takes a piece of string, treats it as though it is JavaScript code, and executes it. The string could be dynamically generated by client-side code, or as in this case, returned from the server. Just what we need here!&lt;br /&gt;&lt;br /&gt;To summarize, here’s why we’ll use JavaScript instead of XML when using XmlHTTPRequest.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Downloading XML data will take more time as compared to JavaScript. Depending on the amount of data to be transferred, this difference might be huge.&lt;/li&gt;&lt;li&gt;Use of XML will necessitate validation of the markup, so that a parser can read the document – a process that requires extra processing on the client-side. This is not necessary with JavaScript.&lt;/li&gt;&lt;li&gt;The XML data is not already in a position to call scripts. Client side code will have to handle that, based on event handlers or such. JavaScript, on the other hand will be ready to be executed on the client.&lt;/li&gt;&lt;/ul&gt;It's easy to see why XML will not be used as the format of choice over XmlHTTPRequest. A little thought later, JavaScript emerges as the winner as the format of choice for data exchange over XmlHTTPRequest.&lt;br /&gt;&lt;br /&gt;Did someone say that JavaScript will be coming out of the closet this year?&lt;br /&gt;&lt;br /&gt;&lt;div class="Previously"&gt;Previously:&lt;ul&gt;&lt;li&gt;&lt;a href="http://piecesofrakesh.blogspot.com/2004/09/look-ma-no-refresh.html"&gt;Look Ma, No Refresh&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110551771284302335?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110551771284302335/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110551771284302335' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110551771284302335'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110551771284302335'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/01/why-xml-in-xmlhttprequest.html' title='Why XML in XmlHTTPRequest?'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110545777919888728</id><published>2005-01-11T21:07:00.000+05:30</published><updated>2006-10-21T20:11:59.752+05:30</updated><title type='text'>Google Logos</title><content type='html'>You are probably aware of the fact that occassionally Google changes their logos to celebrate a festive occassion. These logos (called the Google Doodles) are really nice to look at. Go &lt;a href="http://www.google.com/holidaylogos.html"&gt;have a look&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;What I didn't know (and I happened to notice it from &lt;a href="http://www.seroundtable.com/archives/001208.html"&gt;somewhere&lt;/a&gt;) is that Google has different search sites for specific topics. Here's the list of some of them, with their logos:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.google.com/unclesam"&gt;US Government Search&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.google.com/unclesam"&gt;&lt;img src="http://www.google.com/sitesearch/unclesam.gif" alt="Google Uncle Sam" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.google.com/linux"&gt;Linux Search&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.google.com/linux"&gt;&lt;img src="http://www.google.com/sitesearch/linux.gif" alt="Google Linux" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.google.com/bsd"&gt;BSD Search&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.google.com/bsd"&gt;&lt;img src="http://www.google.com/sitesearch/bsd.gif" alt="Google BSD" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.google.com/microsoft.html"&gt;Microsoft Search&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.google.com/microsoft.html"&gt;&lt;img src="http://www.google.com/sitesearch/microsoft.gif" alt="Google Microsoft Search"&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.google.com/mac.html"&gt;Apple/Macintosh Search&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.google.com/mac.html"&gt;&lt;img src="http://www.google.com/sitesearch/mac.gif" alt="Google Apple/Macintosh Search"&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;I could'nt help notice the Google Microsoft Search logo. It is the only one with a non-white background. Somehow, it seems to be mocking MS with its sky and grassy hills combination.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110545777919888728?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110545777919888728/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110545777919888728' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110545777919888728'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110545777919888728'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/01/google-logos.html' title='Google Logos'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110521603057395390</id><published>2005-01-09T02:03:00.000+05:30</published><updated>2006-10-21T20:11:59.679+05:30</updated><title type='text'>Reflections</title><content type='html'>&lt;a href='http://photos1.blogger.com/img/77/1572/1024/Reflections.jpg'&gt;&lt;img border='0' style='border:1px solid #AAAAAA; margin:2px' src='http://photos1.blogger.com/img/77/1572/400/Reflections.jpg' alt="Reflections" /&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Reflections&lt;/p&gt;Was spending a night out on the streets of Mumbai today with a friend's camera. I am totally not used to this camera but I managed to get an interesting shot or two. The cam is a &lt;a href="http://www.nikon-image.com/eng/PDF/coolpix3100.htm"&gt;Nikon Coolpix 3100&lt;/a&gt; - the same series as &lt;a href="http://nikonimaging.com/global/products/digitalcamera/coolpix/3700/index.htm"&gt;mine&lt;/a&gt;, but only slightly less loaded.&lt;br /&gt;&lt;br /&gt;This pic shows the reflection of the lights of Hotel Taj in the waters of the Arabian Sea, at the Gateway of India.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110521603057395390?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110521603057395390/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110521603057395390' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110521603057395390'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110521603057395390'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/01/reflections.html' title='Reflections'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110501134690373181</id><published>2005-01-06T16:59:00.000+05:30</published><updated>2006-10-21T20:11:55.962+05:30</updated><title type='text'>Web Applications - The Wave Of The Future</title><content type='html'>Web applications are finally beginning to see the light of the day. I am putting all my money on this. I am sure this is the future of the web, application design, networked software architectures, maybe even desktops and operating systems itself.&lt;br /&gt;&lt;br /&gt;Web based applications will make inroads into (almost) every kind of application we use today. In this post, I try to list out some of the benefits of using web based apps.&lt;br /&gt;&lt;br /&gt;&lt;div class="summary"&gt;&lt;a href="http://piecesofrakesh.blogspot.com/2005/01/web-applications-wave-of-future.html"&gt;Read the complete post...&lt;/a&gt;&lt;/div&gt;&lt;div class="fullpost"&gt;First, a quick introduction to web based apps, for those who just tuned in. Examples of web based applications are &lt;a href="http://www.gmail.com/"&gt;GMail&lt;/a&gt;, &lt;a href="http://www.bloglines.com/"&gt;Bloglines&lt;/a&gt;, and &lt;a href="http://www.oddpost.com/"&gt;OddPost&lt;/a&gt;. GMail is a full featured mail client that does everything that a desktop mail client does, only ups it a few notches. So does OddPost. Bloglines is a web based feed reader that is directly competing with desktop feed readers, and winning. These web apps are basically applications that run on a server, whose &lt;abbr title="User Interface"&gt;UI&lt;/abbr&gt; is exposed in the form of web pages. By the very nature of its architecture, the program logic lies in a central place (the server), and the UI is available to the client in a piece of software that has been around since the birth of &lt;abbr title="HyperText Transfer Protocol"&gt;HTTP&lt;/abbr&gt; itself (the browser). The use of JavaScript and the &lt;abbr title="Document Object Model"&gt;DOM&lt;/abbr&gt; is probably the single most important factor that has made these apps possible.&lt;br /&gt;&lt;br /&gt;The use of JavaScript is very different from the way it was used in 1999. Back then, JavaScript was just a cool way to make mouseovers and cool (now irritating) dynamic elements on the page like mouse pointer trails and flashy text that change colors. JavaScript was used because it could be, not because it should be. At one point, I thought JavaScript was dead, indeed like many other developers must have thought. The use of JavaScript became an example of bad web design, and the language was pushed into the dark annals of the world of notorious web pages.&lt;br /&gt;&lt;br /&gt;Now, though, JavaScript has matured. It is used just what it was designed for - creating dynamic changes on the client side without introducing a server refresh lag. A dynamic front end in a browser window has always been a problem for application design and is probably the only reason why web based applications have not yet seen the light of the day. Today’s use of JavaScript circumvents that problem.&lt;br /&gt;&lt;br /&gt;Now that we can make web applications, here's why we should, and &lt;em&gt;will&lt;/em&gt;, do it.&lt;br /&gt;&lt;br /&gt;&lt;h4 class="post-subtitle"&gt;The application lies at only one place&lt;/h4&gt;The application logic lies on the server, unlike desktop applications, where the application logic lies on the user’s computer. Since there is only one working copy of the application, it’s much easier to distribute. In fact, distributing applications in the traditional way doesn’t make sense here at all, since the user doesn’t really get a copy of the app at all. All the user gets is the UI, which is really all he needs. Application distribution is a non-existent problem, which means it is as easy as it can get.&lt;br /&gt;&lt;br /&gt;&lt;h4 class="post-subtitle"&gt;The user doesn’t need any software&lt;/h4&gt;All the user does is fire his browser and type in a &lt;abbr title="Uniform Resource Locator"&gt;URL&lt;/abbr&gt;. These days, browsers are a standard piece of software that usually gets bundled with the &lt;abbr title="Operating System"&gt;OS&lt;/abbr&gt; itself, so finding a browser on the client is not a problem at all, and really, that’s all the user needs.&lt;br /&gt;&lt;br /&gt;&lt;h4 class="post-subtitle"&gt;The user isn’t the administrator&lt;/h4&gt;Typically, when a user has the need for an application, he has to prepare himself to be the administrator of the application. He will have to do the setup, running, maintenance and troubleshooting, and handle all the problems that come with it. But in the case of web apps, since the app is really not with the user at all, the user won’t have to worry about these problems. And really the user shouldn’t. That makes for a happy user. That translates into a good application. This, of course, is impossible with desktop applications.&lt;br /&gt;&lt;br /&gt;&lt;h4 class="post-subtitle"&gt;The administrator is the application’s programmer&lt;/h4&gt;Yes, the load on the programmers is more. But if you compare that to the costs of making deployable applications and then managing a service team to help users install, maintain and troubleshoot the application, it’s easy to see which is cheaper, not to mention more efficient. A small team of programmers working at one central location to maintain, manage and troubleshoot applications makes more economic sense to app manufacturers.&lt;br /&gt;&lt;br /&gt;&lt;h4 class="post-subtitle"&gt;The application makes no assumptions about the user&lt;/h4&gt;Ok, that is a small lie. The user is assumed to have a capable browser to handle the application. But really, is that such a big deal? Because of the very nature of HTTP, the application is platform independent. This means that the user can use any operating system he wishes to use, and that doesn’t make a difference. This is a huge change from the traditional “Designed for &lt;em&gt;&amp;lt;operating system name here&amp;gt;&lt;/em&gt;” applications. The user doesn’t have 512 &lt;abbr title="Mega Bytes"&gt;MB&lt;/abbr&gt; &lt;abbr title="Random Access Memory"&gt;RAM&lt;/abbr&gt;? No problem. The user doesn’t have processing power? No problem. The user has an outdated motherboard? No problem.&lt;br /&gt;&lt;br /&gt;&lt;h4 class="post-subtitle"&gt;Multiple versions is a thing of the past&lt;/h4&gt;When a new version of the application is out, every single user gets to use it instantly. Literally. How cool is that! Again, this is possible since the application is centralized, and there’s really only one running copy of the application. All version changes are instantaneous and the user doesn’t need to know how to upgrade. This also means that the app developers don’t have to worry about supporting legacy versions and backward compatibility is not an issue.&lt;br /&gt;&lt;br /&gt;&lt;h4 class="post-subtitle"&gt;It’s lightweight&lt;/h4&gt;The user doesn’t really download the whole application before using it. (Take that, Java fans!). He doesn’t even download the whole UI. He only downloads the part of the UI that is required for his use immediately over the URI that he’s on. This makes the application very lightweight and hence responsive and fast. Even very complex applications can load in seconds, maybe less, even over a bad connection, thanks to this.&lt;br /&gt;&lt;br /&gt;&lt;h4 class="post-subtitle"&gt;It’s portable&lt;/h4&gt;There’s nothing installed at the users end, so the user can use the app from any location. Any location means literally any location across the globe. You can use the application in your office, and then at home, and then from your vacation in Hawaii, and every time it works just as well, without any problems of portability.&lt;br /&gt;&lt;br /&gt;&lt;h4 class="post-subtitle"&gt;It’s simple and trustworthy&lt;/h4&gt;No messy extra protocols or port numbers. If your firewalls lets you see web pages (and which firewall blocks that!) you can access the application. So the user doesn’t have to know a thing, or worry about it. He just fires up his browsers, and enters a URL. Simple. Even better, since the application works in the protected environment of the browser, the application can be trusted and can never mess with the user’s system. No more can an application “slow down your system”, or “crash every once in a while”. Those complaints are a thing of the past.&lt;br /&gt;&lt;br /&gt;&lt;h4 class="post-subtitle"&gt;The app architecture is transparent to the client&lt;/h4&gt;So, the programmers think that it would be a good idea to have separate data servers? Maybe split up demanding processes and push them to different computers to handle the job? Maybe they need a whole bank of a hundred thousand computers working together to do the job? This kind of architecture can be designed for optimum load balancing between servers. However this is entirely impossible with desktop applications. With centralized applications, it’s not difficult to construct and maintain such systems. In any case, whatever be the server architecture, the user doesn’t need to know or care.&lt;br /&gt;&lt;br /&gt;Sure, web applications can never do some things that desktop applications can do – far from it. You will never be able to do a defrag through a browser. You can never run 3D modeling software through a browser. Browser based apps cannot replace system programs at all. Not for a long time to come, at least. However, for application programs, the desktop’s days are numbered.&lt;br /&gt;&lt;br /&gt;Welcome to the show. Today’s act: The beginning of the end of the desktop.&lt;/div&gt;&lt;br /&gt;&lt;hr /&gt;&lt;strong&gt;Update:&lt;/strong&gt; This post is now available &lt;a href="http://www.webmascon.com/topics/technologies/12a.asp"&gt;in Russian&lt;/a&gt;. (Thanks, Alexander Kachanov)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110501134690373181?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110501134690373181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110501134690373181' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110501134690373181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110501134690373181'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/01/web-applications-wave-of-future.html' title='Web Applications - The Wave Of The Future'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110494349171388977</id><published>2005-01-05T21:13:00.000+05:30</published><updated>2006-10-21T20:11:55.893+05:30</updated><title type='text'>Bad Forms</title><content type='html'>&lt;a href="http://www.stijlstek.nl/greek2me/"&gt;A site&lt;/a&gt; I frequent has a nice little local weather update shown on its sidebar. Now, I get my local weather forecasts delivered on my desktop through a &lt;a href="http://www.konfabulator.com/"&gt;Konfabulator&lt;/a&gt; widget, The Weather, and have been reasonably happy with it. Also, considering that in the web design circles, not too many bloggers are from Mumbai, I thought it'd be a nice touch to add to my site.&lt;br /&gt;&lt;br /&gt;After some digging, I discovered that my weather feeds are coming from &lt;a href="http://www.weather.com/"&gt;weather.com&lt;/a&gt;. Over at their site, they have tools to display the current local weather on my site, and was very pleased with it at first glance, until I discovered that I have to register to use it.&lt;br /&gt;&lt;br /&gt;I have to say, I have issues with registering for services, especially free ones. I can cite various reasons why I do not and probably &lt;em&gt;should not&lt;/em&gt; register. Most web designers must know that users do not like to register on a site. If they don't, they don't make for good web designers.&lt;br /&gt;&lt;br /&gt;Aaagh! Let me get to my point.&lt;br /&gt;&lt;br /&gt;Have a look at &lt;a href="http://registration.weather.com/registration/wxmagnet/step1?act=reset&amp;sponsor=null&amp;interest=null&amp;aff=null&amp;par=null&amp;installid=null&amp;x=33&amp;y=16"&gt;this form&lt;/a&gt; I had to fill to register. Done? Now, let me list my peeves out.&lt;ul&gt;&lt;li&gt;The form says that fields marked with the red asterisk are required fields. Is it just me, or do you find it funny too that every field has this red asterisk next to it?&lt;/li&gt;&lt;li&gt;Really, do they need my first name, last name, date of birth (what?), and gender (&lt;em&gt;whaaaaat???&lt;/em&gt;) so that I can sign up for a weather service?&lt;/li&gt;&lt;li&gt;The address (and its various fields) are also marked with that asterisk. However, the state I belong to here in India is Maharashtra, which isn't listed there. In fact, none of the Indian states are listed there at all! Wait, it's only American states listed there? Maybe the developers forgot that The Internet is a worldwide network, and America is not the only place in the world? Wonder why they hired developers like that! Required field, you say? What do I select now?&lt;/li&gt;&lt;li&gt;Oh, hang on. They have a option where I can change the country from USA to India. However, I found that only &lt;em&gt;after&lt;/em&gt; I found the 'State' dropdown box. Smart layout, I must say!&lt;/li&gt;&lt;li&gt;Oh, I am wrong again. Changing the country is of no consequence to the list of states. Even if I select "India", the states shown are all American! Smart!&lt;/li&gt;&lt;li&gt;Here in India, our pin codes are 6 digits long. However, I can only enter 5 digits in that box they have on their page. Let me guess, America has 5 digit pins?&lt;/li&gt;&lt;li&gt;Notice, I have not talked about concepts like accessibility yet. Obviously (or, the impression that I get without doing my &lt;em&gt;right click &gt; view source&lt;/em&gt; is that) the form is not the least bit accessible to other kinds of browsers.&lt;/li&gt;&lt;/ul&gt;I must say, it is really irritating when companies like this just assume that their audience is only American. The Internet is not just about America, you know. Don't make me fill forms which require my local information, without doing a study of what local information looks like outside your locality. In any case, when designing a form, please don't assume that America is the world. And please do not ask for stupid irrelevant information, like my gender. By the way, would you also mind giving a little thought to this little thing called 'Usability', while you are at it?&lt;br /&gt;&lt;br /&gt;Sorry weather.com. I do not like you any more. I know you'll probably say "So what?", but that doesn't help improve your image. Quite the contrary, in fact.&lt;br /&gt;&lt;br /&gt;May the web design community use that form as an example of badly designed forms. When you see forms like this, you can put one hand your stomach, point the index finger of your other hand to the screen, tilt your head backwards slightly, and laugh out loud with your stomach bobbing rhythmically up and down.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110494349171388977?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110494349171388977/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110494349171388977' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110494349171388977'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110494349171388977'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/01/bad-forms.html' title='Bad Forms'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110478626750955278</id><published>2005-01-04T02:34:00.000+05:30</published><updated>2006-10-21T20:11:55.818+05:30</updated><title type='text'>Link Bin</title><content type='html'>&lt;ul&gt;&lt;li&gt;Ever wondered what your favourite cartoon characters' skeletal structures are like? &lt;a href="http://michaelpaulus.com/gallery/character-Skeletons"&gt;Take a look&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Did you know that &lt;a href="http://blog.codefront.net/archives/2004/12/14/homer-simpson-uses-tabbed-browsing/"&gt;Homer Simpson uses tabbed browsing&lt;/a&gt;?&lt;/li&gt;&lt;li&gt;&lt;a href="http://weblogs.mozillazine.org/asa/archives/007184.html"&gt;Firefox 1.0 cumulative downloads graph&lt;/a&gt;. (&lt;a href="http://annevankesteren.nl/archives/href/2004/12#link-1125"&gt;via&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.washingtonpost.com/wp-srv/flash/photo/politics/2004-12-08_bestofpolitics/index_frames.htm?startat=1&amp;indexFile=politics_2004-12-08_bestofpolitics"&gt;Best Of The Post 2004 - Politics&lt;/a&gt;: a collection of the best political pics of the year.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.wired.com/wired/archive/13.01/bittorrent.html"&gt;The BitTorrent Effect&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://scribbling.net/how-to-fix-moms-computer"&gt;How to fix Mom's computer&lt;/a&gt; - a novice guide to fixing up a messed up computer.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.siberart.com/signs%20pages/logos_home.html"&gt;Floating Logos Project&lt;/a&gt; - Interesting, but you can't help but wonder how much time people have at hand.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.theinquirer.net/?article=20450"&gt;Eating your mouse&lt;/a&gt; can be injurious to health.&lt;/li&gt;&lt;li&gt;&lt;a href="http://news.bbc.co.uk/2/hi/in_pictures/4098943.stm"&gt;A collection of pics&lt;/a&gt; sent in to the BBC by its readers over the last year.&lt;/li&gt;&lt;li&gt;Winners of the &lt;a href="http://www.guardian.co.uk/life/badscience/"&gt;2004 Bad Science Awards&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Bloggers are the &lt;a href="http://abcnews.go.com/WNT/PersonOfWeek/story?id=372266&amp;page=1"&gt;People of the Year, 2004&lt;/a&gt;, according to ABC News. (&lt;a href="http://slashdot.org/article.pl?sid=04/12/31/2213205"&gt;via&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;An amusing QuickTime &lt;a href="http://www.i-am-bored.com/bored_link.cfm?link_id=7240"&gt;animation about procrastination&lt;/a&gt;. (&lt;a href="http://www.linkbunnies.org/archives/2005/01/03/an_amusing_quic.php"&gt;via&lt;/a&gt;)&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110478626750955278?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110478626750955278/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110478626750955278' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110478626750955278'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110478626750955278'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/01/link-bin_110478626750955278.html' title='Link Bin'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110465560016687444</id><published>2005-01-02T14:17:00.000+05:30</published><updated>2006-10-21T20:11:55.609+05:30</updated><title type='text'>Tsunami Links</title><content type='html'>Here are some links related to the Indian Ocean Tsunami.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The &lt;a href="http://en.wikipedia.org/wiki/2004_Indian_Ocean_earthquake"&gt;wikipedia entry&lt;/a&gt; is extremely informative, with a lot of information, pics, animations, videos and more links.&lt;/li&gt;&lt;li&gt;Waxy.org for more &lt;a href="http://www.waxy.org/archive/2004/12/28/amateur_.shtml"&gt;amateur tsunami video footage&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.aynrand.org/site/News2?page=NewsArticle&amp;id=10688&amp;news_iv_ctrl=1021"&gt;U.S. should not help the tsunami victims&lt;/a&gt;. Just what the victims need. Let the U.S. discuss tax issues and ownership of government money, while people die half way across the globe when they could do with some help.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.digitalglobe.com/tsunami_gallery.html"&gt;A collection of before and after satellite pics&lt;/a&gt; of the affected areas. (&lt;a href="http://slashdot.org/article.pl?sid=04/12/31/0016206"&gt;via&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;People dead = hundreds of thousands. &lt;a href="http://www.wired.com/news/medtech/0,1286,66148,00.html"&gt;Animals dead = zero&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110465560016687444?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110465560016687444/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110465560016687444' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110465560016687444'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110465560016687444'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/01/tsunami-links.html' title='Tsunami Links'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110465323260014921</id><published>2005-01-02T13:24:00.000+05:30</published><updated>2006-10-21T20:11:55.528+05:30</updated><title type='text'>Predictions for 2005</title><content type='html'>I am making this post for two reasons.&lt;ol&gt;&lt;li&gt;Everyone is making similar posts.&lt;/li&gt;&lt;li&gt;It’ll be fun to come back to this list at the end of the year to see how correct I was.&lt;/li&gt;&lt;/ol&gt;So, here are my predictions about the web for the coming year.&lt;br /&gt;&lt;br /&gt;&lt;div class="summary"&gt;&lt;a href="http://piecesofrakesh.blogspot.com/2005/01/predictions-for-2005.html"&gt;Continue reading...&lt;/a&gt;&lt;/div&gt;&lt;div class="fullpost"&gt;&lt;h4 class="post-subtitle"&gt;People will understand why IE sucks&lt;/h4&gt;We know why IE sucks, but the regular user doesn’t even know of his options. Alternative browsers that provide a better surfing environment will make users turn to them. Firefox will lead this bunch, probably breaking the 50% browser share barrier.&lt;br /&gt;&lt;br /&gt;&lt;h4 class="post-subtitle"&gt;Developers will still not take to XHTML&lt;/h4&gt;Developers will realize that XHTML validation is a lot of work and not really worth the effort. Web pages will continue to use HTML. We will use the lessons we’ve learnt from XHTML, like semantics, separation of code and content, CSS based design and accessibility driven design, but the web pages will continue to be invalid XHTML, and people will discover that the validation doesn’t really matter at all. XHTML will be used only by purists. It will remain a great idea that we can’t use yet.&lt;br /&gt;&lt;br /&gt;&lt;h4 class="post-subtitle"&gt;JavaScript will take the stage&lt;/h4&gt;2005 will probably be remembered most for the use of JavaScript and related innovations. Yes, that happened in 1999 too, but it will be different this time around. Developers will understand how to use JavaScript in a fashion that keeps the page accessible to even incapable user agents. XmlHTTPRequest will probably be the hero of the show through this year.&lt;br /&gt;&lt;br /&gt;&lt;h4 class="post-subtitles"&gt;More Web Applications&lt;/h4&gt;There’ll be more applications running off a browser over the Internet. I can already feel this happening with me – I probably use fewer desktop applications than web applications. More and more system independent applications will run off the browser.&lt;br /&gt;&lt;br /&gt;&lt;h4 class="post-subtitle"&gt;Brower independence will be in vogue&lt;/h4&gt;Sites that work only in one browser will be looked down upon. Most such sites will alter their code to accommodate multiple browsers or otherwise be totally browser independent.&lt;br /&gt;&lt;br /&gt;&lt;h4 class="post-subtitle"&gt;Mobile browsing will be more important than ever&lt;/h4&gt;In the long term future, I don’t see people using a desktop computer just to check mail or send an IM. Instead, such things can be done faster and more efficiently on a mobile device, like a phone. Good browsing capabilities for such phones will be very important, and we’ll see crucial steps being taking in that direction this year.&lt;br /&gt;&lt;br /&gt;Most of these are rather obvious. But then, not always is the obvious the necessary consequence. Let’s see what happens at the end of the year.&lt;br /&gt;&lt;br /&gt;Happy new year to one and all. Hope the year is great for you.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110465323260014921?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110465323260014921/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110465323260014921' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110465323260014921'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110465323260014921'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2005/01/predictions-for-2005.html' title='Predictions for 2005'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110442237826209069</id><published>2004-12-30T21:27:00.000+05:30</published><updated>2006-10-21T20:11:55.452+05:30</updated><title type='text'>Donate For Relief</title><content type='html'>Amazon makes it easy for you to &lt;a href="http://s1.amazon.com/paypage/PX3BEL97U9A4I/002-3654929-7805607"&gt;donate to the American Red Cross Society&lt;/a&gt; for the tsunami victims. (&lt;a href="http://www.simplebits.com/quickbits/#1104412879"&gt;via&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110442237826209069?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110442237826209069/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110442237826209069' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110442237826209069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110442237826209069'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2004/12/donate-for-relief.html' title='Donate For Relief'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110421650275227903</id><published>2004-12-28T11:02:00.000+05:30</published><updated>2006-10-21T20:11:55.385+05:30</updated><title type='text'>Earthquake! Tsunami!</title><content type='html'>&lt;div style="text-align:center;"&gt;&lt;a href="http://wwwi.reuters.com/images/asia_quake_map.gif"&gt;&lt;img src="http://wwwi.reuters.com/images/asia_quake_map.gif" width="90%"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="summary"&gt;&lt;a href="http://piecesofrakesh.blogspot.com/2004/12/earthquake-tsunami.html"&gt;Read on&lt;/a&gt; for the horror in first-person.&lt;/div&gt;&lt;div class="fullpost"&gt;&lt;q&gt;Home was hit by Tidal wave... Practically lost everything.... Family is fine... Thank God...&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://www.livejournal.com/users/ronnietan/2959.html"&gt;Ronnietan&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;... and then tidal waves about 16 feet high hit the West coast of Phuket (Rawai, Patong), the Similans, Koh Lanta, Phi Phi Islands. The wave reached 300 m inland at Patong and swept hundreds of tourists into the sea.&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://www.livejournal.com/users/ellie_elephant/5452.html"&gt;ellie_elephant&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;There was a kinda big earthquake in my place this morning... It woke me up, and I ran downstairs amazingly fast... That was shocking. I thought this house will be ruined...&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://www.livejournal.com/users/meilathena/33526.html?mode=reply"&gt;Meilathena&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;Priya and I are safe, barring a nasty shock when she was jerked out of bed early today morning by the quake...&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://www.livejournal.com/users/hserus/11029.html"&gt;Suresh Ramasubramanian&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;Thankfully my parents are okay - they have not been affected physically. However we have lost some of our closest friends...&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://www.livejournal.com/users/dhruhini/83007.html"&gt;Dhruhini&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;I am closer to the beach. A church by the beach is supposedly flooded, and there are reports of people being drowned, while in Church. I wonder if they got trapped or something!&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://www.livejournal.com/users/reethika/23594.html?thread=131114#t131114"&gt;notangel78&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;The beach is totally flooded. Chennai without a beach feels totally weird, even though its only temporary... People around the beach have been forced to evacuate. Looks sad.&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://www.livejournal.com/users/vyshnavi/15960.html"&gt;Vyshnavi&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;We had tremors, and floods. Apparently there are dead bodies up the coastline. Fuck... We're fine. But scared.&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://www.livejournal.com/users/rulinian/66037.html"&gt;Rulinian Wexile&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;I'm scared... My best friend, Alyssa is currently on holiday in Langkawi, Malaysia&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://www.livejournal.com/users/rain_panda/42626.html?mode=reply"&gt;Sophia&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;He was jet-skiing at a beach in Phang-nga province, one of the place that the wave hit hardest. They found his body about 100 metres away from the hotel.&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://www.livejournal.com/users/darthmyrrh/7556.html"&gt;D.M.&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;The water went out then came back in very, very quickly, taking everything with it. When the water came into the bungalow, we put everything on the beds... All the windows were closed, so the water kept pushing everything up towards the roof. It pushed us up to the roof, then the roof came off and we floated away&lt;/q&gt; - &lt;cite&gt;Mr Sköld in &lt;a href="http://phuketgazette.com/news/index.asp?id=3873"&gt;Daily News&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;We were standing there taking pictures and the wave started coming back, faster and faster, so we started to run away, faster and faster, but my parents didn’t run fast enough.&lt;/q&gt; - &lt;cite&gt;Mrs Holmberg in &lt;a href="http://phuketgazette.com/news/index.asp?id=3873"&gt;Daily News&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;Jayanti Lakshmi, 70, had gone shopping with her daughter-in-law in Cuddalore, southern India. Ms Lakshmi returned to find her son and twin grandsons dead in their hut.&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://news.bbc.co.uk/2/hi/south_asia/4125481.stm"&gt;BBC&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;People that were snorkeling were dragged along the coral and washed up on the beach, and people that were sunbathing got washed into the sea.&lt;/q&gt; - &lt;cite&gt;Simon Clark in &lt;a href="http://www.cnn.com/2004/WORLD/asiapcf/12/26/quake.thailand.ap/"&gt;CNN&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;My mate's staying in a police station for the night and luckily she hasn't had to go through the trauma that some of the survivors of the tsunami have had to go through.&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://www.eshindirect.com/index/P604/"&gt;Eshin&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;I feel sad too to see the victim, and the tsunami is 9 mtr high, and it swept out all the living near the beach...&lt;/q&gt; - &lt;cite&gt;In a post to &lt;a href="http://momm-on-the-net.blogspot.com/2004/12/tsunami-swept-out-our-dearest.html"&gt;Meg&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;People are rushing out from the coastal area into town, ambulance the other way round. Bodies have been found, many still missing, millions worth of assets damage, coastline of Penang is in mess.&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://calmocean.blog.com/84553/"&gt;calmocean&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;It's the way of the world. There's only so much we can do against the forces of nature.&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://www.livejournal.com/users/aerna/19971.html"&gt;Aerna&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;We called up our friends in South India and Sri Lanka and they are safe.  Still, they know people who have been affected and some are still missing. We are all affected.&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://radio.weblogs.com/0121664/2004/12/27.html#a544"&gt;Dina Mehta&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;The wave(s) that came were 4-5 m high. If they could pick up those cars and throw them over the fence, we wouldn't have had a chance.&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://www.command-post.org/nk/2_archives/018250.html"&gt;The Command Post&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;There was an earthquake, after five minutes there was water all around and we ran away. When we came back, our homes had been destroyed&lt;/q&gt; - &lt;cite&gt;in &lt;a href="http://www.ndtv.com/template/template.asp?template=Tsunami&amp;slug=Thousands+missing+in+Andamans&amp;id=15967&amp;callid=0&amp;category=National"&gt;NDTV&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;As we watched it became apparent that the sea was behaving very oddly. Waves were not breaking as normal. The sea appeared to be surging. One such surge practically emptied what we could see of the bay. This was followed by the sea moving repidly back into the bay and reaching right up to the promanade area (and possibly beyond) [...] At no time could we make out any people.&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://blogs.vbcity.com/shandy/archive/2004/12/27/535.aspx"&gt;Andrew Sutton&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;Later on we went down to the beach and believe me, the paradise has been changed to hell. We know also for sure that the official figures underestimate the number of casualtiesa, if you think about all the fishermen.&lt;/q&gt; - &lt;cite&gt;(&lt;a href="http://weblogs.asp.net/pleloup/archive/2004/12/27/332577.aspx"&gt;via&lt;/a&gt;)&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;He recounted hearing what sounded like repeated explosions coming from the coast. When he left his home to investigate, he spotted a wave towering above the tree line about a mile inland.&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://story.news.yahoo.com/news?tmpl=story2&amp;u=/washpost/20041227/ts_washpost/a26306_2004dec26"&gt;Yahoo! News&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;Since I was now sure I was fully awake, I sat on the bed. There it was again. There was a definite tremor in my bed. It went on for another two minutes.&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://www.madmanweb.com/archives/0412the_earthquake.html"&gt;MadMan&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;I heard an eerie sound that I have never heard before. It was a high pitched sound followed by a deafening roar. I told everyone to run for their life.&lt;/q&gt; - &lt;cite&gt;Chellappa in &lt;a href="http://www.reuters.com/newsArticle.jhtml?type=topNews&amp;storyID=7180170&amp;src=rss/topNews"&gt;Reuters&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;At 10am (local time) all of a sudden, just out of nowhere, a massive wall of water came through. There are cars upturned and floating, there's debris, there are beach chairs and beach umbrellas, bits of restaurants are starting to float by.&lt;/q&gt; - &lt;cite&gt;Australian State MP John Hyde in &lt;a href="http://smh.com.au/news/World/I-could-see-dead-bodies-all-around/2004/12/27/1103996463532.html?oneclick=true"&gt;smh.com.au&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;&lt;q&gt;...her family lives right on the beach. Her frantic phone calls were unanswered. Her husband and teenage son, who just celebrated his birthday a month or two ago, are either homeless or dead.&lt;/q&gt; - &lt;cite&gt;&lt;a href="http://davidlok.blogspot.com/2004/12/i-had-quite-happy-boxing-day-and-was.html"&gt;David Lok&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;A lot of these were originally compiled by &lt;a href="http://www.livejournal.com/users/insomnia/525268.html"&gt;Insomnia&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110421650275227903?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110421650275227903/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110421650275227903' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110421650275227903'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110421650275227903'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2004/12/earthquake-tsunami.html' title='Earthquake! Tsunami!'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110412003450484577</id><published>2004-12-27T09:30:00.000+05:30</published><updated>2006-10-21T20:11:55.317+05:30</updated><title type='text'>Tropical Snowflakes</title><content type='html'>&lt;a href='http://photos1.blogger.com/img/77/1572/1024/Bryant-Park%2C-Kodai-3.jpg'&gt;&lt;img border='0' style='border:1px solid #AAAAAA; margin:2px' src='http://photos1.blogger.com/img/77/1572/400/Bryant-Park%2C-Kodai-3.jpg' /&gt;&lt;/a&gt;&lt;p class="ImageCaption"&gt;Tropical Snowflakes&lt;/p&gt;It doesn't snow much in India, not even in Kodaikanal. But that doesn't stop nature from placing beautiful white fluffs all over the place in the winters. Shot in Bryant Park, Kodaikanal.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110412003450484577?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110412003450484577/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110412003450484577' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110412003450484577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110412003450484577'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2004/12/tropical-snowflakes.html' title='Tropical Snowflakes'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110408288043346706</id><published>2004-12-26T23:09:00.000+05:30</published><updated>2006-10-21T20:11:55.251+05:30</updated><title type='text'>A Very Good Year</title><content type='html'>According to &lt;a href="http://www.w3schools.com/browsers/browsers_stats.asp"&gt;the browser stats&lt;/a&gt; maintained at the W3Schools, this December the number of Mozilla (mostly Firefox) users was more than 20% of the Internet's crowds. That's a leap from 8.2% to 21.2% in a year. Internet Explorer crashed from a high of 84.1% to 71.7%.&lt;br /&gt;&lt;br /&gt;Let that sink in again. One in every five users is a Firefox user.&lt;br /&gt;&lt;br /&gt;I like the sound of that. I think that makes this a very happy year! Cheers to that!&lt;br /&gt;&lt;br /&gt;Did you &lt;a href="http://www.spreadfirefox.com/?q=affiliates&amp;id=28224&amp;t=86"&gt;get Firefox&lt;/a&gt; yet?&lt;br /&gt;&lt;br /&gt;&lt;div class="Previously"&gt;Previously:&lt;ul&gt;&lt;li&gt;&lt;a href="http://piecesofrakesh.blogspot.com/2004/11/browser-trends.html"&gt;Browser Trends&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110408288043346706?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110408288043346706/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110408288043346706' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110408288043346706'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110408288043346706'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2004/12/very-good-year.html' title='A Very Good Year'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110400454786728365</id><published>2004-12-26T01:27:00.000+05:30</published><updated>2006-10-21T20:11:55.187+05:30</updated><title type='text'>Link Bin</title><content type='html'>Long time no idea for a post. It's time for a link dump!&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A great article on &lt;a href="http://jibbering.com/2002/4/httprequest.html"&gt;Using the XMLHttpRequest Object&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.ioih.org/"&gt;The Institute of Internet History&lt;/a&gt; (&lt;a href="http://science.slashdot.org/article.pl?sid=04/12/05/1615211&amp;from=rss"&gt;via&lt;/a&gt;) - for a record of the origins of the Internet.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.wired.com/news/technology/0,1282,65906-2,00.html?tw=wn_story_page_next1"&gt;Some people just done care about spyware&lt;/a&gt;!&lt;/li&gt;&lt;li&gt;&lt;a href="http://developers.slashdot.org/article.pl?sid=04/12/16/2319240&amp;from=rss"&gt;A slashdot review&lt;/a&gt; of &lt;a href="http://www.amazon.com/exec/obidos/redirect?tag=piecesofrakes-20&amp;amp;path=tg%2Fdetail%2F-%2F0975514008%2Fqid%3D1104002857%2Fsr%3D1-1%2Fref%3Dsr_1_1%3Fv%3Dglance%26s%3Dbooks"&gt;Debugging Indian Computer Programmers: Dude, Did I Steal Your Job?&lt;/a&gt; by N. Sivakumar. The comments that ensue are very interesting.&lt;/li&gt;&lt;li&gt;Now, after the iPod, &lt;a href="http://www.mikeindustries.com/blog/archive/2004/12/iphone-prediction-confirmed"&gt;it's the iPhone&lt;/a&gt;!&lt;/li&gt;&lt;li&gt;Don't boot me! &lt;a href="http://www.legalaffairs.org/issues/January-February-2005/feature_sokis_janfeb05.html"&gt;I'll sue you&lt;/a&gt;! (&lt;a href="http://slashdot.org/article.pl?sid=04/12/19/1913215&amp;from=rss"&gt;via&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.wired.com/wired/archive/12.12/view.html?pg=2"&gt;Why nerds are unpopular&lt;/a&gt;. Now you know.&lt;/li&gt;&lt;li&gt;Orgasms at a push of a button, &lt;a href="http://www.wired.com/news/culture/0,1284,66052,00.html"&gt;now available on your cell phone&lt;/a&gt;. (I love her columns, by the way.)&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.infoworld.com/article/04/11/19/47FEtop20_1.html"&gt;Top 20 IT mistakes to avoid&lt;/a&gt;. At #11 is "Developing Web apps for IE only".&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.useit.com/alertbox/20041206.html"&gt;Most hated online advertising techniques&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Google that speaks. &lt;a href="http://www.speegle.co.uk/"&gt;Speegle&lt;/a&gt;. (&lt;a href="http://news.bbc.co.uk/2/hi/technology/4079005.stm"&gt;via&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.google.com/press/zeitgeist.html"&gt;2004 Year-End Google Zeitgeist&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://brucelawson.co.uk/zengarden.htm"&gt;CSS Zen Garden&lt;/a&gt;? (&lt;a href="http://annevankesteren.nl/archives/href/2004/12#link-1109"&gt;via&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;&lt;q&gt;Our relationship just hasn't been working for a while, and now, this is it. &lt;a href="http://reviews.cnet.com/4520-3513_7-5570803-1.html?tag=nl.e497"&gt;I'm leaving you for another browser&lt;/a&gt;.&lt;/q&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.jackflannel.org/lotr/"&gt;The Nit Picker's Guide to the Lord of the Rings&lt;/a&gt; - so that you know where the movie went wrong.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110400454786728365?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110400454786728365/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110400454786728365' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110400454786728365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110400454786728365'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2004/12/link-bin_26.html' title='Link Bin'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110391936685446221</id><published>2004-12-25T01:46:00.000+05:30</published><updated>2006-10-21T20:11:55.120+05:30</updated><title type='text'>Ho Ho Ho!</title><content type='html'>From a friend over &lt;abbr title="Short Message Service"&gt;SMS&lt;/abbr&gt;, a few days before Christmas:&lt;br /&gt;&lt;blockquote&gt;Merry X'mas. A bit early I know, but there's thousands of beautiful and sexy people to wish, so I thought I'd start with the ugly fuckers first.&lt;/blockquote&gt;Merry Christmas to you too! Hope you have a great time!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110391936685446221?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110391936685446221/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110391936685446221' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110391936685446221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110391936685446221'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2004/12/ho-ho-ho.html' title='Ho Ho Ho!'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110374509697004769</id><published>2004-12-23T01:21:00.000+05:30</published><updated>2006-10-21T20:11:55.044+05:30</updated><title type='text'>What Do You Suggest?</title><content type='html'>It's no news now, but some time ago &lt;a href="http://www.google.com/googleblog/2004/12/ive-got-suggestion.html"&gt;Google announced&lt;/a&gt; the launch of &lt;a href="http://www.google.com/webhp?complete=1&amp;hl=en"&gt;Google Suggest&lt;/a&gt;. Sure enough, &lt;a href="http://slashdot.org/article.pl?sid=04/12/10/1554203&amp;from=rss"&gt;it got slashdotted&lt;/a&gt;. Some &lt;a href="http://www.sitepoint.com/blog-post-view.php?id=216588"&gt;talked&lt;/a&gt; about it, some &lt;a href="http://serversideguy.blogspot.com/2004/12/google-suggest-dissected.html"&gt;dissected&lt;/a&gt; it, some others &lt;a href="http://www.adamstiles.com/adam/2004/12/hacking_google_.html"&gt;hacked&lt;/a&gt; it.&lt;br /&gt;&lt;br /&gt;Then the &lt;a href="http://www.davenetics.com/2004/12/suggested-search.html"&gt;fun stuff&lt;/a&gt; started rolling out. Some others &lt;a href="http://labs.patrickgaskill.com/googlealphabet/"&gt;got more serious about the fun&lt;/a&gt;. Some others thought &lt;a href="http://www.theregister.co.uk/2004/12/14/googles_a_to_z/"&gt;the fun was news&lt;/a&gt;! Weird, isn't it?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110374509697004769?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110374509697004769/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110374509697004769' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110374509697004769'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110374509697004769'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2004/12/what-do-you-suggest.html' title='What Do You Suggest?'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110368469714405901</id><published>2004-12-22T08:34:00.000+05:30</published><updated>2006-10-21T20:11:54.975+05:30</updated><title type='text'>An Incredible Time</title><content type='html'>My 10 day holiday has now extended into 15 days, and I still can't have enough.&lt;br /&gt;&lt;div style="float:right"&gt;&lt;a href="http://www.amazon.com/exec/obidos/redirect?tag=piecesofrakes-20&amp;amp;path=ASIN%2FB00005JN4U%2Fqid%253D1103683719%2Fsr%253D11-1%2Fref%253Dsr%255F11%255F1"&gt;&lt;br /&gt;&lt;img src="http://images.amazon.com/images/P/B00005JN4U.01.MZZZZZZZ.jpg"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Yesterday, I went for &lt;a href="http://www.amazon.com/exec/obidos/redirect?tag=piecesofrakes-20&amp;amp;path=ASIN%2FB00005JN4U%2Fqid%253D1103683719%2Fsr%253D11-1%2Fref%253Dsr%255F11%255F1"&gt;The Incredibles&lt;/a&gt; - an animation by the really cool guys at &lt;a href="http://www.pixar.com/"&gt;Pixar Studios&lt;/a&gt; (the guys behind such movies as &lt;a href="http://www.amazon.com/exec/obidos/redirect?tag=piecesofrakes-20&amp;amp;path=tg%2Fdetail%2F-%2FB0000AQZYM%2Fref%3Dpd_ser_asin_6%3Fv%3Dglance%26s%3Dvideo"&gt;Finding Nemo&lt;/a&gt; and &lt;a href="http://www.amazon.com/exec/obidos/redirect?tag=piecesofrakes-20&amp;amp;path=tg%2Fdetail%2F-%2FB00003W8NO%2Fref%3Dpd_ser_asin_1%3Fv%3Dglance%26s%3Dvideo"&gt;Toy Story&lt;/a&gt;). It's a wonderful story about a family of retired super-heros who eventually get back into the "saving the world while wearing spandex" business, interspersed with very humorous takes on mid-life crises and growing up super-kids.&lt;br /&gt;&lt;br /&gt;Needless to say, this is a can't-miss.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110368469714405901?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110368469714405901/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110368469714405901' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110368469714405901'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110368469714405901'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2004/12/incredible-time.html' title='An Incredible Time'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110363166507897876</id><published>2004-12-21T17:46:00.000+05:30</published><updated>2006-10-21T20:11:54.908+05:30</updated><title type='text'>GMail Invites Again</title><content type='html'>I don't know a single person who doesn't have GMail already (ok, I do, but they don't need it anyway), so when I get invites, I turn to my blog.&lt;br /&gt;&lt;br /&gt;I've got 4 GMail invites with me. If you want an invite, leave me your first name, last name (yes, seriously - I am tired of making up first names and last names from e-mail addresses), and your e-mail address, and I'll zip you an invite within a day. I have only 4, so I'll give it off to the first 4 who write in.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110363166507897876?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110363166507897876/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110363166507897876' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110363166507897876'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110363166507897876'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2004/12/gmail-invites-again.html' title='GMail Invites Again'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110327569843025916</id><published>2004-12-17T15:00:00.000+05:30</published><updated>2006-10-21T20:11:54.837+05:30</updated><title type='text'>The Firefox NYT Ad Is Out</title><content type='html'>Sorry for one too many Firefox posts, but there's stuff happening that cannot be ignored.&lt;br /&gt;&lt;br /&gt;The Firefox advertisement that has been in the pipeline is &lt;a href="http://www.spreadfirefox.com/?q=node/view/8769"&gt;finally out&lt;/a&gt; on &lt;strong&gt;two&lt;/strong&gt; pages in the New York Times.&lt;br /&gt;&lt;br /&gt;For those who want to see a copy but cannot grab the &lt;abbr title="New York Times"&gt;NYT&lt;/abbr&gt;, you can download a &lt;a href="http://www.mozilla.org/press/nytimes-firefox-final.pdf"&gt;PDF version&lt;/a&gt; from the Mozilla site.&lt;br /&gt;&lt;br /&gt;&lt;div class="Previously"&gt;Previously:&lt;ul&gt;&lt;li&gt;&lt;a href="http://piecesofrakesh.blogspot.com/2004/10/more-on-firefox-nyt-ad-campaign.html"&gt;More On The Firefox NYT Campaign&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110327569843025916?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110327569843025916/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110327569843025916' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110327569843025916'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110327569843025916'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2004/12/firefox-nyt-ad-is-out.html' title='The Firefox NYT Ad Is Out'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110317790308569582</id><published>2004-12-16T11:42:00.000+05:30</published><updated>2006-10-21T20:11:54.758+05:30</updated><title type='text'>The Fox On Fire</title><content type='html'>&lt;div align="center"&gt;&lt;img src="http://photos2.flickr.com/2129105_d6546dfd25_o.png"&gt;&lt;/div&gt;Need I say more?&lt;br /&gt;&lt;br /&gt;That was on the 12th. Right now, its beyond 11 million. That's 11 million happy users. And a lot of happy developers. As I see it, there's only &lt;a href="http://www.microsoft.com/"&gt;one company in Redmond&lt;/a&gt; worried right now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110317790308569582?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110317790308569582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110317790308569582' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110317790308569582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110317790308569582'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2004/12/fox-on-fire.html' title='The Fox On Fire'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110317359391058328</id><published>2004-12-16T10:37:00.000+05:30</published><updated>2006-10-21T20:11:54.691+05:30</updated><title type='text'>I'm Back</title><content type='html'>It has been 12 days since I hit that "New Post" button. It feels so good to be clicking it again.&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://piecesofrakesh.blogspot.com/2004/12/well-be-right-back.html"&gt;my last post&lt;/a&gt;, I just assumed that &lt;q&gt;my site hits will plummet to a new low&lt;/q&gt;. However, when &lt;a href="http://mezzoblue.com/"&gt;Dave Shea&lt;/a&gt; gave me &lt;a href="http://mezzoblue.com/dailies/2004/12/08/"&gt;a link in his Dailies&lt;/a&gt;, it started a chain reaction with more site linking to me, resulting in one of the highest ever hits I have got on my site in one day. That effect is still to dwindle.&lt;br /&gt;&lt;br /&gt;Anyway, enough about when I was away. Let's get on with some more blogging, shall we?&lt;br /&gt;&lt;br /&gt;&lt;div class="Previously"&gt;Previously:&lt;ul&gt;&lt;li&gt;&lt;a href="http://piecesofrakesh.blogspot.com/2004/12/well-be-right-back.html"&gt;We'll Be Right Back&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110317359391058328?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110317359391058328/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110317359391058328' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110317359391058328'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110317359391058328'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2004/12/im-back.html' title='I&apos;m Back'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110219417058912136</id><published>2004-12-05T02:30:00.000+05:30</published><updated>2006-10-21T20:11:54.623+05:30</updated><title type='text'>We'll Be Right Back</title><content type='html'>I'm off for 10 days. I will be in a dusty town with no computer access, let alone the chance of getting online and making blog posts. I know my site hits will plummet to a new low. After all, since the inception of this blog, this is going to be the longest break I'll be taking from blogging. But I have to do this. I have no way out. &lt;br /&gt;&lt;br /&gt;Regular programming shall commence on the 16th of this month. Please don't go anywhere. We'll be right back after the break.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110219417058912136?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110219417058912136/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110219417058912136' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110219417058912136'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110219417058912136'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2004/12/well-be-right-back.html' title='We&apos;ll Be Right Back'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110219118904847784</id><published>2004-12-05T01:44:00.000+05:30</published><updated>2006-10-21T20:11:54.556+05:30</updated><title type='text'>Link Bin</title><content type='html'>This is probably going to be my largest link dump till date.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.idler.co.uk/html/library/crapjob.htm"&gt;Crap Jobs&lt;/a&gt; - &lt;q&gt;tales of woe can make for hilarious reading and it is with this in mind that the Idler Crap Job project began.&lt;/q&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.asktog.com/Bughouse/10MostPersistentBugs.html"&gt;The most persistent design bugs&lt;/a&gt; - some of the biggest mistakes we have yet to fix.&lt;/li&gt;&lt;li&gt;&lt;a href="http://johnhaller.com/jh/mozilla/portable_firefox/"&gt;Portable Firefox&lt;/a&gt; - keeping Firefox on a USB drive that you can carry around. (&lt;a href="http://www.hackaday.com/entry/1234000580021910/"&gt;via&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.yourtotalsite.com/archives/online_marketing/really_simple_and_fool_pr/"&gt;Really simple and foolproof traffic building tips&lt;/a&gt; - Nothing new, but a good summary.&lt;/li&gt;&lt;li&gt;&lt;a href="http://arabian-gulf.info/"&gt;Arabian Gulf&lt;/a&gt;? What Arabian Gulf?&lt;/li&gt;&lt;li&gt;WTF is that? &lt;a href="http://thedailywtf.com/ShowPost.aspx?PostID=25933"&gt;VB++&lt;/a&gt;?&lt;/li&gt;&lt;li&gt;I didn't like the semantics of the markup, but &lt;a href="http://www.sicl.co.uk/"&gt;these menus are awesome&lt;/a&gt;!&lt;/li&gt;&lt;li&gt;&lt;a href="http://joshuaink.com/blog/79/hicks-brands-joshuaink"&gt;Hicks rebrands Joshuaink&lt;/a&gt;. From the designer of the Firefox logo, here's his &lt;q&gt;finest work yet&lt;/q&gt;.&lt;/li&gt;&lt;li&gt;I found &lt;a href="http://flickr.com/photos/kt/sets/42312/"&gt;this interesting set&lt;/a&gt; over at Flickr the other day.&lt;/li&gt;&lt;li&gt;&lt;a href="http://news.bbc.co.uk/2/hi/technology/4061375.stm"&gt;Lycos launches attacks on spam servers&lt;/a&gt; by asking users to install a screen-saver, like how the SETI project worked. (&lt;a href="http://it.slashdot.org/article.pl?sid=04/12/02/2221253&amp;from=rss"&gt;via&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.theregister.co.uk/2004/12/02/speeding_excuses/"&gt;Worst excuses people give after being caught speeding&lt;/a&gt; by the safety cameras. (&lt;a href="http://techdirt.com/articles/20041202/1031246_F.shtml"&gt;via&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;An &lt;a href="http://www.fastcompany.com/fast50_05/profile/?stewart_butterfield718"&gt;interview with the co-founders of Flickr&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.diebierdose.de/english/download/dowpop.html"&gt;Beer logos&lt;/a&gt;, available for download in Illustrator and EPS formats. (&lt;a href="http://www.simplebits.com/quickbits/#1102092918"&gt;via&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Wikinews (&lt;a href="http://en.wikinews.org/"&gt;English&lt;/a&gt;, &lt;a href="http://de.wikinews.org/"&gt;German&lt;/a&gt;) launched by &lt;a href="http://www.wikimediafoundation.org/"&gt;The Wikimedia Foundation&lt;/a&gt; (the guys behind the hugely successful &lt;a href="http://en.wikipedia.org/"&gt;Wikipeida&lt;/a&gt;) launch the Wikinews, &lt;q&gt;a free news-source created collaboratively by volunteers around the planet&lt;/q&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.heise.de/english/newsticker/news/53904"&gt;Firefox users ignore ads&lt;/a&gt;. Now I know why it'll really take 5 years for me to get any money for my ads on this site!&lt;/li&gt;&lt;li&gt;&lt;a href="http://monster-island.org/tinashumor/humor/techcalls.html"&gt;Tech Support jokes&lt;/a&gt;. And &lt;a href="http://rinkworks.com/stupid/cs_calls.shtml"&gt;more Tech Support jokes&lt;/a&gt;. (&lt;a href="http://www.linkbunnies.org/archives/2004/12/03/sometimes_i_thi.php"&gt;via&lt;/a&gt;)&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110219118904847784?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110219118904847784/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110219118904847784' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110219118904847784'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110219118904847784'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2004/12/link-bin.html' title='Link Bin'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110206615556106480</id><published>2004-12-03T14:54:00.000+05:30</published><updated>2006-10-21T20:11:54.489+05:30</updated><title type='text'>Fatal Error</title><content type='html'>A small mistake in my previous post, a bandwidth crunch over my network, and Blogger's servers going down temporarily all happened at the same time, pulling my site down for a couple of minutes. I've fixed most of the things now, and everything should work as normal. Only my feeds would have (probably) gotten a little cluttered with titles linking to non-existant posts. I apologize for the confusion. I'll try my best to ensure that it doesn't recur.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110206615556106480?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110206615556106480/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110206615556106480' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110206615556106480'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110206615556106480'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2004/12/fatal-error.html' title='Fatal Error'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110206086110956808</id><published>2004-12-03T13:44:00.002+05:30</published><updated>2006-10-21T20:11:54.332+05:30</updated><title type='text'>Continuum Navigation Links</title><content type='html'>Heavily inspired by &lt;a href="http://lukew.com/ff/entry.asp?99"&gt;Web-log Continuums&lt;/a&gt; at &lt;a href="http://lukew.com/ff/index.asp"&gt;Functioning Form&lt;/a&gt;, I have started adding a list of relevent links, titled "Previously", at the bottom of some of my posts.&lt;blockquote&gt;This lays out a contextually relevant path for readers who are interested in how a particular idea has continued to evolve on this blog.&lt;/blockquote&gt;Though the idea presented there is rather complex to implement, I decided I'd rather get started with using them in my blog. Currently, I am manually adding the links and the relevent markup and style. In my &lt;a href="http://stijlstek.nl/greek2me/2004/12/perfect-weblog-system/"&gt;"Perfect Blogging &lt;abbr title="Content Management System"&gt;CMS&lt;/abbr&gt;"&lt;/a&gt;, these links will be more detailed, and will be inserted automatically. But then again, perfect blogging CMSs have yet to see the light of the day.&lt;br /&gt;&lt;br /&gt;From my site's stats, the continuum navigation looks well received. I would appreciate it if you could tell me first-hand if you like this type of navigation, or if you think it is just some clutter-stub.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110206086110956808?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110206086110956808/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110206086110956808' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110206086110956808'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110206086110956808'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2004/12/continuum-navigation-links.html' title='Continuum Navigation Links'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110205704378499130</id><published>2004-12-03T13:28:00.000+05:30</published><updated>2006-10-21T20:11:54.090+05:30</updated><title type='text'>Road To Ten Million</title><content type='html'>From &lt;a href="http://www.spreadfirefox.com/?q=node/view/7911"&gt;a recent post on the SFx Site&lt;/a&gt;:&lt;blockquote&gt;In just 23 days, you all have helped over 8,000,000 people discover a better Web experience. If we keep up this pace, we have a shot at hitting 10 million downloads in the first month.&lt;/blockquote&gt;Please do your bit. &lt;a href="http://www.spreadfirefox.com/?q=node/view/7764"&gt;Get a co-worker to switch&lt;/a&gt;. &lt;a href="http://www.spreadfirefox.com/?q=node/view/6541"&gt;Give it as a Christmas gift&lt;/a&gt;. &lt;a href="http://www.spreadfirefox.com/?q=node/view/6261"&gt;Spread it in your school&lt;/a&gt;. &lt;a href="http://www.spreadfirefox.com/?q=node/view/3768"&gt;Talk about it to your Internet Cafe guys&lt;/a&gt;. Do anything you can. Let's make browser history!&lt;br /&gt;&lt;br /&gt;&lt;div class="Previously"&gt;Previously:&lt;ul&gt;&lt;li&gt;&lt;a href="http://piecesofrakesh.blogspot.com/2004/11/1-day-1000000-downloads.html"&gt;1 Day, 1,000,000+ Downloads&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110205704378499130?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110205704378499130/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110205704378499130' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110205704378499130'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110205704378499130'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2004/12/road-to-ten-million.html' title='Road To Ten Million'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8112154.post-110192602779520766</id><published>2004-12-01T23:47:00.000+05:30</published><updated>2006-10-21T20:11:54.009+05:30</updated><title type='text'>World AIDS Day</title><content type='html'>&lt;div style="float:right"&gt;&lt;img border='0' style='border:1px solid #AAAAAA; margin:2px' src='http://photos1.blogger.com/img/77/1572/400/ribbon_aids_day.1.jpg' /&gt;&lt;/div&gt;Just a quick note to remind everyone that &lt;a href="http://www.worldaidsday.org/"&gt;the &lt;abbr title="Acquired Immune Deficiency Syndrome"&gt;AIDS&lt;/abbr&gt; threat is real&lt;/a&gt;. Please do what you can in your powers to prevent it, and help those who are suffering.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8112154-110192602779520766?l=blog.rakeshpai.me' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.rakeshpai.me/feeds/110192602779520766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8112154&amp;postID=110192602779520766' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110192602779520766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8112154/posts/default/110192602779520766'/><link rel='alternate' type='text/html' href='http://blog.rakeshpai.me/2004/12/world-aids-day_01.html' title='World AIDS Day'/><author><name>Rakesh Pai</name><uri>http://www.blogger.com/profile/00328152982823663876</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry></feed>
