pagy 7.0.11 → 43.5.1

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 (211) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/apps/calendar.ru +741 -0
  4. data/apps/demo.ru +513 -0
  5. data/apps/enable_rails_page_segment.rb +54 -0
  6. data/apps/index.rb +9 -0
  7. data/apps/keynav+root_key.ru +316 -0
  8. data/apps/keynav.ru +255 -0
  9. data/apps/keyset.ru +219 -0
  10. data/apps/keyset_sequel.ru +212 -0
  11. data/apps/rails.ru +216 -0
  12. data/apps/repro.ru +185 -0
  13. data/bin/pagy +5 -0
  14. data/config/pagy.rb +46 -0
  15. data/javascripts/ai_widget.js +90 -0
  16. data/javascripts/pagy.js +168 -0
  17. data/javascripts/pagy.min.js +2 -0
  18. data/javascripts/pagy.mjs +161 -0
  19. data/javascripts/wand.js +1172 -0
  20. data/lib/pagy/classes/calendar/calendar.rb +101 -0
  21. data/lib/pagy/{calendar → classes/calendar}/day.rb +9 -12
  22. data/lib/pagy/{calendar → classes/calendar}/month.rb +7 -11
  23. data/lib/pagy/{calendar → classes/calendar}/quarter.rb +12 -16
  24. data/lib/pagy/classes/calendar/unit.rb +93 -0
  25. data/lib/pagy/{calendar → classes/calendar}/week.rb +7 -11
  26. data/lib/pagy/{calendar → classes/calendar}/year.rb +9 -9
  27. data/lib/pagy/classes/exceptions.rb +26 -0
  28. data/lib/pagy/classes/keyset/adapters/active_record.rb +50 -0
  29. data/lib/pagy/classes/keyset/adapters/sequel.rb +62 -0
  30. data/lib/pagy/classes/keyset/keynav.rb +85 -0
  31. data/lib/pagy/classes/keyset/keyset.rb +150 -0
  32. data/lib/pagy/classes/offset/countish.rb +17 -0
  33. data/lib/pagy/classes/offset/countless.rb +63 -0
  34. data/lib/pagy/classes/offset/offset.rb +63 -0
  35. data/lib/pagy/classes/offset/search.rb +34 -0
  36. data/lib/pagy/classes/request.rb +48 -0
  37. data/lib/pagy/cli.rb +122 -0
  38. data/lib/pagy/console.rb +5 -20
  39. data/lib/pagy/deprecated.rb +84 -0
  40. data/lib/pagy/modules/abilities/configurable.rb +37 -0
  41. data/lib/pagy/modules/abilities/countable.rb +23 -0
  42. data/lib/pagy/modules/abilities/linkable.rb +72 -0
  43. data/lib/pagy/modules/abilities/rangeable.rb +14 -0
  44. data/lib/pagy/modules/abilities/shiftable.rb +12 -0
  45. data/lib/pagy/modules/b64.rb +35 -0
  46. data/lib/pagy/modules/console.rb +33 -0
  47. data/lib/pagy/modules/i18n/i18n.rb +72 -0
  48. data/lib/pagy/modules/i18n/p11n/arabic.rb +30 -0
  49. data/lib/pagy/modules/i18n/p11n/east_slavic.rb +27 -0
  50. data/lib/pagy/modules/i18n/p11n/one_other.rb +15 -0
  51. data/lib/pagy/modules/i18n/p11n/one_upto_two_other.rb +15 -0
  52. data/lib/pagy/modules/i18n/p11n/other.rb +13 -0
  53. data/lib/pagy/modules/i18n/p11n/polish.rb +27 -0
  54. data/lib/pagy/modules/i18n/p11n/west_slavic.rb +22 -0
  55. data/lib/pagy/modules/i18n/p11n.rb +16 -0
  56. data/lib/pagy/modules/searcher.rb +20 -0
  57. data/lib/pagy/next.rb +25 -0
  58. data/lib/pagy/tasks/sync.rb +20 -0
  59. data/lib/pagy/toolbox/helpers/anchor_tags.rb +21 -0
  60. data/lib/pagy/toolbox/helpers/bootstrap/input_nav_js.rb +28 -0
  61. data/lib/pagy/toolbox/helpers/bootstrap/previous_next_html.rb +19 -0
  62. data/lib/pagy/toolbox/helpers/bootstrap/series_nav.rb +32 -0
  63. data/lib/pagy/toolbox/helpers/bootstrap/series_nav_js.rb +24 -0
  64. data/lib/pagy/toolbox/helpers/bulma/input_nav_js.rb +25 -0
  65. data/lib/pagy/toolbox/helpers/bulma/previous_next_html.rb +20 -0
  66. data/lib/pagy/toolbox/helpers/bulma/series_nav.rb +31 -0
  67. data/lib/pagy/toolbox/helpers/bulma/series_nav_js.rb +23 -0
  68. data/lib/pagy/toolbox/helpers/data_hash.rb +29 -0
  69. data/lib/pagy/toolbox/helpers/headers_hash.rb +30 -0
  70. data/lib/pagy/toolbox/helpers/info_tag.rb +30 -0
  71. data/lib/pagy/toolbox/helpers/input_nav_js.rb +22 -0
  72. data/lib/pagy/toolbox/helpers/limit_tag_js.rb +25 -0
  73. data/lib/pagy/toolbox/helpers/loaders.rb +55 -0
  74. data/lib/pagy/toolbox/helpers/page_url.rb +16 -0
  75. data/lib/pagy/toolbox/helpers/series_nav.rb +30 -0
  76. data/lib/pagy/toolbox/helpers/series_nav_js.rb +20 -0
  77. data/lib/pagy/toolbox/helpers/support/a_lambda.rb +36 -0
  78. data/lib/pagy/toolbox/helpers/support/data_pagy_attribute.rb +19 -0
  79. data/lib/pagy/toolbox/helpers/support/nav_aria_label_attribute.rb +10 -0
  80. data/lib/pagy/toolbox/helpers/support/series.rb +37 -0
  81. data/lib/pagy/toolbox/helpers/support/wrap_input_nav_js.rb +19 -0
  82. data/lib/pagy/toolbox/helpers/support/wrap_series_nav.rb +17 -0
  83. data/lib/pagy/toolbox/helpers/support/wrap_series_nav_js.rb +42 -0
  84. data/lib/pagy/toolbox/helpers/urls_hash.rb +12 -0
  85. data/lib/pagy/toolbox/paginators/calendar.rb +34 -0
  86. data/lib/pagy/toolbox/paginators/countish.rb +38 -0
  87. data/lib/pagy/toolbox/paginators/countless.rb +22 -0
  88. data/lib/pagy/toolbox/paginators/elasticsearch_rails.rb +56 -0
  89. data/lib/pagy/toolbox/paginators/keynav_js.rb +26 -0
  90. data/lib/pagy/toolbox/paginators/keyset.rb +15 -0
  91. data/lib/pagy/toolbox/paginators/meilisearch.rb +34 -0
  92. data/lib/pagy/toolbox/paginators/method.rb +38 -0
  93. data/lib/pagy/toolbox/paginators/offset.rb +24 -0
  94. data/lib/pagy/toolbox/paginators/searchkick.rb +34 -0
  95. data/lib/pagy/toolbox/paginators/typesense_rails.rb +34 -0
  96. data/lib/pagy.rb +67 -131
  97. data/locales/ar.yml +32 -0
  98. data/locales/be.yml +28 -0
  99. data/locales/bg.yml +24 -0
  100. data/locales/bs.yml +28 -0
  101. data/locales/ca.yml +24 -0
  102. data/locales/ckb.yml +20 -0
  103. data/locales/cs.yml +26 -0
  104. data/locales/da.yml +24 -0
  105. data/locales/de.yml +24 -0
  106. data/locales/dz.yml +20 -0
  107. data/locales/en.yml +24 -0
  108. data/{lib/locales → locales}/es.yml +9 -6
  109. data/locales/fr.yml +24 -0
  110. data/locales/hr.yml +28 -0
  111. data/locales/id.yml +20 -0
  112. data/locales/it.yml +24 -0
  113. data/locales/ja.yml +20 -0
  114. data/locales/km.yml +20 -0
  115. data/locales/ko.yml +20 -0
  116. data/locales/nb.yml +24 -0
  117. data/locales/nl.yml +24 -0
  118. data/locales/nn.yml +24 -0
  119. data/locales/pl.yml +28 -0
  120. data/{lib/locales → locales}/pt-BR.yml +10 -7
  121. data/{lib/locales → locales}/pt.yml +10 -7
  122. data/locales/ru.yml +28 -0
  123. data/locales/sk.yml +26 -0
  124. data/locales/sr.yml +28 -0
  125. data/locales/sv-SE.yml +24 -0
  126. data/locales/sv.yml +24 -0
  127. data/locales/sw.yml +28 -0
  128. data/locales/ta.yml +24 -0
  129. data/locales/tr.yml +24 -0
  130. data/locales/uk.yml +28 -0
  131. data/locales/vi.yml +20 -0
  132. data/locales/zh-CN.yml +20 -0
  133. data/locales/zh-HK.yml +20 -0
  134. data/locales/zh-TW.yml +20 -0
  135. data/stylesheets/pagy-tailwind.css +68 -0
  136. data/stylesheets/pagy.css +83 -0
  137. metadata +185 -94
  138. data/lib/config/pagy.rb +0 -258
  139. data/lib/javascripts/pagy-dev.js +0 -112
  140. data/lib/javascripts/pagy-module.js +0 -111
  141. data/lib/javascripts/pagy.js +0 -1
  142. data/lib/locales/ar.yml +0 -30
  143. data/lib/locales/be.yml +0 -25
  144. data/lib/locales/bg.yml +0 -21
  145. data/lib/locales/bs.yml +0 -25
  146. data/lib/locales/ca.yml +0 -23
  147. data/lib/locales/ckb.yml +0 -18
  148. data/lib/locales/cs.yml +0 -23
  149. data/lib/locales/da.yml +0 -23
  150. data/lib/locales/de.yml +0 -21
  151. data/lib/locales/en.yml +0 -21
  152. data/lib/locales/fr.yml +0 -21
  153. data/lib/locales/hr.yml +0 -25
  154. data/lib/locales/id.yml +0 -19
  155. data/lib/locales/it.yml +0 -21
  156. data/lib/locales/ja.yml +0 -19
  157. data/lib/locales/km.yml +0 -19
  158. data/lib/locales/ko.yml +0 -19
  159. data/lib/locales/nb.yml +0 -21
  160. data/lib/locales/nl.yml +0 -21
  161. data/lib/locales/nn.yml +0 -21
  162. data/lib/locales/pl.yml +0 -25
  163. data/lib/locales/ru.yml +0 -27
  164. data/lib/locales/sr.yml +0 -25
  165. data/lib/locales/sv-SE.yml +0 -21
  166. data/lib/locales/sv.yml +0 -21
  167. data/lib/locales/sw.yml +0 -23
  168. data/lib/locales/ta.yml +0 -23
  169. data/lib/locales/tr.yml +0 -19
  170. data/lib/locales/uk.yml +0 -25
  171. data/lib/locales/vi.yml +0 -17
  172. data/lib/locales/zh-CN.yml +0 -19
  173. data/lib/locales/zh-HK.yml +0 -19
  174. data/lib/locales/zh-TW.yml +0 -19
  175. data/lib/pagy/backend.rb +0 -39
  176. data/lib/pagy/calendar/helper.rb +0 -65
  177. data/lib/pagy/calendar.rb +0 -126
  178. data/lib/pagy/countless.rb +0 -37
  179. data/lib/pagy/exceptions.rb +0 -25
  180. data/lib/pagy/extras/arel.rb +0 -36
  181. data/lib/pagy/extras/array.rb +0 -24
  182. data/lib/pagy/extras/bootstrap.rb +0 -108
  183. data/lib/pagy/extras/bulma.rb +0 -105
  184. data/lib/pagy/extras/calendar.rb +0 -53
  185. data/lib/pagy/extras/countless.rb +0 -37
  186. data/lib/pagy/extras/elasticsearch_rails.rb +0 -80
  187. data/lib/pagy/extras/foundation.rb +0 -105
  188. data/lib/pagy/extras/frontend_helpers.rb +0 -67
  189. data/lib/pagy/extras/gearbox.rb +0 -54
  190. data/lib/pagy/extras/headers.rb +0 -53
  191. data/lib/pagy/extras/i18n.rb +0 -26
  192. data/lib/pagy/extras/items.rb +0 -61
  193. data/lib/pagy/extras/jsonapi.rb +0 -79
  194. data/lib/pagy/extras/materialize.rb +0 -96
  195. data/lib/pagy/extras/meilisearch.rb +0 -65
  196. data/lib/pagy/extras/metadata.rb +0 -38
  197. data/lib/pagy/extras/navs.rb +0 -51
  198. data/lib/pagy/extras/overflow.rb +0 -80
  199. data/lib/pagy/extras/searchkick.rb +0 -67
  200. data/lib/pagy/extras/semantic.rb +0 -95
  201. data/lib/pagy/extras/standalone.rb +0 -60
  202. data/lib/pagy/extras/support.rb +0 -40
  203. data/lib/pagy/extras/trim.rb +0 -29
  204. data/lib/pagy/extras/uikit.rb +0 -97
  205. data/lib/pagy/frontend.rb +0 -114
  206. data/lib/pagy/i18n.rb +0 -165
  207. data/lib/pagy/url_helpers.rb +0 -27
  208. data/lib/stylesheets/pagy.css +0 -61
  209. data/lib/stylesheets/pagy.scss +0 -50
  210. data/lib/stylesheets/pagy.tailwind.scss +0 -24
  211. /data/{lib/javascripts/pagy-module.d.ts → javascripts/pagy.d.ts} +0 -0
@@ -1,80 +0,0 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/elasticsearch_rails
2
- # frozen_string_literal: true
3
-
4
- class Pagy # :nodoc:
5
- DEFAULT[:elasticsearch_rails_search] ||= :search
6
- DEFAULT[:elasticsearch_rails_pagy_search] ||= :pagy_search
7
-
8
- # Paginate ElasticsearchRails response objects
9
- module ElasticsearchRailsExtra
10
- module_function
11
-
12
- # Get the count from different version of ElasticsearchRails
13
- def total_count(response)
14
- total = if response.respond_to?(:raw_response)
15
- response.raw_response['hits']['total']
16
- else
17
- response.response['hits']['total']
18
- end
19
- total.is_a?(Hash) ? total['value'] : total
20
- end
21
-
22
- module ModelExtension # :nodoc:
23
- # Return an array used to delay the call of #search
24
- # after the pagination variables are merged to the options.
25
- # It also pushes to the same array an optional method call.
26
- def pagy_elasticsearch_rails(query_or_payload, **options)
27
- [self, query_or_payload, options].tap do |args|
28
- args.define_singleton_method(:method_missing) { |*a| args += a }
29
- end
30
- end
31
- alias_method Pagy::DEFAULT[:elasticsearch_rails_pagy_search], :pagy_elasticsearch_rails
32
- end
33
- Pagy::ElasticsearchRails = ModelExtension
34
-
35
- # Additions for the Pagy class
36
- module PagyAddOn
37
- # Create a Pagy object from an Elasticsearch::Model::Response::Response object
38
- def new_from_elasticsearch_rails(response, vars = {})
39
- vars[:items] = response.search.options[:size] || 10
40
- vars[:page] = ((response.search.options[:from] || 0) / vars[:items]) + 1
41
- vars[:count] = ElasticsearchRailsExtra.total_count(response)
42
- new(vars)
43
- end
44
- end
45
- Pagy.extend PagyAddOn
46
-
47
- # Add specialized backend methods to paginate ElasticsearchRails searches
48
- module BackendAddOn
49
- private
50
-
51
- # Return Pagy object and items
52
- def pagy_elasticsearch_rails(pagy_search_args, vars = {})
53
- model, query_or_payload,
54
- options, *called = pagy_search_args
55
- vars = pagy_elasticsearch_rails_get_vars(nil, vars)
56
- options[:size] = vars[:items]
57
- options[:from] = vars[:items] * (vars[:page] - 1)
58
- response = model.send(DEFAULT[:elasticsearch_rails_search], query_or_payload, **options)
59
- vars[:count] = ElasticsearchRailsExtra.total_count(response)
60
-
61
- pagy = ::Pagy.new(vars)
62
- # with :last_page overflow we need to re-run the method in order to get the hits
63
- return pagy_elasticsearch_rails(pagy_search_args, vars.merge(page: pagy.page)) \
64
- if defined?(::Pagy::OverflowExtra) && pagy.overflow? && pagy.vars[:overflow] == :last_page
65
-
66
- [pagy, called.empty? ? response : response.send(*called)]
67
- end
68
-
69
- # Sub-method called only by #pagy_elasticsearch_rails: here for easy customization of variables by overriding
70
- # the _collection argument is not available when the method is called
71
- def pagy_elasticsearch_rails_get_vars(_collection, vars)
72
- pagy_set_items_from_params(vars) if defined?(ItemsExtra)
73
- vars[:items] ||= DEFAULT[:items]
74
- vars[:page] ||= pagy_get_page(vars)
75
- vars
76
- end
77
- end
78
- Backend.prepend BackendAddOn
79
- end
80
- end
@@ -1,105 +0,0 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/foundation
2
- # frozen_string_literal: true
3
-
4
- require 'pagy/extras/frontend_helpers'
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 FoundationExtra
10
- # Pagination for Foundation: it returns the html with the series of links to the pages
11
- def pagy_foundation_nav(pagy, pagy_id: nil, link_extra: '',
12
- nav_aria_label: nil, nav_i18n_key: nil, **vars)
13
- p_id = %( id="#{pagy_id}") if pagy_id
14
- link = pagy_link_proc(pagy, link_extra:)
15
-
16
- html = +%(<nav#{p_id} class="pagy-foundation-nav" #{
17
- nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)}><ul class="pagination">)
18
- html << foundation_prev_html(pagy, link)
19
- pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
20
- html << case item
21
- when Integer
22
- %(<li>#{link.call item}</li>)
23
- when String
24
- %(<li class="current" role="link" aria-current="page" aria-disabled="true">#{pagy.label_for(item)}</li>)
25
- when :gap
26
- %(<li class="ellipsis gap"></li>)
27
- else
28
- raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
29
- end
30
- end
31
- html << pagy_foundation_next_html(pagy, link)
32
- html << %(</ul></nav>)
33
- end
34
-
35
- # Javascript pagination for foundation: it returns a nav and a JSON tag used by the pagy.js file
36
- def pagy_foundation_nav_js(pagy, pagy_id: nil, link_extra: '',
37
- nav_aria_label: nil, nav_i18n_key: nil, **vars)
38
- sequels = pagy.sequels(**vars)
39
- p_id = %( id="#{pagy_id}") if pagy_id
40
- link = pagy_link_proc(pagy, link_extra:)
41
- tags = { 'before' => %(<ul class="pagination">#{foundation_prev_html pagy, link}),
42
- 'link' => %(<li>#{link.call(PAGE_TOKEN, LABEL_TOKEN)}</li>),
43
- 'active' => %(<li class="current" role="link" aria-current="page" aria-disabled="true">#{LABEL_TOKEN}</li>),
44
- 'gap' => %(<li class="ellipsis gap"></li>),
45
- 'after' => %(#{pagy_foundation_next_html pagy, link}</ul>) }
46
-
47
- %(<nav#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-foundation-nav-js" #{
48
- nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)} #{
49
- pagy_data(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></nav>)
50
- end
51
-
52
- # Javascript combo pagination for Foundation: it returns a nav and a JSON tag used by the pagy.js file
53
- def pagy_foundation_combo_nav_js(pagy, pagy_id: nil, link_extra: '',
54
- nav_aria_label: nil, nav_i18n_key: nil)
55
- p_id = %( id="#{pagy_id}") if pagy_id
56
- link = pagy_link_proc(pagy, link_extra:)
57
- p_page = pagy.page
58
- p_pages = pagy.pages
59
- input = %(<input name="page" class="input-group-field cell shrink" type="number" min="1" max="#{
60
- p_pages}" value="#{p_page}" style="width: #{
61
- p_pages.to_s.length + 1}rem; padding: 0 0.3rem; margin: 0 0.3rem;" aria-current="page">)
62
-
63
- %(<nav#{p_id} class="pagy-foundation-combo-nav-js" #{
64
- nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)} #{
65
- pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))}><div class="input-group">#{
66
- if (p_prev = pagy.prev)
67
- link.call(p_prev, pagy_t('pagy.prev'),
68
- %(style="margin-bottom: 0" class="prev button primary" #{prev_aria_label_attr}))
69
- else
70
- %(<a style="margin-bottom: 0" class="prev button primary disabled" role="link" aria-disabled="true" #{
71
- prev_aria_label_attr}>#{pagy_t('pagy.prev')}</a>)
72
- end
73
- }#{
74
- pagy_t('pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages)
75
- .sub!('<label>', '<label class="input-group-label">')}#{ # add the class to the official dictionary string
76
- if (p_next = pagy.next)
77
- link.call(p_next, pagy_t('pagy.next'),
78
- %(style="margin-bottom: 0" class="next button primary" #{next_aria_label_attr}))
79
- else
80
- %(<a style="margin-bottom: 0" class="next button primary disabled" role="link" aria-disabled="true" #{
81
- next_aria_label_attr}>#{pagy_t 'pagy.next'}</a>)
82
- end
83
- }</div></nav>)
84
- end
85
-
86
- private
87
-
88
- def foundation_prev_html(pagy, link)
89
- if (p_prev = pagy.prev)
90
- %(<li class="prev">#{link.call(p_prev, pagy_t('pagy.prev'), prev_aria_label_attr)}</li>)
91
- else
92
- %(<li class="prev disabled" role="link" aria-disabled="true" #{prev_aria_label_attr}>#{pagy_t('pagy.prev')}</li>)
93
- end
94
- end
95
-
96
- def pagy_foundation_next_html(pagy, link)
97
- if (p_next = pagy.next)
98
- %(<li class="next">#{link.call(p_next, pagy_t('pagy.next'), next_aria_label_attr)}</li>)
99
- else
100
- %(<li class="next disabled" role="link" aria-disabled="true" #{next_aria_label_attr}>#{pagy_t('pagy.next')}</li>)
101
- end
102
- end
103
- end
104
- Frontend.prepend FoundationExtra
105
- end
@@ -1,67 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Pagy # :nodoc:
4
- DEFAULT[:steps] = false # default false will use {0 => @vars[:size]}
5
-
6
- # Private module documented in the main classes
7
- module FrontendHelpers
8
- # Additions for the Pagy class
9
- module PagyAddOn
10
- # `Pagy` instance method used by the `pagy*_nav_js` helpers.
11
- # It returns the sequels of width/series generated from the :steps hash
12
- # Example:
13
- # >> pagy = Pagy.new(count:1000, page: 20, steps: {0 => [1,2,2,1], 350 => [2,3,3,2], 550 => [3,4,4,3]})
14
- # >> pagy.sequels
15
- # #=> { "0" => [1, :gap, 18, 19, "20", 21, 22, :gap, 50],
16
- # "350" => [1, 2, :gap, 17, 18, 19, "20", 21, 22, 23, :gap, 49, 50],
17
- # "550" => [1, 2, 3, :gap, 16, 17, 18, 19, "20", 21, 22, 23, 24, :gap, 48, 49, 50] }
18
- # Notice: if :steps is false it will use the single {0 => @vars[:size]} size
19
- def sequels(steps: @vars[:steps] || { 0 => @vars[:size] }, **_)
20
- raise VariableError.new(self, :steps, 'to define the 0 width', steps) unless steps.key?(0)
21
-
22
- {}.tap do |sequels|
23
- steps.each { |width, step_size| sequels[width.to_s] = series(size: step_size) }
24
- end
25
- end
26
-
27
- # Support for the Calendar API
28
- def label_sequels(*); end
29
- end
30
- Pagy.prepend PagyAddOn
31
-
32
- # Additions for Calendar class
33
- module CalendarOverride
34
- def label_sequels(sequels = self.sequels)
35
- {}.tap do |label_sequels|
36
- sequels.each do |width, series|
37
- label_sequels[width] = series.map { |item| item == :gap ? :gap : label_for(item) }
38
- end
39
- end
40
- end
41
- end
42
- Calendar.prepend CalendarOverride if defined?(Calendar)
43
-
44
- # Additions for the Frontend
45
- module FrontendAddOn
46
- if defined?(Oj)
47
- # Return a data tag with the base64 encoded JSON-serialized args generated with the faster oj gem
48
- # Base64 encoded JSON is smaller than HTML escaped JSON
49
- def pagy_data(pagy, *args)
50
- args << pagy.vars[:page_param] if pagy.vars[:trim_extra]
51
- strict_base64_encoded = [Oj.dump(args, mode: :strict)].pack('m0')
52
- %(data-pagy="#{strict_base64_encoded}")
53
- end
54
- else
55
- require 'json'
56
- # Return a data tag with the base64 encoded JSON-serialized args generated with the slower to_json
57
- # Base64 encoded JSON is smaller than HTML escaped JSON
58
- def pagy_data(pagy, *args)
59
- args << pagy.vars[:page_param] if pagy.vars[:trim_extra]
60
- strict_base64_encoded = [args.to_json].pack('m0')
61
- %(data-pagy="#{strict_base64_encoded}")
62
- end
63
- end
64
- end
65
- Frontend.prepend FrontendAddOn
66
- end
67
- end
@@ -1,54 +0,0 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/gearbox
2
- # frozen_string_literal: true
3
-
4
- class Pagy # :nodoc:
5
- DEFAULT[:gearbox_extra] = true # extra enabled by default
6
- DEFAULT[:gearbox_items] = [15, 30, 60, 100]
7
-
8
- # Automatically change the number of items per page depending on the page number
9
- # accepts an array as the :gearbox_items variable, that will determine the items for the first pages
10
- module GearboxExtra
11
- # Setup @items based on the :gearbox_items variable
12
- def setup_items_var
13
- return super if !@vars[:gearbox_extra] || @vars[:items_extra]
14
-
15
- gearbox_items = @vars[:gearbox_items]
16
- raise VariableError.new(self, :gearbox_items, 'to be an Array of positives', gearbox_items) \
17
- unless gearbox_items.is_a?(Array) && gearbox_items.all? { |num| num.positive? rescue false } # rubocop:disable Style/RescueModifier
18
-
19
- @items = gearbox_items[@page - 1] || gearbox_items.last
20
- end
21
-
22
- # Setup @pages and @last based on the :gearbox_items variable (not used by Pagy::Countless)
23
- def setup_pages_var
24
- return super if !@vars[:gearbox_extra] || @vars[:items_extra]
25
-
26
- gearbox_items = @vars[:gearbox_items]
27
- # This algorithm is thousands of times faster than the one in the geared_pagination gem
28
- @pages = @last = (if @count > (sum = gearbox_items.sum)
29
- [((@count - sum).to_f / gearbox_items.last).ceil, 1].max + gearbox_items.count
30
- else
31
- pages = 0
32
- remainder = @count
33
- while remainder.positive?
34
- pages += 1
35
- remainder -= gearbox_items[pages - 1]
36
- end
37
- [pages, 1].max
38
- end)
39
- end
40
-
41
- # Setup @offset based on the :gearbox_items variable
42
- def setup_offset_var
43
- return super if !@vars[:gearbox_extra] || @vars[:items_extra]
44
-
45
- gearbox_items = @vars[:gearbox_items]
46
- @offset = if @page <= gearbox_items.count
47
- gearbox_items[0, @page - 1].sum
48
- else
49
- gearbox_items.sum + (gearbox_items.last * (@page - gearbox_items.count - 1))
50
- end + @outset
51
- end
52
- end
53
- prepend GearboxExtra
54
- end
@@ -1,53 +0,0 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/headers
2
- # frozen_string_literal: true
3
-
4
- require 'pagy/url_helpers'
5
-
6
- class Pagy # :nodoc:
7
- DEFAULT[:headers] = { page: 'current-page',
8
- items: 'page-items',
9
- count: 'total-count',
10
- pages: 'total-pages' }
11
- # Add specialized backend methods to add pagination response headers
12
- module HeadersExtra
13
- include UrlHelpers
14
-
15
- private
16
-
17
- # Merge the pagy headers into the response.headers
18
- def pagy_headers_merge(pagy)
19
- response.headers.merge!(pagy_headers(pagy))
20
- end
21
-
22
- # Generate a hash of RFC-8288 compliant http headers
23
- def pagy_headers(pagy)
24
- pagy_headers_hash(pagy).tap do |hash|
25
- hash['link'] = hash['link'].map { |rel, link| %(<#{link}>; rel="#{rel}") }.join(', ')
26
- end
27
- end
28
-
29
- # Generates a hash structure of the headers
30
- def pagy_headers_hash(pagy)
31
- countless = defined?(Countless) && pagy.is_a?(Countless)
32
- rel = { 'first' => 1, 'prev' => pagy.prev, 'next' => pagy.next }
33
- rel['last'] = pagy.last unless countless
34
- url_str = pagy_url_for(pagy, PAGE_TOKEN, absolute: true)
35
- link = rel.filter_map do |r, num|
36
- next unless num # rubocop:disable Layout/EmptyLineAfterGuardClause
37
- [r, url_str.sub(PAGE_TOKEN, num.to_s)]
38
- end.compact.to_h
39
- hash = { 'link' => link }
40
- headers = pagy.vars[:headers]
41
- hash[headers[:page]] = pagy.page.to_s if headers[:page]
42
- if headers[:items] && !(defined?(Calendar) && pagy.is_a?(Calendar)) # items is not for Calendar
43
- hash[headers[:items]] = pagy.vars[:items].to_s
44
- end
45
- unless countless
46
- hash[headers[:pages]] = pagy.pages.to_s if headers[:pages]
47
- hash[headers[:count]] = pagy.count.to_s if pagy.count && headers[:count] # count may be nil with Calendar
48
- end
49
- hash
50
- end
51
- end
52
- Backend.prepend HeadersExtra
53
- end
@@ -1,26 +0,0 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/i18n
2
- # frozen_string_literal: true
3
-
4
- class Pagy # :nodoc:
5
- # Use ::I18n gem
6
- module I18nExtra
7
- # Frontend overriding for translation
8
- module FrontendOverride
9
- def pagy_t(key, **opts)
10
- ::I18n.t(key, **opts)
11
- end
12
- end
13
- Frontend.prepend I18nExtra::FrontendOverride
14
-
15
- # Calendar overriding for localization (see also the block in the calendar section of the config/pagy.rb initializer)
16
- module CalendarOverride
17
- def localize(time, opts)
18
- ::I18n.l(time, **opts)
19
- end
20
- end
21
- end
22
- Calendar.prepend I18nExtra::CalendarOverride if defined?(Calendar)
23
-
24
- # Add the pagy locales to the I18n.load_path
25
- ::I18n.load_path += Dir[Pagy.root.join('locales', '*.yml')]
26
- end
@@ -1,61 +0,0 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/items
2
- # frozen_string_literal: true
3
-
4
- require 'pagy/extras/frontend_helpers'
5
-
6
- class Pagy # :nodoc:
7
- DEFAULT[:items_param] = :items
8
- DEFAULT[:max_items] = 100
9
- DEFAULT[:items_extra] = true # extra enabled by default
10
-
11
- # Allow the client to request a custom number of items per page with an optional selector UI
12
- module ItemsExtra
13
- # Additions for the Backend module
14
- module BackendAddOn
15
- private
16
-
17
- # Set the items variable considering the params and other pagy variables
18
- def pagy_set_items_from_params(vars)
19
- return if vars[:items] # :items explicitly set
20
- return unless vars.key?(:items_extra) ? vars[:items_extra] : DEFAULT[:items_extra] # :items_extra is false
21
- return unless (items_count = pagy_get_items_size(vars)) # no items from request params
22
-
23
- vars[:items] = [items_count.to_i, vars.key?(:max_items) ? vars[:max_items] : DEFAULT[:max_items]].compact.min
24
- end
25
-
26
- # Get the items count from the params
27
- # Overridable by the jsonapi extra
28
- def pagy_get_items_size(vars)
29
- params[vars[:items_param] || DEFAULT[:items_param]]
30
- end
31
- end
32
- Backend.prepend ItemsExtra::BackendAddOn
33
-
34
- # Additions for the Frontend module
35
- module FrontendAddOn
36
- ITEMS_PLACEHOLDER = '__pagy_items__'
37
-
38
- # Return the items selector HTML. For example "Show [20] items per page"
39
- def pagy_items_selector_js(pagy, pagy_id: nil, item_name: nil, item_i18n_key: nil)
40
- return '' unless pagy.vars[:items_extra]
41
-
42
- p_id = %( id="#{pagy_id}") if pagy_id
43
- p_vars = pagy.vars
44
- p_items = p_vars[:items]
45
- p_vars[:items] = ITEMS_PLACEHOLDER
46
- url_token = pagy_url_for(pagy, PAGE_TOKEN)
47
- p_vars[:items] = p_items # restore the items
48
-
49
- html = +%(<span#{p_id} class="pagy pagy-items-selector-js" #{pagy_data(pagy, :selector, pagy.from, url_token)}>)
50
- input = %(<input name="items" type="number" min="1" max="#{p_vars[:max_items]}" value="#{
51
- p_items}" style="padding: 0; text-align: center; width: #{p_items.to_s.length + 1}rem;">)
52
- html << pagy_t('pagy.items_selector_js',
53
- item_name: item_name || pagy_t(item_i18n_key || p_vars[:item_i18n_key], count: p_items),
54
- items_input: input,
55
- count: p_items)
56
- html << %(</span>)
57
- end
58
- end
59
- Frontend.prepend ItemsExtra::FrontendAddOn
60
- end
61
- end
@@ -1,79 +0,0 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/jsonapi
2
- # frozen_string_literal: true
3
-
4
- require 'pagy/url_helpers'
5
-
6
- class Pagy # :nodoc:
7
- DEFAULT[:jsonapi] = true
8
-
9
- # Add a specialized backend method compliant with JSON:API
10
- module JsonApiExtra
11
- # JsonApi :page param error
12
- class ReservedParamError < StandardError
13
- # Inform about the actual value
14
- def initialize(value)
15
- super("expected reserved :page param to be nil or Hash-like; got #{value.inspect}")
16
- end
17
- end
18
-
19
- # Module overriding Backend
20
- module BackendOverride
21
- private
22
-
23
- include UrlHelpers
24
-
25
- # Return the jsonapi links
26
- def pagy_jsonapi_links(pagy, **opts)
27
- { first: pagy_url_for(pagy, 1, **opts),
28
- last: pagy_url_for(pagy, pagy.last, **opts),
29
- prev: pagy.prev ? pagy_url_for(pagy, pagy.prev, **opts) : nil,
30
- next: pagy.next ? pagy_url_for(pagy, pagy.next, **opts) : nil }
31
- end
32
-
33
- # Should skip the jsonapi
34
- def pagy_skip_jsonapi?(vars)
35
- return true if vars[:jsonapi] == false || (vars[:jsonapi].nil? && DEFAULT[:jsonapi] == false)
36
- # check the reserved :page param
37
- raise ReservedParamError, params[:page] unless params[:page].respond_to?(:fetch) || params[:page].nil?
38
- end
39
-
40
- # Override the Backend method
41
- def pagy_get_page(vars)
42
- return super if pagy_skip_jsonapi?(vars)
43
- return 1 if params[:page].nil?
44
-
45
- params[:page][vars[:page_param] || DEFAULT[:page_param]].to_i
46
- end
47
- end
48
- Backend.prepend BackendOverride
49
-
50
- # Module overriding ItemsExtra
51
- module ItemsExtraOverride
52
- private
53
-
54
- # Override the ItemsExtra::Backend method
55
- def pagy_get_items_size(vars)
56
- return super if pagy_skip_jsonapi?(vars)
57
- return if params[:page].nil?
58
-
59
- params[:page][vars[:items_param] || DEFAULT[:items_param]]
60
- end
61
- end
62
- # :nocov:
63
- ItemsExtra::BackendAddOn.prepend ItemsExtraOverride if defined?(ItemsExtra::BackendAddOn)
64
- # :nocov:
65
-
66
- # Module overriding UrlHelper
67
- module UrlHelperOverride
68
- # Override UrlHelper method
69
- def pagy_set_query_params(page, vars, params)
70
- return super unless vars[:jsonapi]
71
-
72
- params['page'] ||= {}
73
- params['page'][vars[:page_param].to_s] = page
74
- params['page'][vars[:items_param].to_s] = vars[:items] if vars[:items_extra]
75
- end
76
- end
77
- UrlHelpers.prepend UrlHelperOverride
78
- end
79
- end
@@ -1,96 +0,0 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/materialize
2
- # frozen_string_literal: true
3
-
4
- require 'pagy/extras/frontend_helpers'
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 MaterializeExtra
10
- # 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: '',
12
- nav_aria_label: nil, nav_i18n_key: nil, **vars)
13
- p_id = %( id="#{pagy_id}") if pagy_id
14
- link = pagy_link_proc(pagy, link_extra:)
15
-
16
- html = +%(<div#{p_id} class="pagy-materialize-nav pagination" role="navigation" #{
17
- nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)}><ul class="pagination">)
18
- html << materialize_prev_html(pagy, link)
19
- pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
20
- html << case item
21
- when Integer
22
- %(<li class="waves-effect">#{link.call(item)}</li>)
23
- when String
24
- %(<li class="active"><a role="link" aria-current="page" aria-disabled="true">#{pagy.label_for(item)}</a></li>)
25
- when :gap
26
- %(<li class="gap disabled"><a role="link" aria-disabled="true">#{pagy_t 'pagy.gap'}</a></li>)
27
- else
28
- raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
29
- end
30
- end
31
- html << materialize_next_html(pagy, link)
32
- html << %(</ul></div>)
33
- end
34
-
35
- # Javascript pagination for materialize: it returns a nav and a JSON tag used by the pagy.js file
36
- def pagy_materialize_nav_js(pagy, pagy_id: nil, link_extra: '',
37
- nav_aria_label: nil, nav_i18n_key: nil, **vars)
38
- sequels = pagy.sequels(**vars)
39
- p_id = %( id="#{pagy_id}") if pagy_id
40
- link = pagy_link_proc(pagy, link_extra:)
41
-
42
- tags = { 'before' => %(<ul class="pagination">#{materialize_prev_html pagy, link}),
43
- 'link' => %(<li class="waves-effect">#{link.call(PAGE_TOKEN, LABEL_TOKEN)}</li>),
44
- 'active' => %(<li class="active"><a role="link" aria-current="page" aria-disabled="true">#{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, link}</ul>) }
47
-
48
- %(<div#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-materialize-nav-js" role="navigation" #{
49
- nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)} #{
50
- pagy_data(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></div>)
51
- end
52
-
53
- # Javascript combo pagination for materialize: it returns a nav and a JSON tag used by the pagy.js file
54
- def pagy_materialize_combo_nav_js(pagy, pagy_id: nil, link_extra: '',
55
- nav_aria_label: nil, nav_i18n_key: nil)
56
- p_id = %( id="#{pagy_id}") if pagy_id
57
- link = pagy_link_proc(pagy, link_extra:)
58
- p_page = pagy.page
59
- p_pages = pagy.pages
60
- style = ' style="vertical-align: middle"'
61
- input = %(<input name="page" type="number" class="browser-default" min="1" max="#{p_pages}" value="#{
62
- p_page}" style="text-align: center; width: #{p_pages.to_s.length + 1}rem;" aria-current="page">)
63
-
64
- html = %(<ul#{p_id} class="pagy-materialize-combo-nav-js pagination chip" role="navigation" #{
65
- nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)})
66
- %(#{html} style="padding-right: 0" #{
67
- pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))}>#{
68
- materialize_prev_html pagy, link, style}<li class="pagy-combo-input">#{
69
- pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages}</li>#{
70
- materialize_next_html pagy, link, style}</ul>)
71
- end
72
-
73
- private
74
-
75
- def materialize_prev_html(pagy, link, style = '')
76
- if (p_prev = pagy.prev)
77
- %(<li class="waves-effect prev"#{style}>#{
78
- link.call(p_prev, '<i class="material-icons">chevron_left</i>', prev_aria_label_attr)}</li>)
79
- else
80
- %(<li class="prev disabled"#{style}><a role="link" aria-disabled="true" #{
81
- prev_aria_label_attr}><i class="material-icons">chevron_left</i></a></li>)
82
- end
83
- end
84
-
85
- def materialize_next_html(pagy, link, style = '')
86
- if (p_next = pagy.next)
87
- %(<li class="waves-effect next"#{style}>#{
88
- link.call(p_next, '<i class="material-icons">chevron_right</i>', next_aria_label_attr)}</li>)
89
- else
90
- %(<li class="next disabled"#{style}><a role="link" aria-disabled="true" #{
91
- next_aria_label_attr}><i class="material-icons">chevron_right</i></a></li>)
92
- end
93
- end
94
- end
95
- Frontend.prepend MaterializeExtra
96
- end