pagy 4.11.0 → 6.0.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/LICENSE.txt +1 -1
- data/lib/config/pagy.rb +119 -58
- data/lib/javascripts/pagy-dev.js +114 -0
- data/lib/javascripts/pagy-module.d.ts +5 -0
- data/lib/javascripts/pagy-module.js +113 -0
- data/lib/javascripts/pagy.js +1 -121
- data/lib/locales/de.yml +1 -1
- data/lib/locales/ko.yml +1 -1
- data/lib/locales/nn.yml +22 -0
- data/lib/locales/ta.yml +22 -0
- data/lib/pagy/backend.rb +10 -13
- data/lib/pagy/calendar/day.rb +39 -0
- data/lib/pagy/calendar/helper.rb +61 -0
- data/lib/pagy/calendar/month.rb +40 -0
- data/lib/pagy/calendar/quarter.rb +47 -0
- data/lib/pagy/calendar/week.rb +39 -0
- data/lib/pagy/calendar/year.rb +33 -0
- data/lib/pagy/calendar.rb +100 -0
- data/lib/pagy/console.rb +6 -4
- data/lib/pagy/countless.rb +22 -23
- data/lib/pagy/exceptions.rb +14 -16
- data/lib/pagy/extras/arel.rb +11 -7
- data/lib/pagy/extras/array.rb +9 -9
- data/lib/pagy/extras/bootstrap.rb +45 -38
- data/lib/pagy/extras/bulma.rb +50 -38
- data/lib/pagy/extras/calendar.rb +49 -0
- data/lib/pagy/extras/countless.rb +15 -18
- data/lib/pagy/extras/elasticsearch_rails.rb +67 -48
- data/lib/pagy/extras/foundation.rb +39 -35
- data/lib/pagy/extras/frontend_helpers.rb +72 -0
- data/lib/pagy/extras/gearbox.rb +54 -0
- data/lib/pagy/extras/headers.rb +30 -20
- data/lib/pagy/extras/i18n.rb +15 -13
- data/lib/pagy/extras/items.rb +42 -40
- data/lib/pagy/extras/materialize.rb +40 -38
- data/lib/pagy/extras/meilisearch.rb +53 -44
- data/lib/pagy/extras/metadata.rb +15 -20
- data/lib/pagy/extras/navs.rb +35 -34
- data/lib/pagy/extras/overflow.rb +62 -61
- data/lib/pagy/extras/searchkick.rb +54 -46
- data/lib/pagy/extras/semantic.rb +42 -40
- data/lib/pagy/extras/standalone.rb +50 -46
- data/lib/pagy/extras/support.rb +24 -16
- data/lib/pagy/extras/trim.rb +15 -14
- data/lib/pagy/extras/uikit.rb +41 -38
- data/lib/pagy/frontend.rb +36 -59
- data/lib/pagy/i18n.rb +164 -0
- data/lib/pagy/url_helpers.rb +24 -0
- data/lib/pagy.rb +90 -31
- data/lib/templates/bootstrap_nav.html.erb +2 -2
- data/lib/templates/bootstrap_nav.html.haml +2 -2
- data/lib/templates/bootstrap_nav.html.slim +2 -2
- data/lib/templates/foundation_nav.html.erb +1 -1
- data/lib/templates/foundation_nav.html.haml +1 -1
- data/lib/templates/foundation_nav.html.slim +1 -1
- data/lib/templates/nav.html.erb +1 -1
- data/lib/templates/nav.html.haml +1 -1
- data/lib/templates/nav.html.slim +1 -1
- data/lib/templates/uikit_nav.html.erb +2 -2
- data/lib/templates/uikit_nav.html.haml +1 -1
- data/lib/templates/uikit_nav.html.slim +2 -2
- metadata +29 -13
- data/lib/locales/utils/i18n.rb +0 -17
- data/lib/locales/utils/loader.rb +0 -31
- data/lib/locales/utils/p11n.rb +0 -112
- data/lib/pagy/deprecation.rb +0 -27
- data/lib/pagy/extras/shared.rb +0 -52
data/lib/pagy/extras/semantic.rb
CHANGED
@@ -1,80 +1,82 @@
|
|
1
1
|
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/semantic
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require 'pagy/extras/
|
5
|
-
|
6
|
-
class Pagy
|
7
|
-
module Frontend
|
4
|
+
require 'pagy/extras/frontend_helpers'
|
8
5
|
|
6
|
+
class Pagy # :nodoc:
|
7
|
+
# Frontend modules are specially optimized for performance.
|
8
|
+
# The resulting code may not look very elegant, but produces the best benchmarks
|
9
|
+
module SemanticExtra
|
9
10
|
# Pagination for semantic: it returns the html with the series of links to the pages
|
10
|
-
def pagy_semantic_nav(pagy, pagy_id: nil, link_extra: '')
|
11
|
+
def pagy_semantic_nav(pagy, pagy_id: nil, link_extra: '', **vars)
|
11
12
|
p_id = %( id="#{pagy_id}") if pagy_id
|
12
13
|
link = pagy_link_proc(pagy, link_extra: %(class="item" #{link_extra}))
|
13
14
|
|
14
15
|
html = +%(<div#{p_id} class="pagy-semantic-nav ui pagination menu">)
|
15
16
|
html << pagy_semantic_prev_html(pagy, link)
|
16
|
-
pagy.series.each do |item|
|
17
|
+
pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
|
17
18
|
html << case item
|
18
|
-
when Integer then link.call item
|
19
|
-
when String then %(<a class="item active">#{item}</a>)
|
20
|
-
when :gap then %(<div class="disabled item">#{pagy_t 'pagy.nav.gap'}</div>)
|
19
|
+
when Integer then link.call item
|
20
|
+
when String then %(<a class="item active">#{pagy.label_for(item)}</a>)
|
21
|
+
when :gap then %(<div class="disabled item">#{pagy_t 'pagy.nav.gap'}</div>)
|
22
|
+
else raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
|
21
23
|
end
|
22
24
|
end
|
23
25
|
html << pagy_semantic_next_html(pagy, link)
|
24
26
|
html << %(</div>)
|
25
27
|
end
|
26
28
|
|
27
|
-
# Javascript pagination for semantic: it returns a nav and a JSON tag used by the
|
28
|
-
def pagy_semantic_nav_js(pagy,
|
29
|
-
|
29
|
+
# Javascript pagination for semantic: it returns a nav and a JSON tag used by the pagy.js file
|
30
|
+
def pagy_semantic_nav_js(pagy, pagy_id: nil, link_extra: '', **vars)
|
31
|
+
sequels = pagy.sequels(**vars)
|
30
32
|
p_id = %( id="#{pagy_id}") if pagy_id
|
31
33
|
link = pagy_link_proc(pagy, link_extra: %(class="item" #{link_extra}))
|
32
34
|
tags = { 'before' => pagy_semantic_prev_html(pagy, link),
|
33
|
-
'link' => link.call(PAGE_PLACEHOLDER),
|
34
|
-
'active' => %(<a class="item active">#{
|
35
|
+
'link' => link.call(PAGE_PLACEHOLDER, LABEL_PLACEHOLDER),
|
36
|
+
'active' => %(<a class="item active">#{LABEL_PLACEHOLDER}</a>),
|
35
37
|
'gap' => %(<div class="disabled item">#{pagy_t('pagy.nav.gap')}</div>),
|
36
38
|
'after' => pagy_semantic_next_html(pagy, link) }
|
37
39
|
|
38
|
-
%(<div#{p_id} class="pagy-
|
40
|
+
%(<div#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-semantic-nav-js ui pagination menu" role="navigation" #{
|
41
|
+
pagy_data(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></div>)
|
39
42
|
end
|
40
43
|
|
41
|
-
# Combo pagination for semantic: it returns a nav and a JSON tag used by the
|
42
|
-
def pagy_semantic_combo_nav_js(pagy,
|
43
|
-
pagy_id = Pagy.deprecated_arg(:id, deprecated_id, :pagy_id, pagy_id) if deprecated_id
|
44
|
+
# Combo pagination for semantic: it returns a nav and a JSON tag used by the pagy.js file
|
45
|
+
def pagy_semantic_combo_nav_js(pagy, pagy_id: nil, link_extra: '')
|
44
46
|
p_id = %( id="#{pagy_id}") if pagy_id
|
45
47
|
link = pagy_link_proc(pagy, link_extra: %(class="item" #{link_extra}))
|
46
48
|
p_page = pagy.page
|
47
49
|
p_pages = pagy.pages
|
48
|
-
input = %(<input type="number" min="1" max="#{p_pages}" value="#{
|
50
|
+
input = %(<input type="number" min="1" max="#{p_pages}" value="#{
|
51
|
+
p_page}" style="padding: 0; text-align: center; width: #{p_pages.to_s.length + 1}rem; margin: 0 0.3rem">)
|
49
52
|
|
50
53
|
%(<div#{p_id} class="pagy-semantic-combo-nav-js ui compact menu" role="navigation" #{
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
}</div>)
|
54
|
+
pagy_data(pagy, :combo, pagy_marked_link(link))}>#{
|
55
|
+
pagy_semantic_prev_html pagy, link
|
56
|
+
}<div class="pagy-combo-input item">#{
|
57
|
+
pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages
|
58
|
+
}</div> #{
|
59
|
+
pagy_semantic_next_html pagy, link
|
60
|
+
}</div>)
|
59
61
|
end
|
60
62
|
|
61
63
|
private
|
62
64
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
end
|
65
|
+
def pagy_semantic_prev_html(pagy, link)
|
66
|
+
if (p_prev = pagy.prev)
|
67
|
+
link.call p_prev, '<i class="left small chevron icon"></i>', 'aria-label="previous"'
|
68
|
+
else
|
69
|
+
+%(<div class="item disabled"><i class="left small chevron icon"></i></div>)
|
69
70
|
end
|
71
|
+
end
|
70
72
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
end
|
73
|
+
def pagy_semantic_next_html(pagy, link)
|
74
|
+
if (p_next = pagy.next)
|
75
|
+
link.call p_next, '<i class="right small chevron icon"></i>', 'aria-label="next"'
|
76
|
+
else
|
77
|
+
+%(<div class="item disabled"><i class="right small chevron icon"></i></div>)
|
77
78
|
end
|
78
|
-
|
79
|
+
end
|
79
80
|
end
|
81
|
+
Frontend.prepend SemanticExtra
|
80
82
|
end
|
@@ -2,61 +2,65 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require 'uri'
|
5
|
-
class Pagy
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
value.map { |k, v| build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k)) }.delete_if(&:empty?).join('&')
|
19
|
-
when nil
|
20
|
-
prefix
|
21
|
-
else
|
22
|
-
raise ArgumentError, 'value must be a Hash' if prefix.nil?
|
23
|
-
"#{prefix}=#{escape(value)}"
|
6
|
+
class Pagy # :nodoc:
|
7
|
+
# Use pagy without any request object, nor Rack environment/gem, nor any defined params method,
|
8
|
+
# even in the irb/rails console without any app or config.
|
9
|
+
module StandaloneExtra
|
10
|
+
# Extracted from Rack::Utils and reformatted for rubocop
|
11
|
+
# :nocov:
|
12
|
+
module QueryUtils
|
13
|
+
module_function
|
14
|
+
|
15
|
+
def escape(str)
|
16
|
+
URI.encode_www_form_component(str)
|
24
17
|
end
|
25
|
-
end
|
26
|
-
end
|
27
18
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
19
|
+
def build_nested_query(value, prefix = nil)
|
20
|
+
case value
|
21
|
+
when Array
|
22
|
+
value.map { |v| build_nested_query(v, "#{prefix}[]") }.join('&')
|
23
|
+
when Hash
|
24
|
+
value.map do |k, v|
|
25
|
+
build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
|
26
|
+
end.delete_if(&:empty?).join('&')
|
27
|
+
when nil
|
28
|
+
prefix
|
29
|
+
else
|
30
|
+
raise ArgumentError, 'value must be a Hash' if prefix.nil?
|
31
|
+
|
32
|
+
"#{prefix}=#{escape(value)}"
|
33
|
+
end
|
41
34
|
end
|
42
|
-
params = params.merge(p_vars[:params])
|
43
|
-
params[p_vars[:page_param].to_s] = page
|
44
|
-
params[p_vars[:items_param].to_s] = p_vars[:items] if defined?(UseItemsExtra)
|
45
|
-
query_string = "?#{QueryUtils.build_nested_query(pagy_get_params(params))}" unless params.empty?
|
46
|
-
"#{url_string}#{query_string}#{p_vars[:fragment]}"
|
47
35
|
end
|
48
|
-
|
36
|
+
# :nocov:
|
49
37
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
38
|
+
# Return the URL for the page. If there is no pagy.vars[:url]
|
39
|
+
# it works exactly as the regular #pagy_url_for, relying on the params method and Rack.
|
40
|
+
# If there is a defined pagy.vars[:url] variable it does not need the params method nor Rack.
|
41
|
+
def pagy_url_for(pagy, page, absolute: false, html_escaped: false)
|
42
|
+
return super unless pagy.vars[:url]
|
54
43
|
|
55
|
-
|
44
|
+
vars = pagy.vars
|
45
|
+
page_param = vars[:page_param].to_s
|
46
|
+
items_param = vars[:items_param].to_s
|
47
|
+
params = pagy.params.is_a?(Hash) ? pagy.params.clone : {} # safe when it gets reused
|
48
|
+
params[page_param] = page
|
49
|
+
params[items_param] = vars[:items] if vars[:items_extra]
|
50
|
+
params = pagy.params.call(params) if pagy.params.is_a?(Proc)
|
51
|
+
query_string = "?#{Rack::Utils.build_nested_query(params)}"
|
52
|
+
query_string = query_string.gsub('&', '&') if html_escaped # the only unescaped entity
|
53
|
+
"#{vars[:url]}#{query_string}#{vars[:fragment]}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
# In ruby 3+ `UrlHelpers.prepend StandaloneExtra` would be enough instead of using the next 2 lines
|
57
|
+
Frontend.prepend StandaloneExtra
|
58
|
+
Backend.prepend StandaloneExtra
|
59
|
+
|
60
|
+
# Define a dummy params method if it's not already defined in the including module
|
56
61
|
module Backend
|
57
62
|
def self.included(controller)
|
58
|
-
controller.define_method(:params){{}} unless controller.method_defined?(:params)
|
63
|
+
controller.define_method(:params) { {} } unless controller.method_defined?(:params)
|
59
64
|
end
|
60
65
|
end
|
61
|
-
|
62
66
|
end
|
data/lib/pagy/extras/support.rb
CHANGED
@@ -1,46 +1,54 @@
|
|
1
1
|
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/support
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
class Pagy
|
5
|
-
|
6
|
-
module
|
7
|
-
|
4
|
+
class Pagy # :nodoc:
|
5
|
+
# Extra support for features like: incremental, auto-incremental and infinite pagination
|
6
|
+
module SupportExtra
|
7
|
+
# Return the previous page URL string or nil
|
8
8
|
def pagy_prev_url(pagy)
|
9
9
|
pagy_url_for(pagy, pagy.prev) if pagy.prev
|
10
10
|
end
|
11
11
|
|
12
|
+
# Return the next page URL string or nil
|
12
13
|
def pagy_next_url(pagy)
|
13
14
|
pagy_url_for(pagy, pagy.next) if pagy.next
|
14
15
|
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
link_extra = Pagy.deprecated_arg(:link_extra, deprecated_link_extra, :link_extra, link_extra) if deprecated_link_extra
|
17
|
+
# Return the HTML string for the previous page link
|
18
|
+
def pagy_prev_link(pagy, text: pagy_t('pagy.nav.prev'), link_extra: '')
|
19
19
|
if pagy.prev
|
20
|
-
%(<span class="page prev"><a href="#{
|
20
|
+
%(<span class="page prev"><a href="#{
|
21
|
+
pagy_url_for(pagy, pagy.prev, html_escaped: true)
|
22
|
+
}" rel="prev" aria-label="previous" #{
|
23
|
+
pagy.vars[:link_extra]
|
24
|
+
} #{link_extra}>#{text}</a></span>)
|
21
25
|
else
|
22
26
|
%(<span class="page prev disabled">#{text}</span>)
|
23
27
|
end
|
24
28
|
end
|
25
29
|
|
26
|
-
|
27
|
-
|
28
|
-
link_extra = Pagy.deprecated_arg(:link_extra, deprecated_link_extra, :link_extra, link_extra) if deprecated_link_extra
|
30
|
+
# Return the HTML string for the next page link
|
31
|
+
def pagy_next_link(pagy, text: pagy_t('pagy.nav.next'), link_extra: '')
|
29
32
|
if pagy.next
|
30
|
-
%(<span class="page next"><a href="#{
|
33
|
+
%(<span class="page next"><a href="#{
|
34
|
+
pagy_url_for(pagy, pagy.next, html_escaped: true)
|
35
|
+
}" rel="next" aria-label="next" #{
|
36
|
+
pagy.vars[:link_extra]
|
37
|
+
} #{link_extra}>#{text}</a></span>)
|
31
38
|
else
|
32
39
|
%(<span class="page next disabled">#{text}</span>)
|
33
40
|
end
|
34
41
|
end
|
35
42
|
|
43
|
+
# Return the HTML link tag for the previous page or nil
|
36
44
|
def pagy_prev_link_tag(pagy)
|
37
|
-
%(<link href="#{pagy_url_for(pagy, pagy.prev)}" rel="prev"/>) if pagy.prev
|
45
|
+
%(<link href="#{pagy_url_for(pagy, pagy.prev, html_escaped: true)}" rel="prev"/>) if pagy.prev
|
38
46
|
end
|
39
47
|
|
48
|
+
# Return the HTML link tag for the next page or nil
|
40
49
|
def pagy_next_link_tag(pagy)
|
41
|
-
%(<link href="#{pagy_url_for(pagy, pagy.next)}" rel="next"/>) if pagy.next
|
50
|
+
%(<link href="#{pagy_url_for(pagy, pagy.next, html_escaped: true)}" rel="next"/>) if pagy.next
|
42
51
|
end
|
43
|
-
|
44
52
|
end
|
45
|
-
|
53
|
+
Frontend.prepend SupportExtra
|
46
54
|
end
|
data/lib/pagy/extras/trim.rb
CHANGED
@@ -1,28 +1,29 @@
|
|
1
1
|
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/trim
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
class Pagy
|
4
|
+
class Pagy # :nodoc:
|
5
|
+
DEFAULT[:trim_extra] = true # extra enabled by default
|
5
6
|
|
6
|
-
|
7
|
+
# Remove the page=1 param from the first page link
|
8
|
+
module TrimExtra
|
9
|
+
# Override the original pagy_link_proc.
|
10
|
+
# Call the pagy_trim method if the trim_extra is enabled.
|
11
|
+
def pagy_link_proc(pagy, link_extra: '')
|
12
|
+
link_proc = super(pagy, link_extra: link_extra)
|
13
|
+
return link_proc unless pagy.vars[:trim_extra]
|
7
14
|
|
8
|
-
|
15
|
+
lambda do |page, text = pagy.label_for(page), extra = ''|
|
16
|
+
link = +link_proc.call(page, text, extra)
|
17
|
+
return link unless page == 1
|
9
18
|
|
10
|
-
def pagy_link_proc(pagy, deprecated_link_extra=nil, link_extra: '')
|
11
|
-
link_extra = Pagy.deprecated_arg(:link_extra, deprecated_link_extra, :link_extra, link_extra) if deprecated_link_extra
|
12
|
-
link_proc = super(pagy, link_extra: link_extra)
|
13
|
-
return link_proc unless pagy.vars[:enable_trim_extra]
|
14
|
-
lambda do |num, text=num, extra=''|
|
15
|
-
link = +link_proc.call(num, text, extra)
|
16
|
-
return link unless num == 1
|
17
19
|
pagy_trim(pagy, link)
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
23
|
+
# Remove the the :page_param param from the first page link
|
21
24
|
def pagy_trim(pagy, link)
|
22
|
-
link.sub!(/
|
25
|
+
link.sub!(/(\?|&)#{pagy.vars[:page_param]}=1\b(?!&)|\b#{pagy.vars[:page_param]}=1&/, '')
|
23
26
|
end
|
24
|
-
|
25
27
|
end
|
26
|
-
Frontend.prepend
|
27
|
-
|
28
|
+
Frontend.prepend TrimExtra
|
28
29
|
end
|
data/lib/pagy/extras/uikit.rb
CHANGED
@@ -1,81 +1,84 @@
|
|
1
1
|
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/uikit
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require 'pagy/extras/
|
5
|
-
|
6
|
-
class Pagy
|
7
|
-
module Frontend
|
4
|
+
require 'pagy/extras/frontend_helpers'
|
8
5
|
|
6
|
+
class Pagy # :nodoc:
|
7
|
+
# Frontend modules are specially optimized for performance.
|
8
|
+
# The resulting code may not look very elegant, but produces the best benchmarks
|
9
|
+
module UikitExtra
|
9
10
|
# Pagination for uikit: it returns the html with the series of links to the pages
|
10
|
-
def pagy_uikit_nav(pagy, pagy_id: nil, link_extra: '')
|
11
|
+
def pagy_uikit_nav(pagy, pagy_id: nil, link_extra: '', **vars)
|
11
12
|
p_id = %( id="#{pagy_id}") if pagy_id
|
12
13
|
link = pagy_link_proc(pagy, link_extra: link_extra)
|
13
14
|
|
14
15
|
html = +%(<ul#{p_id} class="pagy-uikit-nav uk-pagination uk-flex-center">#{pagy_uikit_prev_html pagy, link})
|
15
|
-
pagy.series.each do |item|
|
16
|
-
html << case
|
16
|
+
pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
|
17
|
+
html << case item
|
17
18
|
when Integer then %(<li>#{link.call item}</li>)
|
18
|
-
when String then %(<li class="uk-active"><span>#{item}</span></li>)
|
19
|
+
when String then %(<li class="uk-active"><span>#{pagy.label_for(item)}</span></li>)
|
19
20
|
when :gap then %(<li class="uk-disabled"><span>#{pagy_t 'pagy.nav.gap'}</span></li>)
|
21
|
+
else raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
|
20
22
|
end
|
21
23
|
end
|
22
24
|
html << pagy_uikit_next_html(pagy, link)
|
23
25
|
html << %(</ul>)
|
24
26
|
end
|
25
27
|
|
26
|
-
# Javascript pagination for uikit: it returns a nav and a JSON tag used by the
|
27
|
-
def pagy_uikit_nav_js(pagy,
|
28
|
-
|
28
|
+
# Javascript pagination for uikit: it returns a nav and a JSON tag used by the pagy.js file
|
29
|
+
def pagy_uikit_nav_js(pagy, pagy_id: nil, link_extra: '', **vars)
|
30
|
+
sequels = pagy.sequels(**vars)
|
29
31
|
p_id = %( id="#{pagy_id}") if pagy_id
|
30
32
|
link = pagy_link_proc(pagy, link_extra: link_extra)
|
31
33
|
tags = { 'before' => pagy_uikit_prev_html(pagy, link),
|
32
|
-
'link' => %(<li>#{link.call(PAGE_PLACEHOLDER)}</li>),
|
33
|
-
'active' => %(<li class="uk-active"><span>#{
|
34
|
+
'link' => %(<li>#{link.call(PAGE_PLACEHOLDER, LABEL_PLACEHOLDER)}</li>),
|
35
|
+
'active' => %(<li class="uk-active"><span>#{LABEL_PLACEHOLDER}</span></li>),
|
34
36
|
'gap' => %(<li class="uk-disabled"><span>#{pagy_t 'pagy.nav.gap'}</span></li>),
|
35
37
|
'after' => pagy_uikit_next_html(pagy, link) }
|
36
38
|
|
37
|
-
%(<ul#{p_id} class="pagy-
|
39
|
+
%(<ul#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-uikit-nav-js uk-pagination uk-flex-center" #{
|
40
|
+
pagy_data(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></ul>)
|
38
41
|
end
|
39
42
|
|
40
|
-
# Javascript combo pagination for uikit: it returns a nav and a JSON tag used by the
|
41
|
-
def pagy_uikit_combo_nav_js(pagy,
|
42
|
-
pagy_id = Pagy.deprecated_arg(:id, deprecated_id, :pagy_id, pagy_id) if deprecated_id
|
43
|
+
# Javascript combo pagination for uikit: it returns a nav and a JSON tag used by the pagy.js file
|
44
|
+
def pagy_uikit_combo_nav_js(pagy, pagy_id: nil, link_extra: '')
|
43
45
|
p_id = %( id="#{pagy_id}") if pagy_id
|
44
46
|
link = pagy_link_proc(pagy, link_extra: link_extra)
|
45
47
|
p_page = pagy.page
|
46
48
|
p_pages = pagy.pages
|
47
|
-
input = %(<input type="number" min="1" max="#{p_pages}" value="#{
|
49
|
+
input = %(<input type="number" min="1" max="#{p_pages}" value="#{
|
50
|
+
p_page}" style="text-align: center; width: #{p_pages.to_s.length + 1}rem;">)
|
48
51
|
|
49
52
|
%(<ul#{p_id} class="pagy-uikit-combo-nav-js uk-button-group uk-pagination uk-flex-center" #{
|
50
|
-
|
51
|
-
|
53
|
+
pagy_data(pagy, :combo, pagy_marked_link(link))
|
54
|
+
}>#{
|
52
55
|
pagy_uikit_prev_html pagy, link
|
53
|
-
|
56
|
+
}<li>#{
|
54
57
|
pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages
|
55
|
-
|
58
|
+
}</li>#{
|
56
59
|
pagy_uikit_next_html pagy, link
|
57
|
-
|
60
|
+
}</ul>)
|
58
61
|
end
|
59
62
|
|
60
63
|
private
|
61
64
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
end
|
65
|
+
def pagy_uikit_prev_html(pagy, link)
|
66
|
+
previous_span = %(<span uk-pagination-previous>#{pagy_t 'pagy.nav.prev'}</span>)
|
67
|
+
if (p_prev = pagy.prev)
|
68
|
+
%(<li>#{link.call p_prev, previous_span}</li>)
|
69
|
+
else
|
70
|
+
%(<li class="uk-disabled"><a href="#">#{previous_span}</a></li>)
|
69
71
|
end
|
72
|
+
end
|
70
73
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
end
|
74
|
+
def pagy_uikit_next_html(pagy, link)
|
75
|
+
next_span = %(<span uk-pagination-next>#{pagy_t 'pagy.nav.next'}</span>)
|
76
|
+
if (p_next = pagy.next)
|
77
|
+
%(<li>#{link.call p_next, next_span}</li>)
|
78
|
+
else
|
79
|
+
%(<li class="uk-disabled"><a href="#">#{next_span}</a></li>)
|
78
80
|
end
|
79
|
-
|
81
|
+
end
|
80
82
|
end
|
83
|
+
Frontend.include UikitExtra
|
81
84
|
end
|
data/lib/pagy/frontend.rb
CHANGED
@@ -1,59 +1,38 @@
|
|
1
1
|
# See Pagy::Frontend API documentation: https://ddnexus.github.io/pagy/api/frontend
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require '
|
4
|
+
require 'pagy/url_helpers'
|
5
|
+
require 'pagy/i18n'
|
5
6
|
|
6
7
|
class Pagy
|
8
|
+
# Used for search and replace, hardcoded also in the pagy.js file
|
9
|
+
PAGE_PLACEHOLDER = '__pagy_page__'
|
10
|
+
LABEL_PLACEHOLDER = '__pagy_label__'
|
7
11
|
|
8
|
-
|
9
|
-
|
10
|
-
# I18n static hash loaded at startup, used as default alternative to the i18n gem.
|
11
|
-
# see https://ddnexus.github.io/pagy/api/frontend#i18n
|
12
|
-
I18n = eval Pagy.root.join('locales', 'utils', 'i18n.rb').read #rubocop:disable Security/Eval
|
13
|
-
|
14
|
-
module Helpers
|
15
|
-
# This works with all Rack-based frameworks (Sinatra, Padrino, Rails, ...)
|
16
|
-
def pagy_url_for(pagy, page, deprecated_url=nil, absolute: nil)
|
17
|
-
absolute = Pagy.deprecated_arg(:url, deprecated_url, :absolute, absolute) if deprecated_url
|
18
|
-
pagy, page = Pagy.deprecated_order(pagy, page) if page.is_a?(Pagy)
|
19
|
-
p_vars = pagy.vars
|
20
|
-
params = request.GET.merge(p_vars[:params])
|
21
|
-
params[p_vars[:page_param].to_s] = page
|
22
|
-
params[p_vars[:items_param].to_s] = p_vars[:items] if defined?(UseItemsExtra)
|
23
|
-
query_string = "?#{Rack::Utils.build_nested_query(pagy_get_params(params))}" unless params.empty?
|
24
|
-
"#{request.base_url if absolute}#{request.path}#{query_string}#{p_vars[:fragment]}"
|
25
|
-
end
|
26
|
-
|
27
|
-
# Sub-method called only by #pagy_url_for: here for easy customization of params by overriding
|
28
|
-
def pagy_get_params(params)
|
29
|
-
params
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# All the code here has been optimized for performance: it may not look very pretty
|
34
|
-
# (as most code dealing with many long strings), but its performance makes it very sexy! ;)
|
12
|
+
# Frontend modules are specially optimized for performance.
|
13
|
+
# The resulting code may not look very elegant, but produces the best benchmarks
|
35
14
|
module Frontend
|
36
|
-
|
37
|
-
include Helpers
|
15
|
+
include UrlHelpers
|
38
16
|
|
39
17
|
# Generic pagination: it returns the html with the series of links to the pages
|
40
|
-
def pagy_nav(pagy, pagy_id: nil, link_extra: '')
|
18
|
+
def pagy_nav(pagy, pagy_id: nil, link_extra: '', **vars)
|
41
19
|
p_id = %( id="#{pagy_id}") if pagy_id
|
42
20
|
link = pagy_link_proc(pagy, link_extra: link_extra)
|
43
21
|
p_prev = pagy.prev
|
44
22
|
p_next = pagy.next
|
45
23
|
|
46
|
-
html
|
24
|
+
html = +%(<nav#{p_id} class="pagy-nav pagination">)
|
47
25
|
html << if p_prev
|
48
26
|
%(<span class="page prev">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'}</span> )
|
49
27
|
else
|
50
28
|
%(<span class="page prev disabled">#{pagy_t('pagy.nav.prev')}</span> )
|
51
29
|
end
|
52
|
-
pagy.series.each do |item|
|
30
|
+
pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
|
53
31
|
html << case item
|
54
|
-
when Integer then %(<span class="page">#{link.call item}</span> )
|
55
|
-
when String then %(<span class="page active">#{item}</span> )
|
56
|
-
when :gap then %(<span class="page gap">#{pagy_t('pagy.nav.gap')}</span> )
|
32
|
+
when Integer then %(<span class="page">#{link.call item}</span> )
|
33
|
+
when String then %(<span class="page active">#{pagy.label_for(item)}</span> )
|
34
|
+
when :gap then %(<span class="page gap">#{pagy_t('pagy.nav.gap')}</span> )
|
35
|
+
else raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
|
57
36
|
end
|
58
37
|
end
|
59
38
|
html << if p_next
|
@@ -64,43 +43,41 @@ class Pagy
|
|
64
43
|
html << %(</nav>)
|
65
44
|
end
|
66
45
|
|
67
|
-
# Return examples: "Displaying items 41-60 of 324 in total"
|
68
|
-
def pagy_info(pagy,
|
69
|
-
p_id
|
70
|
-
item_name = Pagy.deprecated_arg(:item_name, deprecated_item_name, :item_name, item_name) if deprecated_item_name
|
46
|
+
# Return examples: "Displaying items 41-60 of 324 in total" or "Displaying Products 41-60 of 324 in total"
|
47
|
+
def pagy_info(pagy, pagy_id: nil, item_name: nil, i18n_key: nil)
|
48
|
+
p_id = %( id="#{pagy_id}") if pagy_id
|
71
49
|
p_count = pagy.count
|
72
50
|
key = if p_count.zero? then 'pagy.info.no_items'
|
73
51
|
elsif pagy.pages == 1 then 'pagy.info.single_page'
|
74
|
-
else 'pagy.info.multiple_pages'
|
52
|
+
else 'pagy.info.multiple_pages' # rubocop:disable Lint/ElseLayout
|
75
53
|
end
|
76
54
|
|
77
55
|
%(<span#{p_id} class="pagy-info">#{
|
78
|
-
|
79
|
-
|
80
|
-
|
56
|
+
pagy_t key, item_name: item_name || pagy_t(i18n_key || pagy.vars[:i18n_key], count: p_count),
|
57
|
+
count: p_count, from: pagy.from, to: pagy.to
|
58
|
+
}</span>)
|
81
59
|
end
|
82
60
|
|
83
|
-
#
|
61
|
+
# Return a performance optimized proc to generate the HTML links
|
84
62
|
# Benchmarked on a 20 link nav: it is ~22x faster and uses ~18x less memory than rails' link_to
|
85
|
-
def pagy_link_proc(pagy,
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
lambda do |
|
91
|
-
%(#{left}#{
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
63
|
+
def pagy_link_proc(pagy, link_extra: '')
|
64
|
+
p_prev = pagy.prev
|
65
|
+
p_next = pagy.next
|
66
|
+
left, right = %(<a href="#{pagy_url_for(pagy, PAGE_PLACEHOLDER, html_escaped: true)}" #{
|
67
|
+
pagy.vars[:link_extra]} #{link_extra}).split(PAGE_PLACEHOLDER, 2)
|
68
|
+
lambda do |page, text = pagy.label_for(page), extra_attrs = ''|
|
69
|
+
%(#{left}#{page}#{right}#{ case page
|
70
|
+
when p_prev then ' rel="prev"'
|
71
|
+
when p_next then ' rel="next"'
|
72
|
+
else ''
|
73
|
+
end } #{extra_attrs}>#{text}</a>)
|
96
74
|
end
|
97
75
|
end
|
98
76
|
|
99
77
|
# Similar to I18n.t: just ~18x faster using ~10x less memory
|
100
78
|
# (@pagy_locale explicitly initialized in order to avoid warning)
|
101
|
-
def pagy_t(key,
|
102
|
-
Pagy::I18n.
|
79
|
+
def pagy_t(key, opts = {})
|
80
|
+
Pagy::I18n.translate(@pagy_locale ||= nil, key, opts)
|
103
81
|
end
|
104
|
-
|
105
82
|
end
|
106
83
|
end
|