pagy 5.7.5 → 8.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/apps/calendar.ru +745 -0
  4. data/apps/demo.ru +435 -0
  5. data/apps/rails.ru +213 -0
  6. data/apps/repro.ru +177 -0
  7. data/apps/tmp/calendar.sqlite3 +0 -0
  8. data/apps/tmp/calendar.sqlite3-shm +0 -0
  9. data/apps/tmp/calendar.sqlite3-wal +0 -0
  10. data/apps/tmp/local_secret.txt +1 -0
  11. data/bin/pagy +100 -0
  12. data/{lib/config → config}/pagy.rb +72 -96
  13. data/javascripts/pagy-module.js +100 -0
  14. data/javascripts/pagy.d.ts +5 -0
  15. data/javascripts/pagy.js +4 -0
  16. data/javascripts/pagy.min.js +4 -0
  17. data/javascripts/pagy.min.js.map +10 -0
  18. data/javascripts/pagy.mjs +100 -0
  19. data/lib/optimist.rb +1022 -0
  20. data/lib/pagy/backend.rb +16 -4
  21. data/lib/pagy/calendar/day.rb +22 -10
  22. data/lib/pagy/calendar/month.rb +35 -9
  23. data/lib/pagy/calendar/quarter.rb +36 -10
  24. data/lib/pagy/calendar/unit.rb +106 -0
  25. data/lib/pagy/calendar/week.rb +16 -16
  26. data/lib/pagy/calendar/year.rb +15 -9
  27. data/lib/pagy/calendar.rb +60 -68
  28. data/lib/pagy/console.rb +3 -3
  29. data/lib/pagy/countless.rb +17 -12
  30. data/lib/pagy/exceptions.rb +1 -1
  31. data/lib/pagy/extras/arel.rb +2 -2
  32. data/lib/pagy/extras/array.rb +2 -2
  33. data/lib/pagy/extras/bootstrap.rb +57 -53
  34. data/lib/pagy/extras/bulma.rb +53 -57
  35. data/lib/pagy/extras/calendar.rb +54 -37
  36. data/lib/pagy/extras/countless.rb +3 -3
  37. data/lib/pagy/extras/elasticsearch_rails.rb +12 -11
  38. data/lib/pagy/extras/foundation.rb +59 -54
  39. data/lib/pagy/extras/gearbox.rb +32 -19
  40. data/lib/pagy/extras/headers.rb +11 -11
  41. data/lib/pagy/extras/i18n.rb +5 -5
  42. data/lib/pagy/extras/items.rb +34 -24
  43. data/lib/pagy/extras/{frontend_helpers.rb → js_tools.rb} +24 -24
  44. data/lib/pagy/extras/jsonapi.rb +79 -0
  45. data/lib/pagy/extras/materialize.rb +63 -47
  46. data/lib/pagy/extras/meilisearch.rb +26 -22
  47. data/lib/pagy/extras/metadata.rb +13 -9
  48. data/lib/pagy/extras/overflow.rb +13 -10
  49. data/lib/pagy/extras/pagy.rb +82 -0
  50. data/lib/pagy/extras/searchkick.rb +12 -11
  51. data/lib/pagy/extras/semantic.rb +57 -45
  52. data/lib/pagy/extras/size.rb +40 -0
  53. data/lib/pagy/extras/standalone.rb +12 -16
  54. data/lib/pagy/extras/trim.rb +13 -13
  55. data/lib/pagy/extras/uikit.rb +60 -46
  56. data/lib/pagy/frontend.rb +62 -45
  57. data/lib/pagy/i18n.rb +4 -3
  58. data/lib/pagy/url_helpers.rb +13 -25
  59. data/lib/pagy.rb +61 -59
  60. data/locales/ar.yml +28 -0
  61. data/locales/be.yml +25 -0
  62. data/locales/bg.yml +21 -0
  63. data/locales/bs.yml +25 -0
  64. data/locales/ca.yml +21 -0
  65. data/locales/ckb.yml +18 -0
  66. data/locales/cs.yml +23 -0
  67. data/locales/da.yml +21 -0
  68. data/locales/de.yml +21 -0
  69. data/locales/en.yml +21 -0
  70. data/locales/es.yml +21 -0
  71. data/locales/fr.yml +21 -0
  72. data/locales/hr.yml +25 -0
  73. data/locales/id.yml +19 -0
  74. data/locales/it.yml +21 -0
  75. data/locales/ja.yml +19 -0
  76. data/locales/km.yml +19 -0
  77. data/locales/ko.yml +17 -0
  78. data/locales/nb.yml +21 -0
  79. data/locales/nl.yml +21 -0
  80. data/locales/nn.yml +21 -0
  81. data/locales/pl.yml +25 -0
  82. data/locales/pt-BR.yml +21 -0
  83. data/locales/pt.yml +21 -0
  84. data/locales/ru.yml +25 -0
  85. data/locales/sr.yml +25 -0
  86. data/locales/sv-SE.yml +21 -0
  87. data/locales/sv.yml +21 -0
  88. data/locales/sw.yml +23 -0
  89. data/locales/ta.yml +23 -0
  90. data/locales/tr.yml +19 -0
  91. data/locales/uk.yml +25 -0
  92. data/locales/vi.yml +17 -0
  93. data/locales/zh-CN.yml +19 -0
  94. data/locales/zh-HK.yml +19 -0
  95. data/locales/zh-TW.yml +19 -0
  96. data/stylesheets/pagy.css +46 -0
  97. data/stylesheets/pagy.scss +48 -0
  98. data/stylesheets/pagy.tailwind.css +21 -0
  99. metadata +79 -66
  100. data/lib/javascripts/pagy-dev.js +0 -118
  101. data/lib/javascripts/pagy-module.d.ts +0 -30
  102. data/lib/javascripts/pagy-module.js +0 -117
  103. data/lib/javascripts/pagy.js +0 -1
  104. data/lib/locales/ar.yml +0 -26
  105. data/lib/locales/bg.yml +0 -22
  106. data/lib/locales/bs.yml +0 -24
  107. data/lib/locales/ca.yml +0 -22
  108. data/lib/locales/cs.yml +0 -22
  109. data/lib/locales/da.yml +0 -22
  110. data/lib/locales/de.yml +0 -22
  111. data/lib/locales/en.yml +0 -22
  112. data/lib/locales/es.yml +0 -22
  113. data/lib/locales/fr.yml +0 -22
  114. data/lib/locales/hr.yml +0 -24
  115. data/lib/locales/id.yml +0 -20
  116. data/lib/locales/it.yml +0 -22
  117. data/lib/locales/ja.yml +0 -20
  118. data/lib/locales/km.yml +0 -19
  119. data/lib/locales/ko.yml +0 -20
  120. data/lib/locales/nb.yml +0 -22
  121. data/lib/locales/nl.yml +0 -22
  122. data/lib/locales/pl.yml +0 -24
  123. data/lib/locales/pt-BR.yml +0 -22
  124. data/lib/locales/pt.yml +0 -22
  125. data/lib/locales/ru.yml +0 -24
  126. data/lib/locales/sr.yml +0 -23
  127. data/lib/locales/sv-SE.yml +0 -23
  128. data/lib/locales/sv.yml +0 -23
  129. data/lib/locales/sw.yml +0 -22
  130. data/lib/locales/ta.yml +0 -22
  131. data/lib/locales/tr.yml +0 -20
  132. data/lib/locales/uk.yml +0 -24
  133. data/lib/locales/zh-CN.yml +0 -20
  134. data/lib/locales/zh-HK.yml +0 -20
  135. data/lib/locales/zh-TW.yml +0 -20
  136. data/lib/pagy/calendar/month_mixin.rb +0 -49
  137. data/lib/pagy/extras/navs.rb +0 -63
  138. data/lib/pagy/extras/support.rb +0 -54
  139. data/lib/templates/bootstrap_nav.html.erb +0 -24
  140. data/lib/templates/bootstrap_nav.html.haml +0 -34
  141. data/lib/templates/bootstrap_nav.html.slim +0 -34
  142. data/lib/templates/bulma_nav.html.erb +0 -24
  143. data/lib/templates/bulma_nav.html.haml +0 -32
  144. data/lib/templates/bulma_nav.html.slim +0 -32
  145. data/lib/templates/foundation_nav.html.erb +0 -24
  146. data/lib/templates/foundation_nav.html.haml +0 -34
  147. data/lib/templates/foundation_nav.html.slim +0 -34
  148. data/lib/templates/nav.html.erb +0 -22
  149. data/lib/templates/nav.html.haml +0 -30
  150. data/lib/templates/nav.html.slim +0 -29
  151. data/lib/templates/uikit_nav.html.erb +0 -15
  152. data/lib/templates/uikit_nav.html.haml +0 -28
  153. data/lib/templates/uikit_nav.html.slim +0 -28
@@ -1,82 +1,98 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/materialize
2
1
  # frozen_string_literal: true
3
2
 
4
- require 'pagy/extras/frontend_helpers'
3
+ warn '[PAGY WARNING] The materialize extra has been discontinued and it will be removed in v9 ' \
4
+ '(https://github.com/ddnexus/pagy/discussions/672#discussioncomment-9212328)'
5
+
6
+ require_relative 'js_tools'
5
7
 
6
8
  class Pagy # :nodoc:
7
9
  # Frontend modules are specially optimized for performance.
8
10
  # The resulting code may not look very elegant, but produces the best benchmarks
9
11
  module MaterializeExtra
10
12
  # Pagination for materialize: it returns the html with the series of links to the pages
11
- def pagy_materialize_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)
13
+ def pagy_materialize_nav(pagy, id: nil, aria_label: nil, **vars)
14
+ id = %( id="#{id}") if id
15
+ a = pagy_anchor(pagy)
14
16
 
15
- html = +%(<div#{p_id} class="pagy-materialize-nav pagination" role="navigation" aria-label="pager"><ul class="pagination">)
16
- html << pagy_materialize_prev_html(pagy, link)
17
+ html = +%(<div#{id} class="pagy-materialize nav pagination" role="navigation" #{
18
+ nav_aria_label(pagy, aria_label:)}><ul class="pagination">#{
19
+ materialize_prev_html(pagy, a)})
17
20
  pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
18
21
  html << case item
19
- when Integer then %(<li class="waves-effect">#{link.call item}</li>) # page link
20
- when String then %(<li class="active">#{link.call item}</li>) # active page
21
- when :gap then %(<li class="gap disabled"><a href="#">#{pagy_t 'pagy.nav.gap'}</a></li>) # page gap
22
- else raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
22
+ when Integer
23
+ %(<li class="waves-effect">#{a.(item)}</li>)
24
+ when String
25
+ %(<li class="active"><a role="link" aria-current="page" aria-disabled="true">#{pagy.label_for(item)}</a></li>)
26
+ when :gap
27
+ %(<li class="gap disabled"><a role="link" aria-disabled="true">#{pagy_t 'pagy.gap'}</a></li>)
28
+ else
29
+ raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
23
30
  end
24
31
  end
25
- html << pagy_materialize_next_html(pagy, link)
26
- html << %(</ul></div>)
32
+ html << %(#{materialize_next_html(pagy, a)}</ul></div>)
27
33
  end
28
34
 
29
- # Javascript pagination for materialize: it returns a nav and a JSON tag used by the pagy.js file
30
- def pagy_materialize_nav_js(pagy, pagy_id: nil, link_extra: '', **vars)
35
+ # Javascript pagination for materialize: it returns a nav with a data-pagy attribute used by the pagy.js file
36
+ def pagy_materialize_nav_js(pagy, id: nil, aria_label: nil, **vars)
31
37
  sequels = pagy.sequels(**vars)
32
- p_id = %( id="#{pagy_id}") if pagy_id
33
- link = pagy_link_proc(pagy, link_extra: link_extra)
38
+ id = %( id="#{id}") if id
39
+ a = pagy_anchor(pagy)
34
40
 
35
- tags = { 'before' => %(<ul class="pagination">#{pagy_materialize_prev_html pagy, link}),
36
- 'link' => %(<li class="waves-effect">#{mark = link.call(PAGE_PLACEHOLDER, LABEL_PLACEHOLDER)}</li>),
37
- 'active' => %(<li class="active">#{mark}</li>),
38
- 'gap' => %(<li class="gap disabled"><a href="#">#{pagy_t 'pagy.nav.gap'}</a></li>),
39
- 'after' => %(#{pagy_materialize_next_html pagy, link}</ul>) }
41
+ tokens = { 'before' => %(<ul class="pagination">#{materialize_prev_html pagy, a}),
42
+ 'a' => %(<li class="waves-effect">#{a.(PAGE_TOKEN, LABEL_TOKEN)}</li>),
43
+ 'current' => %(<li class="active"><a role="link" aria-current="page" aria-disabled="true">#{
44
+ LABEL_TOKEN}</a></li>),
45
+ 'gap' => %(<li class="gap disabled"><a role="link" aria-disabled="true">#{pagy_t 'pagy.gap'}</a></li>),
46
+ 'after' => %(#{materialize_next_html pagy, a}</ul>) }
40
47
 
41
- %(<div#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-materialize-nav-js" role="navigation" aria-label="pager" #{
42
- pagy_json_attr(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></div>)
48
+ %(<div#{id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-materialize nav-js" role="navigation" #{
49
+ nav_aria_label(pagy, aria_label:)} #{
50
+ pagy_data(pagy, :nav, tokens, sequels, pagy.label_sequels(sequels))
51
+ }></div>)
43
52
  end
44
53
 
45
- # Javascript combo pagination for materialize: it returns a nav and a JSON tag used by the pagy.js file
46
- def pagy_materialize_combo_nav_js(pagy, pagy_id: nil, link_extra: '')
47
- p_id = %( id="#{pagy_id}") if pagy_id
48
- link = pagy_link_proc(pagy, link_extra: link_extra)
49
- p_page = pagy.page
50
- p_pages = pagy.pages
51
- style = ' style="vertical-align: middle"'
52
- input = %(<input type="number" class="browser-default" min="1" max="#{p_pages}" value="#{
53
- p_page}" style="text-align: center; width: #{p_pages.to_s.length + 1}rem;">)
54
+ # Javascript combo pagination for materialize: it returns a nav with a data-pagy attribute used by the pagy.js file
55
+ def pagy_materialize_combo_nav_js(pagy, id: nil, aria_label: nil)
56
+ id = %( id="#{id}") if id
57
+ a = pagy_anchor(pagy)
58
+ pages = pagy.pages
59
+
60
+ page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page" ) <<
61
+ %(style="text-align: center; width: #{pages.to_s.length + 1}rem; height: 1.5rem; font-size: 1.2rem; ) <<
62
+ %(border: none; border-radius: 2px; color: white; background-color: #ee6e73;" class="browser-default"> ) <<
63
+ JSTools::A_TAG
54
64
 
55
- html = %(<ul#{p_id} class="pagy-materialize-combo-nav-js pagination chip" role="navigation")
56
- %(#{html} aria-label="pager" style="padding-right: 0" #{
57
- pagy_json_attr pagy, :combo, pagy_marked_link(link)}>#{
58
- pagy_materialize_prev_html pagy, link, style}<li class="pagy-combo-input">#{
59
- pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages}</li>#{
60
- pagy_materialize_next_html pagy, link, style}</ul>)
65
+ %(<ul#{id} class="pagy-materialize combo-nav-js pagination" role="navigation" style="padding-right: 0;" #{
66
+ nav_aria_label(pagy, aria_label:)} #{
67
+ pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))
68
+ }>#{
69
+ materialize_prev_html(pagy, a)
70
+ }<li style="vertical-align: -webkit-baseline-middle;"><label style="font-size: 1.2rem;">#{
71
+ pagy_t('pagy.combo_nav_js', page_input:, pages:)
72
+ }</label></li>#{
73
+ materialize_next_html(pagy, a)
74
+ }</ul>)
61
75
  end
62
76
 
63
77
  private
64
78
 
65
- def pagy_materialize_prev_html(pagy, link, style = '')
79
+ def materialize_prev_html(pagy, a)
66
80
  if (p_prev = pagy.prev)
67
- %(<li class="waves-effect prev"#{style}>#{
68
- link.call p_prev, '<i class="material-icons">chevron_left</i>', 'aria-label="previous"'}</li>)
81
+ %(<li class="waves-effect prev">#{
82
+ a.(p_prev, '<i class="material-icons">chevron_left</i>', aria_label: pagy_t('pagy.aria_label.prev'))}</li>)
69
83
  else
70
- %(<li class="prev disabled"#{style}><a href="#"><i class="material-icons">chevron_left</i></a></li>)
84
+ %(<li class="prev disabled"><a role="link" aria-disabled="true" aria-label="#{
85
+ pagy_t('pagy.aria_label.prev')}"><i class="material-icons">chevron_left</i></a></li>)
71
86
  end
72
87
  end
73
88
 
74
- def pagy_materialize_next_html(pagy, link, style = '')
89
+ def materialize_next_html(pagy, a)
75
90
  if (p_next = pagy.next)
76
- %(<li class="waves-effect next"#{style}>#{
77
- link.call p_next, '<i class="material-icons">chevron_right</i>', 'aria-label="next"'}</li>)
91
+ %(<li class="waves-effect next">#{
92
+ a.(p_next, '<i class="material-icons">chevron_right</i>', aria_label: pagy_t('pagy.aria_label.next'))}</li>)
78
93
  else
79
- %(<li class="next disabled"#{style}><a href="#"><i class="material-icons">chevron_right</i></a></li>)
94
+ %(<li class="next disabled"#><a role="link" aria-disabled="true" aria-label="#{
95
+ pagy_t('pagy.aria_label.next')}><i class="material-icons">chevron_right</i></a></li>)
80
96
  end
81
97
  end
82
98
  end
@@ -1,43 +1,49 @@
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/meilisearch
1
2
  # frozen_string_literal: true
2
3
 
3
4
  class Pagy # :nodoc:
4
- DEFAULT[:meilisearch_search_method] ||= :pagy_search
5
+ DEFAULT[:meilisearch_search] ||= :ms_search
6
+ DEFAULT[:meilisearch_pagy_search] ||= :pagy_search
5
7
 
6
8
  # Paginate Meilisearch results
7
9
  module MeilisearchExtra
8
- module Meilisearch # :nodoc:
10
+ module ModelExtension # :nodoc:
9
11
  # Return an array used to delay the call of #search
10
12
  # after the pagination variables are merged to the options
11
- def pagy_meilisearch(term = nil, **vars)
12
- [self, term, vars]
13
+ def pagy_meilisearch(query, params = {})
14
+ [self, query, params]
13
15
  end
14
- alias_method DEFAULT[:meilisearch_search_method], :pagy_meilisearch
16
+ alias_method DEFAULT[:meilisearch_pagy_search], :pagy_meilisearch
15
17
  end
18
+ Pagy::Meilisearch = ModelExtension
16
19
 
17
- # Additions for the Pagy class
18
- module Pagy
20
+ # Extension for the Pagy class
21
+ module PagyExtension
19
22
  # Create a Pagy object from a Meilisearch results
20
23
  def new_from_meilisearch(results, vars = {})
21
- vars[:items] = results.raw_answer['limit']
22
- vars[:page] = [results.raw_answer['offset'] / vars[:items], 1].max
23
- vars[:count] = results.raw_answer['nbHits']
24
+ vars[:items] = results.raw_answer['hitsPerPage']
25
+ vars[:page] = results.raw_answer['page']
26
+ vars[:count] = results.raw_answer['totalHits']
27
+
24
28
  new(vars)
25
29
  end
26
30
  end
31
+ Pagy.extend PagyExtension
27
32
 
28
33
  # Add specialized backend methods to paginate Meilisearch results
29
- module Backend
34
+ module BackendAddOn
30
35
  private
31
36
 
32
37
  # Return Pagy object and results
33
38
  def pagy_meilisearch(pagy_search_args, vars = {})
34
- model, term, options = pagy_search_args
35
- vars = pagy_meilisearch_get_vars(nil, vars)
36
- options[:limit] = vars[:items]
37
- options[:offset] = (vars[:page] - 1) * vars[:items]
38
- results = model.search(term, **options)
39
- vars[:count] = results.raw_answer['nbHits']
40
- pagy = ::Pagy.new(vars)
39
+ model, term, options = pagy_search_args
40
+ vars = pagy_meilisearch_get_vars(nil, vars)
41
+ options[:hits_per_page] = vars[:items]
42
+ options[:page] = vars[:page]
43
+ results = model.send(:ms_search, term, options)
44
+ vars[:count] = results.raw_answer['totalHits']
45
+
46
+ pagy = ::Pagy.new(vars)
41
47
  # with :last_page overflow we need to re-run the method in order to get the hits
42
48
  return pagy_meilisearch(pagy_search_args, vars.merge(page: pagy.page)) \
43
49
  if defined?(::Pagy::OverflowExtra) && pagy.overflow? && pagy.vars[:overflow] == :last_page
@@ -50,12 +56,10 @@ class Pagy # :nodoc:
50
56
  def pagy_meilisearch_get_vars(_collection, vars)
51
57
  pagy_set_items_from_params(vars) if defined?(ItemsExtra)
52
58
  vars[:items] ||= DEFAULT[:items]
53
- vars[:page] ||= (params[vars[:page_param] || DEFAULT[:page_param]] || 1).to_i
59
+ vars[:page] ||= pagy_get_page(vars)
54
60
  vars
55
61
  end
56
62
  end
63
+ Backend.prepend BackendAddOn
57
64
  end
58
- Meilisearch = MeilisearchExtra::Meilisearch
59
- extend MeilisearchExtra::Pagy
60
- Backend.prepend MeilisearchExtra::Backend
61
65
  end
@@ -1,7 +1,7 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/metadata
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/metadata
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/url_helpers'
4
+ require_relative '../url_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  DEFAULT[:metadata] = %i[ scaffold_url first_url prev_url page_url next_url last_url
@@ -15,17 +15,21 @@ class Pagy # :nodoc:
15
15
 
16
16
  # Return the metadata hash
17
17
  def pagy_metadata(pagy, absolute: nil)
18
- scaffold_url = pagy_url_for(pagy, PAGE_PLACEHOLDER, absolute: absolute)
18
+ scaffold_url = pagy_url_for(pagy, PAGE_TOKEN, absolute:)
19
19
  {}.tap do |metadata|
20
- keys = defined?(Calendar) && pagy.is_a?(Calendar) ? pagy.vars[:metadata] - %i[count items] : pagy.vars[:metadata]
20
+ keys = if defined?(Calendar::Unit) && pagy.is_a?(Calendar::Unit)
21
+ pagy.vars[:metadata] - %i[count items]
22
+ else
23
+ pagy.vars[:metadata]
24
+ end
21
25
  keys.each do |key|
22
26
  metadata[key] = case key
23
27
  when :scaffold_url then scaffold_url
24
- when :first_url then scaffold_url.sub(PAGE_PLACEHOLDER, 1.to_s)
25
- when :prev_url then scaffold_url.sub(PAGE_PLACEHOLDER, pagy.prev.to_s)
26
- when :page_url then scaffold_url.sub(PAGE_PLACEHOLDER, pagy.page.to_s)
27
- when :next_url then scaffold_url.sub(PAGE_PLACEHOLDER, pagy.next.to_s)
28
- when :last_url then scaffold_url.sub(PAGE_PLACEHOLDER, pagy.last.to_s)
28
+ when :first_url then scaffold_url.sub(PAGE_TOKEN, 1.to_s)
29
+ when :prev_url then scaffold_url.sub(PAGE_TOKEN, pagy.prev.to_s)
30
+ when :page_url then scaffold_url.sub(PAGE_TOKEN, pagy.page.to_s)
31
+ when :next_url then scaffold_url.sub(PAGE_TOKEN, pagy.next.to_s)
32
+ when :last_url then scaffold_url.sub(PAGE_TOKEN, pagy.last.to_s)
29
33
  else pagy.send(key)
30
34
  end
31
35
  rescue NoMethodError
@@ -1,4 +1,4 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/overflow
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/overflow
2
2
  # frozen_string_literal: true
3
3
 
4
4
  class Pagy # :nodoc:
@@ -7,7 +7,7 @@ class Pagy # :nodoc:
7
7
  # Handles OverflowError exceptions for different classes with different options
8
8
  module OverflowExtra
9
9
  # Support for Pagy class
10
- module Pagy
10
+ module PagyOverride
11
11
  # Is the requested page overflowing?
12
12
  def overflow?
13
13
  @overflow
@@ -27,8 +27,9 @@ class Pagy # :nodoc:
27
27
  initialize vars.merge!(page: @last) # re-run with the last page
28
28
  @vars[:page] = requested_page # restore the requested page
29
29
  when :empty_page
30
- @offset = @items = @from = @to = 0 # vars relative to the actual page
31
- if defined?(Calendar) && is_a?(Calendar) # only for Calendar instances
30
+ @offset = @items = @in = @from = @to = 0 # vars relative to the actual page
31
+ if defined?(Calendar::Unit) \
32
+ && is_a?(Calendar::Unit) # only for Calendar::Units instances
32
33
  edge = @order == :asc ? @final : @initial # get the edge of the overflow side (neat, but any time would do)
33
34
  @from = @to = edge # set both to the edge utc time (a >=&&< query will get no records)
34
35
  end
@@ -41,7 +42,7 @@ class Pagy # :nodoc:
41
42
 
42
43
  # Special series for empty page
43
44
  module Series
44
- def series(*)
45
+ def series(*, **)
45
46
  @page = @last # series for last page
46
47
  super.tap do |s| # call original series
47
48
  s[s.index(@page.to_s)] = @page # string to integer (i.e. no current page)
@@ -50,9 +51,11 @@ class Pagy # :nodoc:
50
51
  end
51
52
  end
52
53
  end
54
+ Pagy.prepend PagyOverride
55
+ Pagy::Calendar::Unit.prepend PagyOverride if defined?(Calendar::Unit)
53
56
 
54
57
  # Support for Pagy::Countless class
55
- module Countless
58
+ module CountlessOverride
56
59
  # Add rescue clause for different behaviors
57
60
  def finalize(items)
58
61
  @overflow = false
@@ -64,15 +67,15 @@ class Pagy # :nodoc:
64
67
  raise # same as without the extra
65
68
  when :empty_page
66
69
  @offset = @items = @from = @to = 0 # vars relative to the actual page
67
- @vars[:size] = [] # no page in the series
70
+ @vars[:size] = 0 # no page in the series
68
71
  self
69
72
  else
70
73
  raise VariableError.new(self, :overflow, 'to be in [:empty_page, :exception]', @vars[:overflow])
71
74
  end
72
75
  end
73
76
  end
77
+ # :nocov:
78
+ Pagy::Countless.prepend CountlessOverride if defined?(Countless)
79
+ # :nocov:
74
80
  end
75
- prepend OverflowExtra::Pagy
76
- Calendar.prepend OverflowExtra::Pagy if defined?(Calendar)
77
- Countless.prepend OverflowExtra::Countless if defined?(Countless)
78
81
  end
@@ -0,0 +1,82 @@
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/pagy
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'js_tools'
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 PagyExtra
10
+ # pagy_nav is defined in the Frontend itself
11
+ # Javascript pagination: it returns a nav with a data-pagy attribute used by the pagy.js file
12
+ def pagy_nav_js(pagy, id: nil, aria_label: nil, **vars)
13
+ sequels = pagy.sequels(**vars)
14
+ id = %( id="#{id}") if id
15
+ a = pagy_anchor(pagy)
16
+ tokens = { 'before' => prev_a(pagy, a),
17
+ 'a' => a.(PAGE_TOKEN, LABEL_TOKEN),
18
+ 'current' => %(<a class="current" role="link" aria-current="page" aria-disabled="true">#{
19
+ LABEL_TOKEN}</a>),
20
+ 'gap' => %(<a class="gap" role="link" aria-disabled="true">#{pagy_t('pagy.gap')}</a>),
21
+ 'after' => next_a(pagy, a) }
22
+
23
+ %(<nav#{id} class="#{'pagy-rjs ' if sequels.size > 1}pagy nav-js" #{
24
+ nav_aria_label(pagy, aria_label:)} #{
25
+ pagy_data(pagy, :nav, tokens, sequels, pagy.label_sequels(sequels))
26
+ }></nav>)
27
+ end
28
+
29
+ # Javascript combo pagination: it returns a nav with a data-pagy attribute used by the pagy.js file
30
+ def pagy_combo_nav_js(pagy, id: nil, aria_label: nil)
31
+ id = %( id="#{id}") if id
32
+ a = pagy_anchor(pagy)
33
+ pages = pagy.pages
34
+
35
+ page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page" ) <<
36
+ %(style="text-align: center; width: #{pages.to_s.length + 1}rem; padding: 0;">#{JSTools::A_TAG})
37
+
38
+ %(<nav#{id} class="pagy combo-nav-js" #{
39
+ nav_aria_label(pagy, aria_label:)} #{
40
+ pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))}>#{
41
+ prev_a(pagy, a)
42
+ }<label>#{
43
+ pagy_t('pagy.combo_nav_js', page_input:, pages:)
44
+ }</label>#{
45
+ next_a(pagy, a)
46
+ }</nav>)
47
+ end
48
+
49
+ # Return the previous page URL string or nil
50
+ def pagy_prev_url(pagy, absolute: false)
51
+ pagy_url_for(pagy, pagy.prev, absolute:) if pagy.prev
52
+ end
53
+
54
+ # Return the next page URL string or nil
55
+ def pagy_next_url(pagy, absolute: false)
56
+ pagy_url_for(pagy, pagy.next, absolute:) if pagy.next
57
+ end
58
+
59
+ # Return the enabled/disabled previous page anchor tag
60
+ def pagy_prev_a(pagy, text: pagy_t('pagy.prev'), aria_label: pagy_t('pagy.aria_label.prev'))
61
+ a = pagy_anchor(pagy)
62
+ prev_a(pagy, a, text:, aria_label:)
63
+ end
64
+
65
+ # Return the enabled/disabled next page anchor tag
66
+ def pagy_next_a(pagy, text: pagy_t('pagy.next'), aria_label: pagy_t('pagy.aria_label.next'))
67
+ a = pagy_anchor(pagy)
68
+ next_a(pagy, a, text:, aria_label:)
69
+ end
70
+
71
+ # Conditionally return the previous page link tag
72
+ def pagy_prev_link(pagy, absolute: false)
73
+ %(<link href="#{pagy_url_for(pagy, pagy.prev, absolute:)}"/>) if pagy.prev
74
+ end
75
+
76
+ # Conditionally return the next page link tag
77
+ def pagy_next_link(pagy, absolute: false)
78
+ %(<link href="#{pagy_url_for(pagy, pagy.next, absolute:)}"/>) if pagy.next
79
+ end
80
+ end
81
+ Frontend.prepend PagyExtra
82
+ end
@@ -1,12 +1,13 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/searchkick
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/searchkick
2
2
  # frozen_string_literal: true
3
3
 
4
4
  class Pagy # :nodoc:
5
- DEFAULT[:searchkick_search_method] ||= :pagy_search
5
+ DEFAULT[:searchkick_search] ||= :search
6
+ DEFAULT[:searchkick_pagy_search] ||= :pagy_search
6
7
 
7
8
  # Paginate Searchkick::Results objects
8
9
  module SearchkickExtra
9
- module Searchkick # :nodoc:
10
+ module ModelExtension # :nodoc:
10
11
  # Return an array used to delay the call of #search
11
12
  # after the pagination variables are merged to the options.
12
13
  # It also pushes to the same array an optional method call.
@@ -15,11 +16,12 @@ class Pagy # :nodoc:
15
16
  args.define_singleton_method(:method_missing) { |*a| args += a }
16
17
  end
17
18
  end
18
- alias_method Pagy::DEFAULT[:searchkick_search_method], :pagy_searchkick
19
+ alias_method Pagy::DEFAULT[:searchkick_pagy_search], :pagy_searchkick
19
20
  end
21
+ Pagy::Searchkick = ModelExtension
20
22
 
21
23
  # Additions for the Pagy class
22
- module Pagy
24
+ module PagyExtension
23
25
  # Create a Pagy object from a Searchkick::Results object
24
26
  def new_from_searchkick(results, vars = {})
25
27
  vars[:items] = results.options[:per_page]
@@ -28,9 +30,10 @@ class Pagy # :nodoc:
28
30
  new(vars)
29
31
  end
30
32
  end
33
+ Pagy.extend PagyExtension
31
34
 
32
35
  # Add specialized backend methods to paginate Searchkick::Results
33
- module Backend
36
+ module BackendAddOn
34
37
  private
35
38
 
36
39
  # Return Pagy object and results
@@ -39,7 +42,7 @@ class Pagy # :nodoc:
39
42
  vars = pagy_searchkick_get_vars(nil, vars)
40
43
  options[:per_page] = vars[:items]
41
44
  options[:page] = vars[:page]
42
- results = model.search(term, **options, &block)
45
+ results = model.send(DEFAULT[:searchkick_search], term, **options, &block)
43
46
  vars[:count] = results.total_count
44
47
 
45
48
  pagy = ::Pagy.new(vars)
@@ -55,12 +58,10 @@ class Pagy # :nodoc:
55
58
  def pagy_searchkick_get_vars(_collection, vars)
56
59
  pagy_set_items_from_params(vars) if defined?(ItemsExtra)
57
60
  vars[:items] ||= DEFAULT[:items]
58
- vars[:page] ||= (params[vars[:page_param] || DEFAULT[:page_param]] || 1).to_i
61
+ vars[:page] ||= pagy_get_page(vars)
59
62
  vars
60
63
  end
61
64
  end
65
+ Backend.prepend BackendAddOn
62
66
  end
63
- Searchkick = SearchkickExtra::Searchkick
64
- extend SearchkickExtra::Pagy
65
- Backend.prepend SearchkickExtra::Backend
66
67
  end
@@ -1,80 +1,92 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/semantic
2
1
  # frozen_string_literal: true
3
2
 
4
- require 'pagy/extras/frontend_helpers'
3
+ warn '[PAGY WARNING] The semantic extra has been discontinued and it will be removed in v9 ' \
4
+ '(https://github.com/ddnexus/pagy/discussions/672#discussioncomment-9212328)'
5
+
6
+ require_relative 'js_tools'
5
7
 
6
8
  class Pagy # :nodoc:
7
9
  # Frontend modules are specially optimized for performance.
8
10
  # The resulting code may not look very elegant, but produces the best benchmarks
9
11
  module SemanticExtra
10
12
  # Pagination for semantic: it returns the html with the series of links to the pages
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}))
13
+ def pagy_semantic_nav(pagy, id: nil, aria_label: nil, **vars)
14
+ id = %( id="#{id}") if id
15
+ a = pagy_anchor(pagy)
14
16
 
15
- html = +%(<div#{p_id} class="pagy-semantic-nav ui pagination menu">)
16
- html << pagy_semantic_prev_html(pagy, link)
17
+ html = %(<div#{id} role="navigation" class="pagy-semantic nav ui pagination menu" #{
18
+ nav_aria_label(pagy, aria_label:)}>#{semantic_prev_html(pagy, a)})
17
19
  pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
18
20
  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}"
21
+ when Integer
22
+ a.(item, pagy.label_for(item), classes: 'item')
23
+ when String
24
+ %(<a role="link" class="item active" aria-current="page" aria-disabled="true">#{pagy.label_for(item)}</a>)
25
+ when :gap
26
+ %(<div class="disabled item">#{pagy_t 'pagy.gap'}</div>)
27
+ else
28
+ raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
23
29
  end
24
30
  end
25
- html << pagy_semantic_next_html(pagy, link)
26
- html << %(</div>)
31
+ html << %(#{semantic_next_html(pagy, a)}</div>)
27
32
  end
28
33
 
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)
34
+ # Javascript pagination for semantic: it returns a nav with a data-pagy attribute used by the pagy.js file
35
+ def pagy_semantic_nav_js(pagy, id: nil, aria_label: nil, **vars)
31
36
  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>),
37
- 'gap' => %(<div class="disabled item">#{pagy_t('pagy.nav.gap')}</div>),
38
- 'after' => pagy_semantic_next_html(pagy, link) }
37
+ id = %( id="#{id}") if id
38
+ a = pagy_anchor(pagy)
39
+ tokens = { 'before' => semantic_prev_html(pagy, a),
40
+ 'a' => a.(PAGE_TOKEN, LABEL_TOKEN, classes: 'item'),
41
+ 'current' => %(<a role="link" class="item active" aria-current="page" aria-disabled="true">#{LABEL_TOKEN}</a>),
42
+ 'gap' => %(<div class="disabled item">#{pagy_t('pagy.gap')}</div>),
43
+ 'after' => semantic_next_html(pagy, a) }
39
44
 
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>)
45
+ %(<div#{id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-semantic nav-js ui pagination menu" role="navigation" #{
46
+ nav_aria_label(pagy, aria_label:)} #{
47
+ pagy_data(pagy, :nav, tokens, sequels, pagy.label_sequels(sequels))
48
+ }></div>)
42
49
  end
43
50
 
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">)
51
+ # Combo pagination for semantic: it returns a nav with a data-pagy attribute used by the pagy.js file
52
+ def pagy_semantic_combo_nav_js(pagy, id: nil, aria_label: nil)
53
+ id = %( id="#{id}") if id
54
+ a = pagy_anchor(pagy)
55
+ pages = pagy.pages
56
+
57
+ page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page") <<
58
+ %(style="text-align: center; width: #{pages.to_s.length + 1}rem; padding: 0; margin: 0 0.3rem">) <<
59
+ JSTools::A_TAG
52
60
 
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
61
+ %(<div#{id} class="pagy-semantic combo-nav-js ui compact menu" role="navigation" #{
62
+ nav_aria_label(pagy, aria_label:)} #{
63
+ pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))
64
+ }>#{
65
+ semantic_prev_html(pagy, a)
66
+ }<div class="item"><label>#{
67
+ pagy_t('pagy.combo_nav_js', page_input:, pages:)
68
+ }</label></div> #{
69
+ semantic_next_html(pagy, a)
60
70
  }</div>)
61
71
  end
62
72
 
63
73
  private
64
74
 
65
- def pagy_semantic_prev_html(pagy, link)
75
+ def semantic_prev_html(pagy, a)
66
76
  if (p_prev = pagy.prev)
67
- link.call p_prev, '<i class="left small chevron icon"></i>', 'aria-label="previous"'
77
+ a.(p_prev, pagy_t('pagy.prev'), classes: 'item', aria_label: pagy_t('pagy.aria_label.prev'))
68
78
  else
69
- +%(<div class="item disabled"><i class="left small chevron icon"></i></div>)
79
+ %(<div class="item disabled" role="a" aria-disabled="true" aria-label="#{
80
+ pagy_t('pagy.aria_label.prev')}">#{pagy_t('pagy.prev')}</div>)
70
81
  end
71
82
  end
72
83
 
73
- def pagy_semantic_next_html(pagy, link)
84
+ def semantic_next_html(pagy, a)
74
85
  if (p_next = pagy.next)
75
- link.call p_next, '<i class="right small chevron icon"></i>', 'aria-label="next"'
86
+ a.(p_next, pagy_t('pagy.next'), classes: 'item', aria_label: pagy_t('pagy.aria_label.next'))
76
87
  else
77
- +%(<div class="item disabled"><i class="right small chevron icon"></i></div>)
88
+ %(<div class="item disabled" role="link" aria-disabled="true" aria=label="#{
89
+ pagy_t('pagy.aria_label.prev')}">#{pagy_t('pagy.next')}</div>)
78
90
  end
79
91
  end
80
92
  end