pagy 3.11.0 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,13 +1,21 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/searchkick
2
- # encoding: utf-8
3
2
  # frozen_string_literal: true
4
3
 
5
- require 'pagy/extras/pagy_search'
6
-
7
4
  class Pagy
8
5
 
9
- # used by the items extra
10
- SEARCHKICK = true
6
+ VARS[:searchkick_search_method] ||= :pagy_search
7
+
8
+ module Searchkick
9
+ # returns an array used to delay the call of #search
10
+ # after the pagination variables are merged to the options
11
+ # it also pushes to the same array an eventually called method
12
+ def pagy_searchkick(term = '*', **options, &block)
13
+ [self, term, options, block].tap do |args|
14
+ args.define_singleton_method(:method_missing){|*a| args += a}
15
+ end
16
+ end
17
+ alias_method VARS[:searchkick_search_method], :pagy_searchkick
18
+ end
11
19
 
12
20
  # create a Pagy object from a Searchkick::Results object
13
21
  def self.new_from_searchkick(results, vars={})
@@ -18,22 +26,24 @@ class Pagy
18
26
  end
19
27
 
20
28
  # Add specialized backend methods to paginate Searchkick::Results
21
- module Backend ; private
29
+ module Backend
30
+ private
22
31
 
23
32
  # Return Pagy object and results
24
33
  def pagy_searchkick(pagy_search_args, vars={})
25
- model, search_args, block, *called = pagy_search_args
26
- vars = pagy_searchkick_get_vars(nil, vars)
27
- search_args[-1][:per_page] = vars[:items]
28
- search_args[-1][:page] = vars[:page]
29
- results = model.search(*search_args, &block)
30
- vars[:count] = results.total_count
34
+ model, term, options, block, *called = pagy_search_args
35
+ vars = pagy_searchkick_get_vars(nil, vars)
36
+ options[:per_page] = vars[:items]
37
+ options[:page] = vars[:page]
38
+ results = model.search(term, **options, &block)
39
+ vars[:count] = results.total_count
40
+
31
41
  pagy = Pagy.new(vars)
32
42
  # with :last_page overflow we need to re-run the method in order to get the hits
33
- if defined?(OVERFLOW) && pagy.overflow? && pagy.vars[:overflow] == :last_page
34
- return pagy_searchkick(pagy_search_args, vars.merge(page: pagy.page))
35
- end
36
- return pagy, called.empty? ? results : results.send(*called)
43
+ return pagy_searchkick(pagy_search_args, vars.merge(page: pagy.page)) \
44
+ if defined?(Pagy::UseOverflowExtra) && pagy.overflow? && pagy.vars[:overflow] == :last_page
45
+
46
+ [ pagy, called.empty? ? results : results.send(*called) ]
37
47
  end
38
48
 
39
49
  # Sub-method called only by #pagy_searchkick: here for easy customization of variables by overriding
@@ -1,5 +1,4 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/semantic
2
- # encoding: utf-8
3
2
  # frozen_string_literal: true
4
3
 
5
4
  require 'pagy/extras/shared'
@@ -9,47 +8,69 @@ class Pagy
9
8
 
10
9
  # Pagination for semantic: it returns the html with the series of links to the pages
11
10
  def pagy_semantic_nav(pagy)
12
- link, p_prev, p_next = pagy_link_proc(pagy, 'class="item"'), pagy.prev, pagy.next
11
+ link = pagy_link_proc(pagy, 'class="item"')
13
12
 
14
- html = EMPTY + (p_prev ? %(#{link.call p_prev, '<i class="left small chevron icon"></i>', 'aria-label="previous"'})
15
- : %(<div class="item disabled"><i class="left small chevron icon"></i></div>))
13
+ html = +%(<div class="pagy-semantic-nav ui pagination menu" aria-label="pager">)
14
+ html << pagy_semantic_prev_html(pagy, link)
16
15
  pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
17
- html << if item.is_a?(Integer); %(#{link.call item}) # page link
18
- elsif item.is_a?(String) ; %(<a class="item active">#{item}</a>) # current page
19
- elsif item == :gap ; %(<div class="disabled item">...</div>) # page gap
16
+ html << case item
17
+ when Integer then link.call item # page link
18
+ when String then %(<a class="item active">#{item}</a>) # current page
19
+ when :gap then %(<div class="disabled item">...</div>) # page gap
20
20
  end
21
21
  end
22
- html << (p_next ? %(#{link.call p_next, '<i class="right small chevron icon"></i>', 'aria-label="next"'})
23
- : %(<div class="item disabled"><i class="right small chevron icon"></i></div>))
24
- %(<div class="pagy-semantic-nav ui pagination menu" aria-label="pager">#{html}</div>)
22
+ html << pagy_semantic_next_html(pagy, link)
23
+ html << %(</div>)
25
24
  end
26
25
 
27
26
  # Javascript pagination for semantic: it returns a nav and a JSON tag used by the Pagy.nav javascript
28
27
  def pagy_semantic_nav_js(pagy, id=pagy_id)
29
- link, p_prev, p_next = pagy_link_proc(pagy, 'class="item"'), pagy.prev, pagy.next
30
- tags = { 'before' => (p_prev ? %(#{link.call(p_prev, '<i class="left small chevron icon"></i>', 'aria-label="previous"')})
31
- : %(<div class="item disabled"><i class="left small chevron icon"></i></div>)),
32
- 'link' => %(#{link.call(PAGE_PLACEHOLDER)}),
28
+ link = pagy_link_proc(pagy, 'class="item"')
29
+ tags = { 'before' => pagy_semantic_prev_html(pagy, link),
30
+ 'link' => link.call(PAGE_PLACEHOLDER),
33
31
  'active' => %(<a class="item active">#{pagy.page}</a>),
34
32
  'gap' => %(<div class="disabled item">#{pagy_t('pagy.nav.gap')}</div>),
35
- 'after' => (p_next ? %(#{link.call(p_next, '<i class="right small chevron icon"></i>', 'aria-label="next"')})
36
- : %(<div class="item disabled"><i class="right small chevron icon"></i></div>)) }
37
- %(<div id="#{id}" class="pagy-semantic-nav-js ui pagination menu" role="navigation" aria-label="pager"></div>#{pagy_json_tag(:nav, id, tags, pagy.sequels, defined?(TRIM) && pagy.vars[:page_param])})
33
+ 'after' => pagy_semantic_next_html(pagy, link) }
34
+
35
+ html = %(<div id="#{id}" class="pagy-semantic-nav-js ui pagination menu" role="navigation" aria-label="pager"></div>)
36
+ html << pagy_json_tag(pagy, :nav, id, tags, pagy.sequels)
38
37
  end
39
38
 
40
39
  # Combo pagination for semantic: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
41
40
  def pagy_semantic_combo_nav_js(pagy, id=pagy_id)
42
- link, p_prev, p_next, p_page, p_pages = pagy_link_proc(pagy, 'class="item"'), pagy.prev, pagy.next, pagy.page, pagy.pages
43
-
44
- html = EMPTY + %(<div id="#{id}" class="pagy-semantic-combo-nav-js ui compact menu" role="navigation" aria-label="pager">)
45
- html << (p_prev ? %(#{link.call p_prev, '<i class="left small chevron icon"></i>', 'aria-label="previous"'})
46
- : %(<div class="item disabled"><i class="left small chevron icon"></i></div>))
47
- input = %(<input type="number" min="1" max="#{p_pages}" value="#{p_page}" style="padding: 0; text-align: center; width: #{p_pages.to_s.length+1}rem; margin: 0 0.3rem">)
48
- html << %(<div class="pagy-combo-input item">#{pagy_t('pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages)}</div> )
49
- html << (p_next ? %(#{link.call p_next, '<i class="right small chevron icon"></i>', 'aria-label="next"'})
50
- : %(<div class="item disabled"><i class="right small chevron icon"></i></div>))
51
- html << %(</div>#{pagy_json_tag(:combo_nav, id, p_page, pagy_marked_link(link), defined?(TRIM) && pagy.vars[:page_param])})
41
+ link = pagy_link_proc(pagy, 'class="item"')
42
+ p_page = pagy.page
43
+ p_pages = pagy.pages
44
+ input = %(<input type="number" min="1" max="#{p_pages}" value="#{p_page}" style="padding: 0; text-align: center; width: #{p_pages.to_s.length+1}rem; margin: 0 0.3rem">)
45
+
46
+ %(<div id="#{id}" class="pagy-semantic-combo-nav-js ui compact menu" role="navigation" aria-label="pager">#{
47
+ pagy_semantic_prev_html pagy, link
48
+ }<div class="pagy-combo-input item">#{
49
+ pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages
50
+ }</div> #{
51
+ pagy_semantic_next_html pagy, link
52
+ }</div>#{
53
+ pagy_json_tag pagy, :combo_nav, id, p_page, pagy_marked_link(link)
54
+ })
52
55
  end
53
56
 
57
+ private
58
+
59
+ def pagy_semantic_prev_html(pagy, link)
60
+ if (p_prev = pagy.prev)
61
+ link.call p_prev, '<i class="left small chevron icon"></i>', 'aria-label="previous"'
62
+ else
63
+ +%(<div class="item disabled"><i class="left small chevron icon"></i></div>)
64
+ end
65
+ end
66
+
67
+ def pagy_semantic_next_html(pagy, link)
68
+ if (p_next = pagy.next)
69
+ link.call p_next, '<i class="right small chevron icon"></i>', 'aria-label="next"'
70
+ else
71
+ +%(<div class="item disabled"><i class="right small chevron icon"></i></div>)
72
+ end
73
+ end
74
+
54
75
  end
55
76
  end
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require 'digest'
@@ -19,21 +18,26 @@ class Pagy
19
18
  # Notice: if :steps is false it will use the single {0 => @vars[:size]} size
20
19
  def sequels
21
20
  steps = @vars[:steps] || {0 => @vars[:size]}
22
- steps.key?(0) or raise(VariableError.new(self), "expected :steps to define the 0 width; got #{steps.inspect}")
23
- sequels = {}; steps.each {|width, size| sequels[width.to_s] = series(size)}; sequels
21
+ raise VariableError.new(self), "expected :steps to define the 0 width; got #{steps.inspect}" \
22
+ unless steps.key?(0)
23
+ {}.tap do |sequels|
24
+ steps.each {|width, size| sequels[width.to_s] = series(size)}
25
+ end
24
26
  end
25
27
 
26
28
  module Frontend
27
29
 
28
30
  if defined?(Oj)
29
31
  # it returns a script tag with the JSON-serialized args generated with the faster oj gem
30
- def pagy_json_tag(*args)
32
+ def pagy_json_tag(pagy, *args)
33
+ args << pagy.vars[:page_param] if pagy.vars[:trim]
31
34
  %(<script type="application/json" class="pagy-json">#{Oj.dump(args, mode: :strict)}</script>)
32
35
  end
33
36
  else
34
37
  require 'json'
35
38
  # it returns a script tag with the JSON-serialized args generated with the slower to_json
36
- def pagy_json_tag(*args)
39
+ def pagy_json_tag(pagy, *args)
40
+ args << pagy.vars[:page_param] if pagy.vars[:trim]
37
41
  %(<script type="application/json" class="pagy-json">#{args.to_json}</script>)
38
42
  end
39
43
  end
@@ -45,7 +49,7 @@ class Pagy
45
49
 
46
50
  # it returns the marked link to used by pagy.js
47
51
  def pagy_marked_link(link)
48
- link.call(PAGE_PLACEHOLDER, '', 'style="display: none;"')
52
+ link.call PAGE_PLACEHOLDER, '', 'style="display: none;"'
49
53
  end
50
54
 
51
55
  end
@@ -1,5 +1,4 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/support
2
- # encoding: utf-8
3
2
  # frozen_string_literal: true
4
3
 
5
4
  class Pagy
@@ -15,13 +14,19 @@ class Pagy
15
14
  end
16
15
 
17
16
  def pagy_prev_link(pagy, text = pagy_t('pagy.nav.prev'), link_extra = '')
18
- pagy.prev ? %(<span class="page prev"><a href="#{pagy_url_for(pagy.prev, pagy)}" rel="prev" aria-label="previous" #{pagy.vars[:link_extra]} #{link_extra}>#{text}</a></span>)
19
- : %(<span class="page prev disabled">#{text}</span>)
17
+ if pagy.prev
18
+ %(<span class="page prev"><a href="#{pagy_url_for(pagy.prev, pagy)}" rel="prev" aria-label="previous" #{pagy.vars[:link_extra]} #{link_extra}>#{text}</a></span>)
19
+ else
20
+ %(<span class="page prev disabled">#{text}</span>)
21
+ end
20
22
  end
21
23
 
22
24
  def pagy_next_link(pagy, text = pagy_t('pagy.nav.next'), link_extra = '')
23
- pagy.next ? %(<span class="page next"><a href="#{pagy_url_for(pagy.next, pagy)}" rel="next" aria-label="next" #{pagy.vars[:link_extra]} #{link_extra}>#{text}</a></span>)
24
- : %(<span class="page next disabled">#{text}</span>)
25
+ if pagy.next
26
+ %(<span class="page next"><a href="#{pagy_url_for(pagy.next, pagy)}" rel="next" aria-label="next" #{pagy.vars[:link_extra]} #{link_extra}>#{text}</a></span>)
27
+ else
28
+ %(<span class="page next disabled">#{text}</span>)
29
+ end
25
30
  end
26
31
 
27
32
  def pagy_prev_link_tag(pagy)
@@ -1,23 +1,23 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/trim
2
- # encoding: utf-8
3
2
  # frozen_string_literal: true
4
3
 
5
4
  class Pagy
6
5
 
7
- module Frontend
6
+ VARS[:trim] = true
8
7
 
9
- TRIM = true # boolean used by *_js helpers
8
+ module UseTrimExtra
10
9
 
11
- alias_method :pagy_link_proc_without_trim, :pagy_link_proc
12
- def pagy_link_proc_with_trim(pagy, link_extra='')
13
- link_proc = pagy_link_proc_without_trim(pagy, link_extra)
14
- re = /[?&]#{pagy.vars[:page_param]}=1\b(?!&)|\b#{pagy.vars[:page_param]}=1&/
15
- lambda do |n, text=n, extra=''|
16
- link = link_proc.call(n, text, extra)
17
- n == 1 ? link.sub(re, '') : link
10
+ def pagy_link_proc(pagy, link_extra='')
11
+ link_proc = super(pagy, link_extra)
12
+ return link_proc unless pagy.vars[:trim]
13
+ lambda do |num, text=num, extra=''|
14
+ link = link_proc.call(num, text, extra)
15
+ return link unless num == 1
16
+ link.sub!(/[?&]#{pagy.vars[:page_param]}=1\b(?!&)|\b#{pagy.vars[:page_param]}=1&/, '')
18
17
  end
19
18
  end
20
- alias_method :pagy_link_proc, :pagy_link_proc_with_trim
21
19
 
22
20
  end
21
+ Frontend.prepend UseTrimExtra
22
+
23
23
  end
@@ -1,5 +1,4 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/uikit
2
- # encoding: utf-8
3
2
  # frozen_string_literal: true
4
3
 
5
4
  require 'pagy/extras/shared'
@@ -9,54 +8,80 @@ class Pagy
9
8
 
10
9
  # Pagination for uikit: it returns the html with the series of links to the pages
11
10
  def pagy_uikit_nav(pagy)
12
- link, p_prev, p_next = pagy_link_proc(pagy), pagy.prev, pagy.next
11
+ link = pagy_link_proc(pagy)
13
12
 
14
- previous_span = "<span uk-pagination-previous>#{pagy_t('pagy.nav.prev')}</span>"
15
- html = EMPTY + (p_prev ? %(<li>#{link.call p_prev, previous_span}</li>)
16
- : %(<li class="uk-disabled"><a href="#">#{previous_span}</a></li>))
13
+ html = %(<ul class="pagy-uikit-nav uk-pagination uk-flex-center">#{pagy_uikit_prev_html pagy, link})
17
14
  pagy.series.each do |item|
18
- html << if item.is_a?(Integer); %(<li>#{link.call item}</li>)
19
- elsif item.is_a?(String) ; %(<li class="uk-active"><span>#{item}</span></li>)
20
- elsif item == :gap ; %(<li class="uk-disabled"><span>#{pagy_t('pagy.nav.gap')}</span></li>)
15
+ html << case item
16
+ when Integer then %(<li>#{link.call item}</li>)
17
+ when String then %(<li class="uk-active"><span>#{item}</span></li>)
18
+ when :gap then %(<li class="uk-disabled"><span>#{pagy_t 'pagy.nav.gap'}</span></li>)
21
19
  end
22
20
  end
23
- next_span = "<span uk-pagination-next>#{pagy_t('pagy.nav.next')}</span>"
24
- html << (p_next ? %(<li>#{link.call p_next, next_span}</li>)
25
- : %(<li class="uk-disabled"><a href="#">#{next_span}</a></li>))
26
- %(<ul class="pagy-uikit-nav uk-pagination uk-flex-center">#{html}</ul>)
21
+ html << pagy_uikit_next_html(pagy, link)
22
+ html << %(</ul>)
27
23
  end
28
24
 
29
25
  # Javascript pagination for uikit: it returns a nav and a JSON tag used by the Pagy.nav javascript
30
26
  def pagy_uikit_nav_js(pagy, id=pagy_id)
31
- link, p_prev, p_next = pagy_link_proc(pagy), pagy.prev, pagy.next
32
- previous_span = "<span uk-pagination-previous>#{pagy_t('pagy.nav.prev')}</span>"
33
- next_span = "<span uk-pagination-next>#{pagy_t('pagy.nav.next')}</span>"
34
- tags = { 'before' => p_prev ? %(<li>#{link.call p_prev, previous_span}</li>)
35
- : %(<li class="uk-disabled"><a href="#">#{previous_span}</a></li>),
27
+ link = pagy_link_proc(pagy)
28
+ tags = { 'before' => pagy_uikit_prev_html(pagy, link),
36
29
  'link' => %(<li>#{link.call(PAGE_PLACEHOLDER)}</li>),
37
30
  'active' => %(<li class="uk-active"><span>#{PAGE_PLACEHOLDER}</span></li>),
38
31
  'gap' => %(<li class="uk-disabled"><span>#{pagy_t('pagy.nav.gap')}</span></li>),
39
- 'after' => p_next ? %(<li>#{link.call p_next, next_span}</li>)
40
- : %(<li class="uk-disabled"><a href="#">#{next_span}</a></li>) }
41
- %(<ul id="#{id}" class="pagy-uikit-nav-js uk-pagination uk-flex-center"></ul>#{pagy_json_tag(:nav, id, tags, pagy.sequels, defined?(TRIM) && pagy.vars[:page_param])})
32
+ 'after' => pagy_uikit_next_html(pagy, link) }
33
+
34
+ html = %(<ul id="#{id}" class="pagy-uikit-nav-js uk-pagination uk-flex-center"></ul>)
35
+ html << pagy_json_tag(pagy, :nav, id, tags, pagy.sequels)
42
36
  end
43
37
 
44
38
  # Javascript combo pagination for uikit: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
45
39
  def pagy_uikit_combo_nav_js(pagy, id=pagy_id)
46
- link, p_prev, p_next, p_page, p_pages = pagy_link_proc(pagy), pagy.prev, pagy.next, pagy.page, pagy.pages
40
+ link = pagy_link_proc(pagy)
41
+ p_page = pagy.page
42
+ p_pages = pagy.pages
43
+ input = %(<input type="number" min="1" max="#{p_pages}" value="#{p_page}" class="uk-input" style="padding: 0; text-align: center; width: #{p_pages.to_s.length+1}rem;">)
44
+
45
+ %(<div id="#{id}" class="pagy-uikit-combo-nav-js uk-button-group">#{
46
+ if (p_prev = pagy.prev)
47
+ link.call p_prev, pagy_t('pagy.nav.prev'), 'class="uk-button uk-button-default"'
48
+ else
49
+ %(<button class="uk-button uk-button-default" disabled>#{pagy_t 'pagy.nav.prev'}</button>)
50
+ end
51
+ }<div class="uk-text-middle uk-margin-left uk-margin-right">#{
52
+ pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages
53
+ }</div>#{
54
+ if (p_next = pagy.next)
55
+ link.call p_next, pagy_t('pagy.nav.next'), 'class="uk-button uk-button-default"'
56
+ else
57
+ %(<button class="uk-button uk-button-default" disabled>#{pagy_t 'pagy.nav.next'}</button>)
58
+ end
59
+ }</div>#{
60
+ pagy_json_tag pagy, :combo_nav, id, p_page, pagy_marked_link(link)
61
+ })
62
+ end
47
63
 
48
- html = %(<div id="#{id}" class="pagy-uikit-combo-nav-js uk-button-group">)
49
- html = html + (p_prev ? link.call(p_prev, pagy_t('pagy.nav.prev'), 'class="uk-button uk-button-default"')
50
- : %(<button class="uk-button uk-button-default" disabled>#{pagy_t('pagy.nav.prev')}</button>))
51
64
 
52
- html << %(<div class="uk-text-middle uk-margin-left uk-margin-right">)
53
- input = %(<input type="number" min="1" max="#{p_pages}" value="#{p_page}" class="uk-input" style="padding: 0; text-align: center; width: #{p_pages.to_s.length+1}rem;">)
54
- html << pagy_t('pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages) + '</div>'
55
65
 
56
- html << (p_next ? link.call(p_next, pagy_t('pagy.nav.next'), 'class="uk-button uk-button-default"')
57
- : %(<button class="uk-button uk-button-default" disabled>#{pagy_t('pagy.nav.next')}</button>))
66
+ private
67
+
68
+ def pagy_uikit_prev_html(pagy, link)
69
+ previous_span = %(<span uk-pagination-previous>#{pagy_t 'pagy.nav.prev'}</span>)
70
+ if (p_prev = pagy.prev)
71
+ %(<li>#{link.call p_prev, previous_span}</li>)
72
+ else
73
+ %(<li class="uk-disabled"><a href="#">#{previous_span}</a></li>)
74
+ end
75
+ end
76
+
77
+ def pagy_uikit_next_html(pagy, link)
78
+ next_span = %(<span uk-pagination-next>#{pagy_t 'pagy.nav.next'}</span>)
79
+ if (p_next = pagy.next)
80
+ %(<li>#{link.call p_next, next_span}</li>)
81
+ else
82
+ %(<li class="uk-disabled"><a href="#">#{next_span}</a></li>)
83
+ end
84
+ end
58
85
 
59
- html << %(</div>#{pagy_json_tag(:combo_nav, id, p_page, pagy_marked_link(link), defined?(TRIM) && pagy.vars[:page_param])})
60
- end
61
86
  end
62
87
  end
data/lib/pagy/frontend.rb CHANGED
@@ -1,26 +1,27 @@
1
1
  # See Pagy::Frontend API documentation: https://ddnexus.github.io/pagy/api/frontend
2
- # encoding: utf-8
3
2
  # frozen_string_literal: true
4
3
 
5
4
  require 'yaml'
6
5
 
7
6
  class Pagy
8
7
 
9
- PAGE_PLACEHOLDER = '__pagy_page__' # string used for search and replace, hardcoded also in the pagy.js file
8
+ PAGE_PLACEHOLDER = '__pagy_page__' # string used for search and replace, hardcoded also in the pagy.js file
10
9
 
11
10
  # I18n static hash loaded at startup, used as default alternative to the i18n gem.
12
11
  # see https://ddnexus.github.io/pagy/api/frontend#i18n
13
- I18n = eval(Pagy.root.join('locales', 'utils', 'i18n.rb').read) #rubocop:disable Security/Eval
12
+ I18n = eval Pagy.root.join('locales', 'utils', 'i18n.rb').read #rubocop:disable Security/Eval
14
13
 
15
14
  module Helpers
16
15
  # This works with all Rack-based frameworks (Sinatra, Padrino, Rails, ...)
17
- def pagy_url_for(page, pagy, url=false)
18
- p_vars = pagy.vars; params = request.GET.merge(p_vars[:params]); params[p_vars[:page_param].to_s] = page
16
+ def pagy_url_for(page, pagy, url=nil)
17
+ p_vars = pagy.vars
18
+ params = request.GET.merge(p_vars[:params])
19
+ params[p_vars[:page_param].to_s] = page
19
20
  "#{request.base_url if url}#{request.path}?#{Rack::Utils.build_nested_query(pagy_get_params(params))}#{p_vars[:anchor]}"
20
21
  end
21
22
 
22
23
  # Sub-method called only by #pagy_url_for: here for easy customization of params by overriding
23
- def pagy_get_params(params) params end
24
+ def pagy_get_params(params) = params
24
25
  end
25
26
 
26
27
  # All the code here has been optimized for performance: it may not look very pretty
@@ -29,47 +30,64 @@ class Pagy
29
30
 
30
31
  include Helpers
31
32
 
32
- EMPTY = '' # EMPTY + 'string' is almost as fast as +'string' but is also 1.9 compatible
33
- MARK = PAGE_PLACEHOLDER # backward compatibility in case of helper-overriding in legacy apps
34
-
35
33
  # Generic pagination: it returns the html with the series of links to the pages
36
34
  def pagy_nav(pagy)
37
- link, p_prev, p_next = pagy_link_proc(pagy), pagy.prev, pagy.next
35
+ link = pagy_link_proc(pagy)
36
+ p_prev = pagy.prev
37
+ p_next = pagy.next
38
38
 
39
- html = EMPTY + (p_prev ? %(<span class="page prev">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'}</span> )
40
- : %(<span class="page prev disabled">#{pagy_t('pagy.nav.prev')}</span> ))
39
+ html = +%(<nav class="pagy-nav pagination" role="navigation" aria-label="pager">)
40
+ html << if p_prev
41
+ %(<span class="page prev">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'}</span> )
42
+ else
43
+ %(<span class="page prev disabled">#{pagy_t('pagy.nav.prev')}</span> )
44
+ end
41
45
  pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
42
- html << if item.is_a?(Integer); %(<span class="page">#{link.call item}</span> ) # page link
43
- elsif item.is_a?(String) ; %(<span class="page active">#{item}</span> ) # current page
44
- elsif item == :gap ; %(<span class="page gap">#{pagy_t('pagy.nav.gap')}</span> ) # page gap
46
+ html << case item
47
+ when Integer then %(<span class="page">#{link.call item}</span> ) # page link
48
+ when String then %(<span class="page active">#{item}</span> ) # current page
49
+ when :gap then %(<span class="page gap">#{pagy_t('pagy.nav.gap')}</span> ) # page gap
45
50
  end
46
51
  end
47
- html << (p_next ? %(<span class="page next">#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'}</span>)
48
- : %(<span class="page next disabled">#{pagy_t('pagy.nav.next')}</span>))
49
- %(<nav class="pagy-nav pagination" role="navigation" aria-label="pager">#{html}</nav>)
52
+ html << if p_next
53
+ %(<span class="page next">#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'}</span>)
54
+ else
55
+ %(<span class="page next disabled">#{pagy_t('pagy.nav.next')}</span>)
56
+ end
57
+ html << %(</nav>)
50
58
  end
51
59
 
52
60
  # Return examples: "Displaying items 41-60 of 324 in total" of "Displaying Products 41-60 of 324 in total"
53
61
  def pagy_info(pagy, item_name=nil)
54
- path = if (count = pagy.count) == 0 ; 'pagy.info.no_items'
55
- else pagy.pages == 1 ? 'pagy.info.single_page' : 'pagy.info.multiple_pages'
56
- end
57
- pagy_t(path, item_name: item_name || pagy_t(pagy.vars[:i18n_key], count: count), count: count, from: pagy.from, to: pagy.to)
62
+ count = pagy.count
63
+ key = if count.zero? then 'pagy.info.no_items'
64
+ elsif pagy.pages == 1 then 'pagy.info.single_page'
65
+ else 'pagy.info.multiple_pages'
66
+ end
67
+ pagy_t key, item_name: item_name || pagy_t(pagy.vars[:i18n_key], count: count),
68
+ count: count, from: pagy.from, to: pagy.to
58
69
  end
59
70
 
60
71
  # Returns a performance optimized proc to generate the HTML links
61
72
  # Benchmarked on a 20 link nav: it is ~22x faster and uses ~18x less memory than rails' link_to
62
73
  def pagy_link_proc(pagy, link_extra='')
63
- p_prev, p_next = pagy.prev, pagy.next
64
- a, b = %(<a href="#{pagy_url_for(PAGE_PLACEHOLDER, pagy)}" #{pagy.vars[:link_extra]} #{link_extra}).split(PAGE_PLACEHOLDER, 2)
65
- lambda {|n, text=n, extra=''| "#{a}#{n}#{b}#{ if n == p_prev ; ' rel="prev"'
66
- elsif n == p_next ; ' rel="next"'
67
- else '' end } #{extra}>#{text}</a>"}
74
+ p_prev = pagy.prev
75
+ p_next = pagy.next
76
+ left, right = %(<a href="#{pagy_url_for PAGE_PLACEHOLDER, pagy}" #{pagy.vars[:link_extra]} #{link_extra}).split(PAGE_PLACEHOLDER, 2)
77
+ lambda do |num, text=num, extra=''|
78
+ %(#{left}#{num}#{right}#{ case num
79
+ when p_prev then ' rel="prev"'
80
+ when p_next then ' rel="next"'
81
+ else ''
82
+ end } #{extra}>#{text}</a>)
83
+ end
68
84
  end
69
85
 
70
86
  # Similar to I18n.t: just ~18x faster using ~10x less memory
71
- # (@pagy_locale explicitly initilized in order to avoid warning)
72
- def pagy_t(path, vars={}) Pagy::I18n.t(@pagy_locale||=nil, path, vars) end
87
+ # (@pagy_locale explicitly initialized in order to avoid warning)
88
+ def pagy_t(key, **opts)
89
+ Pagy::I18n.t @pagy_locale||=nil, key, **opts
90
+ end
73
91
 
74
92
  end
75
93
  end