home icon contact icon rss icon last FM icon facebook icon LinkedIn icon Delicious icon twitter icon

Custom facebook ajax will_paginate renderer

will_paginate is one of the most used rails plugin. It take care of pagination of a large collectoon of item, automatically limiting records to display. It also display a pagination bar, with next, previous and numbered pages.

The fact is that by default, links are just normal link to relative path. It what you want most of the time. Some times you want some AJAX. There is many different way to do it. But some times, you want some AJAX in a Facebook Application...

Here is how I do it.

# In RAILS_ROOT/app/helpers/remote_link_renderer.rb
class RemoteLinkRenderer < WillPaginate::LinkRenderer
  def prepare(collection, options, template)
    @remote = options.delete(:remote) || {}
    super
    @options[:params].is_a?(Hash) ? @options[:params].merge({:only_path => false, :canvas => false}) : @options[:params] = {:only_path => false, :canvas => false}
  end

protected
  def page_link(page, text, attributes = {})
    @template.link_to(text, "#", :onclick => "#{@remote[:method_name]}({url: '#{url_for(page)}', container: '#{@remote[:container]}', parameters: { type: '#{@remote[:type]}' }}); return false;")
  end
end

will_paginate allow us to use different renderer in order to customize our pagination. I've build one here. The prepare method is called by will_paginate to let us initialize our renderer before rendering anything. The main thing is to prepare url_for to return absolute, non canvas url because the Facebook FBJS AJAX proxy doesn't allow anything else.

In the page_link method, we generate links displayed by will_paginate. We can't set the href attribute to the url because again, the Facebook FBJS AJAX proxy doesn't allow anything but # here. And since in Profile Boxes and Tabs, we can't use onLoad event, we use onClick in order to call our AJAX builder. Parameters of that function are specific to my need, but it's just to show you that we can pass in variables and build a custom link.

Here is a sample code showing the way to specify our renderer to will_paginate.

# Somewhere in the view
<%= will_paginate users, :renderer => 'RemoteLinkRenderer' , :remote => {:method_name => 'ajaxizer', :container => container, :type => type}, :previous_label => "precedent", :next_label => "suivant" %>