This is the Alagad blog, AKA The Alagad Ally.
Remember to Contribute to OSS (or Tweet) to Get an Alagad Backpack
Pardon the shortness of this post, I simply wanted to remind those out there who follow this blog that I’m holding a contest to give away a very nice Alagad Swiss Gear laptop backback. To quote Vicky Rider of CodeBass fame, they’re “legendary”. All you need to do is make a first time contribution to an open source project and comment on it on this entry. The best first time contribution will be picked and that lucky person will get the backpack! The contest is open through the end of the year and, as of now, I’ve received precisely zero submissions.
So, go forth and contribute. Then report back! It’s that simple. You’ll be helping support the community of OSS developers and you just might get a really, really, nice backpack out of the deal!
Also, to try to drive a little interest in this contest, I’m holding a side contest for yet another Alagad bag. Simply tweet the following to enter and I’ll pick a random tweet the same day that this OSS contest ends. Here what you tweet:
Now I wish I’d never contributed to open source! #AlagadBag http://bit.ly/eJvDfi
Also – you may want to note that CodeBass is holding a contest to give away some swag to commemorate their MediaSlurp collaboration. I’ve donated an Alagad bag to their swag set. Get more info and learn how to enter their contest here.
Contest: Best First Time Open Source Contribution (Updated)
A couple of days ago I asked for suggestions for contests so that I could give away a bunch of extra Swiss Gear Alagad laptop backpacks that are taking up my precious garage space. I received a number of good suggestions and, for my first contest, I’m going to go with Kurt Wiersma’s suggestion: Best First Time Open Source Contribution! (Congrat’s Kurt – Send me your address and I’ll send you a backpack.)
The contest title is pretty self descriptive. I want to encourage those of you who haven’t contributed to an open source project in the past to contribute. So, go out, choose a project you deem worthy and contribute. It doesn’t matter how you contribute. Obviously you could contribute code or bug fixes. You could also write documentation. There are probably other things you could do as well. For example, maybe you could start a fundraising or publicity campaign for your designated project. The choice is yours – be creative!
As you make your contribution please put a summary into the comments on this blog entry. Be sure to make a good sales pitch on why your contribution should be the winner. When the contest ends I’ll post a survey and the community can choose which contribution is their favorite. The winner will get a really nice laptop backpack. Everyone else will get the glowing sense of well being and pride in knowing you’ve done a good deed.
The contest starts now and runs through the end of 2010.
I’ve given away several of these backpacks in the past, but, if you’ve never seen them in person, trust me, they’re very nice! I’ve been using mine for about two years and it still looks brand new. It’s very well constructed from very nice materials. It’s well padded and won’t hurt your shoulders, no matter what you load into it. There are about a bazillion pockets on this beast – more than enough to securely store and organize just about anything you might want to cary with you. Heck, it’s even got ventilation channels to keep your back cool!
So, please, go do a good deed and help out an open source project and report back!
Update: I’ve added a side contest to this contest. More information can be found here. In short, all you need to do is tweet the following to enter:
Now I wish I’d never contributed to open source! #AlagadBag http://bit.ly/eJvDfi
Contest: Help Alagad Give Away Swiss Gear Backpacks
I have a bunch of promotional laptop backpacks I purchased for Alagad taking up precious space in my garage. These are very nice swiss gear backpacks with the Alagad logo tastefully embroidered on the back pocket. They’ve got, I’d guess, a zillion pockets, lots of storage space, can fit a 17″ laptop, and are tough as heck. I’ve been using mine for a couple years and it still looks like new! I really want to give them away to good homes, but I’ve been struggling on how to best do this. Maybe you can help?
A few weeks ago I posted a contest where entrants would make a word search generator in an unfamiliar language. And, well, honestly, that went over like a lead balloon. I had precisely zero entrants. Maybe I made it a bit too complex?
I’d like to turn this into a game or a contest or something of the sort and have a little fun with it! Furthermore, a little promotional activity can’t hurt since it looks like Alagad will be winding up their current contract in April. (It’s never too early to be looking for the next gig.) If possible, it’d be really nice to be able to help people learn something new or, perhaps, help out those who are less fortunate, especially durring this time of year. Winners of these contests would get an Alagad backpack.
So, this time I’m having a contest to come up with ideas for contests, games, or whatever. If you have an idea on what I should do to give away these backpacks post it in the comments below. I’ll pick one or more of the ideas and run with them. If your idea is picked, you’ll get a very nice backpack for your troubles!
So, how should I give away these backpacks?
Make a Word Search Puzzle Generator and Win an Alagad Backpack
My family is in the midst of downsizing a bit and moving to a new house. While digging around in our attic I discovered a set of Alagad promotional backpacks. Personally, I love mine. It has about a bazillion pockets, is very well made, and can easily hold a 17” laptop. Over the last few years I’ve given a number of these away and everyone who has one raves about them.
I don’t plan to sponsor any conferences any time soon and so I thought I should come up with a way to give these backpacks away. (I’ve only got so many backs, myself.) What better way to do this than to have a contest?
My son loves word search puzzles. He loves them enough that I’ve often considered writing a simple application to generate word search puzzles for him. In my minds eye I see an application where I can provide various options I can choose from such as:
- How many letters wide and tall a puzzle should be.
- A maximum length for and number of words to choose randomly from a dictionary.
- An option to provide your own words and title.
- Directionality settings. Such as forward, down, down at an angle, backwards, backwards at an angle, up, etc. These would control how words would be hidden in the puzzle.
Clicking a button would spit out a word search that I could print out and do with a pen. I’m sure you could come up with many of your own ideas for how a simple word search generator might work.
Of course there are already a wide number of word search puzzle generators on the web, but as a programmer I was interested in the challenge. And so, here is my challenge to the community in general: Create a word search generating application.
And here’s the twist: Create the word search genrator in any language (or technology) you don’t already know. If I were to write this right now I’d probably choose NodeJS since I’m interested in its capabilities and it’d be fun to do something more than just a hello world application in it.
Your application can be as complex or simple as you want. Complexity doesn’t guarantee a win and neither does simplicity. What I’m going to be looking for is the uniqueness of the language you choose and how well written the application is from my personal perspective. For example, I’ll be more interested in a well-written Clojure application than a poorly written one in Ruby or C. Yes, it’s entirely subjective, but I’m less familiar with Clojure (and bet most of my readers are too) and therefore would be more interested in seeing what can be learned.
Submissions are due a week from now. I’ll start reviewing them on Tuesday the 26th. Depending on how loudly people complain I may push this deadline back.
Once I’ve had a chance to review the entries I’ll pick three winners, each of whom will get one Alagad backpack. I’ll then write a blog entry (or three) about the entries, the languages used, and the approaches taken in building the applications. Assuming it’s practical, I’ll also host the applications so the whole world can play around with them. Furthermore, I’ll publish a SVN or GIT repository where people can download the source code.
Every time I do one of these contests I forget something important. So, if you have any questions or concerns please add them in the comments. I’ll reply and clarify.
Good luck!
Google Chrome Extensions are Crazy Easy
Occasionally I have to work on web applications that are horribly slow. Some complex applications can take several minutes to completely reload. I’m sure I’m not alone in this experience. And so, when working on these sites, what do you do while waiting for stuff to load? If you’re like me, you go to another tab and work on something else while you wait for that tab to load (or you troll around Twitter, etc).
This isn’t really a problem except that more often than not I fail to notice when the other tab has finished loaded and end up wasting time. Because of this, I’ve long wished that there were a tab extension that would could play a sound when a tab finishes loading. However, look as I may, I never found anything that did what I wanted.
In the past I’ve considered writing a simple extension for this. The thing is, until recently I’ve been a fairly diehard Firefox user. Having written a now-defunct Firefox extension, I know what a flaming pain in the ass it is to write Firefox extensions. There was no way I was going to write this extension for Firefox.
However, I recently decided to take Google Chrome for a real test drive and I’ve been using it exclusively for a few weeks. During this period I also began working on a website that takes a very long time to reload. So long, in fact, that I became frustrated enough to go and research what’s involved in making extensions for Chrome. And, as it turns out, there’s not a whole lot involved!
In Firefox, when you write an extension you can change or override just about any feature of the browser. For example, if you don’t like how bookmarks system works, you can pretty much replace it with something you do like. The thing is, with all that power and flexibility comes a boatload of complexity. I really don’t even have the patience to write about the hoops I had to jump through to get started. Let it suffice to say that I had to run the browser in a different test user account and, if I recall correctly, reload the browser each time I made a chance to my extension. Then there’s the fact that Firefox extensions are written using XUL (XML User Interface Language). And there was more fun too. In summary: It’s a pain and no fun at all.
Chrome, by contrast, is much more limiting in what you can do. However, it’s API is a dream to work with. In Chrome most extensions are either browser actions, which are browser-wide, or page actions, which only affect the current page. Both of these are quite easy to write, but I’ll focus on browser actions since that’s what I wrote.
In addition to the two basic extension points, Chrome also provides a nice API for interacting with browser features such as bookmarks and tabs. Like everything else in Chrome, these APIs are very simple and easy to use.
At a minimum, Chrome extensions are made up of HTML files and a manifest file written in JSON. The manifest defines basic information like the name, version, description, icons, etc.
It also defines a “background page”. A background page is a page that is loaded by the extension and runs constantly behind the scenes. This is useful for storing state information and providing the core features of the plugin.
The manifest also allows you to define browser actions. Browser actions define an image or button that appears to the right of the address bar and provides an entry point into your extension. When you click on that icon a popup you create appears.
Here was the manifest for my plugin:
{ "name": "Tab Bing!", "version": "1.1", "description": "This extension produces a 'bing' when a tab finishes loading.", "icons": { "128": "bell_128.png" }, "background_page": "background.html", "browser_action": { "default_title": "", "default_icon": "bell_19.png", "default_popup": "popup.html" }, "permissions": [ "tabs" ] }
The manifest file above defines the name, etc, of my extension. It also says that the background page, background.html, will be loaded and run behind the scenes at all times. Additionally, there will be a button to the right of the nav menu. Clicking this button will show the popup, popup.html.
At this point all I need to do is create the files referenced and load the extension into Chrome. Just for an example, here is the directory structure of my extension:
You can ignore the mp3 files and play.png file as they’re my extension’s assets. Really, what I have is three very simple: manifest.json, background.html, and popup.html.
If I wanted to load my extension into my browser how I can do so by putting the extension tab into developer mode. I do this by opening the extensions tab and clicking on the Developer mode link.
After that I can click on Load Unpacked Extension and simply choose the directory my extension is in. At this point I can see my button appear next to the tool bar. Clicking the button shows a popup window containing the contents of my popup.html file. It really doesn’t get much simpler than this!
Now that I have the basics of my Chrome extension in place I can start writing my extension’s features.
The way my extension works is to allow the user to indicate if they want the current tab to “bing” when done loading. To support this I’ve created a simple popup that collects a few options from the user. These options are stored by the background.html file that is persistent for the duration of the browser’s lifespan.
So, here’s my popup.html:
body{ width: 300px; font-family: verdana; } var background = chrome.extension.getBackgroundPage(); var tab = null; var tabSettings = null; var previewedSound = null; // get the current tab chrome.tabs.getSelected(null, function(_tab){ tab = _tab; insureElementExists(); tabSettings = background.bingTabs[tab.id]; // check the bing box document.getElementById("bing").checked = tabSettings.bing; // select the sound var sound = document.getElementById("sound"); for(var i = 0 ; i < sound.options.length; i++){ var option = sound.options[i]; if(option.value == tabSettings.sound){ sound.selectedIndex = i; break; } } // check the repeat box document.getElementById("repeat").checked = tabSettings.repeat; }); function toggleBing(bing){ background.bingTabs[tab.id].bing = bing; } function selectSound(sound){ background.bingTabs[tab.id].sound = sound; preview(sound); } function toggleRepeat(repeat){ background.bingTabs[tab.id].repeat = repeat; } function insureElementExists(){ if(background.bingTabs[tab.id] == undefined){ background.bingTabs[tab.id] = { bing: false, sound: "Bing", repeat: false, playing: null } } } function preview(sound){ if(previewedSound != null){ background.stop(previewedSound); } previewedSound = background.play(sound, false); } <p> Make this tab bing when loaded. </p> <p> Choose a sound: Alarm Bing Bleep Door Buzzer Rooster Siren Smoke Alarm Whoop <img src="play.png" /> </p> <p> Repeat until the tab is selected. </p>
The first thing you may note is that this looks pretty much like any HTML file. That’s because it is! Take a look at the body and note that I’m using HTML form elements to define my popup. Heck, I even use CSS to format the popup!
Here’s what it looks like in the browser:
Looking at the JavaScript in the popup you’ll see that I have this line of code first:
var background = chrome.extension.getBackgroundPage();
This returns a reference to the background.html page. Once I have this reference I can call functions on it. Before I show that though, let me show you the code for the background.html:
chrome.tabs.onUpdated.addListener( function(tabId, changeInfo, tab) { if(changeInfo.status == "complete"){ if(bingTabs[tabId] != undefined && bingTabs[tabId].bing){ if(currentTab != tabId && bingTabs[tabId].repeat){ bingTabs[tabId].playing = play(bingTabs[tabId].sound, true); } else { bingTabs[tabId].playing = play(bingTabs[tabId].sound, false); } } } } ); chrome.tabs.getSelected(null, function(tab){ currentTab = tab.id; }); chrome.tabs.onSelectionChanged.addListener( function(tabId, selectInfo){ currentTab = tabId; stop(bingTabs[tabId].playing); } ); var bingTabs = {}; function bing(id){ sound = bingTabs[id].sound; play(sound, false); } function play(sound, repeat){ var audio = new Audio(sound + ".mp3"); if(repeat){ audio.loop = true; } audio.play(); return audio; } function stop(sound){ sound.pause(); }
Not a very long script is it? It’s entirely JavaScript too!
What this does, is make use of the Chrome extension API to listen for tab updated events. When they occur it looks to see if that specific tab is set to bing. If so, it bings by using the HTML 5 audio API to play an MP3 file.
Going back to the popup.html, when you check the checkbox to make the tab bing, the checkbox’s onChange event calls the toggleBing() function. This toggleBing() function simply calls the background page and tells it to make that tab bing when done loading.
What I really think is cool about Chrome extensions are how quickly I got up to speed. It literally only took about half an hour and I was off to the races. The Chrome extensions documentation is terrific to! And once I had a working version I was able to quickly and easily make changes to add additional features. You do have to click reload in the extensions tab, but that beats the pants off reloading the entire browser with each change.
Additionally, with Firefox, it was really very difficult to publish the extension to addons.mozilla.com. For Chrome it was as simple as uploading my extension’s folder to Google’s Chrome extensions website.
The biggest gripe I have, though, is that Chrome’s simplicity is also a little limiting. I can’t completely change any feature within the browser. But, in all honesty, I think it’s a good tradeoff for a much nicer user experience.
If you’re interested you can download my Tab Bing! Chrome extension here.
I figure that next I’ll make my Tab Bing! extension make the tab’s icon blink when a tab is loaded! What extensions would you create if you had the time and know-how?
A Handy Way To Convert US Time Zones
Today’s blog entry is a bit off my typical subjects on this blog. But, as someone who works from home for clients across the US, I often have to figure out what, for example, 9am Eastern Time is in Pacific Time.
As the title suggests, I have a – ahem – handy way to figure this out. What I do is use my knuckles. Specifically, there are four knuckles on each of your hand (excluding your thumb). There are also four time zones in the US. So, if you need to convert from one time zone or another, you simply choose the knuckle corresponding to the time zone and count up to the right and down to the left. Here’s an image that helps demonstrate the concept:
The idea is that if someone asks you to attend a meeting at 3pm Pacific Time and you’re in Central Time, you simply start at the Pacific knuckle and count up to Central. Thus, 3pm Pacific is 5pm Central. And, vice versa. If someone in Eastern Time suggests a 3pm meeting and you’re in Mountain Time, you start with the right-most knuckle and count down to find out that 3pm Eastern is 1pm Mountain.
For those of you who are naturals at figuring out time zone differences this may be a little less than useful. For everyone else, I hope you enjoy!
And, while I’m on it, this idea came to me from a similar trick I use to figure out the number of days in each month.
What you do is start from your left-most knuckle and count months to the right. In this case you count both the knuckles and the space between the knuckles. So the left most knuckle is January, the first space is February, the second knuckle is March, etc. (The last space and knuckle on your right hand isn’t used.) Here’s an illustration:
Any knuckle-month has 31 days and any space-month has 30 days. The only exception is February, which usually has 28 unless you’re in a leap year and it has 29.
What do you think? Do you use any hand-based mnemonics?
Ant4CF’s Documentation and Ant 1.8
I’ve been notified twice now that there are problems running Ant4CF on Ant 1.8 or later. I wanted to let those users of Ant4CF know that I’m aware of these problems and will eventually update the project to work with Ant 1.8. My guess is that the project is being compiled against an older Ant API that isn’t compatible with Ant 1.8. That said, a quick Google search on this didn’t turn up any details. I’ll take care of this before too long and let everyone know about it!
Also, a few people have had issues getting Ant4CF up and running. The usual culprit here is the config.properties file that users need to edit to point to the local installation of Ant. On Windows in particular this can be confusing. The cause of this is that the default path to Ant is “/usr/bin/ant”. On *nix OSes this is a path to an executable. But to a Windows user this looks like it might be a path to a directory. I’ve updated the documentation to explain that on Windows this path is likely to be something more like “c:/program files/ant/bin/ant.bat”. Also, because there are spaces in the path, the path needs to be surrounded in quotes in the configuration file.
And that’s it for Ant4CF news. But, let me ask you, do you use Ant4CF? What do you think of it? Any suggestions on what I could do with it next?
I’ll Be At CFUnited After All!
It looks like the stars have aligned for me, after all and I will be attending this year’s (and the last ever) CFUnited. I managed to schedule a couple client meetings at the same time and that really helps justify the expense.
If you’re going to be there too, please look me up! Why? Well, there’s no exciting reason, honestly. Unlike past years, I’m not giving anything away. Honestly, I just want to meet as many people as I can, hear what they’re working on, and learn as much has I possibly can. And, if I’m lucky maybe I’ll find a business opportunity or two.
Also, because I waited until the last moment, it seems that the Landsdown resort is booked up for Wednesday night. If anyone has some spare floor space or a couch I could crash on for one night, I’d be greatly indebted to you! Thanks!
An Introduction To NodeJS, A JavaScript-Based Server
Recently, I’ve been dipping my toes into languages and technologies I might not previously have. For the last ten years or so ColdFusion has been my bread and butter. Yes, I’ve tinkered with other languages like Groovy, but now I’m trying to make a more concerted effort to learn more about things I otherwise might not.
Recently I’ve been teaching myself a little Ruby and Rails. A local buddy of mine, Bucky Schwarz brought the The Raleigh-area Ruby Brigade to my attention. Last night I attended one of their meetings anticipating learning more about Ruby. However, the topic was not on Ruby, but on NodeJS. The talk was given by Aaron Heckmann.
I recently heard about some developments around JavaScript based servers. Some people are making use of them because they can apparently handle insane loads. I’ve heard of some applications handling thousands of connections a second. Last week I tried to Google around and see what I could find, with no luck. So, imagine my surprise when the Ruby meetup topic was about NodeJS, a JavaScript server.
NodeJS is the brainchild of Ryan Dahl and makes use of Google’s open source V8 JavaScript engine. Because of this, NodeJS benefits from the recent competition between Firefox, Google, IE, and Opera on JavaScript engine performance. In other words, NodeJS is very fast.
Installing NodeJS was very simple for me, since I’m on OS X. I can’t say it will be quite that simple for those in the Windows world since you have to download and build the source code. This was as simple as running ./configure, make, make install. Once NodeJS was installed I was able to run a couple of simple sample applications without any problems.
Much to my surprise, I was able to make small changes to these sample applications because… I know JavaScript! I was able to take the HTTP hello world application and change it slightly. The same was true for the network socket sample. Cool!
My initial impression with both of these samples were two-fold:
- Wow, that starts up fast! For the simple hello world-style applications there was literally no wait to start NodeJS.
- The basic sytax was simple and easy to read. All you need to do to start listening for HTTP requests is this:
var http = require('http'); http.createServer(function (req, res) {…}
Now, there are some challenges with Node. In particular, it’s intended to be pretty low-level. Those of us more comfortable working with higher-level languages might find Node, perhaps, a bit cumbersome.
Thankfully there are a lot of handy modules available for Node. One of these is Express. Express is a small server-side JavaScript web development framework for NodeJS.
To install Express I had to first install Kiwi, which is yet another package management system. To install Kiwi, I simply cloned the Git repository locally using:
git clone http://github.com/visionmedia/kiwi.git
Next, I ran make install in the newly downloaded kiwi directory. For me, this just worked.
Once I had Kiwi I was able to install express by simply running:
kiwi -v install express
Now that I have everything I needed I was able to create copy and paste a quick Express hello world application:
var sys = require("sys"), kiwi = require("kiwi"), express = kiwi.require('express') get('/', function(){ this.redirect('/hello/world') }) get('/hello/world', function(){ return 'Hello World' }) get('/goodbye/world', function(){ return 'Goodbye World' }) run()
In the example above, once you start node running this application, you can hit this application at http://localhost:3000. The default request will redirect you to /hello/world. You can also go to /goodbye/world.
The Express module has a range of other features for routing requests, rendering views, and more. Frankly, I haven’t taken it much beyond what’s in this article yet.
Despite the relative youth of the NodeJS project, it seems to me like there’s a lot of energy and excitement behind it. You only need to look at the Module list to realize there are a lot of people working very hard on this project. Just to highlight a few, there are modules to connect to various databases, including MySQL and MongoDB, and many others. There are also modules for logging, templating, testing, and much, much more.
Overall, NodeJS really seems worth trying out and experimenting with.
Dan Wilson Will Kick Ass at CFUnited
Last Thursday the local Triangle Area ColdFusion User Group (TACFUG) held a meeting where our very own Dan Wilson gave preview presentations of two of the four presentations he’ll be giving at CFUnited in the next week.
The first presentation he gave was Get the Lead Out – Practical Optimization. As with everything Dan does, this was a very good presentation. Dan started out the presentation with a set of slides asking which was faster between two sets of similar code. For example, he compared using cfif to cfswitch. I was really surprised by this, but it turned out this was a red herring and wasn’t the real meat of the presentation. Dan gets into a lot of detail about holistically testing applications. In fact, he even taught me a few things I didn’t know, and I like to think I know a thing or two about this stuff.
The second presentation has what may well be the best title I’ve ever seen at a tech conference, Cache Me if You Can. Of course, that title doesn’t make any sense to our Australian friend, Mark Mandel, but we’ll just have to deal with that. In this presentation Dan talked about a whole range of assumptions many developers make about caching. He also makes some very interesting points about being sure that you know what you’re caching and why. As usual, this was an excellent presentation as well.
Dan has a really easy and relaxed style of presentation that I really admire. If you’ve not heard him talk and you’ll be at CFUnited, then I highly recommend you catch his talks!