-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsort-by-dom-position.js
66 lines (60 loc) · 1.75 KB
/
sort-by-dom-position.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import { invoker, compose } from 'ramda';
/**
* Calls compareDocumentPosition on two elements
* @type {Function}
* @param {Element} a
* @param {Element} b
*
* @return {number}
*/
const compareDocumentPosition = invoker(1, 'compareDocumentPosition');
/**
* Returns true if the bitmask contains the 2 bit set
* @param {number} bitmask
*
* @return {boolean}
*/
const isPrecedingValue = bitmask => (bitmask & 2) > 0; // eslint-disable-line no-bitwise
/**
* Returns the direction to move an element based on the isPreceding
* @param {boolean} isPreceding
*
* @return {number}
*/
const moveDirection = isPreceding => (isPreceding ? -1 : 1);
/**
* Returns 1 or -1 based on the element being before or after in the dom
* @type {Function}
* @param {Element} a
* @param {Element} b
*
* @return {number}
*/
const sortByDomPosition = compose(moveDirection, isPrecedingValue, compareDocumentPosition);
/**
* Performs a sort of the elements by dom position, and updates the state
* with the new index of the currently selected item
*
* @param {Element[]} elements
* @param {NavigationListState} state
*/
export const sortElementsByDomPosition = ({ elements, state }) => {
const element = elements[state.currentIndex];
elements.sort(sortByDomPosition);
state.currentIndex = elements.indexOf(element); // eslint-disable-line no-param-reassign
};
/**
* Plugin that sorts the elements by dom position before applying a new state
* @class
* @implements {NavigationListPlugin}
*/
export default class SortByDomPositionPlugin {
/**
* Initiates the plugin
* @param {NavigationList} navigationList
*/
// eslint-disable-next-line class-methods-use-this
init(navigationList) {
navigationList.on('beforeUpdateState', sortElementsByDomPosition);
}
}