| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- 'use strict';
- var isDisabled = require('../misc/isDisabled.js');
- var isElementType = require('../misc/isElementType.js');
- var isVisible = require('../misc/isVisible.js');
- var selector = require('./selector.js');
- function getTabDestination(activeElement, shift) {
- const document = activeElement.ownerDocument;
- const focusableElements = document.querySelectorAll(selector.FOCUSABLE_SELECTOR);
- const enabledElements = Array.from(focusableElements).filter((el)=>el === activeElement || !(Number(el.getAttribute('tabindex')) < 0 || isDisabled.isDisabled(el)));
- // tabindex has no effect if the active element has negative tabindex
- if (Number(activeElement.getAttribute('tabindex')) >= 0) {
- enabledElements.sort((a, b)=>{
- const i = Number(a.getAttribute('tabindex'));
- const j = Number(b.getAttribute('tabindex'));
- if (i === j) {
- return 0;
- } else if (i === 0) {
- return 1;
- } else if (j === 0) {
- return -1;
- }
- return i - j;
- });
- }
- const checkedRadio = {};
- let prunedElements = [
- document.body
- ];
- const activeRadioGroup = isElementType.isElementType(activeElement, 'input', {
- type: 'radio'
- }) ? activeElement.name : undefined;
- enabledElements.forEach((currentElement)=>{
- const el = currentElement;
- // For radio groups keep only the active radio
- // If there is no active radio, keep only the checked radio
- // If there is no checked radio, treat like everything else
- if (isElementType.isElementType(el, 'input', {
- type: 'radio'
- }) && el.name) {
- // If the active element is part of the group, add only that
- if (el === activeElement) {
- prunedElements.push(el);
- return;
- } else if (el.name === activeRadioGroup) {
- return;
- }
- // If we stumble upon a checked radio, remove the others
- if (el.checked) {
- prunedElements = prunedElements.filter((e)=>!isElementType.isElementType(e, 'input', {
- type: 'radio',
- name: el.name
- }));
- prunedElements.push(el);
- checkedRadio[el.name] = el;
- return;
- }
- // If we already found the checked one, skip
- if (typeof checkedRadio[el.name] !== 'undefined') {
- return;
- }
- }
- prunedElements.push(el);
- });
- for(let index = prunedElements.findIndex((el)=>el === activeElement);;){
- index += shift ? -1 : 1;
- // loop at overflow
- if (index === prunedElements.length) {
- index = 0;
- } else if (index === -1) {
- index = prunedElements.length - 1;
- }
- if (prunedElements[index] === activeElement || prunedElements[index] === document.body || isVisible.isVisible(prunedElements[index])) {
- return prunedElements[index];
- }
- }
- }
- exports.getTabDestination = getTabDestination;
|