Skip to content

Commit

Permalink
fix: update logic for index diff calculations, fixes #14
Browse files Browse the repository at this point in the history
  • Loading branch information
theKashey committed Jun 15, 2020
1 parent 4933db7 commit 4c7e637
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 17 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
## [0.6.8](https://github.com/theKashey/focus-lock/compare/v0.6.7...v0.6.8) (2020-04-24)


### Bug Fixes

* dataset of null error ([7cb428b](https://github.com/theKashey/focus-lock/commit/7cb428b))



## [0.6.7](https://github.com/theKashey/focus-lock/compare/v0.6.6...v0.6.7) (2020-04-17)


Expand Down
13 changes: 12 additions & 1 deletion _tests/focusMerge.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,21 @@ describe('focus Merge order', () => {
const innerNodes = [radio1, radioChecked, 4];
expect(newFocus(innerNodes, [1, ...innerNodes, 5], 5, 4)).to.be.equal(1);
});

it('picks active radio to right', () => {
const innerNodes = [1, radio1, radioChecked, radio2];
expect(newFocus(innerNodes, [0, ...innerNodes, 5], 0, 1)).to.be.equal(2);
})
});

it('jump out via last node', () => {
const innerNodes = [1, radioChecked];
expect(newFocus(innerNodes, [0, ...innerNodes, 5], 5, radioChecked)).to.be.equal(0);
});
it('jump out via unchecked node', () => {
// radio1 and radio2 should be invisible to algo
const innerNodes = [1, radioChecked, radio1, radio2];
expect(newFocus(innerNodes, [0, ...innerNodes, 5], 5, radioChecked)).to.be.equal(0);
});
});

it('should select auto focused', () => {
Expand Down
11 changes: 9 additions & 2 deletions src/focusMerge.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { getCommonParent, getTabbableNodes, getAllTabbableNodes, parentAutofocus
import pickFirstFocus, { pickFocusable } from './utils/firstFocus';
import getAllAffectedNodes from './utils/all-affected';
import { asArray } from './utils/array';
import { correctNodes } from './utils/correctFocus';

const findAutoFocused = autoFocusables => node => (
!!node.autofocus ||
Expand Down Expand Up @@ -30,6 +31,12 @@ export const newFocus = (innerNodes, outerNodes, activeElement, lastNode, autoFo
const firstNodeIndex = outerNodes.indexOf(firstFocus);
const lastNodeIndex = outerNodes.indexOf(lastFocus);

const correctedNodes = correctNodes(outerNodes);
const correctedIndexDiff = (
correctedNodes.indexOf(activeElement) -
correctedNodes.indexOf(lastNode || activeIndex)
);

const returnFirstNode = pickFocusable(innerNodes, 0);
const returnLastNode = pickFocusable(innerNodes, cnt - 1);

Expand All @@ -50,11 +57,11 @@ export const newFocus = (innerNodes, outerNodes, activeElement, lastNode, autoFo
return returnLastNode;
}
// last element
if (activeIndex >= firstNodeIndex && isOnGuard && Math.abs(indexDiff) > 1) {
if (activeIndex >= lastNodeIndex && isOnGuard && Math.abs(indexDiff) > 1) {
return returnFirstNode;
}
// jump out, but not on the guard
if (indexDiff && Math.abs(indexDiff) > 1) {
if (indexDiff && Math.abs(correctedIndexDiff) > 1) {
return lastNodeInside;
}
// focus above lock
Expand Down
3 changes: 3 additions & 0 deletions src/utils/DOMutils.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ export const getTabbableNodes = (topNodes, withGuards) => (
orderByTabIndex(filterFocusable(getFocusables(topNodes, withGuards)), true, withGuards)
);

/**
* actually anything focusable
*/
export const getAllTabbableNodes = topNodes => (
orderByTabIndex(filterFocusable(getFocusables(topNodes)), false)
);
Expand Down
24 changes: 24 additions & 0 deletions src/utils/correctFocus.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const isRadio = node => node.tagName === 'INPUT' && node.type === 'radio';

const findSelectedRadio = (node, nodes) => (
nodes
.filter(isRadio)
.filter(el => el.name === node.name)
.filter(el => el.checked)[0]
|| node
);

export const correctNode = (node, nodes) => {
if (isRadio(node) && node.name) {
return findSelectedRadio(node, nodes);
}
return node;
};

export const correctNodes = (nodes) => {
// IE11 has no Set constructor
const resultSet = new Set();
nodes.forEach(node => resultSet.add(node))
// using filter to support IE11
return nodes.filter(node => resultSet.has(node));
};
17 changes: 3 additions & 14 deletions src/utils/firstFocus.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,16 @@
const isRadio = node => node.tagName === 'INPUT' && node.type === 'radio';
import { correctNode } from './correctFocus';

const findSelectedRadio = (node, nodes) => (
nodes
.filter(isRadio)
.filter(el => el.name === node.name)
.filter(el => el.checked)[0]
|| node
);

const pickFirstFocus = (nodes) => {
if (nodes[0] && nodes.length > 1) {
if (isRadio(nodes[0]) && nodes[0].name) {
return findSelectedRadio(nodes[0], nodes);
}
return correctNode(nodes[0], nodes);
}
return nodes[0];
};

export const pickFocusable = (nodes, index) => {
if (nodes.length > 1) {
if (isRadio(nodes[index]) && nodes[index].name) {
return nodes.indexOf(findSelectedRadio(nodes[index], nodes));
}
return nodes.indexOf(correctNode(nodes[index], nodes));
}
return index;
};
Expand Down

0 comments on commit 4c7e637

Please sign in to comment.