Filter
Options
Settings you can change (these are the defaults).
// Overrideable options
Shuffle.options = {
buffer: 0, // Useful for percentage based heights when they might not always be exactly the same (in pixels).
columnThreshold: 0.01, // Reading the width of elements isn't precise enough and can cause columns to jump between values.
columnWidth: 0, // A static number or function that returns a number which tells the plugin how wide the columns are (in pixels).
delimiter: null, // If your group is not json, and is comma delimited, you could set delimiter to ','.
easing: 'cubic-bezier(0.4, 0.0, 0.2, 1)', // CSS easing function to use.
filterMode: Shuffle.FilterMode.ANY, // When using an array with filter(), the element passes the test if any of its groups are in the array. With "all", the element only passes if all groups are in the array.
group: Shuffle.ALL_ITEMS, // Initial filter group.
gutterWidth: 0, // A static number or function that tells the plugin how wide the gutters between columns are (in pixels).
initialSort: null, // Shuffle can be initialized with a sort object. It is the same object given to the sort method.
isCentered: false, // Attempt to center grid items in each row.
isRTL: false, // Attempt to align grid items to right.
itemSelector: '*', // e.g. '.picture-item'.
roundTransforms: true, // Whether to round pixel values used in translate(x, y). This usually avoids blurriness.
sizer: null, // Element or selector string. Use an element to determine the size of columns and gutters.
speed: 250, // Transition/animation speed (milliseconds).
staggerAmount: 15, // Transition delay offset for each item in milliseconds.
staggerAmountMax: 150, // Maximum stagger delay in milliseconds.
throttle: throttle, // By default, shuffle will throttle resize events. This can be changed or removed.
throttleTime: 300, // How often shuffle can be called on resize (in milliseconds).
useTransforms: true, // Whether to use transforms or absolute positioning.
};
No options need to be specified, but itemSelector
should be used. Other common options to change are speed
and sizer
.
Usage
The HTML Structure
The only real important thing here is the data-groups
attribute. It has to be a valid JSON array of strings. It can also be a string delimited by a value you provide with the delimiter
option.
This example is using this site's grid. Each item would be 4 columns at the "sm" breakpoint (768px).
Images
Images are wrapped in .aspect
elements to take up the same amount of space the image will when it loads. For details, check out the images demo.
<div class="row my-shuffle-container">
<figure class="col-4@sm picture-item" data-groups='["animal"]' data-date-created="2016-08-12" data-title="Crocodile">
<div class="aspect aspect--16x9">
<div class="aspect__inner">
<img src="crocodile.jpg" alt="A close, profile view of a crocodile looking directly into the camera" />
</div>
</div>
<figcaption>Crocodile</figcaption>
</figure>
<figure class="col-4@sm picture-item" data-groups='["city"]' data-date-created="2016-06-09" data-title="Crossroads">
<div class="aspect aspect--16x9">
<div class="aspect__inner">
<img src="crossroads.jpg" alt="A multi-level highway stack interchange in Puxi, Shanghai" />
</div>
</div>
<figcaption>Crossroads</figcaption>
</figure>
<figure class="col-4@sm picture-item" data-groups='["nature","city"]' data-date-created="2015-10-20" data-title="Central Park">
<div class="aspect aspect--16x9">
<div class="aspect__inner">
<img src="central-park.jpg" alt="Looking down on central park and the surrounding builds from the Rockefellar Center" />
</div>
</div>
<figcaption>Central Park</figcaption>
</figure>
<div class="col-1@sm my-sizer-element"></div>
</div>
How column widths work
There are 4 options for defining the width of the columns:
- Use a sizer element. This is the easiest way to specify column and gutter widths. Add the sizer element and make it 1 column wide. Shuffle will measure the
width
andmargin-left
of thissizer
element each time the grid resizes. This is awesome for responsive or fluid grids where the width of a column is a percentage. - Use a function. When a function is used, its first parameter will be the width of the shuffle element. You need to return the column width for shuffle to use (in pixels).
- A number. This will explicitly set the column width to your number (in pixels).
- By default, shuffle will use the width of the first item to calculate the column width.
A basic setup example
If you want functional buttons, check out the js file.
Shuffle uses a UMD definition so that you can use it with globals, AMD, or CommonJS.
const Shuffle = window.Shuffle;
const element = document.querySelector('.my-shuffle-container');
const sizer = element.querySelector('.my-sizer-element');
const shuffleInstance = new Shuffle(element, {
itemSelector: '.picture-item',
sizer: sizer // could also be a selector: '.my-sizer-element'
});
Filters
Filter by a group
Use the filter()
method. If, for example, you wanted to show only items that match "space"
, you would do this:
shuffleInstance.filter('space');
Filter by multiple groups
Show multiple groups at once by using an array.
shuffleInstance.filter(['space', 'nature']);
By default, this will show items that match space
or nature
. To show only groups that match space
and nature
, set the filterMode
option to Shuffle.FilterMode.ALL
.
Show all items
To go back to having no items filtered, you can call filter()
without a parameter, or use Shuffle.ALL_ITEMS
(which by default is the string "all"
).
shuffleInstance.filter(Shuffle.ALL_ITEMS); // or .filter()
Overrides
You can override both Shuffle.ALL_ITEMS
and Shuffle.FILTER_ATTRIBUTE_KEY
if you want.
// Defaults
Shuffle.ALL_ITEMS = 'all';
Shuffle.FILTER_ATTRIBUTE_KEY = 'groups';
// You can change them to something else.
Shuffle.ALL_ITEMS = 'any';
Shuffle.FILTER_ATTRIBUTE_KEY = 'categories';
Then you would have to use data-categories
attribute on your items instead of data-groups
.
Advanced Filters
By passing a function to filter
, you can fully customize filtering items. Shuffle will iterate over each item and give your function the element and the shuffle instance. Return true
to keep the element or false
to hide it.
Example
// Filters elements with a data-title attribute with less than 10 characters
shuffleInstance.filter((element) => {
return element.dataset.title.length < 10;
});
Searching
// Advanced filtering
addSearchFilter() {
document.querySelector('.js-shuffle-search').addEventListener('keyup', this._handleSearchKeyup.bind(this));
};
// Filter the shuffle instance by items with a title that matches the search input.
_handleSearchKeyup(evt) {
const searchText = evt.target.value.toLowerCase();
this.shuffle.filter((element, shuffle) => {
const titleElement = element.querySelector('.picture-item__title');
const titleText = titleElement.textContent.toLowerCase().trim();
return titleText.indexOf(searchText) !== -1;
});
};
Check out the compounded filters demo.
Sorting
You can order the elements with a function you supply. In the demo above, each item has a data-date-created
and data-title
attribute which are used for sorting.
<figure class="col-4@sm picture-item" data-groups='["city"]' data-date-created="2016-06-09" data-title="Crossroads">…</figure>
<select class="sort-options">
<option value="">Default</option>
<option value="title">Title</option>
<option value="date-created">Date Created</option>
</select>
addSorting() {
document.querySelector('.sort-options').addEventListener('change', this._handleSortChange.bind(this));
};
_handleSortChange(evt) {
const value = evt.target.value;
function sortByDate(element) {
return element.dataset.created;
}
function sortByTitle(element) {
return element.dataset.title.toLowerCase();
}
let options;
if (value === 'date-created') {
options = {
reverse: true,
by: sortByDate,
};
} else if (value === 'title') {
options = {
by: sortByTitle,
};
} else {
options = {};
}
this.shuffle.sort(options);
};
The options
object can contain three properties:
reverse
: a boolean which will reverse the resulting order.by
: a function with an element as the parameter. Above, we’re returning the value of thedata-date-created
ordata-title
attribute.randomize
: Make the order random.
Returning undefined
from the by
function will reset the order to DOM order.
Calling sort with an empty object will reset the elements to DOM order.
Check out the demo.
Filter and sort
You can filter and sort at the same time by passing a sort object as the second parameter.
shuffleInstance.filter('space', {
by: (element) => {
return element.dataset.title.toLowerCase();
},
});
Advanced sorting
You can provide the entire sort compare function if you need more control.
The parameters (a
, b
) are ShuffleItem
instances and you'll probably only use the element
property. The reverse
option still works with the compare
function if you need it.
For example, if you wanted to sort by the first group in data-groups
, then by data-age
, you could do this:
shuffleInstance.sort({
compare: (a, b) => {
// Sort by first group, then by age.
const groupA = JSON.parse(a.element.dataset.groups)[0];
const groupB = JSON.parse(b.element.dataset.groups)[0];
if (groupA > groupB) {
return 1;
}
if (groupA < groupB) {
return -1;
}
// At this point, the group strings are the exact same. Test the age.
const ageA = parseInt(a.element.dataset.age, 10);
const ageB = parseInt(b.element.dataset.age, 10);
return ageA - ageB;
},
});
Events
Shuffle is a subclass of TinyEmitter. It emits an event when a layout happens and when elements are removed. The event names are Shuffle.EventType.LAYOUT
and Shuffle.EventType.REMOVED
.
Get notified when a layout happens
shuffleInstance.on(Shuffle.EventType.LAYOUT, () => {
console.log('Things finished moving!');
});
Do something when an item is removed
shuffleInstance.on(Shuffle.EventType.REMOVED, (data) => {
console.log(this, data, data.collection, data.shuffle);
});
Check out the demo at the top of the page, or its JavaScript file.
Adding and Removing Items
You can add and remove elements from shuffle after it has been created. This also works for infinite scrolling.
Adding elements
Wherever you add the element in the DOM is where it will show up in the grid (assuming you’re using the default sort-by-dom-order). With this in mind, you can append, prepend, or insert elements wherever you need to get them to show up in the right order.
/**
* Create some DOM elements, append them to the shuffle container, then notify
* shuffle about the new items. You could also insert the HTML as a string.
*/
onAppendBoxes() {
const elements = this._getArrayOfElementsToAdd();
elements.forEach((element) => {
this.shuffle.element.appendChild(element);
});
// Tell shuffle elements have been appended.
// It expects an array of elements as the parameter.
this.shuffle.add(elements);
};
Removing elements
Shuffle will animate the element away and then remove it from the DOM once it's finished. It will then emit the Shuffle.EventType.REMOVED
event with the array of elements in event.collection
.
this.shuffle.remove([element1, element2]);
Check out the adding and removing demo.
Public Methods
A list of the methods available to you and what they do.
filter(category, sortObject)
- Filters all the shuffle items and then sorts them.category
can be a string, array of strings, or a function. The sort object is optional and will use the last-used sort object.sort(sortObject)
- Sorts the currently filtered shuffle items.update()
- Repositions everything. Useful for when dimensions (like the window size) change.layout()
- Use this instead ofupdate()
if you don't need the columns and gutters updated. Maybe an image loaded and now has a height.add(newItems)
- New items have been appended to the shuffle container.newItems
is an array of elements.disable()
- Disables Shuffle from updating dimensions and layout on resize.enable()
- Enables Shuffle again.remove()
- Remove one or more shuffle items.getItemByElement(element)
- Retrieve aShuffleItem
by its element.destroy()
- Destroys Shuffle, removes events, styles, classes, and references.
Customizing Styles
You can customize the default styles which are applied to Shuffle items upon initialization, before layout, after layout, before hiding, and after hidden.
Here are the defaults:
ShuffleItem.Css = {
INITIAL: {
position: 'absolute',
top: 0,
left: 0,
visibility: 'visible',
'will-change': 'transform',
},
VISIBLE: {
before: {
opacity: 1,
visibility: 'visible',
},
after: {
transitionDelay: '',
},
},
HIDDEN: {
before: {
opacity: 0,
},
after: {
visibility: 'hidden',
transitionDelay: '',
},
},
};
ShuffleItem.Scale = {
VISIBLE: 1,
HIDDEN: 0.001,
};
If you wanted to add a 50% red background to every item when they initialize, you could do this:
Shuffle.ShuffleItem.Css.INITIAL.backgroundColor = 'rgba(255, 0, 0, 0.5)';
To set the text color to teal
after the item has finished moving:
Shuffle.ShuffleItem.Css.VISIBLE.after.color = 'teal';
You can also customize the scaling effect with visible or hidden items.
Shuffle.ShuffleItem.Scale.HIDDEN = 0.5;
Dependencies
Shuffle's dependencies are bundled with the dist file.
Changelog
For a more detailed changelog, visit the latest releases on GitHub.
v6.0.0
2022-02-01 - Drop IE 11, remove misspelleddelimeter
option, removematches-selector
package.-
v5.4.1
2021-05-29 - AddsortedItems
property. FixgetComputedStyle
bug for Chrome on Windows. v5.3.0
2021-03-23 - AddisRTL
option.-
v5.2.3
2019-08-29 - Add missing inherited methods fromTinyEmitter
to TypeScript definitions. v5.2.2
2019-06-03 - Update TypeScript definitions.-
v5.2.1
2018-12-01 - Change `index.d.ts` to use `export default Shuffle` (#214). Upgrade dev dependencies. -
v5.2.0
2018-08-19 - Lazily test whether the browser'sgetComputedStyle
includes padding. This allows the bundled file to be imported in node for server side rendering. -
v5.1.2
2018-03-26 - Fix misspelleddelimiter
option. Both "delimiter" and "delimeter" will continue to work for v5. v5.1.1
2018-03-02 - Fix new item animation when there is an active filter.-
v5.1.0
2018-02-20 - Addcompare
option to sorter. Addes
build to package and"module"
field topackage.json
. v5.0.3
2017-10-30 - Fix rounding error.v5.0.2
2017-09-23 - Update type definitions. Upgrade dev dependencies.v5.0.1
2017-07-18 - AddroundTransforms
option.-
v5.0.0
2017-07-18 - Change global export fromshuffle
toShuffle
. Remove bower support. Expect ES6 environment. Make Shuffle instances Event Emitters instead of dispatchingCustomEvent
. -
v4.2.0
2017-05-10 - Replacewebpack
build withrollup
. Replacejshint
andjscs
witheslint
. AddfilterMode
option. -
v4.1.1
2017-03-21 - thebefore
styles for aShuffleItem
were not applied if the item didn’t move. v4.1.0
2017-01-30 - Use webpack-2 to bundle Shuffle.v4.0.2
2016-09-15 - Updatecustom-event-polyfill
dependency.v4.0.1
2016-07-30 - Fixdelimiter
option.-
v4.0.0
2016-04-20 - Rewrite in ES6 with babel. Remove jQuery and Modernizr dependencies. Remove support for IE<11. Docs improvements. Switch to gulp build system with webpack. -
v3.1.0
2015-03-23 - Allow zero speed option (#64) and cancel previous animations instead of ignoring new ones (#69). Handle non-integer columns better (#46) v3.0.4
2015-02-16 - Publish to NPM.v3.0.2
2015-01-21 - Remove from jQuery plugins directory.v3.0.1
2014-12-29 - Add CommonJS support.-
v3.0.0
2014-10-06 - Refactored with improvements, added unit tests, more documentation. Removed some triggered events. -
v2.1.2
2014-06-01 - Usewindow.jQuery
instead ofwindow.$
to work better with noConflict. Fixed #25. v2.1.1
2014-04-16 - Fix items with zero opacity overlapping visible ones in IE<10.v2.1.0
2014-04-12 - Register with bower asshufflejs
.- 2014-04-10 - Add AMD support.
- 2014-04-08 - Separate Modernizr into its own file and custom Shuffle build.
- 2014-03-08 - Add Bootstrap 3 demo. Fixed issue with percentage width items.
- 2013-10-04 - Moved some Shuffle instance properties to constants. Converted from 4 to 2 space indentation. Added events enum and pulled out some strings to constants.
- 2013-08-30 - Added animate-in demo.
v2.0.0
2013-07-05 - Shuffle 2.0 with masonry, adding and removing, and more.- 2012-11-03 - Replaced layout system with masonry. Items can now be different sizes! Added addtional examples.
- 2012-10-24 - Better handling of grid item dimensions. Added a minimal markup page.
- 2012-09-20 - Added
destroy
method - 2012-09-18 - Added sorting ability and made plugin responsive. Updated to Modernizr 2.6.2
- 2012-07-21 - Rewrote plugin in more object oriented structure. Added custom events. Updated to Modernizr 2.6.1
- 2012-07-03 - Removed dependency on the css file and now apply the css with javascript