Advertisement
Venelin

acc

Feb 10th, 2023
2,230
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
jQuery 3.66 KB | None | 0 0
  1. import { KEY_DOWN, KEY_UP, KEY_HOME, KEY_END } from "keycode-js";
  2. import * as $ from "jquery";
  3.  
  4. const Accordion = ({ element = document.querySelector("[data-accordion]") } = {}) => {
  5.     const $element = $(element);
  6.     const $accordionTitles = $element.children("[data-accordion-title]");
  7.     const $accordionPanels = $element.children("[data-accordion-panel]");
  8.  
  9.     const state = {
  10.         accordion: [],
  11.     };
  12.  
  13.     const initAccordionScaffoldingAndState = () => {
  14.         // Setup accordion title
  15.         $accordionTitles.each((index, accordionTitle) => {
  16.             const $accordionTitle = $(accordionTitle);
  17.             const accordionId = $(accordionTitle).data("accordion-id");
  18.  
  19.             // Wrap initial title content in button with accessible labels
  20.             const $accessibleTitleButton = $(`<button class="accordion__button">${$accordionTitle.html()}</button>`);
  21.             $accessibleTitleButton.attr("id", accordionId);
  22.             $accessibleTitleButton.attr("aria-expanded", "false");
  23.             $accessibleTitleButton.attr("aria-controls", `${accordionId}-panel`);
  24.  
  25.             $accordionTitle.html($accessibleTitleButton);
  26.  
  27.             state.accordion.push({
  28.                 index,
  29.                 id: accordionId,
  30.                 titleTrigger: $accessibleTitleButton,
  31.                 panelEl: undefined,
  32.                 isOpened: false,
  33.             });
  34.         });
  35.  
  36.         // Setup accordion panel
  37.         $accordionPanels.each((index, accordionPanel) => {
  38.             const $accordionPanel = $(accordionPanel);
  39.             const accordionId = $(accordionPanel).data("accordion-id");
  40.  
  41.             $accordionPanel.attr("id", `${accordionId}-panel`);
  42.             $accordionPanel.attr("role", "region");
  43.             $accordionPanel.attr("aria-labelledby", accordionId);
  44.  
  45.             const accordionState = state.accordion.find(accordion => accordion.id === accordionId);
  46.  
  47.             if (accordionState) {
  48.                 accordionState.panelEl = $accordionPanel;
  49.  
  50.                 if (!accordionState.isOpened) {
  51.                     accordionState.panelEl.hide();
  52.                 }
  53.             }
  54.         });
  55.     };
  56.  
  57.     const attachEventListener = () => {
  58.         state.accordion.forEach(accordion => {
  59.             if (!accordion.panelEl) {
  60.                 console.warn(`Accordion "${accordion.id}" does not have a matching panel`);
  61.                 return;
  62.             }
  63.             accordion.titleTrigger.click(event => handleToggleAccordion(event, accordion));
  64.             accordion.titleTrigger.on("keydown", event => handleAccordionNavigation(event, accordion));
  65.         });
  66.     };
  67.  
  68.     const handleToggleAccordion = (event, accordion) => {
  69.         event.preventDefault();
  70.  
  71.         if (accordion.isOpened) {
  72.             accordion.panelEl.slideUp();
  73.         } else {
  74.             accordion.panelEl.slideDown();
  75.         }
  76.  
  77.         accordion.isOpened = !accordion.isOpened;
  78.         accordion.titleTrigger.attr("aria-expanded", accordion.isOpened);
  79.     };
  80.  
  81.     const handleAccordionNavigation = (event, accordion) => {
  82.         if (
  83.             event.type === "keydown" &&
  84.             event.keyCode !== KEY_UP &&
  85.             event.keyCode !== KEY_DOWN &&
  86.             event.keyCode !== KEY_HOME &&
  87.             event.keyCode !== KEY_END
  88.         ) {
  89.             return;
  90.         }
  91.  
  92.         event.preventDefault();
  93.  
  94.         let newFocusIndex = 0;
  95.  
  96.         if (event.keyCode === KEY_UP || event.keyCode === KEY_DOWN) {
  97.             if (event.keyCode === KEY_UP) {
  98.                 newFocusIndex = accordion.index - 1;
  99.  
  100.                 if (accordion.index === 0) {
  101.                     newFocusIndex = state.accordion.length - 1;
  102.                 }
  103.             }
  104.  
  105.             if (event.keyCode === KEY_DOWN) {
  106.                 newFocusIndex = accordion.index + 1;
  107.  
  108.                 if (accordion.index === state.accordion.length - 1) {
  109.                     newFocusIndex = 0;
  110.                 }
  111.             }
  112.         }
  113.  
  114.         if (event.keyCode === KEY_HOME || event.keyCode === KEY_END) {
  115.             if (event.keyCode === KEY_HOME) {
  116.                 newFocusIndex = 0;
  117.             }
  118.  
  119.             if (event.keyCode === KEY_END) {
  120.                 newFocusIndex = state.accordion.length - 1;
  121.             }
  122.         }
  123.  
  124.         state.accordion[newFocusIndex].titleTrigger.focus();
  125.     };
  126.  
  127.     initAccordionScaffoldingAndState();
  128.     attachEventListener();
  129. };
  130.  
  131. export default Accordion;
  132. export { Accordion };
  133.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement