Rails Illustrated

Rails, Web Design and the User Experience

Screencast: Hover Content in Rails and Prototype (Part 1)


Screencast: Hover Content in Rails and Prototype from Erik Andrejko on Vimeo.

It is often a good idea to show content when the user hovers the mouse above a link or an element in a page. This technique has been abused by some, but when used correctly it can enhance the user's experience. This is particularly the case when you have a lot of information that may be relevant to the user's interests but is too much to display all at once.

Screencast

Required

  • LowPro for unobtrusive javascript for Prototype

Optional

Basic Strategy

Hover Content Wrapper Div

We want to place the content that appears when the mouse is hovered as near as possible to the element that generates the hover (the affordance). We accomplish this by means of a wrapper div around each row of contacts.

1. Controller

In the controller the contacts are grouped into groups of 4 so that they can be wrapped in a div.

def index
  @contacts = Contact.find(:all, :order => 'last_name asc, first_name asc')
  @contact_groups = @contacts.in_groups_of(4,false)
end

def show
  @contact = Contact.find(params[:id])
end

2. View

The trick is to wrap each each row of contacts with the wrapper div. This accomplished by the contact_group partial.

<% content_for :scripts do %>
<%= javascript_include_tag 'hover_content' %>
<% end %>


<div id='contact-names'>
<%= render :partial => 'contact_group', :collection => @contact_groups %>
</div>

The contact_group partial wraps the row in a div.

<div class='contact-group'>
    <%= render :partial => 'contact_name', :collection => contact_group %>
</div>

3. Unobtrusive Javascript

The javascript is fairly straightforward. When the mouseover event is received, we load the content to display with an Ajax call.

Bubbling Event Problem

The div that we watch for mouseover events has child elements. When any of those elements received a mouseover event it will be sent to the parent elements. This means that the div will receive extraneous events. We must ignore these extra events to provide smooth visual effects.

The check for bubbling mouseover events from child elements with Protoype:

// from http://groups.google.com/group/prototype-scriptaculous/browse_thread/thread/badf3974a0dd5ac6
function bubbledFromChild(element, event)  {
  var target = $(event).element();
  if (target === element) target = event.relatedTarget;
  return (target && target.descendantOf(element));
}

This check is used on each function that handles either the mouseover or mouseout events. The rest of the Javascript is fairly routine:

Event.addBehavior({
  ".contact-name:mouseover" : function(e){
    if(!bubbledFromChild(this,e)){
      $(this).setStyle({backgroundColor:"#f0f0f0"});
      var id = $(this).readAttribute("id").match(/[0-9]+$/)[0];
      var container = $(this).up(".contact-group");
      $$(".contact").each( function(e) {
        e.hide();
      });
      if($(container).down("#contact-"+id)){
        new Effect.Appear("contact-"+id, {queue: 'end', duration: 0.7})
      }else{
        if(Ajax.activeRequestCount == 0){
          var url = $(this).down("a").readAttribute("href");
          new Ajax.Request(url,{
            method: 'get',
            onSuccess: function(xhr){
              container.insert({bottom: xhr.responseText});
            }});
        }
      }      
    }
  },

  ".contact-name:mouseout" : function(e){
    if(!bubbledFromChild(this,e)){
      $$(".contact").each( function(e) {
        e.hide();
      });      
    }
  }
})

Optional Enhancements

Over the next couple of weeks we shall continue this screencast by enhancing this hover technique to improve usability.

Credits

Intro music thanks to Courtney Williams via Podcast NYC.

Comments  

1

Very cool your UI rails screencasts. The video isn't easy to read from. Have you tried or are you encoding using Apple Animation?

Andrew Brown wrote on March 2 2009
2

Andrew- I think that the text is slightly garbled by the Vimeo compression. You might have better luck with the quicktime version.

erik wrote on March 4 2009
3

Great screencast! One thing I missed in vid is that You didn't showed how You tied rjs with view.

It's most simplest thing which we can find on basic rails guides but... lot of new comers would like to see that :)

Martin wrote on July 13 2009
4

For some reason, it is totally screwed up for me. Maybe the new version of rails screwed it up?

http://twitlens.com/o/12639037110_clicklesscontent.png

Senthil wrote on January 19 2010
5

I cant get this to work where-in the mouse over event doesnt fire at all.I saw Erik's comment on Mar 4,2009 that says it needs to tie the rjs with the view.I am new to rails.Can someone please tell me how to do this. Thanks in advance :-)

whiz wrote on January 20 2010
6

Overall a poor tutorial, though it does cover a few important points. It doesn't tie everything together into a working example, pieces are left out. Typical for the Rails community. I'm sure if you offer the guy some money he'll explain it for you.

Hydra wrote on March 28 2010

Add Comment

(required)
(required, won't be displayed)

(Use Markdown syntax)