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
}
});