Smileys with Ruby
I needed a simple, preferably accessible, way to add smilies support to one of my projects.

The first challenge was to find nice looking, but free to use, smilies. It was more difficult than you might think, because all the quality smilies I found did not accept commercial usage. Therefore, I ended up creating set of my own
My original idea was to use a little helper that would markup a given text with smilies a bit. For instance:
This is funny :) This is hilarious :D
The markup'ed version would be:
This is funny <span class="smiley smile">:)</span> This is hilarious <span class="smiley grin">:D</span>
Then, using one of those CSS image replacement techniques, I would display a graphical smiley and hide the text version.
The first problem I encountered was those techniques seem to work only on block level DOM elements. Smileys, however, should be part of the normal text flow. Another problem was that I could not make the text inside span dissappear and at the same time display a smiley graphics as background. Therefore, I needed another span. I also had to add some content inside the outer span so that Firefox would render it nicely and Internet Explorer would display it at all.
.smiley {
background-repeat:no-repeat;
padding-left: 16px; /* The width of the image */
}
.smiley.smile {
background-image:url(/images/smileys/smile_16.png);
}
.smiley.grin {
background-image:url(/images/smileys/grin_16.png);
}
.smiley .smiley-as-text {
position: fixed;
top: -500px;
}
Why did not I just hide the smiley-as-text span? The answer: some screen readers would skip the smiley. To be honest, I don't know how screen readers handle smileys, but by not hiding the span, smilies will at least be read.
Here's the Ruby code I would use in one of my Rails helpers.
SMILEYS = {
':)' => 'smile',
':-)' => 'smile',
'=]' => 'smile',
'=)' => 'smile',
';)' => 'wink',
';]' => 'wink',
';-)' => 'wink'
} # and the rest of the smilies...
def smiley(text)
SMILEYS.each do |smiley, smiley_class|
text.gsub!(smiley, "<span class='smiley #{smiley_class}'><span class='smiley-as-text'>#{smiley}</span> </span>")
end
return text
end
What if I have varying font sizes and we want to use smilies that scales with the text size. Well, my solution is to create smileys for the each font size. E.g. wink_16.png would work well with 16px fonts. We do not need not to touch the Ruby helper at all. Instead, we handle smiley sizes using CSS and simply wrap the the text with a new class, for instance <div class='big-text'>This blog entry is about to end :(</div>.
.big-text {
font-size: 24px;
}
.big-text .smiley {
padding-left: 24px;
}
.big-text .smiley.sad {
background-image:url(/images/smileys/sad_24.png);
}