Skip to content

Commit 1e4cfdd

Browse files
author
Jihye Hong
authored
Merge pull request #132 from jeonghee27/non-standard-api
Fix bug about float number from getBoundingClientRect()
2 parents c81a8aa + 5a030b9 commit 1e4cfdd

1 file changed

Lines changed: 32 additions & 12 deletions

File tree

polyfill/spatnav-heuristic.js

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// Indicates global variables for spatnav (starting position)
1414
const spatNavManager = {
1515
startingPosition: null,
16-
useStandardName: true,
16+
useStandardName: true
1717
};
1818

1919
// Use non standard names by default, as per https://www.w3.org/2001/tag/doc/polyfills/#don-t-squat-on-proposed-names-in-speculative-polyfills
@@ -33,6 +33,7 @@
3333
const ARROW_KEY_CODE = {37: 'left', 38: 'up', 39: 'right', 40: 'down'};
3434
const TAB_KEY_CODE = 9;
3535
let spatialNaviagtionKeyMode = 'ARROW';
36+
let mapOfBoundRect = new Map();
3637

3738
function focusNavigationHeuristics() {
3839

@@ -57,6 +58,7 @@
5758
const currentKeyMode = (parent && parent.__spatialNavigation__.getKeyMode()) || window.__spatialNavigation__.getKeyMode();
5859
const eventTarget = document.activeElement;
5960
const dir = ARROW_KEY_CODE[e.keyCode];
61+
mapOfBoundRect = new Map();
6062

6163
if (e.keyCode === TAB_KEY_CODE)
6264
spatNavManager.startingPosition = null;
@@ -374,8 +376,8 @@
374376
// to do
375377
// Offscreen handling when originalContainer is not <HTML>
376378
if (!isVisible(currentElm) && originalContainer.parentElement && container !== originalContainer)
377-
eventTargetRect = originalContainer.getBoundingClientRect();
378-
else eventTargetRect = currentElm.getBoundingClientRect();
379+
eventTargetRect = getBoundingClientRect(originalContainer);
380+
else eventTargetRect = getBoundingClientRect(currentElm);
379381

380382
// If D(dir) is null, let candidates be the same as visibles
381383
if (dir === undefined)
@@ -388,7 +390,7 @@
388390
*/
389391
return candidates.filter(candidate =>
390392
container.contains(candidate.getSpatialNavigationContainer()) &&
391-
isOutside(candidate.getBoundingClientRect(), eventTargetRect, dir)
393+
isOutside(getBoundingClientRect(candidate), eventTargetRect, dir)
392394
);
393395
}
394396

@@ -407,9 +409,10 @@
407409
let bestCandidate;
408410
let minDistance = Number.POSITIVE_INFINITY;
409411
let tempDistance = undefined;
412+
let eventTargetRect = getBoundingClientRect(currentElm);
410413

411414
for (let i = 0; i < candidates.length; i++) {
412-
tempDistance = getDistance(currentElm.getBoundingClientRect(), candidates[i].getBoundingClientRect(), dir);
415+
tempDistance = getDistance(eventTargetRect, getBoundingClientRect(candidates[i]), dir);
413416
if (tempDistance < minDistance) {
414417
minDistance = tempDistance;
415418
bestCandidate = candidates[i];
@@ -429,14 +432,14 @@
429432
* @returns {<Node>} the best candidate
430433
**/
431434
function selectBestCandidateFromEdge(currentElm, candidates, dir) {
432-
const eventTargetRect = currentElm.getBoundingClientRect();
435+
const eventTargetRect = getBoundingClientRect(currentElm);
433436
let minDistanceElement = undefined;
434437
let minDistance = Number.POSITIVE_INFINITY;
435438
let tempMinDistance = undefined;
436439

437440
if(candidates) {
438441
for (let i = 0; i < candidates.length; i++) {
439-
tempMinDistance = getInnerDistance(eventTargetRect, candidates[i].getBoundingClientRect(), dir);
442+
tempMinDistance = getInnerDistance(eventTargetRect, getBoundingClientRect(candidates[i]), dir);
440443

441444
// If the same distance, the candidate will be selected in the DOM order
442445
if (tempMinDistance < minDistance) {
@@ -791,8 +794,8 @@
791794
* @returns {Boolean}
792795
**/
793796
function isEntirelyVisible(element) {
794-
const rect = element.getBoundingClientRect();
795-
const containerRect = element.getSpatialNavigationContainer().getBoundingClientRect();
797+
const rect = getBoundingClientRect(element);
798+
const containerRect = getBoundingClientRect(element.getSpatialNavigationContainer());
796799

797800
// FIXME: when element is bigger than container?
798801
const entirelyVisible = !((rect.left < containerRect.left) ||
@@ -830,7 +833,7 @@
830833
offsetX = isNaN(offsetX) ? 0 : offsetX;
831834
offsetY = isNaN(offsetY) ? 0 : offsetY;
832835

833-
const elementRect = element.getBoundingClientRect();
836+
const elementRect = getBoundingClientRect(element);
834837

835838
const middleElem = document.elementFromPoint((elementRect.left + elementRect.right) / 2, (elementRect.top + elementRect.bottom) / 2);
836839
const leftTopElem = document.elementFromPoint(elementRect.left + offsetX, elementRect.top + offsetY);
@@ -1139,6 +1142,23 @@
11391142
return focusNavigableArrowKey;
11401143
}
11411144

1145+
function getBoundingClientRect(element) {
1146+
let rect = mapOfBoundRect.get(element); // memoization
1147+
if(!rect) {
1148+
const boundingClientRect = element.getBoundingClientRect();
1149+
rect = {
1150+
top: Number(boundingClientRect.top.toFixed(2)),
1151+
right: Number(boundingClientRect.right.toFixed(2)),
1152+
bottom: Number(boundingClientRect.bottom.toFixed(2)),
1153+
left: Number(boundingClientRect.left.toFixed(2)),
1154+
width: Number(boundingClientRect.width.toFixed(2)),
1155+
height: Number(boundingClientRect.height.toFixed(2))
1156+
};
1157+
mapOfBoundRect.set(element, rect);
1158+
}
1159+
return rect;
1160+
}
1161+
11421162
function setStandardName() {
11431163
spatNavManager.useStandardName = true;
11441164
}
@@ -1295,10 +1315,10 @@
12951315
getDistanceFromTarget: (element, candidateElement, dir) => {
12961316
if ((isContainer(element) || element.nodeName === 'BODY') && !(element.nodeName === 'INPUT')) {
12971317
if (element.focusableAreas().includes(candidateElement)) {
1298-
return getInnerDistance(element.getBoundingClientRect(), candidateElement.getBoundingClientRect(), dir);
1318+
return getInnerDistance(getBoundingClientRect(element), getBoundingClientRect(candidateElement), dir);
12991319
}
13001320
}
1301-
return getDistance(element.getBoundingClientRect(), candidateElement.getBoundingClientRect(), dir);
1321+
return getDistance(getBoundingClientRect(element), getBoundingClientRect(candidateElement), dir);
13021322
},
13031323

13041324
setKeyMode : (option) => {

0 commit comments

Comments
 (0)