pagy 3.13.0 → 4.4.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.
- checksums.yaml +4 -4
- data/lib/config/pagy.rb +36 -25
- data/lib/javascripts/pagy.js +60 -56
- data/lib/locales/utils/i18n.rb +3 -11
- data/lib/locales/utils/loader.rb +7 -10
- data/lib/locales/utils/p11n.rb +24 -20
- data/lib/pagy.rb +51 -40
- data/lib/pagy/backend.rb +5 -3
- data/lib/pagy/countless.rb +13 -10
- data/lib/pagy/deprecation.rb +27 -0
- data/lib/pagy/exceptions.rb +7 -5
- data/lib/pagy/extras/arel.rb +4 -3
- data/lib/pagy/extras/array.rb +4 -3
- data/lib/pagy/extras/bootstrap.rb +62 -30
- data/lib/pagy/extras/bulma.rb +61 -38
- data/lib/pagy/extras/countless.rb +7 -8
- data/lib/pagy/extras/elasticsearch_rails.rb +28 -17
- data/lib/pagy/extras/foundation.rb +62 -32
- data/lib/pagy/extras/headers.rb +13 -9
- data/lib/pagy/extras/i18n.rb +8 -11
- data/lib/pagy/extras/items.rb +21 -34
- data/lib/pagy/extras/materialize.rb +59 -35
- data/lib/pagy/extras/metadata.rb +27 -21
- data/lib/pagy/extras/navs.rb +45 -20
- data/lib/pagy/extras/overflow.rb +50 -48
- data/lib/pagy/extras/searchkick.rb +27 -16
- data/lib/pagy/extras/semantic.rb +56 -30
- data/lib/pagy/extras/shared.rb +12 -13
- data/lib/pagy/extras/standalone.rb +71 -0
- data/lib/pagy/extras/support.rb +20 -11
- data/lib/pagy/extras/trim.rb +12 -11
- data/lib/pagy/extras/uikit.rb +64 -34
- data/lib/pagy/frontend.rb +62 -33
- metadata +5 -7
- data/lib/pagy/extras/pagy_search.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 48e9fa30f5123b3b985a58c0f20e00803b8708662d25e4b8116f786264adf382
|
4
|
+
data.tar.gz: fd51c8bf8bb897c01382459c4ab1a6baf3e28c7c9437213652382cbf5d01b8f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 073dd75676b37ba14baaccd30a58ce008e8d32dd8e1dfd8508bc02abf0f1d85bfe8a503a4790b4157cd8a36f3e8b1c89284ae3d83c0ea8cb6565e5e32a74985d
|
7
|
+
data.tar.gz: 449da76a99d14327a89fcc30fad843dc5581c8225fab8c5678aa72f9888b160ebbd09d6c1b6946d8bcd1002267803a72b97a28de7797ac1a0be28ece704475f6
|
data/lib/config/pagy.rb
CHANGED
@@ -1,11 +1,34 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
|
-
# Pagy initializer file (
|
3
|
+
# Pagy initializer file (4.4.0)
|
5
4
|
# Customize only what you really need and notice that 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 Variables
|
9
|
+
# See https://ddnexus.github.io/pagy/api/pagy#variables
|
10
|
+
# All the Pagy::VARS are set for all the Pagy instances but can be overridden
|
11
|
+
# per instance by just passing them to Pagy.new or the #pagy controller method
|
12
|
+
|
13
|
+
|
14
|
+
# Instance variables
|
15
|
+
# See https://ddnexus.github.io/pagy/api/pagy#instance-variables
|
16
|
+
# Pagy::VARS[:page] = 1 # default
|
17
|
+
# Pagy::VARS[:items] = 20 # default
|
18
|
+
# Pagy::VARS[:outset] = 0 # default
|
19
|
+
|
20
|
+
|
21
|
+
# Other Variables
|
22
|
+
# See https://ddnexus.github.io/pagy/api/pagy#other-variables
|
23
|
+
# Pagy::VARS[:size] = [1,4,4,1] # default
|
24
|
+
# Pagy::VARS[:page_param] = :page # default
|
25
|
+
# Pagy::VARS[:params] = {} # default
|
26
|
+
# Pagy::VARS[:fragment] = '#fragment' # example
|
27
|
+
# Pagy::VARS[:link_extra] = 'data-remote="true"' # example
|
28
|
+
# Pagy::VARS[:i18n_key] = 'pagy.item_name' # default
|
29
|
+
# Pagy::VARS[:cycle] = true # example
|
30
|
+
|
31
|
+
|
9
32
|
# Extras
|
10
33
|
# See https://ddnexus.github.io/pagy/extras
|
11
34
|
|
@@ -19,17 +42,21 @@
|
|
19
42
|
# Countless extra: Paginate without any count, saving one query per rendering
|
20
43
|
# See https://ddnexus.github.io/pagy/extras/countless
|
21
44
|
# require 'pagy/extras/countless'
|
22
|
-
# Pagy::VARS[:cycle] = false # default
|
23
45
|
|
24
46
|
# Elasticsearch Rails extra: Paginate `ElasticsearchRails::Results` objects
|
25
47
|
# See https://ddnexus.github.io/pagy/extras/elasticsearch_rails
|
48
|
+
# default :pagy_search method: change only if you use
|
49
|
+
# also the searchkick extra that defines the same
|
50
|
+
# VARS[:elasticsearch_rails_search_method] = :pagy_search
|
26
51
|
# require 'pagy/extras/elasticsearch_rails'
|
27
52
|
|
28
53
|
# Searchkick extra: Paginate `Searchkick::Results` objects
|
29
54
|
# See https://ddnexus.github.io/pagy/extras/searchkick
|
55
|
+
# default :pagy_search method: change only if you use
|
56
|
+
# also the elasticsearch_rails extra that defines the same
|
57
|
+
# VARS[:searchkick_search_method] = :pagy_search
|
30
58
|
# require 'pagy/extras/searchkick'
|
31
59
|
|
32
|
-
|
33
60
|
# Frontend Extras
|
34
61
|
|
35
62
|
# Bootstrap extra: Add nav, nav_js and combo_nav_js helpers and templates for Bootstrap pagination
|
@@ -83,6 +110,8 @@
|
|
83
110
|
# require 'pagy/extras/items'
|
84
111
|
# Pagy::VARS[:items_param] = :items # default
|
85
112
|
# Pagy::VARS[:max_items] = 100 # default
|
113
|
+
# set to false if you want to make :enable_items_extra an opt-in variable
|
114
|
+
# Pagy::VARS[:enable_items_extra] = false # default true
|
86
115
|
|
87
116
|
# Overflow extra: Allow for easy handling of overflowing pages
|
88
117
|
# See https://ddnexus.github.io/pagy/extras/overflow
|
@@ -100,27 +129,9 @@
|
|
100
129
|
# Trim extra: Remove the page=1 param from links
|
101
130
|
# See https://ddnexus.github.io/pagy/extras/trim
|
102
131
|
# require 'pagy/extras/trim'
|
103
|
-
|
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
|
132
|
+
# after requiring it will trim by default
|
133
|
+
# set to false if you want to make :enable_trim_extra an opt-in variable
|
134
|
+
# Pagy::VARS[:enable_trim_extra] = false # default true
|
124
135
|
|
125
136
|
|
126
137
|
# Rails
|
data/lib/javascripts/pagy.js
CHANGED
@@ -2,34 +2,35 @@
|
|
2
2
|
|
3
3
|
function Pagy(){}
|
4
4
|
|
5
|
-
Pagy.version = '
|
5
|
+
Pagy.version = '4.4.0';
|
6
6
|
|
7
|
-
Pagy.
|
7
|
+
Pagy.timeout = 100;
|
8
|
+
|
9
|
+
Pagy.timeoutId = 0;
|
10
|
+
|
11
|
+
Pagy.init = function(arg) {
|
8
12
|
var target = arg instanceof Event || arg === undefined ? document : arg,
|
9
13
|
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
14
|
for (var i = 0, len = jsonTags.length; i < len; i++) {
|
15
|
-
var args
|
16
|
-
|
15
|
+
var args = JSON.parse(jsonTags[i].innerHTML),
|
16
|
+
fname = args.shift();
|
17
|
+
args.unshift(jsonTags[i].previousSibling);
|
18
|
+
Pagy[fname].apply(null, args);
|
17
19
|
}
|
18
|
-
}
|
20
|
+
}
|
19
21
|
|
20
|
-
Pagy.nav = function(
|
21
|
-
var
|
22
|
-
lastWidth = undefined,
|
22
|
+
Pagy.nav = function(pagyEl, tags, sequels, param) {
|
23
|
+
var lastWidth = undefined,
|
23
24
|
timeoutId = 0,
|
24
25
|
pageREg = new RegExp(/__pagy_page__/g),
|
25
26
|
widths = [],
|
26
|
-
|
27
|
+
wait = function() { clearTimeout(timeoutId); timeoutId = setTimeout(pagyEl.render, Pagy.timeout) };
|
27
28
|
|
28
29
|
for (var width in sequels) { widths.push(parseInt(width)) } // fine with sequels structure
|
29
|
-
widths.sort(function(a, b){return b-a});
|
30
|
+
widths.sort(function(a, b) { return b - a });
|
30
31
|
|
31
|
-
pagyEl.render = function(){
|
32
|
-
if (this.parentElement.clientWidth === 0) {
|
32
|
+
pagyEl.render = function() {
|
33
|
+
if (this.parentElement.clientWidth === 0) { return wait() } // not ready yet
|
33
34
|
var width, i, len;
|
34
35
|
for (i = 0, len = widths.length; i < len; i++) {
|
35
36
|
if (this.parentElement.clientWidth > widths[i]) { width = widths[i]; break }
|
@@ -50,57 +51,60 @@ Pagy.nav = function(id, tags, sequels, param){
|
|
50
51
|
lastWidth = width;
|
51
52
|
}
|
52
53
|
}.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
54
|
pagyEl.render();
|
61
|
-
}
|
55
|
+
}
|
62
56
|
|
63
|
-
Pagy.combo_nav = function(
|
64
|
-
var
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
};
|
57
|
+
Pagy.combo_nav = function(pagyEl, page, link, param) {
|
58
|
+
var input = pagyEl.getElementsByTagName('input')[0],
|
59
|
+
go = function() {
|
60
|
+
if (page !== input.value) {
|
61
|
+
var html = link.replace(/__pagy_page__/, input.value);
|
62
|
+
if (typeof (param) === 'string' && input.value === '1') { html = Pagy.trim(html, param) }
|
63
|
+
pagyEl.insertAdjacentHTML('afterbegin', html);
|
64
|
+
pagyEl.getElementsByTagName('a')[0].click();
|
65
|
+
}
|
66
|
+
};
|
74
67
|
Pagy.addInputEventListeners(input, go);
|
75
|
-
}
|
68
|
+
}
|
76
69
|
|
77
|
-
Pagy.items_selector = function(
|
78
|
-
var
|
79
|
-
input = pagyEl.getElementsByTagName('input')[0],
|
70
|
+
Pagy.items_selector = function(pagyEl, from, link, param) {
|
71
|
+
var input = pagyEl.getElementsByTagName('input')[0],
|
80
72
|
current = input.value,
|
81
|
-
go = function(){
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
73
|
+
go = function() {
|
74
|
+
var items = input.value;
|
75
|
+
if (current !== items) {
|
76
|
+
var page = Math.max(Math.ceil(from / items), 1),
|
77
|
+
html = link.replace(/__pagy_page__/, page).replace(/__pagy_items__/, items);
|
78
|
+
if (typeof (param) === 'string' && page === 1) { html = Pagy.trim(html, param) }
|
79
|
+
pagyEl.insertAdjacentHTML('afterbegin', html);
|
80
|
+
pagyEl.getElementsByTagName('a')[0].click();
|
81
|
+
}
|
82
|
+
};
|
91
83
|
Pagy.addInputEventListeners(input, go);
|
92
|
-
}
|
84
|
+
}
|
93
85
|
|
94
|
-
Pagy.addInputEventListeners = function(input, handler){
|
86
|
+
Pagy.addInputEventListeners = function(input, handler) {
|
95
87
|
// select the content on click: easier for typing a number
|
96
|
-
input.addEventListener('click', function(){ this.select() });
|
88
|
+
input.addEventListener('click', function() { this.select() });
|
97
89
|
// go when the input looses focus
|
98
90
|
input.addEventListener('focusout', handler);
|
99
91
|
// … and when pressing enter inside the input
|
100
|
-
input.addEventListener('keyup', function(e){ if (e.which === 13) handler() }.bind(this));
|
101
|
-
}
|
92
|
+
input.addEventListener('keyup', function(e) { if (e.which === 13) {handler()} }.bind(this));
|
93
|
+
}
|
102
94
|
|
103
|
-
Pagy.trim = function(html, param){
|
95
|
+
Pagy.trim = function(html, param) {
|
104
96
|
var re = new RegExp('[?&]' + param + '=1\\b(?!&)|\\b' + param + '=1&');
|
105
97
|
return html.replace(re, '');
|
106
|
-
}
|
98
|
+
}
|
99
|
+
|
100
|
+
Pagy.renderNjs = function() {
|
101
|
+
var navs = document.getElementsByClassName('pagy-njs');
|
102
|
+
for (var i = 0, len = navs.length; i < len; i++) { navs[i].render() }
|
103
|
+
}
|
104
|
+
|
105
|
+
Pagy.wait = function() {
|
106
|
+
clearTimeout(Pagy.timeoutId);
|
107
|
+
Pagy.timeoutId = setTimeout(Pagy.renderNjs, Pagy.timeout);
|
108
|
+
}
|
109
|
+
|
110
|
+
window.addEventListener('resize', Pagy.wait, true);
|
data/lib/locales/utils/i18n.rb
CHANGED
@@ -1,25 +1,17 @@
|
|
1
1
|
# See https://ddnexus.github.io/pagy/api/frontend#i18n
|
2
|
-
# encoding: utf-8
|
3
2
|
# frozen_string_literal: true
|
4
3
|
|
5
4
|
# this file returns the I18n hash used as default alternative to the i18n gem
|
6
5
|
|
7
|
-
Pagy::DEPRECATED_LOCALES = {'pt-br' =>'pt-BR', 'se' => 'sv-SE'}
|
8
|
-
|
9
6
|
Hash.new{|h,_| h.first[1]}.tap do |i18n_hash| # first loaded locale used as default
|
10
7
|
i18n_hash.define_singleton_method(:load) do |*load_args|
|
11
8
|
# eval: we don't need to keep the loader proc in memory
|
12
9
|
eval(Pagy.root.join('locales', 'utils', 'loader.rb').read).call(i18n_hash, *load_args) #rubocop:disable Security/Eval
|
13
10
|
end
|
14
|
-
i18n_hash.define_singleton_method(:t) do |locale,
|
15
|
-
if Pagy::DEPRECATED_LOCALES.key?(locale)
|
16
|
-
new_locale = Pagy::DEPRECATED_LOCALES[locale]
|
17
|
-
$stderr.puts("WARNING: the Pagy locale '#{locale}' is deprecated; use '#{new_locale}' instead")
|
18
|
-
locale = new_locale
|
19
|
-
end
|
11
|
+
i18n_hash.define_singleton_method(:t) do |locale, key, **opts|
|
20
12
|
data, pluralize = self[locale]
|
21
|
-
translate = data[
|
22
|
-
translate.call(
|
13
|
+
translate = data[key] || opts[:count] && data[key+=".#{pluralize.call(opts[:count])}"] or return %([translation missing: "#{key}"])
|
14
|
+
translate.call(opts)
|
23
15
|
end
|
24
16
|
i18n_hash.load(locale: 'en')
|
25
17
|
end
|
data/lib/locales/utils/loader.rb
CHANGED
@@ -1,18 +1,20 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
# the whole file will be eval'ed/executed and gc-collected after returning/executing the loader proc
|
5
4
|
|
6
5
|
# eval: no need for the whole file in memory
|
7
|
-
plurals,
|
6
|
+
plurals, = eval Pagy.root.join('locales', 'utils', 'p11n.rb').read # rubocop:disable Security/Eval
|
8
7
|
|
9
8
|
# flatten the dictionary file nested keys
|
10
9
|
# convert each value to a simple ruby interpolation proc
|
11
10
|
flatten = lambda do |hash, key=''|
|
12
11
|
hash.each.reduce({}) do |h, (k, v)|
|
13
|
-
v.is_a?(Hash)
|
14
|
-
|
15
|
-
|
12
|
+
if v.is_a?(Hash)
|
13
|
+
h.merge! flatten.call(v, "#{key}#{k}.")
|
14
|
+
else
|
15
|
+
code = %({"#{key}#{k}" => lambda{|vars|"#{v.gsub(/%{[^}]+?}/){|m| "\#{vars[:#{m[2..-2]}]||'#{m}'}" }}"}})
|
16
|
+
h.merge! eval(code) # rubocop:disable Security/Eval
|
17
|
+
end
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
@@ -20,11 +22,6 @@ flatten = lambda do |hash, key=''|
|
|
20
22
|
lambda do |i18n, *args|
|
21
23
|
i18n.clear
|
22
24
|
args.each do |arg|
|
23
|
-
if Pagy::DEPRECATED_LOCALES.key?(arg[:locale])
|
24
|
-
new_locale = Pagy::DEPRECATED_LOCALES[arg[:locale]]
|
25
|
-
$stderr.puts("WARNING: the Pagy locale '#{arg[:locale]}' is deprecated; use '#{new_locale}' instead")
|
26
|
-
arg[:locale] = new_locale
|
27
|
-
end
|
28
25
|
arg[:filepath] ||= Pagy.root.join('locales', "#{arg[:locale]}.yml")
|
29
26
|
arg[:pluralize] ||= plurals[arg[:locale]]
|
30
27
|
hash = YAML.load(File.read(arg[:filepath], encoding: 'UTF-8')) #rubocop:disable Security/YAMLLoad
|
data/lib/locales/utils/p11n.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
# See https://ddnexus.github.io/pagy/api/frontend#i18n
|
2
|
-
# encoding: utf-8
|
3
2
|
# frozen_string_literal: true
|
4
3
|
|
5
4
|
# This file adds support for multiple built-in plualization types.
|
@@ -18,46 +17,51 @@ from12to14 = [12,13,14].freeze
|
|
18
17
|
# Each proc may apply to one or more locales below.
|
19
18
|
# Pluralization logic adapted from https://github.com/svenfuchs/rails-i18n
|
20
19
|
p11n = {
|
21
|
-
one_other:
|
20
|
+
one_other: -> (n){ n == 1 ? 'one' : 'other' }, # default
|
22
21
|
|
23
22
|
east_slavic: lambda do |n|
|
24
23
|
n ||= 0
|
25
24
|
mod10 = n % 10
|
26
25
|
mod100 = n % 100
|
27
26
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
case
|
28
|
+
when mod10 == 1 && mod100 != 11 then 'one'
|
29
|
+
when from2to4.include?(mod10) && !from12to14.include?(mod100) then 'few'
|
30
|
+
when mod10 == 0 || from5to9.include?(mod10) || from11to14.include?(mod100) then 'many' # rubocop:disable Style/NumericPredicate
|
31
|
+
else 'other'
|
32
32
|
end
|
33
33
|
end,
|
34
34
|
|
35
35
|
west_slavic: lambda do |n|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
case n
|
37
|
+
when 1 then 'one'
|
38
|
+
when 2, 3, 4 then 'few'
|
39
|
+
else 'other'
|
40
|
+
end
|
40
41
|
end,
|
41
42
|
|
42
43
|
one_two_other: lambda do |n|
|
43
|
-
|
44
|
-
|
45
|
-
|
44
|
+
case n
|
45
|
+
when 1 then 'one'
|
46
|
+
when 2 then 'two'
|
47
|
+
else 'other'
|
46
48
|
end
|
47
49
|
end,
|
48
50
|
|
49
|
-
one_upto_two_other:
|
51
|
+
one_upto_two_other: -> (n){ n && n >= 0 && n < 2 ? 'one' : 'other' },
|
50
52
|
|
51
|
-
other:
|
53
|
+
other: -> (*){ 'other' },
|
52
54
|
|
53
55
|
polish: lambda do |n|
|
54
56
|
n ||= 0
|
55
|
-
mod10
|
57
|
+
mod10 = n % 10
|
56
58
|
mod100 = n % 100
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
59
|
+
|
60
|
+
case
|
61
|
+
when n == 1 then 'one'
|
62
|
+
when from2to4.include?(mod10) && !from12to14.include?(mod100) then 'few'
|
63
|
+
when (from0to1 + from5to9).include?(mod10) || from12to14.include?(mod100) then 'many'
|
64
|
+
else 'other'
|
61
65
|
end
|
62
66
|
end
|
63
67
|
}
|
data/lib/pagy.rb
CHANGED
@@ -1,65 +1,76 @@
|
|
1
1
|
# See Pagy API documentation: https://ddnexus.github.io/pagy/api/pagy
|
2
|
-
# encoding: utf-8
|
3
2
|
# frozen_string_literal: true
|
4
3
|
|
5
4
|
require 'pathname'
|
6
5
|
|
7
|
-
|
6
|
+
# main class
|
7
|
+
class Pagy
|
8
|
+
VERSION = '4.4.0'
|
8
9
|
|
9
10
|
# Root pathname to get the path of Pagy files like templates or dictionaries
|
10
|
-
def self.root
|
11
|
+
def self.root
|
12
|
+
@root ||= Pathname.new(__dir__).freeze
|
13
|
+
end
|
11
14
|
|
12
15
|
# default vars
|
13
|
-
VARS = { page:1, items:20, outset:0, size:[1,4,4,1], page_param: :page,
|
16
|
+
VARS = { page: 1, items: 20, outset: 0, size: [1, 4, 4, 1], page_param: :page, # rubocop:disable Style/MutableConstant
|
17
|
+
params: {}, fragment: '', link_extra: '', i18n_key: 'pagy.item_name', cycle: false }
|
14
18
|
|
15
19
|
attr_reader :count, :page, :items, :vars, :pages, :last, :offset, :from, :to, :prev, :next
|
16
20
|
|
21
|
+
INSTANCE_VARS_MIN = { count: 0, items: 1, page: 1, outset: 0 }.freeze
|
22
|
+
|
17
23
|
# Merge and validate the options, do some simple arithmetic and set the instance variables
|
18
24
|
def initialize(vars)
|
19
|
-
@vars = VARS.merge(vars.delete_if{|
|
20
|
-
|
21
|
-
|
22
|
-
|
25
|
+
@vars = VARS.merge( vars.delete_if{|k,v| VARS.key?(k) && (v.nil? || v == '') } )
|
26
|
+
@vars[:fragment] = deprecated_var(:anchor, @vars[:anchor], :fragment, @vars[:fragment]) if @vars[:anchor]
|
27
|
+
|
28
|
+
INSTANCE_VARS_MIN.each do |name,min|
|
29
|
+
raise VariableError.new(self), "expected :#{name} >= #{min}; got #{@vars[name].inspect}" \
|
30
|
+
unless @vars[name] && instance_variable_set(:"@#{name}", @vars[name].to_i) >= min
|
23
31
|
end
|
24
|
-
@pages = @last = [(@count.to_f / @items).ceil, 1].max
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
@
|
29
|
-
@
|
30
|
-
@
|
31
|
-
@
|
32
|
+
@pages = @last = [(@count.to_f / @items).ceil, 1].max
|
33
|
+
raise OverflowError.new(self), "expected :page in 1..#{@last}; got #{@page.inspect}" \
|
34
|
+
if @page > @last
|
35
|
+
|
36
|
+
@offset = @items * (@page - 1) + @outset
|
37
|
+
@items = @count - ((@pages - 1) * @items) if @page == @last && @count.positive?
|
38
|
+
@from = @count.zero? ? 0 : @offset + 1 - @outset
|
39
|
+
@to = @count.zero? ? 0 : @offset + @items - @outset
|
40
|
+
@prev = (@page - 1 unless @page == 1)
|
41
|
+
@next = @page == @last ? (1 if @vars[:cycle]) : @page + 1
|
32
42
|
end
|
33
43
|
|
34
44
|
# Return the array of page numbers and :gap items e.g. [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
|
35
|
-
def series(size=@vars[:size])
|
36
|
-
|
37
|
-
|
38
|
-
unless size.size == 4 && size.all?{ |num| num
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
45
|
+
def series(size=@vars[:size])
|
46
|
+
return [] if size.empty?
|
47
|
+
raise VariableError.new(self), "expected 4 items >= 0 in :size; got #{size.inspect}" \
|
48
|
+
unless size.size == 4 && size.all?{ |num| !num.negative? rescue false } # rubocop:disable Style/RescueModifier
|
49
|
+
# This algorithm is up to ~5x faster and ~2.3x lighter than the previous one (pagy < 4.3)
|
50
|
+
left_gap_start = 1 + size[0]
|
51
|
+
left_gap_end = @page - size[1] - 1
|
52
|
+
right_gap_start = @page + size[2] + 1
|
53
|
+
right_gap_end = @last - size[3]
|
54
|
+
left_gap_end = right_gap_end if left_gap_end > right_gap_end
|
55
|
+
right_gap_start = left_gap_start if left_gap_start > right_gap_start
|
56
|
+
series = []
|
57
|
+
start = 1
|
58
|
+
if (left_gap_end - left_gap_start).positive?
|
59
|
+
series.push(*start..(left_gap_start - 1), :gap)
|
60
|
+
start = left_gap_end + 1
|
61
|
+
end
|
62
|
+
if (right_gap_end - right_gap_start).positive?
|
63
|
+
series.push(*start..(right_gap_start - 1), :gap)
|
64
|
+
start = right_gap_end + 1
|
65
|
+
end
|
66
|
+
series.push(*start..@last)
|
67
|
+
series[series.index(@page)] = @page.to_s
|
68
|
+
series
|
55
69
|
end
|
56
|
-
series.push(*start..@last)
|
57
|
-
series[series.index(@page)] = @page.to_s
|
58
|
-
series
|
59
|
-
end
|
60
70
|
|
61
71
|
end
|
62
72
|
|
73
|
+
require 'pagy/deprecation'
|
63
74
|
require 'pagy/backend'
|
64
75
|
require 'pagy/frontend'
|
65
76
|
require 'pagy/exceptions'
|