module Pagy::Frontend
def self.deprecate(old_meth, new_meth)
def self.deprecate(old_meth, new_meth) send(:define_method, old_meth) do |pagy, id=pagy_id| Warning.warn "WARNING: The ##{old_meth} pagy helper method is deprecated and will be removed in 2.0; please use ##{new_meth} instead. More info at https://github.com/ddnexus/pagy/blob/master/DEPRECATIONS.md\n" method(new_meth).arity == 1 ? send(new_meth, pagy) : send(new_meth, pagy, id) end end
def pagy_apply_init_tag(pagy, function, payload=pagy_serialized(pagy))
def pagy_apply_init_tag(pagy, function, payload=pagy_serialized(pagy)) pagy_json_tag(:applyInit, function, payload) end
def pagy_bootstrap_compact_nav(pagy, id=pagy_id)
Compact pagination for bootstrap: it returns the html with the series of links to the pages
def pagy_bootstrap_compact_nav(pagy, id=pagy_id) html, 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-nav-compact-bootstrap pagy-bootstrap-compact-nav pagination" role="navigation" aria-label="pager">) html << link.call(MARKER, '', %(style="display: none;" )) (html << link.call(1, '', %(style="display: none;" ))) if defined?(TRIM) html << %(<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-compact-input btn btn-primary disabled">#{pagy_t('pagy.compact', 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(:compact, id, MARKER, p_page, !!defined?(TRIM))}) end
def pagy_bootstrap_nav(pagy)
def pagy_bootstrap_nav(pagy) html, link, p_prev, p_next = +'', pagy_link_proc(pagy, 'class="page-link"'), pagy.prev, pagy.next 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>)) 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 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-nav-bootstrap pagy-bootstrap-nav pagination" role="navigation" aria-label="pager"><ul class="pagination">#{html}</ul></nav>) end
def pagy_bootstrap_responsive_nav(pagy, id=pagy_id)
Responsive pagination for bootstrap: it returns the html with the series of links to the pages
def pagy_bootstrap_responsive_nav(pagy, id=pagy_id) tags, link, p_prev, p_next, responsive = {}, pagy_link_proc(pagy, 'class="page-link"'), pagy.prev, pagy.next, pagy.responsive tags['before'] = +'<ul class="pagination">' tags['before'] << (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>)) responsive[:items].each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36] tags[item.to_s] = 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 end end tags['after'] = +(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>)) tags['after'] << '</ul>' script = pagy_json_tag(:responsive, id, tags, responsive[:widths], responsive[:series]) %(<nav id="#{id}" class="pagy-nav-responsive-bootstrap pagy-bootstrap-responsive-nav pagination" role="navigation" aria-label="pager"></nav>#{script}) end
def pagy_bulma_compact_nav(pagy, id=pagy_id)
Compact pagination for Bulma: it returns the html with the series of links to the pages
def pagy_bulma_compact_nav(pagy, id=pagy_id) html, 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-nav-compact-bulma pagy-bulma-compact-nav" role="navigation" aria-label="pagination">) html << link.call(MARKER, '', 'style="display: none;"') (html << link.call(1, '', %(style="display: none;"))) if defined?(TRIM) html << %(<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-compact-input control level is-mobile">#{pagy_t('pagy.compact', 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(:compact, id, MARKER, p_page, !!defined?(TRIM))}) end
def pagy_bulma_nav(pagy)
def pagy_bulma_nav(pagy) html, link, p_prev, p_next = +'', pagy_link_proc(pagy), pagy.prev, pagy.next 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>)) html << (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">' 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 end end html << '</ul>' %(<nav class="pagy-nav-bulma pagy-bulma-nav pagination is-centered" role="navigation" aria-label="pagination">#{html}</nav>) end
def pagy_bulma_responsive_nav(pagy, id=pagy_id)
Responsive pagination for Bulma: it returns the html with the series of links to the pages
def pagy_bulma_responsive_nav(pagy, id=pagy_id) tags, link, p_prev, p_next, responsive = {}, pagy_link_proc(pagy), pagy.prev, pagy.next, pagy.responsive 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>)) tags['before'] << (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>)) tags['before'] << '<ul class="pagination-list">' responsive[:items].each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36] tags[item.to_s] = if item.is_a?(Integer); %(<li>#{link.call item, item, %(class="pagination-link" aria-label="goto page #{item}")}</li>) elsif item.is_a?(String) ; %(<li>#{link.call item, item, %(class="pagination-link is-current" aria-current="page" aria-label="page #{item}")}</li>) elsif item == :gap ; %(<li><span class="pagination-ellipsis">#{pagy_t('pagy.nav.gap')}</span></li>) end end tags['after'] = '</ul>' script = pagy_json_tag(:responsive, id, tags, responsive[:widths], responsive[:series]) %(<nav id="#{id}" class="pagy-nav-responsive-bulma pagy-bulma-responsive-nav pagination is-centered" role="navigation" aria-label="pagination"></nav>#{script}) end
def pagy_foundation_compact_nav(pagy, id=pagy_id)
Compact pagination for Foundation: it returns the html with the series of links to the pages
def pagy_foundation_compact_nav(pagy, id=pagy_id) html, 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-nav-compact-foundation pagy-foundation-compact-nav" role="navigation" aria-label="Pagination">) html << link.call(MARKER, '', %(style="display: none;" )) (html << link.call(1, '', %(style="display: none;" ))) if defined?(TRIM) html << %(<div class="input-group">) html << (p_prev ? link.call(p_prev, pagy_t('pagy.nav.prev'), 'style="margin-bottom: 0px;" aria-label="previous" class="prev button primary"') : %(<a style="margin-bottom: 0px;" class="prev button primary disabled" href="#">#{pagy_t('pagy.nav.prev')}</a>)) input = %(<input class="input-group-field cell shrink" type="number" min="1" max="#{p_pages}" value="#{p_page}" style="width: #{p_pages.to_s.length+1}rem; padding: 0 0.3rem; margin: 0 0.3rem;">) html << %(<span class="input-group-label">#{pagy_t('pagy.compact', page_input: input, count: p_page, pages: p_pages)}</span>) html << (p_next ? link.call(p_next, pagy_t('pagy.nav.next'), 'style="margin-bottom: 0px;" aria-label="next" class="next button primary"') : %(<a style="margin-bottom: 0px;" class="next button primary disabled" href="#">#{pagy_t('pagy.nav.next')}</a>)) html << %(</div></nav>#{pagy_json_tag(:compact, id, MARKER, p_page, !!defined?(TRIM))}) end
def pagy_foundation_nav(pagy)
def pagy_foundation_nav(pagy) html, link, p_prev, p_next = +'', pagy_link_proc(pagy), pagy.prev, pagy.next html << (p_prev ? %(<li class="prev">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'}</li>) : %(<li class="prev disabled">#{pagy_t('pagy.nav.prev')}</li>)) 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}</li>) # page link elsif item.is_a?(String) ; %(<li class="current">#{item}</li>) # active page elsif item == :gap ; %(<li class="ellipsis gap" aria-hidden="true"></li>) # page gap end end html << (p_next ? %(<li class="next">#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'}</li>) : %(<li class="next disabled">#{pagy_t('pagy.nav.next')}</li>)) %(<nav class="pagy-nav-foundation pagy-foundation-nav" role="navigation" aria-label="Pagination"><ul class="pagination">#{html}</ul></nav>) end
def pagy_foundation_responsive_nav(pagy, id=pagy_id)
Responsive pagination for Foundation: it returns the html with the series of links to the pages
def pagy_foundation_responsive_nav(pagy, id=pagy_id) tags, link, p_prev, p_next, responsive = {}, pagy_link_proc(pagy), pagy.prev, pagy.next, pagy.responsive tags['before'] = +'<ul class="pagination">' tags['before'] << (p_prev ? %(<li class="prev">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'}</li>) : %(<li class="prev disabled">#{pagy_t('pagy.nav.prev')}</li>)) responsive[:items].each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36] tags[item.to_s] = if item.is_a?(Integer); %(<li>#{link.call item}</li>) # page link elsif item.is_a?(String) ; %(<li class="current">#{item}</li>) # active page elsif item == :gap ; %(<li class="ellipsis gap" aria-hidden="true"></li>) # page gap end end tags['after'] = +(p_next ? %(<li class="next">#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'}</li>) : %(<li class="next disabled">#{pagy_t('pagy.nav.next')}</li>)) tags['after'] << '</ul>' script = pagy_json_tag(:responsive, id, tags, responsive[:widths], responsive[:series]) %(<nav id="#{id}" class="pagy-nav-responsive-foundation pagy-foundation-responsive-nav" aria-label="Pagination"></nav>#{script}) end
def pagy_get_params(params) params end
def pagy_get_params(params) params end
def pagy_id
def pagy_id # SHA1 is the fastest on modern ruby "pagy-#{Digest::SHA1.hexdigest(caller(2..2)[0].split(':in')[0])}" end
def pagy_info(pagy)
def pagy_info(pagy) name = pagy_t(pagy.vars[:item_path], count: pagy.count) path = pagy.pages == 1 ? 'pagy.info.single_page' : 'pagy.info.multiple_pages' pagy_t(path, item_name: name, count: pagy.count, from: pagy.from, to: pagy.to) end
def pagy_items_selector(pagy, id=pagy_id)
def pagy_items_selector(pagy, id=pagy_id) p_vars = pagy.vars; p_items = p_vars[:items]; p_vars[:items] = "#{MARKER}-items-" html = +%(<span id="#{id}">) html << %(<a href="#{pagy_url_for("#{MARKER}-page-", pagy)}"></a>) p_vars[:items] = p_items # restore the items input = %(<input type="number" min="1" max="#{p_vars[:max_items]}" value="#{p_items}" style="padding: 0; text-align: center; width: #{p_items.to_s.length+1}rem;">) html << %(#{pagy_t('pagy.items', items_input: input, count: p_items)}) html << %(</span>#{pagy_json_tag(:items, id, MARKER, pagy.from)}) end
def pagy_json_tag(*args)
def pagy_json_tag(*args) %(<script type="application/json" class="pagy-json">#{args.to_json}</script>) end
def pagy_link_proc(pagy, link_extra='')
Returns a performance optimized proc to generate the HTML links
def pagy_link_proc(pagy, link_extra='') p_prev, p_next = pagy.prev, pagy.next a, b = %(<a href="#{pagy_url_for(MARKER, pagy)}" #{pagy.vars[:link_extra]} #{link_extra}).split(MARKER, 2) -> (n, text=n, extra='') { "#{a}#{n}#{b}#{ if n == p_prev ; ' rel="prev"' elsif n == p_next ; ' rel="next"' else '' end } #{extra}>#{text}</a>" } end
def pagy_link_proc_with_trim(pagy, link_extra='')
def pagy_link_proc_with_trim(pagy, link_extra='') p_prev, p_next, p_vars = pagy.prev, pagy.next, pagy.vars marker_url = pagy_url_for(MARKER, pagy) page1_url = pagy_trim_url(marker_url, "#{p_vars[:page_param]}=#{MARKER}") page1_link = %(<a href="#{page1_url}" #{p_vars[:link_extra]} #{link_extra}) a, b = %(<a href="#{marker_url}" #{p_vars[:link_extra]} #{link_extra}).split(MARKER, 2) -> (n, text=n, extra='') { start = n.to_i == 1 ? page1_link : "#{a}#{n}#{b}" "#{start}#{ if n == p_prev ; ' rel="prev"' elsif n == p_next ; ' rel="next"' else '' end } #{extra}>#{text}</a>" } end
def pagy_materialize_compact_nav(pagy, id=pagy_id)
Compact pagination for materialize: it returns the html with the series of links to the pages
def pagy_materialize_compact_nav(pagy, id=pagy_id) html, link, p_prev, p_next, p_page, p_pages = +'', pagy_link_proc(pagy), pagy.prev, pagy.next, pagy.page, pagy.pages html << %(<div id="#{id}" class="pagy-nav-compact-materialize pagy-materialize-compact-nav pagination" role="navigation" aria-label="pager">) html << link.call(MARKER, '', %(style="display: none;" )) (html << link.call(1, '', %(style="display: none;" ))) if defined?(TRIM) html << %(<div class="pagy-compact-chip role="group" style="height: 35px; border-radius: 18px; background: #e4e4e4; display: inline-block;">) html << '<ul class="pagination" style="margin: 0px;">' li_style = 'style="vertical-align: middle;"' html << (p_prev ? %(<li class="waves-effect prev" #{li_style}>#{link.call p_prev, '<i class="material-icons">chevron_left</i>', 'aria-label="previous"'}</li>) : %(<li class="prev disabled" #{li_style}><a href="#"><i class="material-icons">chevron_left</i></a></li>)) input = %(<input type="number" class="browser-default" min="1" max="#{p_pages}" value="#{p_page}" style="padding: 2px; border: none; border-radius: 2px; text-align: center; width: #{p_pages.to_s.length+1}rem;">) html << %(<div class="pagy-compact-input btn-flat" style="cursor: default; padding: 0px">#{pagy_t('pagy.compact', page_input: input, count: p_page, pages: p_pages)}</div>) html << (p_next ? %(<li class="waves-effect next" #{li_style}>#{link.call p_next, '<i class="material-icons">chevron_right</i>', 'aria-label="next"'}</li>) : %(<li class="next disabled" #{li_style}><a href="#"><i class="material-icons">chevron_right</i></a></li>)) html << %(</ul></div>#{pagy_json_tag(:compact, id, MARKER, p_page, !!defined?(TRIM))}) end
def pagy_materialize_nav(pagy)
def pagy_materialize_nav(pagy) html, link, p_prev, p_next = +'', pagy_link_proc(pagy), pagy.prev, pagy.next html << (p_prev ? %(<li class="waves-effect prev">#{link.call p_prev, '<i class="material-icons">chevron_left</i>', 'aria-label="previous"'}</li>) : %(<li class="prev disabled"><a href="#"><i class="material-icons">chevron_left</i></a></li>)) pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36] html << if item.is_a?(Integer); %(<li class="waves-effect">#{link.call item}</li>) # page link elsif item.is_a?(String) ; %(<li class="active">#{link.call item}</li>) # active page elsif item == :gap ; %(<li class="gap disabled"><a href="#">#{pagy_t('pagy.nav.gap')}</a></li>) # page gap end end html << (p_next ? %(<li class="waves-effect next">#{link.call p_next, '<i class="material-icons">chevron_right</i>', 'aria-label="next"'}</li>) : %(<li class="next disabled"><a href="#"><i class="material-icons">chevron_right</i></a></li>)) %(<div class="pagy-nav-materialize pagy-materialize-nav pagination" role="navigation" aria-label="pager"><ul class="pagination">#{html}</ul></div>) end
def pagy_materialize_responsive_nav(pagy, id=pagy_id)
Responsive pagination for Materialize: it returns the html with the series of links to the pages
def pagy_materialize_responsive_nav(pagy, id=pagy_id) tags, link, p_prev, p_next, responsive = {}, pagy_link_proc(pagy), pagy.prev, pagy.next, pagy.responsive tags['before'] = +'<ul class="pagination">' tags['before'] << (p_prev ? %(<li class="waves-effect prev">#{link.call p_prev, '<i class="material-icons">chevron_left</i>', 'aria-label="previous"'}</li>) : %(<li class="prev disabled"><a href="#"><i class="material-icons">chevron_left</i></a></li>)) responsive[:items].each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36] tags[item.to_s] = if item.is_a?(Integer); %(<li class="waves-effect">#{link.call item}</li>) # page link elsif item.is_a?(String) ; %(<li class="active">#{link.call item}</li>) # active page elsif item == :gap ; %(<li class="gap disabled"><a href="#">#{pagy_t('pagy.nav.gap')}</a></li>) # page gap end end tags['after'] = +(p_next ? %(<li class="waves-effect next">#{link.call p_next, '<i class="material-icons">chevron_right</i>', 'aria-label="next"'}</li>) : %(<li class="next disabled"><a href="#"><i class="material-icons">chevron_right</i></a></li>)) tags['after'] << '</ul>' script = pagy_json_tag(:responsive, id, tags, responsive[:widths], responsive[:series]) %(<div id="#{id}" class="pagy-nav-responsive-materialize pagy-materialize-responsive-nav pagination" role="navigation" aria-label="pager"></div>#{script}) end
def pagy_nav(pagy)
def pagy_nav(pagy) html, link, p_prev, p_next = +'', pagy_link_proc(pagy), pagy.prev, pagy.next html << (p_prev ? %(<span class="page prev">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'}</span> ) : %(<span class="page prev disabled">#{pagy_t('pagy.nav.prev')}</span> )) pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36] html << if item.is_a?(Integer); %(<span class="page">#{link.call item}</span> ) # page link elsif item.is_a?(String) ; %(<span class="page active">#{item}</span> ) # current page elsif item == :gap ; %(<span class="page gap">#{pagy_t('pagy.nav.gap')}</span> ) # page gap end end html << (p_next ? %(<span class="page next">#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'}</span>) : %(<span class="page next disabled">#{pagy_t('pagy.nav.next')}</span>)) %(<nav class="pagy-nav pagination" role="navigation" aria-label="pager">#{html}</nav>) end
def pagy_next_link(pagy, text = pagy_t('pagy.nav.next'), link_extra = '')
def pagy_next_link(pagy, text = pagy_t('pagy.nav.next'), link_extra = '') pagy.next ? %(<span class="page next"><a href="#{pagy_next_url(pagy)}" rel="next" aria-label="next" #{pagy.vars[:link_extra]} #{link_extra}>#{text}</a></span>) : %(<span class="page next disabled">#{text}</span>) end
def pagy_next_url(pagy)
def pagy_next_url(pagy) pagy_url_for(pagy.next, pagy) if pagy.next end
def pagy_plain_compact_nav(pagy, id=pagy_id)
Plain compact pagination: it returns the html with the series of links to the pages
def pagy_plain_compact_nav(pagy, id=pagy_id) html, 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-nav-compact pagy-plain-compact-nav pagination" role="navigation" aria-label="pager">) html << link.call(MARKER, '', %(style="display: none;" )) (html << link.call(1, '', %(style="display: none;" ))) if defined?(TRIM) html << (p_prev ? %(<span class="page prev">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'}</span> ) : %(<span class="page prev disabled">#{pagy_t('pagy.nav.prev')}</span> )) input = %(<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;">) html << %(<span class="pagy-compact-input" style="margin: 0 0.6rem;">#{pagy_t('pagy.compact', page_input: input, count: p_page, pages: p_pages)}</span> ) html << (p_next ? %(<span class="page next">#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'}</span>) : %(<span class="page next disabled">#{pagy_t('pagy.nav.next')}</span>)) html << %(</nav>#{pagy_json_tag(:compact, id, MARKER, p_page, !!defined?(TRIM))}) end
def pagy_plain_responsive_nav(pagy, id=pagy_id)
Plain responsive pagination: it returns the html with the series of links to the pages
def pagy_plain_responsive_nav(pagy, id=pagy_id) tags, link, p_prev, p_next, responsive = {}, pagy_link_proc(pagy), pagy.prev, pagy.next, pagy.responsive tags['before'] = (p_prev ? %(<span class="page prev">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'}</span> ) : %(<span class="page prev disabled">#{pagy_t('pagy.nav.prev')}</span> )) responsive[:items].each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36] tags[item.to_s] = if item.is_a?(Integer); %(<span class="page">#{link.call item}</span> ) # page link elsif item.is_a?(String) ; %(<span class="page active">#{item}</span> ) # current page elsif item == :gap ; %(<span class="page gap">#{pagy_t('pagy.nav.gap')}</span> ) # page gap end end tags['after'] = (p_next ? %(<span class="page next">#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'}</span>) : %(<span class="page next disabled">#{pagy_t('pagy.nav.next')}</span>)) script = pagy_json_tag(:responsive, id, tags, responsive[:widths], responsive[:series]) %(<nav id="#{id}" class="pagy-nav-responsive pagy-plain-responsive-nav pagination" role="navigation" aria-label="pager"></nav>#{script}) end
def pagy_prev_link(pagy, text = pagy_t('pagy.nav.prev'), link_extra = '')
def pagy_prev_link(pagy, text = pagy_t('pagy.nav.prev'), link_extra = '') pagy.prev ? %(<span class="page prev"><a href="#{pagy_prev_url(pagy)}" rel="next" aria-label="next" #{pagy.vars[:link_extra]} #{link_extra}>#{text}</a></span>) : %(<span class="page prev disabled">#{text}</span>) end
def pagy_prev_url(pagy)
def pagy_prev_url(pagy) pagy_url_for(pagy.prev, pagy) if pagy.prev end
def pagy_semantic_compact_nav(pagy, id=pagy_id)
Compact pagination for semantic: it returns the html with the series of links to the pages
def pagy_semantic_compact_nav(pagy, id=pagy_id) html, link, p_prev, p_next, p_page, p_pages = +'', pagy_link_proc(pagy, 'class="item"'), pagy.prev, pagy.next, pagy.page, pagy.pages html << %(<div id="#{id}" class="pagy-nav-compact-semantic pagy-semantic-compact-nav ui compact menu" role="navigation" aria-label="pager">) html << link.call(MARKER, '', %(style="display: none;" )) (html << link.call(1, '', %(style="display: none;" ))) if defined?(TRIM) html << (p_prev ? %(#{link.call p_prev, '<i class="left small chevron icon"></i>', 'aria-label="previous"'}) : %(<div class="item disabled"><i class="left small chevron icon"></i></div>)) input = %(<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-compact-input item">#{pagy_t('pagy.compact', page_input: input, count: p_page, pages: p_pages)}</div> ) html << (p_next ? %(#{link.call p_next, '<i class="right small chevron icon"></i>', 'aria-label="next"'}) : %(<div class="item disabled"><i class="right small chevron icon"></i></div>)) html << %(</div>#{pagy_json_tag(:compact, id, MARKER, p_page, !!defined?(TRIM))}) end
def pagy_semantic_nav(pagy)
def pagy_semantic_nav(pagy) html, link, p_prev, p_next = +'', pagy_link_proc(pagy, 'class="item"'), pagy.prev, pagy.next html << (p_prev ? %(#{link.call p_prev, '<i class="left small chevron icon"></i>', 'aria-label="previous"'}) : %(<div class="item disabled"><i class="left small chevron icon"></i></div>)) pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36] html << if item.is_a?(Integer); %(#{link.call item}) # page link elsif item.is_a?(String) ; %(<a class="item active">#{item}</a>) # current page elsif item == :gap ; %(<div class="disabled item">...</div>) # page gap end end html << (p_next ? %(#{link.call p_next, '<i class="right small chevron icon"></i>', 'aria-label="next"'}) : %(<div class="item disabled"><i class="right small chevron icon"></i></div>)) %(<div class="pagy-nav-semantic pagy-semantic-nav ui pagination menu" aria-label="pager">#{html}</div>) end
def pagy_semantic_responsive_nav(pagy, id=pagy_id)
Responsive pagination for semantic: it returns the html with the series of links to the pages
def pagy_semantic_responsive_nav(pagy, id=pagy_id) tags, link, p_prev, p_next, responsive = {}, pagy_link_proc(pagy, 'class="item"'), pagy.prev, pagy.next, pagy.responsive tags['before'] = (p_prev ? %(#{link.call p_prev, '<i class="left small chevron icon"></i>', 'aria-label="previous"'}) : %(<div class="item disabled"><i class="left small chevron icon"></i></div>)) responsive[:items].each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36] tags[item.to_s] = if item.is_a?(Integer); %(#{link.call item}) # page link elsif item.is_a?(String) ; %(<a class="item active">#{item}</a>) # current page elsif item == :gap ; %(<div class="disabled item">...</div>) # page gap end end tags['after'] = (p_next ? %(#{link.call p_next, '<i class="right small chevron icon"></i>', 'aria-label="next"'}) : %(<div class="item disabled"><i class="right small chevron icon"></i></div>)) script = pagy_json_tag(:responsive, id, tags, responsive[:widths], responsive[:series]) %(<div id="#{id}" class="pagy-nav-responsive-semantic pagy-semantic-responsive-nav ui pagination menu" role="navigation" aria-label="pager"></div>#{script}) end
def pagy_serialized(pagy)
def pagy_serialized(pagy) pagy.to_h.merge(prev_url: pagy_prev_url(pagy), next_url: pagy_next_url(pagy)) end
def pagy_t(*args)
def pagy_t(*args) ::I18n.t(*args) end
def pagy_t(path, vars={})
It is specialized for Pagy and 5x faster than I18n.t (see https://ddnexus.github.io/pagy/api/frontend#i18n)
Similar to I18n.t for streamlined interpolation and pluralization but without dynamic translation.
def pagy_t(path, vars={}) value = I18N[:data].dig(*path.split('.')) or return %(translation missing: "#{path}") if value.is_a?(Hash) vars.key?(:count) or return value plural = I18N[:plural].call(vars[:count]) value.key?(plural) or return %(invalid pluralization data: "#{path}" cannot be used with count: #{vars[:count]}; key "#{plural}" is missing.) value = value[plural] or return %(translation missing: "#{path}") end sprintf value, Hash.new{|_,k| "%{#{k}}"}.merge!(vars) # interpolation end
def pagy_trim_url(url, param_string)
def pagy_trim_url(url, param_string) url.sub(/((?:[?&])#{param_string}\z|\b(?<=[?&])#{param_string}&)/, '') end
def pagy_url_for(page, pagy)
def pagy_url_for(page, pagy) p_vars = pagy.vars; params = request.GET.merge(p_vars[:page_param].to_s => page).merge!(p_vars[:params]) "#{request.path}?#{Rack::Utils.build_nested_query(pagy_get_params(params))}#{p_vars[:anchor]}" end
def pagy_url_for_with_items(page, pagy)
def pagy_url_for_with_items(page, pagy) p_vars = pagy.vars; params = request.GET.merge(p_vars[:page_param] => page, p_vars[:items_param] => p_vars[:items]).merge!(p_vars[:params]) "#{request.path}?#{Rack::Utils.build_nested_query(pagy_get_params(params))}#{p_vars[:anchor]}" end