|
11 | 11 | (function () { |
12 | 12 |
|
13 | 13 | // Indicates global variables for spatnav (starting position) |
14 | | - let spatNavManager = { |
| 14 | + const spatNavManager = { |
15 | 15 | startingPosition: null, |
16 | 16 | useStandardName: true, |
17 | 17 | }; |
|
32 | 32 |
|
33 | 33 | const ARROW_KEY_CODE = {37: 'left', 38: 'up', 39: 'right', 40: 'down'}; |
34 | 34 | const TAB_KEY_CODE = 9; |
35 | | - let shiftArrow = false; |
| 35 | + let spatialNaviagtionKeyMode = 'ARROW'; |
36 | 36 |
|
37 | 37 | function focusNavigationHeuristics() { |
38 | 38 |
|
|
54 | 54 | * If arrow key pressed, get the next focusing element and send it to focusing controller |
55 | 55 | */ |
56 | 56 | window.addEventListener('keydown', function(e) { |
57 | | - const spatnavPolyfillOff = window.spatnavPolyfillOff || (parent && parent.spatnavPolyfillOff); |
58 | | - if (!spatnavPolyfillOff && !e.defaultPrevented) { |
| 57 | + const currentKeyMode = (parent && parent.__spatialNavigation__.getKeyMode()) || window.__spatialNavigation__.getKeyMode() ; |
| 58 | + const eventTarget = document.activeElement; |
| 59 | + const dir = ARROW_KEY_CODE[e.keyCode]; |
| 60 | + |
| 61 | + if(!currentKeyMode || |
| 62 | + (currentKeyMode === 'NONE') || |
| 63 | + ((currentKeyMode === 'SHIFTARROW') && !e.shiftKey) || |
| 64 | + ((currentKeyMode === 'ARROW') && e.shiftKey)) |
| 65 | + return; |
| 66 | + |
| 67 | + if (!e.defaultPrevented) { |
59 | 68 | let focusNavigableArrowKey = {'left': true, 'up': true, 'right': true, 'down': true}; |
60 | | - const eventTarget = document.activeElement; |
61 | | - const dir = ARROW_KEY_CODE[e.keyCode]; |
62 | 69 |
|
63 | | - if(!shiftArrow || e.shiftKey) { |
64 | | - // Edge case (text input, area) : Don't move focus, just navigate cursor in text area |
65 | | - if ((eventTarget.nodeName === 'INPUT') || eventTarget.nodeName === 'TEXTAREA') |
66 | | - focusNavigableArrowKey = handlingEditableElement(e); |
| 70 | + // Edge case (text input, area) : Don't move focus, just navigate cursor in text area |
| 71 | + if ((eventTarget.nodeName === 'INPUT') || eventTarget.nodeName === 'TEXTAREA') |
| 72 | + focusNavigableArrowKey = handlingEditableElement(e); |
67 | 73 |
|
68 | | - if (focusNavigableArrowKey[dir]) { |
69 | | - e.preventDefault(); |
70 | | - navigate(dir); |
| 74 | + if (focusNavigableArrowKey[dir]) { |
| 75 | + e.preventDefault(); |
| 76 | + navigate(dir); |
71 | 77 |
|
72 | | - spatNavManager.startingPosition = null; |
73 | | - } |
| 78 | + spatNavManager.startingPosition = null; |
74 | 79 | } |
75 | 80 | } |
76 | 81 |
|
|
323 | 328 | **/ |
324 | 329 | function spatNavSearch (dir, candidates, container) { |
325 | 330 | // Let container be the nearest ancestor of eventTarget that is a spatnav container. |
326 | | - let targetElement = this; |
| 331 | + const targetElement = this; |
327 | 332 | let bestCandidate = null; |
328 | 333 |
|
329 | 334 | candidates = spatNavCandidates(targetElement, dir, candidates, container); |
|
573 | 578 | } |
574 | 579 |
|
575 | 580 | function isCSSSpatNavContain(el) { |
576 | | - return (readCssVar(el, 'spatial-navigation-contain') == 'contain') ? true : false; |
| 581 | + return readCssVar(el, 'spatial-navigation-contain') == 'contain'; |
577 | 582 | } |
578 | 583 |
|
579 | 584 | /** |
|
1001 | 1006 | * @returns {Number} euclidian distance between two elements |
1002 | 1007 | **/ |
1003 | 1008 | function getEntryAndExitPoints(dir = 'down', rect1, rect2) { |
1004 | | - let points = {entryPoint:[0,0], exitPoint:[0,0]}; |
| 1009 | + const points = {entryPoint:[0,0], exitPoint:[0,0]}; |
1005 | 1010 |
|
1006 | 1011 | // Set direction |
1007 | 1012 | switch (dir) { |
|
1146 | 1151 |
|
1147 | 1152 |
|
1148 | 1153 | function addNonStandardAPI() { |
1149 | | - function isScrollableElement(container, dir) { |
| 1154 | + function canScroll(container, dir) { |
1150 | 1155 | return (isScrollable(container, dir) && !isScrollBoundary(container, dir)) || |
1151 | 1156 | (!container.parentElement && !isHTMLScrollBoundary(container, dir)); |
1152 | 1157 | } |
|
1179 | 1184 | return bestNextTarget; |
1180 | 1185 | } |
1181 | 1186 | } |
1182 | | - if (isScrollableElement(eventTarget, dir)) { |
| 1187 | + if (canScroll(eventTarget, dir)) { |
1183 | 1188 | if(findCandidate) { |
1184 | 1189 | return []; |
1185 | 1190 | } else { |
|
1221 | 1226 | // If there isn't any candidate and the best candidate among candidate: |
1222 | 1227 | // 1) Scroll or 2) Find candidates of the ancestor container |
1223 | 1228 | // 8 - if |
1224 | | - else if (isScrollableElement(container, dir)) { |
| 1229 | + else if (canScroll(container, dir)) { |
1225 | 1230 | if(findCandidate) { |
1226 | 1231 | return []; |
1227 | 1232 | } else { |
|
1239 | 1244 | eventTarget = window.frameElement; |
1240 | 1245 | container = window.parent.document.documentElement; |
1241 | 1246 | } |
1242 | | - else { |
1243 | | - if(findCandidate) { |
1244 | | - return []; |
1245 | | - } else { |
1246 | | - return null; |
1247 | | - } |
| 1247 | + else if(findCandidate) { |
| 1248 | + return []; |
| 1249 | + } else { |
| 1250 | + return null; |
1248 | 1251 | } |
1249 | 1252 |
|
1250 | 1253 | parentContainer = container.getSpatnavContainer(); |
|
1278 | 1281 | } |
1279 | 1282 | } |
1280 | 1283 |
|
1281 | | - if (isScrollableElement(container, dir)) { |
| 1284 | + if (canScroll(container, dir)) { |
1282 | 1285 | bestNextTarget = eventTarget; |
1283 | 1286 | return bestNextTarget; |
1284 | 1287 | } |
|
1288 | 1291 | isContainer: isContainer, |
1289 | 1292 | findCandidates: findTarget.bind(null, true), |
1290 | 1293 | findNextTarget: findTarget.bind(null, false), |
1291 | | - getDistance: (element, candidateElement, dir) => { |
| 1294 | + getDistanceFromTarget: (element, candidateElement, dir) => { |
1292 | 1295 | if ((isContainer(element) || element.nodeName === 'BODY') && !(element.nodeName === 'INPUT')) { |
1293 | 1296 | if (element.focusableAreas().includes(candidateElement)) { |
1294 | 1297 | return getInnerDistance(element.getBoundingClientRect(), candidateElement.getBoundingClientRect(), dir); |
|
1297 | 1300 | return getDistance(element.getBoundingClientRect(), candidateElement.getBoundingClientRect(), dir); |
1298 | 1301 | }, |
1299 | 1302 |
|
1300 | | - setPolyfillOnOff: (option) => { |
1301 | | - switch(option) { |
1302 | | - case 'SHIFTARROW': |
1303 | | - window.spatnavPolyfillOff = false; |
1304 | | - if(parent) { |
1305 | | - parent.spatnavPolyfillOff = false; |
1306 | | - } |
1307 | | - shiftArrow = true; |
1308 | | - break; |
1309 | | - case 'OFF': |
1310 | | - window.spatnavPolyfillOff = true; |
1311 | | - break; |
1312 | | - case 'ARROW': |
1313 | | - default: |
1314 | | - window.spatnavPolyfillOff = false; |
1315 | | - if(parent) { |
1316 | | - parent.spatnavPolyfillOff = false; |
1317 | | - } |
1318 | | - shiftArrow = false; |
1319 | | - break; |
| 1303 | + setKeyMode : (option) => { |
| 1304 | + if(['SHIFTARROW', 'ARROW', 'NONE'].includes(option)) { |
| 1305 | + spatialNaviagtionKeyMode = option; |
| 1306 | + } else { |
| 1307 | + spatialNaviagtionKeyMode = 'ARROW'; |
1320 | 1308 | } |
1321 | | - } |
| 1309 | + }, |
| 1310 | + |
| 1311 | + getKeyMode : () => spatialNaviagtionKeyMode |
1322 | 1312 | }; |
1323 | 1313 | } |
1324 | 1314 | addNonStandardAPI(); |
|
0 commit comments