pagy 8.0.1 → 8.1.0

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/{gem/apps → apps}/calendar.ru +1 -1
  3. data/{gem/apps → apps}/demo.ru +1 -1
  4. data/{gem/apps → apps}/rails.ru +10 -10
  5. data/{gem/apps → apps}/repro.ru +1 -1
  6. data/{gem/bin → bin}/pagy +1 -1
  7. data/{gem/config → config}/pagy.rb +9 -9
  8. data/javascripts/pagy-dev.js +114 -0
  9. data/{gem/javascripts → javascripts}/pagy-module.js +4 -2
  10. data/javascripts/pagy.js +1 -0
  11. data/{gem/lib → lib}/pagy/calendar/day.rb +1 -1
  12. data/{gem/lib → lib}/pagy/calendar/month.rb +1 -1
  13. data/{gem/lib → lib}/pagy/calendar/quarter.rb +1 -1
  14. data/{gem/lib → lib}/pagy/calendar/week.rb +1 -1
  15. data/{gem/lib → lib}/pagy/calendar/year.rb +1 -1
  16. data/{gem/lib → lib}/pagy/calendar.rb +4 -4
  17. data/{gem/lib → lib}/pagy/console.rb +2 -2
  18. data/{gem/lib → lib}/pagy/countless.rb +10 -7
  19. data/{gem/lib → lib}/pagy/extras/bootstrap.rb +2 -2
  20. data/{gem/lib → lib}/pagy/extras/bulma.rb +3 -2
  21. data/{gem/lib → lib}/pagy/extras/calendar.rb +2 -2
  22. data/{gem/lib → lib}/pagy/extras/countless.rb +1 -1
  23. data/{gem/lib → lib}/pagy/extras/foundation.rb +2 -2
  24. data/lib/pagy/extras/gearbox.rb +55 -0
  25. data/{gem/lib → lib}/pagy/extras/headers.rb +1 -1
  26. data/{gem/lib → lib}/pagy/extras/items.rb +2 -2
  27. data/{gem/lib → lib}/pagy/extras/js_tools.rb +3 -0
  28. data/{gem/lib → lib}/pagy/extras/jsonapi.rb +1 -1
  29. data/{gem/lib → lib}/pagy/extras/materialize.rb +3 -2
  30. data/{gem/lib → lib}/pagy/extras/metadata.rb +1 -1
  31. data/{gem/lib → lib}/pagy/extras/pagy.rb +2 -2
  32. data/{gem/lib → lib}/pagy/extras/semantic.rb +3 -2
  33. data/{gem/lib → lib}/pagy/extras/standalone.rb +2 -2
  34. data/{gem/lib → lib}/pagy/extras/uikit.rb +2 -2
  35. data/{gem/lib → lib}/pagy/frontend.rb +2 -2
  36. data/{gem/lib → lib}/pagy/url_helpers.rb +8 -8
  37. data/{gem/lib → lib}/pagy.rb +26 -28
  38. data/{gem/locales → locales}/ru.yml +5 -7
  39. metadata +93 -93
  40. data/gem/javascripts/pagy-dev.js +0 -112
  41. data/gem/javascripts/pagy.js +0 -1
  42. data/gem/lib/pagy/extras/gearbox.rb +0 -54
  43. /data/{gem/javascripts → javascripts}/pagy-module.d.ts +0 -0
  44. /data/{gem/lib → lib}/optimist.rb +0 -0
  45. /data/{gem/lib → lib}/pagy/backend.rb +0 -0
  46. /data/{gem/lib → lib}/pagy/calendar/helper.rb +0 -0
  47. /data/{gem/lib → lib}/pagy/exceptions.rb +0 -0
  48. /data/{gem/lib → lib}/pagy/extras/arel.rb +0 -0
  49. /data/{gem/lib → lib}/pagy/extras/array.rb +0 -0
  50. /data/{gem/lib → lib}/pagy/extras/elasticsearch_rails.rb +0 -0
  51. /data/{gem/lib → lib}/pagy/extras/i18n.rb +0 -0
  52. /data/{gem/lib → lib}/pagy/extras/meilisearch.rb +0 -0
  53. /data/{gem/lib → lib}/pagy/extras/overflow.rb +0 -0
  54. /data/{gem/lib → lib}/pagy/extras/searchkick.rb +0 -0
  55. /data/{gem/lib → lib}/pagy/extras/trim.rb +0 -0
  56. /data/{gem/lib → lib}/pagy/i18n.rb +0 -0
  57. /data/{gem/locales → locales}/ar.yml +0 -0
  58. /data/{gem/locales → locales}/be.yml +0 -0
  59. /data/{gem/locales → locales}/bg.yml +0 -0
  60. /data/{gem/locales → locales}/bs.yml +0 -0
  61. /data/{gem/locales → locales}/ca.yml +0 -0
  62. /data/{gem/locales → locales}/ckb.yml +0 -0
  63. /data/{gem/locales → locales}/cs.yml +0 -0
  64. /data/{gem/locales → locales}/da.yml +0 -0
  65. /data/{gem/locales → locales}/de.yml +0 -0
  66. /data/{gem/locales → locales}/en.yml +0 -0
  67. /data/{gem/locales → locales}/es.yml +0 -0
  68. /data/{gem/locales → locales}/fr.yml +0 -0
  69. /data/{gem/locales → locales}/hr.yml +0 -0
  70. /data/{gem/locales → locales}/id.yml +0 -0
  71. /data/{gem/locales → locales}/it.yml +0 -0
  72. /data/{gem/locales → locales}/ja.yml +0 -0
  73. /data/{gem/locales → locales}/km.yml +0 -0
  74. /data/{gem/locales → locales}/ko.yml +0 -0
  75. /data/{gem/locales → locales}/nb.yml +0 -0
  76. /data/{gem/locales → locales}/nl.yml +0 -0
  77. /data/{gem/locales → locales}/nn.yml +0 -0
  78. /data/{gem/locales → locales}/pl.yml +0 -0
  79. /data/{gem/locales → locales}/pt-BR.yml +0 -0
  80. /data/{gem/locales → locales}/pt.yml +0 -0
  81. /data/{gem/locales → locales}/sr.yml +0 -0
  82. /data/{gem/locales → locales}/sv-SE.yml +0 -0
  83. /data/{gem/locales → locales}/sv.yml +0 -0
  84. /data/{gem/locales → locales}/sw.yml +0 -0
  85. /data/{gem/locales → locales}/ta.yml +0 -0
  86. /data/{gem/locales → locales}/tr.yml +0 -0
  87. /data/{gem/locales → locales}/uk.yml +0 -0
  88. /data/{gem/locales → locales}/vi.yml +0 -0
  89. /data/{gem/locales → locales}/zh-CN.yml +0 -0
  90. /data/{gem/locales → locales}/zh-HK.yml +0 -0
  91. /data/{gem/locales → locales}/zh-TW.yml +0 -0
  92. /data/{gem/stylesheets → stylesheets}/pagy.css +0 -0
  93. /data/{gem/stylesheets → stylesheets}/pagy.scss +0 -0
  94. /data/{gem/stylesheets → stylesheets}/pagy.tailwind.css +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d43138bcedb3ad5c8a1ef97c80e2ebf873f592407d77e725cde2dae8be507472
4
- data.tar.gz: b92dc21e1d2aecd759a7b3caea7a2f32888fa61332690dd567255c2b3474d049
3
+ metadata.gz: 58dd8aedfd3cbff422189cea6a6ce7741a789648f637d81cbf2393c1d7f367bf
4
+ data.tar.gz: aa2e1eb12fbb6e4eb8c044f16ef88c1ec21eb12b2953c5d243ec1be3e89fbc1c
5
5
  SHA512:
6
- metadata.gz: c96cd67017eadce0279b19bcfa4e251424043264b9eae220d0136fa8820e01f7ec3a2911a0e99b17b0e9fca561114c5bcd91b5d81f884ab77e8ba77e77042321
7
- data.tar.gz: dec54c4ba97e64802a99dd25d753fc6c254a9ab336b17b668103e3d1c914e248830ff174c8965c46fda8c993ebab41c9ffdb4d51b1547c5e58ad925651895b21
6
+ metadata.gz: 7cbbd1cb07fce3aa859454fecb96db8d9011b258320304352d5df5c8e8489ac1a6d9bdbbbf63bcc67bab89fa36e46449999e1f8c333bb07613fbed53e10db88f
7
+ data.tar.gz: 561333556eda4acf895b0cca0ca45b7a23207ba6e5536f3c3cb288f1901a6f2b6d5b78e7c879450c256a81017633b68db6629b595a1a70dc0f00f64b4f126d01
@@ -18,7 +18,7 @@
18
18
  # DOC
19
19
  # https://ddnexus.github.io/pagy/playground/#4-calendar-app
20
20
 
21
- VERSION = '8.0.1'
21
+ VERSION = '8.1.0'
22
22
 
23
23
  require 'bundler/inline'
24
24
  gemfile(true) do
@@ -18,7 +18,7 @@
18
18
  # DOC
19
19
  # https://ddnexus.github.io/pagy/playground/#3-demo-app
20
20
 
21
- VERSION = '8.0.1'
21
+ VERSION = '8.1.0'
22
22
 
23
23
  require 'bundler/inline'
24
24
  gemfile(true) do
@@ -15,7 +15,7 @@
15
15
  # DOC
16
16
  # https://ddnexus.github.io/pagy/playground/#2-rails-app
17
17
 
18
- VERSION = '8.0.1'
18
+ VERSION = '8.1.0'
19
19
 
20
20
  # Gemfile
21
21
  require 'bundler/inline'
@@ -27,15 +27,6 @@ gemfile(true) do
27
27
  gem 'sqlite3'
28
28
  end
29
29
 
30
- # Pagy initializer
31
- require 'pagy/extras/pagy'
32
- require 'pagy/extras/items'
33
- require 'pagy/extras/overflow'
34
- Pagy::DEFAULT[:size] = [1, 4, 4, 1]
35
- Pagy::DEFAULT[:items] = 10
36
- Pagy::DEFAULT[:overflow] = :empty_page
37
- Pagy::DEFAULT.freeze
38
-
39
30
  # require 'rails/all' # too much stuff
40
31
  require 'action_controller/railtie'
41
32
  require 'active_record'
@@ -64,6 +55,15 @@ unless File.writable?(dir)
64
55
  exit 1
65
56
  end
66
57
 
58
+ # Pagy initializer
59
+ require 'pagy/extras/pagy'
60
+ require 'pagy/extras/items'
61
+ require 'pagy/extras/overflow'
62
+ Pagy::DEFAULT[:size] = [1, 4, 4, 1]
63
+ Pagy::DEFAULT[:items] = 10
64
+ Pagy::DEFAULT[:overflow] = :empty_page
65
+ Pagy::DEFAULT.freeze
66
+
67
67
  ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: "#{dir}/tmp/pagy-rails.sqlite3")
68
68
  ActiveRecord::Schema.define do
69
69
  create_table :posts, force: true do |t|
@@ -15,7 +15,7 @@
15
15
  # DOC
16
16
  # https://ddnexus.github.io/pagy/playground/#1-repro-app
17
17
 
18
- VERSION = '8.0.1'
18
+ VERSION = '8.1.0'
19
19
 
20
20
  require 'bundler/inline'
21
21
  gemfile(true) do
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- VERSION = '8.0.1'
4
+ VERSION = '8.1.0'
5
5
  APPS = %w[repro rails demo calendar].freeze
6
6
 
7
7
  require_relative '../lib/optimist'
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Pagy initializer file (8.0.1)
3
+ # Pagy initializer file (8.1.0)
4
4
  # Customize only what you really need and notice that the core Pagy works also without any of the following lines.
5
5
  # Should you just cherry pick part of this file, please maintain the require-order of the extras
6
6
 
@@ -18,14 +18,14 @@
18
18
 
19
19
  # Other Variables
20
20
  # See https://ddnexus.github.io/pagy/docs/api/pagy#other-variables
21
- # Pagy::DEFAULT[:size] = [1,4,4,1] # default in pagy < 7.0
22
- # Pagy::DEFAULT[:page_param] = :page # default
23
- # Pagy::DEFAULT[:fragment] = '#fragment' # example
24
- # Pagy::DEFAULT[:link_extra] = 'data-remote="true"' # example
25
- # Pagy::DEFAULT[:cycle] = true # example
26
- # Pagy::DEFAULT[:request_path] = '/foo' # example
27
- # Pagy::DEFAULT[:count_args] = [] # example for non AR ORMs
28
- # Pagy::DEFAULT[:params] = {} # default
21
+ # Pagy::DEFAULT[:size] = [1,4,4,1] # default in pagy < 7.0
22
+ # Pagy::DEFAULT[:page_param] = :page # default
23
+ # Pagy::DEFAULT[:fragment] = '#fragment' # example
24
+ # Pagy::DEFAULT[:anchor_string] = 'data-remote="true"' # example
25
+ # Pagy::DEFAULT[:cycle] = true # example
26
+ # Pagy::DEFAULT[:request_path] = '/foo' # example
27
+ # Pagy::DEFAULT[:count_args] = [] # example for non AR ORMs
28
+ # Pagy::DEFAULT[:params] = {} # default
29
29
  # NOTICE: The :params can be also set as a lambda e.g:
30
30
  # ->(params){ params.exclude('useless').merge!('custom' => 'useful') }
31
31
 
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ window.Pagy = (() => {
3
+ // The observer instance for responsive navs
4
+ const rjsObserver = new ResizeObserver(entries => entries.forEach(e => e.target.querySelectorAll(".pagy-rjs").forEach(el => el.pagyRender())));
5
+ // Init the *_nav_js helpers
6
+ const initNav = (el, [tokens, sequels, labelSequels, trimParam]) => {
7
+ const container = el.parentElement ?? el;
8
+ const widths = Object.keys(sequels).map(w => parseInt(w)).sort((a, b) => b - a);
9
+ let lastWidth = -1;
10
+ const fillIn = (a, page, label) => a.replace(/__pagy_page__/g, page).replace(/__pagy_label__/g, label);
11
+ (el.pagyRender = function () {
12
+ const width = widths.find(w => w < container.clientWidth) || 0;
13
+ if (width === lastWidth) {
14
+ return;
15
+ } // no change: abort
16
+ let html = tokens.before; // already trimmed in html
17
+ const series = sequels[width.toString()];
18
+ const labels = labelSequels?.[width.toString()] ?? series.map(l => l.toString());
19
+ for (const i in series) {
20
+ const item = series[i];
21
+ const label = labels[i];
22
+ let filled;
23
+ if (typeof item === "number") {
24
+ filled = fillIn(tokens.a, item.toString(), label);
25
+ }
26
+ else if (item === "gap") {
27
+ filled = tokens.gap;
28
+ }
29
+ else { // active page
30
+ filled = fillIn(tokens.current, item, label);
31
+ }
32
+ html += (typeof trimParam === "string" && item == 1) ? trim(filled, trimParam) : filled;
33
+ }
34
+ html += tokens.after; // eslint-disable-line align-assignments/align-assignments
35
+ el.innerHTML = "";
36
+ el.insertAdjacentHTML("afterbegin", html);
37
+ lastWidth = width;
38
+ })();
39
+ if (el.classList.contains("pagy-rjs")) {
40
+ rjsObserver.observe(container);
41
+ }
42
+ };
43
+ // Init the *_combo_nav_js helpers
44
+ const initCombo = (el, [url_token, trimParam]) => initInput(el, inputValue => [inputValue, url_token.replace(/__pagy_page__/, inputValue)], trimParam);
45
+ // Init the items_selector_js helper
46
+ const initSelector = (el, [from, url_token, trimParam]) => {
47
+ initInput(el, inputValue => {
48
+ const page = Math.max(Math.ceil(from / parseInt(inputValue)), 1).toString();
49
+ const url = url_token.replace(/__pagy_page__/, page).replace(/__pagy_items__/, inputValue);
50
+ return [page, url];
51
+ }, trimParam);
52
+ };
53
+ // Init the input element
54
+ const initInput = (el, getVars, trimParam) => {
55
+ const input = el.querySelector("input");
56
+ const link = el.querySelector("a");
57
+ const initial = input.value;
58
+ const action = function () {
59
+ if (input.value === initial) {
60
+ return;
61
+ } // not changed
62
+ const [min, val, max] = [input.min, input.value, input.max].map(n => parseInt(n) || 0);
63
+ if (val < min || val > max) { // reset invalid/out-of-range
64
+ input.value = initial;
65
+ input.select();
66
+ return;
67
+ }
68
+ let [page, url] = getVars(input.value); // eslint-disable-line prefer-const
69
+ if (typeof trimParam === "string" && page === "1") {
70
+ url = trim(url, trimParam);
71
+ }
72
+ link.href = url;
73
+ link.click();
74
+ };
75
+ ["change", "focus"].forEach(e => input.addEventListener(e, input.select)); // auto-select
76
+ input.addEventListener("focusout", action); // trigger action
77
+ input.addEventListener("keypress", e => { if (e.key === "Enter") {
78
+ action();
79
+ } }); // trigger action
80
+ };
81
+ // Trim the ${page-param}=1 params in links
82
+ const trim = (a, param) => a.replace(new RegExp(`[?&]${param}=1\\b(?!&)|\\b${param}=1&`), "");
83
+ // Public interface
84
+ return {
85
+ version: "8.1.0",
86
+ // Scan for elements with a "data-pagy" attribute and call their init functions with the decoded args
87
+ init(arg) {
88
+ const target = arg instanceof Element ? arg : document;
89
+ const elements = target.querySelectorAll("[data-pagy]");
90
+ for (const el of elements) {
91
+ try {
92
+ const uint8array = Uint8Array.from(atob(el.getAttribute("data-pagy")), c => c.charCodeAt(0));
93
+ const [keyword, ...args] = JSON.parse((new TextDecoder()).decode(uint8array)); // base64-utf8 -> JSON -> Array
94
+ if (keyword === "nav") {
95
+ initNav(el, args);
96
+ }
97
+ else if (keyword === "combo") {
98
+ initCombo(el, args);
99
+ }
100
+ else if (keyword === "selector") {
101
+ initSelector(el, args);
102
+ }
103
+ else {
104
+ console.warn("Skipped Pagy.init() for: %o\nUnknown keyword '%s'", el, keyword);
105
+ }
106
+ }
107
+ catch (err) {
108
+ console.warn("Skipped Pagy.init() for: %o\n%s", el, err);
109
+ }
110
+ }
111
+ }
112
+ };
113
+ })();
114
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFneS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInBhZ3kudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQWtCQSxNQUFNLElBQUksR0FBRyxDQUFDLEdBQUcsRUFBRTtJQUNmLDRDQUE0QztJQUM1QyxNQUFNLFdBQVcsR0FBRyxJQUFJLGNBQWMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUNOLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFhLFdBQVcsQ0FBQyxDQUFDLE9BQU8sQ0FDM0UsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFeEUsNEJBQTRCO0lBQzVCLE1BQU0sT0FBTyxHQUFHLENBQUMsRUFBYSxFQUFFLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsU0FBUyxDQUFTLEVBQUUsRUFBRTtRQUNsRixNQUFNLFNBQVMsR0FBRyxFQUFFLENBQUMsYUFBYSxJQUFJLEVBQUUsQ0FBQztRQUN6QyxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNoRixJQUFJLFNBQVMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNuQixNQUFNLE1BQU0sR0FBRyxDQUFDLENBQVEsRUFBRSxJQUFXLEVBQUUsS0FBWSxFQUFTLEVBQUUsQ0FDMUQsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDeEUsQ0FBQyxFQUFFLENB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TyxHQUFHLEVBQUUsQ0FBQztvQkFBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGlDQUFpQyxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUMsQ0FBQTtnQkFBQyxDQUFDO1lBQzlFLENBQUM7UUFDTCxDQUFDO0tBQ0osQ0FBQztBQUNOLENBQUMsQ0FBQyxFQUFFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJ0eXBlIE5hdkFyZ3MgPSByZWFkb25seSBbVG9rZW5zLCBTZXF1ZWxzLCBudWxsIHwgTGFiZWxTZXF1ZWxzLCBzdHJpbmc/XVxudHlwZSBDb21ib0FyZ3MgPSByZWFkb25seSBbc3RyaW5nLCBzdHJpbmc/XVxudHlwZSBTZWxlY3RvckFyZ3MgPSByZWFkb25seSBbbnVtYmVyLCBzdHJpbmcsIHN0cmluZz9dXG5cbmludGVyZmFjZSBUb2tlbnMge1xuICAgIHJlYWRvbmx5IGJlZm9yZTpzdHJpbmdcbiAgICByZWFkb25seSBhOnN0cmluZ1xuICAgIHJlYWRvbmx5IGN1cnJlbnQ6c3RyaW5nXG4gICAgcmVhZG9ubHkgZ2FwOnN0cmluZ1xuICAgIHJlYWRvbmx5IGFmdGVyOnN0cmluZ1xufVxuXG5pbnRlcmZhY2UgU2VxdWVscyB7cmVhZG9ubHkgW3dpZHRoOnN0cmluZ106KHN0cmluZyB8IG51bWJlcilbXX1cblxuaW50ZXJmYWNlIExhYmVsU2VxdWVscyB7cmVhZG9ubHkgW3dpZHRoOnN0cmluZ106c3RyaW5nW119XG5cbmludGVyZmFjZSBOYXZFbGVtZW50IGV4dGVuZHMgRWxlbWVudCB7cGFneVJlbmRlcigpOnZvaWR9XG5cbmNvbnN0IFBhZ3kgPSAoKCkgPT4ge1xuICAgIC8vIFRoZSBvYnNlcnZlciBpbnN0YW5jZSBmb3IgcmVzcG9uc2l2ZSBuYXZzXG4gICAgY29uc3QgcmpzT2JzZXJ2ZXIgPSBuZXcgUmVzaXplT2JzZXJ2ZXIoZW50cmllcyA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbnRyaWVzLmZvckVhY2goZSA9PiBlLnRhcmdldC5xdWVyeVNlbGVjdG9yQWxsPE5hdkVsZW1lbnQ+KFwiLnBhZ3ktcmpzXCIpLmZvckVhY2goXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbCA9PiBlbC5wYWd5UmVuZGVyKCkpKSk7XG5cbiAgICAvLyBJbml0IHRoZSAqX25hdl9qcyBoZWxwZXJzXG4gICAgY29uc3QgaW5pdE5hdiA9IChlbDpOYXZFbGVtZW50LCBbdG9rZW5zLCBzZXF1ZWxzLCBsYWJlbFNlcXVlbHMsIHRyaW1QYXJhbV06TmF2QXJncykgPT4ge1xuICAgICAgICBjb25zdCBjb250YWluZXIgPSBlbC5wYXJlbnRFbGVtZW50ID8/IGVsO1xuICAgICAgICBjb25zdCB3aWR0aHMgPSBPYmplY3Qua2V5cyhzZXF1ZWxzKS5tYXAodyA9PiBwYXJzZUludCh3KSkuc29ydCgoYSwgYikgPT4gYiAtIGEpO1xuICAgICAgICBsZXQgbGFzdFdpZHRoID0gLTE7XG4gICAgICAgIGNvbnN0IGZpbGxJbiA9IChhOnN0cmluZywgcGFnZTpzdHJpbmcsIGxhYmVsOnN0cmluZyk6c3RyaW5nID0+XG4gICAgICAgICAgICBhLnJlcGxhY2UoL19fcGFneV9wYWdlX18vZywgcGFnZSkucmVwbGFjZSgvX19wYWd5X2xhYmVsX18vZywgbGFiZWwpO1xuICAgICAgICAoZWwucGFneVJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gd2lkdGhzLmZpbmQodyA9PiB3IDwgY29udGFpbmVyLmNsaWVudFdpZHRoKSB8fCAwO1xuICAgICAgICAgICAgaWYgKHdpZHRoID09PSBsYXN0V2lkdGgpIHsgcmV0dXJuIH0gLy8gbm8gY2hhbmdlOiBhYm9ydFxuICAgICAgICAgICAgbGV0IGh0bWwgPSB0b2tlbnMuYmVmb3JlOyAgLy8gYWxyZWFkeSB0cmltbWVkIGluIGh0bWxcbiAgICAgICAgICAgIGNvbnN0IHNlcmllcyA9IHNlcXVlbHNbd2lkdGgudG9TdHJpbmcoKV07XG4gICAgICAgICAgICBjb25zdCBsYWJlbHMgPSBsYWJlbFNlcXVlbHM/Llt3aWR0aC50b1N0cmluZygpXSA/PyBzZXJpZXMubWFwKGwgPT4gbC50b1N0cmluZygpKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgaSBpbiBzZXJpZXMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBpdGVtID0gc2VyaWVzW2ldO1xuICAgICAgICAgICAgICAgIGNvbnN0IGxhYmVsID0gbGFiZWxzW2ldO1xuICAgICAgICAgICAgICAgIGxldCBmaWxsZWQ7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBpdGVtID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpbGxlZCA9IGZpbGxJbih0b2tlbnMuYSwgaXRlbS50b1N0cmluZygpLCBsYWJlbCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpdGVtID09PSBcImdhcFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpbGxlZCA9IHRva2Vucy5nYXA7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHsgLy8gYWN0aXZlIHBhZ2VcbiAgICAgICAgICAgICAgICAgICAgZmlsbGVkID0gZmlsbEluKHRva2Vucy5jdXJyZW50LCBpdGVtLCBsYWJlbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGh0bWwgKz0gKHR5cGVvZiB0cmltUGFyYW0gPT09IFwic3RyaW5nXCIgJiYgaXRlbSA9PSAxKSA/IHRyaW0oZmlsbGVkLCB0cmltUGFyYW0pIDogZmlsbGVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaHRtbCArPSB0b2tlbnMuYWZ0ZXI7ICAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBhbGlnbi1hc3NpZ25tZW50cy9hbGlnbi1hc3NpZ25tZW50c1xuICAgICAgICAgICAgZWwuaW5uZXJIVE1MID0gXCJcIjtcbiAgICAgICAgICAgIGVsLmluc2VydEFkamFjZW50SFRNTChcImFmdGVyYmVnaW5cIiwgaHRtbCk7XG4gICAgICAgICAgICBsYXN0V2lkdGggPSB3aWR0aDtcbiAgICAgICAgfSkoKTtcbiAgICAgICAgaWYgKGVsLmNsYXNzTGlzdC5jb250YWlucyhcInBhZ3ktcmpzXCIpKSB7IHJqc09ic2VydmVyLm9ic2VydmUoY29udGFpbmVyKSB9XG4gICAgfTtcblxuICAgIC8vIEluaXQgdGhlICpfY29tYm9fbmF2X2pzIGhlbHBlcnNcbiAgICBjb25zdCBpbml0Q29tYm8gPSAoZWw6RWxlbWVudCwgW3VybF90b2tlbiwgdHJpbVBhcmFtXTpDb21ib0FyZ3MpID0+XG4gICAgICAgIGluaXRJbnB1dChlbCwgaW5wdXRWYWx1ZSA9PiBbaW5wdXRWYWx1ZSwgdXJsX3Rva2VuLnJlcGxhY2UoL19fcGFneV9wYWdlX18vLCBpbnB1dFZhbHVlKV0sIHRyaW1QYXJhbSk7XG5cbiAgICAvLyBJbml0IHRoZSBpdGVtc19zZWxlY3Rvcl9qcyBoZWxwZXJcbiAgICBjb25zdCBpbml0U2VsZWN0b3IgPSAoZWw6RWxlbWVudCwgW2Zyb20sIHVybF90b2tlbiwgdHJpbVBhcmFtXTpTZWxlY3RvckFyZ3MpID0+IHtcbiAgICAgICAgaW5pdElucHV0KGVsLCBpbnB1dFZhbHVlID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHBhZ2UgPSBNYXRoLm1heChNYXRoLmNlaWwoZnJvbSAvIHBhcnNlSW50KGlucHV0VmFsdWUpKSwgMSkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGNvbnN0IHVybCA9IHVybF90b2tlbi5yZXBsYWNlKC9fX3BhZ3lfcGFnZV9fLywgcGFnZSkucmVwbGFjZSgvX19wYWd5X2l0ZW1zX18vLCBpbnB1dFZhbHVlKTtcbiAgICAgICAgICAgIHJldHVybiBbcGFnZSwgdXJsXTtcbiAgICAgICAgfSwgdHJpbVBhcmFtKTtcbiAgICB9O1xuXG4gICAgLy8gSW5pdCB0aGUgaW5wdXQgZWxlbWVudFxuICAgIGNvbnN0IGluaXRJbnB1dCA9IChlbDpFbGVtZW50LCBnZXRWYXJzOih2OnN0cmluZykgPT4gW3N0cmluZywgc3RyaW5nXSwgdHJpbVBhcmFtPzpzdHJpbmcpID0+IHtcbiAgICAgICAgY29uc3QgaW5wdXQgPSBlbC5xdWVyeVNlbGVjdG9yKFwiaW5wdXRcIikgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICAgICAgY29uc3QgbGluayA9IGVsLnF1ZXJ5U2VsZWN0b3IoXCJhXCIpIGFzIEhUTUxBbmNob3JFbGVtZW50O1xuICAgICAgICBjb25zdCBpbml0aWFsID0gaW5wdXQudmFsdWU7XG4gICAgICAgIGNvbnN0IGFjdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChpbnB1dC52YWx1ZSA9PT0gaW5pdGlhbCkgeyByZXR1cm4gfSAgLy8gbm90IGNoYW5nZWRcbiAgICAgICAgICAgIGNvbnN0IFttaW4sIHZhbCwgbWF4XSA9IFtpbnB1dC5taW4sIGlucHV0LnZhbHVlLCBpbnB1dC5tYXhdLm1hcChuID0+IHBhcnNlSW50KG4pIHx8IDApO1xuICAgICAgICAgICAgaWYgKHZhbCA8IG1pbiB8fCB2YWwgPiBtYXgpIHsgIC8vIHJlc2V0IGludmFsaWQvb3V0LW9mLXJhbmdlXG4gICAgICAgICAgICAgICAgaW5wdXQudmFsdWUgPSBpbml0aWFsO1xuICAgICAgICAgICAgICAgIGlucHV0LnNlbGVjdCgpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBbcGFnZSwgdXJsXSA9IGdldFZhcnMoaW5wdXQudmFsdWUpOyAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgcHJlZmVyLWNvbnN0XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRyaW1QYXJhbSA9PT0gXCJzdHJpbmdcIiAmJiBwYWdlID09PSBcIjFcIikgeyB1cmwgPSB0cmltKHVybCwgdHJpbVBhcmFtKSB9XG4gICAgICAgICAgICBsaW5rLmhyZWYgPSB1cmw7XG4gICAgICAgICAgICBsaW5rLmNsaWNrKCk7XG4gICAgICAgIH07XG4gICAgICAgIFtcImNoYW5nZVwiLCBcImZvY3VzXCJdLmZvckVhY2goZSA9PiBpbnB1dC5hZGRFdmVudExpc3RlbmVyKGUsIGlucHV0LnNlbGVjdCkpOyAgICAgICAgLy8gYXV0by1zZWxlY3RcbiAgICAgICAgaW5wdXQuYWRkRXZlbnRMaXN0ZW5lcihcImZvY3Vzb3V0XCIsIGFjdGlvbik7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdHJpZ2dlciBhY3Rpb25cbiAgICAgICAgaW5wdXQuYWRkRXZlbnRMaXN0ZW5lcihcImtleXByZXNzXCIsIGUgPT4geyBpZiAoZS5rZXkgPT09IFwiRW50ZXJcIikgeyBhY3Rpb24oKSB9IH0pOyAvLyB0cmlnZ2VyIGFjdGlvblxuICAgIH07XG5cbiAgICAvLyBUcmltIHRoZSAke3BhZ2UtcGFyYW19PTEgcGFyYW1zIGluIGxpbmtzXG4gICAgY29uc3QgdHJpbSA9IChhOnN0cmluZywgcGFyYW06c3RyaW5nKSA9PlxuICAgICAgICBhLnJlcGxhY2UobmV3IFJlZ0V4cChgWz8mXSR7cGFyYW19PTFcXFxcYig/ISYpfFxcXFxiJHtwYXJhbX09MSZgKSwgXCJcIik7XG5cbiAgICAvLyBQdWJsaWMgaW50ZXJmYWNlXG4gICAgcmV0dXJuIHtcbiAgICAgICAgdmVyc2lvbjogXCI4LjEuMFwiLFxuXG4gICAgICAgIC8vIFNjYW4gZm9yIGVsZW1lbnRzIHdpdGggYSBcImRhdGEtcGFneVwiIGF0dHJpYnV0ZSBhbmQgY2FsbCB0aGVpciBpbml0IGZ1bmN0aW9ucyB3aXRoIHRoZSBkZWNvZGVkIGFyZ3NcbiAgICAgICAgaW5pdChhcmc/OkVsZW1lbnQgfCBuZXZlcikge1xuICAgICAgICAgICAgY29uc3QgdGFyZ2V0ID0gYXJnIGluc3RhbmNlb2YgRWxlbWVudCA/IGFyZyA6IGRvY3VtZW50O1xuICAgICAgICAgICAgY29uc3QgZWxlbWVudHMgPSB0YXJnZXQucXVlcnlTZWxlY3RvckFsbChcIltkYXRhLXBhZ3ldXCIpO1xuICAgICAgICAgICAgZm9yIChjb25zdCBlbCBvZiBlbGVtZW50cykge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHVpbnQ4YXJyYXkgPSBVaW50OEFycmF5LmZyb20oYXRvYihlbC5nZXRBdHRyaWJ1dGUoXCJkYXRhLXBhZ3lcIikgYXMgc3RyaW5nKSwgYyA9PiBjLmNoYXJDb2RlQXQoMCkpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBba2V5d29yZCwgLi4uYXJnc10gPSBKU09OLnBhcnNlKChuZXcgVGV4dERlY29kZXIoKSkuZGVjb2RlKHVpbnQ4YXJyYXkpKTsgLy8gYmFzZTY0LXV0ZjggLT4gSlNPTiAtPiBBcnJheVxuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5d29yZCA9PT0gXCJuYXZcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdE5hdihlbCBhcyBOYXZFbGVtZW50LCBhcmdzIGFzIE5hdkFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGtleXdvcmQgPT09IFwiY29tYm9cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdENvbWJvKGVsLCBhcmdzIGFzIENvbWJvQXJncyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoa2V5d29yZCA9PT0gXCJzZWxlY3RvclwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbml0U2VsZWN0b3IoZWwsIGFyZ3MgYXMgU2VsZWN0b3JBcmdzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlNraXBwZWQgUGFneS5pbml0KCkgZm9yOiAlb1xcblVua25vd24ga2V5d29yZCAnJXMnXCIsIGVsLCBrZXl3b3JkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikgeyBjb25zb2xlLndhcm4oXCJTa2lwcGVkIFBhZ3kuaW5pdCgpIGZvcjogJW9cXG4lc1wiLCBlbCwgZXJyKSB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xufSkoKTtcbiJdfQ==
@@ -52,6 +52,7 @@ const Pagy = (() => {
52
52
  // Init the input element
53
53
  const initInput = (el, getVars, trimParam) => {
54
54
  const input = el.querySelector("input");
55
+ const link = el.querySelector("a");
55
56
  const initial = input.value;
56
57
  const action = function () {
57
58
  if (input.value === initial) {
@@ -67,7 +68,8 @@ const Pagy = (() => {
67
68
  if (typeof trimParam === "string" && page === "1") {
68
69
  url = trim(url, trimParam);
69
70
  }
70
- window.location.href = url;
71
+ link.href = url;
72
+ link.click();
71
73
  };
72
74
  ["change", "focus"].forEach(e => input.addEventListener(e, input.select)); // auto-select
73
75
  input.addEventListener("focusout", action); // trigger action
@@ -79,7 +81,7 @@ const Pagy = (() => {
79
81
  const trim = (a, param) => a.replace(new RegExp(`[?&]${param}=1\\b(?!&)|\\b${param}=1&`), "");
80
82
  // Public interface
81
83
  return {
82
- version: "8.0.1",
84
+ version: "8.1.0",
83
85
  // Scan for elements with a "data-pagy" attribute and call their init functions with the decoded args
84
86
  init(arg) {
85
87
  const target = arg instanceof Element ? arg : document;
@@ -0,0 +1 @@
1
+ !function(){let e=(()=>{let e=new ResizeObserver(e=>e.forEach(e=>e.target.querySelectorAll(".pagy-rjs").forEach(e=>e.pagyRender()))),t=(t,[r,a,n,l])=>{let i=t.parentElement??t,c=Object.keys(a).map(e=>parseInt(e)).sort((e,t)=>t-e),p=-1,s=(e,t,r)=>e.replace(/__pagy_page__/g,t).replace(/__pagy_label__/g,r);(t.pagyRender=function(){let e=c.find(e=>e<i.clientWidth)||0;if(e===p)return;let g=r.before,y=a[e.toString()],f=n?.[e.toString()]??y.map(e=>e.toString());for(let e in y){let t;let a=y[e],n=f[e];t="number"==typeof a?s(r.a,a.toString(),n):"gap"===a?r.gap:s(r.current,a,n),g+="string"==typeof l&&1==a?o(t,l):t}g+=r.after,t.innerHTML="",t.insertAdjacentHTML("afterbegin",g),p=e})(),t.classList.contains("pagy-rjs")&&e.observe(i)},r=(e,[t,r])=>n(e,e=>[e,t.replace(/__pagy_page__/,e)],r),a=(e,[t,r,a])=>{n(e,e=>{let a=Math.max(Math.ceil(t/parseInt(e)),1).toString(),n=r.replace(/__pagy_page__/,a).replace(/__pagy_items__/,e);return[a,n]},a)},n=(e,t,r)=>{let a=e.querySelector("input"),n=e.querySelector("a"),l=a.value,i=function(){if(a.value===l)return;let[e,i,c]=[a.min,a.value,a.max].map(e=>parseInt(e)||0);if(i<e||i>c){a.value=l,a.select();return}let[p,s]=t(a.value);"string"==typeof r&&"1"===p&&(s=o(s,r)),n.href=s,n.click()};["change","focus"].forEach(e=>a.addEventListener(e,a.select)),a.addEventListener("focusout",i),a.addEventListener("keypress",e=>{"Enter"===e.key&&i()})},o=(e,t)=>e.replace(RegExp(`[?&]${t}=1\\b(?!&)|\\b${t}=1&`),"");return{version:"8.1.0",init(e){for(let n of(e instanceof Element?e:document).querySelectorAll("[data-pagy]"))try{let e=Uint8Array.from(atob(n.getAttribute("data-pagy")),e=>e.charCodeAt(0)),[o,...l]=JSON.parse(new TextDecoder().decode(e));"nav"===o?t(n,l):"combo"===o?r(n,l):"selector"===o?a(n,l):console.warn("Skipped Pagy.init() for: %o\nUnknown keyword '%s'",n,o)}catch(e){console.warn("Skipped Pagy.init() for: %o\n%s",n,e)}}}})();window.Pagy=e}();
@@ -16,7 +16,7 @@ class Pagy # :nodoc:
16
16
  super
17
17
  @initial = @starting.beginning_of_day
18
18
  @final = @ending.tomorrow.beginning_of_day
19
- @pages = @last = page_offset(@initial, @final)
19
+ @last = page_offset(@initial, @final)
20
20
  @from = starting_time_for(@page)
21
21
  @to = @from.tomorrow
22
22
  end
@@ -16,7 +16,7 @@ class Pagy # :nodoc:
16
16
  super
17
17
  @initial = @starting.beginning_of_month
18
18
  @final = @ending.next_month.beginning_of_month
19
- @pages = @last = (months_in(@final) - months_in(@initial))
19
+ @last = (months_in(@final) - months_in(@initial))
20
20
  @from = starting_time_for(@page)
21
21
  @to = @from.next_month
22
22
  end
@@ -23,7 +23,7 @@ class Pagy # :nodoc:
23
23
  super
24
24
  @initial = @starting.beginning_of_quarter
25
25
  @final = @ending.next_quarter.beginning_of_quarter
26
- @pages = @last = (months_in(@final) - months_in(@initial)) / 3
26
+ @last = (months_in(@final) - months_in(@initial)) / 3
27
27
  @from = starting_time_for(@page)
28
28
  @to = @from.next_quarter
29
29
  end
@@ -15,7 +15,7 @@ class Pagy # :nodoc:
15
15
  super
16
16
  @initial = @starting.beginning_of_week
17
17
  @final = @ending.next_week.beginning_of_week
18
- @pages = @last = page_offset(@initial, @final)
18
+ @last = page_offset(@initial, @final)
19
19
  @from = starting_time_for(@page)
20
20
  @to = @from.next_week
21
21
  end
@@ -16,7 +16,7 @@ class Pagy # :nodoc:
16
16
  super
17
17
  @initial = @starting.beginning_of_year
18
18
  @final = @ending.next_year.beginning_of_year
19
- @pages = @last = @final.year - @initial.year
19
+ @last = @final.year - @initial.year
20
20
  @from = starting_time_for(@page)
21
21
  @to = @from.next_year
22
22
  end
@@ -7,7 +7,7 @@ require 'active_support/core_ext/date_and_time/calculations'
7
7
  require 'active_support/core_ext/numeric/time'
8
8
  require 'active_support/core_ext/integer/time'
9
9
 
10
- require 'pagy'
10
+ require_relative '../pagy'
11
11
 
12
12
  class Pagy # :nodoc:
13
13
  # Base class for time units subclasses (Year, Quarter, Month, Week, Day)
@@ -67,14 +67,14 @@ class Pagy # :nodoc:
67
67
  Warning.warn "Pagy::Calendar#page_at: Rescued #{time} out of range by returning the #{ordinal} page."
68
68
  end
69
69
  offset = page_offset_at(fit_time) # offset starts from 0
70
- @order == :asc ? offset + 1 : @pages - offset
70
+ @order == :asc ? offset + 1 : @last - offset
71
71
  end
72
72
 
73
73
  # Base class method for the setup of the unit variables (subclasses must implement it and call super)
74
74
  def setup_unit_vars
75
75
  raise VariableError.new(self, :format, 'to be a strftime format', @vars[:format]) unless @vars[:format].is_a?(String)
76
76
  raise VariableError.new(self, :order, 'to be in [:asc, :desc]', @order) \
77
- unless %i[asc desc].include?(@order = @vars[:order])
77
+ unless %i[asc desc].include?((@order = @vars[:order]))
78
78
 
79
79
  @starting, @ending = @vars[:period]
80
80
  raise VariableError.new(self, :period, 'to be a an Array of min and max TimeWithZone instances', @vars[:period]) \
@@ -90,7 +90,7 @@ class Pagy # :nodoc:
90
90
  # Number of time units to offset from the @initial time, in order to get the ordered starting time for the page.
91
91
  # Used in starting_time_for(page) where page starts from 1 (e.g. page to starting_time means subtracting 1)
92
92
  def time_offset_for(page)
93
- @order == :asc ? page - 1 : @pages - page
93
+ @order == :asc ? page - 1 : @last - page
94
94
  end
95
95
 
96
96
  # Period of the active page (used internally for nested units)
@@ -1,8 +1,8 @@
1
1
  # See Pagy::Console API documentation: https://ddnexus.github.io/pagy/docs/api/console
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy' # so you can require just the extra in the console
5
- require 'pagy/extras/standalone'
4
+ require_relative '../pagy' # so you can require just the extra in the console
5
+ require_relative 'extras/standalone'
6
6
 
7
7
  class Pagy
8
8
  # Provide a ready to use pagy environment when included in irb/rails console
@@ -1,7 +1,7 @@
1
1
  # See Pagy::Countless API documentation: https://ddnexus.github.io/pagy/docs/api/countless
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy'
4
+ require_relative '../pagy'
5
5
 
6
6
  class Pagy
7
7
  # No need to know the count to paginate
@@ -19,12 +19,15 @@ class Pagy
19
19
  def finalize(fetched_size)
20
20
  raise OverflowError.new(self, :page, "to be < #{@page}", @page) if fetched_size.zero? && @page > 1
21
21
 
22
- @pages = @last = (fetched_size > @items ? @page + 1 : @page)
23
- @in = [fetched_size, @items].min
24
- @from = @in.zero? ? 0 : @offset - @outset + 1
25
- @to = @offset - @outset + @in
26
- @prev = (@page - 1 unless @page == 1)
27
- @next = @page == @last ? (1 if @vars[:cycle]) : @page + 1
22
+ @last = fetched_size > @items ? @page + 1 : @page
23
+ @last = vars[:max_pages] if vars[:max_pages] && @last > vars[:max_pages]
24
+ raise OverflowError.new(self, :page, "in 1..#{@last}", @page) if @page > @last
25
+
26
+ @in = [fetched_size, @items].min
27
+ @from = @in.zero? ? 0 : @offset - @outset + 1
28
+ @to = @offset - @outset + @in
29
+ @prev = (@page - 1 unless @page == 1)
30
+ @next = @page == @last ? (1 if @vars[:cycle]) : @page + 1
28
31
  self
29
32
  end
30
33
 
@@ -1,7 +1,7 @@
1
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/js_tools'
4
+ require_relative 'js_tools'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  # Frontend modules are specially optimized for performance.
@@ -57,7 +57,7 @@ class Pagy # :nodoc:
57
57
 
58
58
  page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page" ) <<
59
59
  %(style="text-align: center; width: #{pages.to_s.length + 1}rem; padding: 0; ) <<
60
- %(border: none; display: inline-block;" class="page-link active">)
60
+ %(border: none; display: inline-block;" class="page-link active">#{JSTools::A_TAG})
61
61
 
62
62
  %(<nav#{id} class="pagy-bootstrap combo-nav-js" #{
63
63
  nav_aria_label(pagy, aria_label:)} #{
@@ -1,7 +1,7 @@
1
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/js_tools'
4
+ require_relative 'js_tools'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  # Frontend modules are specially optimized for performance.
@@ -56,7 +56,8 @@ class Pagy # :nodoc:
56
56
 
57
57
  page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page") <<
58
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; background-color: #485fc7;">)
59
+ %(border: none; border-radius: 4px; padding: 0; font-size: 1.1rem; color: white; ) <<
60
+ %(background-color: #485fc7;">#{JSTools::A_TAG})
60
61
 
61
62
  %(<nav#{id} class="#{classes}" #{
62
63
  nav_aria_label(pagy, aria_label:)} #{
@@ -1,8 +1,8 @@
1
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'
5
- require 'pagy/calendar/helper'
4
+ require_relative '../calendar'
5
+ require_relative '../calendar/helper'
6
6
 
7
7
  class Pagy # :nodoc:
8
8
  # Add pagination filtering by calendar unit (:year, :quarter, :month, :week, :day) to the regular pagination
@@ -1,7 +1,7 @@
1
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
@@ -1,7 +1,7 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/foundation
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/extras/js_tools'
4
+ require_relative 'js_tools'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  # Frontend modules are specially optimized for performance.
@@ -55,7 +55,7 @@ class Pagy # :nodoc:
55
55
 
56
56
  page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page" ) <<
57
57
  %(style="text-align: center; width: #{pages.to_s.length + 1}rem; ) <<
58
- %(height: 1.5rem; padding: .5rem; margin: 0 .4rem; font-size: .875rem;" class="current">)
58
+ %(height: 1.5rem; padding: .5rem; margin: 0 .4rem; font-size: .875rem;" class="current">#{JSTools::A_TAG})
59
59
 
60
60
  %(<nav#{id} class="pagy-foundation-combo-nav-js" #{
61
61
  nav_aria_label(pagy, aria_label:)} #{
@@ -0,0 +1,55 @@
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
+ gears = @vars[:gearbox_items]
16
+ raise VariableError.new(self, :gearbox_items, 'to be an Array of positives', gears) \
17
+ unless gears.is_a?(Array) && gears.all? { |num| num.positive? rescue false } # rubocop:disable Style/RescueModifier
18
+
19
+ @items = gears[@page - 1] || gears.last
20
+ end
21
+
22
+ # Setup Pagy @last based on the :gearbox_items variable and @count
23
+ def setup_last_var
24
+ return super if !@vars[:gearbox_extra] || @vars[:items_extra]
25
+
26
+ gears = @vars[:gearbox_items]
27
+ # This algorithm is thousands of times faster than the one in the geared_pagination gem
28
+ @last = (if count > (sum = gears.sum)
29
+ [((count - sum).to_f / gears.last).ceil, 1].max + gears.count
30
+ else
31
+ pages = 0
32
+ remainder = count
33
+ while remainder.positive?
34
+ pages += 1
35
+ remainder -= gears[pages - 1]
36
+ end
37
+ [pages, 1].max
38
+ end)
39
+ @last = vars[:max_pages] if vars[:max_pages] && @last > vars[:max_pages]
40
+ end
41
+
42
+ # Setup @offset based on the :gearbox_items variable
43
+ def setup_offset_var
44
+ return super if !@vars[:gearbox_extra] || @vars[:items_extra]
45
+
46
+ gears = @vars[:gearbox_items]
47
+ @offset = if @page <= gears.count
48
+ gears[0, @page - 1].sum
49
+ else
50
+ gears.sum + (gears.last * (@page - gears.count - 1))
51
+ end + @outset
52
+ end
53
+ end
54
+ prepend GearboxExtra
55
+ end
@@ -1,7 +1,7 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/headers
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/url_helpers'
4
+ require_relative '../url_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  DEFAULT[:headers] = { page: 'current-page',
@@ -1,7 +1,7 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/items
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/extras/js_tools'
4
+ require_relative 'js_tools'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  DEFAULT[:items_param] = :items
@@ -47,7 +47,7 @@ class Pagy # :nodoc:
47
47
  vars[:items] = items # restore the items
48
48
 
49
49
  items_input = %(<input name="items" type="number" min="1" max="#{vars[:max_items]}" value="#{
50
- items}" style="padding: 0; text-align: center; width: #{items.to_s.length + 1}rem;">)
50
+ items}" style="padding: 0; text-align: center; width: #{items.to_s.length + 1}rem;">#{JSTools::A_TAG})
51
51
 
52
52
  %(<span#{id} class="pagy items-selector-js" #{
53
53
  pagy_data(pagy, :selector, pagy.from, url_token)
@@ -5,6 +5,9 @@ class Pagy # :nodoc:
5
5
 
6
6
  # Private module documented in the main classes
7
7
  module JSTools
8
+ # Dummy tag for input helpers: needed because Turbo does not intercept window.location changes
9
+ A_TAG = '<a href="#" style="display: none;">#</a>'
10
+
8
11
  # Additions for the Pagy class
9
12
  module PagyAddOn
10
13
  # `Pagy` instance method used by the `pagy*_nav_js` helpers.
@@ -1,7 +1,7 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/jsonapi
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/url_helpers'
4
+ require_relative '../url_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  DEFAULT[:jsonapi] = true