Skip to content

Commit

Permalink
reorganization of Javascript documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
ddnexus committed Feb 11, 2020
1 parent fead55c commit a2b915e
Show file tree
Hide file tree
Showing 14 changed files with 333 additions and 302 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
3 changes: 2 additions & 1 deletion docs/_layouts/default.html
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand All @@ -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>
Expand Down
10 changes: 5 additions & 5 deletions docs/api/frontend.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 ] ] )
```

Expand Down Expand Up @@ -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:
Expand All @@ -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)
Expand All @@ -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' }
```

Expand Down
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.
Loading

0 comments on commit a2b915e

Please sign in to comment.