2011-02-10 18:45:43 +00:00
|
|
|
require File.join(File.dirname(__FILE__), 'tags')
|
|
|
|
|
2011-02-05 14:05:40 +00:00
|
|
|
module Kaminari
|
|
|
|
module Helpers
|
2011-02-05 14:09:07 +00:00
|
|
|
class PaginationRenderer
|
2011-02-15 09:40:30 +00:00
|
|
|
attr_reader :options, :params, :left, :window, :right
|
2011-02-05 14:09:07 +00:00
|
|
|
|
2011-02-10 23:22:59 +00:00
|
|
|
def initialize(template, options) #:nodoc:
|
2011-02-05 14:20:06 +00:00
|
|
|
@template, @options = template, options
|
2011-02-13 09:25:07 +00:00
|
|
|
@params = options[:params] ? template.params.merge(options.delete :params) : template.params
|
2011-02-05 14:20:06 +00:00
|
|
|
@left, @window, @right = (options[:left] || options[:outer_window] || 1), (options[:window] || options[:inner_window] || 4), (options[:right] || options[:outer_window] || 1)
|
2011-02-05 14:09:07 +00:00
|
|
|
end
|
|
|
|
|
2011-02-15 09:40:30 +00:00
|
|
|
def current_page
|
2011-02-15 09:50:00 +00:00
|
|
|
@last = CurrentPage.new self, :page => @page
|
2011-02-15 08:29:18 +00:00
|
|
|
end
|
|
|
|
|
2011-02-15 09:40:30 +00:00
|
|
|
def page_link
|
|
|
|
case @page
|
2011-02-15 08:29:18 +00:00
|
|
|
when 1
|
|
|
|
FirstPageLink
|
|
|
|
when @options[:num_pages]
|
|
|
|
LastPageLink
|
|
|
|
else
|
|
|
|
PageLink
|
2011-02-15 09:40:30 +00:00
|
|
|
end.new self, :page => @page
|
2011-02-15 08:29:18 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
%w[prev_link prev_span next_link next_span truncated_span].each do |tag|
|
|
|
|
eval <<-DEF
|
|
|
|
def #{tag}
|
2011-02-15 09:50:00 +00:00
|
|
|
@last = #{tag.classify}.new self
|
2011-02-15 08:29:18 +00:00
|
|
|
end
|
|
|
|
DEF
|
|
|
|
end
|
|
|
|
|
2011-02-15 09:40:30 +00:00
|
|
|
def each_page
|
|
|
|
1.upto(@options[:num_pages]) do |i|
|
|
|
|
@page = i
|
2011-02-15 09:50:00 +00:00
|
|
|
yield PageProxy.new(self, i, @last)
|
2011-02-15 09:40:30 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-02-10 23:22:59 +00:00
|
|
|
def tagify_links #:nodoc:
|
2011-02-15 09:40:30 +00:00
|
|
|
num_pages, current_page = @options[:num_pages], @options[:current_page]
|
2011-02-08 16:40:09 +00:00
|
|
|
return [] if num_pages <= 1
|
2011-02-05 14:20:06 +00:00
|
|
|
|
|
|
|
tags = []
|
2011-02-15 08:29:18 +00:00
|
|
|
tags << (current_page > 1 ? prev_link : prev_span)
|
2011-02-15 09:40:30 +00:00
|
|
|
each_page do |page|
|
|
|
|
if page.current?
|
|
|
|
tags << current_page()
|
|
|
|
elsif page.left_outer? || page.right_outer? || page.inside_window?
|
|
|
|
tags << page_link
|
2011-02-05 14:20:06 +00:00
|
|
|
else
|
2011-02-15 09:50:00 +00:00
|
|
|
tags << truncated_span unless page.was_truncated?
|
2011-02-05 14:20:06 +00:00
|
|
|
end
|
|
|
|
end
|
2011-02-15 08:29:18 +00:00
|
|
|
tags << (num_pages > current_page ? next_link : next_span)
|
2011-02-05 14:09:07 +00:00
|
|
|
end
|
|
|
|
|
2011-02-11 06:30:26 +00:00
|
|
|
def partial_exists?(name) #:nodoc:
|
|
|
|
resolver = context.instance_variable_get('@view_paths').first
|
|
|
|
resolver.find_all(*args_for_lookup(name)).present?
|
2011-02-10 17:45:53 +00:00
|
|
|
end
|
|
|
|
|
2011-02-10 23:22:59 +00:00
|
|
|
def to_s #:nodoc:
|
2011-02-06 14:17:11 +00:00
|
|
|
suppress_logging_render_partial do
|
2011-02-07 01:53:48 +00:00
|
|
|
clear_content_for :kaminari_paginator_tags
|
2011-02-09 20:09:50 +00:00
|
|
|
@template.content_for :kaminari_paginator_tags, tagify_links.join.html_safe
|
2011-02-06 14:17:11 +00:00
|
|
|
Paginator.new(self).to_s
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-02-05 14:20:06 +00:00
|
|
|
private
|
2011-02-11 06:30:26 +00:00
|
|
|
def context
|
|
|
|
@template.instance_variable_get('@lookup_context')
|
|
|
|
end
|
|
|
|
|
|
|
|
def args_for_lookup(name)
|
|
|
|
if (method = context.method :args_for_lookup).arity == 3
|
|
|
|
# 3.0
|
|
|
|
method.call name, 'kaminari', true
|
|
|
|
else
|
|
|
|
# 3.1
|
|
|
|
method.call name, 'kaminari', true, []
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-02-05 14:09:07 +00:00
|
|
|
def method_missing(meth, *args, &blk)
|
|
|
|
@template.send meth, *args, &blk
|
|
|
|
end
|
2011-02-06 12:21:13 +00:00
|
|
|
|
2011-02-07 01:53:48 +00:00
|
|
|
# dirty hack
|
2011-02-06 12:21:13 +00:00
|
|
|
def suppress_logging_render_partial(&blk)
|
|
|
|
if subscriber = ActionView::LogSubscriber.log_subscribers.detect {|ls| ls.is_a? ActionView::LogSubscriber}
|
|
|
|
class << subscriber
|
|
|
|
alias_method :render_partial_with_logging, :render_partial
|
|
|
|
# do nothing
|
|
|
|
def render_partial(event)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
ret = blk.call
|
|
|
|
class << subscriber
|
|
|
|
alias_method :render_partial, :render_partial_with_logging
|
|
|
|
undef :render_partial_with_logging
|
|
|
|
end
|
|
|
|
ret
|
|
|
|
else
|
|
|
|
blk.call
|
|
|
|
end
|
|
|
|
end
|
2011-02-07 01:53:48 +00:00
|
|
|
|
|
|
|
# another dirty hack
|
|
|
|
def clear_content_for(name)
|
|
|
|
@template.instance_variable_get('@_content_for')[name] = ActiveSupport::SafeBuffer.new
|
|
|
|
end
|
2011-02-15 09:40:30 +00:00
|
|
|
|
|
|
|
class PageProxy
|
2011-02-15 09:50:00 +00:00
|
|
|
def initialize(renderer, page, last)
|
|
|
|
@renderer, @page, @last = renderer, page, last
|
2011-02-15 09:40:30 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def current?
|
|
|
|
@page == @renderer.options[:current_page]
|
|
|
|
end
|
|
|
|
|
|
|
|
def left_outer?
|
|
|
|
@page <= @renderer.left + 1
|
|
|
|
end
|
|
|
|
|
|
|
|
def right_outer?
|
|
|
|
@renderer.options[:num_pages] - @page <= @renderer.right
|
|
|
|
end
|
|
|
|
|
|
|
|
def inside_window?
|
|
|
|
(@page - @renderer.options[:current_page]).abs <= @renderer.window
|
|
|
|
end
|
2011-02-15 09:50:00 +00:00
|
|
|
|
|
|
|
def was_truncated?
|
|
|
|
@last.is_a? TruncatedSpan
|
|
|
|
end
|
2011-02-15 09:40:30 +00:00
|
|
|
end
|
2011-02-05 14:09:07 +00:00
|
|
|
end
|
|
|
|
|
2011-02-10 23:22:59 +00:00
|
|
|
# = Helpers
|
|
|
|
#
|
|
|
|
# A helper that renders the pagination links.
|
|
|
|
#
|
|
|
|
# <%= paginate @articles %>
|
|
|
|
#
|
|
|
|
# ==== Options
|
|
|
|
# * <tt>:window</tt> - The "inner window" size (2 by default).
|
|
|
|
# * <tt>:outer_window</tt> - The "outer window" size (1 by default).
|
|
|
|
# * <tt>:left</tt> - The "left outer window" size (1 by default).
|
|
|
|
# * <tt>:right</tt> - The "right outer window" size (1 by default).
|
2011-02-13 09:25:07 +00:00
|
|
|
# * <tt>:params</tt> - url_for parameters for the links (:controller, :action, etc.)
|
2011-02-10 23:22:59 +00:00
|
|
|
# * <tt>:remote</tt> - Ajax? (false by default)
|
|
|
|
# * <tt>:ANY_OTHER_VALUES</tt> - Any other hash key & values would be directly passed into each tag as :locals value.
|
2011-02-05 14:09:07 +00:00
|
|
|
def paginate(scope, options = {}, &block)
|
2011-02-08 16:29:58 +00:00
|
|
|
PaginationRenderer.new self, options.reverse_merge(:current_page => scope.current_page, :num_pages => scope.num_pages, :per_page => scope.limit_value, :remote => false)
|
2011-02-05 14:05:40 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|