# Isotope (Masonry Layout)

Provides functionality to animate, filter and sort masonry layouts.

###

About the Plugin

Website GitHub npm

Isotope facilitates filterable, sortable responsive masonry-style layouts.

Our script provides a wrapper to the Isotope library, exposing the most common functions and allowing all configuration to occur in HTML via markup and data-attributes.

##### Features

- Simple masonry layout
- Multiple masonry layouts per page
- Filtering by click
- Many filter groups per collection
- Filtering by URL hash
- Sorting criteria
- Many sorter groups per collection
- Reverse sorting

###

Initializing

The demo pages already include the following code. These steps are only necessary if you are building a page from scratch. Remove these references if you are not using this plugin to improve page load times.

1. ###### Include the library in your page

   - Copy the script tag below and paste in the foot of your page. Add this where you see the other library scripts. This line should be inserted after `jquery.js` and before `theme.js`.

         <!-- Isotope (masonry layouts and filtering) -->
         <script type="text/javascript" src="assets/js/isotope.pkgd.min.js"></script>

     Alternatively you may wish to load this resource from a CDN to potentially improve page load times.

         <!-- Isotope (masonry layouts and filtering) -->
         <script type="text/javascript" src="https://unpkg.com/isotope-layout@~3.0.6"></script>

2. ###### Load the initializer code in `index.js`

   - Declare the following import statement in `js/mrare/index.js`. This ensures that the initializer code is included in the `theme.js` bundle.

         import mrIsotope from './isotope';

   - Ensure the following line appears in the `export` object:

         export {
         mrIsotope,
         };

###

Basic Usage

A basic Isotope layout requires a `<div>` with data attribute `data-isotope-collection`.

Each direct child of the `<div>` should have the `data-isotope-item` attribute to be included as part of the collection.

The Isotope plugin will handle laying out each item with best fit. Isotope items can have any width.

Any other classes may be added to the Isotope items to style them how you wish.

    <div class="col">
      <h2>Basic Example</h2>
      <div class="row" data-isotope-collection>
        <div data-isotope-item class="col-4">
          <div class="card bg-primary min-vh-10"></div>
        </div>
        <div data-isotope-item class="col-4">
          <div class="card bg-primary min-vh-30"></div>
        </div>
        <div data-isotope-item class="col-4">
          <div class="card bg-primary min-vh-20"></div>
        </div>
        <div data-isotope-item class="col-4">
          <div class="card bg-primary min-vh-20"></div>
        </div>
        <div data-isotope-item class="col-4">
          <div class="card bg-primary min-vh-30"></div>
        </div>
        <div data-isotope-item class="col-4">
          <div class="card bg-primary min-vh-10"></div>
        </div>
        <div data-isotope-item class="col-4">
          <div class="card bg-primary min-vh-20"></div>
        </div>
        <div data-isotope-item class="col-4">
          <div class="card bg-primary min-vh-10"></div>
        </div>
      </div>
    </div>

###

Layout Mode

Add `data-layout-mode` to the `data-isotope-collection` element to specify one of the built-in layout modes provided by Isotope.

See the Isotope Layout Modes documentation for more.

###

Filters

Isotope collections can be filtered to show and hide grouped items matching a selected criteria. Filter groups contain the clickable elements used to filter the collection. An Isotope collection may have many filter groups linked to it.

To create a filter group, create an element with attribute `data-isotope-filters`. This can be placed anywhere on the page, and does not need to be placed adjacent to the Isotope layout.

When using filters, the `data-isotope-collection` and `data-isotope-filters` elements must have a matching `data-isotope-id` attribute. This is what links the two elements, allowing multiple Isotope collections per page, and multiple filter groups per collection.

Any element inside the `data-isotope-filters` element with attribute `data-filter` is considered a clickable filter.

Each `data-isotope-item` element requires a `data-category` attribute to specify which filter it belongs to. It will be shown when the corresponding filter is clicked, and hidden when a non-matching filter is clicked. An item may belong to two categories, as the filter uses a wildcard selector to match filters and categories.

Use `data-filter="*"` to show all items.

This basic example shows the required heirarchy:

    <!-- First group of filters -->
    <div data-isotope-filters data-isotope-id="matching_id_1">
      <a href="#" data-filter="*">All</a>
      <a href="#" data-filter="Blue">All</a>
      <a href="#" data-filter="Pink">All</a>
      <a href="#" data-filter="Navy">All</a>
    </div>

    <!-- Isotope collection -->
    <div data-isotope-collection data-isotope-id="matching_id_1">
      <div data-isotope-item data-category="Blue">
      <div data-isotope-item data-category="Pink">
      <div data-isotope-item data-category="Navy">
      <div data-isotope-item data-category="Navy, Pink">
      <div data-isotope-item data-category="Pink, Blue">
    </div>

    <!-- Optional second group of filters linked to the same Isotope collection -->
    <div data-isotope-filters data-isotope-id="matching_id_1">
      <a href="#" data-filter="*">All</a>
      <a href="#" data-filter="Blue">All</a>
      <a href="#" data-filter="Pink">All</a>
      <a href="#" data-filter="Navy">All</a>
      <a href="#" data-filter="Navy">All</a>
    </div>

This is a full HTML example with a single filter group.

    <div class="row justify-content-center">
      <div class="col">
        <h2>Filtering</h2>
        <div class="row">
          <div class="col">
            <ul data-isotope-filters data-isotope-id="isotope_1" class="nav mb-3">
              <li class="nav-item">
                <a href="#" class="nav-link active" data-filter="*">All</a>
              </li>
              <li class="nav-item">
                <a href="#" class="nav-link" data-filter="Blue">Blue</a>
              </li>
              <li class="nav-item">
                <a href="#" class="nav-link" data-filter="Pink">Pink</a>
              </li>
              <li class="nav-item">
                <a href="#" class="nav-link" data-filter="Navy">Navy</a>
              </li>
            </ul>
          </div>
        </div>
        <div class="row" data-isotope-collection data-isotope-id="isotope_1">
          <div data-isotope-item class="col-4" data-category="Blue">
            <div class="card shadow-3d bg-primary min-vh-30"></div>
          </div>
          <div data-isotope-item class="col-4" data-category="Blue">
            <div class="card shadow-3d bg-primary min-vh-10"></div>
          </div>
          <div data-isotope-item class="col-4" data-category="Navy">
            <div class="card shadow-3d bg-primary-3 min-vh-20"></div>
          </div>
          <div data-isotope-item class="col-4" data-category="Pink">
            <div class="card shadow-3d bg-primary-2 min-vh-10"></div>
          </div>
          <div data-isotope-item class="col-4" data-category="Blue">
            <div class="card shadow-3d bg-primary min-vh-10"></div>
          </div>
          <div data-isotope-item class="col-4" data-category="Navy">
            <div class="card shadow-3d bg-primary-3 min-vh-30"></div>
          </div>
          <div data-isotope-item class="col-4" data-category="Pink">
            <div class="card shadow-3d bg-primary-2 min-vh-20"></div>
          </div>
          <div data-isotope-item class="col-4" data-category="Navy">
            <div class="card shadow-3d bg-primary-3 min-vh-20"></div>
          </div>
        </div>
      </div>
    </div>

###

Setting Default Filter

Add `data-default-filter` to the `data-isotope-collection` `<div>` with the value matching a category string.

###

Filtering By URL

Collections may be filtered by the hash in the page URL. For example, if you have an isotope collection on your page and a filter with `data-filter="pink"`, you can automatically filter to pink on page load using `#pink` in your URL like so:

This will allow you to link to particular parts of your collection from anywhere in your site.

    https://yourdomain.com/collections.html#pink

To disable this feature, add attribute `data-ignore-hash="true"` to the `data-isotope-collection` `<div>`.

###

Sorting

Isotope collections can be sorted according to set criteria. Sorting is controlled by clickable elements in a sorter group. An Isotope collection may have many sorter groups linked to it.

To create a sorter group, create an element with attribute `data-isotope-sorters`. This can be placed anywhere on the page, and does not need to be placed adjacent to the Isotope layout.

When using sorters, the `data-isotope-collection` and `data-isotope-sorters` elements must have a matching `data-isotope-id` attribute. This is what links the two elements, allowing multiple Isotope collections per page, and multiple sorter groups per collection.

Any element inside the `data-isotope-sorters` element with attribute `data-sort` and `data-sort-selector` is considered a clickable sorter.

Class `active` is applied to sorters when clicked, while being removed from all other sorters in the collection.

    <ul data-isotope-sorters data-isotope-id="projects-1">
      <li>
        <span>Example Sorters</span>
      </li>
      <li data-sort="original-order" data-sort-selector="original-order">
        <span>Original Order</span>
      </li>
      <li data-sort="sortByStarRating" data-sort-selector="[data-star-rating] parseInt" data-sort-ascending="false">
        <span>Star Rating</span>
      </li>
      <li data-sort="sortByLikes" data-sort-selector=".num-likes parseInt" data-sort-ascending="false">
        <span>Likes</span>
      </li>
    </ul>

##### Built-In Sort Methods

Isotope has two built-in sorting methods. To use these sorting methods, add the following required attributes to your button or link.

Required Attributes | Description
--- | ---
`data-sort="original-order" data-sort-selector="original-order"` | This sorts the Isotope items into the original order laid out in HTML.
`data-sort="random" data-sort-selector="random"` | Randomizes the order of the items with each click.

##### Custom Sort Methods

Isotope items can be sorted according to text or data held within the markup of each item. Custom sort methods are defined by the clickable elements in the `data-isotope-sorters` `<div>`.

Each sort method requires the following two attributes:

- A unique `id` for the sort method, defined by the `data-sort` attribute. Eg. `"sortByName"`, or `"sortByRanking"`.
- A source for the data defined by the `data-sort-selector` attribute. This selector points to an element or attribute which each Isotope item has in common.

###### Sorting data can be taken from the following sources

Source | `data-sort-selector`
--- | ---
Text of child element of Isotope items | A selector which identifies the item. Eg. `"span"` or `".likes-count"`
Text of child element of Isotope items parsed as integer | A selector which identifies the item with the addition of `parseInt` directive. Eg. `"span parseInt"` or `".likes-count parseInt"`
Text of child element of Isotope items parsed as float | A selector which identifies the item with the addition of `parseFloat` directive. Eg. `"span parseFloat"` or `".longitude parseFloat"`
Plain attribute on an Isotope item | `"[src]"`, `"[href]"`, `"[alt]"` etc.
Data attribute on Isotope item | `"[data-category]"`, `"[data-likes]"`, `"[data-index]"`, `"[data-ranking]"` etc.

Note: If you are familiar with the Isotope plugin, the `data-sort` value is used internally as each key in Isotope's `getSortData` configuration option. See documentation for more detail.

###### Examples

In the following examples, the items will be sorted in ascending order, which is the default. See Sort Ascending / Descending below.

    data-sort-selector=".name"  // Sort by text of child element with class 'name'.
    data-sort-selector=".symbol"  // Sort by text of child element with class 'symbol'.
    data-sort-selector="[data-category]" // Sort by alphabetic text of the `data-category` attribute.
    data-sort-selector=".number parseInt" // Sort by text of child element with class 'number', parsed as an integer.
    data-sort-selector=".weight parseFloat" // Sort by text of element with class 'weight', parsed as a float.

For more examples, please see the Isotope Documentation.

###

Setting Default Sort

Add `data-default-sort` to the `data-isotope-collection` `<div>` with the value containing the `data-sort` ID of your preferred default sort method.

If not specified, the default sort method will be `original-order`.

##### Example

    <div data-isotope-sorters data-isotope-id="isotope_1">
      <li data-sort="original-order" data-sort-selector="original-order">
        <span>Original Order</span>
      </li>
      <li data-sort="sortByStarRating" data-sort-selector="[data-star-rating] parseFloat" data-sort-ascending="false">
        <span>Star Rating</span>
      </li>
      <li data-sort="sortByLikes" data-sort-selector=".num-likes parseInt" data-sort-ascending="false">
        <span>Likes</span>
      </li>
    </div>
    <div class="row" data-isotope-collection data-isotope-id="isotope_1" data-default-sort="sortByLikes">
      <div data-isotope-item class="col-4" data-category="Blue" data-star-rating=-"4.5">
        <div class="card shadow-3d bg-primary min-vh-30">
          <span class="num-likes">125</span>
        </div>
      </div>
      <div data-isotope-item class="col-4" data-category="Blue" data-star-rating="3.9">
        <div class="card shadow-3d bg-primary min-vh-10">
          <span class="num-likes">98</span>
        </div>
      </div>
    </div>

###

Sort Ascending / Descending

By default, custom sort methods will sort in ascending order (from lower to higher, a-z). To reverse the sort direction, add the attribute `data-sort-ascending="false"` to your custom sort method.

TIP: To create sort options, simply create two sorting methods like so:

    <ul data-isotope-sorters data-isotope-id="projects-1">
      <li data-sort="starRatingHighLow" data-sort-selector="[data-star-rating] parseFloat" data-sort-ascending="false">
        <span>Star Rating (High to Low)</span>
      </li>
      <li data-sort="starRatingLowHigh" data-sort-selector="[data-star-rating] parseFloat">
        <span>Star Rating (Low to High)</span>
      </li>
    </ul>

###

Advanced Sorting

You may wish to sort by two criteria at the same time, such as "Date then Likes" or "Ranking then Price".

For a sorter to use two criteria, it must have the following three attributes:

- `data-sort` - ID for this sorting method.
- `data-primary-sort` - first priority.
- `data-secondary-sort` - second priority.

The value of these attributes must be sorter IDs defined in `data-sort` on other sorters in the collection.

##### Example

    <ul data-isotope-sorters data-isotope-id="projects-1">
      <li data-sort="starRatingHighLow" data-sort-selector="[data-star-rating] parseFloat" data-sort-ascending="false">
        <span>Sort By Star Rating (High to Low)</span>
      </li>
      <li data-sort="priceLowHigh" data-sort-selector="span.price parseFloat">
        <span>Sort By Price (Low to High)</span>
      </li>
      <li data-sort="ratingThenPrice" data-primary-sort="starRatingHighLow" data-secondary-sort="priceLowHigh">
        <span>Sort By Star Rating then Price</span>
      </li>
    </ul>

###

Full Example

This example shows how to use various filters, various sorters, advanced sorters, reverse "show all"

    <style>
      .active { font-weight: bold; }
      ul { list-style: none; }
      [data-isotope-filters] li, [data-isotope-sorters] li { cursor: pointer; }
      .num-likes { font-style: italic }
    </style>

    <section>
      <div class="container">
        <div class="row">
          <div class="col text-center">

            <!-- Filters 1 -->
            <ul data-isotope-filters data-isotope-id="full-example">
              <li>
                <span>Filter Group 1</span>
              </li>
              <li data-filter="*">
                <span>All</span>
              </li>
              <li data-filter="widgets">
                <span>Widgets</span>
              </li>
              <li data-filter="gadgets">
                <span>Gadgets</span>
              </li>
              <li data-filter="doosies">
                <span>Doosies</span>
              </li>
              <li data-filter="trinkets">
                <span>Trinkets</span>
              </li>
            </ul>

            <hr>

            <!-- Sorters 1 -->
            <ul data-isotope-sorters data-isotope-id="full-example">
              <li>
                <span>Sorter Group 1</span>
              </li>
              <li data-sort="original-order" data-sort-selector="original-order">
                <span>Original Order</span>
              </li>
              <li data-sort="starRating" data-sort-selector="[data-star-rating] parseInt" data-sort-ascending="false">
                <span>Star Rating</span>
              </li>
              <li data-sort="likes" data-sort-selector=".num-likes parseInt" data-sort-ascending="false">
                <span>Likes</span>
              </li>
            </ul>
          </div>
        </div>

        <hr>

        <div class="row">
          <div class="col text-center">

            <!-- Isotope Collection -->
            <div class="row" data-isotope-collection data-isotope-id="full-example" data-default-sort="starRating">
              <div class="col-3" data-isotope-item data-category="widgets" data-star-rating="3">
                <img src="https://picsum.photos/200/300/?random&0" alt="widgets,trinkets">
                <span>Widgets</span>
                <span class="star-rating">(Rating: 3)</span>
                <span class="num-likes">463</span> <span>Likes</span>
              </div>

              <div class="col-3" data-isotope-item data-category="widgets,doosies" data-star-rating="4">
                <img src="https://picsum.photos/200/300/?random&00" alt="image">
                <span>Widgets, Doosies</span>
                <span class="star-rating">(Rating: 4)</span>
                <span class="num-likes">964</span> <span>Likes</span>
              </div>

              <div class="col-3" data-isotope-item data-category="widgets" data-star-rating="8">
                <img src="https://picsum.photos/200/300/?random&1" alt="image">
                <span>Widgets</span>
                <span class="star-rating">(Rating: 8)</span>
                <span class="num-likes">367</span> <span>Likes</span>
              </div>

              <div class="col-3" data-isotope-item data-category="gadgets" data-star-rating="6">
                <img src="https://picsum.photos/200/300/?random&2" alt="image">
                <span>Gadgets</span>
                <span class="star-rating">(Rating: 6)</span>
                <span class="num-likes">27</span> <span>Likes</span>
              </div>

              <div class="col-3" data-isotope-item data-category="gadgets,doosies" data-star-rating="3">
                <img src="https://picsum.photos/200/300/?random&3" alt="image">
                <span>Gadgets, Doosies</span>
                <span class="star-rating">(Rating: 3)</span>
                <span class="num-likes">3557</span> <span>Likes</span>
              </div>

              <div class="col-3" data-isotope-item data-category="gadgets" data-star-rating="1">
                <img src="https://picsum.photos/200/300/?random&4" alt="image">
                <span>Gadgets</span>
                <span class="star-rating">(Rating: 1)</span>
                <span class="num-likes">563</span> <span>Likes</span>
              </div>

              <div class="col-3" data-isotope-item data-category="trinkets" data-star-rating="5">
                <img src="https://picsum.photos/200/300/?random&5" alt="image">
                <span>Trinkets</span>
                <span class="star-rating">(Rating: 5)</span>
                <span class="num-likes">95</span> <span>Likes</span>
              </div>

              <div class="col-3" data-isotope-item data-category="trinkets,gadgets" data-star-rating="4">
                <img src="https://picsum.photos/200/300/?random&6" alt="image">
                <span>Trinkets, Gadgets</span>
                <span class="star-rating">(Rating: 4)</span>
                <span class="num-likes">158</span> <span>Likes</span>
              </div>

              <div class="col-3" data-isotope-item data-category="doosies" data-star-rating="2">
                <img src="https://picsum.photos/200/300/?random&7" alt="image">
                <span>Doosies</span>
                <span class="star-rating">(Rating: 2)</span>
                <span class="num-likes">582</span> <span>Likes</span>
              </div>

              <div class="col-3" data-isotope-item data-category="doosies,trinkets" data-star-rating="9">
                <img src="https://picsum.photos/200/300/?random&8" alt="image">
                <span>Doosies, Trinkets</span>
                <span class="star-rating">(Rating: 9)</span>
                <span class="num-likes">113</span> <span>Likes</span>
              </div>

              <div class="col-3" data-isotope-item data-category="doosies" data-star-rating="2">
                <img src="https://picsum.photos/200/300/?random&9" alt="image">
                <span>Doosies</span>
                <span class="star-rating">(Rating: 2)</span>
                <span class="num-likes">784</span> <span>Likes</span>
              </div>

              <div class="col-3" data-isotope-item data-category="widgets" data-star-rating="8">
                <img src="https://picsum.photos/200/300/?random&10" alt="image">
                <span>Widgets</span>
                <span class="star-rating">(Rating: 8)</span>
                <span class="num-likes">35</span> <span>Likes</span>
              </div>

              <div class="col-3" data-isotope-item data-category="trinkets" data-star-rating="3">
                <img src="https://picsum.photos/200/300/?random&11" alt="image">
                <span>Trinkets</span>
                <span class="star-rating">(Rating: 3)</span>
                <span class="num-likes">10</span> <span>Likes</span>
              </div>

              <div class="col-3" data-isotope-item data-category="trinkets" data-star-rating="7">
                <img src="https://picsum.photos/200/300/?random&12" alt="image">
                <span>Trinkets</span>
                <span class="star-rating">(Rating: 7)</span>
                <span class="num-likes">2</span> <span>Likes</span>
              </div>

            </div>
            <!-- END Isotope Collection -->

          </div>
        </div>

        <div class="row">
          <div class="col text-center">

            <!-- Sorters 2 -->
            <ul data-isotope-sorters data-isotope-id="full-example">
              <li>
                <span>Sorter Group 2</span>
              </li>
              <li data-sort="original-order" data-sort-selector="original-order">
                <span>Original Order</span>
              </li>
              <li data-sort="starRating" data-sort-selector="[data-star-rating] parseInt" data-sort-ascending="false">
                <span>Star Rating</span>
              </li>
              <li data-sort="likes" data-sort-selector=".num-likes parseInt" data-sort-ascending="false">
                <span>Likes</span>
              </li>
            </ul>

            <hr>

            <!-- Filters 2 -->
            <ul data-isotope-filters data-isotope-id="full-example">
              <li>
                <span>Filter Group 2</span>
              </li>
              <li data-filter="*">
                <span>All</span>
              </li>
              <li data-filter="widgets">
                <span>Widgets</span>
              </li>
              <li data-filter="gadgets">
                <span>Gadgets</span>
              </li>
              <li data-filter="doosies">
                <span>Doosies</span>
              </li>
              <li data-filter="trinkets">
                <span>Trinkets</span>
              </li>
            </ul>
          </div>
        </div>
      </div>
    </section>