Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts

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);
})();

2009-05-10

Little projects I'm warming up to

I've been cooped up a lot between real life, work and a low energy budget for a while now, but think I'm getting a hankering for some ideas I'd like to develop or see developed, again. Here's a little off-the-top-of-my-head list of a few of them, small and large:

  • Data SVGs: Craft a few examples of how to encode data in its original raw form in SVG graph(ic)s and have the SVG render them right via coordinate transforms. Forward goal: get Wikipedia to incorporate this principle in their guidelines for how to represent data in vector graphics. Erik Möller (Deputy Director at Wikimedia Foundation) and Brion Vibber (CTO) both found this a cool idea. I ought to at least blog it if I'm not going to be the main advocate rallying people around the idea.
  • Migrate Kronos Utils (user script here), which I'm not maintaining or developing as much as I used to, and other ikariam related hackery I've done at some time or others, to github, so others that want to hack at it have an easier time forking it. I apparently started doing that, at some time or others, in an ikariam repository, and then promptly forgot about it. *pushes recent changes*

    So I guess this pretty much boils down to migrating my updates off of Google Code and onto githubg. And figuring out how to have my pushes and/or commits trigger a tweet to @ikariam_tools, which apparently people have already spotted and started following, despite its severe lack of content. :-) Does anyone remember how that is done? I seem to recall some setting somewhere for it at github, but wasn't successful finding it in all of a minute's scouting around.

    Oh, and figuring out how to have vc-mode in Emacs do git things.
  • Run the jQuery test suite from a Greasemonkey script, to figure out how much breaks under the Firefox javascript sandbox. It'll be nice to have fine grained data on which parts that remain useable and which don't, so maybe someone would even care to fix the latter.
  • Revive the live Exhibit web scraper thing I crafted some year ago and never got to the point of happiness with where I ever blogged about it. With recent development in Ext JS, it seems it could get a nice UI indeed, this time in a pop-open window, so I don't have the CSS invasion problem, and don't invade the DOM we're trying to scrape.
  • Don't fold comments on pages we arrived at through a permalink with a fragment pointing to something in the foldable section (at that point, we know we foremost wanted to read that specific comment, and not the article, so don't tuck it away). Edit: Done!

Taking down that specification in text instead of code seems indicative I'm not really in a coding mood today and ought to go have lunch. See you around!

2008-07-24

Fun with Greasemonkey: @require

After the release of Greasemonkey 0.8, the door is open for @require helper libraries, the user script take on Ruby's require, or the C family's #include pre-processor directive. For security reasons, the required library is downloaded a single time at script installation time, and from a functional perspective, is equivalent to pasting the script or scripts referenced at the top of your script, in the order of the @require lines listed. (==UserScript== headers in the referenced files are presently ignored, so a library may not yet use @require or @resource lines of its own.)

@require in practice makes user scripting scale down better, which is essentially to lower the threshold towards getting a job done, to a level where implementation cost to scratch an itch is so low that rather than feeling that mild annoyance with something twice, you address the issue once, and never see it happen again -- on that site, or the web at large. We are still far from there (in as much as "getting there" would ever happen -- that threshold can always be chipped off further, I assure you) -- but @require is healthy progress.

This is what the feature can look like in an example script of mine which adds image captions to online comics, by default Dinosaur Comics and xkcd (expect another upcoming post about $x and $X):
// ==UserScript==
// @name      Image title captions
// @namespace http://code.google.com/p/ecmanaut/
// @require   http://ecmanaut.googlecode.com/svn/trunk/lib/gm/$x$X.js
// ==/UserScript==

I'll be sharing some of my own helpers here, in a little series of "Fun with Greasemonkey" posts. I encourage you to write, and share, your own, on your blog, as well. User script authorship is a very social form of software, especially when you share your results on userscripts.org, and your best practices, for instance by way of blogging.

2008-06-05

Javascript books

I just received two javascript books I recently ordered from Amazon (the US branch, for once, since the dirt cheap dollar made shipping across the Atlantic notably favourable to shipping across the English Channel): John Resig's Pro javascript techniques and Douglas Crockford's Javascript: the good parts.

I had for the longest time (since the nineties) been of the opinion that the only javascript book worth getting was David Flanagan's Javascript: the definitive guide, which I at the time found excellent in it's third edition and still good (and much updated) in its fourth (by my cursory looks and used for reference, at least), but as two of my favourite authors on the subject of javascript (the last being Dean Edwards, whose primarily means of expression on the subject, so far, at least, is terse, solid code) have been published since then, it was time to challenge that assumption. And I'm quite glad to say that both were up to par.

Pro javascript techniques really shows Resig's experience in library writing, and shares lots of useful input and practices, and provides an enjoyable and rather useful walk-through of the popular javascript libraries of its day, which manages to still be fairly relevant, in spite of the evolution they have seen since its publication. Much the same applies to the bits and details it shares on browsers and the tool-chain, but that is to be expected. (I am really looking forward to its successor, Secrets of the javascript ninja, much of which can already be read online.) Particularly enjoyably and usefully, he shows off strengths of each library without much fuss.

As for Crockford's Javascript: the good parts, it follows his usual seasoned narrative which has earned him nicknames such as "the Yoda of javascript", and keeps a close focus on the more timeless parts of the core language itself, devoid of all the clutter and temporally challenged aspects of the document and browser object models. It follows a clean-slate approach to describing the beautiful parts of the language most worth learning, while warning about the pitfalls of some of its worst warts, and is just as enlightening as the rest of Doug's work. It's something of a feel-good book for javascript buffs wanting to meditate over their use of the language -- or at least it is for myself.

Great companions for a season where the weather merits some good outdoors rather than indoors geekery. ;-)

2007-08-22

Extending Greasemonkey by way of getters

Javascript getters and setters may be one of the most useful upcoming language features today (already working in some browsers, including Firefox), but google the feature and you will be swamped with articles and posts, not on how to put them to good use, but how to defend against malicious use of them for web pages tripping (Firefox / ditto extension) security holes. It's really just John Resig that stands out of the crowd, showing how it is done, suggesting good uses, and teaching the stuff.

Getters and setters are a Javascript 1.6 (IIRC) language feature that lets you provide interfaces that look and feel like DOM 0 interfaces, where you read and set a variable or property like document.title or document.links, and receive something that may or may not require computation, compositing and much else behind the scenes. The only news is that you can now implement things like the location object (set href and affect all the other properties in one go) from mere javascript and that the syntax is even rather friendly, by javascript standards:
var myLoc = (function() {
var url; // private variable hidden in the function closure

return {
toString: function() {
return this.href;
},
get href() {
return url;
},
set href(h) {
return url = h;
},
get prototcol() {
return url.match(/^.*?:/)[0];
},
set protocol(p) {
url = p + url.match(/^.*:(.*)/)[1];
return p;
}
};
})();
- which will yield you an object with an href and a protocol property you can tweak, just like any other, and see changes reflect to the other property, what you see if you alert(myLoc), and so on. It's a dream for making APIs that don't feel like java pushed down your throat with a ten-foot pole.

I've been meaning to add some features to Greasemonkey to grant it proper introspection (as all great software systems are introspective), for the Greasemonkey header block, and once I thought twice about it, for the source code at large. Something like a self object, with a "source" property for the code and a headers property for the parsed headers -- so self.headers.include would be the array of all @include headers, and so on.

I wanted that feature to give anybody the option to make their own cool extensions and libraries to Greasemonkey, making use of structured information -- much like an @xpath feature I've been noodling on on and off over the past few months to make GM scripts much more maintainable (and quick to write, and, optionally, self deprecating).

Anyway, the natural way of implementing this is via getters, and I was just about done when I hit a wall with Mozilla's extension API which wouldn't let the script executing in the Greasemonkey sandbox read my exposed getter variable (at the time named GM_headers): it threw a "Permission denied to get property Sandbox.GM_headers" exception when code accessed GM_headers, and that was that. Is this feature crippled for extensions wanting to provide getter / setter APIs from javascript code, or do I miss some incantations to bless the sandboxed code to read that?

The (hopefully) full picture of relevant details, surrounding my implementation:
var safeWin = new XPCNativeWrapper(unsafeContentWin);
var sandbox = new Components.utils.Sandbox(safeWin);
// ...
sandbox.__proto__ = {
get GM_headers() {
return headers.get();
}
};
sandbox.__proto__.__proto__ = safeWin;
This misfeature is also what stopped us from getting a responseXML property on the GM_xmlhttpRequest response object, earlier this spring. Any Mozilla hackers out there with solutions, knowledge or even just input on this? Your help and insights on this would be most valued.

2007-06-13

Javascript MD5 singleton

I really love how Yahoo! are spreading the gospel on sound javascript code practices and design patterns, popularizing good ideas among the masses, the most recent example being the module pattern.

In some ways it's the pop version of Douglas Crockford's writings on javascript, in this case private members in javascript, which tells the story of how almost any higher aspect of programming in javascript is accomplished through exploiting the few properties of the function keyword and closures. You can do most kinds of programming in javascript, there is just very rarely any syntactic aid for it.

By contrast, posts like this one would be the boring narrative recount telling you to read the gospel. I'm actually going to add a tiny bit more than that, though, and give an example of how to (re)structure code (not even necessarily your own) to use the module pattern, where it did not use to. It greatly helps keeping mess out of your way.

For a one-off hack (a user script that shows bookmark permalinks at del.icio.us, so you can share them with others, even before more people than yourself have bookmarked the url), I needed a javascript MD5 implementation. Paul Johnston's one (linked) is BSD licensed and works well, but exposes lots of namespace clutter, so I wrapped it up in an MD5 object, exposing only the bits I wanted from it.

Basically, I ended up framing the code inside a var MD5 = (function(){ /* original function definitions here */ return {hash:hex_md5}; })(); block, which exposes the only method I wanted as MD5.hash( data ). No namespace pollution, readable code.

Since an MD5 component is something I often want to use to interface with the world (here it was just to interface with Del.icio.us, which uses hex encoded MD5 hashes of urls for permalinks), I decided to go on and wrap up a version exposing the full (MD5 related) feature set of the lib, though, into a tidy MD5 module.

The API is very lightly wrapped, into methods MD5.string(data), which does a raw MD5 hash on its input string, MD5.hex(data), returning the same, but hexified, MD5.base64(data), ditto but base64 encoded instead, and the same method names with an "MD5.hmac." prefix for the hmac variants. (There is an MD5.test() method for good measure too.) The same config options as the original are supported too, and with the same default values, so set MD5.b64pad = "=" for real base64.

I thought I'd mention this too, here: if you want a similar javascript AES/Rijndael singleton, you should peek at Josh Davis's project on javascript cryptography, which has embarked on a similar path to the above since its conception. It might still be applying an UTF-8 codec on all data that passes through it, but if you need raw AES, just drop the few utf8 related lines, and you've got one.

2007-05-31

Google Gears: next quantum leap after XMLHttpRequest

Not much of great consequence has happened on the javascript, BOM and DOM in recent years since XMLHttpRequest and DOM 1.0. The large proprietary software people (Adobe, Apple, Microsoft, Sun) have all recently tried deploying new lock-in schemes of their own targeting the web to attract web developers into their proprietary, closed-source shackles under various flavours of EULAs and/or restrictions management, all of which will hopefully fail.

Brad Neuberg recently gave an Inventing the Future keynote speech at Yahoo FrontEnd Summit 2007, relating (among many things) that the secret to shaping the future is to be an inventive leader, in turn accomplished by combining leadership, great inventions and good values. There is much truth in that. I would personally add "working in the open" to the list.

This is exactly what Google is presently doing with Gears, which Aaron Boodman presented today (via) at Google Developer Day Sydney:



Google Gears is the next quantum leap in web development since XMLHttpRequest, addressing three of the largest issues with javascript webside development:

  • the lack of large scale (gigabyte range) client side storage,
  • offline availability of online resources, and
  • client side javascript freezing up the browser user interface due to its single-threaded design.
All this, in order to tackle the offline problem, which Brad Neuberg had incidentally been working with in the open for some time already for the Dojo Storage and Offline modules. Gears solves all rather beautifully with these three related but separate modules:

LocalServerLocalServer
caches and serves resources (HTML, javascript, images, et c.) locally,
DatabaseDatabase
stores data locally in a fully-searchable (SQLite) relational database
WorkerPoolWorkerPool
makes web applications more responsive by performing resource-intensive operations concurrently and asynchronously

I really recommend watching the half-an-hour presentation for the full story. Gears is already available for Firefox and Internet Explorer, soon for Safari, and, being fully new BSD licensed, allows anyone to port it to any other browser environment too. This is how you evolve the web. It is hardly coincidental that Aaron Boodman, who gave us Greasemonkey (licensed just as liberally) has been on the Gears team and gave the presentation.

2007-05-06

Useless content-*-type meta tags

I think it was in David Flanagan's Javascript: the Definitive Guide (recommended) that I picked up on the <meta name="content-script-type" content="text/javascript; charset=UTF-8"> tag, and, similarly, content-style-type, which lets you pick a default content-type for the <script> and <style> tags respectively (or so it would seem, to the naked eye).

I can't seem to find the book to verify the phrasing in JSDG, but at the time I read it, it sounded like a lovely way of doing away with the repetitive typing of type attributes for all tags of those kinds, throughout the entire document. Great!

Well, not so.

The HTML DTDs still require those type attributes (if you want your documents to verify as correct HTML), and the purpose of those meta tags is purely senseless standards masturbation mode and not this convenient Don't-Repeat-Yourself way of specifying a type and character set in one place only (so my ;charset=UTF-8 appendix is particularly misleading). The intent? Well, they mark the content type of the tag attributes (onclick="...", ..., style="...") where the HTML standard already declares sensible defaults. The relevant parts of the HTML standard linked above are very fuzzily phrased in terms of setting the default language for a document, so the misinterpretation is certainly very easy to do.

Thus it's not the ideal marriage with the pragmatic minimalist Douglas Crockford's advice of just dropping those type attributes all together and have browsers and web servers do the right thing for you. If you want your web pages to keep working after you have saved them (and their relatively linked required resources) to disk, you'd better keep those type attributes with charset specifications, or your browser will have to guess.

Which might not have been such a bad thing, had they only guessed UTF-8 for anything that could possibly be UTF-8. Oh, well.