Docs updates. Remove LOADING and DONE events.

pull/111/head
Glen Cheney 8 years ago
parent eec4bfc157
commit 60cc0241b3

@ -13,7 +13,6 @@ exclude: [
'bower.json', 'bower.json',
'CONTRIBUTING.md', 'CONTRIBUTING.md',
'gulpfile.js', 'gulpfile.js',
'package.json',
'README.md', 'README.md',
'webpack.config.js', 'webpack.config.js',
'webpack.config.min.js' 'webpack.config.min.js'

@ -1,27 +1,20 @@
<h2>Events<a href="#events"></a></h2> <h2>Events<a href="#events"></a></h2>
<p>A list of events shuffle triggers:</p> <p>Shuffle emits an event when a layout happens and when elements are removed. The event names are <code class="language-javascript">Shuffle.EventType.LAYOUT</code> and <code class="language-javascript">Shuffle.EventType.REMOVED</code>.</p>
<ul class="breathable-list"> <p>Shuffle uses the global <code>CustomEvent</code> to <a href="https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent">create events</a>. A polyfill for IE&lt;=11 is bundled with Shuffle.</p>
<li><code class="language-javascript">'loading.shuffle'</code></li>
<li><code class="language-javascript">'done.shuffle'</code></li>
<li><code class="language-javascript">'layout.shuffle'</code></li>
<li><code class="language-javascript">'removed.shuffle'</code></li>
</ul>
<h3>Get notified when shuffle is done with setup</h3> <h3>Get notified when a layout happens</h3>
<div class="code-block"> <div class="code-block">
<pre rel="JavaScript"><code class="language-javascript">$grid.on('done.shuffle', function() { <pre rel="JavaScript"><code class="language-javascript">element.addEventListener(Shuffle.EventType.LAYOUT, function () {
console.log('Finished initializing shuffle!'); console.log('Things finished moving!');
}); });</code></pre>
// Initialize shuffle
$grid.shuffle( options );</code></pre>
</div> </div>
<h3>Do something when an item is removed</h3> <h3>Do something when an item is removed</h3>
<div class="code-block"> <div class="code-block">
<pre rel="JavaScript"><code class="language-javascript">$grid.on('removed.shuffle', function( evt, $collection, shuffle ) { <pre rel="JavaScript"><code class="language-javascript">element.addEventListener(Shuffle.EventType.REMOVED, function (evt) {
console.log( this, evt, $collection, shuffle ); var detail = evt.detail;
console.log(this, evt, detail.collection, detail.shuffle);
});</code></pre> });</code></pre>
</div> </div>

@ -1,8 +1,7 @@
<h2>Features<a href="#features"></a></h2> <h2>Features<a href="#features"></a></h2>
<ul> <ul>
<li>Fast - Only one forced synchronous layout (aka reflow) on init, sort, or shuffle.</li> <li>Fast - Only one forced synchronous layout (aka reflow) on init, sort, or filter.</li>
<li>Uses CSS Transitions!</li>
<li>Responsive (try resizing the window!)</li> <li>Responsive (try resizing the window!)</li>
<li>Filter items by groups</li> <li>Filter items by groups</li>
<li>Items can have multiple groups and be different sizes</li> <li>Items can have multiple groups and be different sizes</li>

@ -25,6 +25,8 @@
<link id="favicon" rel="icon" type="image/png" href="favicon.png" > <link id="favicon" rel="icon" type="image/png" href="favicon.png" >
<script>window.location.host.indexOf("github.io")>-1&&"https:"!=window.location.protocol&&(window.location.protocol="https:");</script>
<!-- Prefetch DNS for external assets --> <!-- Prefetch DNS for external assets -->
<link rel="dns-prefetch" href="https://fonts.googleapis.com"> <link rel="dns-prefetch" href="https://fonts.googleapis.com">
<link rel="dns-prefetch" href="https://themes.googleusercontent.com"> <link rel="dns-prefetch" href="https://themes.googleusercontent.com">

@ -4,22 +4,23 @@
<div class="code-block"> <div class="code-block">
<pre rel="JavaScript"><code class="language-javascript">// Overrideable options <pre rel="JavaScript"><code class="language-javascript">// Overrideable options
Shuffle.options = { Shuffle.options = {
group: ALL_ITEMS, // Initial filter group. group: Shuffle.ALL_ITEMS, // Initial filter group.
speed: 250, // Transition/animation speed (milliseconds). speed: 250, // Transition/animation speed (milliseconds).
easing: 'ease-out', // CSS easing function to use. easing: 'ease', // CSS easing function to use.
itemSelector: '', // e.g. '.picture-item'. itemSelector: '*', // e.g. '.picture-item'.
sizer: null, // Sizer element. Use an element to determine the size of columns and gutters. sizer: null, // Element or selector string. Use an element to determine the size of columns and gutters.
gutterWidth: 0, // A static number or function that tells the plugin how wide the gutters between columns are (in pixels). gutterWidth: 0, // A static number or function that tells the plugin how wide the gutters between columns are (in pixels).
columnWidth: 0, // A static number or function that returns a number which tells the plugin how wide the columns are (in pixels). columnWidth: 0, // A static number or function that returns a number which tells the plugin how wide the columns are (in pixels).
delimeter: null, // If your group is not json, and is comma delimeted, you could set delimeter to ','. delimeter: null, // If your group is not json, and is comma delimeted, you could set delimeter to ','.
buffer: 0, // Useful for percentage based heights when they might not always be exactly the same (in pixels). buffer: 0, // Useful for percentage based heights when they might not always be exactly the same (in pixels).
columnThreshold: HAS_COMPUTED_STYLE ? 0.01 : 0.1, // Reading the width of elements isn't precise enough and can cause columns to jump between values. columnThreshold: 0.01, // Reading the width of elements isn't precise enough and can cause columns to jump between values.
initialSort: null, // Shuffle can be initialized with a sort object. It is the same object given to the sort method. initialSort: null, // Shuffle can be initialized with a sort object. It is the same object given to the sort method.
throttle: throttle, // By default, shuffle will throttle resize events. This can be changed or removed. 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). throttleTime: 300, // How often shuffle can be called on resize (in milliseconds).
sequentialFadeDelay: 150, // Delay between each item that fades in when adding items. staggerAmount: 15, // Transition delay offset for each item in milliseconds.
supported: CAN_TRANSITION_TRANSFORMS // Whether to use transforms or absolute positioning. staggerAmountMax: 250, // Maximum stagger delay in milliseconds.
useTransforms: true, // Whether to use transforms or absolute positioning.
};</code></pre> };</code></pre>
</div> </div>
<p>No options <em>need</em> to be specified, but <code>itemSelector</code> should be used. Other common options to change are <code>speed</code>, <code>easing</code>, <code>gutterWidth</code>, and <code>columnWidth</code> (or <code>sizer</code>).</p> <p>No options <em>need</em> to be specified, but <code>itemSelector</code> should be used. Other common options to change are <code>speed</code> and <code>sizer</code>.</p>

@ -3,47 +3,45 @@
<h3>The HTML Structure</h3> <h3>The HTML Structure</h3>
<p>The only real important thing here is the <code class="language-markup token attr-name">data-groups</code> attribute. It has to be a <a href="http://jsonlint.com/">valid JSON</a> array of strings. Optionally, it can be a string delimeted by a value you provide. See <code>delimeter</code> in the <a href="#options">options</a>.</p> <p>The only real important thing here is the <code class="language-markup token attr-name">data-groups</code> attribute. It has to be a <a href="http://jsonlint.com/">valid JSON</a> array of strings. Optionally, it can be a string delimeted by a value you provide. See <code>delimeter</code> in the <a href="#options">options</a>.</p>
<p>In this example, shuffle is using the fluid grid from the <a href="http://twitter.github.io/bootstrap/">Twitter Bootstrap v2.3</a>. It's also making use of <a href="http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/"><abbr title="Block-Element-Modifier">BEM</abbr></a> class naming.</p> <p>This example is using this site's grid. Each item would be 4 columns at the "sm" breakpoint (768px).</p>
<h3>Images</h3>
<p>To see why the images are wrapped in <code>.aspect</code> elements, check out the <a href="{{ site.baseurl }}{% post_url 2013-05-03-images %}">images demo</a>.</p>
<div class="code-block"> <div class="code-block">
<pre rel="HTML"><code class="language-markup">&lt;div id="grid" class="row"&gt; <pre rel="HTML"><code class="language-markup">&lt;div id="grid" class="row my-shuffle-container"&gt;
&lt;figure class="col-3@sm picture-item" data-groups='["photography"]'&gt; &lt;figure class="col-4@sm picture-item" data-groups='[&quot;photography&quot;]' data-date-created="2010-09-14" data-title="Baseball"&gt;
&lt;img src="/img/baseball.png" height="145" width="230" /&gt; &lt;div class="aspect aspect--16x9"&gt;
&lt;div class="picture-item__details"&gt; &lt;div class="aspect__inner"&gt;
&lt;figcaption class="picture-item__title"&gt;Baseball&lt;/figcaption&gt; &lt;img src="/img/baseball.png" alt="" height="145" width="230"&gt;
&lt;p class="picture-item__tags"&gt;photography&lt;/p&gt; &lt;/div&gt;
&lt;/div&gt;
&lt;/figure&gt;
&lt;figure class="col-6@sm picture-item" data-groups='["wallpaper","3d"]'&gt;
&lt;img src="/img/tennis-ball.png" height="145" width="230" /&gt;
&lt;div class="picture-item__details"&gt;
&lt;figcaption class="picture-item__title"&gt;Tennis&lt;/figcaption&gt;
&lt;p class="picture-item__tags"&gt;wallpaper, 3d&lt;/p&gt;
&lt;/div&gt; &lt;/div&gt;
&lt;p class="picture-item__description"&gt;Some description here.&lt;/p&gt; &lt;figcaption&gt;Baseball&lt;/figcaption&gt;
&lt;/figure&gt; &lt;/figure&gt;
&lt;figure class="col-3@sm picture-item" data-groups='["wallpaper","3d"]'&gt; &lt;figure class="col-4@sm picture-item" data-groups='[&quot;wallpaper&quot;,&quot;3d&quot;]' data-date-created="2011-08-14" data-title="Tennis"&gt;
&lt;img src="/img/imac.png" height="145" width="230" /&gt; &lt;div class="aspect aspect--16x9"&gt;
&lt;div class="picture-item__details"&gt; &lt;div class="aspect__inner"&gt;
&lt;figcaption class="picture-item__title"&gt;iMac&lt;/figcaption&gt; &lt;img src="/img/tennis-ball.png" alt="" height="145" width="230"&gt;
&lt;p class="picture-item__tags"&gt;wallpaper, 3d&lt;/p&gt; &lt;/div&gt;
&lt;/div&gt; &lt;/div&gt;
&lt;figcaption&gt;Tennis&lt;/figcaption&gt;
&lt;/figure&gt; &lt;/figure&gt;
&lt;figure class="col-3@sm picture-item picture-item--h2" data-groups='["graphics"]'&gt; &lt;figure class="col-4@sm picture-item" data-groups='[&quot;wallpaper&quot;,&quot;3d&quot;]' data-date-created="2009-05-27" data-title="iMac"&gt;
&lt;img src="/img/master-chief.png" height="145" width="230" /&gt; &lt;div class="aspect aspect--16x9"&gt;
&lt;div class="picture-item__details"&gt; &lt;div class="aspect__inner"&gt;
&lt;figcaption class="picture-item__title"&gt;Master Chief&lt;/figcaption&gt; &lt;img src="/img/imac.png" alt="" height="145" width="230"&gt;
&lt;p class="picture-item__tags"&gt;graphics&lt;/p&gt; &lt;/div&gt;
&lt;/div&gt; &lt;/div&gt;
&lt;p class="picture-item__description"&gt;Some description here.&lt;/p&gt; &lt;figcaption&gt;iMac&lt;/figcaption&gt;
&lt;/figure&gt; &lt;/figure&gt;
&lt;div class="col-1@sm my-sizer-element"&gt;&lt;/div&gt;
&lt;/div&gt;</code></pre> &lt;/div&gt;</code></pre>
</div> </div>
<h3 id="columns">How column widths work<a href="#how-column-widths-work"></a></h3> <h3 id="columns">How column widths work<a href="#how-column-widths-work"></a></h3>
<p>The <code>columnWidth</code> option is used to calculate the column width. You have several options:</p> <p>There are 4 options for defining the width of the columns:</p>
<ol> <ol>
<li>Use a <strong>sizer</strong> element. This is the easest way to specify column and gutter widths. You can use an element or an element wrapped in jQuery to define the column width and gutter width. Shuffle will measure the <code>width</code> and <code>margin-left</code> of this <code>sizer</code> element each time the grid resizes. This is awesome for responsive or fluid grids where the width of a column is a percentage. The <code>sizer</code> option is an alias for <code>columnWidth</code>.<span class="demo-link-container">See <a href="{{ site.baseurl }}{% post_url 2013-05-01-basic %}">a demo</a> using a sizer element or <a href="{{ site.baseurl }}/js/demos/homepage.js">look at the js file</a> for the sizer demo.</span></li> <li>Use a <strong>sizer</strong> 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 <code>width</code> and <code>margin-left</code> of this <code>sizer</code> element each time the grid resizes. This is awesome for responsive or fluid grids where the width of a column is a percentage.</li>
<li>Use a <strong>function</strong>. 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).</li> <li>Use a <strong>function</strong>. 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).</li>
<li>A <strong>number</strong>. This will explicitly set the column width to your number (in pixels).</li> <li>A <strong>number</strong>. This will explicitly set the column width to your number (in pixels).</li>
<li>By default, shuffle will use the width of the first item to calculate the column width.</li> <li>By default, shuffle will use the width of the first item to calculate the column width.</li>
@ -51,14 +49,14 @@
<h3>A basic setup example</h3> <h3>A basic setup example</h3>
<p>If you want functional buttons, check out <a href="{{ site.baseurl }}/js/demos/homepage.js">the js file</a>.</p> <p>If you want functional buttons, check out <a href="{{ site.baseurl }}/js/demos/homepage.js">the js file</a>.</p>
<p>Shuffle uses a UMD definition so that you can use it with globals, AMD, or CommonJS.</p>
<div class="code-block"> <div class="code-block">
<pre rel="JavaScript"><code class="language-javascript">$(document).ready(function() { <pre rel="JavaScript"><code class="language-javascript">var Shuffle = window.shuffle;
var $grid = $('#grid'), var element = document.getElementById('grid');
$sizer = $grid.find('.shuffle__sizer'); var sizer = element.querySelector('.my-sizer-element');
$grid.shuffle({ var shuffle = new Shuffle(element, {
itemSelector: '.picture-item', itemSelector: '.picture-item',
sizer: $sizer sizer: sizer // could also be a selector: '.my-sizer-element'
});
});</code></pre> });</code></pre>
</div> </div>

@ -14,12 +14,12 @@ extraJS: [ "demos/homepage.js" ]
<div class="container"> <div class="container">
<div id="grid" class="row shuffle--container shuffle--fluid"> <div id="grid" class="row my-shuffle-container">
{% for item in site.items %} {% for item in site.items %}
{% assign item = item %} {% assign item = item %}
{% include picture-item.html %} {% include picture-item.html %}
{% endfor %} {% endfor %}
<div class="col-1@sm col-1@xs shuffle__sizer"></div> <div class="col-1@sm col-1@xs my-sizer-element"></div>
</div> </div>
</div> </div>

@ -8,13 +8,17 @@ prism: true
--- ---
<div class="container"> <div class="container">
<h2>Using images with Shuffle</h2> <div class="row">
<p>You can encounter problems when shuffle item dimensions depend on images. <a href="{{ site.baseurl }}{% post_url 2013-06-29-image-problems %}">Like this demo</a>. There are three good solutions to this.</p> <div class="col-12@sm">
<ol> <h2>Using images with Shuffle</h2>
<li>Set an explicit height on <code>.shuffle-item</code>s like the <a href="{{ site.baseurl }}{% post_url 2013-05-01-basic %}">basic demo</a>.</li> <p>You can encounter problems when shuffle item dimensions depend on images. <a href="{{ site.baseurl }}{% post_url 2013-06-29-image-problems %}">Like this demo</a>. There are three good solutions to this.</p>
<li>Similar to number 1, make the height of the image container a percentage of the width. If you know the aspect ratio of the images you're using, this is the technique you should use. This demo uses this technique.</li> <ol>
<li>Get notified when images load and call <code>myShuffleInstance.layout()</code>. I recommend using <a href="http://desandro.github.io/imagesloaded/">Desandro's images loaded plugin</a> to know when your images have finished loading.</li> <li>Set an explicit height on <code>.shuffle-item</code>s like the <a href="{{ site.baseurl }}{% post_url 2013-05-01-basic %}">basic demo</a>.</li>
</ol> <li>Similar to number 1, make the height of the image container a percentage of the width. If you know the aspect ratio of the images you're using, this is the technique you should use. This demo uses this technique.</li>
<li>Get notified when images load and call <code>myShuffleInstance.layout()</code>. I recommend using <a href="http://desandro.github.io/imagesloaded/">Desandro's images loaded plugin</a> to know when your images have finished loading.</li>
</ol>
</div>
</div>
</div> </div>

@ -6,9 +6,13 @@ extraJS: [ "demos/images.js"]
--- ---
<div class="container"> <div class="container">
<h2>This probably looks broken.</h2> <div class="row">
<p>In this demo, the height of each item in the grid depends on the image. If Shuffle is initialized before the images load, the heights it calculates will be incorrect. <a href="{{ site.baseurl }}{% post_url 2013-05-03-images %}">See here</a> for a solution.</p> <div class="col-12@sm">
<p>Resize the window and it'll fix itself.</p> <h2>This probably looks broken.</h2>
<p>In this demo, the height of each item in the grid depends on the image. If Shuffle is initialized before the images load, the heights it calculates will be incorrect. <a href="{{ site.baseurl }}{% post_url 2013-05-03-images %}">See here</a> for a solution.</p>
<p>Resize the window and it'll fix itself.</p>
</div>
</div>
</div> </div>

@ -14,7 +14,7 @@ extraJS: [ "viewport.js", "demos/animate-in.js" ]
<div class="container"> <div class="container">
<div id="grid" class="row shuffle--container shuffle--fluid shuffle--animatein"> <div id="grid" class="row my-shuffle-container shuffle--animatein">
{% for item in site.items %} {% for item in site.items %}
{% assign item = item %} {% assign item = item %}
{% include picture-item.html %} {% include picture-item.html %}
@ -27,7 +27,7 @@ extraJS: [ "viewport.js", "demos/animate-in.js" ]
{% assign item = item %} {% assign item = item %}
{% include picture-item.html %} {% include picture-item.html %}
{% endfor %} {% endfor %}
<div class="col-1@sm col-1@xs shuffle__sizer"></div> <div class="col-1@sm col-1@xs my-sizer-element"></div>
</div> </div>
</div> </div>

@ -63,7 +63,7 @@ extraJS: [ "demos/padding-grid.js" ]
<div class="col-xs-12 col-sm-9"> <div class="col-xs-12 col-sm-9">
<div class="row"> <div class="row">
<div id="grid" class="shuffle--container shuffle--fluid"> <div id="grid" class="my-shuffle-container">
{% for i in (1..20) %} {% for i in (1..20) %}
<div class="grid__brick col-xs-6 col-sm-4"> <div class="grid__brick col-xs-6 col-sm-4">
<div class="grid__brick-inner"> <div class="grid__brick-inner">
@ -75,7 +75,7 @@ extraJS: [ "demos/padding-grid.js" ]
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
<div class="col-xs-1 shuffle__sizer"></div> <div class="col-xs-1 my-sizer-element"></div>
</div> </div>
</div> </div>

@ -11,10 +11,14 @@ pagejs: false
--- ---
<div class="container"> <div class="container">
<h2>RequireJS!</h2> <div class="row">
<p> <div class="col-12@sm">
Shuffle uses a UMD wrapper, so it is compatible with AMD loaders like <a href="http://requirejs.org">RequireJS</a>. The UMD wrapper also allows Shuffle to work with CommonJS modules. You can take a peek at the <a href="{{ site.baseurl }}/js/require-main.js">config file</a> used on this page. <h2>RequireJS!</h2>
</p> <p>
Shuffle uses a UMD wrapper, so it is compatible with AMD loaders like <a href="http://requirejs.org">RequireJS</a>. The UMD wrapper also allows Shuffle to work with CommonJS modules. You can take a peek at the <a href="{{ site.baseurl }}/js/require-main.js">config file</a> used on this page.
</p>
</div>
</div>
</div> </div>
@ -34,7 +38,7 @@ pagejs: false
</style> </style>
<div class="container shuffle-wrap"> <div class="container shuffle-wrap">
<div id="grid" class="shuffle--container row"> <div id="grid" class="my-shuffle-container row">
{% for item in site.items %} {% for item in site.items %}
<figure class="js-item img-item col-3@sm col-3@xs"> <figure class="js-item img-item col-3@sm col-3@xs">
<div class="aspect aspect--16x9"> <div class="aspect aspect--16x9">
@ -50,10 +54,12 @@ pagejs: false
</div> </div>
<section> <section class="container">
<div class="container"> <div class="row">
<h2>Shuffle.js</h2> <div class="col-12@sm">
<p>{{ site.longDescription }}</p> <h2>Shuffle.js</h2>
<p>{{ site.longDescription }}</p>
</div>
</div> </div>
</section> </section>

@ -87,8 +87,12 @@
pre { pre {
position: relative; position: relative;
z-index: 1; z-index: 1;
min-height: 56px;
padding-top: 1em;
padding-bottom: 1em;
padding-left: calc(3.5vw + #{($grid-gutter-width / 2)}); padding-left: calc(3.5vw + #{($grid-gutter-width / 2)});
padding-right: calc(3.5vw + #{($grid-gutter-width / 2)}); padding-right: calc(3.5vw + #{($grid-gutter-width / 2)});
margin: .5em 0;
} }
} }

@ -108,12 +108,12 @@ $itemHeight: 220px;
It will set it for you, but it'll cause another style recalculation and layout. It will set it for you, but it'll cause another style recalculation and layout.
AKA worse performance - so just set it here AKA worse performance - so just set it here
*/ */
.shuffle--container { .my-shuffle-container {
position: relative; position: relative;
overflow: hidden; overflow: hidden;
} }
.shuffle--fluid .shuffle__sizer { .my-sizer-element {
position: absolute; position: absolute;
opacity: 0; opacity: 0;
visibility: hidden; visibility: hidden;

@ -76,11 +76,11 @@
It will set it for you, but it'll cause another style recalculation and layout. It will set it for you, but it'll cause another style recalculation and layout.
AKA worse performance - so just set it here AKA worse performance - so just set it here
*/ */
.shuffle--container { .my-shuffle-container {
position: relative; position: relative;
overflow: hidden; } overflow: hidden; }
.shuffle--fluid .shuffle__sizer { .my-sizer-element {
position: absolute; position: absolute;
opacity: 0; opacity: 0;
visibility: hidden; } visibility: hidden; }

@ -997,8 +997,12 @@ h3:hover > a {
.code-block pre { .code-block pre {
position: relative; position: relative;
z-index: 1; z-index: 1;
min-height: 56px;
padding-top: 1em;
padding-bottom: 1em;
padding-left: calc(3.5vw + 8px); padding-left: calc(3.5vw + 8px);
padding-right: calc(3.5vw + 8px); } padding-right: calc(3.5vw + 8px);
margin: .5em 0; }
@media screen and (min-width: 768px) { @media screen and (min-width: 768px) {
.code-block { .code-block {

58
dist/shuffle.js vendored

@ -114,10 +114,6 @@ return /******/ (function(modules) { // webpackBootstrap
} }
} }
function defer(fn, context, wait) {
return setTimeout(fn.bind(context), wait);
}
function arrayMax(array) { function arrayMax(array) {
return Math.max.apply(Math, array); return Math.max.apply(Math, array);
} }
@ -163,7 +159,7 @@ return /******/ (function(modules) { // webpackBootstrap
this.isDestroyed = false; this.isDestroyed = false;
this.isInitialized = false; this.isInitialized = false;
this._transitions = []; this._transitions = [];
this._isMovementCanceled = false; this.isTransitioning = false;
this._queue = []; this._queue = [];
element = this._getElementOption(element); element = this._getElementOption(element);
@ -175,15 +171,8 @@ return /******/ (function(modules) { // webpackBootstrap
this.element = element; this.element = element;
this.id = 'shuffle_' + id++; this.id = 'shuffle_' + id++;
this._dispatch(Shuffle.EventType.LOADING);
this._init(); this._init();
this.isInitialized = true;
// Dispatch the done event asynchronously so that people can bind to it after
// Shuffle has been initialized.
defer(function () {
this.isInitialized = true;
this._dispatch(Shuffle.EventType.DONE);
}, this, 16);
} }
_createClass(Shuffle, [{ _createClass(Shuffle, [{
@ -221,12 +210,13 @@ return /******/ (function(modules) { // webpackBootstrap
// Kick off! // Kick off!
this.filter(this.options.group, this.options.initialSort); this.filter(this.options.group, this.options.initialSort);
// The shuffle items haven't had transitions set on them yet // The shuffle items haven't had transitions set on them yet so the user
// so the user doesn't see the first layout. Set them now that the first layout is done. // doesn't see the first layout. Set them now that the first layout is done.
defer(function () { // First, however, a synchronous layout must be caused for the previous
this._setTransitions(); // styles to be applied without transitions.
this.element.style.transition = 'height ' + this.options.speed + 'ms ' + this.options.easing; this.element.offsetWidth; // jshint ignore: line
}, this); this._setTransitions();
this.element.style.transition = 'height ' + this.options.speed + 'ms ' + this.options.easing;
} }
/** /**
@ -535,16 +525,16 @@ return /******/ (function(modules) { // webpackBootstrap
var size; var size;
// If the columnWidth property is a function, then the grid is fluid // If the columnWidth property is a function, then the grid is fluid
if (typeof this.columnWidth === 'function') { if (typeof this.options.columnWidth === 'function') {
size = this.columnWidth(containerWidth); size = this.options.columnWidth(containerWidth);
// columnWidth option isn't a function, are they using a sizing element? // columnWidth option isn't a function, are they using a sizing element?
} else if (this.useSizer) { } else if (this.useSizer) {
size = Shuffle.getSize(this.options.sizer).width; size = Shuffle.getSize(this.options.sizer).width;
// if not, how about the explicitly set option? // if not, how about the explicitly set option?
} else if (this.columnWidth) { } else if (this.options.columnWidth) {
size = this.columnWidth; size = this.options.columnWidth;
// or use the size of the first item // or use the size of the first item
} else if (this.items.length > 0) { } else if (this.items.length > 0) {
@ -654,6 +644,10 @@ return /******/ (function(modules) { // webpackBootstrap
value: function _dispatch(name) { value: function _dispatch(name) {
var details = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; var details = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
if (this.isDestroyed) {
return;
}
details.shuffle = this; details.shuffle = this;
return !this.element.dispatchEvent(new CustomEvent(name, { return !this.element.dispatchEvent(new CustomEvent(name, {
bubbles: true, bubbles: true,
@ -957,13 +951,12 @@ return /******/ (function(modules) { // webpackBootstrap
key: '_transition', key: '_transition',
value: function _transition(opts) { value: function _transition(opts) {
opts.item.applyCss(this._getStylesForTransition(opts)); opts.item.applyCss(this._getStylesForTransition(opts));
this._whenTransitionDone(opts.item.element, opts.callback); return this._whenTransitionDone(opts.item.element, opts.callback);
} }
/** /**
* Execute the styles gathered in the style queue. This applies styles to elements, * Execute the styles gathered in the style queue. This applies styles to elements,
* triggering transitions. * triggering transitions.
* @param {boolean} withLayout Whether to trigger a layout event.
* @private * @private
*/ */
@ -972,8 +965,6 @@ return /******/ (function(modules) { // webpackBootstrap
value: function _processQueue() { value: function _processQueue() {
var _this6 = this; var _this6 = this;
var withLayout = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0];
if (this.isTransitioning) { if (this.isTransitioning) {
this._cancelMovement(); this._cancelMovement();
} }
@ -996,8 +987,8 @@ return /******/ (function(modules) { // webpackBootstrap
// A call to layout happened, but none of the newly filtered items will // A call to layout happened, but none of the newly filtered items will
// change position. Asynchronously fire the callback here. // change position. Asynchronously fire the callback here.
} else if (withLayout) { } else {
defer(this._dispatchLayout, this); setTimeout(this._dispatchLayout.bind(this), 0);
} }
// Remove everything in the style queue // Remove everything in the style queue
@ -1421,8 +1412,6 @@ return /******/ (function(modules) { // webpackBootstrap
* @enum {string} * @enum {string}
*/ */
Shuffle.EventType = { Shuffle.EventType = {
LOADING: 'shuffle:loading',
DONE: 'shuffle:done',
LAYOUT: 'shuffle:layout', LAYOUT: 'shuffle:layout',
REMOVED: 'shuffle:removed' REMOVED: 'shuffle:removed'
}; };
@ -1444,7 +1433,8 @@ return /******/ (function(modules) { // webpackBootstrap
// e.g. '.picture-item'. // e.g. '.picture-item'.
itemSelector: '*', itemSelector: '*',
// Sizer element. Use an element to determine the size of columns and gutters. // Element or selector string. Use an element to determine the size of columns
// and gutters.
sizer: null, sizer: null,
// A static number or function that tells the plugin how wide the gutters // A static number or function that tells the plugin how wide the gutters
@ -1481,7 +1471,7 @@ return /******/ (function(modules) { // webpackBootstrap
// Transition delay offset for each item in milliseconds. // Transition delay offset for each item in milliseconds.
staggerAmount: 15, staggerAmount: 15,
// It can look a little weird when the last element is in the top row // Maximum stagger delay in milliseconds.
staggerAmountMax: 250, staggerAmountMax: 250,
// Whether to use transforms or absolute positioning. // Whether to use transforms or absolute positioning.
@ -2096,7 +2086,7 @@ return /******/ (function(modules) { // webpackBootstrap
function cancelTransitionEnd(id) { function cancelTransitionEnd(id) {
if (transitions[id]) { if (transitions[id]) {
transitions[id].element.removeEventListener(eventName, transitions[id].listener); transitions[id].element.removeEventListener(eventName, transitions[id].listener);
delete transitions[id]; transitions[id] = null;
return true; return true;
} }

File diff suppressed because one or more lines are too long

@ -70,12 +70,12 @@ prism: true
</div> </div>
<div class="container"> <div class="container">
<div id="grid" class="row shuffle--container shuffle--fluid"> <div id="grid" class="row my-shuffle-container">
{% for item in site.items %} {% for item in site.items %}
{% assign item = item %} {% assign item = item %}
{% include picture-item.html %} {% include picture-item.html %}
{% endfor %} {% endfor %}
<div class="col-1@sm col-1@xs shuffle__sizer"></div> <div class="col-1@sm col-1@xs my-sizer-element"></div>
</div> </div>
</div> </div>
</section> </section>
@ -188,6 +188,8 @@ prism: true
<div class="row"> <div class="row">
<div class="col-12@sm"> <div class="col-12@sm">
<h2>Dependencies<a href="#dependencies"></a></h2> <h2>Dependencies<a href="#dependencies"></a></h2>
<p>Shuffle assumes <code>Promise</code> is available globally. If you care about IE11, use a <a href="https://github.com/stefanpenner/es6-promise">polyfill</a>. <a href="http://caniuse.com/#feat=promises">Current support</a>.</p>
<p>Shuffle's <a href="{{ site.baseurl }}/package.json">other dependencies</a> are bundled with the dist file.</p>
</div> </div>
</div> </div>
</div> </div>
@ -219,11 +221,11 @@ prism: true
<div class="col-12@sm"> <div class="col-12@sm">
<h2>Be Social<a href="#be-social"></a></h2> <h2>Be Social<a href="#be-social"></a></h2>
<div class="text-center"> <div class="text-center">
<iframe src="http://ghbtns.com/github-btn.html?user=Vestride&repo=Shuffle&type=watch&count=true&size=large" height="30" width="170" frameborder="0" scrolling="0" style="width:170px; height: 30px;" allowTransparency="true" seamless></iframe> <iframe src="https://ghbtns.com/github-btn.html?user=Vestride&repo=Shuffle&type=star&size=large" frameborder="0" scrolling="0" width="76px" height="30px"></iframe>
<a href="https://twitter.com/share" class="twitter-share-button" data-url="http://vestride.github.io/Shuffle/" data-via="Vestride" data-size="large">Tweet</a> <a href="https://twitter.com/share" class="twitter-share-button" data-via="Vestride" data-size="large">Tweet</a>
<div class="g-plusone" data-href="http://vestride.github.io/Shuffle/" data-size="standard" data-annotation="bubble"></div> <div class="g-plusone" data-annotation="none"></div>
</div> </div>
</div> </div>
</div> </div>

@ -6,7 +6,7 @@ var Viewport = window.Viewport;
var Demo = function () { var Demo = function () {
this.element = document.getElementById('grid'); this.element = document.getElementById('grid');
this.gridItems = this.element.querySelectorAll('.picture-item'); this.gridItems = this.element.querySelectorAll('.picture-item');
var sizer = this.element.querySelector('.shuffle__sizer'); var sizer = this.element.querySelector('.my-sizer-element');
this.shuffle = new Shuffle(this.element, { this.shuffle = new Shuffle(this.element, {
itemSelector: '.picture-item', itemSelector: '.picture-item',

@ -10,7 +10,7 @@ var Demo = function (element) {
this.shuffle = new Shuffle(element, { this.shuffle = new Shuffle(element, {
itemSelector: '.picture-item', itemSelector: '.picture-item',
sizer: element.querySelector('.shuffle__sizer'), sizer: element.querySelector('.my-sizer-element'),
}); });
this._activeFilters = []; this._activeFilters = [];
@ -44,8 +44,6 @@ Demo.prototype.addShuffleEventListeners = function () {
console.log('type: %s', event.type, 'detail:', event.detail); console.log('type: %s', event.type, 'detail:', event.detail);
}; };
this.element.addEventListener(Shuffle.EventType.LOADING, handler, false);
this.element.addEventListener(Shuffle.EventType.DONE, handler, false);
this.element.addEventListener(Shuffle.EventType.LAYOUT, handler, false); this.element.addEventListener(Shuffle.EventType.LAYOUT, handler, false);
this.element.addEventListener(Shuffle.EventType.REMOVED, handler, false); this.element.addEventListener(Shuffle.EventType.REMOVED, handler, false);
}; };

@ -2,5 +2,5 @@ var Shuffle = window.shuffle;
window.myShuffle = new Shuffle(document.querySelector('.my-grid-with-images'), { window.myShuffle = new Shuffle(document.querySelector('.my-grid-with-images'), {
itemSelector: '.js-item', itemSelector: '.js-item',
sizer: '.shuffle__sizer', sizer: '.my-sizer-element',
}); });

@ -2,5 +2,5 @@
window.demo = new window.shuffle(document.getElementById('grid'), { window.demo = new window.shuffle(document.getElementById('grid'), {
itemSelector: '.grid__brick', itemSelector: '.grid__brick',
sizer: document.querySelector('#grid .shuffle__sizer'), sizer: document.querySelector('#grid .my-sizer-element'),
}); });

@ -27,7 +27,7 @@ export function onTransitionEnd(element, callback) {
export function cancelTransitionEnd(id) { export function cancelTransitionEnd(id) {
if (transitions[id]) { if (transitions[id]) {
transitions[id].element.removeEventListener(eventName, transitions[id].listener); transitions[id].element.removeEventListener(eventName, transitions[id].listener);
delete transitions[id]; transitions[id] = null;
return true; return true;
} }

@ -24,10 +24,6 @@ function each(obj, iterator, context) {
} }
} }
function defer(fn, context, wait) {
return setTimeout(fn.bind(context), wait);
}
function arrayMax(array) { function arrayMax(array) {
return Math.max.apply(Math, array); return Math.max.apply(Math, array);
} }
@ -68,7 +64,7 @@ class Shuffle {
this.isDestroyed = false; this.isDestroyed = false;
this.isInitialized = false; this.isInitialized = false;
this._transitions = []; this._transitions = [];
this._isMovementCanceled = false; this.isTransitioning = false;
this._queue = []; this._queue = [];
element = this._getElementOption(element); element = this._getElementOption(element);
@ -80,15 +76,8 @@ class Shuffle {
this.element = element; this.element = element;
this.id = 'shuffle_' + id++; this.id = 'shuffle_' + id++;
this._dispatch(Shuffle.EventType.LOADING);
this._init(); this._init();
this.isInitialized = true;
// Dispatch the done event asynchronously so that people can bind to it after
// Shuffle has been initialized.
defer(function () {
this.isInitialized = true;
this._dispatch(Shuffle.EventType.DONE);
}, this, 16);
} }
_init() { _init() {
@ -124,12 +113,13 @@ class Shuffle {
// Kick off! // Kick off!
this.filter(this.options.group, this.options.initialSort); this.filter(this.options.group, this.options.initialSort);
// The shuffle items haven't had transitions set on them yet // The shuffle items haven't had transitions set on them yet so the user
// so the user doesn't see the first layout. Set them now that the first layout is done. // doesn't see the first layout. Set them now that the first layout is done.
defer(function () { // First, however, a synchronous layout must be caused for the previous
this._setTransitions(); // styles to be applied without transitions.
this.element.style.transition = 'height ' + this.options.speed + 'ms ' + this.options.easing; this.element.offsetWidth; // jshint ignore: line
}, this); this._setTransitions();
this.element.style.transition = 'height ' + this.options.speed + 'ms ' + this.options.easing;
} }
/** /**
@ -381,16 +371,16 @@ class Shuffle {
var size; var size;
// If the columnWidth property is a function, then the grid is fluid // If the columnWidth property is a function, then the grid is fluid
if (typeof this.columnWidth === 'function') { if (typeof this.options.columnWidth === 'function') {
size = this.columnWidth(containerWidth); size = this.options.columnWidth(containerWidth);
// columnWidth option isn't a function, are they using a sizing element? // columnWidth option isn't a function, are they using a sizing element?
} else if (this.useSizer) { } else if (this.useSizer) {
size = Shuffle.getSize(this.options.sizer).width; size = Shuffle.getSize(this.options.sizer).width;
// if not, how about the explicitly set option? // if not, how about the explicitly set option?
} else if (this.columnWidth) { } else if (this.options.columnWidth) {
size = this.columnWidth; size = this.options.columnWidth;
// or use the size of the first item // or use the size of the first item
} else if (this.items.length > 0) { } else if (this.items.length > 0) {
@ -479,6 +469,10 @@ class Shuffle {
* @return {boolean} Whether the event was prevented or not. * @return {boolean} Whether the event was prevented or not.
*/ */
_dispatch(name, details = {}) { _dispatch(name, details = {}) {
if (this.isDestroyed) {
return;
}
details.shuffle = this; details.shuffle = this;
return !this.element.dispatchEvent(new CustomEvent(name, { return !this.element.dispatchEvent(new CustomEvent(name, {
bubbles: true, bubbles: true,
@ -747,16 +741,15 @@ class Shuffle {
_transition(opts) { _transition(opts) {
opts.item.applyCss(this._getStylesForTransition(opts)); opts.item.applyCss(this._getStylesForTransition(opts));
this._whenTransitionDone(opts.item.element, opts.callback); return this._whenTransitionDone(opts.item.element, opts.callback);
} }
/** /**
* Execute the styles gathered in the style queue. This applies styles to elements, * Execute the styles gathered in the style queue. This applies styles to elements,
* triggering transitions. * triggering transitions.
* @param {boolean} withLayout Whether to trigger a layout event.
* @private * @private
*/ */
_processQueue(withLayout = true) { _processQueue() {
if (this.isTransitioning) { if (this.isTransitioning) {
this._cancelMovement(); this._cancelMovement();
} }
@ -779,8 +772,8 @@ class Shuffle {
// A call to layout happened, but none of the newly filtered items will // A call to layout happened, but none of the newly filtered items will
// change position. Asynchronously fire the callback here. // change position. Asynchronously fire the callback here.
} else if (withLayout) { } else {
defer(this._dispatchLayout, this); setTimeout(this._dispatchLayout.bind(this), 0);
} }
// Remove everything in the style queue // Remove everything in the style queue
@ -1138,8 +1131,6 @@ Shuffle.FILTER_ATTRIBUTE_KEY = 'groups';
* @enum {string} * @enum {string}
*/ */
Shuffle.EventType = { Shuffle.EventType = {
LOADING: 'shuffle:loading',
DONE: 'shuffle:done',
LAYOUT: 'shuffle:layout', LAYOUT: 'shuffle:layout',
REMOVED: 'shuffle:removed', REMOVED: 'shuffle:removed',
}; };
@ -1161,7 +1152,8 @@ Shuffle.options = {
// e.g. '.picture-item'. // e.g. '.picture-item'.
itemSelector: '*', itemSelector: '*',
// Sizer element. Use an element to determine the size of columns and gutters. // Element or selector string. Use an element to determine the size of columns
// and gutters.
sizer: null, sizer: null,
// A static number or function that tells the plugin how wide the gutters // A static number or function that tells the plugin how wide the gutters
@ -1198,7 +1190,7 @@ Shuffle.options = {
// Transition delay offset for each item in milliseconds. // Transition delay offset for each item in milliseconds.
staggerAmount: 15, staggerAmount: 15,
// It can look a little weird when the last element is in the top row // Maximum stagger delay in milliseconds.
staggerAmountMax: 250, staggerAmountMax: 250,
// Whether to use transforms or absolute positioning. // Whether to use transforms or absolute positioning.

@ -49,7 +49,7 @@ describe('shuffle', function () {
} }
} }
function cleanup() { function removeFixture() {
if (instance && instance.element) { if (instance && instance.element) {
instance.destroy(); instance.destroy();
} }
@ -62,19 +62,6 @@ describe('shuffle', function () {
fixture = null; fixture = null;
} }
function removeFixture(done) {
if (!instance || instance.isInitialized) {
cleanup();
done();
} else {
instance.element.addEventListener(Shuffle.EventType.DONE, function onDone() {
instance.element.removeEventListener(Shuffle.EventType.DONE, onDone);
cleanup();
done();
});
}
}
function once(element, eventType, fn) { function once(element, eventType, fn) {
var handler = function (e) { var handler = function (e) {
element.removeEventListener(eventType, handler); element.removeEventListener(eventType, handler);
@ -103,12 +90,12 @@ describe('shuffle', function () {
appendFixture('regular').then(done); appendFixture('regular').then(done);
}); });
afterEach(function (done) { afterEach(function () {
removeFixture(done);
Shuffle.prototype._whenTransitionDone.restore(); Shuffle.prototype._whenTransitionDone.restore();
removeFixture();
}); });
it('should have default options', function (done) { it('should have default options', function () {
instance = new Shuffle(fixture); instance = new Shuffle(fixture);
expect(instance.items.length).to.equal(10); expect(instance.items.length).to.equal(10);
expect(instance.visibleItems).to.equal(10); expect(instance.visibleItems).to.equal(10);
@ -124,12 +111,7 @@ describe('shuffle', function () {
expect(instance.useSizer).to.equal(false); expect(instance.useSizer).to.equal(false);
expect(instance.id).to.equal('shuffle_0'); expect(instance.id).to.equal('shuffle_0');
expect(instance.isInitialized).to.be.false; expect(instance.isInitialized).to.be.true;
instance.element.addEventListener(Shuffle.EventType.DONE, function onDone() {
instance.element.removeEventListener(Shuffle.EventType.DONE, onDone);
expect(instance.isInitialized).to.be.true;
done();
});
}); });
it('should add classes and default styles', function () { it('should add classes and default styles', function () {
@ -233,11 +215,6 @@ describe('shuffle', function () {
speed: 0, speed: 0,
}); });
function first() {
once(fixture, Shuffle.EventType.LAYOUT, second);
instance.filter('design');
}
function second() { function second() {
expect(instance.visibleItems).to.equal(3); expect(instance.visibleItems).to.equal(3);
var concealed = [3, 4, 5, 6, 7, 8, 10].map(function (num) { var concealed = [3, 4, 5, 6, 7, 8, 10].map(function (num) {
@ -287,7 +264,8 @@ describe('shuffle', function () {
done(); done();
} }
once(fixture, Shuffle.EventType.DONE, first); once(fixture, Shuffle.EventType.LAYOUT, second);
instance.filter('design');
}); });
it('can initialize filtered and the category parameter is optional', function () { it('can initialize filtered and the category parameter is optional', function () {
@ -314,159 +292,146 @@ describe('shuffle', function () {
expect(instance.lastSort).to.deep.equal(sortObj); expect(instance.lastSort).to.deep.equal(sortObj);
}); });
describe('after initialized', function () { it('can calculate column spans', function () {
var clock; instance = new Shuffle(fixture);
expect(instance._getColumnSpan(50, 100, 3)).to.equal(1);
beforeEach(function () { expect(instance._getColumnSpan(200, 100, 3)).to.equal(2);
clock = sinon.useFakeTimers(); expect(instance._getColumnSpan(200, 200, 3)).to.equal(1);
instance = new Shuffle(fixture); expect(instance._getColumnSpan(300, 100, 3)).to.equal(3);
clock.tick(17);
expect(instance.isInitialized).to.be.true;
});
afterEach(function () {
clock.restore();
});
it('can calculate column spans', function () { // Column span should not be larger than the number of columns.
expect(instance._getColumnSpan(50, 100, 3)).to.equal(1); expect(instance._getColumnSpan(300, 50, 3)).to.equal(3);
expect(instance._getColumnSpan(200, 100, 3)).to.equal(2);
expect(instance._getColumnSpan(200, 200, 3)).to.equal(1);
expect(instance._getColumnSpan(300, 100, 3)).to.equal(3);
// Column span should not be larger than the number of columns. // Fix for percentage values.
expect(instance._getColumnSpan(300, 50, 3)).to.equal(3); expect(instance._getColumnSpan(100.02, 100, 4)).to.equal(1);
expect(instance._getColumnSpan(99.98, 100, 4)).to.equal(1);
});
// Fix for percentage values. it('can calculate column sets', function () {
expect(instance._getColumnSpan(100.02, 100, 4)).to.equal(1); instance = new Shuffle(fixture);
expect(instance._getColumnSpan(99.98, 100, 4)).to.equal(1);
});
it('can calculate column sets', function () { // _getColumnSet(columnSpan, columns)
// _getColumnSet(columnSpan, columns) instance.positions = [150, 0, 0, 0];
instance.positions = [150, 0, 0, 0]; expect(instance._getColumnSet(1, 4)).to.deep.equal([150, 0, 0, 0]);
expect(instance._getColumnSet(1, 4)).to.deep.equal([150, 0, 0, 0]); expect(instance._getColumnSet(2, 4)).to.deep.equal([150, 0, 0]);
expect(instance._getColumnSet(2, 4)).to.deep.equal([150, 0, 0]); });
});
it('can get an element option', function () { it('can get an element option', function () {
var first = fixture.firstElementChild; instance = new Shuffle(fixture);
var first = fixture.firstElementChild;
expect(instance._getElementOption(first)).to.equal(first);
expect(instance._getElementOption('#item1')).to.equal(first); expect(instance._getElementOption(first)).to.equal(first);
expect(instance._getElementOption('#hello-world')).to.be.null; expect(instance._getElementOption('#item1')).to.equal(first);
expect(instance._getElementOption(null)).to.be.null; expect(instance._getElementOption('#hello-world')).to.be.null;
expect(instance._getElementOption(undefined)).to.be.null; expect(instance._getElementOption(null)).to.be.null;
expect(instance._getElementOption(function () { expect(instance._getElementOption(undefined)).to.be.null;
return first; expect(instance._getElementOption(function () {
})).to.be.null; return first;
}); })).to.be.null;
});
it('can test elements against filters', function () { it('can test elements against filters', function () {
instance = new Shuffle(fixture);
var first = fixture.firstElementChild; var first = fixture.firstElementChild;
expect(instance._doesPassFilter('design', first)).to.be.true; expect(instance._doesPassFilter('design', first)).to.be.true;
expect(instance._doesPassFilter('black', first)).to.be.false; expect(instance._doesPassFilter('black', first)).to.be.false;
expect(instance._doesPassFilter(function (element) { expect(instance._doesPassFilter(function (element) {
expect(element).to.exist; expect(element).to.exist;
return element.getAttribute('data-age') === '21'; return element.getAttribute('data-age') === '21';
}, first)).to.equal(true); }, first)).to.equal(true);
expect(instance._doesPassFilter(function (element) { expect(instance._doesPassFilter(function (element) {
return element.getAttribute('data-age') === '22'; return element.getAttribute('data-age') === '22';
}, first)).to.equal(false); }, first)).to.equal(false);
}); });
it('will maintain the last sort object', function () { it('will maintain the last sort object', function () {
var initialSort = instance.lastSort; instance = new Shuffle(fixture);
var initialSort = instance.lastSort;
instance.sort(); instance.sort();
expect(instance.lastSort).to.deep.equal(initialSort); expect(instance.lastSort).to.deep.equal(initialSort);
instance.sort({ glen: true }); instance.sort({ glen: true });
expect(instance.lastSort).to.deep.equal({ glen: true }); expect(instance.lastSort).to.deep.equal({ glen: true });
instance.sort(); instance.sort();
expect(instance.lastSort).to.deep.equal({ glen: true }); expect(instance.lastSort).to.deep.equal({ glen: true });
}); });
it('should reset columns', function () { it('should reset columns', function () {
instance = new Shuffle(fixture);
expect(instance.cols).to.be.above(0); expect(instance.cols).to.be.above(0);
instance._resetCols(); instance._resetCols();
var positions = new Array(instance.cols); var positions = new Array(instance.cols);
for (var i = 0; i < instance.cols; i++) { for (var i = 0; i < instance.cols; i++) {
positions[i] = 0; positions[i] = 0;
} }
expect(instance.positions).to.deep.equal(positions); expect(instance.positions).to.deep.equal(positions);
}); });
it('should destroy properly', function () { it('should destroy properly', function () {
instance.destroy(); instance = new Shuffle(fixture);
instance.destroy();
expect(instance.element).to.be.null; expect(instance.element).to.be.null;
expect(instance.items).to.be.null; expect(instance.items).to.be.null;
expect(instance.options.sizer).to.be.null; expect(instance.options.sizer).to.be.null;
expect(instance.isDestroyed).to.be.true; expect(instance.isDestroyed).to.be.true;
expect(fixture).to.not.have.class('shuffle'); expect(fixture).to.not.have.class('shuffle');
toArray(fixture.children).forEach(function (child) { toArray(fixture.children).forEach(function (child) {
expect(child).to.not.have.class('shuffle-item'); expect(child).to.not.have.class('shuffle-item');
expect(child).to.not.have.class('filtered'); expect(child).to.not.have.class('filtered');
expect(child).to.not.have.class('concealed'); expect(child).to.not.have.class('concealed');
});
}); });
});
it('should not update or shuffle when disabled or destroyed', function () { it('should not update or shuffle when disabled or destroyed', function () {
var update = sinon.spy(instance, 'update'); instance = new Shuffle(fixture);
var _filter = sinon.spy(instance, '_filter'); var update = sinon.spy(instance, 'update');
var _filter = sinon.spy(instance, '_filter');
instance.disable(); instance.disable();
instance.filter('design'); instance.filter('design');
expect(_filter.called).to.be.false; expect(_filter.called).to.be.false;
expect(update.called).to.be.false; expect(update.called).to.be.false;
instance.enable(false); instance.enable(false);
instance.destroy(); instance.destroy();
instance._onResize(); instance._onResize();
expect(update.called).to.be.false; expect(update.called).to.be.false;
}); });
it('should not update when the container is the same size', function () { it('should not update when the container is the same size', function () {
var update = sinon.spy(instance, 'update'); instance = new Shuffle(fixture);
var update = sinon.spy(instance, 'update');
instance._onResize(); instance._onResize();
expect(update.called).to.be.false; expect(update.called).to.be.false;
});
}); });
describe('removing elements', function () { describe('removing elements', function () {
var itemsToRemove; var itemsToRemove;
var onDone;
var onRemoved;
beforeEach(function () { beforeEach(function () {
var children = toArray(fixture.children); var children = toArray(fixture.children);
itemsToRemove = children.slice(0, 2); itemsToRemove = children.slice(0, 2);
onDone = function () {
once(fixture, Shuffle.EventType.REMOVED, onRemoved);
instance.remove(itemsToRemove);
};
}); });
afterEach(function () { afterEach(function () {
itemsToRemove = null; itemsToRemove = null;
onDone = null;
onRemoved = null;
}); });
it('can remove items', function (done) { it('can remove items', function (done) {
@ -474,17 +439,20 @@ describe('shuffle', function () {
speed: 16, speed: 16,
}); });
onRemoved = function (evt) { once(fixture, Shuffle.EventType.REMOVED, function (evt) {
var detail = evt.detail; var detail = evt.detail;
expect(detail.shuffle.visibleItems).to.equal(8); expect(detail.shuffle.visibleItems).to.equal(8);
expect(detail.collection[0].id).to.equal('item1'); expect(detail.collection[0].id).to.equal('item1');
expect(detail.collection[1].id).to.equal('item2'); expect(detail.collection[1].id).to.equal('item2');
expect(detail.shuffle.element.children).to.have.lengthOf(8); expect(detail.shuffle.element.children).to.have.lengthOf(8);
expect(instance.isTransitioning).to.equal(false); expect(instance.isTransitioning).to.equal(false);
done();
};
once(fixture, Shuffle.EventType.DONE, onDone); once(fixture, Shuffle.EventType.LAYOUT, function () {
done();
});
});
instance.remove(itemsToRemove);
}); });
it('can remove items without transforms', function (done) { it('can remove items without transforms', function (done) {
@ -493,17 +461,20 @@ describe('shuffle', function () {
useTransforms: false, useTransforms: false,
}); });
onRemoved = function (evt) { once(fixture, Shuffle.EventType.REMOVED, function (evt) {
var detail = evt.detail; var detail = evt.detail;
expect(detail.shuffle.visibleItems).to.equal(8); expect(detail.shuffle.visibleItems).to.equal(8);
expect(detail.collection[0].id).to.equal('item1'); expect(detail.collection[0].id).to.equal('item1');
expect(detail.collection[1].id).to.equal('item2'); expect(detail.collection[1].id).to.equal('item2');
expect(detail.shuffle.element.children).to.have.lengthOf(8); expect(detail.shuffle.element.children).to.have.lengthOf(8);
expect(detail.shuffle.isTransitioning).to.equal(false); expect(detail.shuffle.isTransitioning).to.equal(false);
done();
};
once(fixture, Shuffle.EventType.DONE, onDone); once(fixture, Shuffle.EventType.LAYOUT, function () {
done();
});
});
instance.remove(itemsToRemove);
}); });
}); });
@ -535,7 +506,6 @@ describe('shuffle', function () {
}); });
describe('inserting elements', function () { describe('inserting elements', function () {
var clock;
var items = []; var items = [];
beforeEach(function () { beforeEach(function () {
@ -555,18 +525,14 @@ describe('shuffle', function () {
items.push(eleven, twelve); items.push(eleven, twelve);
clock = sinon.useFakeTimers();
instance = new Shuffle(fixture, { instance = new Shuffle(fixture, {
speed: 100, speed: 100,
group: 'black', group: 'black',
}); });
clock.tick(17);
expect(instance.isInitialized).to.be.true;
}); });
afterEach(function (done) { afterEach(function (done) {
once(fixture, Shuffle.EventType.LAYOUT, function () { once(fixture, Shuffle.EventType.LAYOUT, function () {
clock.restore();
items.length = 0; items.length = 0;
done(); done();
}); });
@ -611,10 +577,10 @@ describe('shuffle', function () {
}); });
}); });
afterEach(function (done) { afterEach(function () {
items.length = 0; items.length = 0;
clone.length = 0; clone.length = 0;
removeFixture(done); removeFixture();
}); });
it('will catch empty objects', function () { it('will catch empty objects', function () {

Loading…
Cancel
Save