64 Degrees of Bacon
No, this has nothing to do with Kevin. I looked at my computer’s notification area for the weather. It was 64 degrees of bacon.

Do an image search for “bacon signs.” Bacon is everywhere. Mmm…bacon…
What happened to rubyonrails.org?
I was on my way api.rubyonrails.org to look up something about routes when I was greeted by this:

According to the rubyonrails.org Whois record, the registration expired yesterday and was snatched up by BuyDomains.dk, LLC. Apparently this also happened in 2008, so it will probably get worked out again.
Until then I’m going to have to figure out ri.
Update 11:04 am: Looks like everything’s back to normal!*
Deploying your own EtherPad on Ubuntu
There are lots of walkthroughs on setting up your own EtherPad instance running around out there, but many of them either stop after localhost:9000 (hardly useful for a collaborative editing tool) or just don’t quite fit your situation.
I wanted to set up a public instance running at etherpad.jordanhollinger.com running behind an Apache proxy on top of Ubuntu Server 9.04. If you want to do something very much like that, this may be the walk-through for you. Otherwise, keep searching.
Before we begin you should
- be comfortable on the Linux command line
- have some notion of configuring Apache
- realize the EtherPad code base is in a state of flux
- realize this walk-through is intended more for a hobby instance than a fully-secured and enterprise-ready installation
- accept that your milage may vary
Also, note that the material for walk-through was culled from some wikis, several other EtherPad walkthroughs, and the Apache Web Server documentation. If at any point you run into trouble, you may want to peruse some of these source documents:
- code.google.com/p/etherpad/wiki/Instructions
- wiki.ubuntu.com/Etherpad
- karteek.selfdabba.com/post/301488675/etherpad-opensourced
- httpd.apache.org/docs/2.0/mod/mod_proxy.html
Prep your Env
First, open your apt repository list,
sudo vim /etc/apt/sources.list
add
deb http://archive.ubuntu.com/ubuntu hardy universe multiverse
deb-src http://archive.ubuntu.com/ubuntu hardy universe multiverse
deb http://us.archive.ubuntu.com/ubuntu/ hardy-updates universe multiverse
deb-src http://us.archive.ubuntu.com/ubuntu/ hardy-updates universe multiverse
and run sudo apt-get update.
Now that we have access to all the packages we need, we can install them.
sudo apt-get install sun-java6-jdk scala mysql-server mysql-client libmysql-java mercurial apache2
Download the MySQL Java connector from www.mysql.com/downloads/connector/j/ and move it to /usr/share/java/mysql-connector-java.jar.
We’ll need some environmental variables set. You can edit /etc/profile or create something like /etc/profile.d/etherpad.sh. Add the following:
export JAVA_HOME="/usr/lib/jvm/java-6-sun"
export SCALA_HOME="/usr/share/java"
export MYSQL_CONNECTOR_JAR="/usr/share/java/mysql-connector-java.jar"
You’ll need to restart your shell for these to take effect.
Grab the Pad
hg clone https://etherpad.googlecode.com/hg/ etherpad
cd etherpad/trunk/etherpad
Patch the Pad
For the installer to find everything it needs in Ubuntu, you’ll need to edit ../infrastructure/bin/makejar.sh:
-JARFILES=`echo $SCALA_HOME/lib/scala-library.jar lib/*.jar lib/manifest`
+JARFILES=`echo $SCALA_HOME/scala-library.jar lib/*.jar lib/manifest`
- $JAR xf $SCALA_HOME/lib/scala-library.jar
+ $JAR xf $SCALA_HOME/scala-library.jar
At this time, “etherpad.com” is still hard-coded in lots of places under src/. You’ll need to change this to your domain. To get a list of all the files you need to change, run
grep -irl "etherpad.com" src/
One particularly important file to change is src/etherpad/globals.js. Be sure to add your domain to the SUPERDOMAINS hash.
Now bin/setup-mysql-db.sh needs some patching:
Add mysql="mysql" right above db="etherpad".
Add -pMyPassword after -u root in the two mysql calls.
Configure the Pad
Open etc/etherpad.localdev-default.properties and change
- devMode to false
- etherpad.isProduction to true
- listen to localhost:9000
- etherpad.isPNE to true (only if you want to run in PNE mode – I don’t know what that means)
- etherpad.adminPass to something better
Put it in a jar
bin/rebuildjar.sh
This may take awhile. You’ll only need to do it again if you ever change anything under ../infrastructure.
Run it
bin/run-local.sh
You should now be able to access your EtherPad locally through localhost:9000, but that won’t do anybody any good, especially since we’ve hardcoded your domain all through it.
Configure Apache to proxy
Setting up the proper DNS records and locking down your server is left as an exercise to the reader.
Create an apache virtual host file like /etc/apache/sites-enabled/001-etherpad
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<VirtualHost *:80>
ServerName etherpad.yourdomain.com
ServerSignature Off
ErrorLog /var/log/apache2/etherpad.yourdomain.com/error.log
LogLevel warn
CustomLog /var/log/apache2/etherpad.yourdomain.com/access.log combined
ProxyPass / http://localhost:9000/
ProxyPassReverse / http://localhost:9000/
ProxyPreserveHost on
<Proxy *>
Options FollowSymLinks MultiViews
AllowOverride None
Order deny,allow
Allow from etherpad.yourdomain.com
</Proxy>
</VirtualHost>
|
Create your logs directory:
sudo mkdir /var/log/apache2/etherpad.yourdomain.com
Make apache the owner:
sudo chown www-data:www-data /var/log/apache2/etherpad.yourdomain.com
Enable mod_proxy:
sudo a2enmod proxy
sudo a2enmod proxy_http
Restart Apache:
sudo /etc/init.d/apache restart
That’s it!
Collaboration is just a website away, all in the comfort of your own domain. Some features will be disabled, like email (unless you set up SMTP on your server) and a few of the export formats. Some have had success enabling more features. Try it out if you’re brave. It will be exciting to see how this develops as an open-source project.
EtherPad
Late in 2009 Google acquired AppJet, the company responsible for the popular collaberative Web-based text editing tool, Etherpad.
Presumably this is to beef up Wave’s feature set, which is way cool. Uncool though, was the announcement that free public “pads” could no longer be created, and the entire service would be discontinued on March 31, 2010. After much uproar, Google and EtherPad revised their stance, promising to leave the site up and free to the public until the entirety of the source code (and the AppJet platform running it) could be opened to the public, allowing anyone to host his or her own Etherpad instance.
Though the process is still in the early stages, many are already setting up their own EtherPad instances, getting ready for the day Google pulls the plug. I’m among these hordes, and I’ll probably toss up an Ubuntu server walk-through once I get mine fully working at etherpad.jordanhollinger.com.
What does ruthless mean?
Better asked, why does ruthless mean what it means? What is ruth, and why do some things have none of it. Is anyone ever ruthfull?
Example: Daniel Webster was a ruthful man.
Merry Christmas, and Prepare to Meet Thy Maker
Traveling home to West Virginia for Christmas I came upon a hearse. Sad to think about on Christmas Eve Eve Day. But this hearse wasn’t carrying a dead body. It was carrying an old woman, and she was driving it. Emblazoned on the back I could read, “For the wages of sin is death.” A sign affixed to the roof admonished drivers, “Prepare To Meet Thy Maker.”
I found this a rather severe Holiday greeting, so to you I simply say “Merry Christmas!” Or if that offends you I say, “Stop getting offended so easily, and Appropriate Seasonal Festivities!”
Baking Day
Spent the whole day with Alicia making everyone’s Christmas favorites, pretzels + Hershey’s Kisses + M&M’s and Sushi. And my new 50mm lense. Best day in a while.




Diet

This could make millions. …of people healthier.
Oh Tennenbaum
Visiting home for Thanksgiving and putting up the family tree. My mother has been complaining that our tree (plastics make it possible) is too large for our living room. She didn’t appreciate an attempt at compromise.

Neither snow nor rain...
In early October I mailed my rent check like a good tenant. A little later in October I received a letter asking where my rent was. “Oh, they’ll get it soon enough,” said I to myself.
The day before Halloween my landlord called, saying they had received the check that very day, postmarked October 6th. “Curious.”
“Yes,” replied the landlord. “It’s destroyed. Can you send double rent for November?”
I did. They returned my check “for my records,” which I took to mean here.

I accept your apologies, PO. I don’t wish to malign all government services, but juxtaposed with the President’s “my health care plan will succeed just like the Post Office” comment, I find my mail being delivered in a body bag…disquieting.
But at least we know they care.
Daniel Webster is PO'ed
Look at this cat. What got stuck up in his craw and died? He doesn’t look like a man happy about the proliferation of words.

What is he thinking? To prime the pump I’ll throw out Shut up. I wrote the friggin’ dictionary and If they would rather die they had better do it, and decrease the surplus population…of words.
Unobtrusive in-field text labels
Warning: This post concerns Web interface development and may be appear as arcane to many. It also contains HTML and JavaScript examples that may not render properly in feed readers or importers like Facebook. Follow the link back to the original post if you’re having trouble.
In HTML user-input forms, it is not uncommon to see text fields with “labels” as grayed-out text in the field itself which disappear when clicked.

My search for “best practices” on this technique left me…wanting. Firstly, I wasn’t sure what to call it. Secondly, many implementations were riddled with problems, paramount of which was abominable degradation. I am no accessibility expert, but these solutions didn’t even try. Here are two of the most common, and unfortunately, the worst.
Trickle-down
Initially this method looked promising. You explicitly set the value of the field to your label string which trickles down to the defaultValue attribute. You can then use defaultValue to determine when to clear or reset the label. Problems:
- Mean to screen-readers, non-JavaScript browsers, and those who use them
- Mean to your controller/form processing code (it somehow has to know to ignore your labels when they’re posted as values)
- Mean to forms that edit existing data (did defaultValue come from the label or from real data? If it’s real, there is no way to default back to the label if the user removes the value)
- Depending on the implementation it can be obtrusive
Some of these issues can be resolved through code, but it’s not going to be pretty.
Hidden fields
This, uh, solution, displays a “throw-away” text field as the label. On click, it’s replaced by the real field. To the user it appears that the text just disappeared. This has all the problems above plus some:
- Really really mean to screen readers and non-JavaScript browsers (there will be duplicate fields with text already in them for no apparent reason)
- Really mean to controller/form processing code (it has to arbitrarily ignore entire fields, not just values)
- It’s unbelievably intrusive
- It’s just a horrible idea on par with suggesting users place and remove labeled Post-it notes when moving from field to field
A better way
First, there may be an Even Better Way, but I believe this address all of the problems above, both practical and conceptual. In a nutshell, you set the field’s title, which you should be doing for accessibility reasons anyway. Optionally add a “real” label tag linked by id to it’s input field. JavaScript then looks for titled fields with blank values, hides their labels, sets the value to the title, and binds focus and blur events to the field. These respectively clear and reset the label (by comparing the value to the title) when users click on or off. On form submit, if any of these fields’ values match their titles, they are cleared by some JavaScript. Benefits:
- Unobtrusive
- Graceful degradation (screen-readers and non-JS browsers can fall back on the real label or title attribute)
- Uses all field attributes for their intended purposes
- Places all responsibility/logic in one location, removing the need for controllers to treat certain values or fields specially
- No Post-it notes
A possible draw-back is that users cannot submit a value that matches the field’s title. If that’s a real problem, you could probably add some more checks to hack around it. But how often is someone’s first name First?
My implementation uses >= jQuery 1.3. Since we’re on the Web anyway, I thought I’d throw in a working example below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
<form id="form_field_label_example" action="" method="post"> <p> <label for="first_name">First</label> <input id="first_name" name="first" size="15" title="First" type="text" /> <label for="middle_name">Middle</label> <input id="middle_name" name="middle" size="8" title="Middle" type="text" /> <label for="last">Last</label> <input id="last" name="last" size="25" title="Last" type="text" /> </p> </form> <script type="text/javascript"> $(document).ready(function() { auto_label("form#form_field_label_example input[title][type=text]") }) function auto_label(str) { $(str).each(function() { // Hide the field's real label $('label[for=' + this.id + ']').hide() // Set the label text and color for blank fields if ( !this.value || this.value == this.title ) { this.value = this.title $(this).css('color', '#999') } // On focus of blank fields, clear the label text and reset the color $(this).focus(function() { if ( this.value == this.title ) { this.value = '' $(this).css('color', 'inherit') } }) // On unfocus of blank fields, restore the label text and color $(this).blur(function() { if ( !this.value ) { this.value = this.title $(this).css('color', '#999') } }) }) // Clear label text when submitting form $(str).closest('form').submit(function() { $(str).each(function() { if ( this.title && this.value == this.title ) { this.value = '' } }) }) } </script> |
Quick, someone get John Wilkes Booth!
I saw Abraham Lincoln recently. Not in a cloud or a potato chip. In person. He showed up for the 150th anniversary of the Murfreesboro courthouse in Murfreesboro, Tennessee. Looking good considering that whole John Wilkes Booth thing. Then he let us do some handstands.



Here's irony for you
So my hard drive just bought the farm. I always tell people to back up their data, and fortunately I was smart enough to listen to my own advice. In fact I wrote my own backup program because I wasn’t fond of the existing solutions.
Pat on the back, right? Unfortunately the most recent backup is about a month old, so I’ve lost some recent work. The irony is of course that the recent work I lost was a major refactoring of the backup program.
What's your car's ringtone, man?
Bloomberg reports electric cars are too quite and are running down the unsuspecting blind, young, and elderly. Clearly this is bad for business.
An early idea was for electric cars to re-create the sound of combustion engines, but fortunately Nissan has taken a stand for aesthetics and is moving towards a “beautiful” and “futuristic” sound, like Blade Runner’s flying cars. The sound is completely artificial, I imagine emanating from an unobtrusive external speaker system.
While that’s awesome, the next logical step is even cooler: custom “ringtones” for your car. Don’t like the flying car loop that came bundled with your Chevy Volt? Upload an mp3 of the Enterprise warp core or George Jetson’s car.
And has anyone thought about what the blind are going to do when we have real flying cars? They won’t know whether to duck or run. This isn’t a solution, people!