captured sparks

Archive for 2009

Autocomplete with Rails and Prototype

For an application, I’m working on, I needed to associate an aircraft to an airport. The airport database I’m using has about 10000 entries so using a select box was impractical.

I looked at some autocomplete plugins but none of them seemed to do what I wanted so I decided to make my own. The solution had to take a string entered by the user and return a list of airports containing that string; display the list of airports, then fill the text box when a user clicks on the airport name. This is how I did it:

new Form.Element.Observer('plane_airport_id', 0.1, function(event) {
  var string = $F('plane_airport_id');
    if (string.length >= 3) {

This sets up an observer on the appropriate form field, captures the value and, if the length of the input is greater than or equal to three characters, executes the next part of the script.

      new Ajax.Request('/airports', {method:'get',parameters:{search:string},
        onSuccess: function(transport) {
          var airports = transport.responseJSON;

We then setup an XHR to the index method of our airports controller, passing the field value as the search parameter. When the call returns successfully, we pass the returned data into the airports variable.

          var lis = $('airport-list').descendants();
          if (lis.length > 0) {
            lis.each(function(l) {
              l.remove();
            });
          };
[javascript]

This removes any existing airports in the airport list.

[javascript]
          airports.each(function(a) {
            var item = "<li class='airport'><a href='javascript:;' class='airport-link'>" + a + "</a></li>";
            $('airport-list').insert(item);
          });
          $$('.airport-link').each(function(a) {
            a.observe("click", function() {
              var text = $(this).innerHTML;
              Form.Element.setValue('plane_airport_id',text);
            });
          });

Finally, we take each returned airport, enclose it in list item and anchor tags, and insert each into the unordered list element already in the page. We attach an observer to each anchor tag, so that when it is clicked, it will update the field with the appropriate value. The remaining open brackets are closed accordingly.

The index action in the airports controller is fairly straightforward:

def index
  search = params[:search]
  airports = Airport.find(:all, :conditions => ['name LIKE ?', "%"+search+"%"])
  @airports = Array.new
  airports.each do |a|
    @airports << "#{capitalize_all(a.name)}, #{capitalize_all(a.country)} (#{a.icao})"
  end
  render :json => @airports.to_json
end

As the form passes the airport as a string value, when creating an aircraft, I use a regex to extract the ICAO identifier from the string, lookup the corresponding airport and manually update the association column for the aircraft.

The entire javascript code is available as a gist.

How do aviva get it so wrong?

Aviva password recovery screen

The first thing is the security question. I can’t remember ever telling Aviva the name of the first street I lived on but will assume for these purposes that I did. The street name consisted of 7 letters and then 5 letters: let’s say Putting Green.

The first problem is of course encountered when entering the 13th letter. To make it work, the space needs to be included. This then presents the second problem; the 8th letter would be the space. It is easy enough to remove the space when creating the security question but no security question should allow the user to enter a string with spaces when you’re asking for specific letters.

The second issue is that the statement, “Not sure of your answer>>”, which one assumes to be a link, is not a link.

I was viewing this in Safari 4, so I’m not sure what they are doing with the password hint box. Perhaps it works fine in IE.

Finally, and it is not demonstrated on the screenshot, the cursor retains its default setting when hovering over the continue and back links. It should of course change to pointer so that user expectations are met when hovering a link.

As a result of this, my account ended up being locked. Despite an online request for somebody to contact me to fix it, I’ve had no response. I gave up waiting in their phone queue after 15 minutes.

One would hope that large companies could avoid such basic errors, particularly when the service is marketed as an online service. Access to all policy documents is via the online portal so it is a fundamental part of their service.

A ruby wrapper for tr.im

I’ve spent the weekend creating my first gem release, version 0.0.1 of which is now available.

The purpose of the gem is to provide a wrapper around the tr.im api. At the moment, it only supports the ability to trim a larger url down to size. I found this to be a good introduction to working with an API as no authentication is required for this basic functionality. Over time, I intend to add in the other functionality supported by the API.

Following Github’s decision to not support the creation of new gems, the gem is stored at Gemcutter. To install, you will need to do the following:

gem sources -a http://gemcutter.org/
gem install trim-api

I hope it is of use.

Design Decisions

When redesigning captured sparks, I made the conscious decision to design for the latest browsers. This was for 2 reasons: Firstly, it reduced the amount of time I needed to spend testing the site – an entirely selfish reason, I accept. Secondly, the only way to drive a reduction in the number of users with older browsers, is for more developers and designers to design sites using the latest technology.

I accept, of course, that a significant number of users in corporate environments may have no control over their browser of choice. For this, I do plan on offering a simple version of captured sparks.

In light of this, I have not had regard to compatibility with older browsers such as Internet Explorer 6. The main feature, unsupported by older browsers, that this site makes use of is the @font-face construct. Headings on the site use the Contra font, with degradation to Georgia etc.

I also make liberal use of some other CSS3 properties:

border-radius: 5px;
box-shadow: 2px 2px 10px #222;

I’m also using a Safari only property to handle the fades on the “Work”:http://capturedsparks.com/jobs page:

-webkit-transition: opacity 0.7s linear;

Given that I use this site to try and secure work, it may not be the best illustration of how I can make a site cross-browser compatible. However, in these circumstances, I hope potential clients will look at my other work and see that for paid work, cross-browser compatibility is something I do strive for.

Back

So, I’m back. And with a refresh.

In the 8 months since my last posting, I’ve worked on another site and done a lot of work at my day job.

I have a couple of posts lined up web design on bits and pieces that I’ve noticed recently and I’m considering doing a beginner’s series on Ruby on Rails but want to make sure I have a plan for it first.

Good to be back.

Update!

So, my last entry here was 17th August 2008. And that was written just over a month after I said I would post more. Work took over. My full-time job was incredibly busy during the last 3 months of 2008 and the I have been working on a Rails site since October and that is still ongoing. As a result of this combination, I never really had the opportunity to post anything to the blog.

For me, 2008 was a good year. During 2007, my site received 200 visits. In 2008, it received over 1700 visits. This was driven primarily by three articles I wrote on 2 subjects – combining ActiveMerchant and Paypal (something I still receive emails about) and receiving emails with Rails. The visitor numbers have kept up through January 2009 and I hope to post more this year to drive more traffic.

The site I’m working on at the moment is a straight-forward brochure site although I have done a nice implementation with Google Maps to show the nearest stockists for the products sold by the client. This should be finished within the next month, following which I hope to work on a small project of my own. Nothing concrete as yet but have some ideas floating round my head.

Finally, I’ve been spammed massively in the comments. If you left a comment after 16 January, I’m afraid I’ve had to delete it as I couldn’t go through 2000 comments to identify the genuine ones. Sorry again.