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