Skip to content

Commit

Permalink
code-restyling: extras
Browse files Browse the repository at this point in the history
  • Loading branch information
ddnexus committed Apr 10, 2021
1 parent b2dc35a commit cb67353
Show file tree
Hide file tree
Showing 24 changed files with 499 additions and 311 deletions.
28 changes: 14 additions & 14 deletions lib/pagy.rb
Expand Up @@ -45,22 +45,22 @@ def series(size=@vars[:size])
raise VariableError.new(self), "expected 4 items >= 0 in :size; got #{size.inspect}" \
unless size.size == 4 && size.all?{ |num| num >= 0 rescue false } # rubocop:disable Style/RescueModifier

[].tap do |series|
[ *0..size[0], # initial pages from 0
*@page-size[1]..@page+size[2], # around current page
*@last-size[3]+1..@last+1 # final pages till @last+1
].sort!.each_cons(2) do |left, right| # sort and loop by 2
next if left.negative? || left == right # skip out of range and duplicates
break if left > @last # break if out of @last boundary
case right
when left+1 then series.push(left) # no gap -> no additions
when left+2 then series.push(left, left+1) # 1 page gap -> fill with missing page
else series.push(left, :gap) # n page gap -> add gap
end
series = []
[ *0..size[0], # initial pages from 0
*@page-size[1]..@page+size[2], # around current page
*@last-size[3]+1..@last+1 # final pages till @last+1
].sort!.each_cons(2) do |left, right| # sort and loop by 2
next if left.negative? || left == right # skip out of range and duplicates
break if left > @last # break if out of @last boundary
case right
when left+1 then series.push(left) # no gap -> no additions
when left+2 then series.push(left, left+1) # 1 page gap -> fill with missing page
else series.push(left, :gap) # n page gap -> add gap
end
series.shift # shift the start boundary (0)
series[series.index(@page)] = @page.to_s # convert the current page to String
end
series.shift # shift the start boundary (0)
series[series.index(@page)] = @page.to_s # convert the current page to String
series
end

end
Expand Down
1 change: 1 addition & 0 deletions lib/pagy/countless.rb
Expand Up @@ -22,6 +22,7 @@ def initialize(vars={}) # rubocop:disable Lint/MissingSuper
def finalize(fetched)
raise OverflowError.new(self), "page #{@page} got no items" \
if fetched.zero? && @page > 1

@pages = @last = (fetched > @items ? @page + 1 : @page) # set the @pages and @last
@items = fetched if fetched < @items && fetched.positive? # adjust items for last non-empty page
@from = fetched.zero? ? 0 : @offset + 1 - @outset # page begins from item
Expand Down
6 changes: 3 additions & 3 deletions lib/pagy/extras/arel.rb
@@ -1,13 +1,13 @@
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/arel
# encoding: utf-8
# frozen_string_literal: true

class Pagy
module Backend ; private
module Backend
private

def pagy_arel(collection, vars={})
pagy = Pagy.new(pagy_arel_get_vars(collection, vars))
return pagy, pagy_get_items(collection, pagy)
[ pagy, pagy_get_items(collection, pagy) ]
end

def pagy_arel_get_vars(collection, vars)
Expand Down
6 changes: 3 additions & 3 deletions lib/pagy/extras/array.rb
@@ -1,15 +1,15 @@
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/array
# encoding: utf-8
# frozen_string_literal: true

class Pagy
# Add specialized backend methods to paginate array collections
module Backend ; private
module Backend
private

# Return Pagy object and items
def pagy_array(array, vars={})
pagy = Pagy.new(pagy_array_get_vars(array, vars))
return pagy, array[pagy.offset, pagy.items]
[ pagy, array[pagy.offset, pagy.items] ]
end

# Sub-method called only by #pagy_array: here for easy customization of variables by overriding
Expand Down
81 changes: 54 additions & 27 deletions lib/pagy/extras/bootstrap.rb
@@ -1,5 +1,4 @@
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/bootstrap
# encoding: utf-8
# frozen_string_literal: true

require 'pagy/extras/shared'
Expand All @@ -9,47 +8,75 @@ module Frontend

# Pagination for bootstrap: it returns the html with the series of links to the pages
def pagy_bootstrap_nav(pagy)
link, p_prev, p_next = pagy_link_proc(pagy, 'class="page-link"'), pagy.prev, pagy.next
link = pagy_link_proc(pagy, 'class="page-link"')

html = (p_prev ? %(<li class="page-item prev">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'}</li>)
: %(<li class="page-item prev disabled"><a href="#" class="page-link">#{pagy_t('pagy.nav.prev')}</a></li>))
html = +%(<nav class="pagy-bootstrap-nav" role="navigation" aria-label="pager"><ul class="pagination">)
html << pagy_bootstrap_prev_html(pagy, link)
pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
html << if item.is_a?(Integer); %(<li class="page-item">#{link.call item}</li>) # page link
elsif item.is_a?(String) ; %(<li class="page-item active">#{link.call item}</li>) # active page
elsif item == :gap ; %(<li class="page-item gap disabled"><a href="#" class="page-link">#{pagy_t('pagy.nav.gap')}</a></li>) # page gap
html << case item
when Integer then %(<li class="page-item">#{link.call item}</li>)
when String then %(<li class="page-item active">#{link.call item}</li>)
when :gap then %(<li class="page-item gap disabled"><a href="#" class="page-link">#{pagy_t 'pagy.nav.gap'}</a></li>)
end
end
html << (p_next ? %(<li class="page-item next">#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'}</li>)
: %(<li class="page-item next disabled"><a href="#" class="page-link">#{pagy_t('pagy.nav.next')}</a></li>))
%(<nav class="pagy-bootstrap-nav" role="navigation" aria-label="pager"><ul class="pagination">#{html}</ul></nav>)
html << pagy_bootstrap_next_html(pagy, link)
html << %(</ul></nav>)
end

# Javascript pagination for bootstrap: it returns a nav and a JSON tag used by the Pagy.nav javascript
def pagy_bootstrap_nav_js(pagy, id=pagy_id)
link, p_prev, p_next = pagy_link_proc(pagy, 'class="page-link"'), pagy.prev, pagy.next
tags = { 'before' => p_prev ? %(<ul class="pagination"><li class="page-item prev">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'}</li>)
: %(<ul class="pagination"><li class="page-item prev disabled"><a href="#" class="page-link">#{pagy_t('pagy.nav.prev')}</a></li>),
link = pagy_link_proc(pagy, 'class="page-link"')
tags = { 'before' => %(<ul class="pagination">#{pagy_bootstrap_prev_html pagy, link}),
'link' => %(<li class="page-item">#{mark = link.call(PAGE_PLACEHOLDER)}</li>),
'active' => %(<li class="page-item active">#{mark}</li>),
'gap' => %(<li class="page-item gap disabled"><a href="#" class="page-link">#{pagy_t('pagy.nav.gap')}</a></li>),
'after' => p_next ? %(<li class="page-item next">#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'}</li></ul>)
: %(<li class="page-item next disabled"><a href="#" class="page-link">#{pagy_t('pagy.nav.next')}</a></li></ul>) }
%(<nav id="#{id}" class="pagy-bootstrap-nav-js" role="navigation" aria-label="pager"></nav>#{pagy_json_tag(pagy, :nav, id, tags, pagy.sequels)})
'gap' => %(<li class="page-item gap disabled"><a href="#" class="page-link">#{pagy_t 'pagy.nav.gap'}</a></li>),
'after' => %(#{pagy_bootstrap_next_html pagy, link}</ul>) }

html = %(<nav id="#{id}" class="pagy-bootstrap-nav-js" role="navigation" aria-label="pager"></nav>)
html << pagy_json_tag(pagy, :nav, id, tags, pagy.sequels)
end

# Javascript combo pagination for bootstrap: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
def pagy_bootstrap_combo_nav_js(pagy, id=pagy_id)
link, p_prev, p_next, p_page, p_pages = pagy_link_proc(pagy), pagy.prev, pagy.next, pagy.page, pagy.pages

html = %(<nav id="#{id}" class="pagy-bootstrap-combo-nav-js pagination" role="navigation" aria-label="pager">) + %(<div class="btn-group" role="group">)
html << (p_prev ? link.call(p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous" class="prev btn btn-primary"')
: %(<a class="prev btn btn-primary disabled" href="#">#{pagy_t('pagy.nav.prev')}</a>))
input = %(<input type="number" min="1" max="#{p_pages}" value="#{p_page}" class="text-primary" style="padding: 0; border: none; text-align: center; width: #{p_pages.to_s.length+1}rem;">)
html << %(<div class="pagy-combo-input btn btn-primary disabled" style="white-space: nowrap;">#{pagy_t('pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages)}</div>)
html << (p_next ? link.call(p_next, pagy_t('pagy.nav.next'), 'aria-label="next" class="next btn btn-primary"')
: %(<a class="next btn btn-primary disabled" href="#">#{pagy_t('pagy.nav.next')}</a>))
html << %(</div></nav>#{pagy_json_tag(pagy, :combo_nav, id, p_page, pagy_marked_link(link))})
link = pagy_link_proc(pagy)
p_page = pagy.page
p_pages = pagy.pages
input = %(<input type="number" min="1" max="#{p_pages}" value="#{p_page}" class="text-primary" style="padding: 0; border: none; text-align: center; width: #{p_pages.to_s.length+1}rem;">)

%(<nav id="#{id}" class="pagy-bootstrap-combo-nav-js pagination" role="navigation" aria-label="pager"><div class="btn-group" role="group">#{
if (p_prev = pagy.prev)
link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous" class="prev btn btn-primary"'
else
%(<a class="prev btn btn-primary disabled" href="#">#{pagy_t('pagy.nav.prev')}</a>)
end
}<div class="pagy-combo-input btn btn-primary disabled" style="white-space: nowrap;">#{pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages}</div>#{
if (p_next = pagy.next)
link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next" class="next btn btn-primary"'
else
%(<a class="next btn btn-primary disabled" href="#">#{pagy_t 'pagy.nav.next' }</a>)
end
}</div></nav>#{
pagy_json_tag(pagy, :combo_nav, id, p_page, pagy_marked_link(link))
})
end

private

def pagy_bootstrap_prev_html(pagy, link)
if (p_prev = pagy.prev)
%(<li class="page-item prev">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'}</li>)
else
%(<li class="page-item prev disabled"><a href="#" class="page-link">#{pagy_t 'pagy.nav.prev'}</a></li>)
end
end

def pagy_bootstrap_next_html(pagy, link)
if (p_next = pagy.next)
%(<li class="page-item next">#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'}</li>)
else
%(<li class="page-item next disabled"><a href="#" class="page-link">#{pagy_t 'pagy.nav.next'}</a></li>)
end
end

end
end
86 changes: 52 additions & 34 deletions lib/pagy/extras/bulma.rb
@@ -1,5 +1,4 @@
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/bulma
# encoding: utf-8
# frozen_string_literal: true

require 'pagy/extras/shared'
Expand All @@ -9,52 +8,71 @@ module Frontend

# Pagination for Bulma: it returns the html with the series of links to the pages
def pagy_bulma_nav(pagy)
link, p_prev, p_next = pagy_link_proc(pagy), pagy.prev, pagy.next
link = pagy_link_proc(pagy)

html = (p_prev ? link.call(p_prev, pagy_t('pagy.nav.prev'), 'class="pagination-previous" aria-label="previous page"')
: %(<a class="pagination-previous" disabled>#{pagy_t('pagy.nav.prev')}</a>)) \
+ (p_next ? link.call(p_next, pagy_t('pagy.nav.next'), 'class="pagination-next" aria-label="next page"')
: %(<a class="pagination-next" disabled>#{pagy_t('pagy.nav.next')}</a>))
html << '<ul class="pagination-list">'
html = +%(<nav class="pagy-bulma-nav pagination is-centered" role="navigation" aria-label="pagination">)
html << pagy_bulma_prev_next_html(pagy, link)
html << %(<ul class="pagination-list">)
pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
html << if item.is_a?(Integer); %(<li>#{link.call item, item, %(class="pagination-link" aria-label="goto page #{item}") }</li>) # page link
elsif item.is_a?(String) ; %(<li>#{link.call item, item, %(class="pagination-link is-current" aria-label="page #{item}" aria-current="page")}</li>) # active page
elsif item == :gap ; %(<li><span class="pagination-ellipsis">#{pagy_t('pagy.nav.gap')}</span></li>) # page gap
html << case item
when Integer then %(<li>#{link.call item, item, %(class="pagination-link" aria-label="goto page #{item}") }</li>) # page link
when String then %(<li>#{link.call item, item, %(class="pagination-link is-current" aria-label="page #{item}" aria-current="page")}</li>) # active page
when :gap then %(<li><span class="pagination-ellipsis">#{pagy_t('pagy.nav.gap')}</span></li>) # page gap
end
end
html << '</ul>'
%(<nav class="pagy-bulma-nav pagination is-centered" role="navigation" aria-label="pagination">#{html}</nav>)
html << %(</ul></nav>)
end

# Javascript pagination for bulma: it returns a nav and a JSON tag used by the Pagy.nav javascript
def pagy_bulma_nav_js(pagy, id=pagy_id)
link, p_prev, p_next = pagy_link_proc(pagy), pagy.prev, pagy.next
tags = { 'before' => ( (p_prev ? link.call(p_prev, pagy_t('pagy.nav.prev'), 'class="pagination-previous" aria-label="previous page"')
: %(<a class="pagination-previous" disabled>#{pagy_t('pagy.nav.prev')}</a>)) \
+ (p_next ? link.call(p_next, pagy_t('pagy.nav.next'), 'class="pagination-next" aria-label="next page"')
: %(<a class="pagination-next" disabled>#{pagy_t('pagy.nav.next')}</a>)) \
+ '<ul class="pagination-list">' ),
'link' => %(<li>#{link.call(PAGE_PLACEHOLDER, PAGE_PLACEHOLDER, %(class="pagination-link" aria-label="goto page #{PAGE_PLACEHOLDER}"))}</li>),
'active' => %(<li>#{link.call(PAGE_PLACEHOLDER, PAGE_PLACEHOLDER, %(class="pagination-link is-current" aria-current="page" aria-label="page #{PAGE_PLACEHOLDER}"))}</li>),
'gap' => %(<li><span class="pagination-ellipsis">#{pagy_t('pagy.nav.gap')}</span></li>),
link = pagy_link_proc(pagy)
tags = { 'before' => %(#{pagy_bulma_prev_next_html(pagy, link)}<ul class="pagination-list">),
'link' => %(<li>#{link.call PAGE_PLACEHOLDER, PAGE_PLACEHOLDER, %(class="pagination-link" aria-label="goto page #{PAGE_PLACEHOLDER}")}</li>),
'active' => %(<li>#{link.call PAGE_PLACEHOLDER, PAGE_PLACEHOLDER, %(class="pagination-link is-current" aria-current="page" aria-label="page #{PAGE_PLACEHOLDER}")}</li>),
'gap' => %(<li><span class="pagination-ellipsis">#{pagy_t 'pagy.nav.gap' }</span></li>),
'after' => '</ul>' }
%(<nav id="#{id}" class="pagy-bulma-nav-js pagination is-centered" role="navigation" aria-label="pagination"></nav>#{pagy_json_tag(pagy, :nav, id, tags, pagy.sequels)})

html = %(<nav id="#{id}" class="pagy-bulma-nav-js pagination is-centered" role="navigation" aria-label="pagination"></nav>)
html << pagy_json_tag(pagy, :nav, id, tags, pagy.sequels)
end

# Javascript combo pagination for Bulma: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
def pagy_bulma_combo_nav_js(pagy, id=pagy_id)
link, p_prev, p_next, p_page, p_pages = pagy_link_proc(pagy), pagy.prev, pagy.next, pagy.page, pagy.pages

html = %(<nav id="#{id}" class="pagy-bulma-combo-nav-js" role="navigation" aria-label="pagination">) \
+ %(<div class="field is-grouped is-grouped-centered" role="group">)
html << (p_prev ? %(<p class="control">#{link.call(p_prev, pagy_t('pagy.nav.prev'), 'class="button" aria-label="previous page"')}</p>)
: %(<p class="control"><a class="button" disabled>#{pagy_t('pagy.nav.prev')}</a></p>))
input = %(<input class="input" type="number" min="1" max="#{p_pages}" value="#{p_page}" style="padding: 0; text-align: center; width: #{p_pages.to_s.length+1}rem; margin:0 0.3rem;">)
html << %(<div class="pagy-combo-input control level is-mobile">#{pagy_t('pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages)}</div>)
html << (p_next ? %(<p class="control">#{link.call(p_next, pagy_t('pagy.nav.next'), 'class="button" aria-label="next page"')}</p>)
: %(<p class="control"><a class="button" disabled>#{pagy_t('pagy.nav.next')}</a></p>))
html << %(</div></nav>#{pagy_json_tag(pagy, :combo_nav, id, p_page, pagy_marked_link(link))})
link = pagy_link_proc(pagy)
p_page = pagy.page
p_pages = pagy.pages
input = %(<input class="input" type="number" min="1" max="#{p_pages}" value="#{p_page}" style="padding: 0; text-align: center; width: #{p_pages.to_s.length+1}rem; margin:0 0.3rem;">)

%(<nav id="#{id}" class="pagy-bulma-combo-nav-js" role="navigation" aria-label="pagination"><div class="field is-grouped is-grouped-centered" role="group">#{
if (p_prev = pagy.prev)
%(<p class="control">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'class="button" aria-label="previous page"'}</p>)
else
%(<p class="control"><a class="button" disabled>#{pagy_t 'pagy.nav.prev'}</a></p>)
end
}<div class="pagy-combo-input control level is-mobile">#{pagy_t('pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages)}</div>#{
if (p_next = pagy.next)
%(<p class="control">#{link.call p_next, pagy_t('pagy.nav.next'), 'class="button" aria-label="next page"'}</p>)
else
%(<p class="control"><a class="button" disabled>#{pagy_t 'pagy.nav.next'}</a></p>)
end
}</div></nav>#{
pagy_json_tag(pagy, :combo_nav, id, p_page, pagy_marked_link(link))
})
end

private

def pagy_bulma_prev_next_html(pagy, link)
html = if (p_prev = pagy.prev)
link.call p_prev, pagy_t('pagy.nav.prev'), 'class="pagination-previous" aria-label="previous page"'
else
%(<a class="pagination-previous" disabled>#{pagy_t 'pagy.nav.prev'}</a>)
end
html << if (p_next = pagy.next)
link.call p_next, pagy_t('pagy.nav.next'), 'class="pagination-next" aria-label="next page"'
else
%(<a class="pagination-next" disabled>#{pagy_t 'pagy.nav.next' }</a>)
end
end

end
end

0 comments on commit cb67353

Please sign in to comment.