Of course, we’re all already familiar with the front-end performance gains of putting your Javascripts at the bottom of the page but this can be inconvenient. Sometimes it’s just easier to put a little $(onready) action in the middle of a page – eg: so I can include form-validation logic in the same partial as the form itself. (I think this still counts as progressive enhancement.)
The problem is that without $() defined in the head of your page, you’ll get errors adding onready callbacks to jQuery – and we especially want to hold back script src tags until the bottom of the page. Blocking rendering + an extra http request … but there’s a alternative! We can have our cake and eat it too.
This is all that goes in your document head:
<script type="text/javascript" charset="utf-8">
var $sanddollars=[],$=function(cb){$sanddollars.push(cb)};
</script>
And then after you’ve included jQuery.js, (just before the closing body tag, or in your jquery.extras.js file) include this callback to activate your stored functions:
<script type="text/javascript" charset="utf-8">
$(function(){$.each($sanddollars,function(){$(this)})});
</script>
Like magic, any $() callbacks you have peppered through the page will be picked up and used by jQuery, even though you include it last!
This is just something I came up with to solve a problem on Grabb.it today. I was happy to get it done so simply. Maybe there are other implementations of the same idea out there. Let me know if you spot any!
Here’s the video of my talk last night. There’s also an mp3 file of the AppDrop PDX.rb Talk if you’d prefer audio.
I was unable to add slides to the video, but Amy did a great job capturing the slides on camera – slides are also available as a pdf so you can follow along at home if you’d like.
Thanks to PDX.rb for giving me the opportunity to put this out there.
OK not really. I’m coming to grips with that I might have lost some data. Not everything (most of my music-recording is backed up or on other hard drives) but some key stuff (ssh key that is) so that’s a pita.
sudo ddrescue -v /dev/disk2s2 /Volumes/Kayak/brindle.dmg /Volumes/Kayak/brindle-rescue.log
DDRescue seems to be working slowly, but I think the disc may have shutdown, so it’s time for a reboot to see if that helps. I’m gonna seek to the middle of the disc and see if it’s faster.
I’ve been holding out on Leopard but I think I’m gonna upgrade (and configure Time Machine). Fun fun fun.
The jobs for which App Engine will really shine are the ones for which lock-in is not really an issue. I’ve spent some time in the bottom-of-the-barrel web consulting trenches. As a HTML/PHP monkey for local coffee shops, you can burn up a lot of (mostly unpaid) time fixing little crap that would never come up on App Engine. When your host screws with their Apache conf and you have to change a global variable somewhere, 6 months after you considered the project done, there’s only so many free lattes you can drink before your head explodes. With App Engine, the promise is, that will never happen again.
Assuming the whole thing bootstraps like it should, we’ll soon see Drupal and shopping carts and blog engines all running in the App Engine container. We’ll also see people fork AppDrop’s code to make it more stable and scalable, and perhaps charge a modest fee for hosting it (sites like Dreamhost will include it in existing packages). The idea that they’d have to invest engineering time in writing a Big Table clone is ludicrous. The applications in this sweet spot don’t need high scalability. Backing the datastore API with MySQL would more than serve the needs for this constituency, slotting smoothly into existing infrastructure.
The App Engine sweet spot is a lot closer to GeoCities than to Joyent. It’s defining characteristic is fire-and-forget, with standardization as a close second. When clients need to add features to an existing application, bringing a new developer up to speed will be even easier than on a Rails project. Sheesh, it took me 2 hours to write and deploy my first App Engine app, and I spent half that time learning Python.
There are two senses in which one can understand the question, “Will it scale?”: In the technical sense Google has convinced us that their implementation can handle high traffic loads (if you are willing to pay). In the social sense, the sense in which crappy-but-simple often scales (examples being PHP, AK-47s, and $30 cellphones), I hope AppDrop has made the point that standardized App Engine compatible containers can also scale.
But just because the sweet spot is local coffee shops and flash games written by high-schoolers, doesn’t mean clever developers can’t make App Engine a part of their toolkit for more ambitious projects. More on that in a later post.
With Google’s release of App Engine, we felt the opportunity landscape of the web shift a little under our feet. With the advent of true fire-and-forget dynamic websites, the kinds of projects that will be economical to try has expanded enormously. Truly, just throw it against the wall and see if it sticks. And if it takes a year or two to start making money, no worries. You’ll have created 20 other apps in the meantime.
I heard grumblings about lock in on the one hand, and pronouncements of web-Hypercard on the other, and figured that writing an argument pushing back against the lock in question would not be half as effective as doing something.
Host your App Engine applications on my new site, AppDrop.com, it’s lotsa fun, and pretty much works. I didn’t build it to scale, or for extra security – but it is open source, so if you are up for it, there are links to the GitHub projects from the App Drop homepage. It should be relatively straightforward to build your own App Engine host. It looks like applanding.com is still available…
I don’t think Amazon has anything to worry about here. The slice of the pie that needs to run 25-machine Hadoop jobs is getting bigger all the time. Until Google provides open access to their real compute cluster, I don’t see a threat to that. As I said in my last post, I could see porting the user side of Grabb.it to AppSpot (or AppDrop) and using the urlfetch api to keep the storage in CouchDB on EC2 (where I can manage a web-scale spider). Hey, aren’t we supposed to keep our user data seperate from our application data? This might be a way to get cheaper, lower-latency HTML serving, without any real lock-in.
I managed to swing an AppEngine account on the first day, and build an app and everything. The hardest part was deciding what to build. For that I asked my lovely wife Amy and after talking about it we decided that the best thing for the world would be more snarky comments about celebrities. You’ve heard of Go Fug Yourself – now everyone can get in on the action with Fug This!
The application is simple. Just a bookmarklet to post new Fugs into the system, and a page to display the fugs. We’ll probably add RSS feeds and user pages once I learn Python. :)
If you want to see how simple it really is (one python file, a yaml configuration file, and a template) I’ve released the whole thing on GitHub—if anyone wants to add pagination, that’d be sweet!
About the only complicated bit in the whole application is storing blobs of photos in the database (and that was in part due to an inconsistency between Google’s Python implementation and the one on my Mac).
I can see AppEngine really taking off, once Google starts supporting real programming languages (like Javascript) in their runtime. You can’t run background tasks in AppEngine. But who cares?—If you are doing a web-crawl or RSS feeds or something where you have serious software and data, you’d be stupid to give it to Google anyway. But for lightning fast page serving and no-hassle scalability, AppEngine is the way to go.
I can easily see building the next generation of Grabb.it as an EC2-based web crawling MapReducer, with its client front-side hosted on AppEngine.
It was so easy I forgot it was Python. :)

Grabb.it has revved up another notch.
Version 1.0 began in 2005 as a hobby project to learn Rails. Early 2007, we started from scratch on Grabb.it 2.0, released last May. Meet rev 3.
We’re shifting the focus to mp3 blogs – they’ve be around a while, but the new UI puts them out front. So if you love music and blogging, we’ll be doing a little of both around there, and you’re welcome to join us.
Here’s some old-time music I grabbed from the Berea Music Archive ages ago:
Occasionally I forget to mention some of the little things I come across when hacking. Here’s another one for my series:
The first is a compound selector, sets a light-grey color on links inside .calendar elements, and links with class .user that are inside the DOM element #adiv
#adiv a.user, .calendar a {
color:#aaa;
}
We want a hover color for most links, just not the calendar links (don’t ask me why.) So we apply the hover color to all links.
a.user:hover {
color:#f00;
}
This should set a hover color on just the .user paragraphs. Sadly it has no effect. The reason:
The spec gives you the formula to calculate specificity.
A selector’s specificity is calculated as follows:
Example(s):
* {} /* a=0 b=0 c=0 -> specificity = 0 */
LI {} /* a=0 b=0 c=1 -> specificity = 1 */
UL LI {} /* a=0 b=0 c=2 -> specificity = 2 */
UL OL+LI {} /* a=0 b=0 c=3 -> specificity = 3 */
H1 + *[REL=up]{} /* a=0 b=1 c=1 -> specificity = 11 */
UL OL LI.red {} /* a=0 b=1 c=3 -> specificity = 13 */
LI.red.level {} /* a=0 b=2 c=1 -> specificity = 21 */
#x34y {} /* a=1 b=0 c=0 -> specificity = 100 */
Increasing the specificity of your hover CSS will cover this corner-case and get the hover color working.
#adiv a.user:hover {
color:#f00;
}
This is required because the (#adiv a.user) color selector, has a higher specificity score (111) than a.user:hover, with only 21. By adding the #adiv, the resulting selector (#adiv a.user:hover) has specificity 121, so it overrides the color selector.
When faced with technical challenges like this, it is often worthwhile to reconsider the requirements which raise them. By relaxing the color selector so that it is not compound, for instance by adding a shared class to all the a links (a.grey) which should have the color or better yet, just applying color and hover-color to all links.Never underestimate the power of less code.
Ok this may be old news for some of you, but yesterday I wanted to send Javascript back to the client as part of an Ajax response, with a failure HTTP header. Specifically I wanted to send a flash message back when the user entered a wrong password on login. The details shouldn’t matter for you – you might expect jQuery to eval Javascript sent with a 4xx header just like it does with a success header.
Use this snippet and you’ll get that expected behavior:
$(window).bind('ajaxError', function (e, xhr, s) {
if (s.dataType == 'script' && xhr.responseText) {
$.globalEval(xhr.responseText);
}
});
Announcement ya’ll I just dropped the Grabb.it API Documentation and examples on a brand new Google group. I’m inviting you to come mix up our data, and providing some Javascript kit as well.
Click here for the Grabb.it Playlist API Documentation.
There are code examples and more REST theory on the way.
Embeded below is a simple Flash Player playing New Music from Grandpa Chris, a Grabb.it XSPF playlist:
(consider me surprised if that comes through your reader)
just saying…
I’m head-over-heels with enthusiasm for Mozilla’s Weave project, and see a unique opportunity to make the CouchDB HTTP protocol ubiquitous. I think it’s the best RESTful document API, and a perfect basis for the standard web data store. If someday we all have local CouchDB instances, with which we can grant access to various web services on a document basis, we’ll have all the ingredients we need to “take back the web.”
We should keep the cloud as dumb as possible to ensure that people can setup their own with freely available tools. The idea would be that while Mozilla would provide a basic set of optional services, it would be open and extensible so that individuals, groups, or companies could host their own either in whole (the entire cloud) or in part (a specific service for bookmarks). We should give people the flexibility to have as much or as little control of their own data as they want. —The Space Between
From the moment I heard about Weave I thought the ideal implementation would be generic and web-like. The use cases I’d like to see all revolve around users sharing their data with web services on an a-la-carte basis. Imagine a music-site allowing you to save playlists in a standard format (to your local Weave store). You could then grant other music sites access to that document, and they could provision audio or more recommendations based on the original playlist.
Above bookmark / profile stores, this would require that users could treat Weave as a synced and web-aware “filesystem”. In this case it would be helpful for Weave to annotate documents with type information.
As an implementation proposal, imagine that web sites access the local Weave store via HTTP. Then Javascript programmers could use the standard Ajax toolkit to request documents, and the server could alert users to requests and allow them to grant/deny access. Imagine Weave stores available at special urls like http://weave.local/path/to/document
Specifically, the CouchDB project is ready to be a drop-in document store. It already provides a RESTful API to documents with fine-grained access control. It’s eventual-consistency replication features would be ideal for syncing multiple Weave stores with backup(s) in the cloud (the cloud servers could also use CouchDB). Weave’s business logic could be implemented in an HTTP proxy between the access url and the CouchDB instance itself. Small pieces loosely joined.
I’ve got a lot of enthusiasm about this vision of Weave, but I understand that the project’s roadmap may not mesh with these ideas. I’m curious to know what both Weave and CouchDB developers think, and hope that something close to what I’m proposing will be feasible, if not as the core Weave implementation, as a simple extension.
Apologies for mentioning the iPhone thing. I’m getting sick of all the discussion too. Just one counter-point I need to make.
Certain negative comments I’ve seen on posts like the NY Times Bits blog disturb me deeply. The gist of the bad comments are “quit crying, baby, you took the risk and voided you’re warranty”. On them I call bullshit.
But the question is: where do people get the idea that one shouldn’t hack your own computer? My conjecture is that if you consider the iPhone as a fancy phone then it’s way cooler than anything LG is selling. But seeing it as a computer that happens to make calls and fit in your pocket, I’m offended and dismayed by Apple’s stance.
There is a reason Free Software advocates mean “free as in freedom” and to anyone who has been exposed to those ideas, any device which is essentially a computer, but which is actively hostile to its users, is deeply troubling. Computing (communications) and freedom go hand-in-hand, as we’ve seen time and again.
The enemies of freedom are scared by the widespread adoption of general purpose computing (it threatens their business model) and are trying as hard as they can to lock the doors. Should the new iPhone prove unhackable, it will show tyrants (and freedom fighters) that freedom and computing do not necessarily go hand in hand.
If Apple keeps this up much longer, they’ll go on my list of companies to put out of business. Freedom to compute as you wish is rapidly becoming as fundamental as freedom of speech, thought, and assembly. An enemy of freedom is an enemy of mine.
Astute readers may have noticed the increasing coverage of Grabb.it related topics in my various feeds. We’ve been putting the spit ‘n polish on for release. Hodel 3000, etc.
Basically all the things we have to do to iterate quickly and surely once we deploy. If you want to follow Grabb.it more closely, we’ve started a tumblr:
I’m running my blog again, just like before, but with more power! So if you were accustomed to looking at the old Daytime Running Lights, now you’ll get accustomed to looking at the new.
If you’ve got the time and inclination, head over to the index page and check out the variety of feeds available. Some of you might rather subscribe to Livin’ or maybe even Music. There is a new party in town called Vinyl where I’m blogging my parents’ huge record collection, one Jerry Jeff Walker or freaky chilled-out flute player at a time.