alpinesmuseum-public/assets/js/lib/magnet/README.md

25 KiB

Magnet

Magnet is a Vanilla JavaScript library and a jQuery plugin to create gapless, filterable and sortable layouts.

Getting Started

An overview of Magnet, including folder structure, how to download and use it, examples and more.

What's Included

Every downloaded copy of Magnet is compressed. Once downloaded, unzip the compressed folder to get a structure like this:

magnet/
├── js/
│   ├── magnet.js
│   └── magnet.min.js
└── README.md
  • magnet.js for development.
  • magnet.min.js for production.

Installation

Download

Copy magnet.js or magnet.min.js to your project, then include it in your site.

<script src="/path/to/magnet.min.js"></script>

HTML

Magnet works on a container element with a group of child items. This items are selected by a class.

<div class="grid">
  <div class="grid-item">
  <div class="grid-item grid-item--width2">
  <div class="grid-item">
  ...
  <div class="grid-item">
</div>

CSS

Item style is handled by your own CSS.

.grid-item { width: 25%; }
.grid-item--width2 { width: 50%; }

Initialization

jQuery

Initialize Magnet as a jQuery plugin.

//No options
$('.grid').magnet();

//With options
$('.grid').magnet({
  itemSelector: '.grid-item',
  layoutMode: 'grid'
});

Bind plugin initialization to a jQuery event to ensure all items have finished loading, if the script is included within <head>.

//Document is ready
$(document).ready(function() {
  $('.grid').magnet();
});

//Images have finished loading.
//Wait until images loading is complete to get their correct size.
//You can use any other method to detect completion, 
//then initialize the plugin. 
$(window).load(function() {
  $('.grid').magnet();
});
JavaScript

Initialize the plugin with Vanilla JavaScript. Magnet constructor accepts two arguments: container element and options object.

var elem = document.querySelector('.grid');
var mgnt = new Magnet(elem, {
  itemSelector: '.grid-item'
});

Filter

Magnet uses filtering to show or hide items. Items matching a filter will be shown, otherwise will be hidden.

HTML

Items are filtered using selectors or functions. Using selectors, like classes, is the easiest way to filter items. Each item can have several classes to be identified:

<div class="grid">
  <div class="grid-item nonmetal">
  <div class="grid-item noble-gas">
  <div class="grid-item alkali metal">
  <div class="grid-item alkaline-earth metal">
  <div class="grid-item metalloid">
  ...
  <div class="grid-item transition metal">
</div>

Additionally, you can use any element to filter items with the data attribute. In this case, <button> and data-filter:

<div class="button-group filter-group">
  <button data-filter="*">All</button>
  <button data-filter=".nonmetal">Nonmetals</button>
  <button data-filter=".noble-gas">Noble Gases</button>
  <button data-filter=".metal">Metals</button>
  <button data-filter=".alkali.metal">Alkali Metals</button>
  <button data-filter=".metalloid">Metalloids</button>
</div>

jQuery

Set a selector with the filter option. Items matching a filter will be shown, otherwise will be hidden.

//Filter metal items
$('.grid').magnet({filter: '.metal'});

//Filter nonmetal or noble gas items
$('.grid').magnet({filter: '.nonmetal, .noble-gas'});

//Filter alkali and metal items
$('.grid').magnet({filter: '.alkali.metal'});

//Show all items
$('.grid').magnet({filter: '*'});

To filter items when a button is clicked, use the value in data-filter attribute for the filter option.

//Filter items on button click
$('.filter-group').click(function() {
  var filter = $(this).data('filter');
  $('.grid').magnet({filter: filter});
});

Items can be filtered using a function. The function requires a parameter elem, which is the item element selector, and must return the data.

$('.grid').magnet({
  filter: function(elem) {
    //Get text from .symbol element
    var symbol = $(elem).find('.symbol').text();
    //Return elements with one character symbol
    return symbol.match(/^[A-Z]$/);
  }
});

Sort

Magnet can change the order of items based on their data.

HTML

Items can be ordered using several values, obtained from data attributes or elements:

<div class="grid">
  <div class="grid-item nonmetal" data-category="nonmetal">
    <p class="name">Hydrogenium</p>
    <p class="number">1</p>
    <p class="symbol">H</p>
    <p class="weight">1.008</p>
  </div>
  <div class="grid-item noble-gas" data-category="noble-gas">
    <p class="name">Helium</p>
    <p class="number">2</p>
    <p class="symbol">He</p>
    <p class="weight">4.002</p>
  </div>
  ...
</div>

Additionally, you can use any element to sort items with the data attribute. In this case, <button> and data-sort-by:

<div class="button-group sort-by-group">
  <button data-sort-by="original">Original Order</button>
  <button data-sort-by="category">Category</button>
  <button data-sort-by="name">Name</button>
  <button data-sort-by="number">Number</button>
  <button data-sort-by="symbol">Symbol</button>
  <button data-sort-by="weight">Weight</button>
</div>

jQuery

Order items with the sortBy option. This option requires to have previously obtained data from the HTML with the sortData option object.

//Get sort data, then sort by name
$('.grid').magnet({
  sortData: {
    category: '[data-category]',
    name: '.name',
    number: '.number',
    symbol: '.symbol',
    weight: '.weight'
  },
  sortBy: 'name'
});

//Get sort data on initialization,
//sort items later
$('.grid').magnet({
  sortData: {
    category: '[data-category]',
    name: '.name',
    number: '.number',
    symbol: '.symbol',
    weight: '.weight'
  }
});
//Sort items by name after initialization
$('.grid').magnet({sortBy: 'name'});

//Sort items by name, then by number
$('.grid').magnet({sortBy: ['name', 'number']});

To sort items when a button is clicked, use the value in data-sort-by attribute for the sortBy option.

//Sort items on button click
$('.sort-by-group').click(function() {
  var sortBy = $(this).data('sort-by');
  $('.grid').magnet({sortBy: sortBy});
});

Get data from the HTML with the sortData option object. Object's keys, are used as keywords to sort by. Object's values, are a string or a function to retrieve data.

A string set as value, will be used as a query selector to get the text of child elements for each item.

$('.grid').magnet({
  sortData: {
    //Use text of '.name' selector
    name: '.name',
    //Use text of '.symbol' selector
    symbol: '.symbol'
  }
});

Any string wrapped in brackets, like [attribute], will be used to get the value of an attribute.

$('.grid').magnet({
  sortData: {
    //Use the value of the data-category attribute
    category: '[data-category]'
  }
});

Numeric values should be parsed to get a correct order. Add parser keywords to the keyword string to parse values.

$('.grid').magnet({
  sortData: {
    //Parse value as an integer
    number: '.number parseInt',
    //Parse value as a float
    weight: '.weight parseFloat'
  }
});

A function can be used as a value. This function is used to get data from each item. The function requires a parameter elem, which is the item element selector, and must return the data.

$('.grid').magnet({
  sortData: {
    weight: function(elem) {
      //Get text from .weight element
      var weight = $(elem).find('.weight').text();
      //Remove parenthesis and parse value as a float
      return parseFloat(weight.replace(/[()]/g, ''));
    }
  }
});

Sort items with sortBy option for every property set in sortData. The value of sortBy must match a key in sortData.

$('.grid').magnet({
  sortData: {
    name: '.name'
  },
  sortBy: 'name'
});

There are two built-in sortBy options.

//Original order
$('.grid').magnet({
  sortBy: 'original'
});
//Random order
$('.grid').magnet({
  sortBy: 'random'
});

To sort by multiple properties, set sortBy to an array. Items will be sort by the first property, then by the next.

//Sort by category, then by symbol
$('.grid').magnet({
  sortBy: ['category', 'symbol']
});

By default, items are sort ascendengly. To sort descendingly, set sortAscending: false.

//Sort by number, from highest to lowest
$('.grid').magnet({
  sortBy: 'number',
  sortAscending: false
});

//Set to an object to set sort direction for each property
$('.grid').magnet({
  sortAscending: {
    name: true,
    number: false,
    symbol: true,
    weight: false,
    category: true
  }
});

Layout Modes

Magnet position items depending on a layout mode. A layout mode, follows its own layout logic.

Grid

Magnet lays out items using a bin-packing algorithm, creating gapless layouts. This is the default layout mode used.

Rows

Magnet lays out items into rows. Rows progress vertically when a row is completed. Arranges items similar to a grid using CSS floats.

Columns

Magnet lays out items into columns. Columns progress horizontally when a column is completed. Horizontal layout modes need the container to have a height value:

//Both are valid values
.grid { height: 50%; }
.grid { height: 500px; }

Horizontal

Magnet lays out items horizontally. Horizontal layout modes need the container to have a height value:

//Both are valid values
.grid { height: 50%; }
.grid { height: 500px; }

Vertical

Magnet lays out items vertically.

Events

Magnet emits events on certain processes completion. This events can be emitted by the container or items.

Container

arrangeComplete

Triggers after all items have ended hide, reveal and layout transitions.

//jQuery
$('.grid').on('arrangeComplete', function() {
  console.log('Arrange is completed');
});
//vanilla JS
var elem = document.querySelector('.grid');
elem.addEventListener('arrangeComplete', function(){
  console.log('Arrange is completed');
});

layoutComplete

Triggers after all items have ended layout transition.

//jQuery
$('.grid').on('layoutComplete', function() {
  console.log('Layout is completed');
});
//vanilla JS
var elem = document.querySelector('.grid');
elem.addEventListener('layoutComplete', function(){
  console.log('Layout is completed');
});

revealComplete

Triggers after all items have ended reveal transition.

//jQuery
$('.grid').on('revealComplete', function() {
  console.log('Reveal is completed');
});
//vanilla JS
var elem = document.querySelector('.grid');
elem.addEventListener('revealComplete', function(){
  console.log('Reveal is completed');
});

hideComplete

Triggers after all items have ended reveal transition.

//jQuery
$('.grid').on('hideComplete', function() {
  console.log('Hide is completed');
});
//vanilla JS
var elem = document.querySelector('.grid');
elem.addEventListener('hideComplete', function(){
  console.log('Hide is completed');
});

removeComplete

Triggers after all items have ended remove transition.

//jQuery
$('.grid').on('removeComplete', function() {
  console.log('Remove is completed');
});
//vanilla JS
var elem = document.querySelector('.grid');
elem.addEventListener('removeComplete', function(){
  console.log('Remove is completed');
});

Items

layout

Triggers after an item has been positioned on the layout and ended transition.

//jQuery
$('.grid-item').on('layout', function(event){
  console.log('Positioned ' + event.target);
});
//vanilla JS
var elems = document.querySelectorAll('.grid-item');
elems.forEach(function(elem){
  elem.addEventListener('layout', function(){
    console.log('Positioned ' + event.currentTarget);
  });
});

reveal

Triggers after an item has been revealed in the layout and ended transition.

//jQuery
$('.grid-item').on('reveal', function(event){
  console.log('Revealed ' + event.target);
});
//vanilla JS
var elems = document.querySelectorAll('.grid-item');
elems.forEach(function(elem){
  elem.addEventListener('layout', function(){
    console.log('Revealed ' + event.currentTarget);
  });
});

hide

Triggers after an item has been hidden in the layout and ended transition.

//jQuery
$('.grid-item').on('hide', function(event){
  console.log('Hidden ' + event.target);
});
//vanilla JS
var elems = document.querySelectorAll('.grid-item');
elems.forEach(function(elem){
  elem.addEventListener('layout', function(){
    console.log('Hidden ' + event.currentTarget);
  });
});

remove

Triggers after an item has been removed from the layout and ended transition.

//jQuery
$('.grid-item').on('remove', function(event){
  console.log('Removed ' + event.target);
});
//vanilla JS
var elems = document.querySelectorAll('.grid-item');
elems.forEach(function(elem){
  elem.addEventListener('layout', function(){
    console.log('Removed ' + event.currentTarget);
  });
});

transition

Triggers after an item has ended a transition.

//jQuery
$('.grid-item').on('transition', function(event){
  console.log('Transition ended ' + event.target);
});
//vanilla JS
var elems = document.querySelectorAll('.grid-item');
elems.forEach(function(elem){
  elem.addEventListener('layout', function(){
    console.log('Transition ended ' + event.currentTarget);
  });
});

Methods

Methods are actions that take place on Magnet instances.

jQuery methods follow the jQuery UI pattern .magnet('methodName', /* arguments */);

$('.grid').magnet()
  .magnet('hide', elem)
  .magnet('layout')
  //Chaining is broken by methods that return values
  .magnet('getFilteredItems');

Vanilla javascript methods follow the pattern magnet.methodName(/* arguments */), but they cannot be chained.

var elem = document.querySelector('.grid');
var mgnt = new Magnet(elem);
mgnt.hide(elem);
mgnt.layout();
mgnt.getFilteredItems();

Arrange and layout

arrange

Arguments: Yes Type: Object

Filters, sorts and lays out items. Accepts an option object as an argument to apply filtering and sorting.

//jQuery
$('.grid').magnet('arrange', options);
//Arrange is the main method of Magnet
//Both lines produce the same result
$('.grid').magnet(options);
//vanilla JS
mgnt.arrange(options);

layout

Arguments: No

Lays out all items. Refreshes the layout, if an item has changed size and items need to be laid out again.

//jQuery
$('.grid').magnet('layout');
//vanilla JS
mgnt.layout();

layoutItems

Arguments: Yes Type: Array of Items, Boolean

Lays out specified items.

//jQuery
$('.grid').magnet('layoutItems', items, instant);
//vanilla JS
mgnt.layout(items, instant);

updateSortData

Arguments: No

Updates sort data.

//jQuery
$('.grid').magnet('updateSortData');
//vanilla JS
mgnt.updateSortData();

shuffle

Arguments: No

Lays out items in a random order.

//jQuery
$('.grid').magnet('shuffle');
//vanilla JS
mgnt.shuffle();

hide

Arguments: Yes Type: Element, NodeList, Array or jQuery Object

Hides items.

//jQuery
$('.grid').magnet('hide', elements);
//vanilla JS
mgnt.hide(elements);

reveal

Arguments: Yes Type: Element, NodeList, Array or jQuery Object

Reveals hidden items.

//jQuery
$('.grid').magnet('reveal', elements);
//vanilla JS
mgnt.reveal(elements);

Add or remove items

append

Arguments: Yes Type: Element, NodeList, Array or jQuery Object

Adds and lays out elements as items to the end of the layout.

//jQuery
$('.grid').magnet('append', elements);
//vanilla JS
mgnt.append(elements);

prepend

Arguments: Yes Type: Element, NodeList, Array or jQuery Object

Adds and lays out elements as items to the beginning of the layout.

//jQuery
$('.grid').magnet('prepend', elements);
//vanilla JS
mgnt.prepend(elements);

addItems

Arguments: Yes Type: Element, NodeList, Array or jQuery Object

Adds items to the layout, therefore to the instance. Items are not laid out.

//jQuery
$('.grid').magnet('addItems', elements);
//vanilla JS
mgnt.addItems(elements);

insert

Arguments: Yes Type: Element, NodeList, Array or jQuery Object

Adds elements as items to the layout and filters, sorts and lays out items.

//jQuery
$('.grid').magnet('insert', elements);
//vanilla JS
mgnt.insert(elements);

remove

Arguments: Yes Type: Element, NodeList, Array or jQuery Object

Removes elements as items from the layout, therefore from the instance and DOM.

//jQuery
$('.grid').magnet('remove', elements);
//vanilla JS
mgnt.remove(elements);

Utilities

reloadItems

Arguments: No

Updates all items data. Applies changes made to the DOM to Magnet.

//jQuery
$('.grid').magnet('reloadItems');
//vanilla JS
mgnt.reloadItems();

getItem

Arguments: Yes Type: Element Returns: Item

Returns an item from the layout.

//jQuery
var item = $('.grid').magnet('getItem', element);
console.log(item);
//vanilla JS
var item = mgnt.getItem(element);
console.log(item);

getItems

Arguments: Yes Type: Element, NodeList, Array or jQuery Object Returns: Array of Items

Returns an array of all items from the layout.

//jQuery
var items = $('.grid').magnet('getItem', elements);
console.log(items);
//vanilla JS
var items = mgnt.getItem(elements);
console.log(items);

getItemsElements

Arguments: No Returns: Array of Items

Returns an array of all items elements from the layout.

//jQuery
var items = $('.grid').magnet('getItemsElements');
console.log(items);
//vanilla JS
var items = mgnt.getItemsElements();
console.log(items);

getFilteredItems

Arguments: No Returns: Array of Items

Returns an array of filtered items in the current order.

//jQuery
var items = $('.grid').magnet('getFilteredItems');
console.log(items);
//vanilla JS
var items = mgnt.getFilteredItems();
console.log(items);

getFilteredItemsElements

Arguments: No Returns: Array of Items

Returns an array of filtered items elements in the current order.

//jQuery
var items = $('.grid').magnet('getFilteredItemsElements');
console.log(items);
//vanilla JS
var items = mgnt.getFilteredItemsElements();
console.log(items);

destroy

Arguments: No

Removes all Magnet functionallity and returns the element back to its pre-initialization state.

//jQuery
$('.grid').magnet('destroy');
//vanilla JS
mgnt.destroy();

Options

All options are optional. Some options overwrite default value.

Setup

itemSelector

Type: String

Select elements to be used as items in the layout. Recommended to always set up, to exclude elements that are not part of the layout. By default, all children elements are selected.

$('.grid').magnet({
  itemSelector: '.grid-item'
});

resize

Type: Boolean Default: true

Enables items to adjust size and position on window resize.

//Items stay on same position
$('.grid').magnet({
  resize: false
});

resizeContainer

Type: Boolean Default: true

Enables item container to resize.

$('.grid').magnet({
  resizeContainer: false
});
//Container has fixed size
.grid {
  width: 500px;
  height: 500px;
}

initLayout

Type: Boolean Default: true

Enables layout on initialization. Set initLayout: false to disable layout on initialization to use methods or add events.

var grid = $('.grid').magnet({
  //Disable initial layout
  initLayout: false
});

//Bind event
grid.on('arrangeComplete', function() {
  console.log('Arrange is completed');
});

//Manual initial layout
grid.magnet();

layoutInstant

Type: Boolean

Disables transitions. Set layoutInstant: false to enable transitions on initialization. Transitions on initialization are disabled by default, but enabled after first layout.

$('.grid').magnet({
  layoutInstant: true
});

itemStyle

Type: Object Default: { position: 'absolute' }

Style applied to items.

$('.grid').magnet({
  itemStyle: { 
    //Do not overwrite
    position: 'absolute',
    //Additional properties with
    //priority over CSS
    borderRadius: 0,
    boxShadow: 'none'
  }
});

containerStyle

Type: Object Default: { position: 'relative' }

Style applied to item container.

$('.grid').magnet({
  containerStyle: { position: 'relative' }
});

Layout

layoutMode

Type: String Default: 'grid' Value: 'grid', 'rows', 'columns', 'horizontal' or 'vertical'

Sets the layout mode to position items.

$('.grid').magnet({
  layoutMode: 'grid'
});

horizontal

Type: Boolean

Lays out items vertically instead of horizontally. Only for layoutMode: 'grid'.

$('.grid').magnet({
  horizontal: true
});

Horizontal layout modes need the container to have a height value:

//Both are valid values
.grid { height: 50%; }
.grid { height: 500px; }

Filtering

filter

Type: String or Function

Shows items that match the filter and hides items that don't.

$('.grid').magnet({
  filter: '.selector'
});

Items can be filtered using a function. The function requires a parameter elem, which is the item element selector, and must return the data.

$('.grid').magnet({
  filter: function(elem) {
    //Get text from .symbol element
    var symbol = $(elem).find('.symbol').text();
    //Return elements with one character symbol
    return symbol.match(/^[A-Z]$/);
  }
});

Sorting

sortData

Type: Object

Gets data from the HTML. Object's keys, are used as keywords to sort by. Object's values, are a string or a function to retrieve data.

$('.grid').magnet({
  sortData: {
    category: '[data-category]',
    symbol: '.symbol'
  }
});

Any string wrapped in brackets, like [attribute], will be used to get the value of an attribute.

$('.grid').magnet({
  sortData: {
    //Use the value of the data-category attribute
    category: '[data-category]'
  }
});

Numeric values should be parsed to get a correct order. Add parser keywords to the keyword string to parse values.

$('.grid').magnet({
  sortData: {
    //Parse value as an integer
    number: '.number parseInt',
    //Parse value as a float
    weight: '.weight parseFloat'
  }
});

A function can be used as a value. This function is used to get data from each item. The function requires a parameter elem, which is the item element selector, and must return the data.

$('.grid').magnet({
  sortData: {
    weight: function(elem) {
      //Get text from .weight element
      var weight = $(elem).find('.weight').text();
      //Remove parenthesis and parse value as a float
      return parseFloat(weight.replace(/[()]/g, ''));
    }
  }
});

sortBy

Type: String or Array

Sorts items according to a property value. Value must match a key name in sortData.

$('.grid').magnet({
  sortData: {
    name: '.name'
  },
  sortBy: 'name'
});

There are two built-in sortBy options.

//Original order
$('.grid').magnet({
  sortBy: 'original'
});
//Random order
$('.grid').magnet({
  sortBy: 'random'
});

To sort by multiple properties, set sortBy to an array. Items will be sort by the first property, then by the next.

//Sort by category, then by symbol
$('.grid').magnet({
  sortBy: ['category', 'symbol']
});

Set to an object to set sort direction for each property.

$('.grid').magnet({
  sortAscending: {
    name: true,
    number: false,
    symbol: true,
    weight: false,
    category: true
  }
});

sortAscending

Type: Boolean Default: true

Sorts items ascending. Set sortAscending: false to sort descending.

$('.grid').magnet({
  sortAscending: true
});

Transitions

duration

Type: Number Default: 500

Items transition duration, in milliseconds.

$('.grid').magnet({
  duration: 250
});

easing

Type: String Default: 'ease'

Items transition effect speed curve.

$('.grid').magnet({
  easing: 'ease-in-out'
});

stagger

Type: Number Default: 0

Staggers items transitions, incrementally after one another.

$('.grid').magnet({
  stagger: 50
});

hiddenStyle

Type: Object Default: { opacity: 0, transform: 'scale(0.001)' }

Style applied to hide items.

$('.grid').magnet({
  hiddenStyle: { 
    opacity: 0
  },
  visibleStyle: { 
    opacity: 1
  }
});

visibleStyle

Type: Object Default: { opacity: 1, transform: 'scale(1)' }

Style applied to reveal hidden items.

$('.grid').magnet({
  hiddenStyle: { 
    opacity: 0
  },
  visibleStyle: { 
    opacity: 1
  }
});