Passed
Push — task/improve-find-skills-modal... ( 73dfaf...ede470 )
by Yonathan
05:06
created

resources/assets/js/helpers/focus.ts   A

Complexity

Total Complexity 8
Complexity/F 0

Size

Lines of Code 88
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 8
eloc 52
dl 0
loc 88
rs 10
c 0
b 0
f 0
mnd 8
bc 8
fnc 0
bpm 0
cpm 0
noi 0
1
import { FormikProps, FormikValues } from "formik";
2
import isEmpty from "lodash/isEmpty";
3
import { RefObject } from "react";
4
import { notEmpty } from "./queries";
5
6
export const focusableElementSelector =
7
  "button:not([disabled]), [href], input:not([disabled]), select, textarea, [tabindex]:not([tabindex='-1'])";
8
9
/**
10
 * Get all focusable elements that are descendent of element,
11
 * or all focusable elements in the document body if element is null.
12
 */
13
export const getFocusableElements = (
14
  element: HTMLElement | null = null,
15
): NodeListOf<HTMLElement> =>
16
  element
17
    ? element.querySelectorAll<HTMLElement>(focusableElementSelector)
18
    : document.body.querySelectorAll<HTMLElement>(focusableElementSelector);
19
20
/**
21
 * Takes a selector or an HTMLElement and focuses on the element.
22
 * @param x
23
 */
24
export const focusOnElement = (x: HTMLElement | string): void => {
25
  if (typeof x === "string") {
26
    if (x === "") {
27
      return;
28
    }
29
    const element = document.querySelector(x) as HTMLElement;
30
    if (element) {
31
      element.focus();
32
    }
33
  } else {
34
    x.focus();
35
  }
36
};
37
38
/**
39
 * Toggle accordion with given id.
40
 * @param id
41
 */
42
export const toggleAccordion = (elementId: string): void => {
43
  const element = document.getElementById(elementId);
44
  if (element) {
45
    element.classList.toggle("active");
46
    const { firstElementChild } = element;
47
    if (firstElementChild) {
48
      firstElementChild.setAttribute("aria-expanded", "true");
49
    }
50
  }
51
};
52
53
/**
54
 * Focuses on the previous element in the list.
55
 * @param focusList List of focusable HTML elements.
56
 */
57
export const focusPreviousItem = (focusList: NodeListOf<HTMLElement>): void => {
58
  const item = document.activeElement as HTMLElement;
59
  const activeElementIndex = Array.from(focusList).findIndex(
60
    (focusItem) => item === focusItem,
61
  );
62
  // If, the active element is first in order then move focus to last element in the focus list.
63
  // Else, move to the previous element.
64
  if (activeElementIndex === 0) {
65
    focusList[focusList.length - 1].focus();
66
  } else {
67
    focusList[activeElementIndex - 1].focus();
68
  }
69
};
70
71
/**
72
 * Focuses on the next element in the list.
73
 * @param focusList List of focusable HTML elements.
74
 */
75
export const focusNextItem = (focusList: NodeListOf<HTMLElement>): void => {
76
  const item = document.activeElement as HTMLElement;
77
  const activeElementIndex = Array.from(focusList).findIndex(
78
    (focusItem) => item === focusItem,
79
  );
80
  // If, the active element is last in order then move focus to first element in the focus list.
81
  // Else, move to the previous element.
82
  if (activeElementIndex === focusList.length - 1) {
83
    focusList[0].focus();
84
  } else {
85
    focusList[activeElementIndex + 1].focus();
86
  }
87
};
88