Add sortedItems prop, fix Chrome bug (#351)

pull/353/head
Glen Cheney 3 years ago committed by GitHub
parent 19875b85b8
commit 9f79d9f441
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,5 +1,5 @@
module.exports = {
extends: 'airbnb-base',
extends: ['airbnb-base', 'prettier'],
env: {
node: true,
browser: true,

20
dist/shuffle.js vendored

@ -105,6 +105,8 @@
};
}
var tinyEmitter = {exports: {}};
function E () {
// Keep this empty so it's easier to inherit from
// (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)
@ -169,9 +171,10 @@
}
};
var tinyEmitter = E;
var TinyEmitter = E;
tinyEmitter.TinyEmitter = TinyEmitter;
tinyEmitter.exports = E;
tinyEmitter.exports.TinyEmitter = E;
var TinyEmitter = tinyEmitter.exports;
var proto = typeof Element !== 'undefined' ? Element.prototype : {};
var vendor = proto.matches
@ -510,7 +513,12 @@
var e = document.createElement('div');
e.style.cssText = 'width:10px;padding:2px;box-sizing:border-box;';
element.appendChild(e);
value = window.getComputedStyle(e, null).width === '10px';
var _window$getComputedSt = window.getComputedStyle(e, null),
width = _window$getComputedSt.width; // Fix for issue #314
value = Math.round(getNumber(width)) === 10;
element.removeChild(e);
return value;
});
@ -973,6 +981,7 @@
key: "_init",
value: function _init() {
this.items = this._getItems();
this.sortedItems = this.items;
this.options.sizer = this._getElementOption(this.options.sizer); // Add class and invalidate styles
this.element.classList.add(Shuffle.Classes.BASE); // Set initial css for each item
@ -1815,6 +1824,7 @@
this._resetCols();
var items = sorter(this._getFilteredItems(), sortOptions);
this.sortedItems = items;
this._layout(items); // `_layout` always happens after `_shrink`, so it's safe to process the style
// queue here with styles from the shrink method.
@ -2151,7 +2161,7 @@
}]);
return Shuffle;
}(tinyEmitter);
}(TinyEmitter);
Shuffle.ShuffleItem = ShuffleItem;
Shuffle.ALL_ITEMS = 'all';

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,42 +1,100 @@
<h2>Changelog<a href="#changelog"></a></h2>
<p>For a more detailed changelog, visit <a href="https://github.com/Vestride/Shuffle/releases">the latest releases</a> on GitHub.</p>
<p>
For a more detailed changelog, visit <a href="https://github.com/Vestride/Shuffle/releases">the latest releases</a> on
GitHub.
</p>
<ul>
<li>
<code>v5.4.0</code> 2021-05-29 - Add <code>sortedItems</code> property. Fix <code>getComputedStyle</code> bug for
Chrome on Windows.
</li>
<li><code>v5.3.0</code> 2021-03-23 - Add <code>isRTL</code> option.</li>
<li><code>v5.2.3</code> 2019-08-29 - Add missing inherited methods from <code>TinyEmitter</code> to TypeScript definitions.</li>
<li>
<code>v5.2.3</code> 2019-08-29 - Add missing inherited methods from <code>TinyEmitter</code> to TypeScript
definitions.
</li>
<li><code>v5.2.2</code> 2019-06-03 - Update TypeScript definitions.</li>
<li><code>v5.2.1</code> 2018-12-01 - Change `index.d.ts` to use `export default Shuffle` (<a href="https://github.com/Vestride/Shuffle/issues/214#issuecomment-441409237">#214</a>). Upgrade dev dependencies.</li>
<li><code>v5.2.0</code> 2018-08-19 - Lazily test whether the browser's <code>getComputedStyle</code> includes padding. This allows the bundled file to be imported in node for server side rendering.</li>
<li><code>v5.1.2</code> 2018-03-26 - Fix misspelled <code>delimiter</code> option. Both "delimiter" and "delimeter" will continue to work for v5.</li>
<li>
<code>v5.2.1</code> 2018-12-01 - Change `index.d.ts` to use `export default Shuffle` (<a
href="https://github.com/Vestride/Shuffle/issues/214#issuecomment-441409237"
>#214</a
>). Upgrade dev dependencies.
</li>
<li>
<code>v5.2.0</code> 2018-08-19 - Lazily test whether the browser's <code>getComputedStyle</code> includes padding.
This allows the bundled file to be imported in node for server side rendering.
</li>
<li>
<code>v5.1.2</code> 2018-03-26 - Fix misspelled <code>delimiter</code> option. Both "delimiter" and "delimeter" will
continue to work for v5.
</li>
<li><code>v5.1.1</code> 2018-03-02 - Fix new item animation when there is an active filter.</li>
<li><code>v5.1.0</code> 2018-02-20 - Add <code>compare</code> option to sorter. Add <code>es</code> build to package and <code>"module"</code> field to <code>package.json</code>.</li>
<li>
<code>v5.1.0</code> 2018-02-20 - Add <code>compare</code> option to sorter. Add <code>es</code> build to package and
<code>"module"</code> field to <code>package.json</code>.
</li>
<li><code>v5.0.3</code> 2017-10-30 - Fix rounding error.</li>
<li><code>v5.0.2</code> 2017-09-23 - Update type definitions. Upgrade dev dependencies.</li>
<li><code>v5.0.1</code> 2017-07-18 - Add <code>roundTransforms</code> option.</li>
<li><code>v5.0.0</code> 2017-07-18 - Change global export from <code>shuffle</code> to <code>Shuffle</code>. Remove bower support. Expect ES6 environment. Make Shuffle instances Event Emitters instead of dispatching <code>CustomEvent</code>.</li>
<li><code>v4.2.0</code> 2017-05-10 - Replace <code>webpack</code> build with <code>rollup</code>. Replace <code>jshint</code> and <code>jscs</code> with <code>eslint</code>. Add <code>filterMode</code> option.</li>
<li><code>v4.1.1</code> 2017-03-21 - the <code>before</code> styles for a <code>ShuffleItem</code> were not applied if the item didn&rsquo;t move.</li>
<li>
<code>v5.0.0</code> 2017-07-18 - Change global export from <code>shuffle</code> to <code>Shuffle</code>. Remove
bower support. Expect ES6 environment. Make Shuffle instances Event Emitters instead of dispatching
<code>CustomEvent</code>.
</li>
<li>
<code>v4.2.0</code> 2017-05-10 - Replace <code>webpack</code> build with <code>rollup</code>. Replace
<code>jshint</code> and <code>jscs</code> with <code>eslint</code>. Add <code>filterMode</code> option.
</li>
<li>
<code>v4.1.1</code> 2017-03-21 - the <code>before</code> styles for a <code>ShuffleItem</code> were not applied if
the item didn&rsquo;t move.
</li>
<li><code>v4.1.0</code> 2017-01-30 - Use webpack-2 to bundle Shuffle.</li>
<li><code>v4.0.2</code> 2016-09-15 - Update <code>custom-event-polyfill</code> dependency.</li>
<li><code>v4.0.1</code> 2016-07-30 - Fix <code>delimiter</code> option.</li>
<li><code>v4.0.0</code> 2016-04-20 - Rewrite in ES6 with babel. Remove jQuery and Modernizr dependencies. Remove support for IE&lt;11. Docs improvements. Switch to gulp build system with webpack.</li>
<li><code>v3.1.0</code> 2015-03-23 - Allow zero speed option (<a href="https://github.com/Vestride/Shuffle/issues/64">#64</a>) and cancel previous animations instead of ignoring new ones (<a href="https://github.com/Vestride/Shuffle/issues/69">#69</a>). Handle non-integer columns better (<a href="https://github.com/Vestride/Shuffle/issues/46">#46</a>)</li>
<li>
<code>v4.0.0</code> 2016-04-20 - Rewrite in ES6 with babel. Remove jQuery and Modernizr dependencies. Remove support
for IE&lt;11. Docs improvements. Switch to gulp build system with webpack.
</li>
<li>
<code>v3.1.0</code> 2015-03-23 - Allow zero speed option (<a href="https://github.com/Vestride/Shuffle/issues/64"
>#64</a
>) and cancel previous animations instead of ignoring new ones (<a
href="https://github.com/Vestride/Shuffle/issues/69"
>#69</a
>). Handle non-integer columns better (<a href="https://github.com/Vestride/Shuffle/issues/46">#46</a>)
</li>
<li><code>v3.0.4</code> 2015-02-16 - Publish to NPM.</li>
<li><code>v3.0.2</code> 2015-01-21 - Remove from jQuery plugins directory.</li>
<li><code>v3.0.1</code> 2014-12-29 - Add CommonJS support.</li>
<li><code>v3.0.0</code> 2014-10-06 - Refactored with improvements, added unit tests, more documentation. Removed some triggered events.</li>
<li><code>v2.1.2</code> 2014-06-01 - Use <code>window.jQuery</code> instead of <code>window.$</code> to work better with noConflict. Fixed <a href="https://github.com/Vestride/Shuffle/issues/25">#25</a>.</li>
<li>
<code>v3.0.0</code> 2014-10-06 - Refactored with improvements, added unit tests, more documentation. Removed some
triggered events.
</li>
<li>
<code>v2.1.2</code> 2014-06-01 - Use <code>window.jQuery</code> instead of <code>window.$</code> to work better with
noConflict. Fixed <a href="https://github.com/Vestride/Shuffle/issues/25">#25</a>.
</li>
<li><code>v2.1.1</code> 2014-04-16 - Fix items with zero opacity overlapping visible ones in IE&lt;10.</li>
<li><code>v2.1.0</code> 2014-04-12 - Register with bower as <code>shufflejs</code>.</li>
<li>2014-04-10 - Add AMD support.</li>
<li>2014-04-08 - Separate Modernizr into its own file and custom Shuffle build.</li>
<li>2014-03-08 - Add Bootstrap 3 demo. Fixed issue with percentage width items.</li>
<li>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.</li>
<li>
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.
</li>
<li>2013-08-30 - Added animate-in demo.</li>
<li><code>v2.0.0</code> 2013-07-05 - Shuffle 2.0 with masonry, adding and removing, and more.</li>
<li>2012-11-03 - Replaced layout system with <a href="http://masonry.desandro.com/">masonry</a>. Items can now be different sizes! Added addtional examples.</li>
<li>
2012-11-03 - Replaced layout system with <a href="http://masonry.desandro.com/">masonry</a>. Items can now be
different sizes! Added addtional examples.
</li>
<li>2012-10-24 - Better handling of grid item dimensions. Added a minimal markup page.</li>
<li>2012-09-20 - Added <code>destroy</code> method</li>
<li>2012-09-18 - Added sorting ability and made plugin responsive. Updated to Modernizr 2.6.2</li>
<li>2012-07-21 - Rewrote plugin in more object oriented structure. Added custom events. Updated to Modernizr 2.6.1</li>
<li>
2012-07-21 - Rewrote plugin in more object oriented structure. Added custom events. Updated to Modernizr 2.6.1
</li>
<li>2012-07-03 - Removed dependency on the css file and now apply the css with javascript</li>
</ul>

@ -1 +1 @@
.picture-item{height:220px;margin-top:24px;margin-left:0}.picture-item img{display:block;width:100%}@supports ((-o-object-fit: cover) or (object-fit: cover)){.picture-item img{max-width:none;height:100%;-o-object-fit:cover;object-fit:cover}}.picture-item--h2{height:464px}.picture-item__inner{position:relative;height:100%;overflow:hidden;background:#ecf0f1}img.picture-item__blur{display:none}.picture-item__details{display:flex;align-items:baseline;justify-content:space-between;width:100%;padding:1em}.picture-item__description{width:100%;padding:0 2em 1em 1em;margin:0}.picture-item__title{flex-shrink:0;margin-right:4px}.picture-item__tags{flex-shrink:1;text-align:right;margin:0}@media screen and (min-width:768px){.picture-item--overlay .picture-item__details{position:absolute;bottom:0;left:0;width:100%;background-color:rgba(0,0,0,.6);color:#fff;overflow:hidden}.picture-item--overlay .picture-item__description{display:none}@supports (filter:blur(1px)) and ((-webkit-clip-path: inset(0 0 0 0)) or (clip-path: inset(0 0 0 0))){.picture-item--overlay .picture-item__blur{position:absolute;z-index:1;top:0;left:0;display:block;filter:blur(7px);-webkit-clip-path:inset(170px 0 0 0);clip-path:inset(170px 0 0 0)}.picture-item--overlay .picture-item__details{background:none}.picture-item--overlay .picture-item__tags,.picture-item--overlay .picture-item__title{position:relative;z-index:2}}}.my-shuffle-container{position:relative;overflow:hidden}.my-sizer-element{position:absolute;opacity:0;visibility:hidden}.shuffle--animatein{overflow:visible}.shuffle--animatein .picture-item__inner{opacity:0;transform:translateY(220px)}.shuffle--animatein .picture-item__inner--transition{transition:all .6s ease}.shuffle--animatein .picture-item.in .picture-item__inner{opacity:1;transform:translate(0)}@media screen and (max-width:767px){.picture-item{height:auto;margin-top:20px}.picture-item__description,.picture-item__details{font-size:.875em;padding:.625em}.picture-item__description{padding-right:.875em;padding-bottom:1.25em}.picture-item--h2{height:auto}}
.picture-item{height:220px;margin-left:0;margin-top:24px}.picture-item img{display:block;width:100%}@supports ((-o-object-fit:cover) or (object-fit:cover)){.picture-item img{height:100%;max-width:none;-o-object-fit:cover;object-fit:cover}}.picture-item--h2{height:464px}.picture-item__inner{background:#ecf0f1;height:100%;overflow:hidden;position:relative}img.picture-item__blur{display:none}.picture-item__details{align-items:baseline;display:flex;justify-content:space-between;padding:1em;width:100%}.picture-item__description{margin:0;padding:0 2em 1em 1em;width:100%}.picture-item__title{flex-shrink:0;margin-right:4px}.picture-item__tags{flex-shrink:1;margin:0;text-align:right}@media screen and (min-width:768px){.picture-item--overlay .picture-item__details{background-color:rgba(0,0,0,.6);bottom:0;color:#fff;left:0;overflow:hidden;position:absolute;width:100%}.picture-item--overlay .picture-item__description{display:none}@supports (filter:blur(1px)) and ((-webkit-clip-path:inset(0 0 0 0)) or (clip-path:inset(0 0 0 0))){.picture-item--overlay .picture-item__blur{-webkit-clip-path:inset(170px 0 0 0);clip-path:inset(170px 0 0 0);display:block;filter:blur(7px);left:0;position:absolute;top:0;z-index:1}.picture-item--overlay .picture-item__details{background:none}.picture-item--overlay .picture-item__tags,.picture-item--overlay .picture-item__title{position:relative;z-index:2}}}.my-shuffle-container{overflow:hidden;position:relative}.my-sizer-element{opacity:0;position:absolute;visibility:hidden}.shuffle--animatein{overflow:visible}.shuffle--animatein .picture-item__inner{opacity:0;transform:translateY(220px)}.shuffle--animatein .picture-item__inner--transition{transition:all .6s ease}.shuffle--animatein .picture-item.in .picture-item__inner{opacity:1;transform:translate(0)}@media screen and (max-width:767px){.picture-item{height:auto;margin-top:20px}.picture-item__description,.picture-item__details{font-size:.875em;padding:.625em}.picture-item__description{padding-bottom:1.25em;padding-right:.875em}.picture-item--h2{height:auto}}

File diff suppressed because one or more lines are too long

@ -105,6 +105,8 @@
};
}
var tinyEmitter = {exports: {}};
function E () {
// Keep this empty so it's easier to inherit from
// (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)
@ -169,9 +171,10 @@
}
};
var tinyEmitter = E;
var TinyEmitter = E;
tinyEmitter.TinyEmitter = TinyEmitter;
tinyEmitter.exports = E;
tinyEmitter.exports.TinyEmitter = E;
var TinyEmitter = tinyEmitter.exports;
var proto = typeof Element !== 'undefined' ? Element.prototype : {};
var vendor = proto.matches
@ -510,7 +513,12 @@
var e = document.createElement('div');
e.style.cssText = 'width:10px;padding:2px;box-sizing:border-box;';
element.appendChild(e);
value = window.getComputedStyle(e, null).width === '10px';
var _window$getComputedSt = window.getComputedStyle(e, null),
width = _window$getComputedSt.width; // Fix for issue #314
value = Math.round(getNumber(width)) === 10;
element.removeChild(e);
return value;
});
@ -973,6 +981,7 @@
key: "_init",
value: function _init() {
this.items = this._getItems();
this.sortedItems = this.items;
this.options.sizer = this._getElementOption(this.options.sizer); // Add class and invalidate styles
this.element.classList.add(Shuffle.Classes.BASE); // Set initial css for each item
@ -1815,6 +1824,7 @@
this._resetCols();
var items = sorter(this._getFilteredItems(), sortOptions);
this.sortedItems = items;
this._layout(items); // `_layout` always happens after `_shrink`, so it's safe to process the style
// queue here with styles from the shrink method.
@ -2151,7 +2161,7 @@
}]);
return Shuffle;
}(tinyEmitter);
}(TinyEmitter);
Shuffle.ShuffleItem = ShuffleItem;
Shuffle.ALL_ITEMS = 'all';

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

12
index.d.ts vendored

@ -82,7 +82,7 @@ export interface ShuffleOptions {
/**
* Whether to round pixel values used in translate(x, y). This usually avoids blurriness.
*/
roundTransforms?: boolean,
roundTransforms?: boolean;
/**
* Element or selector string. Use an element to determine the size of columns and gutters.
@ -246,7 +246,7 @@ declare class Shuffle extends TinyEmitter {
* Returns styles which will be applied to the an item for a transition.
* @param {object} obj Transition options.
*/
protected getStylesForTransition(obj: { item: Shuffle.ShuffleItem, styles: InlineCssStyles }): InlineCssStyles;
protected getStylesForTransition(obj: { item: Shuffle.ShuffleItem; styles: InlineCssStyles }): InlineCssStyles;
/**
* Mutate positions before they're applied.
@ -293,8 +293,12 @@ declare class Shuffle extends TinyEmitter {
/** Whether items are currently transitioning */
isTransitioning: boolean;
/** ShuffleItems being kept track of */
/** ShuffleItems being kept track of, sorted in DOM order. */
items: Shuffle.ShuffleItem[];
/** Visible ShuffleItems being tracked, sorted in the current sort order */
sortedItems: Shuffle.ShuffleItem[];
lastFilter: FilterArg;
lastSort: SortOptions;
@ -312,7 +316,7 @@ declare class Shuffle extends TinyEmitter {
* @param {HTMLElement} element The element.
* @param {boolean} [includeMargins=false] Whether to include margins.
*/
static getSize(element: HTMLElement, includeMargins?: boolean): {width: number, height: number};
static getSize(element: HTMLElement, includeMargins?: boolean): { width: number; height: number };
}
declare namespace Shuffle {

@ -58,6 +58,7 @@
"cssnano": "^5.0.4",
"eslint": "^7.5.0",
"eslint-config-airbnb-base": "^14.0.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.17.3",
"gulp": "^4.0.2",
"gulp-postcss": "^9.0.0",

@ -1,3 +1,5 @@
import getNumber from './get-number';
let value = null;
export default () => {
if (value !== null) {
@ -9,7 +11,9 @@ export default () => {
e.style.cssText = 'width:10px;padding:2px;box-sizing:border-box;';
element.appendChild(e);
value = window.getComputedStyle(e, null).width === '10px';
const { width } = window.getComputedStyle(e, null);
// Fix for issue #314
value = Math.round(getNumber(width)) === 10;
element.removeChild(e);

@ -10,13 +10,7 @@ import Classes from './classes';
import getNumberStyle from './get-number-style';
import sorter from './sorter';
import { onTransitionEnd, cancelTransitionEnd } from './on-transition-end';
import {
getItemPosition,
getColumnSpan,
getAvailablePositions,
getShortColumn,
getCenteredPositions,
} from './layout';
import { getItemPosition, getColumnSpan, getAvailablePositions, getShortColumn, getCenteredPositions } from './layout';
import arrayMax from './array-max';
import hyphenate from './hyphenate';
@ -72,6 +66,7 @@ class Shuffle extends TinyEmitter {
_init() {
this.items = this._getItems();
this.sortedItems = this.items;
this.options.sizer = this._getElementOption(this.options.sizer);
@ -126,9 +121,7 @@ class Shuffle extends TinyEmitter {
*/
_getResizeFunction() {
const resizeFunction = this._handleResize.bind(this);
return this.options.throttle
? this.options.throttle(resizeFunction, this.options.throttleTime)
: resizeFunction;
return this.options.throttle ? this.options.throttle(resizeFunction, this.options.throttleTime) : resizeFunction;
}
/**
@ -216,8 +209,8 @@ class Shuffle extends TinyEmitter {
if (category === Shuffle.ALL_ITEMS) {
visible = items;
// Loop through each item and use provided function to determine
// whether to hide it or not.
// Loop through each item and use provided function to determine
// whether to hide it or not.
} else {
items.forEach((item) => {
if (this._doesPassFilter(category, item.element)) {
@ -248,9 +241,7 @@ class Shuffle extends TinyEmitter {
// Check each element's data-groups attribute against the given category.
const attr = element.getAttribute('data-' + Shuffle.FILTER_ATTRIBUTE_KEY);
const keys = this.options.delimiter
? attr.split(this.options.delimiter)
: JSON.parse(attr);
const keys = this.options.delimiter ? attr.split(this.options.delimiter) : JSON.parse(attr);
function testCategory(category) {
return keys.includes(category);
@ -376,19 +367,19 @@ class Shuffle extends TinyEmitter {
if (typeof this.options.columnWidth === 'function') {
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.options.sizer) {
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.options.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) {
size = Shuffle.getSize(this.items[0].element, true).width;
// if there's no items, use size of container
// if there's no items, use size of container
} else {
size = containerWidth;
}
@ -431,8 +422,7 @@ class Shuffle extends TinyEmitter {
let calculatedColumns = (containerWidth + gutter) / columnWidth;
// Widths given from getStyles are not precise enough...
if (Math.abs(Math.round(calculatedColumns) - calculatedColumns)
< this.options.columnThreshold) {
if (Math.abs(Math.round(calculatedColumns) - calculatedColumns) < this.options.columnThreshold) {
// e.g. calculatedColumns = 11.998876
calculatedColumns = Math.round(calculatedColumns);
}
@ -719,9 +709,9 @@ class Shuffle extends TinyEmitter {
this._styleImmediately(this._queue);
this._dispatch(Shuffle.EventType.LAYOUT);
// A call to layout happened, but none of the newly visible items will
// change position or the transition duration is zero, which will not trigger
// the transitionend event.
// A call to layout happened, but none of the newly visible items will
// change position or the transition duration is zero, which will not trigger
// the transitionend event.
} else {
this._dispatch(Shuffle.EventType.LAYOUT);
}
@ -818,6 +808,7 @@ class Shuffle extends TinyEmitter {
this._resetCols();
const items = sorter(this._getFilteredItems(), sortOptions);
this.sortedItems = items;
this._layout(items);
@ -943,9 +934,7 @@ class Shuffle extends TinyEmitter {
const collection = arrayUnique(elements);
const oldItems = collection
.map((element) => this.getItemByElement(element))
.filter((item) => !!item);
const oldItems = collection.map((element) => this.getItemByElement(element)).filter((item) => !!item);
const handleLayout = () => {
this._disposeItems(oldItems);
@ -1025,6 +1014,7 @@ class Shuffle extends TinyEmitter {
this._disposeItems(this.items);
this.items.length = 0;
this.sortedItems.length = 0;
this._transitions.length = 0;
// Null DOM references

@ -26,4 +26,4 @@ export const delimiter = `
<div class="item" id="item9" data-groups='design,red'>Person 9</div>
<div class="item" id="item10" data-groups='technology,black'>Person 10</div>
</div>
`
`;

@ -38,7 +38,6 @@ describe('shuffle', () => {
}
describe('regular fixture', () => {
beforeEach(() => {
// Mock the transition end event wrapper.
sinon.stub(Shuffle.prototype, '_whenTransitionDone').callsFake(whenTransitionDoneStub);
@ -55,6 +54,7 @@ describe('shuffle', () => {
instance = new Shuffle(fixture);
expect(instance.items.length).toBe(10);
expect(instance.visibleItems).toBe(10);
expect(instance.sortedItems).toHaveLength(10);
expect(instance.options.group).toBe('all');
expect(instance.options.speed).toBe(250);
expect(instance.options.itemSelector).toBe('*');
@ -165,23 +165,23 @@ describe('shuffle', () => {
expect(instance.positions).toEqual([40, 40, 30, 30]);
});
it('can filter by the data attribute', done => {
it('can filter by the data attribute', (done) => {
instance = new Shuffle(fixture, {
speed: 0,
});
function second() {
expect(instance.visibleItems).toBe(3);
const hidden = [3, 4, 5, 6, 7, 8, 10].map(num => id(`item${num}`));
const hidden = [3, 4, 5, 6, 7, 8, 10].map((num) => id(`item${num}`));
const visible = [1, 2, 9].map(num => id(`item${num}`));
const visible = [1, 2, 9].map((num) => id(`item${num}`));
hidden.forEach(element => {
hidden.forEach((element) => {
expect(element.classList.contains(Shuffle.Classes.HIDDEN)).toBe(true);
expect(element.style.visibility).toBe('hidden');
});
visible.forEach(element => {
visible.forEach((element) => {
expect(element.classList.contains(Shuffle.Classes.VISIBLE)).toBe(true);
expect(element.style.visibility).toBe('visible');
});
@ -194,16 +194,16 @@ describe('shuffle', () => {
function third() {
expect(instance.visibleItems).toBe(2);
const hidden = [1, 2, 5, 6, 7, 8, 9, 10].map(num => id(`item${num}`));
const hidden = [1, 2, 5, 6, 7, 8, 9, 10].map((num) => id(`item${num}`));
const visible = [3, 4].map(num => id(`item${num}`));
const visible = [3, 4].map((num) => id(`item${num}`));
hidden.forEach(element => {
hidden.forEach((element) => {
expect(element.classList.contains(Shuffle.Classes.HIDDEN)).toBe(true);
expect(element.style.visibility).toBe('hidden');
});
visible.forEach(element => {
visible.forEach((element) => {
expect(element.classList.contains(Shuffle.Classes.VISIBLE)).toBe(true);
expect(element.style.visibility).toBe('visible');
});
@ -264,15 +264,20 @@ describe('shuffle', () => {
it('can center already-positioned items', () => {
// 4-2-1 even heights
expect(Shuffle.__getCenteredPositions([
new Shuffle.Rect(0, 0, 250, 100, 0),
new Shuffle.Rect(250, 0, 250, 100, 1),
new Shuffle.Rect(500, 0, 250, 100, 2),
new Shuffle.Rect(750, 0, 250, 100, 3),
new Shuffle.Rect(0, 100, 600, 100, 4),
new Shuffle.Rect(600, 100, 300, 100, 5),
new Shuffle.Rect(0, 200, 250, 100, 6),
], 1000)).toEqual([
expect(
Shuffle.__getCenteredPositions(
[
new Shuffle.Rect(0, 0, 250, 100, 0),
new Shuffle.Rect(250, 0, 250, 100, 1),
new Shuffle.Rect(500, 0, 250, 100, 2),
new Shuffle.Rect(750, 0, 250, 100, 3),
new Shuffle.Rect(0, 100, 600, 100, 4),
new Shuffle.Rect(600, 100, 300, 100, 5),
new Shuffle.Rect(0, 200, 250, 100, 6),
],
1000,
),
).toEqual([
new Shuffle.Point(0, 0),
new Shuffle.Point(250, 0),
new Shuffle.Point(500, 0),
@ -287,15 +292,16 @@ describe('shuffle', () => {
// 2x1
// Centers the first row, but then finds that the 3rd item will overlap
// the 2x2 and resets the first row.
expect(Shuffle.__getCenteredPositions([
new Shuffle.Rect(0, 0, 500, 200, 0),
new Shuffle.Rect(500, 0, 250, 100, 1),
new Shuffle.Rect(500, 100, 500, 100, 2),
], 1000)).toEqual([
new Shuffle.Point(0, 0),
new Shuffle.Point(500, 0),
new Shuffle.Point(500, 100),
]);
expect(
Shuffle.__getCenteredPositions(
[
new Shuffle.Rect(0, 0, 500, 200, 0),
new Shuffle.Rect(500, 0, 250, 100, 1),
new Shuffle.Rect(500, 100, 500, 100, 2),
],
1000,
),
).toEqual([new Shuffle.Point(0, 0), new Shuffle.Point(500, 0), new Shuffle.Point(500, 100)]);
});
it('can get an element option', () => {
@ -317,12 +323,14 @@ describe('shuffle', () => {
expect(instance._doesPassFilter('design', first)).toBe(true);
expect(instance._doesPassFilter('black', first)).toBe(false);
expect(instance._doesPassFilter(element => {
expect(element).toBeDefined();
return element.getAttribute('data-age') === '21';
}, first)).toBe(true);
expect(
instance._doesPassFilter((element) => {
expect(element).toBeDefined();
return element.getAttribute('data-age') === '21';
}, first),
).toBe(true);
expect(instance._doesPassFilter(element => element.getAttribute('data-age') === '22', first)).toBe(false);
expect(instance._doesPassFilter((element) => element.getAttribute('data-age') === '22', first)).toBe(false);
// Arrays.
expect(instance._doesPassFilter(['design'], first)).toBe(true);
@ -348,7 +356,39 @@ describe('shuffle', () => {
instance.sort();
expect(instance.lastSort).toEqual({ glen: true });
});
it('tracks sorted items', () => {
instance = new Shuffle(fixture);
expect(instance.sortedItems.map((item) => item.element.id)).toEqual([
'item1',
'item2',
'item3',
'item4',
'item5',
'item6',
'item7',
'item8',
'item9',
'item10',
]);
instance.sort({
reverse: true,
});
expect(instance.sortedItems.map((item) => item.element.id)).toEqual([
'item10',
'item9',
'item8',
'item7',
'item6',
'item5',
'item4',
'item3',
'item2',
'item1',
]);
});
it('should reset columns', () => {
@ -376,7 +416,7 @@ describe('shuffle', () => {
expect(fixture.classList.contains('shuffle')).toBe(false);
Array.from(fixture.children).forEach(child => {
Array.from(fixture.children).forEach((child) => {
expect(child.classList.contains('shuffle-item')).toBe(false);
expect(child.classList.contains('shuffle-item--visible')).toBe(false);
expect(child.classList.contains('shuffle-item--hidden')).toBe(false);
@ -422,7 +462,7 @@ describe('shuffle', () => {
children = null;
});
it('can remove items', done => {
it('can remove items', (done) => {
instance = new Shuffle(fixture, {
speed: 16,
});
@ -440,7 +480,7 @@ describe('shuffle', () => {
instance.remove(itemsToRemove);
});
it('can remove items without transforms', done => {
it('can remove items without transforms', (done) => {
instance = new Shuffle(fixture, {
speed: 100,
useTransforms: false,
@ -517,13 +557,14 @@ describe('shuffle', () => {
items.length = 0;
});
it('can add items', done => {
it('can add items', (done) => {
fixture.appendChild(items[0]);
fixture.appendChild(items[1]);
instance.add(items);
// Already 2 in the items, plus number 11.
expect(instance.visibleItems).toBe(3);
expect(instance.sortedItems.map((item) => item.element.id)).toEqual(['item8', 'item10', 'item11']);
expect(instance.items).toHaveLength(12);
instance.once(Shuffle.EventType.LAYOUT, () => {
@ -531,13 +572,14 @@ describe('shuffle', () => {
});
});
it('can prepend items', done => {
it('can prepend items', (done) => {
fixture.insertBefore(items[1], fixture.firstElementChild);
fixture.insertBefore(items[0], fixture.firstElementChild);
instance.add(items);
expect(instance.items[0].element).toBe(items[0]);
expect(instance.items[1].element).toBe(items[1]);
expect(instance.sortedItems.map((item) => item.element.id)).toEqual(['item11', 'item8', 'item10']);
expect(instance.items).toHaveLength(12);
instance.once(Shuffle.EventType.LAYOUT, () => {
@ -557,7 +599,6 @@ describe('shuffle', () => {
expect(instance.items[1].element).toBe(items[1]);
expect(instance.items).toHaveLength(2);
});
});
});
@ -611,7 +652,7 @@ describe('shuffle', () => {
// The layout method will have already set styles to their 'after' states
// upon initialization. Reset them here.
instance.items.forEach(item => {
instance.items.forEach((item) => {
item.applyCss(Shuffle.ShuffleItem.Css.INITIAL);
});
@ -635,8 +676,8 @@ describe('shuffle', () => {
beforeEach(() => {
appendFixture('regular');
items = Array.from(fixture.children).map(element => ({
element
items = Array.from(fixture.children).map((element) => ({
element,
}));
clone = Array.from(items);
@ -678,11 +719,13 @@ describe('shuffle', () => {
});
it('can sort by a function and reverse it', () => {
clone.sort((a, b) => {
const age1 = parseInt(a.element.getAttribute('data-age'), 10);
const age2 = parseInt(b.element.getAttribute('data-age'), 10);
return age1 - age2;
}).reverse();
clone
.sort((a, b) => {
const age1 = parseInt(a.element.getAttribute('data-age'), 10);
const age2 = parseInt(b.element.getAttribute('data-age'), 10);
return age1 - age2;
})
.reverse();
const result = Shuffle.__sorter(items, {
reverse: true,
@ -696,42 +739,48 @@ describe('shuffle', () => {
it('will revert to DOM order if the `by` function returns undefined', () => {
let count = 0;
expect(Shuffle.__sorter(items, {
by() {
count++;
return count < 5 ? Math.random() : undefined;
},
})).toEqual(clone);
expect(
Shuffle.__sorter(items, {
by() {
count++;
return count < 5 ? Math.random() : undefined;
},
}),
).toEqual(clone);
});
it('can sort things to the top', () => {
items = items.slice(0, 4);
const final = [items[1], items[0], items[3], items[2]];
expect(Shuffle.__sorter(items, {
by(element) {
const age = parseInt(element.getAttribute('data-age'), 10);
if (age === 50) {
return 'sortFirst';
} else {
return age;
}
},
})).toEqual(final);
expect(
Shuffle.__sorter(items, {
by(element) {
const age = parseInt(element.getAttribute('data-age'), 10);
if (age === 50) {
return 'sortFirst';
} else {
return age;
}
},
}),
).toEqual(final);
});
it('can sort things to the bottom', () => {
items = items.slice(0, 4);
const final = [items[0], items[2], items[1], items[3]];
expect(Shuffle.__sorter(items, {
by(element) {
const age = parseInt(element.getAttribute('data-age'), 10);
if (age === 27) {
return 'sortLast';
} else {
return age;
}
},
})).toEqual(final);
expect(
Shuffle.__sorter(items, {
by(element) {
const age = parseInt(element.getAttribute('data-age'), 10);
if (age === 27) {
return 'sortLast';
} else {
return age;
}
},
}),
).toEqual(final);
});
it('can have a custom sort comparator', () => {
@ -747,25 +796,26 @@ describe('shuffle', () => {
clone[3], // ux, 27
clone[4], // ux, 35
];
expect(Shuffle.__sorter(items, {
compare(a, b) {
// Sort by first group, then by age.
const groupA = JSON.parse(a.element.getAttribute('data-groups'))[0];
const groupB = JSON.parse(b.element.getAttribute('data-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.getAttribute('data-age'), 10);
const ageB = parseInt(b.element.getAttribute('data-age'), 10);
return ageA - ageB;
},
})).toEqual(final);
expect(
Shuffle.__sorter(items, {
compare(a, b) {
// Sort by first group, then by age.
const groupA = JSON.parse(a.element.getAttribute('data-groups'))[0];
const groupB = JSON.parse(b.element.getAttribute('data-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.getAttribute('data-age'), 10);
const ageB = parseInt(b.element.getAttribute('data-age'), 10);
return ageA - ageB;
},
}),
).toEqual(final);
});
});
});

@ -9,12 +9,7 @@ if (!mainElement) {
throw new TypeError('oopsie');
}
console.log(
Shuffle.EventType.LAYOUT,
Shuffle.Classes.SHUFFLE_ITEM,
Shuffle.FilterMode.ALL,
Shuffle.ShuffleItem.Css,
);
console.log(Shuffle.EventType.LAYOUT, Shuffle.Classes.SHUFFLE_ITEM, Shuffle.FilterMode.ALL, Shuffle.ShuffleItem.Css);
const options: ShuffleOptions = {
buffer: 0,
@ -49,6 +44,7 @@ const sortOptions: SortOptions = {
},
};
shuffle.sort(sortOptions);
console.log(shuffle.sortedItems);
shuffle.update(true);
Shuffle.getSize(mainElement, true);

Loading…
Cancel
Save