Saturday, April 17, 2010

1 Item Remaining Problem In IE

There are a bunch of different bugs in IE which manifest themselves as a page which doesn't finish loading and displays "X items remaining" (or "1 item remaining") in the status bar. C.M. Palmer on Stack Overflow has a pretty good answer for one of these bugs. I recently found an answer to another.

One of the symptoms of this particular bug (and probably others) is that it only happens in certain environments. I finally got access to one client's environment where this happened, and was able to track it down. Intermittently, and for no apparent reason, IE would fail to load the following script:

<script defer src=//:></script>

Yes, that's a script element with a src of "//:". This ugly hack is actually the best way to simulate the DOMContentLoaded event in IE (the event which signals that the HTML page has been parsed and its document object-model is fully built), as Dean Edwards and friends have figured out (they also tried src values of javascript:void(0), javascript:false, and //0 before settling on //:).

Fortunately, there's another trick that works for this purpose, as Diego Perini discovered: skip this ugly script element, and poll to check if document.body.doScroll() is working yet. The downside is that because it requires a timer to call doScroll() every X milliseconds, you won't be notified of the DOM's readiness quite as quickly as when using the "//:" hack (whereby you listen for onreadystatechange events on the script element — so you're notified of the readiness immediately, rather than having to poll for it).

The upside, of course, is that the doScroll() method works more reliably, with no "1 item remaining" for which to wait indefinitely. Another problem I had noticed in the past with the script element method was that IE sometimes would fire the onreadystate complete event before the DOM was loaded (and I had worked around that by checking if the page's footer element existed, and if not, waiting until it did). I haven't found any holes with this doScroll() technique yet, though, so I'm happy so far.

The 1.6.x version of the Prototype JavaScript Framework used the script technique (and I'm sure other libraries have, or still do); the 1.7 version has been updated with the doScroll() method. Here's the specific code it uses for the doScroll() technique (I've added comments where it uses Prototype-specific code, in case someone wants to adapt it to a non-Prototype environment):

(function() { /* Support for the DOMContentLoaded event is based on work by Dan Webb, Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */ var timer; function fireContentLoadedEvent() { if (document.loaded) return; if (timer) window.clearTimeout(timer); document.loaded = true; // raise the Prototype dom:loaded function // (your custom ondomcontentloaded code goes here) document.fire('dom:loaded'); } function checkReadyState() { if (document.readyState === 'complete') { // Prototype for removeEventListener()/detachEvent() document.stopObserving('readystatechange', checkReadyState); fireContentLoadedEvent(); } } function pollDoScroll() { try { document.documentElement.doScroll('left'); } catch(e) { // Prototype for setTimeout() timer = pollDoScroll.defer(); return; } fireContentLoadedEvent(); } if (document.addEventListener) { document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false); } else { // Prototype for addEventListener()/attachEvent() document.observe('readystatechange', checkReadyState); if (window == top) // Prototype for setTimeout() timer = pollDoScroll.defer(); } // Prototype for addEventListener()/attachEvent() Event.observe(window, 'load', fireContentLoadedEvent); })();

Saturday, April 3, 2010

These Aren't the Droids You're Looking For

So a few weeks ago Google contacted me about the Device Seeding Program for Top Android Market Developers — they wanted to give me (and a bunch of other developers) a free phone for having a popular app on the Android Market (mine is Ring Toggle). I thought "Awesome!", and signed up.

Throughout most of the world, Google is sending developers the Nexus One. In the US, they're sending half the developers (by random distribution) Nexus Ones, and half Motorola Droids. They shipped me my phone yesterday, and when I opened the box, it was a Droid.

I thought "Awesome!", and I shut down my old HTC G1, pulled out the SIM card and popped open the Droid. I hunted around inside the Droid's battery compartment, but I couldn't figure out where to stick the SIM. So I googled it — and it turns out the Droid is hardwired to Verizon's nextwork. Mother fucker!

Right now I've got six months left on my plan with T-Mobile, where I'm paying $30 for like 300 minutes and $25 for the data plan (plus 400 text messages). The cheapest equivalent plan with Verizon is $60 for 450 minutes and unlimited text messages, and $30 for the data plan. So to actually use this new Droid, I have to pay $90 a month on top of my existing T-mobile plan for the next six months. Thanks Google, thanks a bunch.

I know I shouldn't be angry at Google — giving away free android phones is really cool of them — but I can't help feeling that instead of a pat on the back, I got a kick in the nuts. And the thing is, after a few minutes of awkwardness when I turned on the Droid and followed the prompts to "activate" it by calling Verizon (the call-center guy was really nice, but even more confused than I was — turns out there's no point in calling Verizon because they have no clue what's going on), I found that the Droid is a really awesome android device. It's so much more responsive than my G1, and it's got the slicker 2.0 android OS (I'm stuck on 1.6).

So I'm completely sick because I want so badly to use this new Droid instead of my old G1, but I have a hard time justifying adding a second phone plan on top of the one I already have, especially since I don't really use my phone for phone purposes all that much. But at the same time, I can't justify lugging around two phones in my pocket, one to use as a phone and the other as an ipod. And I know I'm eventually going to give in and pay both T-Mobile and Verizon a bunch of money for the privilege of having a second-rate cellular-data plan and occasional phone service, just so I can carry around my super sweet new Droid in my pocket.

So I think a couple of big evil companies just played a Jedi mind trick on me.