pagy 3.10.0 → 5.7.3

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 (94) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/lib/config/pagy.rb +121 -52
  4. data/lib/javascripts/pagy-dev.js +117 -0
  5. data/lib/javascripts/pagy.js +1 -106
  6. data/lib/javascripts/pagy.mjs +118 -0
  7. data/lib/locales/ar.yml +26 -0
  8. data/lib/locales/bg.yml +2 -2
  9. data/lib/locales/bs.yml +24 -0
  10. data/lib/locales/ca.yml +2 -2
  11. data/lib/locales/cs.yml +2 -2
  12. data/lib/locales/da.yml +2 -2
  13. data/lib/locales/de.yml +2 -2
  14. data/lib/locales/en.yml +2 -2
  15. data/lib/locales/es.yml +2 -2
  16. data/lib/locales/fr.yml +2 -2
  17. data/lib/locales/hr.yml +24 -0
  18. data/lib/locales/id.yml +2 -2
  19. data/lib/locales/it.yml +2 -2
  20. data/lib/locales/ja.yml +2 -2
  21. data/lib/locales/km.yml +2 -2
  22. data/lib/locales/ko.yml +2 -2
  23. data/lib/locales/nb.yml +2 -2
  24. data/lib/locales/nl.yml +2 -2
  25. data/lib/locales/pl.yml +2 -2
  26. data/lib/locales/pt-BR.yml +2 -2
  27. data/lib/locales/pt.yml +2 -2
  28. data/lib/locales/ru.yml +2 -2
  29. data/lib/locales/sr.yml +23 -0
  30. data/lib/locales/sv-SE.yml +2 -2
  31. data/lib/locales/sv.yml +2 -2
  32. data/lib/locales/sw.yml +22 -0
  33. data/lib/locales/ta.yml +22 -0
  34. data/lib/locales/tr.yml +2 -2
  35. data/lib/locales/uk.yml +24 -0
  36. data/lib/locales/zh-CN.yml +2 -2
  37. data/lib/locales/zh-HK.yml +2 -2
  38. data/lib/locales/zh-TW.yml +3 -3
  39. data/lib/pagy/backend.rb +11 -12
  40. data/lib/pagy/calendar/day.rb +29 -0
  41. data/lib/pagy/calendar/month.rb +16 -0
  42. data/lib/pagy/calendar/month_mixin.rb +49 -0
  43. data/lib/pagy/calendar/quarter.rb +23 -0
  44. data/lib/pagy/calendar/week.rb +39 -0
  45. data/lib/pagy/calendar/year.rb +29 -0
  46. data/lib/pagy/calendar.rb +90 -0
  47. data/lib/pagy/console.rb +23 -0
  48. data/lib/pagy/countless.rb +23 -19
  49. data/lib/pagy/exceptions.rb +16 -13
  50. data/lib/pagy/extras/arel.rb +12 -7
  51. data/lib/pagy/extras/array.rb +10 -9
  52. data/lib/pagy/extras/bootstrap.rb +77 -39
  53. data/lib/pagy/extras/bulma.rb +77 -43
  54. data/lib/pagy/extras/calendar.rb +66 -0
  55. data/lib/pagy/extras/countless.rb +17 -17
  56. data/lib/pagy/extras/elasticsearch_rails.rb +66 -37
  57. data/lib/pagy/extras/foundation.rb +74 -41
  58. data/lib/pagy/extras/frontend_helpers.rb +70 -0
  59. data/lib/pagy/extras/gearbox.rb +42 -0
  60. data/lib/pagy/extras/headers.rb +32 -18
  61. data/lib/pagy/extras/i18n.rb +18 -17
  62. data/lib/pagy/extras/items.rb +42 -53
  63. data/lib/pagy/extras/materialize.rb +68 -43
  64. data/lib/pagy/extras/meilisearch.rb +61 -0
  65. data/lib/pagy/extras/metadata.rb +27 -26
  66. data/lib/pagy/extras/navs.rb +54 -29
  67. data/lib/pagy/extras/overflow.rb +57 -52
  68. data/lib/pagy/extras/searchkick.rb +54 -36
  69. data/lib/pagy/extras/semantic.rb +66 -39
  70. data/lib/pagy/extras/standalone.rb +64 -0
  71. data/lib/pagy/extras/support.rb +34 -17
  72. data/lib/pagy/extras/trim.rb +18 -12
  73. data/lib/pagy/extras/uikit.rb +66 -44
  74. data/lib/pagy/frontend.rb +61 -53
  75. data/lib/pagy/i18n.rb +164 -0
  76. data/lib/pagy/url_helpers.rb +38 -0
  77. data/lib/pagy.rb +96 -30
  78. data/lib/templates/bootstrap_nav.html.erb +1 -1
  79. data/lib/templates/bootstrap_nav.html.haml +1 -1
  80. data/lib/templates/bootstrap_nav.html.slim +1 -1
  81. data/lib/templates/foundation_nav.html.erb +1 -1
  82. data/lib/templates/foundation_nav.html.haml +1 -1
  83. data/lib/templates/foundation_nav.html.slim +1 -1
  84. data/lib/templates/uikit_nav.html.erb +2 -2
  85. data/lib/templates/uikit_nav.html.haml +1 -1
  86. data/lib/templates/uikit_nav.html.slim +2 -2
  87. metadata +37 -16
  88. data/lib/locales/README.md +0 -35
  89. data/lib/locales/utils/i18n.rb +0 -25
  90. data/lib/locales/utils/loader.rb +0 -34
  91. data/lib/locales/utils/p11n.rb +0 -88
  92. data/lib/pagy/extras/pagy_search.rb +0 -18
  93. data/lib/pagy/extras/shared.rb +0 -53
  94. data/pagy.gemspec +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9ce66549213b7c1a7f89755a31d5faec46f09372f5b854d7f7ede99fb329b5d0
4
- data.tar.gz: 35071f34f9a15378e91efb38f060e1178ccc2d7609ff2bdc99b435f8f9242417
3
+ metadata.gz: 3b065a7027d07b5bc504cbd2b80389a2e25168a075a7485d6a0155bd54b36bf4
4
+ data.tar.gz: 345c15d964cf6511adcbdf60514f605c64b83e51dd172849f98d337fcff67696
5
5
  SHA512:
6
- metadata.gz: d0a3520386cf1b796c5e26fe13c65ebc158d6fccbb24547a37bfcd5ef39ede686e1d3cb771c6ce23303d83529a075d03fc5e0288704b26bd0be17e0e641f1553
7
- data.tar.gz: 7ef28712f3e38fc05fbbebb5445d25d7f0ec97d61bebbd0c1a45830345c4bd5ba1be202b5a7417bc23d8f822d85408cd0051d1d3de22d66e6c6ee10c49caedbd
6
+ metadata.gz: 16b5e3b3cee1cde9f609260324ad045e45b97ecbb457eb648044b726fcc0735dd16f7909f49066ae21c01589e3dafdf303be19a865d0d71fcebe3e9b325e9fe1
7
+ data.tar.gz: df2a7604efbd881c69977e05a23b4b4125eaf0660410d619dbeafbfed7f42de2f4382f01b91f591bd66a6a799c8f5970deb782ea6ca48e9cb8fe95c018428feb
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2017-2020 Domizio Demichelis
3
+ Copyright (c) 2017-2022 Domizio Demichelis
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/lib/config/pagy.rb CHANGED
@@ -1,11 +1,35 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
- # Pagy initializer file (3.10.0)
5
- # Customize only what you really need and notice that Pagy works also without any of the following lines.
3
+ # Pagy initializer file (5.7.3)
4
+ # Customize only what you really need and notice that the core Pagy works also without any of the following lines.
6
5
  # Should you just cherry pick part of this file, please maintain the require-order of the extras
7
6
 
8
7
 
8
+ # Pagy DEFAULT Variables
9
+ # See https://ddnexus.github.io/pagy/api/pagy#variables
10
+ # All the Pagy::DEFAULT are set for all the Pagy instances but can be overridden per instance by just passing them to
11
+ # Pagy.new|Pagy::Countless.new|Pagy::Calendar::*.new or any of the #pagy* controller methods
12
+
13
+
14
+ # Instance variables
15
+ # See https://ddnexus.github.io/pagy/api/pagy#instance-variables
16
+ # Pagy::DEFAULT[:page] = 1 # default
17
+ # Pagy::DEFAULT[:items] = 20 # default
18
+ # Pagy::DEFAULT[:outset] = 0 # default
19
+
20
+
21
+ # Other Variables
22
+ # See https://ddnexus.github.io/pagy/api/pagy#other-variables
23
+ # Pagy::DEFAULT[:size] = [1,4,4,1] # default
24
+ # Pagy::DEFAULT[:page_param] = :page # default
25
+ # The :params can be also set as a lambda e.g ->(params){ params.exclude('useless').merge!('custom' => 'useful') }
26
+ # Pagy::DEFAULT[:params] = {} # default
27
+ # Pagy::DEFAULT[:fragment] = '#fragment' # example
28
+ # Pagy::DEFAULT[:link_extra] = 'data-remote="true"' # example
29
+ # Pagy::DEFAULT[:i18n_key] = 'pagy.item_name' # default
30
+ # Pagy::DEFAULT[:cycle] = true # example
31
+
32
+
9
33
  # Extras
10
34
  # See https://ddnexus.github.io/pagy/extras
11
35
 
@@ -16,18 +40,77 @@
16
40
  # See https://ddnexus.github.io/pagy/extras/array
17
41
  # require 'pagy/extras/array'
18
42
 
43
+ # Calendar extra: Add pagination filtering by calendar time unit (year, quarter, month, week, day)
44
+ # See https://ddnexus.github.io/pagy/extras/calendar
45
+ # require 'pagy/extras/calendar'
46
+ # Default for each unit
47
+ # Pagy::Calendar::Year::DEFAULT[:order] = :asc # Time direction of pagination
48
+ # Pagy::Calendar::Year::DEFAULT[:format] = '%Y' # strftime format
49
+ #
50
+ # Pagy::Calendar::Quarter::DEFAULT[:order] = :asc # Time direction of pagination
51
+ # Pagy::Calendar::Quarter::DEFAULT[:format] = '%Y-Q%q' # strftime format
52
+ #
53
+ # Pagy::Calendar::Month::DEFAULT[:order] = :asc # Time direction of pagination
54
+ # Pagy::Calendar::Month::DEFAULT[:format] = '%Y-%m' # strftime format
55
+ #
56
+ # Pagy::Calendar::Week::DEFAULT[:order] = :asc # Time direction of pagination
57
+ # Pagy::Calendar::Week::DEFAULT[:format] = '%Y-%W' # strftime format
58
+ # Pagy::Calendar::Week::DEFAULT[:offset] = 0 # Day offset from Sunday (0: Sunday; 1: Monday;... 6: Saturday)
59
+ #
60
+ # Pagy::Calendar::Day::DEFAULT[:order] = :asc # Time direction of pagination
61
+ # Pagy::Calendar::Day::DEFAULT[:format] = '%Y-%m-%d' # strftime format
62
+ #
63
+ # Uncomment the following lines, if you need calendar localization without using the I18n extra
64
+ # module LocalizePagyCalendar
65
+ # def localize(time, opts)
66
+ # ::I18n.l(time, **opts)
67
+ # end
68
+ # end
69
+ # Pagy::Calendar.prepend LocalizePagyCalendar
70
+
19
71
  # Countless extra: Paginate without any count, saving one query per rendering
20
72
  # See https://ddnexus.github.io/pagy/extras/countless
21
73
  # require 'pagy/extras/countless'
22
- # Pagy::VARS[:cycle] = false # default
74
+ # Pagy::DEFAULT[:countless_minimal] = false # default (eager loading)
23
75
 
24
76
  # Elasticsearch Rails extra: Paginate `ElasticsearchRails::Results` objects
25
77
  # See https://ddnexus.github.io/pagy/extras/elasticsearch_rails
78
+ # default :pagy_search method: change only if you use also
79
+ # the searchkick or meilisearch extra that defines the same
80
+ # Pagy::DEFAULT[:elasticsearch_rails_search_method] = :pagy_search
26
81
  # require 'pagy/extras/elasticsearch_rails'
27
82
 
83
+ # Headers extra: http response headers (and other helpers) useful for API pagination
84
+ # See http://ddnexus.github.io/pagy/extras/headers
85
+ # require 'pagy/extras/headers'
86
+ # Pagy::DEFAULT[:headers] = { page: 'Current-Page',
87
+ # items: 'Page-Items',
88
+ # count: 'Total-Count',
89
+ # pages: 'Total-Pages' } # default
90
+
91
+ # Meilisearch extra: Paginate `Meilisearch` result objects
92
+ # See https://ddnexus.github.io/pagy/extras/meilisearch
93
+ # default :pagy_search method: change only if you use also
94
+ # the elasticsearch_rails or searchkick extra that define the same method
95
+ # Pagy::DEFAULT[:meilisearch_search_method] = :pagy_search
96
+ # require 'pagy/extras/meilisearch'
97
+
98
+ # Metadata extra: Provides the pagination metadata to Javascript frameworks like Vue.js, react.js, etc.
99
+ # See https://ddnexus.github.io/pagy/extras/metadata
100
+ # you must require the shared internal extra (BEFORE the metadata extra) ONLY if you need also the :sequels
101
+ # require 'pagy/extras/shared'
102
+ # require 'pagy/extras/metadata'
103
+ # For performance reasons, you should explicitly set ONLY the metadata you use in the frontend
104
+ # Pagy::DEFAULT[:metadata] = %i[scaffold_url page prev next last] # example
105
+
28
106
  # Searchkick extra: Paginate `Searchkick::Results` objects
29
107
  # See https://ddnexus.github.io/pagy/extras/searchkick
108
+ # default :pagy_search method: change only if you use also
109
+ # the elasticsearch_rails or meilisearch extra that defines the same
110
+ # DEFAULT[:searchkick_search_method] = :pagy_search
30
111
  # require 'pagy/extras/searchkick'
112
+ # uncomment if you are going to use Searchkick.pagy_search
113
+ # Searchkick.extend Pagy::Searchkick
31
114
 
32
115
 
33
116
  # Frontend Extras
@@ -64,63 +147,45 @@
64
147
 
65
148
  # Multi size var used by the *_nav_js helpers
66
149
  # See https://ddnexus.github.io/pagy/extras/navs#steps
67
- # Pagy::VARS[:steps] = { 0 => [2,3,3,2], 540 => [3,5,5,3], 720 => [5,7,7,5] } # example
150
+ # Pagy::DEFAULT[:steps] = { 0 => [2,3,3,2], 540 => [3,5,5,3], 720 => [5,7,7,5] } # example
68
151
 
69
152
 
70
153
  # Feature Extras
71
154
 
72
- # Headers extra: http response headers (and other helpers) useful for API pagination
73
- # See http://ddnexus.github.io/pagy/extras/headers
74
- # require 'pagy/extras/headers'
75
- # Pagy::VARS[:headers] = { page: 'Current-Page', items: 'Page-Items', count: 'Total-Count', pages: 'Total-Pages' } # default
76
-
77
- # Support extra: Extra support for features like: incremental, infinite, auto-scroll pagination
78
- # See https://ddnexus.github.io/pagy/extras/support
79
- # require 'pagy/extras/support'
155
+ # Gearbox extra: Automatically change the number of items per page depending on the page number
156
+ # See https://ddnexus.github.io/pagy/extras/gearbox
157
+ # require 'pagy/extras/gearbox'
158
+ # set to false only if you want to make :gearbox_extra an opt-in variable
159
+ # Pagy::DEFAULT[:gearbox_extra] = false # default true
160
+ # Pagy::DEFAULT[:gearbox_items] = [15, 30, 60, 100] # default
80
161
 
81
162
  # Items extra: Allow the client to request a custom number of items per page with an optional selector UI
82
163
  # See https://ddnexus.github.io/pagy/extras/items
83
164
  # require 'pagy/extras/items'
84
- # Pagy::VARS[:items_param] = :items # default
85
- # Pagy::VARS[:max_items] = 100 # default
165
+ # set to false only if you want to make :items_extra an opt-in variable
166
+ # Pagy::DEFAULT[:items_extra] = false # default true
167
+ # Pagy::DEFAULT[:items_param] = :items # default
168
+ # Pagy::DEFAULT[:max_items] = 100 # default
86
169
 
87
170
  # Overflow extra: Allow for easy handling of overflowing pages
88
171
  # See https://ddnexus.github.io/pagy/extras/overflow
89
172
  # require 'pagy/extras/overflow'
90
- # Pagy::VARS[:overflow] = :empty_page # default (other options: :last_page and :exception)
173
+ # Pagy::DEFAULT[:overflow] = :empty_page # default (other options: :last_page and :exception)
91
174
 
92
- # Metadata extra: Provides the pagination metadata to Javascript frameworks like Vue.js, react.js, etc.
93
- # See https://ddnexus.github.io/pagy/extras/metadata
94
- # you must require the shared internal extra (BEFORE the metadata extra) ONLY if you need also the :sequels
95
- # require 'pagy/extras/shared'
96
- # require 'pagy/extras/metadata'
97
- # For performance reason, you should explicitly set ONLY the metadata you use in the frontend
98
- # Pagy::VARS[:metadata] = [:scaffold_url, :count, :page, :prev, :next, :last] # example
175
+ # Support extra: Extra support for features like: incremental, infinite, auto-scroll pagination
176
+ # See https://ddnexus.github.io/pagy/extras/support
177
+ # require 'pagy/extras/support'
99
178
 
100
179
  # Trim extra: Remove the page=1 param from links
101
180
  # See https://ddnexus.github.io/pagy/extras/trim
102
181
  # require 'pagy/extras/trim'
182
+ # set to false only if you want to make :trim_extra an opt-in variable
183
+ # Pagy::DEFAULT[:trim_extra] = false # default true
103
184
 
104
-
105
-
106
- # Pagy Variables
107
- # See https://ddnexus.github.io/pagy/api/pagy#variables
108
- # All the Pagy::VARS are set for all the Pagy instances but can be overridden
109
- # per instance by just passing them to Pagy.new or the #pagy controller method
110
-
111
-
112
- # Instance variables
113
- # See https://ddnexus.github.io/pagy/api/pagy#instance-variables
114
- # Pagy::VARS[:items] = 20 # default
115
-
116
-
117
- # Other Variables
118
- # See https://ddnexus.github.io/pagy/api/pagy#other-variables
119
- # Pagy::VARS[:size] = [1,4,4,1] # default
120
- # Pagy::VARS[:page_param] = :page # default
121
- # Pagy::VARS[:params] = {} # default
122
- # Pagy::VARS[:anchor] = '#anchor' # example
123
- # Pagy::VARS[:link_extra] = 'data-remote="true"' # example
185
+ # Standalone extra: Use pagy in non Rack environment/gem
186
+ # See https://ddnexus.github.io/pagy/extras/standalone
187
+ # require 'pagy/extras/standalone'
188
+ # Pagy::DEFAULT[:url] = 'http://www.example.com/subdir' # optional default
124
189
 
125
190
 
126
191
  # Rails
@@ -147,18 +212,18 @@
147
212
  #
148
213
  # load the "de", "en" and "es" built-in locales:
149
214
  # (the first passed :locale will be used also as the default_locale)
150
- # Pagy::I18n.load({locale: 'de'},
151
- # {locale: 'en'},
152
- # {locale: 'es'})
215
+ # Pagy::I18n.load({ locale: 'de' },
216
+ # { locale: 'en' },
217
+ # { locale: 'es' })
153
218
  #
154
219
  # load the "en" built-in locale, a custom "es" locale,
155
220
  # and a totally custom locale complete with a custom :pluralize proc:
156
221
  # (the first passed :locale will be used also as the default_locale)
157
- # Pagy::I18n.load({locale: 'en'},
158
- # {locale: 'es', filepath: 'path/to/pagy-es.yml'},
159
- # {locale: 'xyz', # not built-in
160
- # filepath: 'path/to/pagy-xyz.yml',
161
- # pluralize: lambda{|count| ... } )
222
+ # Pagy::I18n.load({ locale: 'en' },
223
+ # { locale: 'es', filepath: 'path/to/pagy-es.yml' },
224
+ # { locale: 'xyz', # not built-in
225
+ # filepath: 'path/to/pagy-xyz.yml',
226
+ # pluralize: lambda{ |count| ... } )
162
227
 
163
228
 
164
229
  # I18n extra: uses the standard i18n gem which is ~18x slower using ~10x more memory
@@ -167,4 +232,8 @@
167
232
  # require 'pagy/extras/i18n'
168
233
 
169
234
  # Default i18n key
170
- # Pagy::VARS[:i18n_key] = 'pagy.item_name' # default
235
+ # Pagy::DEFAULT[:i18n_key] = 'pagy.item_name' # default
236
+
237
+
238
+ # When you are done setting your own default freeze it, so it will not get changed accidentally
239
+ Pagy::DEFAULT.freeze
@@ -0,0 +1,117 @@
1
+ // The Pagy object
2
+ const Pagy = {
3
+ version: "5.7.3",
4
+ // Scan for "data-pagy-json" elements, parse their JSON content and call their init functions
5
+ init(arg) {
6
+ const target = arg instanceof Element ? arg : document;
7
+ const elements = target.querySelectorAll("[data-pagy-json]");
8
+ const warn = (el, err) => console.warn("Pagy.init() skipped element: %o\n%s", el, err);
9
+ for (const element of elements) {
10
+ const json = element.getAttribute("data-pagy-json");
11
+ try {
12
+ const [keyword, ...args] = JSON.parse(json);
13
+ if (keyword === "nav") {
14
+ Pagy.initNav(element, args);
15
+ }
16
+ else if (keyword === "combo") {
17
+ Pagy.initCombo(element, args);
18
+ }
19
+ else if (keyword === "selector") {
20
+ Pagy.initSelector(element, args);
21
+ }
22
+ else {
23
+ warn(element, `Illegal PagyJSON keyword: expected "nav"|"combo"|"selector", got "${keyword}"`);
24
+ }
25
+ }
26
+ catch (err) {
27
+ warn(element, err);
28
+ }
29
+ }
30
+ },
31
+ // Init the *_nav_js helpers
32
+ initNav(el, [tags, sequels, labelSequels, trimParam]) {
33
+ const container = el.parentElement ?? el;
34
+ const widths = Object.getOwnPropertyNames(sequels).map(w => parseInt(w)).sort((a, b) => b - a);
35
+ let lastWidth = -1;
36
+ const fillIn = (link, page, label) => link.replace(/__pagy_page__/g, page).replace(/__pagy_label__/g, label);
37
+ (el.pagyRender = function () {
38
+ const width = widths.find(w => w < container.clientWidth) || 0;
39
+ if (width === lastWidth) {
40
+ return;
41
+ } // no change: abort
42
+ let html = tags.before;
43
+ const series = sequels[width.toString()];
44
+ const labels = labelSequels?.[width.toString()] ?? series.map(l => l.toString());
45
+ for (const i in series) {
46
+ const item = series[i];
47
+ const label = labels[i];
48
+ if (typeof trimParam === "string" && item === 1) {
49
+ html += Pagy.trim(fillIn(tags.link, item.toString(), label), trimParam);
50
+ }
51
+ else if (typeof item === "number") {
52
+ html += fillIn(tags.link, item.toString(), label);
53
+ }
54
+ else if (item === "gap") {
55
+ html += tags.gap;
56
+ }
57
+ else { // active page
58
+ html += fillIn(tags.active, item, label);
59
+ }
60
+ }
61
+ html += tags.after; // eslint-disable-line align-assignments/align-assignments
62
+ el.innerHTML = "";
63
+ el.insertAdjacentHTML("afterbegin", html);
64
+ lastWidth = width;
65
+ })();
66
+ if (el.classList.contains("pagy-rjs")) {
67
+ Pagy.rjsObserver.observe(container);
68
+ }
69
+ },
70
+ // The observer instance for responsive navs
71
+ rjsObserver: new ResizeObserver(entries => {
72
+ entries.filter(e => e.contentBoxSize)
73
+ .forEach(e => e.target.querySelectorAll(".pagy-rjs")
74
+ .forEach(rjs => rjs.pagyRender()));
75
+ }),
76
+ // Init the *_combo_nav_js helpers
77
+ initCombo(el, [link, trimParam]) {
78
+ Pagy.initInput(el, inputValue => [inputValue, link.replace(/__pagy_page__/, inputValue)], trimParam);
79
+ },
80
+ // Init the items_selector_js helper
81
+ initSelector(el, [from, link, trimParam]) {
82
+ Pagy.initInput(el, inputValue => {
83
+ const page = Math.max(Math.ceil(from / parseInt(inputValue)), 1).toString();
84
+ const html = link.replace(/__pagy_page__/, page).replace(/__pagy_items__/, inputValue);
85
+ return [page, html];
86
+ }, trimParam);
87
+ },
88
+ // Init the input element
89
+ initInput(el, getVars, trimParam) {
90
+ const input = el.querySelector("input");
91
+ const initial = input.value;
92
+ const action = function () {
93
+ if (input.value === initial) {
94
+ return;
95
+ } // not changed
96
+ const [min, val, max] = [input.min, input.value, input.max].map(n => parseInt(n) || 0);
97
+ if (val < min || val > max) { // reset invalid/out-of-range
98
+ input.value = initial;
99
+ input.select();
100
+ return;
101
+ }
102
+ let [page, html] = getVars(input.value); // eslint-disable-line prefer-const
103
+ if (typeof trimParam === "string" && page === "1") {
104
+ html = Pagy.trim(html, trimParam);
105
+ }
106
+ el.insertAdjacentHTML("afterbegin", html);
107
+ el.querySelector("a").click();
108
+ };
109
+ ["change", "focus"].forEach(e => input.addEventListener(e, input.select)); // auto-select
110
+ input.addEventListener("focusout", action); // trigger action
111
+ input.addEventListener("keypress", e => { if (e.key === "Enter") {
112
+ action();
113
+ } }); // trigger action
114
+ },
115
+ // Trim the ${page-param}=1 params in links
116
+ trim: (link, param) => link.replace(new RegExp(`[?&]${param}=1\\b(?!&)|\\b${param}=1&`), "")
117
+ };
@@ -1,106 +1 @@
1
- // See the Pagy documentation: https://ddnexus.github.io/pagy/extras#javascript
2
-
3
- function Pagy(){}
4
-
5
- Pagy.version = '3.10.0';
6
-
7
- Pagy.init = function(arg){
8
- var target = arg instanceof Event || arg === undefined ? document : arg,
9
- jsonTags = target.getElementsByClassName('pagy-json');
10
- if (target === document) { // reset resize-listeners on page load (#163)
11
- for (var id in Pagy.navResizeListeners) { window.removeEventListener('resize', Pagy.navResizeListeners[id], true) }
12
- Pagy.navResizeListeners = {};
13
- }
14
- for (var i = 0, len = jsonTags.length; i < len; i++) {
15
- var args = JSON.parse(jsonTags[i].innerHTML);
16
- Pagy[args.shift()].apply(null, args);
17
- }
18
- };
19
-
20
- Pagy.nav = function(id, tags, sequels, param){
21
- var pagyEl = document.getElementById(id),
22
- lastWidth = undefined,
23
- timeoutId = 0,
24
- pageREg = new RegExp(/__pagy_page__/g),
25
- widths = [],
26
- rendering = function(){ clearTimeout(timeoutId); timeoutId = setTimeout(pagyEl.render, 150) }; // suppress rapid firing rendering
27
-
28
- for (var width in sequels) { widths.push(parseInt(width)) } // fine with sequels structure
29
- widths.sort(function(a, b){return b-a});
30
-
31
- pagyEl.render = function(){
32
- if (this.parentElement.clientWidth === 0) { rendering() }
33
- var width, i, len;
34
- for (i = 0, len = widths.length; i < len; i++) {
35
- if (this.parentElement.clientWidth > widths[i]) { width = widths[i]; break }
36
- }
37
- if (width !== lastWidth) {
38
- var html = tags.before,
39
- series = sequels[width];
40
- for (i = 0, len = series.length; i < len; i++) {
41
- var item = series[i];
42
- if (typeof(param) === 'string' && item === 1) { html += Pagy.trim(tags.link.replace(pageREg, item), param) }
43
- else if (typeof(item) === 'number') { html += tags.link.replace(pageREg, item) }
44
- else if (item === 'gap') { html += tags.gap }
45
- else if (typeof(item) === 'string') { html += tags.active.replace(pageREg, item) }
46
- }
47
- html += tags.after;
48
- this.innerHTML = '';
49
- this.insertAdjacentHTML('afterbegin', html);
50
- lastWidth = width;
51
- }
52
- }.bind(pagyEl);
53
-
54
- if (widths.length > 1) {
55
- // refresh the window resize listener (avoiding rendering multiple times)
56
- window.removeEventListener('resize', Pagy.navResizeListeners[id], true); // needed for AJAX init
57
- window.addEventListener('resize', rendering, true);
58
- Pagy.navResizeListeners[id] = rendering;
59
- }
60
- pagyEl.render();
61
- };
62
-
63
- Pagy.combo_nav = function(id, page, link, param){
64
- var pagyEl = document.getElementById(id),
65
- input = pagyEl.getElementsByTagName('input')[0],
66
- go = function(){
67
- if (page !== input.value) {
68
- var html = link.replace(/__pagy_page__/, input.value);
69
- if (typeof(param) === 'string' && input.value === '1') { html = Pagy.trim(html, param) }
70
- pagyEl.insertAdjacentHTML('afterbegin', html);
71
- pagyEl.getElementsByTagName('a')[0].click();
72
- }
73
- };
74
- Pagy.addInputEventListeners(input, go);
75
- };
76
-
77
- Pagy.items_selector = function(id, from, link, param){
78
- var pagyEl = document.getElementById(id),
79
- input = pagyEl.getElementsByTagName('input')[0],
80
- current = input.value,
81
- go = function(){
82
- var items = input.value;
83
- if (current !== items) {
84
- var page = Math.max(Math.ceil(from / items),1),
85
- html = link.replace(/__pagy_page__/, page).replace(/__pagy_items__/, items);
86
- if (typeof(param) === 'string' && page === 1){ html = Pagy.trim(html, param) }
87
- pagyEl.insertAdjacentHTML('afterbegin', html);
88
- pagyEl.getElementsByTagName('a')[0].click();
89
- }
90
- };
91
- Pagy.addInputEventListeners(input, go);
92
- };
93
-
94
- Pagy.addInputEventListeners = function(input, handler){
95
- // select the content on click: easier for typing a number
96
- input.addEventListener('click', function(){ this.select() });
97
- // go when the input looses focus
98
- input.addEventListener('focusout', handler);
99
- // … and when pressing enter inside the input
100
- input.addEventListener('keyup', function(e){ if (e.which === 13) handler() }.bind(this));
101
- };
102
-
103
- Pagy.trim = function(html, param){
104
- var re = new RegExp('[?&]' + param + '=1\\b(?!&)|\\b' + param + '=1&');
105
- return html.replace(re, '');
106
- };
1
+ !function(){function t(t){if(Array.isArray(t))return t}function n(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}function e(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}function r(r,i){return t(r)||n(r)||e()}var i={version:"5.7.3",init:function(r){var a,o=(r instanceof Element?r:document).querySelectorAll("[data-pagy-json]"),c=function(t,n){return console.warn("Pagy.init() skipped element: %o\n%s",t,n)},u=!0,l=!1,f=void 0;try{for(var p,s=o[Symbol.iterator]();!(u=(p=s.next()).done);u=!0){var v=p.value,g=v.getAttribute("data-pagy-json");try{var y=t(a=JSON.parse(g))||n(a)||e(),d=y[0],m=y.slice(1);"nav"===d?i.initNav(v,m):"combo"===d?i.initCombo(v,m):"selector"===d?i.initSelector(v,m):c(v,'Illegal PagyJSON keyword: expected "nav"|"combo"|"selector", got "'.concat(d,'"'))}catch(t){c(v,t)}}}catch(t){l=!0,f=t}finally{try{u||null==s.return||s.return()}finally{if(l)throw f}}},initNav:function(t,n){var e,a=r(n),o=a[0],c=a[1],u=a[2],l=a[3],f=null!==(e=t.parentElement)&&void 0!==e?e:t,p=Object.getOwnPropertyNames(c).map((function(t){return parseInt(t)})).sort((function(t,n){return n-t})),s=-1,v=function(t,n,e){return t.replace(/__pagy_page__/g,n).replace(/__pagy_label__/g,e)};(t.pagyRender=function(){var n=p.find((function(t){return t<f.clientWidth}))||0;if(n!==s){var e,r=o.before,a=c[n.toString()],g=null!==(e=null==u?void 0:u[n.toString()])&&void 0!==e?e:a.map((function(t){return t.toString()}));for(var y in a){var d=a[y],m=g[y];r+="string"==typeof l&&1===d?i.trim(v(o.link,d.toString(),m),l):"number"==typeof d?v(o.link,d.toString(),m):"gap"===d?o.gap:v(o.active,d,m)}r+=o.after,t.innerHTML="",t.insertAdjacentHTML("afterbegin",r),s=n}})(),t.classList.contains("pagy-rjs")&&i.rjsObserver.observe(f)},rjsObserver:new ResizeObserver((function(t){t.filter((function(t){return t.contentBoxSize})).forEach((function(t){return t.target.querySelectorAll(".pagy-rjs").forEach((function(t){return t.pagyRender()}))}))})),initCombo:function(t,n){var e=r(n),a=e[0],o=e[1];i.initInput(t,(function(t){return[t,a.replace(/__pagy_page__/,t)]}),o)},initSelector:function(t,n){var e=r(n),a=e[0],o=e[1],c=e[2];i.initInput(t,(function(t){var n=Math.max(Math.ceil(a/parseInt(t)),1).toString();return[n,o.replace(/__pagy_page__/,n).replace(/__pagy_items__/,t)]}),c)},initInput:function(t,n,e){var a=t.querySelector("input"),o=a.value,c=function(){if(a.value!==o){var c=r([a.min,a.value,a.max].map((function(t){return parseInt(t)||0}))),u=c[0],l=c[1],f=c[2];if(l<u||l>f)return a.value=o,void a.select();var p=r(n(a.value)),s=p[0],v=p[1];"string"==typeof e&&"1"===s&&(v=i.trim(v,e)),t.insertAdjacentHTML("afterbegin",v),t.querySelector("a").click()}};["change","focus"].forEach((function(t){return a.addEventListener(t,a.select)})),a.addEventListener("focusout",c),a.addEventListener("keypress",(function(t){"Enter"===t.key&&c()}))},trim:function(t,n){return t.replace(new RegExp("[?&]".concat(n,"=1\\b(?!&)|\\b").concat(n,"=1&")),"")}},a=i;window.Pagy=a}();
@@ -0,0 +1,118 @@
1
+ // The Pagy object
2
+ const Pagy = {
3
+ version: "5.7.3",
4
+ // Scan for "data-pagy-json" elements, parse their JSON content and call their init functions
5
+ init(arg) {
6
+ const target = arg instanceof Element ? arg : document;
7
+ const elements = target.querySelectorAll("[data-pagy-json]");
8
+ const warn = (el, err) => console.warn("Pagy.init() skipped element: %o\n%s", el, err);
9
+ for (const element of elements) {
10
+ const json = element.getAttribute("data-pagy-json");
11
+ try {
12
+ const [keyword, ...args] = JSON.parse(json);
13
+ if (keyword === "nav") {
14
+ Pagy.initNav(element, args);
15
+ }
16
+ else if (keyword === "combo") {
17
+ Pagy.initCombo(element, args);
18
+ }
19
+ else if (keyword === "selector") {
20
+ Pagy.initSelector(element, args);
21
+ }
22
+ else {
23
+ warn(element, `Illegal PagyJSON keyword: expected "nav"|"combo"|"selector", got "${keyword}"`);
24
+ }
25
+ }
26
+ catch (err) {
27
+ warn(element, err);
28
+ }
29
+ }
30
+ },
31
+ // Init the *_nav_js helpers
32
+ initNav(el, [tags, sequels, labelSequels, trimParam]) {
33
+ const container = el.parentElement ?? el;
34
+ const widths = Object.getOwnPropertyNames(sequels).map(w => parseInt(w)).sort((a, b) => b - a);
35
+ let lastWidth = -1;
36
+ const fillIn = (link, page, label) => link.replace(/__pagy_page__/g, page).replace(/__pagy_label__/g, label);
37
+ (el.pagyRender = function () {
38
+ const width = widths.find(w => w < container.clientWidth) || 0;
39
+ if (width === lastWidth) {
40
+ return;
41
+ } // no change: abort
42
+ let html = tags.before;
43
+ const series = sequels[width.toString()];
44
+ const labels = labelSequels?.[width.toString()] ?? series.map(l => l.toString());
45
+ for (const i in series) {
46
+ const item = series[i];
47
+ const label = labels[i];
48
+ if (typeof trimParam === "string" && item === 1) {
49
+ html += Pagy.trim(fillIn(tags.link, item.toString(), label), trimParam);
50
+ }
51
+ else if (typeof item === "number") {
52
+ html += fillIn(tags.link, item.toString(), label);
53
+ }
54
+ else if (item === "gap") {
55
+ html += tags.gap;
56
+ }
57
+ else { // active page
58
+ html += fillIn(tags.active, item, label);
59
+ }
60
+ }
61
+ html += tags.after; // eslint-disable-line align-assignments/align-assignments
62
+ el.innerHTML = "";
63
+ el.insertAdjacentHTML("afterbegin", html);
64
+ lastWidth = width;
65
+ })();
66
+ if (el.classList.contains("pagy-rjs")) {
67
+ Pagy.rjsObserver.observe(container);
68
+ }
69
+ },
70
+ // The observer instance for responsive navs
71
+ rjsObserver: new ResizeObserver(entries => {
72
+ entries.filter(e => e.contentBoxSize)
73
+ .forEach(e => e.target.querySelectorAll(".pagy-rjs")
74
+ .forEach(rjs => rjs.pagyRender()));
75
+ }),
76
+ // Init the *_combo_nav_js helpers
77
+ initCombo(el, [link, trimParam]) {
78
+ Pagy.initInput(el, inputValue => [inputValue, link.replace(/__pagy_page__/, inputValue)], trimParam);
79
+ },
80
+ // Init the items_selector_js helper
81
+ initSelector(el, [from, link, trimParam]) {
82
+ Pagy.initInput(el, inputValue => {
83
+ const page = Math.max(Math.ceil(from / parseInt(inputValue)), 1).toString();
84
+ const html = link.replace(/__pagy_page__/, page).replace(/__pagy_items__/, inputValue);
85
+ return [page, html];
86
+ }, trimParam);
87
+ },
88
+ // Init the input element
89
+ initInput(el, getVars, trimParam) {
90
+ const input = el.querySelector("input");
91
+ const initial = input.value;
92
+ const action = function () {
93
+ if (input.value === initial) {
94
+ return;
95
+ } // not changed
96
+ const [min, val, max] = [input.min, input.value, input.max].map(n => parseInt(n) || 0);
97
+ if (val < min || val > max) { // reset invalid/out-of-range
98
+ input.value = initial;
99
+ input.select();
100
+ return;
101
+ }
102
+ let [page, html] = getVars(input.value); // eslint-disable-line prefer-const
103
+ if (typeof trimParam === "string" && page === "1") {
104
+ html = Pagy.trim(html, trimParam);
105
+ }
106
+ el.insertAdjacentHTML("afterbegin", html);
107
+ el.querySelector("a").click();
108
+ };
109
+ ["change", "focus"].forEach(e => input.addEventListener(e, input.select)); // auto-select
110
+ input.addEventListener("focusout", action); // trigger action
111
+ input.addEventListener("keypress", e => { if (e.key === "Enter") {
112
+ action();
113
+ } }); // trigger action
114
+ },
115
+ // Trim the ${page-param}=1 params in links
116
+ trim: (link, param) => link.replace(new RegExp(`[?&]${param}=1\\b(?!&)|\\b${param}=1&`), "")
117
+ };
118
+ export default Pagy;
@@ -0,0 +1,26 @@
1
+ # :arabic pluralization (see https://github.com/ddnexus/pagy/blob/master/lib/locales/utils/p11n.rb)
2
+
3
+ ar:
4
+ pagy:
5
+
6
+ item_name:
7
+ zero: "صفر"
8
+ one: "عنصر"
9
+ two: "عنصرين"
10
+ few: "قليل"
11
+ many: "كثير"
12
+ other: "عناصر"
13
+
14
+ nav:
15
+ prev: "&lsaquo;&nbsp;السابق"
16
+ next: "التالي&nbsp;&rsaquo;"
17
+ gap: "&hellip;"
18
+
19
+ info:
20
+ no_items: "لا يوجد %{item_name}"
21
+ single_page: "عرض <b>%{count}</b> %{item_name}"
22
+ multiple_pages: "عرض %{item_name} <b>%{from}-%{to}</b> من اجمالي <b>%{count}</b>"
23
+
24
+ combo_nav_js: "الصفحة %{page_input} من %{pages}"
25
+
26
+ items_selector_js: "عرض %{items_input} %{item_name} لكل صفحة"
data/lib/locales/bg.yml CHANGED
@@ -17,6 +17,6 @@ bg:
17
17
  single_page: "Показани са <b>%{count}</b> %{item_name}"
18
18
  multiple_pages: "Показани са %{item_name} <b>%{from}-%{to}</b> от <b>%{count}</b> общо"
19
19
 
20
- combo_nav_js: "Страница %{page_input} от %{pages}"
20
+ combo_nav_js: "<label>Страница %{page_input} от %{pages}</label>"
21
21
 
22
- items_selector_js: "Покажи %{items_input} %{item_name} на страница"
22
+ items_selector_js: "<label>Покажи %{items_input} %{item_name} на страница</label>"