Quantcast
Channel: Whomwah.com » howto
Viewing all articles
Browse latest Browse all 9

Another tag cloud script for Ruby on Rails

$
0
0

Or any other Ruby program really. I know there are attempts already out there but none that really suited my purposes. I needed a simple way of creating that tag-cloud-look for many situations. I needed a tag cloud by size or by colour and I didn’t want it to do everything, just provide me with the style attributes I needed to get the job done. Below is an example of what gets returned by default:

font-size:16px;color:rgb(70,70,70);

Here’s the code; it comes with no warranty.

With all these tags cloud scripts you really only need 3 parameters:

  1. The total counts of items – For example you have 10 tags each that has been used numerous times. The total counts would be all of the uses added together
  2. The minimum count of items in a batch – Using the example above this would be a count of the uses for the tag that has been used least
  3. The maximum count of items in a batch – Using the example above this would be a count of the uses for the tag that has been used most

Below is the actual script and then below that I have stuck a quick example of how you could use it.

def font_size_for_tag_cloud( total, lowest, highest, options={} )
  return nil if total.nil? or highest.nil? or lowest.nil?
  #
  # options
  maxf = options.delete( :max_font_size ) || 14
  minf = options.delete( :min_font_size ) || 11
  maxc = options.delete( :max_color ) || [ 0, 0, 0 ]
  minc = options.delete( :min_color ) || [ 156, 156, 156 ]
  hide_sizes = options.delete( :hide_sizes )
  hide_colours = options.delete( :hide_colours )
  #
  # function to work out rgb values
  def rgb_color( a, b, i, x)
    return nil if i <= 1 or x <= 1
    if a & b
      a-(Math.log(i)*(a-b)/Math.log(x)).floor
    else
      (Math.log(i)*(b-a)/Math.log(x)+a).floor
    end
  end
  #
  # work out colours
  c = []
  (0..2).each { |i| c && rgb_color( minc[i], maxc[i], total, highest ) || nil }
  colors = c.compact.empty? ? minc.join(',') : c.join(',')
  #
  # work out the font size
  spread = highest.to_f - lowest.to_f
  spread = 1.to_f if spread <= 0
  fontspread = maxf.to_f - minf.to_f
  fontstep = spread / fontspread
  size = ( minf + ( total.to_f / fontstep ) ).to_i
  size = maxf if size > maxf
  #
  # display the results
  size_txt = "font-size:#{ size.to_s }px;" unless hide_sizes
  color_txt = "color:rgb(#{ colors });" unless hide_colours
  return [ size_txt, color_txt ].join
end

and now a quick example of it’s use in a rails view. This code assumes the db find call looks something like this:

@foo = Foo.find( :all,
  :select => '*, COUNT(DISTINCT(i.id)) AS item_cnt',
  :joins => 'AS f INNER JOIN bars AS b ON f.id=b.foo_id',
  :group => 'b.id',
  :order => 'item_cnt DESC',
  :limit => 50
)

Below just loop through your db results and calls font_size_for_tag_cloud for each item, passing in the required parameters. There are a few options available but if you leave them out you should still see something useful.

<ul>
<% for f in @foo -%>
<%= content_tag( 'li', f.some_label, :style => font_size_for_tag_cloud( f.bars.size, 
  f.first.count_items, 
  f.last.count_items,  
) ) %>
<% end -%>
</ul>

That’s it! I guess I should turn it into a plugin but hey, there’s to much reading to be done on ActiveResource at the moment heyhey!


Viewing all articles
Browse latest Browse all 9

Trending Articles