13Apr

Props to the Digg developers…

Posted by Elf Sternberg as javascript, programming

I was looking at the Digg source code the other day and, I’ve gotta say, mega-props to the developer of their javascript. The traditional rule in web development has become, “Put your Javascript at the end of your page.”  That way, all of the DOM objects you might refer to are guaranteed to be present when you start referring to them.  This had been a chronic problem in web development, associated with much pulling of hair and gnashing of teeth. The more modern way is to load your scripts up front, but use jQuery’s $(document).ready(...) method to ensure that nothing would run until your DOM tree was loaded. You might still have to wait on media assets (you used to be able to say “images”, but with HTML5 media assets include sound and video), but the DOM will be there and ready. You’ll be free to set up onload events to the media assets. The $(document).ready(...) technique ensures that your javascript will run correctly but it still has one classic problem: download delay. If you want an anchor to do something more than just be a link when you click on it, you’ll have to live with the chance that the user will click on it before the javascript has run and it will just be a link. Digg doesn’t live with that. Instead of using $(document).ready(), they do something much more clever. In the header of their HTML document, they create unique event names that signal when some part of the page has been handed to the browser. You can do this with jQuery, which lets anything at all be an event. Let’s say you have an anchor that you want to do something funky when you click on it, something Ajaxy. First, in a javascript library that you load in the header, you define the function:

function dosomethingfunky() { /* ... do something funky with $(this) ... */ }

Then you bind it (note the completely custom event name):

$(document).bind('somethingfunky_ready', dosomethingfunky);

And finally, in the body, when the anchor has been loaded into the DOM, you trigger the set-up right there:

<a href="http://someexampleurl.com" id="somethingfunky">Funk Me!</a>
<script type="text/javascript">$(document).trigger('somethingfunky_ready');</script>

Now that’s cool.  Your race condition window is down to milliseconds; the event handler is probably set up even before the browser has a chance to render the object.  Yes, there’s a price: your page is littered with triggers and unobtrusiveness is a thing of the past.  But if you need this kind of set-up and performance, this is how it’s done, aesthetics be damned.

6 Responses to Props to the Digg developers…

Nathan Klatt

February 17th, 2011 at 10:54 am

Methinks this jQuery plugin would make for a cleaner solution:

http://plugins.jquery.com/project/available

Haven’t yet tried it myself, however.

Elf Sternberg

February 17th, 2011 at 11:13 am

Yes, that looks very cool. My only observation is that it polls during the construction process, so it takes a hot machine to handle it, and older computers will still suffer FLOUC (Flash of Unstructured Content). Still, it does look much cleaner than anything else, and certainly easier to manage, and I’ll probably find myself using it. Thanks for showing it to me.

Damian Pound

February 24th, 2016 at 12:03 pm

Is there any benefit to this over calling functions (ie window.Elf.somethingfunky_ready()) aside from not having a variable in the global scope? Otherwise it just seems like a really fancy trick. The general idea is useful though, define everything in a single cacheable file, then call the functions as needed.

I kinda did that in my own project, but for a different reason. I originally had a bunch of code inside a single IIFE that had pieces conditionally included/omitted by php depending on various things, any data needed was directly injected where needed (instead of defined in variables at the top of the IIFE), and it overall just looked like a huge mess. Now those individual pieces are functions that I can call as needed with whatever data is needed, but at the moment they are all called in the same place and run in the same event stack, no staggering of work is done through even a setTimeout(function() {},0).

Damian Pound

February 24th, 2016 at 12:41 pm

After looking at the code, it probably wouldn’t be better to bring my index_funcs file up above the header and then call the functions after the things they affect because that would require moving the 28 scripts (ridiculous, I know) it potentially depends on up too, which would significantly affect how long it takes for the header to show up. I need to look into this further…

Damian Pound

April 12th, 2016 at 9:34 am

Just realized a benefit over specifying functions on window: you can specify multiple functions for a single event. Though you could also just whip something up quick that does exactly that without the overhead of using the event system.

window.function_stacker=(function() {
var functions={};
return {
add:function(name,func) {
if (!functions.hasOwnProperty(name)) {functions[name]=[];}
functions[name].push(func);
}
,exec:function(name,args,that) {
if (!functions.hasOwnProperty(name)) {return;}
functions[name].forEach(function(func) {
func.apply(that||window,args);
});
}
};
}());

function_stacker.add(‘hello’,function(a) {alert(a);});
function_stacker.add(‘hello’,function(a) {console.log(a);});
function_stacker.exec(‘hello’,[‘world’]);

Damian Pound

April 12th, 2016 at 10:03 am

Forgot that jQuery().bind() allows specifying multiple events to handle… That would be a tad more difficult, but not by much.

Comment Form

Subscribe to Feed

Categories

Calendar

April 2010
M T W T F S S
« Mar   May »
 1234
567891011
12131415161718
19202122232425
2627282930