Unobtrusive Auto-Completing Text Fields With Prototype & Scriptaculous 2

Posted by Carsten Nielsen
on Wednesday, December 17

I recently had to add some auto completion behavior to a few text fields on LearnHub. Rails used to have a view helper for this baked-in, it’s a plugin now, but I never really liked working with it. I hate farting <script> elements throughout my HTML for functionality like this, it looks dirty and just feels wrong to me.

My goal was to go from something nasty like this:


<input type='text' name='school[name]' id='school_name_1' />
<div class='autocompleter-choices' id='school_name_1_completer'></div>
<script type='text/javascript'>
//<![CDATA[
new Ajax.Autocompleter(
  'school_name_1',
  'school_name_1_completer',
  '/schools/autocompleter/search',
  { 'paramName' : 'q' }
);
//]]>
</script>

To something simple and elegant like this:


<input type='text' name='school[name]' autocompleter='/schools/autocompleter/search' />

My solution was to do it unobtrusively with some straight-forward Javascript:


Helpers.TextFieldAutocompleters = {

  init : function()
  {
    $$('input[autocompleter]').each(function(input) {
      url = input.readAttribute('autocompleter');
      container = new Element('div', { 'class' : 'autocompleter-choices' });
      input.insert({ 'after' : container });
      new Ajax.Autocompleter(input.identify(), container.identify(), url, {
        'paramName' : 'q'
      });
    });
  }

}

Event.observe(window, 'load', function() {
  Helpers.TextFieldAutocompleters.init();
});

Lets have a quick look at what I am doing here:

  • I use Prototype’s $$ utility method to grab all of the <input> elements on the page that have an autocompleter attribute.
  • I insert an anonymous <div> below each <input> to contain the <ul> of results returned by the server.
  • I use Prototype’s Element.identify() method to automatically generate DOM IDs for the anonymous/potentially anonymous container <div> and <input> elements.
  • I create a new Scriptaculous Ajax.Autocompleter that will submit to the path indicated in the <input> element’s autocompleter attribute and use ‘q’ as the param name.

That’s all there is to it!

The Rest Of It

This is the controller action:


def autocompleter_search
  @schools = School.name_like(params[:q]).all(:limit => 8)
  t = []
  t << '%ul'
  t << '  - @schools.each do |school|'
  t << '    %li= highlight h(school), h(params[:q])'
  template = t.join("\n")
  respond_to do |format|
    format.js   { render :inline => template, :type => :haml }
    format.html { render :inline => template, :type => :haml }
  end
end

The named_scope I’m using for the above School finder:


named_scope :name_like, lambda { |name|
  { :conditions => ['`name` LIKE ?', "%#{name}%"],
    :order => '`name` ASC' } }

And the styles I use for the choices list:


.autocompleter-choices
  :background #fff
  :border 1px solid #8caddd
  :margin-top -1px
  ul
    :padding 2px
    li
      :padding 3px
      em
        :font-weight bold
        :font-style normal
      &.selected
        :background #f6eda9

That didn’t hurt one bit!

Waking Up The Brain 7

Posted by Carsten Nielsen
on Saturday, October 25

Before the first revision of a comp or the first passed test, I find the biggest problem I face is finding a way to harness my creative wit and direct it towards a new problem. Getting focused when there are all kinds of ideas, deadlines, demands and expectations floating around your noggin is a must, but it’s not always easy.

I’m going to share some methods that I use to get back on track and focus my creative and analytical energy. Sometimes I follow my process start to end and sometimes I jump straight to brainstorming, it depends on my state of mind at the time. I hope you enjoy!

Contour Drawing

Contour drawing is often my first step when I’ve been extremely focused on other things and in need of a reset. I find it really cleans my mind’s slate, sort of like shaking an Etch-A-Sketch. I like to start off blind contour and then move my way to modified contour.

Freestyle (Writing & Drawing)

I find it necessary to turn up the crazy and focus in on something new and offbeat to get myself in the mood for some design and analysis. I usually put on my headphones and queue up some music. I start writing and doodling arbitrarily at first, and then gradually transition towards the topic I’m going to be brainstorming.

I sometimes write a dialog between two characters with opposing opinions or about a feeling or experience that I’ve never felt or had. I will often draw haphazardly; creating a form and then just adding other forms onto it transforming it into whatever. Sometimes if I really need to think differently, I’ll draw a Rube Goldberg machine in some form.

They key with freestyle I find is to avoid stopping and thinking about something else so you don’t interrupt your flow of ideas. Freestyle is a preparatory process for me that leads to brainstorming.

Brainstorming

After contour drawing and/or some freestiling, I start focusing in again. I feel refreshed and I find it much easier to form and output tangible ideas. At this stage I’ll use a little color to spice things up, but often it’s just black ink on layout stock. You could get fancy and use a four color ballpoint like Ed Fella, but that seems like a lot of work to me.

Brainstorming for me is sort of like a formal form of freestyle, I force myself to stay on topic, and I create things that I might show other people. These range from the infamous word cloud, to comprehensive wireframes, and sometimes even code. It’s not uncommon for me to draw a wireframe and also the structure of it’s markup.

Often times I brainstorm my initial ideas independently and in silence. However, when I’m far enough along in the creative process I like to share the activity with other designers and developers, and sometimes friends or other coworkers.

Final Thoughts

I found it tough at first to be this raw. It wasn’t easy until I came to the realization that it’s okay to be bogus. Just because I draw or write something doesn’t automatically make it a direct reflection of who I am and I don’t have to put everything I make on public display. After those realizations I was free to experiment, and able to let myself wander areas of my mind that I’d never been.

Seven Ways To Get Out of The Basement 7

Posted by Carsten Nielsen
on Friday, October 10

I am really happy where I am right now. It’s hard to think that not too long ago, I was in my parents’ basement dreaming of working in the big city and building an awesome product — stuck in a rut of sorts. I’m going to share the values that I feel helped me get out of that rut and move beyond the basement.

1. You Must Have Passion

Passion is your fuel, you need passion! It’s the only way you will be disciplined enough to be able to fight down the odds. If you’re not thinking about it day and night, living and breathing it, then it might not be for you. Passionate people enjoy the company of other passionate people, you want to know passionate people… see where I’m going with this?

2. ‘No’ is a Statement, Not An Answer

Before I decided to take a different approach I tried to get into YSDN two times and Ryerson Image Arts once. It was at the end of my second interview at YSDN that I was told to stop learning on my own until I get the first few years of a BA out of the way, then try applying again.

You will meet a lot of different people along the way, many of which will not share your passion. Politely thank them for their opinion, then visualize yourself in the future telling them they were wrong. You’re on the fringe with your scary, self-disciplined ways, and you are going to be going against the grain of many people.

3. Get Out There And Mingle

A lot of people in my life have just finished university or college and want to get started doing something they love, but how? From my experience handing out resumes and the like won’t get you nearly as far as mingling with the people in your industry.

I’m lucky that there is a very visible technology community in Toronto and tons of free or almost free events all of the time. I met my first employer at a free event, and I met John and Malgosia at a moving party for the company that organizes that event.

I always thought the best events were the free ones, my opinion changed this summer though. I attended a conference that was worth every dollar. I’ve also attended some other conferences that were not worth their weight in silly clown noses. I will say that for the most part, you get back what you put into these things.

Take a chance, get out there and meet people! Even if it means spending some money that you might not have. I’m sure you’ve spent money on less important things.

4. Don’t Turn Down Any Opportunity

My first job in Toronto was at a company called TSOT, their product was a social network for fraternities, not really something I’m personally interested in. However, for a guy with pretty much zero programming experience at the time it was a rare opportunity. If I brushed it off, I might still be in basement land.

5. You Know Nothing

Humility is your best friend! You are surrounded by people who know a lot more than you, and if you aren’t then maybe it’s time to smarten up. As soon as you start to feel comfortable, be terrified. You’re not all that great at whatever it is you do, and you have a lot to learn from a lot of people. Embrace it, love it.

Another part of this is accepting criticism gracefully. It’s only criticism, you don’t have to act on it, but it should always cause you to think twice. If you don’t listen to other peoples’ opinions about your work then you are missing out on a huge amount of opportunity. The twist to this is that you can really learn a lot about someone in the way that they deliver their criticisms to you.

6. Don’t Let The Haters Get You Down

You are always going to encounter toxic people that simply don’t like you. Maybe they are jealous and feel threatened by you and your kind or maybe they were born without genitalia and are just generally miserable, or maybe you can be a bit of a condescending asshole at times. Whatever the case, being pissed off is not going to help. So bitch about it on Twitter and move on.

7. Stay Absolutely Positive

You’re doing what you love, after all! And if not, then why not?

Rubyisms That Ruby Programmers Should Know 3

Posted by Carsten Nielsen
on Monday, September 29

There are a few things that I know now and take for granted which used to blow my mind. If only someone took the 10 minutes to explain these concepts to me back when I started programming I would have been in the know so much sooner. Hopefully I can be that someone for you if you are stuck on any of these yourself.

The Splat


def stuff(*args)
  args.inspect
end

stuff 1, 'neck', :blog # => [1, 'neck', :block]

Splats are basically like telling your method to take as many arguments as it wants and put them in an array called, in this case, args. You can name your splat anything you’d like. Splats can also appear along with other arguments in a method definition like this:


def say_jobs(person, *tasks)
  puts "#{person} will: #{tasks.join(', ')}."
end

say_jobs 'Carsten', 'clean floor', 'make dinner', 'bake a pie'
# => 'Carsten will clean floor, make dinner, bake a pie.'

You might also see a splat appear backwards in the form of a list assignment like this:


malted_battery_acids = ['Coke', 'Pepsi', 'RC Cola']
coke, pepsi, rc_cola = *malted_battery_acids

Array of Words


%w[cat dog bat hat]      # => ['cat', 'dog', 'bat', 'hat']
%w[carsten\ nielsen hat] # => ['carsten nielsen', 'hat']

This is a simple macro which creates an array of strings. It is whitespace sensitive, so it treats everything between spaces as a separate word. You can escape spaces to create words with spaces in them but just keep in mind that it can get confusing for others to read when you start doing stuff like that.

It should also be noted that I chose to use square brackets as start and end delimiters, but you can use curly braces, quotes, bars, most anything you’d like for all the percent-style literals.

Alternative String Literals


%{greetings good sir}  # <- Allows interpolation.
%q{greetings good sir} # <- No interpolation.
%Q{greetings good sir} # <- Allows interpolation.

You can think of these as the heredoc for minimalists. If you use a lowercase q it behaves like a single quoted string, otherwise you have full interpolation like a double quoted string.

Shelling Out


`which ruby`   # => '/opt/local/bin/ruby'
%x{which ruby} # => '/opt/local/bin/ruby'

Whatever you place between the back-ticks is sent to the shell, the results are returned as a string. There is an alternate style too that behaves the same.

The Blarg (Block Argument)


def quote(&block)
  "&ldquo;#{block.call}&rdquo;"
end

quote { 'Johnny Walker Black' }
# => '&ldquo;Johnny Walker Black&rdquo;'

Blargs are great when you have a method that requires a block. If you call the method without a block it will raise an error at runtime. In my example I reference the block by it’s blarg’s name but you can use yield too.

Living With Haml & Sass

Posted by Carsten Nielsen
on Wednesday, June 25

Haml is a pretty awesome templating language for marking up XML documents and hands-down brilliant for marking up XHTML, I think most people who “get it” use Haml whenever they can. We’ve been using it since day one at LearnHub, it makes my job a lot more enjoyable having yet another elegant tool at my disposal. And yes, it’s fast!

So pretty much everyone agrees Haml is fantastic, but what about Haml’s smokin’ hot sister; Sass? I have been using Sass exclusively on LearnHub since day one too, I find the benefits to be just as high as Haml if not higher, especially when it comes to nested selectors, less typing means less room for error and a document that is compact and easier to read.

There are not as many people out there using Sass though, and I think that is a shame. Sass lets you do some pretty nifty things that in turn give you great power. You can easily scope sets of rules to certain selectors and change them with ease, Sass removes all of the syntactic dirt and mostly all of the repetition from CSS. Consider the following example:


#content {
  margin: 0 8px; }
  #content .block {
    border: 1px solid #ddd; }
    #content .block p {
      font-size: 116%; }

Not bad, now let’s see it in Sass:


#content
  :margin 0 8px
  .block
    :border 1px solid #ddd
    p
      :font-size 116%

Sweet jeebas, why wouldn’t you want that?

Another one of my favorite things about Sass is the ability to declare constants, take the following for example, the ability to spec out all of your typefaces in one spot:


!display = "'lucida grande', 'trebuchet ms'"
!sans = "'helvetica neue', arial, 'dejavu sans'"
!serif = "georgia, times"
!monospace = "monaco, consolas, 'dejavu sans mono'"

And the power to do fun stuff such as:


!gunmetal = #ccc
!steel = !gunmetal + #111
!aluminum = !steel + #111

Now I personally don’t use evaluations in Sass very much, I find it easier to just declare everything explicitly, but I often use string concatenation in Sass everywhere:


.pillar
  .brick
    :border = "1px solid" !steel

In spite of Hampton raising an eyebrow, I break from convention and store my Sass documents in /app/sass which I then have compile out into /public/stylesheets/compiled this works better for me as it removes any confusion as to what stylesheets are Sass output and what are hand-coded CSS.

To do this, simply set the following Sass options during initialization:


Sass::Plugin.options[:template_location] = File.join(RAILS_ROOT, 'app/sass')
Sass::Plugin.options[:css_location] = File.join(RAILS_ROOT, 'public/stylesheets/compiled')

I tip my hat to Nathan and the other contributors of Haml; it keeps getting better and better in terms of speed and features. I remember pre version 1.8 speed was a bit of a concern, but after its release the cynics stopped knocking. With the recent release of version 2 we have seen a slew of improvements and enhancements (better error messages, auto-escaping) as well as yet another speed boost — LOVE IT!

Informative & Painless URIs

Posted by Carsten Nielsen
on Saturday, June 21

There is just something nice about those cute URIs that we have all grown to love, I’m sure you’ve seen them around: http://pork.ham/lists/32-grocery-list. Guess what, these are fun and easy to implement, here’s how!

First we need a method that can convert a normal title or name into something safe for use in a URI, here’s my answer:


class ::String

  # Returns a version of self that is safe for inclusion in a URI.
  def urilize
    strip.
    gsub(' ', '-').
    gsub(/[-]+/, '-').
    gsub('&', 'and').
    downcase.
    scan(/[a-z0-9\-]*/).to_s
  end

end

Users enter the darnedest data, so your urilize implementation will probably be tweaked over time. Anyways, the above String extension let’s us do stuff like:


'My Name Is Mud!'.urilize # => "my-name-is-mud"
'Awesome  &  Cool Stuff!!!'.urilize # => "awesome-and-cool-stuff"

Now we need a seamless way to get this functionality into our models so that they start throwing around all of these cool URIs for free. My answer to this is a sweet and simple mixin:


module Findable

  def to_param
    to_s.blank? ? id.to_s : "#{id}-#{to_s.urilize}"
  end

end

In order for our mixin to work we need our ActiveRecord models to have an overloaded to_s method that returns the title or name of the object. This is good practice and you should be doing it in any model where it makes sense to do so.

Anyways we can use our mixin as follows:


class Ticket < ActiveRecord::Base

  include Findable

  ...

  def to_s
    title
  end

  ...

end

Now imagine we have the following ticket in our database:


id: 6
created_by: Captain Obvious
assigned_to: Developer Dude
title: Feature Improvements
body: This massive feature that you implemented in far too little time is imperfect!

Assuming resourceful routes for Tickets we can do something like:


ticket = Ticket.find(6)
ticket_path(ticket) # => "/tickets/6-feature-improvements"

Neat.

Method Name Hack

Posted by Carsten Nielsen
on Friday, June 13

Ruby lets you do some pretty fun stuff, from highly elegant and useful to interesting and hacky. This is more of a hack than anything but it demonstrates some cool concepts.


module ::Kernel

  private
  # Allows you to get the name of the current method inside that method.
  # Example:
  #
  #   def hello
  #     __method_name__
  #   end
  #
  #   hello # => "hello"
  def __method_name__
    caller[0].scan(/`(.*)'/).to_s
  end

end

Ruby let’s you extend anything and everything, which is pretty powerful. The two preceding colons in ::Kernel tell Ruby to access the Kernel module in the global object space, if we were already there they would not be necessary but to be safe it’s best to add them.

Ruby maintains a call stack which is basically an array of strings that look like:


/Users/carsten/Projects/coolness/cool.rb:12:in `awesome_method'

This lets us know the path and file name as well as the line number and method name; neat. Then we just do a cute little regular expression scan and we can see the name of the method we are inside of.