pagy 5.7.5 → 8.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,4 +1,4 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/array
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/array
2
2
  # frozen_string_literal: true
3
3
 
4
4
  class Pagy # :nodoc:
@@ -16,7 +16,7 @@ class Pagy # :nodoc:
16
16
  def pagy_array_get_vars(array, vars)
17
17
  pagy_set_items_from_params(vars) if defined?(ItemsExtra)
18
18
  vars[:count] ||= array.size
19
- vars[:page] ||= params[vars[:page_param] || DEFAULT[:page_param]]
19
+ vars[:page] ||= pagy_get_page(vars)
20
20
  vars
21
21
  end
22
22
  end
@@ -1,91 +1,95 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/bootstrap
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/bootstrap
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/extras/frontend_helpers'
4
+ require_relative 'js_tools'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  # Frontend modules are specially optimized for performance.
8
8
  # The resulting code may not look very elegant, but produces the best benchmarks
9
9
  module BootstrapExtra
10
10
  # Pagination for bootstrap: it returns the html with the series of links to the pages
11
- def pagy_bootstrap_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="page-link" #{link_extra}))
11
+ def pagy_bootstrap_nav(pagy, id: nil, classes: 'pagination', aria_label: nil, **vars)
12
+ id = %( id="#{id}") if id
13
+ a = pagy_anchor(pagy)
14
14
 
15
- html = +%(<nav#{p_id} class="pagy-bootstrap-nav" aria-label="pager"><ul class="pagination">)
16
- html << pagy_bootstrap_prev_html(pagy, link)
15
+ html = %(<nav#{id} class="pagy-bootstrap nav" #{nav_aria_label(pagy, aria_label:)}><ul class="#{classes}">#{
16
+ bootstrap_prev_html(pagy, a)})
17
17
  pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
18
18
  html << case item
19
19
  when Integer
20
- %(<li class="page-item">#{link.call item}</li>)
20
+ %(<li class="page-item">#{a.(item, classes: 'page-link')}</li>)
21
21
  when String
22
- %(<li class="page-item active">#{link.call item}</li>)
22
+ %(<li class="page-item active"><a role="link" class="page-link" aria-current="page" aria-disabled="true">#{
23
+ pagy.label_for(item)}</a></li>)
23
24
  when :gap
24
- %(<li class="page-item gap disabled"><a href="#" class="page-link">#{pagy_t 'pagy.nav.gap'}</a></li>)
25
+ %(<li class="page-item gap disabled"><a role="link" class="page-link" aria-disabled="true">#{
26
+ pagy_t('pagy.gap')}</a></li>)
25
27
  else raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
26
28
  end
27
29
  end
28
- html << pagy_bootstrap_next_html(pagy, link)
29
- html << %(</ul></nav>)
30
+ html << %(#{bootstrap_next_html(pagy, a)}</ul></nav>)
30
31
  end
31
32
 
32
- # Javascript pagination for bootstrap: it returns a nav and a JSON tag used by the pagy.js file
33
- def pagy_bootstrap_nav_js(pagy, pagy_id: nil, link_extra: '', **vars)
33
+ # Javascript pagination for bootstrap: it returns a nav with a data-pagy attribute used by the pagy.js file
34
+ def pagy_bootstrap_nav_js(pagy, id: nil, classes: 'pagination', aria_label: nil, **vars)
34
35
  sequels = pagy.sequels(**vars)
35
- p_id = %( id="#{pagy_id}") if pagy_id
36
- link = pagy_link_proc(pagy, link_extra: %(class="page-link" #{link_extra}))
37
- tags = { 'before' => %(<ul class="pagination">#{pagy_bootstrap_prev_html pagy, link}),
38
- 'link' => %(<li class="page-item">#{mark = link.call(PAGE_PLACEHOLDER, LABEL_PLACEHOLDER)}</li>),
39
- 'active' => %(<li class="page-item active">#{mark}</li>),
40
- 'gap' => %(<li class="page-item gap disabled"><a href="#" class="page-link">#{pagy_t 'pagy.nav.gap'}</a></li>),
41
- 'after' => %(#{pagy_bootstrap_next_html pagy, link}</ul>) }
36
+ id = %( id="#{id}") if id
37
+ a = pagy_anchor(pagy)
38
+ tokens = { 'before' => %(<ul class="#{classes}">#{bootstrap_prev_html(pagy, a)}),
39
+ 'a' => %(<li class="page-item">#{a.(PAGE_TOKEN, LABEL_TOKEN, classes: 'page-link')}</li>),
40
+ 'current' => %(<li class="page-item active"><a role="link" class="page-link" ) +
41
+ %(aria-current="page" aria-disabled="true">#{LABEL_TOKEN}</a></li>),
42
+ 'gap' => %(<li class="page-item gap disabled"><a role="link" class="page-link" aria-disabled="true">#{
43
+ pagy_t('pagy.gap')}</a></li>),
44
+ 'after' => %(#{bootstrap_next_html pagy, a}</ul>) }
42
45
 
43
- %(<nav#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-bootstrap-nav-js" aria-label="pager" #{
44
- pagy_json_attr(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></nav>)
46
+ %(<nav#{id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-bootstrap nav-js" #{
47
+ nav_aria_label(pagy, aria_label:)} #{
48
+ pagy_data(pagy, :nav, tokens, sequels, pagy.label_sequels(sequels))
49
+ }></nav>)
45
50
  end
46
51
 
47
- # Javascript combo pagination for bootstrap: it returns a nav and a JSON tag used by the pagy.js file
48
- def pagy_bootstrap_combo_nav_js(pagy, pagy_id: nil, link_extra: '')
49
- p_id = %( id="#{pagy_id}") if pagy_id
50
- link = pagy_link_proc(pagy, link_extra: link_extra)
51
- p_page = pagy.page
52
- p_pages = pagy.pages
53
- input = %(<input type="number" min="1" max="#{p_pages}" value="#{
54
- p_page}" class="text-primary" style="padding: 0; border: none; text-align: center; width: #{
55
- p_pages.to_s.length + 1}rem;">)
52
+ # Javascript combo pagination for bootstrap: it returns a nav with a data-pagy attribute used by the pagy.js file
53
+ def pagy_bootstrap_combo_nav_js(pagy, id: nil, classes: 'pagination', aria_label: nil)
54
+ id = %( id="#{id}") if id
55
+ a = pagy_anchor(pagy)
56
+ pages = pagy.pages
56
57
 
57
- %(<nav#{p_id} class="pagy-bootstrap-combo-nav-js pagination" aria-label="pager"><div class="btn-group" role="group" #{
58
- pagy_json_attr pagy, :combo, pagy_marked_link(link)}>#{
59
- if (p_prev = pagy.prev)
60
- link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous" class="prev btn btn-primary"'
61
- else
62
- %(<a class="prev btn btn-primary disabled" href="#">#{pagy_t('pagy.nav.prev')}</a>)
63
- end
64
- }<div class="pagy-combo-input btn btn-primary disabled" style="white-space: nowrap;">#{
65
- pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages}</div>#{
66
- if (p_next = pagy.next)
67
- link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next" class="next btn btn-primary"'
68
- else
69
- %(<a class="next btn btn-primary disabled" href="#">#{pagy_t 'pagy.nav.next'}</a>)
70
- end
71
- }</div></nav>)
58
+ page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page" ) <<
59
+ %(style="text-align: center; width: #{pages.to_s.length + 1}rem; padding: 0; ) <<
60
+ %(border: none; display: inline-block;" class="page-link active">#{JSTools::A_TAG})
61
+
62
+ %(<nav#{id} class="pagy-bootstrap combo-nav-js" #{
63
+ nav_aria_label(pagy, aria_label:)} #{
64
+ pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))
65
+ }><ul class="#{classes}">#{
66
+ bootstrap_prev_html(pagy, a)
67
+ }<li class="page-item pagy-bootstrap"><label class="page-link">#{
68
+ pagy_t('pagy.combo_nav_js', page_input:, pages:)
69
+ }</label></li>#{
70
+ bootstrap_next_html(pagy, a)
71
+ }</ul></nav>)
72
72
  end
73
73
 
74
74
  private
75
75
 
76
- def pagy_bootstrap_prev_html(pagy, link)
76
+ def bootstrap_prev_html(pagy, a)
77
77
  if (p_prev = pagy.prev)
78
- %(<li class="page-item prev">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'}</li>)
78
+ %(<li class="page-item prev">#{
79
+ a.(p_prev, pagy_t('pagy.prev'), classes: 'page-link', aria_label: pagy_t('pagy.aria_label.prev'))}</li>)
79
80
  else
80
- %(<li class="page-item prev disabled"><a href="#" class="page-link">#{pagy_t 'pagy.nav.prev'}</a></li>)
81
+ %(<li class="page-item prev disabled"><a role="link" class="page-link" aria-disabled="true" aria-label="#{
82
+ pagy_t('pagy.aria_label.prev')}">#{pagy_t('pagy.prev')}</a></li>)
81
83
  end
82
84
  end
83
85
 
84
- def pagy_bootstrap_next_html(pagy, link)
86
+ def bootstrap_next_html(pagy, a)
85
87
  if (p_next = pagy.next)
86
- %(<li class="page-item next">#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'}</li>)
88
+ %(<li class="page-item next">#{
89
+ a.(p_next, pagy_t('pagy.next'), classes: 'page-link', aria_label: pagy_t('pagy.aria_label.next'))}</li>)
87
90
  else
88
- %(<li class="page-item next disabled"><a href="#" class="page-link">#{pagy_t 'pagy.nav.next'}</a></li>)
91
+ %(<li class="page-item next disabled"><a role="link" class="page-link" aria-disabled="true" aria-label="#{
92
+ pagy_t('pagy.aria_label.next')}">#{pagy_t('pagy.next')}</a></li>)
89
93
  end
90
94
  end
91
95
  end
@@ -1,92 +1,88 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/bulma
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/bulma
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/extras/frontend_helpers'
4
+ require_relative 'js_tools'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  # Frontend modules are specially optimized for performance.
8
8
  # The resulting code may not look very elegant, but produces the best benchmarks
9
9
  module BulmaExtra
10
10
  # Pagination for bulma: it returns the html with the series of links to the pages
11
- def pagy_bulma_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)
11
+ def pagy_bulma_nav(pagy, id: nil, classes: 'pagy-bulma nav pagination is-centered', aria_label: nil, **vars)
12
+ id = %( id="#{id}") if id
13
+ a = pagy_anchor(pagy)
14
14
 
15
- html = +%(<nav#{p_id} class="pagy-bulma-nav pagination is-centered" aria-label="pagination">)
16
- html << pagy_bulma_prev_next_html(pagy, link)
15
+ html = %(<nav#{id} class="#{classes}" #{nav_aria_label(pagy, aria_label:)}>)
16
+ html << bulma_prev_next_html(pagy, a)
17
17
  html << %(<ul class="pagination-list">)
18
18
  pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
19
19
  html << case item
20
20
  when Integer
21
- %(<li>#{link.call item, pagy.label_for(item), %(class="pagination-link" aria-label="goto page #{item}")}</li>)
21
+ %(<li>#{a.(item, pagy.label_for(item), classes: 'pagination-link')}</li>)
22
22
  when String
23
- %(<li>#{link.call item, pagy.label_for(item),
24
- %(class="pagination-link is-current" aria-label="page #{item}" aria-current="page")}</li>)
23
+ %(<li><a role="link" class="pagination-link is-current" aria-current="page" aria-disabled="true">#{
24
+ pagy.label_for(item)}</a></li>)
25
25
  when :gap
26
- %(<li><span class="pagination-ellipsis">#{pagy_t 'pagy.nav.gap'}</span></li>)
26
+ %(<li><span class="pagination-ellipsis">#{pagy_t 'pagy.gap'}</span></li>)
27
27
  else raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
28
28
  end
29
29
  end
30
30
  html << %(</ul></nav>)
31
31
  end
32
32
 
33
- # Javascript pagination for bulma: it returns a nav and a JSON tag used by the Pagy.nav javascript
34
- def pagy_bulma_nav_js(pagy, pagy_id: nil, link_extra: '', **vars)
33
+ # Javascript pagination for bulma: it returns a nav with a data-pagy attribute used by the Pagy.nav javascript
34
+ def pagy_bulma_nav_js(pagy, id: nil, classes: 'pagy-bulma nav-js pagination is-centered', aria_label: nil, **vars)
35
35
  sequels = pagy.sequels(**vars)
36
- p_id = %( id="#{pagy_id}") if pagy_id
37
- link = pagy_link_proc(pagy, link_extra: link_extra)
38
- tags = { 'before' => %(#{pagy_bulma_prev_next_html(pagy, link)}<ul class="pagination-list">),
39
- 'link' => %(<li>#{link.call PAGE_PLACEHOLDER, LABEL_PLACEHOLDER,
40
- %(class="pagination-link" aria-label="goto page #{PAGE_PLACEHOLDER}")}</li>),
41
- 'active' => %(<li>#{link.call PAGE_PLACEHOLDER, LABEL_PLACEHOLDER,
42
- %(class="pagination-link is-current" aria-current="page" aria-label="page #{
43
- PAGE_PLACEHOLDER}")}</li>),
44
- 'gap' => %(<li><span class="pagination-ellipsis">#{pagy_t 'pagy.nav.gap'}</span></li>),
45
- 'after' => '</ul>' }
36
+ id = %( id="#{id}") if id
37
+ a = pagy_anchor(pagy)
38
+ tokens = { 'before' => %(#{bulma_prev_next_html(pagy, a)}<ul class="pagination-list">),
39
+ 'a' => %(<li>#{a.(PAGE_TOKEN, LABEL_TOKEN, classes: 'pagination-link')}</li>),
40
+ 'current' => %(<li><a role="link" class="pagination-link is-current" aria-current="page" aria-disabled="true">#{
41
+ LABEL_TOKEN}</a></li>),
42
+ 'gap' => %(<li><span class="pagination-ellipsis">#{pagy_t 'pagy.gap'}</span></li>),
43
+ 'after' => '</ul>' }
46
44
 
47
- %(<nav#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-bulma-nav-js pagination is-centered" aria-label="pagination" #{
48
- pagy_json_attr(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></nav>)
45
+ %(<nav#{id} class="#{'pagy-rjs ' if sequels.size > 1}#{classes}" #{
46
+ nav_aria_label(pagy, aria_label:)} #{
47
+ pagy_data(pagy, :nav, tokens, sequels, pagy.label_sequels(sequels))
48
+ }></nav>)
49
49
  end
50
50
 
51
- # Javascript combo pagination for bulma: it returns a nav and a JSON tag used by the pagy.js file
52
- def pagy_bulma_combo_nav_js(pagy, pagy_id: nil, link_extra: '')
53
- p_id = %( id="#{pagy_id}") if pagy_id
54
- link = pagy_link_proc(pagy, link_extra: link_extra)
55
- p_page = pagy.page
56
- p_pages = pagy.pages
57
- input = %(<input class="input" type="number" min="1" max="#{p_pages}" value="#{
58
- p_page}" style="padding: 0; text-align: center; width: #{p_pages.to_s.length + 1}rem; margin:0 0.3rem;">)
51
+ # Javascript combo pagination for bulma: it returns a nav with a data-pagy attribute used by the pagy.js file
52
+ def pagy_bulma_combo_nav_js(pagy, id: nil, classes: 'pagy-bulma combo-nav-js pagination is-centered', aria_label: nil)
53
+ id = %( id="#{id}") if id
54
+ a = pagy_anchor(pagy)
55
+ pages = pagy.pages
59
56
 
60
- html = %(<nav#{p_id} class="pagy-bulma-combo-nav-js" aria-label="pagination">)
61
- %(#{html}<div class="field is-grouped is-grouped-centered" role="group" #{
62
- pagy_json_attr pagy, :combo, pagy_marked_link(link)}>#{
63
- if (p_prev = pagy.prev)
64
- %(<p class="control">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'class="button" aria-label="previous page"'}</p>)
65
- else
66
- %(<p class="control"><a class="button" disabled>#{pagy_t 'pagy.nav.prev'}</a></p>)
67
- end
68
- }<div class="pagy-combo-input control level is-mobile">#{
69
- pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages}</div>#{
70
- if (p_next = pagy.next)
71
- %(<p class="control">#{link.call p_next, pagy_t('pagy.nav.next'), 'class="button" aria-label="next page"'}</p>)
72
- else
73
- %(<p class="control"><a class="button" disabled>#{pagy_t 'pagy.nav.next'}</a></p>)
74
- end
75
- }</div></nav>)
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; height: 1.7rem; margin:0 0.3rem; ) <<
59
+ %(border: none; border-radius: 4px; padding: 0; font-size: 1.1rem; color: white; ) <<
60
+ %(background-color: #485fc7;">#{JSTools::A_TAG})
61
+
62
+ %(<nav#{id} class="#{classes}" #{
63
+ nav_aria_label(pagy, aria_label:)} #{
64
+ pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))
65
+ }>#{
66
+ bulma_prev_next_html(pagy, a)
67
+ }<ul class="pagination-list"><li class="pagination-link"><label>#{
68
+ pagy_t('pagy.combo_nav_js', page_input:, pages:)
69
+ }</label></li></ul></nav>)
76
70
  end
77
71
 
78
72
  private
79
73
 
80
- def pagy_bulma_prev_next_html(pagy, link)
81
- html = +if (p_prev = pagy.prev)
82
- link.call p_prev, pagy_t('pagy.nav.prev'), 'class="pagination-previous" aria-label="previous page"'
83
- else
84
- %(<a class="pagination-previous" disabled>#{pagy_t 'pagy.nav.prev'}</a>)
85
- end
74
+ def bulma_prev_next_html(pagy, a)
75
+ html = if (p_prev = pagy.prev)
76
+ a.(p_prev, pagy_t('pagy.prev'), classes: 'pagination-previous', aria_label: pagy_t('pagy.aria_label.prev'))
77
+ else
78
+ %(<a role="link" class="pagination-previous" disabled aria-disabled="true" aria-label="#{
79
+ pagy_t('pagy.aria_label.prev')}">#{pagy_t 'pagy.prev'}</a>)
80
+ end
86
81
  html << if (p_next = pagy.next)
87
- link.call p_next, pagy_t('pagy.nav.next'), 'class="pagination-next" aria-label="next page"'
82
+ a.(p_next, pagy_t('pagy.next'), classes: 'pagination-next', aria_label: pagy_t('pagy.aria_label.next'))
88
83
  else
89
- %(<a class="pagination-next" disabled>#{pagy_t 'pagy.nav.next'}</a>)
84
+ %(<a role="link" class="pagination-next" disabled aria-disabled="true" aria-label="#{
85
+ pagy_t('pagy.aria_label.next')}">#{pagy_t('pagy.next')}</a>)
90
86
  end
91
87
  end
92
88
  end
@@ -1,66 +1,83 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/calendar
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/calendar
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/calendar'
4
+ require_relative '../calendar'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  # Add pagination filtering by calendar unit (:year, :quarter, :month, :week, :day) to the regular pagination
8
8
  module CalendarExtra
9
9
  # Additions for the Backend module
10
- module Backend
10
+ module BackendAddOn
11
11
  CONF_KEYS = (Calendar::UNITS + %i[pagy active]).freeze
12
12
 
13
13
  private
14
14
 
15
15
  # Take a collection and a conf Hash with keys in CONF_KEYS and return an array with 3 items: [calendar, pagy, results]
16
16
  def pagy_calendar(collection, conf)
17
- unless conf.is_a?(Hash) && (conf.keys - CONF_KEYS).empty? && conf.all? { |k, v| v.is_a?(Hash) || k == :active }
18
- raise ArgumentError, "keys must be in #{CONF_KEYS.inspect} and object values must be Hashes; got #{conf.inspect}"
19
- end
20
-
21
- conf[:pagy] = {} unless conf[:pagy] # use default Pagy object when omitted
22
- calendar, collection = pagy_setup_calendar(collection, conf) unless conf.key?(:active) && !conf[:active]
23
- pagy, results = send(conf[:pagy][:backend] || :pagy, collection, conf[:pagy]) # use backend: :pagy when omitted
24
- [calendar, pagy, results]
25
- end
17
+ raise ArgumentError, "keys must be in #{CONF_KEYS.inspect}" \
18
+ unless conf.is_a?(Hash) && (conf.keys - CONF_KEYS).empty?
26
19
 
27
- # Setup and return the calendar objects and the filtered collection
28
- def pagy_setup_calendar(collection, conf)
29
- units = Calendar::UNITS & conf.keys # get the units in time length desc order
30
- raise ArgumentError, 'no calendar unit found in pagy_calendar configuration' if units.empty?
31
-
32
- page_param = conf[:pagy][:page_param] || DEFAULT[:page_param]
33
- units.each do |unit| # set all the :page_param vars for later deletion
34
- unit_page_param = :"#{unit}_#{page_param}"
35
- conf[unit][:page_param] = unit_page_param
36
- conf[unit][:page] = params[unit_page_param]
37
- end
38
- calendar = {}
39
- last_obj = nil
40
- units.each_with_index do |unit, index|
41
- params_to_delete = units[(index + 1), units.size].map { |sub| conf[sub][:page_param] } + [page_param]
42
- conf[unit][:params] = lambda do |params| # delete page_param from the sub-units
43
- params_to_delete.each { |p| params.delete(p.to_s) } # Hash#except missing from ruby 2.5 baseline
44
- params
45
- end
46
- conf[unit][:period] = last_obj&.send(:active_period) || pagy_calendar_period(collection)
47
- calendar[unit] = last_obj = Calendar.send(:create, unit, conf[unit])
20
+ conf[:pagy] ||= {}
21
+ unless conf.key?(:active) && !conf[:active]
22
+ calendar, from, to = Calendar.send(:init, conf, pagy_calendar_period(collection), params)
23
+ if respond_to?(:pagy_calendar_counts)
24
+ calendar.each_key do |unit|
25
+ calendar[unit].vars[:counts] = pagy_calendar_counts(collection, unit, *calendar[unit].vars[:period])
26
+ end
27
+ end
28
+ collection = pagy_calendar_filter(collection, from, to)
48
29
  end
49
- [calendar, pagy_calendar_filter(collection, last_obj.from, last_obj.to)]
30
+ pagy, results = send(conf[:pagy][:backend] || :pagy, collection, conf[:pagy]) # use backend: :pagy when omitted
31
+ [calendar, pagy, results]
50
32
  end
51
33
 
52
34
  # This method must be implemented by the application
53
35
  def pagy_calendar_period(*)
54
36
  raise NoMethodError, 'the pagy_calendar_period method must be implemented by the application ' \
55
- '(see https://ddnexus.github.io/pagy/extras/calendar#pagy_calendar_periodcollection)'
37
+ '(see https://ddnexus.github.io/pagy/docs/extras/calendar/#pagy-calendar-period-collection)'
56
38
  end
57
39
 
58
40
  # This method must be implemented by the application
59
41
  def pagy_calendar_filter(*)
60
42
  raise NoMethodError, 'the pagy_calendar_filter method must be implemented by the application ' \
61
- '(see https://ddnexus.github.io/pagy/extras/calendar#pagy_calendar_filtercollection-from-to)'
43
+ '(see https://ddnexus.github.io/pagy/docs/extras/calendar/#pagy-calendar-filter-collection-from-to)'
44
+ end
45
+ end
46
+
47
+ # Override the pagy_anchor
48
+ module FrontendOverride
49
+ # Consider the vars[:count]
50
+ def pagy_anchor(pagy)
51
+ return super unless (counts = pagy.vars[:counts])
52
+
53
+ a_string = pagy.vars[:anchor_string]
54
+ a_string = %( #{a_string}) if a_string
55
+ left, right = %(<a#{a_string} href="#{pagy_url_for(pagy, PAGE_TOKEN)}").split(PAGE_TOKEN, 2)
56
+ # lambda used by all the helpers
57
+ lambda do |page, text = pagy.label_for(page), classes: nil, aria_label: nil|
58
+ count = counts[page - 1]
59
+ item_name = pagy_t('pagy.item_name', count:)
60
+ if count.zero?
61
+ classes = "#{classes && (classes + ' ')}empty-page"
62
+ title = %( title="#{pagy_t('pagy.info.no_items', item_name:, count:)}")
63
+ else
64
+ title = %( title="#{pagy_t('pagy.info.single_page', item_name:, count:)}")
65
+ end
66
+ classes = %( class="#{classes}") if classes
67
+ aria_label = %( aria-label="#{aria_label}") if aria_label
68
+ %(#{left}#{page}#{right}#{title}#{classes}#{aria_label}>#{text}</a>)
69
+ end
70
+ end
71
+ end
72
+
73
+ # Additions for the Frontend module
74
+ module UrlHelperAddOn
75
+ # Return the url for the calendar page at time
76
+ def pagy_calendar_url_at(calendar, time, **opts)
77
+ pagy_url_for(calendar.send(:calendar_at, time, **opts), 1, **opts)
62
78
  end
63
79
  end
64
80
  end
65
- Backend.prepend CalendarExtra::Backend
81
+ Backend.prepend CalendarExtra::BackendAddOn, CalendarExtra::UrlHelperAddOn
82
+ Frontend.prepend CalendarExtra::UrlHelperAddOn, CalendarExtra::FrontendOverride
66
83
  end
@@ -1,7 +1,7 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/countless
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/countless
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/countless'
4
+ require_relative '../countless'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  DEFAULT[:countless_minimal] = false
@@ -19,7 +19,7 @@ class Pagy # :nodoc:
19
19
  # Sub-method called only by #pagy_countless: here for easy customization of variables by overriding
20
20
  def pagy_countless_get_vars(_collection, vars)
21
21
  pagy_set_items_from_params(vars) if defined?(ItemsExtra)
22
- vars[:page] ||= params[vars[:page_param] || DEFAULT[:page_param]]
22
+ vars[:page] ||= pagy_get_page(vars)
23
23
  vars
24
24
  end
25
25
 
@@ -1,8 +1,9 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/elasticsearch_rails
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/elasticsearch_rails
2
2
  # frozen_string_literal: true
3
3
 
4
4
  class Pagy # :nodoc:
5
- DEFAULT[:elasticsearch_rails_search_method] ||= :pagy_search
5
+ DEFAULT[:elasticsearch_rails_search] ||= :search
6
+ DEFAULT[:elasticsearch_rails_pagy_search] ||= :pagy_search
6
7
 
7
8
  # Paginate ElasticsearchRails response objects
8
9
  module ElasticsearchRailsExtra
@@ -18,7 +19,7 @@ class Pagy # :nodoc:
18
19
  total.is_a?(Hash) ? total['value'] : total
19
20
  end
20
21
 
21
- module ElasticsearchRails # :nodoc:
22
+ module ModelExtension # :nodoc:
22
23
  # Return an array used to delay the call of #search
23
24
  # after the pagination variables are merged to the options.
24
25
  # It also pushes to the same array an optional method call.
@@ -27,11 +28,12 @@ class Pagy # :nodoc:
27
28
  args.define_singleton_method(:method_missing) { |*a| args += a }
28
29
  end
29
30
  end
30
- alias_method Pagy::DEFAULT[:elasticsearch_rails_search_method], :pagy_elasticsearch_rails
31
+ alias_method Pagy::DEFAULT[:elasticsearch_rails_pagy_search], :pagy_elasticsearch_rails
31
32
  end
33
+ Pagy::ElasticsearchRails = ModelExtension
32
34
 
33
35
  # Additions for the Pagy class
34
- module Pagy
36
+ module PagyAddOn
35
37
  # Create a Pagy object from an Elasticsearch::Model::Response::Response object
36
38
  def new_from_elasticsearch_rails(response, vars = {})
37
39
  vars[:items] = response.search.options[:size] || 10
@@ -40,9 +42,10 @@ class Pagy # :nodoc:
40
42
  new(vars)
41
43
  end
42
44
  end
45
+ Pagy.extend PagyAddOn
43
46
 
44
47
  # Add specialized backend methods to paginate ElasticsearchRails searches
45
- module Backend
48
+ module BackendAddOn
46
49
  private
47
50
 
48
51
  # Return Pagy object and items
@@ -52,7 +55,7 @@ class Pagy # :nodoc:
52
55
  vars = pagy_elasticsearch_rails_get_vars(nil, vars)
53
56
  options[:size] = vars[:items]
54
57
  options[:from] = vars[:items] * (vars[:page] - 1)
55
- response = model.search(query_or_payload, **options)
58
+ response = model.send(DEFAULT[:elasticsearch_rails_search], query_or_payload, **options)
56
59
  vars[:count] = ElasticsearchRailsExtra.total_count(response)
57
60
 
58
61
  pagy = ::Pagy.new(vars)
@@ -68,12 +71,10 @@ class Pagy # :nodoc:
68
71
  def pagy_elasticsearch_rails_get_vars(_collection, vars)
69
72
  pagy_set_items_from_params(vars) if defined?(ItemsExtra)
70
73
  vars[:items] ||= DEFAULT[:items]
71
- vars[:page] ||= (params[vars[:page_param] || DEFAULT[:page_param]] || 1).to_i
74
+ vars[:page] ||= pagy_get_page(vars)
72
75
  vars
73
76
  end
74
77
  end
78
+ Backend.prepend BackendAddOn
75
79
  end
76
- ElasticsearchRails = ElasticsearchRailsExtra::ElasticsearchRails
77
- extend ElasticsearchRailsExtra::Pagy
78
- Backend.prepend ElasticsearchRailsExtra::Backend
79
80
  end