You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Vestride_Shuffle/src/sorter.js

103 lines
2.2 KiB
JavaScript

/**
* Fisher-Yates shuffle.
* http://stackoverflow.com/a/962890/373422
* https://bost.ocks.org/mike/shuffle/
* @param {Array} array Array to shuffle.
* @return {Array} Randomly sorted array.
*/
function randomize(array) {
let n = array.length;
while (n) {
n -= 1;
const i = Math.floor(Math.random() * (n + 1));
const temp = array[i];
array[i] = array[n];
array[n] = temp;
}
return array;
}
const defaults = {
// Use array.reverse() to reverse the results
reverse: false,
// Sorting function
by: null,
// Custom sort function
compare: null,
// If true, this will skip the sorting and return a randomized order in the array
randomize: false,
// Determines which property of each item in the array is passed to the
// sorting method.
key: 'element',
};
/**
* You can return `undefined` from the `by` function to revert to DOM order.
* @param {Array<T>} arr Array to sort.
* @param {SortOptions} options Sorting options.
* @return {Array<T>}
*/
export default function sorter(arr, options) {
// eslint-disable-next-line prefer-object-spread
const opts = Object.assign({}, defaults, options);
const original = Array.from(arr);
let revert = false;
if (!arr.length) {
return [];
}
if (opts.randomize) {
return randomize(arr);
}
// Sort the elements by the opts.by function.
// If we don't have opts.by, default to DOM order
if (typeof opts.by === 'function') {
arr.sort((a, b) => {
// Exit early if we already know we want to revert
if (revert) {
return 0;
}
const valA = opts.by(a[opts.key]);
const valB = opts.by(b[opts.key]);
// If both values are undefined, use the DOM order
if (valA === undefined && valB === undefined) {
revert = true;
return 0;
}
if (valA < valB || valA === 'sortFirst' || valB === 'sortLast') {
return -1;
}
if (valA > valB || valA === 'sortLast' || valB === 'sortFirst') {
return 1;
}
return 0;
});
} else if (typeof opts.compare === 'function') {
arr.sort(opts.compare);
}
// Revert to the original array if necessary
if (revert) {
return original;
}
if (opts.reverse) {
arr.reverse();
}
return arr;
}