pagy 8.0.1 → 8.1.0

Sign up to get free protection for your applications and to get access to all the features.
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