Update: I was wrong about the popup preference not working. I had forgotten to turn off popup balloons on one of my computers, and missed a return statement while reading the source code. So my changes are unnecessary.

I am a big fan of twitter. I use it all the time. I follow a lot of people. Some I know personally, some I’ve only met online, and some I have never met. I like to interact with people on twitter in real time.

Of course, the benefits of twitter come at the cost of time. The little bits of time here and there spent reading and posting tweets add up. It can also cause interruptions, making it hard to focus.

twitter.com and twhirl

I used twitter.com at first, then twhirl, and twitter.com again before I discovered TwitterFox.

The biggest problem with using twitter.com is that I have to load twitter.com to check for new tweets, whether or not there are any new tweets. It takes a while to load a web page. Usually that is an interruption in itself. Usually I either miss the action on twitter or I obsessively check twitter.com to see if there are any new tweets. On days when I’m feeling less motivated or more curious about what’s happening on twitter it is usually the latter.

For a month or two I used twhirl to access twitter. There are two different ways of using it, each of which has its own problems. One way is the default, where it pops up new messages in the lower-right corner of the screen. This is the way most desktop twitter clients work. The problem with this is obvious: it’s an interruption, plain and simple. If I’m in the zone, I will likely get distracted. The other way of using twhirl is to turn off pop-up messages, and to either give the window some space on the screen or to switch to it using Alt-Tab to check tweets. The problem with this is it quickly devolves into a glancing or Alt-Tab frenzy, as at any time when I’m even slightly curious about what’s happening on twitter, I can check in an instant. Often times when I would check I would find no new tweets.

the twitter urge

Every so often I get the urge to check twitter. It’s perfectly natural for anyone who has discovered the joy of using twitter. What matters is what I do with those urges. If every urge turns into reading a list of twitter messages, it can turn into a real productivity killer.

For a while I’ve known the way that I would like to be able to use twitter. I would like a number of new messages on the screen. Then, if I got the twitter urge and there weren’t any new messages, it would only cause a split-second of interruption. If there were any new messages, I would know, and if I didn’t check even though there were new messages, I could give myself a pat on the back for staying productive, and know that once I got more work done I would have something to read.

After a week of being frustrated with twitter, I decided to do something about it. So I looked at the list of twitter clients again and tried a couple out. I wanted one that was open source and easy to customize.

TwitterFox

I spend enough time in Firefox, both at work and on my laptop, that having something in the Firefox status bar is pretty much as good as having something in the taskbar, if not better. Firefox extensions are also easy to customize (unless the code is a mess), so I gave it a try. When I saw the number of new tweets in the lower-right corner of my Firefox window, I was elated. This is exactly what I wanted!

It worked really well for me, once I figured out how to turn off popup balloons, where it would show the latest tweet(s) in the bottom-right corner, much like twhirl. At first, I thought the preference wasn’t working, so I made changes to the source code. I found tinkering with the source code to be relatively easy. Since I’m a web developer, I’m very comfortable working in JavaScript.

The tiny difference between TwitterFox and twhirl that makes it work for me is that the number of messages appears on a part of the screen that I see regularly. The information I need is there, and presented in a way that is not distracting. This is also the way I keep tabs on my e-mail (GMail) and my RSS Feeds (Google Reader), though I like the way TwitterFox shows the number better. GMail and Google Reader have the number of new items in their titles, which appear in the Firefox tab bar. Sometime I’d like to find or make extensions that will show the number of new items in those two web apps in the Firefox status bar.

Since I love FireBug, and CouchDB has a JSON API, I attempted to combine the two. My goal was to find a way to use jQuery‘s AJAX functions to create, read, and update CouchDB documents.

Getting Started

The first thing I tried was creating a merb project with a single page referencing jQuery, and accessing CouchDB from there. The browser’s security model got in my way, however. A page on one port on localhost can’t access another port with AJAX. I searched for ways to give a page special permission, but my search turned up empty and I figured that I’d rather not go against the browser anyway, if I could help it.

The next thing I tried was getting a page that references jQuery to be served by CouchDB’s web server. That way the page and jQuery’s JSON API would be on the same port and Firefox would be happy. I opened up CouchDB’s Futon Utility Client at http://localhost:5984/_utils/ and found that it already had the latest version of jQuery included! Problem solved.

I opened the FireBug console (which was already enabled on localhost from when I was trying to get it working with my Merb project) and started trying out jQuery’s AJAX functions on CouchDB.

The GET request returned successfully! However, FireBug doesn’t retain the response, so I have to click Load Response to get it.

OK, there’s CouchDB’s welcome message! Expanding the GET request and clicking Load Response is tedious, though, so a better technique is needed. The first thing that comes to mind is doing a synchronous request. I find that get() doesn’t support this option, so I need to use ajax().

Aside from FireBug’s quoting FAIL, it works nicely. What I’d really like, though, is for FireBug to pretty-print the JSON. So I throw an eval() statement around it, and add the left side of an assignment statement because otherwise I would get an error (another way to get it working is to throw square brackets around the expression).

The output is quite a bit nicer, in my opinion.

Creating a Database

To create a database I use the HttpDatabaseApi page on the CouchDB wiki. Creating a database requires use of a PUT request, which can be made with jQuery’s ajax() function if the browser supports it (and Firefox does).

CouchDB returns a simple OK message to let me know it worked.

Creating a Document

Now that I have a database, I can create a document using the HttpDocumentApi. I opt to take the cavalier approach of having the server generate an ID rather than supplying an ID of my own. To do this, I send a POST with the database’s URL for the address and the document’s contents for the POST data. To send the POST data, I call ajax() with the document’s contents (as a JSON expression) for the data option and the string ‘json’ for the dataType option.

It didn’t work. I expand the POST and look at the data sent to find out why.

The ajax() function didn’t serialize the data! It’s not built into jQuery. It makes sense, given that one of jQuery’s features is its small footprint. I remember that when I viewed the source of the main page of CouchDB’s Futon Utility Client I saw a JSON include. It’s in http://localhost:5984/_utils/script/json2.js. It’s not a jQuery plug-in, but its interface is fairly simple. To serialize data, you call JSON.stringify() with an object as the first parameter. I add this to my statement and try again.

It worked! Or, at least, it didn’t error. It returned a globally unique ID (GUID) generated by the server. Now I use the ID to GET the document’s contents.

Only a summary of the object is shown. If I click the object it expands to a full view.

The data is there. The revision number is also present. One of CouchDB’s coolest features is built-in versioning.

After I realized that I was given only a summary of the object, I tried creating a document again and seeing if I missed any info that was supplied in the response to the POST request. It turns out that I did. The revision (_rev) was given. I’d like to have Firebug print out the whole response (and not a short summary), but I don’t see any way of doing so.

Updating a Document

Documents can be updated by sending a PUT request with the document’s URL as the address and the new contents as the data. The new contents must include the revision number upon which the update is based. This is to prevent conflicts. If a revision number other than that of the latest revision is supplied, it means that another client updated it first.

I update the document by getting the latest copy, storing it in a variable, removing the ID (since it’s already in the URL), changing the radius, and sending a PUT request with the new database contents.

The document is updated. If I expand the object I can see the new revision number.

Pretty cool, huh?

Conclusion & Next Steps

Before I tried using CouchDB with Firebug, I tried using the Futon Utility Client. I felt that I learned more and better retained what I learned when I used Firebug. Firebug as it is right now has a couple of issues that will keep me from using it as an environment in which to try doing different things with CouchDB. The first issue is that the pretty-print doesn’t show the full object in the console view, and there’s no option in the UI to make it do so. The second issue is that I find the editor to be insufficient. When the editor is in vertical mode, there’s no way to go through the history of commands entered. When the editor is in horizontal mode, it can’t expand beyond one line. When I switch between tabs, the text in the editor is often lost.

Firebug is, however, being actively worked on, and will hopefully get some features that will make it easier and more fun to use to play with JavaScript API’s and web services.

I would like to get the custom JavaScript environment mentioned at the top of this post set up and working with CouchDB. One way to get it working might be to set up a proxy of sorts to CouchDB. I could have any requests starting with /couchdb be forwarded to the CouchDB port with the /couchdb part stripped off.

This was fun. I think the next thing I’ll do with CouchDB is try writing a simple wiki using CouchDB and Merb.

In a matter of two days, Google has shaken up the web by releasing a brand new browser, and a pretty impressive one to boot. Google Chrome is in beta, but it’s fast, and as far as I can tell, stable. And it’s got some amazing new features.

The biggest feature is having one process per tab. That way, one badly-behaving site can’t lock up the whole browser. It uses extra memory, but not much. With the included Process Manager, I can see that a tab with a simple web page uses about 5 or 10 megabytes, while a page like Google Maps typically uses about 20 megabytes. With 8 or 9 tabs open (which is typical for me), the total memory usage came to about 100 megabytes. Firefox, on the other hand, was using 220 megabytes, but I was running it for a few days.

I think, however, that even if Chrome used extra memory it would be worth it, to be able to switch between tabs even while one tab was busy. They didn’t even have to make that compromise, though.

Another feature that I think will be extremely valuable is the V8 JavaScript Engine. A Google team in Europe made a new JavaScript engine designed from ground up to be fast and light. How cool is that?

There are also some neat things about the UI. The search bar and location bar are combined. Tabs can be dragged freely between windows. The location bar AutoComplete only shows things you actually typed, not every single site you’ve been to. The history opens up to a full tab instead of a sidebar which winds up wasting valuable screen real estate when the user forgets to close it.

Wow. What an exciting project. This will no doubt keep Google’s ability to recruit new talent going for years to come. Every time things just seem like business as usual at Google, something really exciting comes from them. This is why I chuckled when I read the last item of a list of the Top 10 Reasons Why Chrome Was Developed: Bored Google is bored.

I’ve been trying to find clever Ubiquity commands in the Herd. I want to see things that use the preview functionality in interesting ways, like the built-in map command does. What I’ve wound up doing so far, though, is sifting through dozens of commands that do nothing more than what could be done with a custom entry in the Firefox Search Bar, or commands that are nothing but links to another page.

While I think it’s useful to be able to search and go to websites from a command line, it’s not what I have in mind when I search for new commands.

I think that search engines and bookmarks should be separated from the rest of the commands, and that posting search engines or bookmarks as commands to the command part of the Herd should be discouraged. This will help in several ways:

  • Users who don’t know JavaScript will have an easy time adding bookmarks and search engines to Ubiquity and assigning them strings
  • I’ll be able to add search engines and bookmarks from websites without having to look at the code or decide whether I can trust the people who write the code
  • If I provide a bookmark or search engine on my website I won’t have to worry about convincing my users to trust me enough to install it, since it won’t be able to send any information from their browser to my website except for a search query
  • I won’t have to sift through bookmarks and search engines to find commands that provide advanced functionality
  • It will encourage website owners to create more powerful Ubiquity commands

Ubiquity is at an early stage, so I won’t be surprised if someone’s already working on separating simple commands from more complex ones. I hope so. I really want to see Ubiquity catch on, and for that to happen I think it needs to be easier for users to customize their commands.

Today I got a chance to try out Ubiquity. What a neat concept! It’s a GUI command line like QuickSilver, only it’s implemented as a Firefox extension instead of a desktop application.

The demo movie is impressive.


Ubiquity for Firefox from Aza Raskin on Vimeo.

I like how it shows information based on the text typed as I’m typing it. This functionality, called preview, is used extensively in the map command. In fact, most of the time the map command doesn’t even need to be executed, because a small map can be viewed and added to documents without executing a command. I think the preview functionality will be especially useful for looking up programming documentation.

The preview functionality is also used in the built-in twitter command, which posts an update to the microblogging site Twitter. It shows how many characters are left before you hit twitter’s limit. The built-in twitter command, however, uses 160 characters for the limit instead of the 140 character limit on twitter’s website. The 160 character limit for API’s is provided in case a long URL is included in the tweet, which twitter will auto-shorten using tinyurl.

I often post long tweets and don’t want to guess at whether one is going to be too long, so I created my own command, tweet, which uses is.gd for URL shortening. It uses the longest length of is.gd URLs to calculate what the size of URL will be, and bases the number of characters left on that. It replaces any occurrence of the string isgd with an is.gd link to the current page.

It was very easy to write, in large part due to being integrated into Firefox, and having Firefox’s JavaScript environment. It also is written with JQuery and command writers have jQuery available to them.

Ubiquity might not be the embodiment of a totally new concept, but I find that since it’s a Firefox extension, as opposed to being a desktop application, it’s a lot more convenient for me to use and develop for.

When installing Merb on my laptop, which runs Ubuntu Linux, I ran into a compiler error with hpricot, one of Merb’s dependencies. Before bothering to see what might be causing it, I checked to see if there was a precompiled apt-get package available. There was! I installed it and tried installing Merb again.

It still tried to install hpricot, however, and when I said to skip it, it said it could not install Merb because it was missing hpricot. I could have used force, or “pretty please”, but I wanted to instead tell the packaging system that I have hpricot installed.

I seem to remember a UNIX packaging system having an inject command — which tells the packaging system a program is already installed. I may have got the terminology wrong. I searched for such a command for rubygems but couldn’t find one. I did, however, find another way to convince rubygems that I already had hpricot.

I decided to do some digging in the gems directory. To find the gems directory, I typed:

ben@magicthise:~$ gem environment
RubyGems Environment:
  - VERSION: 0.9.4 (0.9.4)
  - INSTALLATION DIRECTORY: /var/lib/gems/1.8
  - GEM PATH:
     - /var/lib/gems/1.8
  - REMOTE SOURCES:
     - http://gems.rubyforge.org
ben@magicthise:~$ cd /var/lib/gems/1.8/
ben@magicthise:/var/lib/gems/1.8$ ls
bin  cache  doc  gems  source_cache  specifications
ben@magicthise:/var/lib/gems/1.8$ cd specifications/
ben@magicthise:/var/lib/gems/1.8/specifications$ ls
abstract-1.0.0.gemspec          merb-cache-0.9.2.gemspec
actionmailer-2.0.2.gemspec      merb-core-0.9.2.gemspec
...
ben@magicthise:/var/lib/gems/1.8/specifications$

I took a look at the gemspec files and found that they contained the name and version of the library. I copied the smallest of the files to hpricot-0.6.gemspec and used the gemspec documentation to find out which parameters are required. I wound up with the following in /var/lib/gems/1.8/specifications/hpricot-1.6.rb.

Gem::Specification.new do |s|
  s.name = %q{hpricot}
  s.version = "0.6"
end

I tried running:

ben@magicthise:~$ gem install merb --include-dependencies

And it worked!

It might not be everything that’s needed to get it working — but now I at least know how to inject a package.

I’ve become a somewhat avid twitter user over the last several months. It’s helped me to stay in contact with existing friends and to get to know a few people from Refresh Phoenix, a local web design/development club. For those who don’t know what it is, it’s like LiveJournal, except each blog entry is limited to 140 characters, the friends feature works slightly differently, and it has good integration with SMS.

A couple of things I really like about it:

  • The 140 character limit. Twitter has a strict 140-character limit on all blog posts (tweets in twitter lingo). I’ve found this to be a very useful constraint. It reduces the amount of reading I have to do to keep tabs on friends. It also reduces the amount of time spent writing. As long as I don’t follow too many people, and don’t follow those that post too much, I can avoid spending too much time on twitter.

    I think it is also helping me to be a better writer and conversationalist. Trying to tell a story in 140 characters can be an interesting exercise. Inevitably, some details need to be dropped. Sometimes the story is not as good because it’s missing some interesting details, but often what’s left out is uninteresting. I had one such moment today.

    Yesterday, I was hanging out with some friends and told them a story. About half of the people found it interesting, but most thought it was long-winded and the half who weren’t interested were bored by it. If I had been thinking like I am when I write a twitter post, it might have been better received.

    I think the 140-character limit is a constraint people ought to embrace. There are a couple of ways to get around it — posting multiple tweets or dropping vowels and using lots of abbreviations and text-messaging-speak. I have a couple of rules of thumb. I try not to make a post that would make absolutely no sense to someone who didn’t read the other post. I also avoid shortening more than two or three words to make my post fit in 140 characters.

  • Easy come, easy go. On Twitter, if someone follows you it sends you a friendly notice with the username of the person who follows you. If someone stops following you, it sends you no such notice. So, unless you’re constantly checking the list of people who follow you, you can’t give them a hard time about not following you anymore.

    It might annoy some people, but it’s for the greater good. It encourages people not to break twitter etiquette, or else people might stop following them. It also makes twitter fun to use, because if one user is being annoying, you can quit following them instantly and not face immediate blowback, unless that person is a real jerk.

  • Best Wishes. On twitter, the notification e-mails you receive when a person follows you end with the following signature:

    Best,
    Twitter

    A few times, that’s been just the thing to help me to have a better day. The people at twitter are wishing everyone using their service the best. It’s the best closing salutation ever, IMHO. Thanks, folks!

After I talk to someone I meet at a coffee shop or while traveling and help them with a small technical issue like getting photos transferred or getting on a wireless network, I’m sometimes asked for advice on becoming tech savvy. My advice for someone struggling with their PC who I won’t see again and won’t be able to help in the future is to get a mac. I point out that it really is totally different from a PC, and once they get a mac they should be able to figure out how to do a lot of stuff by themselves, instead of asking for help like they do now.

There is one thing, besides not wanting to pay extra money for a mac, that keeps people from empowering themselves by getting a windows-free computer that they can actually learn to use and maintain themselves — either they or someone they know has had hardware problems with a mac.

In my opinion, even if a mac breaks several times, it’s still worth it to get a mac (and an extended warranty) if you can’t figure out windows and need a computer for your career. I’m reminded of this by a comment by an editor on The Consumerist, an extremely popular and successful blog. He says that he’s had issues with three different macs and an iPod, but it’s still worth it to him to have a mac. Of course it is. He built a successful career with macs.

I just wrote my first GreaseMonkey user script. It’s a script that puts a random Benjamin Franklin quote above the stories on reddit to remind me to be dutiful and not spend too much time looking at online news. I found the quotes through (you guessed it) reddit.

Here’s what it looks like:

reddit_franklin.jpg

And here’s the code:

// ==UserScript==
// @name           Reddit Quotes
// @namespace      com.benatkin
// @description    Shows Quotes in front of Reddit
// @include        http://reddit.com/
// ==/UserScript==

function franklinQuote() {
  var quotes = [
    'Early to bed, and early to rise, makes a man healthy, wealthy and wise',
    'Diligence is the mother of good luck',
    'God helps them that help themselves',
    'Sloth, like rust, consumes faster than labor wears, while the used key is always bright',
    'Dost thou love life, then do not squander time, for that’s the stuff life is made of',
    'Lost time is never found again',
    'He that riseth late, must trot all day, and shall scarce overtake his business at night',
    'Drive thy business, let not that drive thee',
    'Industry need not wish',
    'He that lives upon hope will die fasting',
    'There are no gains, without pains',
    'Plough deep, while sluggards sleep, and you shall have corn to sell and to keep',
    'One today is worth two tomorrows',
    'Have you somewhat to do tomorrow, do it today',
    'Be ashamed to catch yourself idle',
    'Let not the sun look down and say, inglorious here he lies',
    'He that hath a trade hath an estate',
    'He that hath a calling hath an office of profit and honor',
    'At the working man’s house hunger looks in, but dares not enter',
    'For industry pays debts, while despair encreaseth them',
    'Constant dropping wears away stones',
    'By diligence and patience the mouse ate in two the cable',
    'Little strokes fell great oaks',
    'Employ thy time well if thou meanest to gain leisure',
    'Since thou art not sure of a minute, throw not away an hour',
    'A life of leisure and a life of laziness are two things. Do you imagine that sloth will afford you more comfort than labor?',
    'Trouble springs from idleness, and grievous toil from needless ease.',
    'Many without labor would live by their wits only, but they break for want of stock',
    'Industry gives comfort, and plenty, and respect: fly pleasures, and they’ll follow you',
    'Keep the shop, and thy shop will keep thee',
    'If you would have your business done, go; if not, send',
    'He that by the plough would thrive, Himself must either hold or drive.',
    'The eye of a master will do more work than both his hands',
    'Want of care does us more damage than want of knowledge',
    'Not to oversee workmen is to leave them your purse open',
    'In the affairs of this world men are saved not by faith, but by the want of it',
    'Learning is to the studious, and riches to the careful, as well as power to the bold, and Heaven to the virtuous',
    'If you would have a faithful servant, and one that you like, serve yourself',
    'For want of a nail the shoe was lost; for want of a shoe the horse was lost, and for want of a horse the rider was lost'
  ];
  return quotes[Math.floor(Math.random()*(quotes.length))];
}

function addFranklinQuote() {
  var tbl = document.getElementById('siteTable');
  if (tbl) {
    var quoteBox = document.createElement('div');
    quoteBox.innerHTML = franklinQuote();
    quoteBox.style.fontSize = "16pt";
    quoteBox.style.backgroundColor = "#f9f7ed";
    quoteBox.style.padding = "1.5em";
    quoteBox.style.position = "relative";
    quoteBox.style.width = '500pt';
    tbl.parentNode.insertBefore(quoteBox, tbl);

    var quoteName = document.createElement('div');
    quoteName.innerHTML = "-- Benjamin Franklin";
    quoteName.style.fontSize = "10pt";
    quoteName.style.position = "absolute";
    quoteName.style.bottom = "0";
    quoteName.style.right = "0";
    quoteBox.appendChild(quoteName);
  }
}

addFranklinQuote();

Greasemonkey really is as simple to use as it sounds. You give it a script and the URL’s to which it applies. When you browse to a page that matches the URL, the script is executed. For this one, it was a simple matter of adding a DOM element in the right place.

Some scripts are meant to be loaded on all pages, such as a script that makes it possible to use shift to quickly check or uncheck a bunch of checkboxes. If you’ve heard people complain about the Greasemonkey overhead, it’s probably because they’ve run a bunch of these utility scripts that run on all pages. A script or two that are browser-wide, with the rest of the scripts only running on a single site shouldn’t slow things down much.

To install, first install greasemonkey. Then, find the greasemonkey folder (gm_scripts) in your profile directory and save the above code into a file called “redditquotes.user.js”.

UPDATE (2007-07-17): After searching for ‘sliding doors css “dead space”‘ I found that someone already solved the problem without using JavaScript.

About a year ago I read Sliding Doors of CSS on A List Apart. While I admired the elegance of the design, I found the dead space on the left side of the tabs to be annoying.

The problem comes down to not being able to wrap an individual anchor tag around a list item tag and have it work. The anchor tag had to be put inside the list item tag, and try as I and the author might, it couldn’t be made to include the entire tab. The left side of the tabs were unclickable, as can be seen in the example.

The other day, I got the idea to fix the problem with JavaScript. I could make the list item trigger an onclick event. I could also make it show a hand cursor when hovering over the list item. The hand cursor thing could be done with CSS, but I like doing it in the JavaScript better, because if somehow the JavaScript code doesn’t execute properly, it won’t show a hand cursor in an area that’s not actually clickable.

I use the following JavaScript code, which relies on the JQuery library, to make the dead space clickable. On the first try I had the whole page flicker in Firefox when part of the anchor was clicked (the part that wasn’t dead space before). I tested it on the old page and it didn’t have the whole page flicker issue. So I figured out that it was probably a result of both the link and the javascript being triggered, and I added an event for the anchor to tell it not to trigger the dead-space event if the user clicked on the anchor.

clickedAnchor = false;

function fixDeadSpace(headerDiv) {
  var items = $('li', headerDiv);
  items.css('cursor', 'pointer');
  items.click(function(arg) {
    if (! clickedAnchor) {
      window.location.href = $('a', arg.target).attr('href');
    }
  });
  $('a', headerDiv).click(function() { clickedAnchor = true; });
}

$(function() {
  fixDeadSpace($('#header'));
});

To use, make sure the JQuery library is available, and add the above in a script tag. Here is the example with my code added, and different query strings in the links.

It behaves just about the same as if the left part of the tab were part of the link. The only difference that might be noticeable to a very small number of users is that when you hover over the area outside the anchor tag, the location isn’t shown in the status bar.