pagy 0.7.2 → 0.8.0

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