All files / public accordion.ts

76.31% Statements 29/38
50% Branches 7/14
75% Functions 6/8
76.31% Lines 29/38

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93      2x 8x 8x 8x 8x               3x     3x 2x 2x     2x   2x 2x     2x 2x     2x         3x     3x 3x                                                       2x 2x   2x     2x     2x 2x 2x       2x 2x 2x   2x      
// based on Vanilla accordion example
// https://github.com/vanilla-framework/vanilla-framework/blob/develop/examples/patterns/accordion.html
 
export const toggleAccordion = (element: HTMLElement, show: boolean): void => {
  element.setAttribute("aria-expanded", show.toString());
  const controlElId: string = `#${element.getAttribute("aria-controls")}`;
  const controlEl = document.querySelector(controlElId) as HTMLElement;
  controlEl.setAttribute("aria-hidden", `${show ? "false" : "true"}`);
};
 
export default function initAccordion(
  accordionContainerSelector: string,
): void {
  // Set up an event listener on the container so that panels can be added
  // and removed and events do not need to be managed separately.
  const accordionContainer = document.querySelector(
    accordionContainerSelector,
  ) as HTMLElement;
  accordionContainer.addEventListener("click", (e) => {
    const targetEl = e.target as HTMLElement;
    const target = targetEl.closest(
      "[class*='p-accordion__tab']",
    ) as HTMLButtonElement;
    Eif (target && !target.disabled) {
      // Find any open panels within the container and close them.
      const currentTarget = e.currentTarget as HTMLElement;
      const expandedElements = currentTarget.querySelectorAll(
        "[aria-expanded=true]",
      ) as NodeListOf<HTMLElement>;
      Array.from(expandedElements).forEach((element: HTMLElement) =>
        toggleAccordion(element, false),
      );
      // Open the target.
      toggleAccordion(target, true);
    }
  });
 
  // Add event listeners to buttons that expand the next section of the accordion
  const nextButtons = [].slice.call(
    document.querySelectorAll("[data-js='js-accordion-next-button']"),
  );
  Eif (nextButtons) {
    nextButtons.forEach((button: HTMLButtonElement) => {
      button.addEventListener("click", (e) => {
        e.preventDefault();
 
        const currentPanel = button.closest(
          ".p-accordion__group",
        ) as HTMLElement;
        const currentToggle = currentPanel.querySelector(
          "[class*='p-accordion__tab']",
        ) as HTMLElement;
        const nextPanel = currentPanel.nextElementSibling as HTMLElement;
        const nextToggle = nextPanel.querySelector(
          "[class*='p-accordion__tab']",
        ) as HTMLElement;
 
        if (currentPanel && nextPanel) {
          toggleAccordion(currentToggle, false);
          toggleAccordion(nextToggle, true);
        }
      });
    });
  }
}
 
/**
  Attaches click event to a button to close current accordion tab and open next one.
*/
export function initAccordionButtons(continueButton: HTMLButtonElement): void {
  continueButton.addEventListener("click", (event) => {
    event.preventDefault();
 
    const currentPanel = continueButton.closest(
      ".p-accordion__group",
    ) as HTMLElement;
    const currentToggle = currentPanel.querySelector(
      "[class*='p-accordion__tab']",
    ) as HTMLElement;
    const currentSuccess = currentPanel.querySelector(".p-icon--success");
    const nextPanel = currentPanel.nextElementSibling as HTMLElement;
    const nextToggle = nextPanel.querySelector(
      "[class*='p-accordion__tab']",
    ) as HTMLElement;
 
    toggleAccordion(currentToggle, false);
    Eif (currentSuccess) {
      currentSuccess.classList.remove("u-hide");
    }
    toggleAccordion(nextToggle, true);
  });
}