2010-06-12

Google BOM feature: ms since pageload

I expect this feature has been around for quite a while already, but this is the first time I have seen it: stealthy browser object model improvements letting a web page figure out how many milliseconds ago it was loaded. It presumably works in any web browser that is Chrome or that runs the Google Toolbar:

function msSincePageLoad() {
try {
var t = null;
if (window.chrome && chrome.csi)
t = chrome.csi().pageT;
if (t === null && window.gtbExternal)
t = window.gtbExternal.pageT();
if (t === null && window.external)
t = window.external.pageT;
} catch (e) {};
return t;
}


In Chrome it (chrome.csi().pageT, that is) even reports the time with decimals, for sub-millisecond precision.

Google, this kind of browser improvements should be blogged! Maybe even documented. All I caught in a brief googling for it were two now-garbage-collected tweets by Paul Irish, leading to where it was committed to Chromium, and a screenshot of the feature in action, along with all the other related features not brought up now:



The rest of this post, about how I happened upon it myself, is probably only interesting to the insatiably curious:

Upon having grown weary of all the Chinese automated porn/malware comment spam that passes through Blogger's sub-par spam filtering to my moderation inbox, I decided to replace it with one that is maintained by a service specializing in (and presumably committed to!) blog comments: Disqus. In the process, being lazy, I decided to let their template wizard install itself in my blog template, which required dropping my old blogger template, upgrading it a few versions, and then (only required by my own discerning taste) attempting to manually weed out the worst crud from the new template (none of which was added by Disqus, I might add).

In the apparently uneditable <b:include data='blog' name='all-head-content'/> section, sat a minified version of approximately this code, which seems to look up the vertical position of some latency-testing DOM node passed to it, the first time the visitor scrolls the page, if it's above the fold (which in Blogger's world is apparently a constant 750 pixels into the page :-). And maybe other things.

(function() {
function Ticker(x) {
this.t = {};
this.tick = function tick(name, data, time) {
time = time ? time : (new Date).getTime();
this.t[name] = [time, data];
};
this.tick("start", null, x);
}

window.jstiming = {
Timer: Ticker,
load: new Ticker
};

try {
var pt = null;
if (window.chrome && window.chrome.csi)
pt = Math.floor(window.chrome.csi().pageT);
if (pt == null && window.gtbExternal)
pt = window.gtbExternal.pageT();
if (pt == null && window.external)
pt = window.external.pageT;
if (pt) window.jstiming.pt = pt;
} catch (e) {};

window.tickAboveFold = function tickAboveFold(node) {
var y = 0;
if (node.offsetParent) {
do y += node.offsetTop;
while ((node = node.offsetParent))
}
if (y <= 750) window.jstiming.load.tick("aft");
};

var alreadyLoggedFirstScroll = false;

function onScroll() {
if (!alreadyLoggedFirstScroll) {
alreadyLoggedFirstScroll = true;
window.jstiming.load.tick("firstScrollTime");
}
}

if (window.addEventListener)
window.addEventListener("scroll", onScroll, false);
else
window.attachEvent("onscroll", onScroll);
})();

Safari Reader Underwhelm

I was somewhat underwhelmed by Safari Reader, mainly on account of the enforced extra friction their designers added to its UI, presumably to make it "look nice":

  • On top (and bottom, but I personally don't mind that part), it adds a drop shadow that makes text harder to read there, as is my personal habit.

  • Even worse, on navigating with the keyboard (arrow keys, Page Down or Up, and worst of all, Home / End), it painstakingly slowly SCROLLS you there -- instead of just snapping into place as Google Chrome, for instance, would. On at least a really page such as this great current SSD disks review, it takes over a second getting from top to bottom or back, which is just massively annoying.

    This actually applies to all of Safari to a lesser degree, I just never noticed it before, as I don't usually use Safari when reading long pages. In normal browsing, it seems to do it in about nine frames (and with ugly visual blits), over the course of somewhat too long a fraction of a second (this even on my massively over-powered state-of-the-art mac pro extra-everything).

    Update: This Safari "feature" can be disabled in System Preferences / Appearance on the mac; uncheck the box "Use smooth scrolling". (Thanks, Fredrik; I was unaware of this.)

  • A slight missed opportunity: every sub-page in the page gets its own top-right discreet "Page n of m" header. That much is great. It just isn't also a permalink to that sub-page, so if you want to toss someone a link to the relevant part (to your own discussion) of the known-to-be-huge article, well, you're out of luck and have to dig it up in non-Reader mode. Unwebby!

As a statement about what we should demand of our digital readership experience, I very much appreciate the idea (yes, in the greater business reality, it's a hypocritical move to strip ads from the web with one hand, while enforcing ads on devices you stepmother with the other -- but I care more about the web). They have just been encumbered by a bit too much Apple designerism. I hope that copycats will borrow the good parts and throw away the bad. Please don't copy Apple's bugs.

2010-04-03

Shaving cycles off your Firefox addon dev cycle

When developing Firefox extensions (like Greasemonkey), some of the best invested time you'll ever spend is on stuff making your change-restart-test cycle shorter, smoother and/or more convenient to you, whatever that looks like. Here are my own top suggestions:

  • As the Firefox extension model still requires a browser restart for many changes, make sure you at least don't have to repeat the messy part of packaging your xpi and installing it again over and over again (unless that is the part you are debugging at the moment).

    Reading the page on how extensions are installed on your operating system, replace the directory with your extension's guid with either a symlink to the directory where you develop your extension, or a file containing the path to it (if, say, you work on Windows with some file system that doesn't support symbolic links). Now you can edit your code, restart Firefox, and see the effect immediately without the extra steps of building an xpi and installing it every time you change something.

    (If your extension uses the more elaborate jar double zipping build procedure, my suggestion is "don't do that while developing", as doing more, invariable also takes more time and effort.)

  • Install the QuickRestart extension, as Firefox developers don't give you access to the crucial feature of restarting your session via keyboard hot key.

  • Check out the File menu and learn the hot key.

  • Some things can be updated without a browser restart, even in Firefox! (*) Set your development profile's about:config preference nglayout.debug.disable_xul_cache = true. <= this entire page is worth a read-through

  • Maybe you're poking around with things in an overlay in browser chrome and really just wish you could have a read-eval-print console into it, kind of like Firebug's. That's what MozRepl does. Install it, and now you can telnet or netcat into your browser session (from a terminal window, or maybe emacs), after focusing which window you want to have a prompt in.

  • If you are hacking on Greasemonkey specifically, and, say, poking with any of the stuff concerning gm_scripts and what is stored there, I suggest you cd into your gm_scripts directory, run git init, git add * and git commit -a -m 'Something descriptive' so you can revert to a prior state effortlessly with a git reset --hard before restarting, when your code changed something and you want to restart from a known earlier state.

That's all for today. Doubtlessly there are tons of other things that slim up the dev cycle. Feel free to post, or better still, link to other useful things to do. The docs at MDC are unfortunately too ill organized to easily strike gold there, so web pages that aggregate the nuggets are particularly valuable resources.

(*) Mozilla developers are hard at work making future extensions based on their (recently rebooted) Jetpack (SDK) project able to update without a browser restart, just like Greasemonkey scripts or Google Chrome extensions can. Any year now.