pagy 0.7.2 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8e51d75e2660aa59d031c00483240f184f15d2776d4c37470bfbee7ed1dd57a2
4
- data.tar.gz: faa522eceb7a6ace73224dc9a24ff29256a82d54d6ed249a331e8deefbe56382
3
+ metadata.gz: ae2667539ba0f1f518150c750faee613c5a47a3dc2154d9fc5ccbdd243891fbf
4
+ data.tar.gz: 4eea6d2bfaf058897bcc233f93ee7c8c43d29f139c374ed9e6fb5685f6e03258
5
5
  SHA512:
6
- metadata.gz: 06a931a110d4622351585b05577b2dd269b88b7b4337b40da887b1b7b9fec4b83d8d06f9333ab1fea315db23111424b1b83d54964867a57750c117ab776c1ed2
7
- data.tar.gz: c711d71396894e99138bac013c7cc9a9972566b5e4f0e0f1f27473cbca028a15c6660690c893fb793bb25fb9e56d14afe4ffcd2e9d0da08cbc9df4410f04fab0
6
+ metadata.gz: 241dc6c9f6b1bcb69edf5294112f915866709ed338947f30ab96ff3be79d0ed677f4a0d41fd08d9ed05495cf661d054b52effaaa948120aa8fe9ffbc6b638ae6
7
+ data.tar.gz: f90c99e9c32cc9e27314555f8f531eb598be43b4c26bb3038506127b73b918f95132b84fa3db688e85003e8addae6314cd55a274743a8f95d85cf6349e670f99
data/lib/pagy.rb CHANGED
@@ -2,10 +2,7 @@
2
2
 
3
3
  require 'pathname'
4
4
 
5
- class Pagy ; VERSION = '0.7.2'
6
-
7
- autoload :Backend, 'pagy/backend'
8
- autoload :Frontend, 'pagy/frontend'
5
+ class Pagy ; VERSION = '0.8.0'
9
6
 
10
7
  class OutOfRangeError < StandardError; end
11
8
 
@@ -13,7 +10,7 @@ class Pagy ; VERSION = '0.7.2'
13
10
  def self.root; Pathname.new(__FILE__).dirname end
14
11
 
15
12
  # default core vars
16
- VARS = { page:1, items:20, outset:0, size:[1,4,4,1] }
13
+ VARS = { page:1, items:20, outset:0, size:[1,4,4,1], page_param: :page }
17
14
 
18
15
  # default I18n vars
19
16
  zero_one = [:zero, :one] ; I18N = { file: Pagy.root.join('locales', 'pagy.yml').to_s, plurals: -> (c) {(zero_one[c] || :other).to_s.freeze} }
@@ -22,7 +19,7 @@ class Pagy ; VERSION = '0.7.2'
22
19
 
23
20
  # merge and validate the options, do some simple aritmetic and set the instance variables
24
21
  def initialize(vars)
25
- @vars = VARS.merge(vars.delete_if{|k,v| v.nil? || v == '' }) # default vars + cleaned instance vars
22
+ @vars = VARS.merge(vars.delete_if{|_,v| v.nil? || v == '' }) # default vars + cleaned instance vars
26
23
  { count:0, items:1, outset:0, page:1 }.each do |k,min| # validate core variables
27
24
  (@vars[k] && instance_variable_set(:"@#{k}", @vars.delete(k).to_i) >= min) \
28
25
  or raise(ArgumentError, "expected :#{k} >= #{min}; got #{instance_variable_get(:"@#{k}").inspect}")
@@ -52,3 +49,6 @@ class Pagy ; VERSION = '0.7.2'
52
49
  end
53
50
 
54
51
  end
52
+
53
+ require 'pagy/backend'
54
+ require 'pagy/frontend'
data/lib/pagy/backend.rb CHANGED
@@ -4,21 +4,22 @@ class Pagy
4
4
  # Defines a few generic methods to paginate a ORM collection out of the box,
5
5
  # or any collection by overriding pagy_get_items in your controller
6
6
 
7
- # See also the pagy-extras gem if you need specialized methods to paginate
7
+ # See also the extras if you need specialized methods to paginate
8
8
  # Arrays, ORM, and other TBD collections
9
9
 
10
10
  module Backend ; private # the whole module is private so no problem with including it in a controller
11
11
 
12
12
  # return pagy object and items
13
- def pagy(collection, vars=nil)
14
- pagy = Pagy.new(vars ? pagy_get_vars(collection).merge!(vars) : pagy_get_vars(collection)) # conditional merge is faster and saves memory
13
+ def pagy(collection, vars={})
14
+ pagy = Pagy.new(pagy_get_vars(collection, vars))
15
15
  return pagy, pagy_get_items(collection, pagy)
16
16
  end
17
17
 
18
18
  # sub-method called only by #pagy: here for easy customization of variables by overriding
19
- def pagy_get_vars(collection)
20
- # return the variables to initialize the pagy object
21
- { count: collection.count, page: params[:page] }
19
+ def pagy_get_vars(collection, vars)
20
+ # return the merged variables to initialize the pagy object
21
+ { count: collection.count,
22
+ page: params[vars[:page_param]||VARS[:page_param]] }.merge!(vars)
22
23
  end
23
24
 
24
25
  # sub-method called only by #pagy: here for easy customization of record-extraction by overriding
@@ -0,0 +1,20 @@
1
+ # See the Pagy Extras documentation: https://ddnexus.github.io/pagy/extras
2
+
3
+ class Pagy
4
+ # Add specialized backend methods to paginate array collections
5
+ module Backend ; private
6
+
7
+ # return pagy object and items
8
+ def pagy_array(array, vars={})
9
+ pagy = Pagy.new(pagy_array_get_vars(array, vars))
10
+ return pagy, array[pagy.offset, pagy.items]
11
+ end
12
+
13
+ def pagy_array_get_vars(array, vars)
14
+ # return the merged variables to initialize the pagy object
15
+ { count: array.count,
16
+ page: params[vars[:page_param]||VARS[:page_param]] }.merge!(vars)
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,26 @@
1
+ # See the Pagy Extras documentation: https://ddnexus.github.io/pagy/extras
2
+
3
+ class Pagy
4
+ # Add nav helper for bootstrap pagination
5
+ module Frontend
6
+
7
+ # Pagination for bootstrap: it returns the html with the series of links to the pages
8
+ def pagy_nav_bootstrap(pagy)
9
+ tags = ''; link = pagy_link_proc(pagy, 'class="page-link"'.freeze)
10
+
11
+ tags << (pagy.prev ? %(<li class="page-item prev">#{link.call pagy.prev, pagy_t('pagy.nav.prev'.freeze), 'aria-label="previous"'.freeze}</li>)
12
+ : %(<li class="page-item prev disabled"><a href="#" class="page-link">#{pagy_t('pagy.nav.prev'.freeze)}</a></li>))
13
+ pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
14
+ tags << if item.is_a?(Integer); %(<li class="page-item">#{link.call item}</li>) # page link
15
+ elsif item.is_a?(String) ; %(<li class="page-item active">#{link.call item}</li>) # active page
16
+ elsif item == :gap ; %(<li class="page-item gap disabled"><a href="#" class="page-link">#{pagy_t('pagy.nav.gap'.freeze)}</a></li>) # page gap
17
+ end
18
+ end
19
+ tags << (pagy.next ? %(<li class="page-item next">#{link.call pagy.next, pagy_t('pagy.nav.next'.freeze), 'aria-label="next"'.freeze}</li>)
20
+ : %(<li class="page-item next disabled"><a href="#" class="page-link">#{pagy_t('pagy.nav.next'.freeze)}</a></li>))
21
+ %(<nav class="pagy-nav-boostrap pagination" role="navigation" aria-label="pager"><ul class="pagination">#{tags}</ul></nav>)
22
+ end
23
+
24
+ end
25
+ end
26
+
@@ -0,0 +1,51 @@
1
+ # See the Pagy Extras documentation: https://ddnexus.github.io/pagy/extras
2
+
3
+ class Pagy
4
+ # Add nav helpers for compact pagination
5
+ module Frontend
6
+
7
+ # Generic compact pagination: it returns the html with the series of links to the pages
8
+ # we use a numeric input tag to set the page and the PagyCompact javascript to navigate
9
+ def pagy_nav_compact(pagy, id=caller(1,1)[0].hash)
10
+ tags = ''; link = pagy_link_proc(pagy)
11
+
12
+ tags << %(<nav id="pagy-nav-#{id}" class="pagy-nav-compact pagination" role="navigation" aria-label="pager">)
13
+
14
+ tags << link.call(MARKER, '', %(style="display: none;" ))
15
+ tags << (pagy.prev ? %(<span class="page prev">#{link.call pagy.prev, pagy_t('pagy.nav.prev'.freeze), 'aria-label="previous"'.freeze}</span> )
16
+ : %(<span class="page prev disabled">#{pagy_t('pagy.nav.prev'.freeze)}</span> ))
17
+
18
+ input = %(<input type="number" min="1" max="#{pagy.last}" value="#{pagy.page}" style="padding: 0; text-align: center; width: #{pagy.pages.to_s.length+1}rem;">)
19
+ tags << %(<span class="pagy-compact-input" style="margin: 0 0.6rem;">#{pagy_t('pagy.compact.page'.freeze)} #{input} #{pagy_t('pagy.compact.of'.freeze)} #{pagy.pages}</span> )
20
+
21
+ tags << (pagy.next ? %(<span class="page next">#{link.call pagy.next, pagy_t('pagy.nav.next'.freeze), 'aria-label="next"'.freeze}</span>)
22
+ : %(<span class="page next disabled">#{pagy_t('pagy.nav.next'.freeze)}</span>))
23
+
24
+ tags << %(</nav><script>PagyCompact('#{id}', '#{MARKER}', '#{pagy.page}');</script>)
25
+ end
26
+
27
+ # Compact pagination for bootstrap: it returns the html with the series of links to the pages
28
+ # we use a numeric input tag to set the page and the PagyCompact javascript to navigate
29
+ def pagy_nav_bootstrap_compact(pagy, id=caller(1,1)[0].hash)
30
+ tags = ''; link = pagy_link_proc(pagy)
31
+
32
+ tags << %(<nav id="pagy-nav-#{id}" class="pagy-nav-bootstrap-compact pagination" role="navigation" aria-label="pager">)
33
+
34
+ tags << link.call(MARKER, '', %(style="display: none;" ))
35
+
36
+ tags << %(<div class="btn-group" role="group">)
37
+ tags << (pagy.prev ? link.call(pagy.prev, pagy_t('pagy.nav.prev'.freeze), 'aria-label="previous" class="prev btn btn-primary"'.freeze)
38
+ : %(<a class="prev btn btn-primary disabled" href="#">#{pagy_t('pagy.nav.prev'.freeze)}</a>))
39
+
40
+ input = %(<input type="number" min="1" max="#{pagy.last}" value="#{pagy.page}" style="padding: 0; border: none; text-align: center; width: #{pagy.pages.to_s.length+1}rem;">)
41
+ tags << %(<div class="pagy-compact-input btn btn-primary disabled">#{pagy_t('pagy.compact.page'.freeze)} #{input} #{pagy_t('pagy.compact.of'.freeze)} #{pagy.pages}</div>)
42
+
43
+ tags << (pagy.next ? link.call(pagy.next, pagy_t('pagy.nav.next'.freeze), 'aria-label="next" class="next btn btn-primary"'.freeze)
44
+ : %(<a class="next btn btn-primary disabled" href="#">#{pagy_t('pagy.nav.next'.freeze)}</a>))
45
+
46
+ tags << %(</div></nav><script>PagyCompact('#{id}', '#{MARKER}', '#{pagy.page}');</script>)
47
+ end
48
+
49
+ end
50
+ end
51
+
@@ -0,0 +1,16 @@
1
+ # See the Pagy Extras documentation: https://ddnexus.github.io/pagy/extras
2
+
3
+ class Pagy
4
+ # Use ::I18n gem
5
+ module Frontend
6
+
7
+ ::I18n.load_path << I18N[:file]
8
+
9
+ # overrides the built-in pagy_t
10
+ def pagy_t(*args)
11
+ I18n.t(*args)
12
+ end
13
+
14
+ end
15
+ end
16
+
@@ -0,0 +1,55 @@
1
+ # Example of initializer file
2
+ # Customize only what you really need but notice that Pagy works also without any of the following lines.
3
+
4
+
5
+ # Extras
6
+ # See https://ddnexus.github.io/pagy/extras
7
+
8
+ # Array: Paginate arrays efficiently avoiding expensive array-wrapping and wihout overriding
9
+ # See https://ddnexus.github.io/pagy/extras/array
10
+ # require 'pagy/extras/array'
11
+
12
+ # Bootstrap: Nav helper and templates for Bootstrap pagination
13
+ # See https://ddnexus.github.io/pagy/extras/bootstrap
14
+ # require 'pagy/extras/bootstrap'
15
+
16
+ # Compact: An alternative UI that combines the pagination with the nav info in one compact element
17
+ # See https://ddnexus.github.io/pagy/extras/compact
18
+ # require 'pagy/extras/compact'
19
+
20
+ # I18n: Uses the `I18n` gem instead of the pagy implementation
21
+ # See https://ddnexus.github.io/pagy/extras/i18n
22
+ # require 'pagy/extras/i18n'
23
+
24
+ # Responsive: On resize, the number of page links will adapt in real-time to the available window or container width
25
+ # See https://ddnexus.github.io/pagy/extras/responsive
26
+ # require 'pagy/extras/responsive'
27
+
28
+
29
+ # Pagy Variables
30
+ # All the Pagy::VARS here are set for all the pagy instances but can be
31
+ # overridden by just passing them to Pagy.new or the pagy controller method
32
+
33
+ # Core variables (See https://ddnexus.github.io/pagy/api/pagy#core-variables)
34
+ # Pagy::VARS[:items] = 20 # default
35
+
36
+ # Non Core Variables (See https://ddnexus.github.io/pagy/api/pagy#non-core-variables)
37
+ # Pagy::VARS[:size] = [1,4,4,1] # default
38
+ # Pagy::Vars[:page_param] = :page # default
39
+ # Pagy::VARS[:link_extra] = 'data-remote="true"' # example
40
+ # Pagy::VARS[:item_path] = 'activerecord.models.product' # example
41
+
42
+ # Extras Non Core Variables
43
+ # See https://ddnexus.github.io/pagy/extras/responsive#breakpoints
44
+ # Pagy::VARS[:breakpoints] = { 0 => [1,2,2,1], 350 => [2,3,3,2], 550 => [3,4,4,3] } # example of width/size pairs
45
+
46
+
47
+ # I18n Variables
48
+ # See https://ddnexus.github.io/pagy/api/frontend#pagy_tpath-vars
49
+ # Pagy::I18N[:file] = Pagy.root.join('locales', 'pagy.yml').to_s # default
50
+ # Pagy::I18N[:plurals] = -> (c) {([:zero, :one][c] || :other).to_s # default
51
+
52
+
53
+ # Rails: extras assets path required by compact or responsive extras
54
+ # See https://ddnexus.github.io/pagy/extras/compact and https://ddnexus.github.io/pagy/extras/responsive
55
+ # Rails.application.config.assets.paths << Pagy.root.join('pagy', 'extras', 'javascripts')
@@ -0,0 +1,15 @@
1
+ function PagyCompact(id, marker, page){
2
+ var pagyNav = document.getElementById('pagy-nav-'+id),
3
+ input = pagyNav.getElementsByTagName('input')[0],
4
+ link = pagyNav.getElementsByTagName('a')[0];
5
+
6
+ this.go = function(){
7
+ if (page !== input.value) {
8
+ var href = link.getAttribute('href').replace(marker, input.value);
9
+ link.setAttribute('href', href);
10
+ link.click();
11
+ }
12
+ };
13
+
14
+ input.addEventListener("focusout", this.go);
15
+ }
@@ -0,0 +1,24 @@
1
+ function PagyResponsive(id, items, widths, series){
2
+ var pagyNav = document.getElementById('pagy-nav-'+id),
3
+ pagyBox = pagyNav.firstChild || pagyNav,
4
+ pagyParent = pagyNav.parentElement,
5
+ lastWidth = undefined;
6
+
7
+ this.render = function(){
8
+ var parentWidth = parseInt(pagyParent.clientWidth),
9
+ width = widths.find(function(w){return parentWidth > w});
10
+ if (width !== lastWidth) {
11
+ while (pagyBox.firstChild) { pagyBox.removeChild(pagyBox.firstChild) }
12
+ var tags = items['prev'];
13
+ series[width].forEach(function(item){tags += items[item]});
14
+ tags += items['next'];
15
+ pagyBox.insertAdjacentHTML('beforeend', tags);
16
+ lastWidth = width;
17
+ }
18
+ };
19
+
20
+ if (window.attachEvent) { window.attachEvent('onresize', this.render) }
21
+ else if (window.addEventListener) { window.addEventListener('resize', this.render, true) }
22
+
23
+ this.render();
24
+ };
@@ -0,0 +1,73 @@
1
+ # See the Pagy Extras documentation: https://ddnexus.github.io/pagy/extras
2
+
3
+ require 'json'
4
+
5
+ class Pagy
6
+
7
+ # default :breakpoints
8
+ VARS[:breakpoints] = { 0 => [1,4,4,1] }
9
+
10
+ # Helper for building the page_nav with javascript. For example:
11
+ # with an object like:
12
+ # Pagy.new count:1000, page: 20, breakpoints: {0 => [1,2,2,1], 350 => [2,3,3,2], 550 => [3,4,4,3]}
13
+ # it returns something like:
14
+ # { :items => [1, :gap, 18, 19, "20", 21, 22, 50, 2, 17, 23, 49, 3, 16, 24, 48],
15
+ # :series => { 0 =>[1, :gap, 18, 19, "20", 21, 22, :gap, 50],
16
+ # 350 =>[1, 2, :gap, 17, 18, 19, "20", 21, 22, 23, :gap, 49, 50],
17
+ # 550 =>[1, 2, 3, :gap, 16, 17, 18, 19, "20", 21, 22, 23, 24, :gap, 48, 49, 50] },
18
+ # :widths => [550, 350, 0] }
19
+ # where :items is the unordered array union of all the page numbers for all sizes (passed to the PagyResponsive javascript function)
20
+ # :series is the hash of the series keyed by width (used by the *_responsive helpers to create the JSON string)
21
+ # :widths is the desc-ordered array of widths (passed to the PagyResponsive javascript function)
22
+ def responsive
23
+ @responsive ||= {items: [], series: {}, widths:[]}.tap do |r|
24
+ @vars[:breakpoints].key?(0) || raise(ArgumentError, "expected :breakpoints to contain the 0 size; got #{@vars[:breakpoint].inspect}")
25
+ @vars[:breakpoints].each {|width, size| r[:items] |= r[:series][width] = series(size)}
26
+ r[:widths] = r[:series].keys.sort!{|a,b| b <=> a}
27
+ end
28
+ end
29
+
30
+ # Add nav helpers for responsive pagination
31
+ module Frontend
32
+
33
+ # Generic responsive pagination: it returns the html with the series of links to the pages
34
+ # we build the tags as a json object string and render them with the PagyResponsive javascript
35
+ def pagy_nav_responsive(pagy, id=caller(1,1)[0].hash)
36
+ tags = '{'; link = pagy_link_proc(pagy); responsive = pagy.responsive
37
+
38
+ tags << (pagy.prev ? %('prev':'<span class="page prev">#{link.call pagy.prev, pagy_t('pagy.nav.prev'.freeze), 'aria-label="previous"'.freeze}</span> ',)
39
+ : %('prev':'<span class="page prev disabled">#{pagy_t('pagy.nav.prev'.freeze)}</span> ',))
40
+ responsive[:items].each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
41
+ tags << if item.is_a?(Integer); %('#{item}':'<span class="page">#{link.call item}</span> ',) # page link
42
+ elsif item.is_a?(String) ; %('#{item}':'<span class="page active">#{item}</span> ',) # current page
43
+ elsif item == :gap ; %('#{item}':'<span class="page gap">#{pagy_t('pagy.nav.gap'.freeze)}</span> ',) # page gap
44
+ end
45
+ end
46
+ tags << (pagy.next ? %('next':'<span class="page next">#{link.call pagy.next, pagy_t('pagy.nav.next'.freeze), 'aria-label="next"'.freeze}</span>'})
47
+ : %('next':'<span class="page next disabled">#{pagy_t('pagy.nav.next'.freeze)}</span>'}))
48
+ script = %(<script>PagyResponsive('#{id}', #{tags}, #{responsive[:widths].to_json}, #{responsive[:series].to_json});</script>)
49
+ %(<nav id="pagy-nav-#{id}" class="pagy-nav-responsive pagination" role="navigation" aria-label="pager"></nav>#{script})
50
+ end
51
+
52
+
53
+ # Responsive pagination for bootstrap: it returns the html with the series of links to the pages
54
+ # we build the tags as a json object string and render them with the PagyResponsive javascript
55
+ def pagy_nav_bootstrap_responsive(pagy, id=caller(1,1)[0].hash)
56
+ tags = '{'; link = pagy_link_proc(pagy, 'class="page-link"'.freeze); responsive = pagy.responsive
57
+
58
+ tags << (pagy.prev ? %('prev':'<li class="page-item prev">#{link.call pagy.prev, pagy_t('pagy.nav.prev'.freeze), 'aria-label="previous"'.freeze}</li>',)
59
+ : %('prev':'<li class="page-item prev disabled"><a href="#" class="page-link">#{pagy_t('pagy.nav.prev'.freeze)}</a></li>',))
60
+ responsive[:items].each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
61
+ tags << if item.is_a?(Integer); %('#{item}':'<li class="page-item">#{link.call item}</li>',) # page link
62
+ elsif item.is_a?(String) ; %('#{item}':'<li class="page-item active">#{link.call item}</li>',) # active page
63
+ elsif item == :gap ; %('#{item}':'<li class="page-item gap disabled"><a href="#" class="page-link">#{pagy_t('pagy.nav.gap'.freeze)}</a></li>',) # page gap
64
+ end
65
+ end
66
+ tags << (pagy.next ? %('next':'<li class="page-item next">#{link.call pagy.next, pagy_t('pagy.nav.next'.freeze), 'aria-label="next"'.freeze}</li>'})
67
+ : %('next':'<li class="page-item next disabled"><a href="#" class="page-link">#{pagy_t('pagy.nav.next'.freeze)}</a></li>'}))
68
+ script = %(<script>PagyResponsive('#{id}', #{tags}, #{responsive[:widths].to_json}, #{responsive[:series].to_json});</script>)
69
+ %(<nav id="pagy-nav-#{id}" class="pagy-nav-bootstrap-responsive pagination" role="navigation" aria-label="pager"><ul class="pagination"></ul></nav>#{script})
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,24 @@
1
+ <%#
2
+ This template is i18n-ready: if you don't use i18n, then you can replace the pagy_t
3
+ calls with the actual strings ("&lsaquo; Prev", "Next &rsaquo;", "&hellip;").
4
+
5
+ The link variable is set to a proc that returns the link tag.
6
+ Usage: link.call( page_number [, text [, extra_attributes_string ]])
7
+ -%>
8
+ <% link = pagy_link_proc(pagy, 'class="page-link"') -%>
9
+ <%# -%><nav aria-label="pager" class="pagy-nav-bootstrap pagination" role="navigation">
10
+ <%# -%> <ul class="pagination">
11
+ <% if pagy.prev -%> <li class="page-item prev"><%== link.call(pagy.prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"') %></li>
12
+ <% else -%> <li class="page-item prev disabled"><a href="#" class="page-link"><%== pagy_t('pagy.nav.prev') %></a></li>
13
+ <% end -%>
14
+ <% pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36] -%>
15
+ <% if item.is_a?(Integer) -%> <li class="page-item"><%== link.call(item) %></li>
16
+ <% elsif item.is_a?(String) -%> <li class="page-item active"><%== link.call(item) %></li>
17
+ <% elsif item == :gap -%> <li class="page-item disabled gap"><a href="#" class="page-link"><%== pagy_t('pagy.nav.gap') %></a></li>
18
+ <% end -%>
19
+ <% end -%>
20
+ <% if pagy.next -%> <li class="page-item next"><%== link.call(pagy.next, pagy_t('pagy.nav.next'), 'aria-label="next"') %></li>
21
+ <% else -%> <li class="page-item next disabled"><a href="#" class="page-link"><%== pagy_t('pagy.nav.next') %></a></li>
22
+ <% end -%>
23
+ <%# -%> </ul>
24
+ <%# -%></nav>
@@ -0,0 +1,34 @@
1
+ -# This template is i18n-ready: if you don't use i18n, then you can replace the pagy_t
2
+ -# calls with the actual strings ("&lsaquo; Prev", "Next &rsaquo;", "&hellip;").
3
+
4
+ -# The link variable is set to a proc that returns the link tag.
5
+ -# Usage: link.call( page_number [, text [, extra_attributes_string ]])
6
+
7
+ - link = pagy_link_proc(pagy, 'class="page-link"')
8
+
9
+ %nav.pagy-nav-bootstrap.pagination{"aria-label" => "pager", :role => "navigation"}
10
+
11
+ %ul.pagination
12
+
13
+ - if pagy.prev
14
+ %li.page-item.prev!= link.call(pagy.prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"')
15
+ - else
16
+ %li.page-item.prev.disabled
17
+ %a.page-link{:href => '#'}!= pagy_t('pagy.nav.prev')
18
+
19
+ - pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
20
+ - if item.is_a?(Integer) # page link
21
+ %li.page-item!= link.call(item)
22
+
23
+ - elsif item.is_a?(String) # current page
24
+ %li.page-item.active!= link.call(item)
25
+
26
+ - elsif item == :gap # page gap
27
+ %li.page-item.disabled.gap
28
+ %a.page-link{:href => "#"}!= pagy_t('pagy.nav.gap')
29
+
30
+ - if pagy.next
31
+ %li.page-item.next!= link.call(pagy.next, pagy_t('pagy.nav.next'), 'aria-label="next"')
32
+ - else
33
+ %li.page-item.next.disabled
34
+ %a.page-link{:href => '#'}!= pagy_t('pagy.nav.next')
@@ -0,0 +1,34 @@
1
+ / This template is i18n-ready: if you don't use i18n, then you can replace the pagy_t
2
+ / calls with the actual strings ("&lsaquo; Prev", "Next &rsaquo;", "&hellip;").
3
+
4
+ / The link variable is set to a proc that returns the link tag.
5
+ / Usage: link.call( page_number [, text [, extra_attributes_string ]])
6
+
7
+ - link = pagy_link_proc(pagy, 'class="page-link"')
8
+
9
+ nav.pagy-nav-bootstrap.pagination role="navigation" aria-label="pager"
10
+
11
+ ul.pagination
12
+
13
+ - if pagy.prev
14
+ li.page-item.prev == link.call(pagy.prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"')
15
+ - else
16
+ li.page-item.prev.disabled
17
+ a.page-link href="#" == pagy_t('pagy.nav.prev')
18
+
19
+ - pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
20
+ - if item.is_a?(Integer) # page link
21
+ li.page-item == link.call(item)
22
+
23
+ - elsif item.is_a?(String) # current page
24
+ li.page-item.active == link.call(item)
25
+
26
+ - elsif item == :gap # page gap
27
+ li.page-item.disabled.gap
28
+ a.page-link href="#" == pagy_t('pagy.nav.gap')
29
+
30
+ - if pagy.next
31
+ li.page-item.next == link.call(pagy.next, pagy_t('pagy.nav.next'), 'aria-label="next"')
32
+ - else
33
+ li.page-item.next.disabled
34
+ a.page-link href="#" == pagy_t('pagy.nav.next')
data/lib/pagy/frontend.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # See Pagy::Frontend API documentation: https://ddnexus.github.io/pagy/api/frontend
2
2
 
3
+ require 'yaml'
4
+
3
5
  class Pagy
4
6
 
5
7
  # All the code here has been optimized for performance: it may not look very pretty
@@ -33,14 +35,14 @@ class Pagy
33
35
 
34
36
 
35
37
  # this works with all Rack-based frameworks (Sinatra, Padrino, Rails, ...)
36
- def pagy_url_for(n)
37
- params = request.GET.merge('page'.freeze => n.to_s)
38
+ def pagy_url_for(page, page_param)
39
+ params = request.GET.merge(page_param => page)
38
40
  "#{request.path}?#{Rack::Utils.build_nested_query(pagy_get_params(params))}"
39
41
  end
40
42
 
41
43
 
42
44
  # sub-method called only by #pagy_url_for: here for easy customization of params by overriding
43
- def pagy_get_params(p) p end
45
+ def pagy_get_params(params) params end
44
46
 
45
47
 
46
48
  MARKER = "-pagy-#{'pagy'.hash}-".freeze
@@ -48,34 +50,28 @@ class Pagy
48
50
  # returns a specialized proc to generate the HTML links
49
51
  def pagy_link_proc(pagy, lx=''.freeze) # "lx" means "link extra"
50
52
  p_prev, p_next, p_lx = pagy.prev, pagy.next, pagy.vars[:link_extra]
51
- a, b = %(<a href="#{pagy_url_for(MARKER)}"#{p_lx ? %( #{p_lx}) : ''.freeze}#{lx.empty? ? lx : %( #{lx})}).split(MARKER)
53
+ a, b = %(<a href="#{pagy_url_for(MARKER, pagy.vars[:page_param])}"#{p_lx ? %( #{p_lx}) : ''.freeze}#{lx.empty? ? lx : %( #{lx})}).split(MARKER)
52
54
  -> (n, text=n, x=''.freeze) { "#{a}#{n}#{b}#{ if n == p_prev ; ' rel="prev"'.freeze
53
55
  elsif n == p_next ; ' rel="next"'.freeze
54
56
  else ''.freeze end }#{x.empty? ? x : %( #{x})}>#{text}</a>" }
55
57
  end
56
58
 
57
59
 
58
- # define #pagy_t depending on I18N[:gem] and I18n
59
- # this file will get autoloaded, so environment constants like ::I18n will be already set
60
- if I18N[:gem] || I18N[:gem].nil? && defined?(I18n)
61
- I18n.load_path << I18N[:file]
62
- def pagy_t(*a) I18n.t(*a) end
63
- else
64
- require 'yaml'
65
- # load data from the first locale in the file
66
- I18N_DATA = YAML.load_file(I18N[:file]).first[1].freeze
67
- # Similar to I18n.t for interpolation and pluralization but without translation
68
- # Use only for single-language apps: it is specialized for pagy and 5x faster than I18n.t
69
- def pagy_t(path, vars={})
70
- value = I18N_DATA.dig(*path.to_s.split('.'.freeze)) or return %(translation missing: "#{path}")
71
- if value.is_a?(Hash)
72
- vars.key?(:count) or return value
73
- plural = I18N[:plurals].call(vars[:count])
74
- value.key?(plural) or return %(invalid pluralization data: "#{path}" cannot be used with count: #{vars[:count]}; key "#{plural}" is missing.)
75
- value = value[plural] or return %(translation missing: "#{path}")
76
- end
77
- sprintf value, Hash.new{|h,k| "%{#{k}}"}.merge!(vars) # interpolation
60
+ # load data from the first locale in the file
61
+ I18N_DATA = YAML.load_file(I18N[:file]).first[1].freeze
62
+
63
+ # Similar to I18n.t for interpolation and pluralization but without translation
64
+ # Use only for single-language apps: it is specialized for pagy and 5x faster than I18n.t
65
+ # See also https://ddnexus.github.io/pagy/extras/i18n to use the standard I18n gem instead
66
+ def pagy_t(path, vars={})
67
+ value = I18N_DATA.dig(*path.to_s.split('.'.freeze)) or return %(translation missing: "#{path}")
68
+ if value.is_a?(Hash)
69
+ vars.key?(:count) or return value
70
+ plural = I18N[:plurals].call(vars[:count])
71
+ value.key?(plural) or return %(invalid pluralization data: "#{path}" cannot be used with count: #{vars[:count]}; key "#{plural}" is missing.)
72
+ value = value[plural] or return %(translation missing: "#{path}")
78
73
  end
74
+ sprintf value, Hash.new{|_,k| "%{#{k}}"}.merge!(vars) # interpolation
79
75
  end
80
76
 
81
77
  end
data/pagy.gemspec CHANGED
@@ -29,5 +29,13 @@ Gem::Specification.new do |s|
29
29
  s.add_development_dependency 'benchmark-ips'
30
30
  s.add_development_dependency 'kalibera'
31
31
  s.add_development_dependency 'memory_profiler'
32
+ s.add_development_dependency 'rubocop', '~> 0.55.0' # needs to be fixed since it constantly adds new cops
33
+
34
+
35
+ s.post_install_message = <<EOM
36
+ ******************************************************************************
37
+ Pagy CHANGELOG: https://github.com/ddnexus/pagy/blob/master/CHANGELOG.md
38
+ ******************************************************************************
39
+ EOM
32
40
 
33
41
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pagy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Domizio Demichelis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-28 00:00:00.000000000 Z
11
+ date: 2018-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rubocop
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 0.55.0
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: 0.55.0
139
153
  description: 'Agnostic pagination in plain ruby: it works with any framework, ORM
140
154
  and DB type, with all kinds of collections, even pre-paginated, scopes, Arrays,
141
155
  JSON data... and just whatever you can count. Easy to use and customize, very fast
@@ -150,16 +164,30 @@ files:
150
164
  - lib/locales/pagy.yml
151
165
  - lib/pagy.rb
152
166
  - lib/pagy/backend.rb
167
+ - lib/pagy/extras/array.rb
168
+ - lib/pagy/extras/bootstrap.rb
169
+ - lib/pagy/extras/compact.rb
170
+ - lib/pagy/extras/i18n.rb
171
+ - lib/pagy/extras/initializer_example.rb
172
+ - lib/pagy/extras/javascripts/pagy-compact.js
173
+ - lib/pagy/extras/javascripts/pagy-responsive.js
174
+ - lib/pagy/extras/responsive.rb
175
+ - lib/pagy/extras/templates/nav.html.erb
176
+ - lib/pagy/extras/templates/nav.html.haml
177
+ - lib/pagy/extras/templates/nav.html.slim
178
+ - lib/pagy/extras/templates/nav_bootstrap.html.erb
179
+ - lib/pagy/extras/templates/nav_bootstrap.html.haml
180
+ - lib/pagy/extras/templates/nav_bootstrap.html.slim
153
181
  - lib/pagy/frontend.rb
154
- - lib/templates/nav.html.erb
155
- - lib/templates/nav.html.haml
156
- - lib/templates/nav.html.slim
157
182
  - pagy.gemspec
158
183
  homepage: https://github.com/ddnexus/pagy
159
184
  licenses:
160
185
  - MIT
161
186
  metadata: {}
162
- post_install_message:
187
+ post_install_message: |
188
+ ******************************************************************************
189
+ Pagy CHANGELOG: https://github.com/ddnexus/pagy/blob/master/CHANGELOG.md
190
+ ******************************************************************************
163
191
  rdoc_options: []
164
192
  require_paths:
165
193
  - lib