pagy 3.10.0 → 5.7.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/lib/config/pagy.rb +121 -52
  4. data/lib/javascripts/pagy-dev.js +117 -0
  5. data/lib/javascripts/pagy.js +1 -106
  6. data/lib/javascripts/pagy.mjs +118 -0
  7. data/lib/locales/ar.yml +26 -0
  8. data/lib/locales/bg.yml +2 -2
  9. data/lib/locales/bs.yml +24 -0
  10. data/lib/locales/ca.yml +2 -2
  11. data/lib/locales/cs.yml +2 -2
  12. data/lib/locales/da.yml +2 -2
  13. data/lib/locales/de.yml +2 -2
  14. data/lib/locales/en.yml +2 -2
  15. data/lib/locales/es.yml +2 -2
  16. data/lib/locales/fr.yml +2 -2
  17. data/lib/locales/hr.yml +24 -0
  18. data/lib/locales/id.yml +2 -2
  19. data/lib/locales/it.yml +2 -2
  20. data/lib/locales/ja.yml +2 -2
  21. data/lib/locales/km.yml +2 -2
  22. data/lib/locales/ko.yml +2 -2
  23. data/lib/locales/nb.yml +2 -2
  24. data/lib/locales/nl.yml +2 -2
  25. data/lib/locales/pl.yml +2 -2
  26. data/lib/locales/pt-BR.yml +2 -2
  27. data/lib/locales/pt.yml +2 -2
  28. data/lib/locales/ru.yml +2 -2
  29. data/lib/locales/sr.yml +23 -0
  30. data/lib/locales/sv-SE.yml +2 -2
  31. data/lib/locales/sv.yml +2 -2
  32. data/lib/locales/sw.yml +22 -0
  33. data/lib/locales/ta.yml +22 -0
  34. data/lib/locales/tr.yml +2 -2
  35. data/lib/locales/uk.yml +24 -0
  36. data/lib/locales/zh-CN.yml +2 -2
  37. data/lib/locales/zh-HK.yml +2 -2
  38. data/lib/locales/zh-TW.yml +3 -3
  39. data/lib/pagy/backend.rb +11 -12
  40. data/lib/pagy/calendar/day.rb +29 -0
  41. data/lib/pagy/calendar/month.rb +16 -0
  42. data/lib/pagy/calendar/month_mixin.rb +49 -0
  43. data/lib/pagy/calendar/quarter.rb +23 -0
  44. data/lib/pagy/calendar/week.rb +39 -0
  45. data/lib/pagy/calendar/year.rb +29 -0
  46. data/lib/pagy/calendar.rb +90 -0
  47. data/lib/pagy/console.rb +23 -0
  48. data/lib/pagy/countless.rb +23 -19
  49. data/lib/pagy/exceptions.rb +16 -13
  50. data/lib/pagy/extras/arel.rb +12 -7
  51. data/lib/pagy/extras/array.rb +10 -9
  52. data/lib/pagy/extras/bootstrap.rb +77 -39
  53. data/lib/pagy/extras/bulma.rb +77 -43
  54. data/lib/pagy/extras/calendar.rb +66 -0
  55. data/lib/pagy/extras/countless.rb +17 -17
  56. data/lib/pagy/extras/elasticsearch_rails.rb +66 -37
  57. data/lib/pagy/extras/foundation.rb +74 -41
  58. data/lib/pagy/extras/frontend_helpers.rb +70 -0
  59. data/lib/pagy/extras/gearbox.rb +42 -0
  60. data/lib/pagy/extras/headers.rb +32 -18
  61. data/lib/pagy/extras/i18n.rb +18 -17
  62. data/lib/pagy/extras/items.rb +42 -53
  63. data/lib/pagy/extras/materialize.rb +68 -43
  64. data/lib/pagy/extras/meilisearch.rb +61 -0
  65. data/lib/pagy/extras/metadata.rb +27 -26
  66. data/lib/pagy/extras/navs.rb +54 -29
  67. data/lib/pagy/extras/overflow.rb +57 -52
  68. data/lib/pagy/extras/searchkick.rb +54 -36
  69. data/lib/pagy/extras/semantic.rb +66 -39
  70. data/lib/pagy/extras/standalone.rb +64 -0
  71. data/lib/pagy/extras/support.rb +34 -17
  72. data/lib/pagy/extras/trim.rb +18 -12
  73. data/lib/pagy/extras/uikit.rb +66 -44
  74. data/lib/pagy/frontend.rb +61 -53
  75. data/lib/pagy/i18n.rb +164 -0
  76. data/lib/pagy/url_helpers.rb +38 -0
  77. data/lib/pagy.rb +96 -30
  78. data/lib/templates/bootstrap_nav.html.erb +1 -1
  79. data/lib/templates/bootstrap_nav.html.haml +1 -1
  80. data/lib/templates/bootstrap_nav.html.slim +1 -1
  81. data/lib/templates/foundation_nav.html.erb +1 -1
  82. data/lib/templates/foundation_nav.html.haml +1 -1
  83. data/lib/templates/foundation_nav.html.slim +1 -1
  84. data/lib/templates/uikit_nav.html.erb +2 -2
  85. data/lib/templates/uikit_nav.html.haml +1 -1
  86. data/lib/templates/uikit_nav.html.slim +2 -2
  87. metadata +37 -16
  88. data/lib/locales/README.md +0 -35
  89. data/lib/locales/utils/i18n.rb +0 -25
  90. data/lib/locales/utils/loader.rb +0 -34
  91. data/lib/locales/utils/p11n.rb +0 -88
  92. data/lib/pagy/extras/pagy_search.rb +0 -18
  93. data/lib/pagy/extras/shared.rb +0 -53
  94. data/pagy.gemspec +0 -16
@@ -1,48 +1,66 @@
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'
4
+ class Pagy # :nodoc:
5
+ DEFAULT[:searchkick_search_method] ||= :pagy_search
6
6
 
7
- class Pagy
7
+ # Paginate Searchkick::Results objects
8
+ module SearchkickExtra
9
+ module Searchkick # :nodoc:
10
+ # Return an array used to delay the call of #search
11
+ # after the pagination variables are merged to the options.
12
+ # It also pushes to the same array an optional method call.
13
+ def pagy_searchkick(term = '*', **options, &block)
14
+ [self, term, options, block].tap do |args|
15
+ args.define_singleton_method(:method_missing) { |*a| args += a }
16
+ end
17
+ end
18
+ alias_method Pagy::DEFAULT[:searchkick_search_method], :pagy_searchkick
19
+ end
8
20
 
9
- # used by the items extra
10
- SEARCHKICK = true
21
+ # Additions for the Pagy class
22
+ module Pagy
23
+ # Create a Pagy object from a Searchkick::Results object
24
+ def new_from_searchkick(results, vars = {})
25
+ vars[:items] = results.options[:per_page]
26
+ vars[:page] = results.options[:page]
27
+ vars[:count] = results.total_count
28
+ new(vars)
29
+ end
30
+ end
11
31
 
12
- # create a Pagy object from a Searchkick::Results object
13
- def self.new_from_searchkick(results, vars={})
14
- vars[:items] = results.options[:per_page]
15
- vars[:page] = results.options[:page]
16
- vars[:count] = results.total_count
17
- new(vars)
18
- end
32
+ # Add specialized backend methods to paginate Searchkick::Results
33
+ module Backend
34
+ private
19
35
 
20
- # Add specialized backend methods to paginate Searchkick::Results
21
- module Backend ; private
22
-
23
- # Return Pagy object and results
24
- 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
31
- pagy = Pagy.new(vars)
32
- # 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))
36
+ # Return Pagy object and results
37
+ def pagy_searchkick(pagy_search_args, vars = {})
38
+ model, term, options, block, *called = pagy_search_args
39
+ vars = pagy_searchkick_get_vars(nil, vars)
40
+ options[:per_page] = vars[:items]
41
+ options[:page] = vars[:page]
42
+ results = model.search(term, **options, &block)
43
+ vars[:count] = results.total_count
44
+
45
+ pagy = ::Pagy.new(vars)
46
+ # with :last_page overflow we need to re-run the method in order to get the hits
47
+ return pagy_searchkick(pagy_search_args, vars.merge(page: pagy.page)) \
48
+ if defined?(::Pagy::OverflowExtra) && pagy.overflow? && pagy.vars[:overflow] == :last_page
49
+
50
+ [pagy, called.empty? ? results : results.send(*called)]
35
51
  end
36
- return pagy, called.empty? ? results : results.send(*called)
37
- end
38
52
 
39
- # Sub-method called only by #pagy_searchkick: here for easy customization of variables by overriding
40
- # the _collection argument is not available when the method is called
41
- def pagy_searchkick_get_vars(_collection, vars)
42
- vars[:items] ||= VARS[:items]
43
- vars[:page] ||= (params[ vars[:page_param] || VARS[:page_param] ] || 1).to_i
44
- vars
53
+ # Sub-method called only by #pagy_searchkick: here for easy customization of variables by overriding
54
+ # the _collection argument is not available when the method is called
55
+ def pagy_searchkick_get_vars(_collection, vars)
56
+ pagy_set_items_from_params(vars) if defined?(ItemsExtra)
57
+ vars[:items] ||= DEFAULT[:items]
58
+ vars[:page] ||= (params[vars[:page_param] || DEFAULT[:page_param]] || 1).to_i
59
+ vars
60
+ end
45
61
  end
46
-
47
62
  end
63
+ Searchkick = SearchkickExtra::Searchkick
64
+ extend SearchkickExtra::Pagy
65
+ Backend.prepend SearchkickExtra::Backend
48
66
  end
@@ -1,55 +1,82 @@
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
- require 'pagy/extras/shared'
6
-
7
- class Pagy
8
- module Frontend
4
+ require 'pagy/extras/frontend_helpers'
9
5
 
6
+ class Pagy # :nodoc:
7
+ # Frontend modules are specially optimized for performance.
8
+ # The resulting code may not look very elegant, but produces the best benchmarks
9
+ module SemanticExtra
10
10
  # Pagination for semantic: it returns the html with the series of links to the pages
11
- def pagy_semantic_nav(pagy)
12
- link, p_prev, p_next = pagy_link_proc(pagy, 'class="item"'), pagy.prev, pagy.next
13
-
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>))
16
- 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
11
+ def pagy_semantic_nav(pagy, pagy_id: nil, link_extra: '', **vars)
12
+ p_id = %( id="#{pagy_id}") if pagy_id
13
+ link = pagy_link_proc(pagy, link_extra: %(class="item" #{link_extra}))
14
+
15
+ html = +%(<div#{p_id} class="pagy-semantic-nav ui pagination menu">)
16
+ html << pagy_semantic_prev_html(pagy, link)
17
+ pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
18
+ html << case item
19
+ when Integer then link.call item
20
+ when String then %(<a class="item active">#{pagy.label_for(item)}</a>)
21
+ when :gap then %(<div class="disabled item">#{pagy_t 'pagy.nav.gap'}</div>)
22
+ else raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
20
23
  end
21
24
  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>)
25
+ html << pagy_semantic_next_html(pagy, link)
26
+ html << %(</div>)
25
27
  end
26
28
 
27
- # Javascript pagination for semantic: it returns a nav and a JSON tag used by the Pagy.nav javascript
28
- 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)}),
33
- 'active' => %(<a class="item active">#{pagy.page}</a>),
29
+ # Javascript pagination for semantic: it returns a nav and a JSON tag used by the pagy.js file
30
+ def pagy_semantic_nav_js(pagy, pagy_id: nil, link_extra: '', **vars)
31
+ sequels = pagy.sequels(**vars)
32
+ p_id = %( id="#{pagy_id}") if pagy_id
33
+ link = pagy_link_proc(pagy, link_extra: %(class="item" #{link_extra}))
34
+ tags = { 'before' => pagy_semantic_prev_html(pagy, link),
35
+ 'link' => link.call(PAGE_PLACEHOLDER, LABEL_PLACEHOLDER),
36
+ 'active' => %(<a class="item active">#{LABEL_PLACEHOLDER}</a>),
34
37
  '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])})
38
+ 'after' => pagy_semantic_next_html(pagy, link) }
39
+
40
+ %(<div#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-semantic-nav-js ui pagination menu" role="navigation" #{
41
+ pagy_json_attr(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></div>)
42
+ end
43
+
44
+ # Combo pagination for semantic: it returns a nav and a JSON tag used by the pagy.js file
45
+ def pagy_semantic_combo_nav_js(pagy, pagy_id: nil, link_extra: '')
46
+ p_id = %( id="#{pagy_id}") if pagy_id
47
+ link = pagy_link_proc(pagy, link_extra: %(class="item" #{link_extra}))
48
+ p_page = pagy.page
49
+ p_pages = pagy.pages
50
+ input = %(<input type="number" min="1" max="#{p_pages}" value="#{
51
+ p_page}" style="padding: 0; text-align: center; width: #{p_pages.to_s.length + 1}rem; margin: 0 0.3rem">)
52
+
53
+ %(<div#{p_id} class="pagy-semantic-combo-nav-js ui compact menu" role="navigation" #{
54
+ pagy_json_attr pagy, :combo, pagy_marked_link(link)}>#{
55
+ pagy_semantic_prev_html pagy, link
56
+ }<div class="pagy-combo-input item">#{
57
+ pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages
58
+ }</div> #{
59
+ pagy_semantic_next_html pagy, link
60
+ }</div>)
38
61
  end
39
62
 
40
- # Combo pagination for semantic: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
41
- 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])})
63
+ private
64
+
65
+ def pagy_semantic_prev_html(pagy, link)
66
+ if (p_prev = pagy.prev)
67
+ link.call p_prev, '<i class="left small chevron icon"></i>', 'aria-label="previous"'
68
+ else
69
+ +%(<div class="item disabled"><i class="left small chevron icon"></i></div>)
70
+ end
52
71
  end
53
72
 
73
+ def pagy_semantic_next_html(pagy, link)
74
+ if (p_next = pagy.next)
75
+ link.call p_next, '<i class="right small chevron icon"></i>', 'aria-label="next"'
76
+ else
77
+ +%(<div class="item disabled"><i class="right small chevron icon"></i></div>)
78
+ end
79
+ end
54
80
  end
81
+ Frontend.prepend SemanticExtra
55
82
  end
@@ -0,0 +1,64 @@
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/standalone
2
+ # frozen_string_literal: true
3
+
4
+ require 'uri'
5
+
6
+ class Pagy # :nodoc:
7
+ # Use pagy without any request object, nor Rack environment/gem, nor any defined params method,
8
+ # even in the irb/rails console without any app or config.
9
+ module StandaloneExtra
10
+ # Extracted from Rack::Utils and reformatted for rubocop
11
+ module QueryUtils
12
+ module_function
13
+
14
+ def escape(str)
15
+ URI.encode_www_form_component(str)
16
+ end
17
+
18
+ def build_nested_query(value, prefix = nil)
19
+ case value
20
+ when Array
21
+ value.map { |v| build_nested_query(v, "#{prefix}[]") }.join('&')
22
+ when Hash
23
+ value.map do |k, v|
24
+ build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
25
+ end.delete_if(&:empty?).join('&')
26
+ when nil
27
+ prefix
28
+ else
29
+ raise ArgumentError, 'value must be a Hash' if prefix.nil?
30
+
31
+ "#{prefix}=#{escape(value)}"
32
+ end
33
+ end
34
+ end
35
+
36
+ # Return the URL for the page. If there is no pagy.vars[:url]
37
+ # it works exactly as the regular #pagy_url_for, relying on the params method and Rack.
38
+ # If there is a defined pagy.vars[:url] variable it does not need the params method nor Rack.
39
+ def pagy_url_for(pagy, page, absolute: nil)
40
+ return super unless pagy.vars[:url]
41
+
42
+ vars = pagy.vars
43
+ page_param = vars[:page_param].to_s
44
+ items_param = vars[:items_param].to_s
45
+ params = pagy.params.is_a?(Hash) ? pagy.params.clone : {} # safe when it gets reused
46
+ params[page_param] = page
47
+ params[items_param] = vars[:items] if vars[:items_extra]
48
+ query_string = "?#{QueryUtils.build_nested_query(pagy_deprecated_params(pagy, params))}" # remove in 6.0
49
+ # params = pagy.params.call(params) if pagy.params.is_a?(Proc) # add in 6.0
50
+ # query_string = "?#{Rack::Utils.build_nested_query(params)}" # add in 6.0
51
+ "#{vars[:url]}#{query_string}#{vars[:fragment]}"
52
+ end
53
+ end
54
+ # In ruby 3+ `UrlHelpers.prepend StandaloneExtra` would be enough instead of using the next 2 lines
55
+ Frontend.prepend StandaloneExtra
56
+ Backend.prepend StandaloneExtra
57
+
58
+ # Define a dummy params method if it's not already defined in the including module
59
+ module Backend
60
+ def self.included(controller)
61
+ controller.define_method(:params) { {} } unless controller.method_defined?(:params)
62
+ end
63
+ end
64
+ end
@@ -1,37 +1,54 @@
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
- class Pagy
6
-
7
- module Frontend
8
-
4
+ class Pagy # :nodoc:
5
+ # Extra support for features like: incremental, auto-incremental and infinite pagination
6
+ module SupportExtra
7
+ # Return the previous page URL string or nil
9
8
  def pagy_prev_url(pagy)
10
- pagy_url_for(pagy.prev, pagy) if pagy.prev
9
+ pagy_url_for(pagy, pagy.prev) if pagy.prev
11
10
  end
12
11
 
12
+ # Return the next page URL string or nil
13
13
  def pagy_next_url(pagy)
14
- pagy_url_for(pagy.next, pagy) if pagy.next
14
+ pagy_url_for(pagy, pagy.next) if pagy.next
15
15
  end
16
16
 
17
- 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
+ # Return the HTML string for the previous page link
18
+ def pagy_prev_link(pagy, text: pagy_t('pagy.nav.prev'), link_extra: '')
19
+ if pagy.prev
20
+ %(<span class="page prev"><a href="#{
21
+ pagy_url_for(pagy, pagy.prev)
22
+ }" rel="prev" aria-label="previous" #{
23
+ pagy.vars[:link_extra]
24
+ } #{link_extra}>#{text}</a></span>)
25
+ else
26
+ %(<span class="page prev disabled">#{text}</span>)
27
+ end
20
28
  end
21
29
 
22
- 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>)
30
+ # Return the HTML string for the next page link
31
+ def pagy_next_link(pagy, text: pagy_t('pagy.nav.next'), link_extra: '')
32
+ if pagy.next
33
+ %(<span class="page next"><a href="#{
34
+ pagy_url_for(pagy, pagy.next)
35
+ }" rel="next" aria-label="next" #{
36
+ pagy.vars[:link_extra]
37
+ } #{link_extra}>#{text}</a></span>)
38
+ else
39
+ %(<span class="page next disabled">#{text}</span>)
40
+ end
25
41
  end
26
42
 
43
+ # Return the HTML link tag for the previous page or nil
27
44
  def pagy_prev_link_tag(pagy)
28
- %(<link href="#{pagy_url_for(pagy.prev, pagy)}" rel="prev"/>) if pagy.prev
45
+ %(<link href="#{pagy_url_for(pagy, pagy.prev)}" rel="prev"/>) if pagy.prev
29
46
  end
30
47
 
48
+ # Return the HTML link tag for the next page or nil
31
49
  def pagy_next_link_tag(pagy)
32
- %(<link href="#{pagy_url_for(pagy.next, pagy)}" rel="next"/>) if pagy.next
50
+ %(<link href="#{pagy_url_for(pagy, pagy.next)}" rel="next"/>) if pagy.next
33
51
  end
34
-
35
52
  end
36
-
53
+ Frontend.prepend SupportExtra
37
54
  end
@@ -1,23 +1,29 @@
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
- class Pagy
4
+ class Pagy # :nodoc:
5
+ DEFAULT[:trim_extra] = true # extra enabled by default
6
6
 
7
- module Frontend
7
+ # Remove the page=1 param from the first page link
8
+ module TrimExtra
9
+ # Override the original pagy_link_proc.
10
+ # Call the pagy_trim method if the trim_extra is enabled.
11
+ def pagy_link_proc(pagy, link_extra: '')
12
+ link_proc = super(pagy, link_extra: link_extra)
13
+ return link_proc unless pagy.vars[:trim_extra]
8
14
 
9
- TRIM = true # boolean used by *_js helpers
15
+ lambda do |page, text = pagy.label_for(page), extra = ''|
16
+ link = +link_proc.call(page, text, extra)
17
+ return link unless page == 1
10
18
 
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
19
+ pagy_trim(pagy, link)
18
20
  end
19
21
  end
20
- alias_method :pagy_link_proc, :pagy_link_proc_with_trim
21
22
 
23
+ # Remove the the :page_param param from the first page link
24
+ def pagy_trim(pagy, link)
25
+ link.sub!(/[?&]#{pagy.vars[:page_param]}=1\b(?!&)|\b#{pagy.vars[:page_param]}=1&/, '')
26
+ end
22
27
  end
28
+ Frontend.prepend TrimExtra
23
29
  end
@@ -1,62 +1,84 @@
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
- require 'pagy/extras/shared'
6
-
7
- class Pagy
8
- module Frontend
4
+ require 'pagy/extras/frontend_helpers'
9
5
 
6
+ class Pagy # :nodoc:
7
+ # Frontend modules are specially optimized for performance.
8
+ # The resulting code may not look very elegant, but produces the best benchmarks
9
+ module UikitExtra
10
10
  # Pagination for uikit: it returns the html with the series of links to the pages
11
- def pagy_uikit_nav(pagy)
12
- link, p_prev, p_next = pagy_link_proc(pagy), pagy.prev, pagy.next
13
-
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>))
17
- 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>)
11
+ def pagy_uikit_nav(pagy, pagy_id: nil, link_extra: '', **vars)
12
+ p_id = %( id="#{pagy_id}") if pagy_id
13
+ link = pagy_link_proc(pagy, link_extra: link_extra)
14
+
15
+ html = +%(<ul#{p_id} class="pagy-uikit-nav uk-pagination uk-flex-center">#{pagy_uikit_prev_html pagy, link})
16
+ pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
17
+ html << case item
18
+ when Integer then %(<li>#{link.call item}</li>)
19
+ when String then %(<li class="uk-active"><span>#{pagy.label_for(item)}</span></li>)
20
+ when :gap then %(<li class="uk-disabled"><span>#{pagy_t 'pagy.nav.gap'}</span></li>)
21
+ else raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
21
22
  end
22
23
  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>)
24
+ html << pagy_uikit_next_html(pagy, link)
25
+ html << %(</ul>)
27
26
  end
28
27
 
29
- # Javascript pagination for uikit: it returns a nav and a JSON tag used by the Pagy.nav javascript
30
- 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>),
36
- 'link' => %(<li>#{link.call(PAGE_PLACEHOLDER)}</li>),
37
- 'active' => %(<li class="uk-active"><span>#{PAGE_PLACEHOLDER}</span></li>),
38
- '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])})
28
+ # Javascript pagination for uikit: it returns a nav and a JSON tag used by the pagy.js file
29
+ def pagy_uikit_nav_js(pagy, pagy_id: nil, link_extra: '', **vars)
30
+ sequels = pagy.sequels(**vars)
31
+ p_id = %( id="#{pagy_id}") if pagy_id
32
+ link = pagy_link_proc(pagy, link_extra: link_extra)
33
+ tags = { 'before' => pagy_uikit_prev_html(pagy, link),
34
+ 'link' => %(<li>#{link.call(PAGE_PLACEHOLDER, LABEL_PLACEHOLDER)}</li>),
35
+ 'active' => %(<li class="uk-active"><span>#{LABEL_PLACEHOLDER}</span></li>),
36
+ 'gap' => %(<li class="uk-disabled"><span>#{pagy_t 'pagy.nav.gap'}</span></li>),
37
+ 'after' => pagy_uikit_next_html(pagy, link) }
38
+
39
+ %(<ul#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-uikit-nav-js uk-pagination uk-flex-center" #{
40
+ pagy_json_attr(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></ul>)
42
41
  end
43
42
 
44
- # Javascript combo pagination for uikit: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
45
- 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
43
+ # Javascript combo pagination for uikit: it returns a nav and a JSON tag used by the pagy.js file
44
+ def pagy_uikit_combo_nav_js(pagy, pagy_id: nil, link_extra: '')
45
+ p_id = %( id="#{pagy_id}") if pagy_id
46
+ link = pagy_link_proc(pagy, link_extra: link_extra)
47
+ p_page = pagy.page
48
+ p_pages = pagy.pages
49
+ input = %(<input type="number" min="1" max="#{p_pages}" value="#{
50
+ p_page}" style="text-align: center; width: #{p_pages.to_s.length + 1}rem;">)
47
51
 
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>))
52
+ %(<ul#{p_id} class="pagy-uikit-combo-nav-js uk-button-group uk-pagination uk-flex-center" #{
53
+ pagy_json_attr pagy, :combo, pagy_marked_link(link)
54
+ }>#{
55
+ pagy_uikit_prev_html pagy, link
56
+ }<li>#{
57
+ pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages
58
+ }</li>#{
59
+ pagy_uikit_next_html pagy, link
60
+ }</ul>)
61
+ end
51
62
 
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>'
63
+ private
55
64
 
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>))
65
+ def pagy_uikit_prev_html(pagy, link)
66
+ previous_span = %(<span uk-pagination-previous>#{pagy_t 'pagy.nav.prev'}</span>)
67
+ if (p_prev = pagy.prev)
68
+ %(<li>#{link.call p_prev, previous_span}</li>)
69
+ else
70
+ %(<li class="uk-disabled"><a href="#">#{previous_span}</a></li>)
71
+ end
72
+ end
58
73
 
59
- html << %(</div>#{pagy_json_tag(:combo_nav, id, p_page, pagy_marked_link(link), defined?(TRIM) && pagy.vars[:page_param])})
74
+ def pagy_uikit_next_html(pagy, link)
75
+ next_span = %(<span uk-pagination-next>#{pagy_t 'pagy.nav.next'}</span>)
76
+ if (p_next = pagy.next)
77
+ %(<li>#{link.call p_next, next_span}</li>)
78
+ else
79
+ %(<li class="uk-disabled"><a href="#">#{next_span}</a></li>)
80
+ end
60
81
  end
61
82
  end
83
+ Frontend.include UikitExtra
62
84
  end