Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
ddnexus committed Feb 11, 2020
2 parents ee22c98 + f67b6ab commit 5cfc10c
Showing 24 changed files with 356 additions and 318 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# CHANGELOG

## Version 3.7.3

### Commits

- [a2b915e](http://github.com/ddnexus/pagy/commit/a2b915e): reorganization of Javascript documentation
- [fead55c](http://github.com/ddnexus/pagy/commit/fead55c): Remove duplicated pagination class for Bootstrap (#212)

## Version 3.7.2

### Changes
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -138,9 +138,9 @@ Use the official extras, or write your own in just a few lines. Extras add speci

Besides the classic pagination offered by the `pagy_nav` helpers, you can use a couple of more performant alternatives:

- [pagy_nav_js](http://ddnexus.github.io/pagy/extras/navs#javascript-navs): A faster and lighter classic looking UI, rendered on the client side with optional responsiveness:<br>![bootstrap_nav_js](docs/assets/images/bootstrap_nav_js-w.png)
- [pagy_nav_js](http://ddnexus.github.io/pagy/api/javascript#javascript-navs): A faster and lighter classic looking UI, rendered on the client side with optional responsiveness:<br>![bootstrap_nav_js](docs/assets/images/bootstrap_nav_js-w.png)

- [pagy_combo_nav_js](http://ddnexus.github.io/pagy/extras/navs#javascript-combo-navs): The fastest and lightest alternative UI _(48x faster, 48x lighter and 2,270x more efficient than Kaminari)_ that combines navigation and pagination info in a single compact element:<br>![bootstrap_combo_nav_js](docs/assets/images/bootstrap_combo_nav_js-w.png)
- [pagy_combo_nav_js](http://ddnexus.github.io/pagy/api/javascript#javascript-combo-navs): The fastest and lightest alternative UI _(48x faster, 48x lighter and 2,270x more efficient than Kaminari)_ that combines navigation and pagination info in a single compact element:<br>![bootstrap_combo_nav_js](docs/assets/images/bootstrap_combo_nav_js-w.png)

### Related Projects

3 changes: 2 additions & 1 deletion docs/_layouts/default.html
Original file line number Diff line number Diff line change
@@ -89,7 +89,7 @@ <h1 id="site-title">{{ site.title | default: site.github.repository_name }}
<gcse:search></gcse:search>
</div>

<p><small>&copy; 2017-2019 <a href="{{ site.github.owner_url }}">Domizio Demichelis</a> &mdash; <a href="https://opensource.org/licenses/MIT">MIT License</a></small></p>
<p><small>&copy; 2017-2020 <a href="{{ site.github.owner_url }}">Domizio Demichelis</a> &mdash; <a href="https://opensource.org/licenses/MIT">MIT License</a></small></p>

</div>

@@ -101,6 +101,7 @@ <h1 id="site-title">{{ site.title | default: site.github.repository_name }}
<a href="{{ site.baseurl }}/api/backend"><p class="indent1" {% if page.title == 'Pagy::Backend' %}id="active"{% endif %} >Pagy::Backend</p></a>
<a href="{{ site.baseurl }}/api/frontend"><p class="indent1" {% if page.title == 'Pagy::Frontend' %}id="active"{% endif %} >Pagy::Frontend</p></a>
<a href="{{ site.baseurl }}/api/countless"><p class="indent1" {% if page.title == 'Pagy::Countless' %}id="active"{% endif %} >Pagy::Countless</p></a>
<a href="{{ site.baseurl }}/api/javascript"><p class="indent1" {% if page.title == 'Javascript' %}id="active"{% endif %} >Javascript</p></a>
<a href="{{ site.baseurl }}/extras"><p {% if page.title == 'Extras' %}id="active"{% endif %} >Extras</p></a>
<a href="{{ site.baseurl }}/extras/arel"><p class="indent1" {% if page.title == 'Arel' %}id="active"{% endif %} >Arel</p></a>
<a href="{{ site.baseurl }}/extras/array"><p class="indent1" {% if page.title == 'Array' %}id="active"{% endif %} >Array</p></a>
10 changes: 5 additions & 5 deletions docs/api/frontend.md
Original file line number Diff line number Diff line change
@@ -94,13 +94,13 @@ This method returns a specialized proc that you call to produce the page links.

Here is how you should use it: in your helper or template call the method to get the proc (just once):

```ruby
```
link = pagy_link_proc( pagy [, extra_attributes_string ] )
```

Then call the `"link"` proc to get the links (multiple times):

```ruby
```
link.call( page_number [, text [, extra_attributes_string ] ] )
```

@@ -178,7 +178,7 @@ If you need to load different built-in locales, and/or custom dictionary files o

Here are a few examples that should cover all the possible confgurations:

```rb
```ruby
# IMPORTANT: use only one load statement
# load the "de" built-in locale:
@@ -198,7 +198,7 @@ Pagy::I18n.load({locale: 'en'},
{locale: 'es', filepath: 'path/to/pagy-es.yml'},
{locale: 'xyz', # not built-in
filepath: 'path/to/pagy-xyz.yml',
pluralize: lambda{|count| ... } )
pluralize: lambda{|count| ... }})
```

**Notice**: You should use a custom `:pluralize` proc only for pluralization types not included in the built-in [p11n.rb](https://github.com/ddnexus/pagy/blob/master/lib/locales/utils/p11n.rb)
@@ -208,7 +208,7 @@ Pagy::I18n.load({locale: 'en'},

When you configure multiple locales, you must also set the locale for each request. You usually do that in the application controller, by checking the `:locale` param. For example, in a rails app you should do something like:

```rb
```ruby
before_action { @pagy_locale = params[:locale] || 'en' }
```

295 changes: 295 additions & 0 deletions docs/api/javascript.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,295 @@
---
title: Javascript
---

# Javascript

## Overview

A few helpers use javascript, and they are clearly recognizable by the `js` suffix:

- `pagy*_nav_js`
- `pagy*_combo_nav_js`
- `pagy_items_selector_js`

If you use any of them you should follow this documentation, if not, consider that Javascript is not used anywhere else, so you can skip this.

## Usage

Load the [pagy.js](https://github.com/ddnexus/pagy/blob/master/lib/javascripts/pagy.js) file, and run `Pagy.init()` on window-load and eventually on [AJAX-load](#using-ajax).

**CAVEATS**
- If you override any `*_js` helper, ensure to override/enforce the relative javascript function, even with a simple copy and paste. If the relation between the helper and the function changes in a next release (e.g. arguments, naming, etc.), your app will still work with your own overriding even without the need to update it.
- See also [Preventing crawlers to follow look-alike links](../how-to.md#preventing-crawlers-to-follow-look-alike-links)

### Add the oj gem

Although it's not a requirement, if you are on ruby 2.0+ (not jruby), and if you use any `*_nav_js` helper, you should add the `gem 'oj'` to your Gemfile. When available, Pagy will automatically use it to boost the performance. (Notice: It does nothing for normal, non-js helpers.)

### In rails apps

#### With the asset pipeline

If your app uses the sprocket asset-pipeline, add the assets-path in the `pagy.rb` initializer:

```ruby
Rails.application.config.assets.paths << Pagy.root.join('javascripts')
```

Add the pagy javascript to the `application.js`:

```js
//= require pagy
```

Add an event listener for turbolinks:

```js
window.addEventListener("turbolinks:load", Pagy.init);
```

or a generic one if your app doesn't use turbolinks:
```js
window.addEventListener("load", Pagy.init);
```

#### With Webpacker

If your app uses Webpacker, ensure that the webpacker `erb` loader is installed:

```sh
bundle exec rails webpacker:install:erb
```

Then create a `pagy.js.erb` in order to render the content of `pagy.js` and add the event listener into it:

```erb
<%= Pagy.root.join('javascripts', 'pagy.js').read %>
window.addEventListener("load", Pagy.init)
```

and import it in `app/javascript/application.js`:

```js
import '../src/javascripts/pagy.js.erb'
```

**Notice**:

- You may want to use `turbolinks:load` if your app uses turbolinks despite webpacker
- or you may want just `export { Pagy }` from the `pagy.js.erb` file and import and use it somewhere else.
- You may want to expose the `Pagy` namespace, if you need it available elsewhere (e.g. in js.erb templates):
```js
global.Pagy = Pagy
```

### In non-rails apps

Ensure the `pagy/extras/javascripts/pagy.js` script gets served with the page.

Add an event listener like:

```js
window.addEventListener('load', Pagy.init);
```

or execute the `Pagy.init()` using jQuery:

```js
$( window ).load(function() {
Pagy.init()
});
```

# Javascript Navs

The following `pagy*_nav_js` helpers:

- `pagy_nav_js`
- `pagy_bootstrap_nav_js`
- `pagy_bulma_nav_js`
- `pagy_foundation_nav_js`
- `pagy_materialize_nav_js`
- `pagy_semantic_nav_js`

look like a normal `pagy*_nav` but have a few added features:

1. Client-side rendering
2. Optional responsiveness
3. Better performance and resource usage _(see [Maximizing Performance](../how-to.md#maximizing-performance))_

Here is a screenshot (from the `bootstrap`extra) showing responsiveness at different widths:

![bootstrap_nav_js](../assets/images/bootstrap_nav_js-g.png)

## Synopsis

See [extras](../extras.md) for general usage info.

In the `pagy.rb` initializer, require the specific extra for the style you want to use:

```ruby
# you only need one of the following extras
require 'pagy/extras/bootstrap'
require 'pagy/extras/bulma'
require 'pagy/extras/foundation'
require 'pagy/extras/materialize'
require 'pagy/extras/navs'
require 'pagy/extras/semantic'
require 'pagy/extras/uikit'
```

Use the `pagy*_nav_js` helpers in any view:

```erb
<%== pagy_nav_js(@pagy) %>
<%== pagy_bootstrap_nav_js(@pagy) %>
<%== pagy_bulma_nav_js(@pagy) %>
<%== pagy_foundation_nav_js(@pagy) %>
<%== pagy_materialize_nav_js(@pagy) %>
<%== pagy_semantic_nav_js(@pagy) %>
```

## Variables

| Variable | Description | Default |
|:---------|:------------------------------------------------------------------|:--------|
| `:steps` | Hash variable to control multipe pagy `:size` at different widths | `false` |

### :steps

The `:steps` is an optional non-core variable used by the `pagy*_nav_js` navs. If it's `false`, the `pagy*_nav_js` will behave exactly as a static `pagy*_nav` respecting the single `:size` variable, just faster and lighter. If it's defined as a hash, it allows you to control multiple pagy `:size` at different widths.

You can set the `:steps` as a hash where the keys are integers representing the widths in pixels and the values are the Pagy `:size` variables to be applied for that width.

As usual, depending on the scope of the customization, you can set the variables globally or for a single pagy instance.

For example:

```ruby
# globally
Pagy::VARS[:steps] = { 0 => [2,3,3,2], 540 => [3,5,5,3], 720 => [5,7,7,5] }
# or for a single instance
pagy, records = pagy(collection, steps: { 0 => [2,3,3,2], 540 => [3,5,5,3], 720 => [5,7,7,5] } )
# or use the :size as any static pagy*_nav
pagy, records = pagy(collection, steps: false )
```

The above statement means that from `0` to `540` pixels width, Pagy will use the `[2,3,3,2]` size, from `540` to `720` it will use the `[3,5,5,3]` size and over `720` it will use the `[5,7,7,5]` size. (Read more about the `:size` variable in the [How to control the page links](../how-to.md#controlling-the-page-links) section).

**IMPORTANT**: You can set any number of steps with any arbitrary width/size. The only requirement is that the `:steps` hash must contain always the `0` width or a `Pagy::VariableError` exception will be raised.

#### Setting the right sizes

Setting the widths and sizes can create a nice transition between widths or some apparently erratic behavior.

Here is what you should consider/ensure:

1. The pagy size changes in discrete `:steps`, defined by the width/size pairs.

2. The automatic transition from one size to another depends on the width available to the pagy nav. That width is the _internal available width_ of its container (excluding eventual horizontal padding).

3. You should ensure that - for each step - each pagy `:size` produces a nav that can be contained in its width.

4. You should ensure that the minimum internal width for the container div be equal (or a bit bigger) to the smaller positive width. (`540` pixels in our previous example).

5. If the container width snaps to specific widths in discrete steps, you should sync the quantity and widths of the pagy `:steps` to the quantity and internal widths for each discrete step of the container.

#### Javascript Caveats

In case of a window resize, the `pagy_*nav_js` elements on the page are re-rendered (when the container width changes), however if the container width changes in any other way that does not involve a window resize, then you should re-render the pagy element explicitly. For example:

```js
document.getElementById('my-pagy-nav-js').render();
```

# Javascript Combo Navs

The following `pagy*_combo_nav_js` offer an alternative pagination UI that combines navigation and pagination info in a single compact element:

- `pagy_combo_nav_js`
- `pagy_bootstrap_combo_nav_js`
- `pagy_bulma_combo_nav_js`
- `pagy_foundation_combo_nav_js`
- `pagy_materialize_combo_nav_js`
- `pagy_semantic_combo_nav_js`

They are the fastest and lighter `nav` on modern environments, recommended when you care about efficiency and server load _(see [Maximizing Performance](../how-to.md#maximizing-performance))_.

Here is a screenshot (from the `bootstrap` extra):

![bootstrap_combo_nav_js](../assets/images/bootstrap_combo_nav_js-g.png)

## Synopsis

See [extras](../extras.md) for general usage info.

In the `pagy.rb` initializer, require the specific extra for the style you want to use:

```ruby
# you only need one of the following extras
require 'pagy/extras/bootstrap'
require 'pagy/extras/bulma'
require 'pagy/extras/foundation'
require 'pagy/extras/materialize'
require 'pagy/extras/navs'
require 'pagy/extras/semantic'
require 'pagy/extras/uikit'
```

Use the `pagy*_combo_nav_js` helpers in any view:

```erb
<%== pagy_combo_nav_js(@pagy) %>
<%== pagy_bootstrap_combo_nav_js(@pagy) %>
<%== pagy_bulma_combo_nav_js(@pagy) %>
<%== pagy_foundation_combo_nav_js(@pagy) %>
<%== pagy_materialize_combo_nav_js(@pagy) %>
<%== pagy_semantic_combo_nav_js(@pagy) %>
```

## Methods

### *_nav_js(pagy, ...)

All `*_nav_js` methods can take an extra `id` argument, which is used to build the `id` attribute of the `nav` tag. Since the internal automatic id generation is based on the code line where you use the helper, you _must_ pass an explicit id if you are going to use more than one `*_js` call in the same line for the same file.

**Notice**: passing an explicit id is also a bit faster than having pagy to generate one.

# Using AJAX

If you AJAX-render any of the javascript helpers mentioned above, you should also execute `Pagy.init(container_element);` in the javascript template. Here is an example for a `pagy_bootstrap_nav_js` AJAX-render:

`pagy_remote_nav_js` controller action (notice the `link_extra` to enable AJAX):

```ruby
def pagy_remote_nav_js
@pagy, @records = pagy(Product.all, link_extra: 'data-remote="true"')
end
```

`pagy_remote_nav_js.html.erb` template for non-AJAX render (first page-load):

```erb
<div id="container">
<%= render partial: 'nav_js' %>
</div>
```

`_nav_js.html.erb` partial shared for AJAX and non-AJAX rendering:

```erb
<%== pagy_bootstrap_nav_js(@pagy) %>
```

`pagy_remote_nav_js.js.erb` javascript template used for AJAX:

```erb
$('#container').html("<%= j(render 'nav_js')%>");
Pagy.init(document.getElementById('container'));
```

**IMPORTANT**: The `document.getElementById('container')` argument will re-init the pagy elements just AJAX-rendered in the container div. If you miss it it will not work with AJAX.
122 changes: 2 additions & 120 deletions docs/extras.md
Original file line number Diff line number Diff line change
@@ -46,130 +46,12 @@ A few extras require the [pagy/extras/shared](https://github.com/ddnexus/pagy/bl

**Notice**: All the other added methods are documented in the respective extras doc.

## Javascript
## Javascript Helpers

A few helpers use javascript, and they are clearly recognizable by the `js` suffix:

- `pagy*_nav_js`
- `pagy*_combo_nav_js`
- `pagy_items_selector_js`

If you use any of them you should load the [pagy.js](https://github.com/ddnexus/pagy/blob/master/lib/javascripts/pagy.js) file, and run `Pagy.init()` on window load and eventually on [AJAX-load](#using-ajax-with-javascript-enabled-helpers).

**CAVEATS**
- If you override any `*_js` helper, ensure to override/enforce the relative javascript function, even with a simple copy and paste. If the relation between the helper and the function changes in a next release (e.g. arguments, naming, etc.), your app will still work with your own overriding even without the need to update it.
- See also [Preventing crawlers to follow look-alike links](how-to.md#preventing-crawlers-to-follow-look-alike-links)

### Add the oj gem

Although it's not a requirement, if you are on ruby 2.0+ (not jruby), and if you use any `*_nav_js` helper, you should add the `gem 'oj'` to your Gemfile. When available, Pagy will automatically use it to boost the performance. (Notice: It does nothing for normal, non-js helpers.)

### In rails apps

#### With the asset pipeline

If your app uses the sprocket asset-pipeline, add the assets-path in the `pagy.rb` initializer:

```ruby
Rails.application.config.assets.paths << Pagy.root.join('javascripts')
```

Add the pagy javascript to the `application.js`:

```js
//= require pagy
```

Add an event listener for turbolinks:

```js
window.addEventListener("turbolinks:load", Pagy.init);
```

or a generic one if your app doesn't use turbolinks:
```js
window.addEventListener("load", Pagy.init);
```

#### With Webpacker

If your app uses Webpacker, ensure that the webpacker `erb` loader is installed:

```sh
bundle exec rails webpacker:install:erb
```

Then create a `pagy.js.erb` in order to render the content of `pagy.js` and add the event listener into it:

```erb
<%= Pagy.root.join('javascripts', 'pagy.js').read %>
window.addEventListener("load", Pagy.init)
```

and import it in `app/javascript/application.js`:

```js
import '../src/javascripts/pagy.js.erb'
```

**Notice**:

- You may want to use `turbolinks:load` if your app uses turbolinks despite webpacker
- or you may want just `export { Pagy }` from the `pagy.js.erb` file and import and use it somewhere else.
- You may want to expose the `Pagy` namespace, if you need it available elsewhere (e.g. in js.erb templates):
```js
global.Pagy = Pagy
```

### In non-rails apps

Ensure the `pagy/extras/javascripts/pagy.js` script gets served with the page.

Add an event listener like:

```js
window.addEventListener('load', Pagy.init);
```

or execute the `Pagy.init()` using jQuery:

```js
$( window ).load(function() {
Pagy.init()
});
```

### Using AJAX with javascript-enabled helpers

If you AJAX-render any of the javascript helpers mentioned above, you should also execute `Pagy.init(container_element);` in the javascript template. Here is an example for a `pagy_bootstrap_nav_js` AJAX-render:

`pagy_remote_nav_js` controller action (notice the `link_extra` to enable AJAX):

```ruby
def pagy_remote_nav_js
@pagy, @records = pagy(Product.all, link_extra: 'data-remote="true"')
end
```

`pagy_remote_nav_js.html.erb` template for non-AJAX render (first page-load):

```erb
<div id="container">
<%= render partial: 'nav_js' %>
</div>
```

`_nav_js.html.erb` partial shared for AJAX and non-AJAX rendering:

```erb
<%== pagy_bootstrap_nav_js(@pagy) %>
```

`pagy_remote_nav_js.js.erb` javascript template used for AJAX:

```erb
$('#container').html("<%= j(render 'nav_js')%>");
Pagy.init(document.getElementById('container'));
```

Notice the `document.getElementById('container')` argument: that will re-init the pagy elements just AJAX-rendered in the container div.
See [Javascript](api/javascript.md)
14 changes: 4 additions & 10 deletions docs/extras/bootstrap.md
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@ or with a template:
<%== render partial: 'pagy/bootstrap_nav', locals: {pagy: @pagy} %>
```

Configure [javascript](../extras.md#javascript) if you use `pagy_bootstrap_nav_js` or `pagy_bootstrap_combo_nav_js`.
See [Javascript](../api/javascript.md) if you use `pagy_bootstrap_nav_js` or `pagy_bootstrap_combo_nav_js`.

## Files

@@ -52,17 +52,11 @@ The `bootstrap_nav.*` templates produce the same output, and can be used as an e

### pagy_bootstrap_nav_js(pagy, ...)

This method is the same as the `pagy_nav_js`, but customized for the Bootstrap framework.

See more details in the [javascript navs](navs.md#javascript-navs) documentation.

See the [Javascript Navs](../api/javascript.md#javascript-navs) documentation.

### pagy_bootstrap_combo_nav_js(pagy, ...)

This method is the same as the `pagy_combo_nav_js`, but customized for the Bootstrap framework.

Here is an example:

![bootstrap_combo_nav_js](../assets/images/bootstrap_combo_nav_js-g.png)

See more details in the [javascript compact navs](navs.md#javascript-combo-navs) documentation.
See the [Javascript Combo Navs](../api/javascript.md#javascript-combo-navs) documentation.

12 changes: 3 additions & 9 deletions docs/extras/bulma.md
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@ or with a template:
<%== render partial: 'pagy/bulma_nav', locals: {pagy: @pagy} %>
```

Configure [javascript](../extras.md#javascript) if you use `pagy_bulma_nav_js` or `pagy_bulma_combo_nav_js`.
See [Javascript](../api/javascript.md) if you use `pagy_bulma_nav_js` or `pagy_bulma_combo_nav_js`.

## Files

@@ -51,16 +51,10 @@ The `bulma_nav.*` templates produce the same output, and can be used as an easie

### pagy_bulma_nav_js(pagy, ...)

This method is the same as the `pagy_nav_js`, but customized for the Bulma CSS framework.

See more details in the [javascript navs](navs.md#javascript-navs) documentation.
See the [Javascript Navs](../api/javascript.md#javascript-navs) documentation.

### pagy_bulma_combo_nav_js(pagy, ...)

This method is the same as the `pagy_combo_nav_js`, but customized for the Bulma CSS framework.

Here is an example:

![bulma_combo_nav_js](../assets/images/bulma_combo_nav_js-g.png)

See more details in the [compact_navs_js](navs.md#javascript-combo-navs) documentation.
See the [Javascript Combo Navs](../api/javascript.md#javascript-combo-navs) documentation.
10 changes: 3 additions & 7 deletions docs/extras/foundation.md
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@ or with a template:
<%== render partial: 'pagy/foundation_nav', locals: {pagy: @pagy} %>
```

Configure [javascript](../extras.md#javascript) if you use `pagy_foundation_nav_js` or `pagy_foundation_combo_nav_js`.
See [Javascript](../api/javascript.md) if you use `pagy_foundation_nav_js` or `pagy_foundation_combo_nav_js`.

## Files

@@ -51,12 +51,8 @@ The `foundation_nav.*` templates produce the same output, and can be used as an

### pagy_foundation_nav_js(pagy, ...)

This method is the same as the `pagy_nav_js`, but customized for the Foundation framework.

See more details in the [javascript navs](navs.md#javascript-navs) documentation.
See the [Javascript Navs](../api/javascript.md#javascript-navs) documentation.

### pagy_foundation_combo_nav_js(pagy, ...)

This method is the same as the `pagy_combo_nav_js`, but customized for the Foundation framework.

See more details in the [compact_navs_js](navs.md#javascript-combo-navs) documentation.
See the [Javascript Combo Navs](../api/javascript.md#javascript-combo-navs) documentation.
2 changes: 1 addition & 1 deletion docs/extras/items.md
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ Pagy::VARS[:items_param] = :custom_param # default :items
Pagy::VARS[:max_items] = 100 # default
```

Configure [javascript](../extras.md#javascript) (only if you use the `pagy_items_selector_js` UI)
See [Javascript](../api/javascript.md) (only if you use the `pagy_items_selector_js` UI)

## Files

12 changes: 3 additions & 9 deletions docs/extras/materialize.md
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ with a fast helper:
<%== pagy_materialize_combo_nav_js(@pagy) %>
```

Configure [javascript](../extras.md#javascript) if you use `pagy_materialize_nav_js` or `pagy_materialize_combo_nav_js`.
See [Javascript](../api/javascript.md) if you use `pagy_materialize_nav_js` or `pagy_materialize_combo_nav_js`.

## Files

@@ -40,16 +40,10 @@ This method is the same as the `pagy_nav`, but customized for Materialize.

### pagy_materialize_nav_js(pagy, ...)

This method is the same as the `pagy_nav_js`, but customized for the Materialize CSS framework.

See more details in the [javascript navs](navs.md#javascript-navs) documentation.
See the [Javascript Navs](../api/javascript.md#javascript-navs) documentation.

### pagy_materialize_combo_nav_js(pagy, ...)

This method is the same as the `pagy_combo_nav_js`, but customized for the Materialize CSS framework.

Here is an example:

![materialize_combo_nav_js](../assets/images/materialize_combo_nav_js-g.png)

See more details in the [compact_navs_js](navs.md#javascript-combo-navs) documentation.
See the [Javascript Combo Navs](../api/javascript.md#javascript-combo-navs) documentation.
132 changes: 8 additions & 124 deletions docs/extras/navs.md
Original file line number Diff line number Diff line change
@@ -17,142 +17,26 @@ In the `pagy.rb` initializer:
require 'pagy/extras/navs'
```

Configure [javascript](../extras.md#javascript).

## Files

- [navs.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/navs.rb)

# Javascript Navs

The `pagy*_nav_js` (implemented by this extra or by other frontend extras) looks like a normal `*_nav` but has a a few added features:

1. It is rendered on the client side
2. It offers optional responsiveness
3. It is faster and lighter than a simple `pagy*_nav` helper _(see [Maximizing Performance](../how-to.md#maximizing-performance))_

Here is a screenshot (from the `bootstrap`extra) showing responsiveness at different widths:

![bootstrap_nav_js](../assets/images/bootstrap_nav_js-g.png)

## Synopsis

Use the `pagy*_nav_js` helpers in any view:
Render the navigation links in some view...
with a fast helper:

```erb
<%== pagy_nav_js(@pagy) %>
<%== pagy_combo_nav_js(@pagy) %>
```

Other extras provide also the following framework-styled helpers:

```erb
<%== pagy_bootstrap_nav_js(@pagy) %>
<%== pagy_bulma_nav_js(@pagy) %>
<%== pagy_foundation_nav_js(@pagy) %>
<%== pagy_materialize_nav_js(@pagy) %>
<%== pagy_semantic_nav_js(@pagy) %>
```

## Variables

| Variable | Description | Default |
|:---------|:------------------------------------------------------------------|:--------|
| `:steps` | Hash variable to control multipe pagy `:size` at different widths | `false` |

### :steps

The `:steps` is an optional non-core variable used by the `pagy*_nav_js` navs. If it's `false`, the `pagy*_nav_js` will behave exactly as a static `pagy*_nav` respecting the single `:size` variable, just faster and lighter. If it's defined as a hash, it allows you to control multiple pagy `:size` at different widths.

You can set the `:steps` as a hash where the keys are integers representing the widths in pixels and the values are the Pagy `:size` variables to be applied for that width.

As usual, depending on the scope of the customization, you can set the variables globally or for a single pagy instance.

For example:

```ruby
# globally
Pagy::VARS[:steps] = { 0 => [2,3,3,2], 540 => [3,5,5,3], 720 => [5,7,7,5] }

# or for a single instance
pagy, records = pagy(collection, steps: { 0 => [2,3,3,2], 540 => [3,5,5,3], 720 => [5,7,7,5] } )

# or use the :size as any static pagy*_nav
pagy, records = pagy(collection, steps: false )

```

The above statement means that from `0` to `540` pixels width, Pagy will use the `[2,3,3,2]` size, from `540` to `720` it will use the `[3,5,5,3]` size and over `720` it will use the `[5,7,7,5]` size. (Read more about the `:size` variable in the [How to control the page links](../how-to.md#controlling-the-page-links) section).

**IMPORTANT**: You can set any number of steps with any arbitrary width/size. The only requirement is that the `:steps` hash must contain always the `0` width or a `Pagy::VariableError` exception will be raised.

#### Setting the right sizes

Setting the widths and sizes can create a nice transition between widths or some apparently erratic behavior.
See [Javascript](../api/javascript.md).

Here is what you should consider/ensure:

1. The pagy size changes in discrete `:steps`, defined by the width/size pairs.

2. The automatic transition from one size to another depends on the width available to the pagy nav. That width is the _internal available width_ of its container (excluding eventual horizontal padding).

3. You should ensure that - for each step - each pagy `:size` produces a nav that can be contained in its width.

4. You should ensure that the minimum internal width for the container div be equal (or a bit bigger) to the smaller positive width. (`540` pixels in our previous example).

5. If the container width snaps to specific widths in discrete steps, you should sync the quantity and widths of the pagy `:steps` to the quantity and internal widths for each discrete step of the container.

#### Javascript Caveats

In case of a window resize, the `pagy_*nav_js` elements on the page are re-rendered (when the container width changes), however if the container width changes in any other way that does not involve a window resize, then you should re-render the pagy element explicitly. For example:
## Files

```js
document.getElementById('my-pagy-nav-js').render();
```
- [navs.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/navs.rb)

## Methods

### pagy_nav_js(pagy, ...)

Similar to the `pagy_nav` helper, but faster and rendered on the client side, with added responsiveness.

It can take an extra `id` argument, which is used to build the `id` attribute of the `nav` tag. Since the internal automatic id generation is based on the code line where you use the helper, you _must_ pass an explicit id if you are going to use more than one `*_js` call in the same line for the same file.

**Notice**: passing an explicit id is also a bit faster than having pagy to generate one.

# Javascript Combo Navs

The `pagy*_combo_nav_js` (implemented by this extra or by other frontend extras) offers an alternative pagination UI that combines navigation and pagination info in a single compact element.

It is the fastest and lighter `nav` on modern environments, recommended when you care about efficiency and server load _(see [Maximizing Performance](../how-to.md#maximizing-performance))_.

Here is a screenshot (from the `bootstrap` extra):

![bootstrap_combo_nav_js](../assets/images/bootstrap_combo_nav_js-g.png)

## Synopsis

Use the `pagy*_combo_nav_js helpers in any view:

```erb
<%== pagy_combo_nav_js(@pagy) %>
```

Other extras provide also the following framework-styled helpers:

```erb
<%== pagy_bootstrap_combo_nav_js(@pagy) %>
<%== pagy_bulma_combo_nav_js(@pagy) %>
<%== pagy_foundation_combo_nav_js(@pagy) %>
<%== pagy_materialize_combo_nav_js(@pagy) %>
<%== pagy_semantic_combo_nav_js(@pagy) %>
```

## Methods
See the [Javascript Navs](../api/javascript.md#javascript-navs) documentation.

### pagy_combo_nav_js(pagy, ...)

Renders a javascript-powered compact navigation helper.

It can take an extra `id` argument, which is used to build the `id` attribute of the `nav` tag. Since the internal automatic id generation is based on the code line where you use the helper, you _must_ pass an explicit id if you are going to use more than one `*_js` call in the same line for the same page.

**Notice**: passing an explicit id is also a bit faster than having pagy to generate one.
See the [Javascript Combo Navs](../api/javascript.md#javascript-combo-navs) documentation.
8 changes: 2 additions & 6 deletions docs/extras/semantic.md
Original file line number Diff line number Diff line change
@@ -38,12 +38,8 @@ This method is the same as the `pagy_nav`, but customized for Semantic UI.

### pagy_semantic_nav_js(pagy, ...)

This method is the same as the `pagy_nav_js`, but customized for the Semantic UI framework.

See more details in the [javascript navs](navs.md#javascript-navs) documentation.
See the [Javascript Navs](../api/javascript.md#javascript-navs) documentation.

### pagy_semantic_combo_nav_js(pagy, ...)

This method is the same as the `pagy_combo_nav_js`, but customized for the Semantic UI framework.

See more details in the [compact_navs_js](navs.md#javascript-combo-navs) documentation.
See the [Javascript Combo Navs](../api/javascript.md#javascript-combo-navs) documentation.
9 changes: 2 additions & 7 deletions docs/extras/uikit.md
Original file line number Diff line number Diff line change
@@ -48,17 +48,12 @@ The `uikit_nav.*` templates produce the same output, and can be used as an easie

### pagy_uikit_nav_js(pagy, ...)

This method is the same as the `pagy_nav_js`, but customized for the UIkit framework.

See more details in the [javascript navs](navs.md#javascript-navs) documentation.

See the [Javascript Navs](../api/javascript.md#javascript-navs) documentation

### pagy_uikit_combo_nav_js(pagy, ...)

This method is the same as the `pagy_combo_nav_js`, but customized for the UIkit framework.
See the [Javascript Combo Navs](../api/javascript.md#javascript-combo-navs) documentation.

Here is an example:

![uikit_combo_nav_js](../assets/images/uikit_combo_nav_js-g.png)

See more details in the [javascript compact navs](navs.md#javascript-combo-navs) documentation.
2 changes: 1 addition & 1 deletion docs/how-to.md
Original file line number Diff line number Diff line change
@@ -531,7 +531,7 @@ Here are some tips that will help chosing the best way to use Pagy, depending on
If you need the classic pagination bar with links and info, then you have a couple of choices, depending on your environment:
- If you are on ruby 2.0+, add the `oj` gem to your gemfile and use any `pagy*_nav_js` helper _(see [Javascript Navs](extras/navs.md#javascript-navs))_. That uses client side rendering and it is faster and lighter than using any `pagy*_nav` helper _(40x faster, 36x lighter and 1,410x more efficient than Kaminari)_. _Notice: the `oj` gem is not a requirement but helps the performance when it is available._
- If you are on ruby 2.0+, add the `oj` gem to your gemfile and use any `pagy*_nav_js` helper _(see [Javascript](api/javascript.md))_. That uses client side rendering and it is faster and lighter than using any `pagy*_nav` helper _(40x faster, 36x lighter and 1,410x more efficient than Kaminari)_. _Notice: the `oj` gem is not a requirement but helps the performance when it is available._
- If you are on jruby (any version) or ruby 1.9.x, or you cannot install `oj` then use the `pagy*_nav` helper, which will give you the same performance of pagy v2.0 (33x faster; 26x lighter; 850x more efficient than Kaminari)
### Consider the combo navs
2 changes: 1 addition & 1 deletion lib/config/pagy.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# encoding: utf-8
# frozen_string_literal: true

# Pagy initializer file (3.7.2)
# Pagy initializer file (3.7.3)
# Customize only what you really need and notice that Pagy works also without any of the following lines.
# Should you just cherry pick part of this file, please maintain the require-order of the extras

2 changes: 1 addition & 1 deletion lib/javascripts/pagy.js
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@

function Pagy(){}

Pagy.version = '3.7.2';
Pagy.version = '3.7.3';

Pagy.init = function(arg){
var target = arg instanceof Event || arg === undefined ? document : arg,
2 changes: 1 addition & 1 deletion lib/pagy.rb
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@

require 'pathname'

class Pagy ; VERSION = '3.7.2'
class Pagy ; VERSION = '3.7.3'

# Root pathname to get the path of Pagy files like templates or dictionaries
def self.root; @root ||= Pathname.new(__FILE__).dirname.freeze end
4 changes: 2 additions & 2 deletions lib/pagy/extras/bootstrap.rb
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@ def pagy_bootstrap_nav(pagy)
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 pagination" role="navigation" aria-label="pager"><ul class="pagination">#{html}</ul></nav>)
%(<nav class="pagy-bootstrap-nav" role="navigation" aria-label="pager"><ul class="pagination">#{html}</ul></nav>)
end

# Javascript pagination for bootstrap: it returns a nav and a JSON tag used by the Pagy.nav javascript
@@ -34,7 +34,7 @@ def pagy_bootstrap_nav_js(pagy, id=pagy_id)
'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 pagination" role="navigation" aria-label="pager"></nav>#{pagy_json_tag(:nav, id, tags, pagy.sequels, defined?(TRIM) && pagy.vars[:page_param])})
%(<nav id="#{id}" class="pagy-bootstrap-nav-js" role="navigation" aria-label="pager"></nav>#{pagy_json_tag(:nav, id, tags, pagy.sequels, defined?(TRIM) && pagy.vars[:page_param])})
end

# Javascript combo pagination for bootstrap: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
2 changes: 1 addition & 1 deletion lib/templates/bootstrap_nav.html.erb
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
Usage: link.call( page_number [, text [, extra_attributes_string ]])
-%>
<% link = pagy_link_proc(pagy, 'class="page-link"') -%>
<%# -%><nav aria-label="pager" class="pagy-bootstrap-nav pagination" role="navigation">
<%# -%><nav aria-label="pager" class="pagy-bootstrap-nav" role="navigation">
<%# -%> <ul class="pagination">
<% if pagy.prev -%> <li class="page-item prev"><%== link.call(pagy.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>
2 changes: 1 addition & 1 deletion lib/templates/bootstrap_nav.html.haml
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
- link = pagy_link_proc(pagy, 'class="page-link"')

%nav.pagy-bootstrap-nav.pagination{"aria-label" => "pager", :role => "navigation"}
%nav.pagy-bootstrap-nav{"aria-label" => "pager", :role => "navigation"}
%ul.pagination
2 changes: 1 addition & 1 deletion lib/templates/bootstrap_nav.html.slim
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
- link = pagy_link_proc(pagy, 'class="page-link"')

nav.pagy-bootstrap-nav.pagination role="navigation" aria-label="pager"
nav.pagy-bootstrap-nav role="navigation" aria-label="pager"

ul.pagination

14 changes: 7 additions & 7 deletions test/pagy/extras/bootstrap_test.rb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion test/pagy/extras/trim_test.rb
Original file line number Diff line number Diff line change
@@ -71,7 +71,7 @@
it 'renders first page' do
pagy = Pagy.new(count: 103, page: 1)
_(view.pagy_nav_js(pagy, pagy_test_id)).must_equal "<nav id=\"test-id\" class=\"pagy-nav-js pagination\" role=\"navigation\" aria-label=\"pager\"></nav><script type=\"application/json\" class=\"pagy-json\">[\"nav\",\"test-id\",{\"before\":\"<span class=\\\"page prev disabled\\\">&lsaquo;&nbsp;Prev</span> \",\"link\":\"<span class=\\\"page\\\"><a href=\\\"/foo?page=__pagy_page__\\\" >__pagy_page__</a></span> \",\"active\":\"<span class=\\\"page active\\\">1</span> \",\"gap\":\"<span class=\\\"page gap\\\">&hellip;</span> \",\"after\":\"<span class=\\\"page next\\\"><a href=\\\"/foo?page=2\\\" rel=\\\"next\\\" aria-label=\\\"next\\\">Next&nbsp;&rsaquo;</a></span>\"},{\"0\":[\"1\",2,3,4,5,6]},\"page\"]</script>"
_(view.pagy_bootstrap_nav_js(pagy, pagy_test_id)).must_equal "<nav id=\"test-id\" class=\"pagy-bootstrap-nav-js pagination\" role=\"navigation\" aria-label=\"pager\"></nav><script type=\"application/json\" class=\"pagy-json\">[\"nav\",\"test-id\",{\"before\":\"<ul class=\\\"pagination\\\"><li class=\\\"page-item prev disabled\\\"><a href=\\\"#\\\" class=\\\"page-link\\\">&lsaquo;&nbsp;Prev</a></li>\",\"link\":\"<li class=\\\"page-item\\\"><a href=\\\"/foo?page=__pagy_page__\\\" class=\\\"page-link\\\" >__pagy_page__</a></li>\",\"active\":\"<li class=\\\"page-item active\\\"><a href=\\\"/foo?page=__pagy_page__\\\" class=\\\"page-link\\\" >__pagy_page__</a></li>\",\"gap\":\"<li class=\\\"page-item gap disabled\\\"><a href=\\\"#\\\" class=\\\"page-link\\\">&hellip;</a></li>\",\"after\":\"<li class=\\\"page-item next\\\"><a href=\\\"/foo?page=2\\\" class=\\\"page-link\\\" rel=\\\"next\\\" aria-label=\\\"next\\\">Next&nbsp;&rsaquo;</a></li></ul>\"},{\"0\":[\"1\",2,3,4,5,6]},\"page\"]</script>"
_(view.pagy_bootstrap_nav_js(pagy, pagy_test_id)).must_equal "<nav id=\"test-id\" class=\"pagy-bootstrap-nav-js\" role=\"navigation\" aria-label=\"pager\"></nav><script type=\"application/json\" class=\"pagy-json\">[\"nav\",\"test-id\",{\"before\":\"<ul class=\\\"pagination\\\"><li class=\\\"page-item prev disabled\\\"><a href=\\\"#\\\" class=\\\"page-link\\\">&lsaquo;&nbsp;Prev</a></li>\",\"link\":\"<li class=\\\"page-item\\\"><a href=\\\"/foo?page=__pagy_page__\\\" class=\\\"page-link\\\" >__pagy_page__</a></li>\",\"active\":\"<li class=\\\"page-item active\\\"><a href=\\\"/foo?page=__pagy_page__\\\" class=\\\"page-link\\\" >__pagy_page__</a></li>\",\"gap\":\"<li class=\\\"page-item gap disabled\\\"><a href=\\\"#\\\" class=\\\"page-link\\\">&hellip;</a></li>\",\"after\":\"<li class=\\\"page-item next\\\"><a href=\\\"/foo?page=2\\\" class=\\\"page-link\\\" rel=\\\"next\\\" aria-label=\\\"next\\\">Next&nbsp;&rsaquo;</a></li></ul>\"},{\"0\":[\"1\",2,3,4,5,6]},\"page\"]</script>"
_(view.pagy_bulma_nav_js(pagy, pagy_test_id)).must_equal "<nav id=\"test-id\" class=\"pagy-bulma-nav-js pagination is-centered\" role=\"navigation\" aria-label=\"pagination\"></nav><script type=\"application/json\" class=\"pagy-json\">[\"nav\",\"test-id\",{\"before\":\"<a class=\\\"pagination-previous\\\" disabled>&lsaquo;&nbsp;Prev</a><a href=\\\"/foo?page=2\\\" rel=\\\"next\\\" class=\\\"pagination-next\\\" aria-label=\\\"next page\\\">Next&nbsp;&rsaquo;</a><ul class=\\\"pagination-list\\\">\",\"link\":\"<li><a href=\\\"/foo?page=__pagy_page__\\\" class=\\\"pagination-link\\\" aria-label=\\\"goto page __pagy_page__\\\">__pagy_page__</a></li>\",\"active\":\"<li><a href=\\\"/foo?page=__pagy_page__\\\" class=\\\"pagination-link is-current\\\" aria-current=\\\"page\\\" aria-label=\\\"page __pagy_page__\\\">__pagy_page__</a></li>\",\"gap\":\"<li><span class=\\\"pagination-ellipsis\\\">&hellip;</span></li>\",\"after\":\"</ul>\"},{\"0\":[\"1\",2,3,4,5,6]},\"page\"]</script>"
_(view.pagy_foundation_nav_js(pagy, pagy_test_id)).must_equal "<nav id=\"test-id\" class=\"pagy-foundation-nav-js\" role=\"navigation\" aria-label=\"Pagination\"></nav><script type=\"application/json\" class=\"pagy-json\">[\"nav\",\"test-id\",{\"before\":\"<ul class=\\\"pagination\\\"><li class=\\\"prev disabled\\\">&lsaquo;&nbsp;Prev</li>\",\"link\":\"<li><a href=\\\"/foo?page=__pagy_page__\\\" >__pagy_page__</a></li>\",\"active\":\"<li class=\\\"current\\\">1</li>\",\"gap\":\"<li class=\\\"ellipsis gap\\\" aria-hidden=\\\"true\\\"></li>\",\"after\":\"<li class=\\\"next\\\"><a href=\\\"/foo?page=2\\\" rel=\\\"next\\\" aria-label=\\\"next\\\">Next&nbsp;&rsaquo;</a></li></ul>\"},{\"0\":[\"1\",2,3,4,5,6]},\"page\"]</script>"
_(view.pagy_materialize_nav_js(pagy, pagy_test_id)).must_equal "<div id=\"test-id\" class=\"pagy-materialize-nav-js\" role=\"navigation\" aria-label=\"pager\"></div><script type=\"application/json\" class=\"pagy-json\">[\"nav\",\"test-id\",{\"before\":\"<ul class=\\\"pagination\\\"><li class=\\\"prev disabled\\\"><a href=\\\"#\\\"><i class=\\\"material-icons\\\">chevron_left</i></a></li>\",\"link\":\"<li class=\\\"waves-effect\\\"><a href=\\\"/foo?page=__pagy_page__\\\" >__pagy_page__</a></li>\",\"active\":\"<li class=\\\"active\\\"><a href=\\\"/foo?page=__pagy_page__\\\" >__pagy_page__</a></li>\",\"gap\":\"<li class=\\\"gap disabled\\\"><a href=\\\"#\\\">&hellip;</a></li>\",\"after\":\"<li class=\\\"waves-effect next\\\"><a href=\\\"/foo?page=2\\\" rel=\\\"next\\\" aria-label=\\\"next\\\"><i class=\\\"material-icons\\\">chevron_right</i></a></li></ul>\"},{\"0\":[\"1\",2,3,4,5,6]},\"page\"]</script>"

0 comments on commit 5cfc10c

Please sign in to comment.