1. Cleaning Up

    I’ve spent several hours this morning performing some long-overdue online identity maintenance. Like many of you, I’d imagine, I’ve accumulated a trail of neglected blogs, web sites, unused domain names and forgotten accounts. There’s still a lot to do to get things where I’d really like them to be, but it feels good to have at least tackled the worst of it.

    Step 1. Taking inventory

    The first thing I did this morning was put together an inventory (of sorts) in MindNode Pro. I put down every domain name, blog, site and service I could recall ever using into nodes on the tree. Having it all in one place made it much easier to see where most of the dead wood needed to be cut away.

    Step 2. Fixing Broken DNS

    I’ve started moving my domain names to a new registrar recently and, in the process, lost a decent amount of DNS configuration information. Broken URLs were at the top of my list, but I also took this time to set up a few forwards on some recently registered domain names.

    Step 3. Giving Notice

    The next step was to post an update to a couple of blogs I no longer use. I tried to say, in the nicest way possible, that while I was no longer posting there, I hadn’t disappeared of the face of the earth and if they’d like to see what I’m doing now, well that’d be swell. I could have deleted these accounts but there’s still content there I want to keep, and they still see traffic that could possible be redirected to more active pages. Eventually, I think I’ll want to consolidate at least the article content into a single site but I not in a huge rush and I’m also not entirely sure my current blog provider (Tumblr) is where I want call home for the long term.

    Step 4. Moving Things Around

    I keep a placeholder page at driscolldev.com that was previously hosted on Google AppEngine. This worked pretty well, but updating the site required having both the latest source and the AppEngine launcher installed. Moving the page over the GitHub pages took less than an hour and now I can update the site from anywhere I have Git and a text editor.

    Step 5. Putting My Best Foot Forward

    This is an ongoing battle when you have multiple accounts online to keep fresh. Bio’s, blurbs and profile pics sit forgotten and woefully out of date on services I rarely visit, and even on some I visit regularly. Gravatar helps a little, but because only a limited number of the services I use have integration, it mostly becomes one more thing to forget to update. It’s also hard to decide what services are worth having to update in the first place (does anyone use about.me?) and I struggle with the trade off between having more content about me online that I have some control over versus the cost of keep it current.

    Keeping It Up

    There’s still (and always) more work to do but it was worth losing a Sunday morning bringing the most visible aspects of my online identity up to date. You never know to whom you’re making a bad first impression online.

  2. JCDHTTPConnection

    The other day on twitter I mused (i.e. complained):

    iOS needs a block-based UIAlertView. So many currently-delegate based interfaces would be better served by block callbacks.

    Being a man of action, Brian Cooke took the off-hand remark and ran with it, creating his RooAlertView block-based UIAlertView wrapper.

    Inspired by Brian’s gift of source – and maybe just to keep this code-volley going – I’m putting up my own block-based NSURLConnection wrapper, JCDHTTPConnection.

    JCDHTTPConnection is a pretty simple class that takes a NSURLRequest object and (up to) three block callbacks: onSuccess, onFailure, and onDidSendData. It’s asyncronous, of course, and much more convenient than setting up a delegate. I’m pretty happy with it, and I hope it might help someone out.

    Get it at GitHub.

  3. ImageKit Has Moved

    I’m very happy to announce that the ImageKit project has acquired a trio of new maintainers. Greg Newman, Bryan Veloso and Chris Drackett have generously offered to help keep the project moving forward and bug-free.

    In the interest of easier collaboration, the project’s main repository and project page have been moved to GitHub. Please direct any future issue reports or feature requests to this site.

    https://github.com/jdriscoll/django-imagekit

  4. SuperDuper and Hazel’s App Sweep

    If Hazel’s App Sweep function stops working for you, a backup drive (or folder) might be the problem. Hazel automatically ignores Time Machine volumes but other backups, such as a Super Duper clone, can trick Hazel into thinking the App is still installed.

    As of writing this, there’s currently no way to ignore volumes or folders in the Hazel interface but there is a hidden preference for it that you can access easily though the Terminal.

    Running the following and restarting Hazel solves the issue:

    defaults write com.noodlesoft.Hazel IgnoredBackupDirs -array dir1 dir2
    

    If you want to ignore a backup drive or your path has spaces in it the command you run might look like this:

    defaults write com.noodlesoft.Hazel IgnoredBackupDirs -array "/Volumes/SD Clone"
    

    If for some crazy reason you don’t own both Super Duper and Hazel (and you use a Mac) go buy them both right now.

  5. Geocoding Forms on Submit with Javascript

    The Google Maps API offers an exceptional geocoding service. It’s accurate, reliable and well documented. However, on shared hosting environments (such as Google’s own AppEngine), rate-limiting can become an issue quickly. Fortunately, using the Javascript API (and jQuery), we can offload this task to the client where the number of requests from the current IP address is unlikely to become an issue. When implemented in conjunction with server-side geocoding, we can deliver a reasonably robust solution that’s transparent to the user and gracefully degrades when Javascript is unavailable.

    Let’s start with a simple example. Let’s assume we need to capture our user’s names and addresses with the intention of plotting them on a map. Here’s a simple form:

    <form method="post">
        <p><label>Name:</label> <input type="text" name="name"></p>
        <p><label>Street Address:</label> <input type="text" name="street_address"></p>
        <p><label>City:</label> <input type="text" name="state"></p>
        <p><label>State:</label> <input type="text" name="state"></p>
        <p><label>Postal Code:</label> <input type="text" name="postal_code"></p>
        <p><label>Country:</label> <input type="text" name="country"></p>
        <p><input type="submit" value="Submit"></p>
    </form>
    

    For the sake of argument, let’s also assume that when submitted, we’ve already implemented the logic necessary to geocode this address on the server before the data is saved. Now all is well and good until we discover that relying on server-side geocoding is not an option (and it wouldn’t it be really nice if our form could supply the latitude and longitude values?)

    This is where the Javascript API can help. What if, when the user submits this form, their address was quietly geocoded behind the scenes and the result was sent along with the form? If the server sees that the address has already been geocoded it can happily save the values without having to attempt the request itself. If not, the server-side geocoding machinery can step in and attempt to complete the process.

    First things first. Let’s give assign our form a CSS class to identify it as a target for geocoding.

    <form class="geocode" method="post">
        <p><label>Name:</label> <input type="text" name="name"></p>
        <p><label>Street Address:</label> <input type="text" name="street_address"></p>
        <p><label>City:</label> <input type="text" name="state"></p>
        <p><label>State:</label> <input type="text" name="state"></p>
        <p><label>Postal Code:</label> <input type="text" name="postal_code"></p>
        <p><label>Country:</label> <input type="text" name="country"></p>
        <p><input type="submit" value="Submit"></p>
    </form>
    

    Next we need to include jQuery and the Google Maps API Javascript library.

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
    <script src="http://maps.google.com/maps/api/js?sensor=false"></script>
    

    Now we can write our script.

    <script>
    var geocoder;
    $(document).ready(function() {
        geocoder = new google.maps.Geocoder();
        $('form.geocode').submit(function(e) {
            var that = this;
            var addr;
            var addrArray = [];
            var addrFields = ['street_address', 'city', 'state', 'postal_code', 'country'];
            $(addrFields).each(function(idx, name) {
                var val = $(this).find('input[name="' + name + '"]').val();
                if (val.length) {
                    addrArray.push(val);
                }
            });
            if (addrArray.length) {
                e.preventDefault();
                $(that).unbind('submit');            
                var onSuccess = function(results, status) {
                    if (status == google.maps.GeocoderStatus.OK) {
                        result = results[0].geometry.location;
                        var point = result.lat() + ', ' + result.lng();
                        $(that).prepend('<input type="hidden" name="point" value="' + point + '">');
                    }
                    $(that).trigger('submit');
                }
            }
        });
    });
    </script>
    

    Let’s take a look at the important bits. First we declare a variable to hold our Geocoder object.

    var geocoder;
    

    After that, using jQuery, we assign a function to the submit event for all forms with the CSS class “Geocode”.

    $('form.geocode').submit(function(e) {
        ...
    

    In the next line, we save the current object (this) to the local variable (that) so that we can access it from within our callback function later via a closure.

    var that = this;
    

    The next few lines just build an array of address values (from our form) that we can assemble into a single string that the Geocoder will accept.

    var addrArray = [];
    var addrFields = ['street_address', 'city', 'state', 'postal_code', 'country'];
    $(addrFields).each(function(idx, name) {
        var val = $(this).find('input[name="' + name + '"]').val();
        if (val.length) {
            addrArray.push(val);
        }
    });
    

    With that out of the way we first make sure we have something to geocode, and if so, call preventDefault to stop the form from being submitted.

    e.preventDefault();
    

    Next we remove the event handler from the form so that once geocoding is complete we can submit the form successfully without triggering our code again.

    $(that).unbind('submit'); 
    

    This next bit is the callback function we’re going to pass to the Geocoder object that will be executed once our request is returned. This function first checks for a successful response, and if found, prepends a hidden field to our form containing the latitude and longitude information we received. Once the request has been returned, regardless of the result, we need to submit the form data by triggering the “submit” event on our form.

    var onSuccess = function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
            result = results[0].geometry.location;
            var point = result.lat() + ', ' + result.lng();
            $(that).prepend('<input type="hidden" name="point" value="' + point + '">');
        }
        $(that).trigger('submit');
    }
    

    Lastly, we assemble the address values into a single, comma separated string and pass this value and our callback function to the geocode method of our geocoder object.

    addr = addrArray.join(', ');
    geocoder.geocode({'address': addr}, onSuccess);
    

    Now we can stop relying on the server to do all our geocoding. Of course, if our request fails (or the user has Javascript disabled), the server can still pick up the slack in most cases.

    If you have any questions, comments or corrections please contact me at justin@driscolldev.com.

  6. Panic Blog » The Panic Status Board »

    Inspirational.

  7. The iPhone, IMAP and Multiple “From:” Addresses

    I currently manage several email addresses through a single Gmail account, and apart from Google’s creative interpretation of the IMAP protocol, it’s been grand. I can send and receive messages to or from any of my accounts from a single, virtually spam-free, inbox. I wanted this ability on my iPhone as well but the setup is not as straightforward as it could be. Here’s what worked:

    First, you need to setup a new mail account on your iPhone for Gmail, but not using the iPhone’s Gmail account type. Seriously, this is key. To be more specific, after you select “Add Account…”, choose “Other”. I should also mention that you can’t do this using Google Sync’s Exchange support. Now, after you’ve typed out your email address and password 12 times and filled in the other important bits as described here, you should have a functional IMAP email account. Which leads us to the second (not so) tricky part. The way you add multiple addresses to your new account is to input them into the “Address” field, under “IMAP Account Information”, with each address separated by a comma. Just like Mail.app! Except, you can’t type a comma in that field. I’ll wait while you try it… No? Good. Anyway, the obvious way around this is open any app that supports editable text, type in your address list, copy it, and paste it back into the “Address” field. You could also use the Description field. It’s up to you.

    Now you should be able to select any of the email addresses you entered as the “From:” address in Mail.

    UPDATE: Here’s a great article on setting up both Mail.app and iPhone Mail for Gmail.

    Posted via email from Just-O-Matic

  8. It snowed like crazy last night and now the power is only available intermittently at work. I guess I&#8217;m working from home today.

    It snowed like crazy last night and now the power is only available intermittently at work. I guess I’m working from home today.

  9. Getting Into the Habit

    Often the simplest goals I set for myself become perpetual disappointments as I fail to meet them time and again. When the cost of failure, or reward for success, falls just short of what is required to motivate me.

    For a long time I’ve wanted get better at capturing the unique moments in my life. Both events I want to share with others and those that may only be meaningful on a personal level. I bought a decent pocket camera and a flip camcorder with this goal in mind, yet I never seem to have either when I need them.

    Last night we found a tiny mouse in our basement, and for the next 10 minutes we engaged in a frantic chase, armed only with a towel, feebly attempting to corral it, before one good toss, and a hurried trip up the stairs and outside, left the mouse darting off into the night. In hindsight it was just the kind of event that I bought the flip to capture, yet the thought never occurred to me.

    Some people seem to have an innate gift for capturing these common, but extraordinary, moments. Is it genetic? Is it a question of superior hardware? Or is just an instinct they’ve cultivated over years?

  10. Reboot…

    I set up this tumblr account some time ago and then proceeded to completely neglect it. Having always been a fan of fresh starts and clean slates, I’ve opted to “reboot” my tumblog and see what happens…

    $ sudo shutdown -r now
    

Theme = Manuscript Neue (Customized)