Socket
Socket
Sign inDemoInstall

@ecl/ec-component-accordion

Package Overview
Dependencies
Maintainers
3
Versions
59
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ecl/ec-component-accordion - npm Package Compare versions

Comparing version 1.2.0 to 2.1.0

LICENSE

207

ec-component-accordion.js

@@ -1,162 +0,87 @@

// Heavily inspired by the accordion component from https://github.com/frend/frend.co
import { queryOne, queryAll } from '@ecl/ec-base/helpers/dom';
import { queryAll } from '@ecl/ec-base/helpers/dom';
class Accordion {
constructor(
element,
{
toggleSelector: toggleSelector = '[data-ecl-accordion-toggle]',
attachClickListener: attachClickListener = true,
} = {}
) {
// Check element
if (!element || element.nodeType !== Node.ELEMENT_NODE) {
throw new TypeError(
'DOM element should be given to initialize this widget.'
);
}
/**
* @param {object} options Object containing configuration overrides
*/
export const accordions = ({
selector: selector = '.ecl-accordion',
headerSelector: headerSelector = '.ecl-accordion__header',
} = {}) => {
// SUPPORTS
if (
!('querySelector' in document) ||
!('addEventListener' in window) ||
!document.documentElement.classList
)
return null;
this.element = element;
// SETUP
// set accordion element NodeLists
const accordionContainers = queryAll(selector);
// Options
this.toggleSelector = toggleSelector;
this.attachClickListener = attachClickListener;
// ACTIONS
function hidePanel(target) {
// get panel
const activePanel = document.getElementById(
target.getAttribute('aria-controls')
);
// Private variables
this.toggles = null;
this.forceClose = false;
this.target = null;
this.label = null;
target.setAttribute('aria-expanded', 'false');
// toggle aria-hidden
activePanel.setAttribute('aria-hidden', 'true');
// Bind `this` for use in callbacks
this.handleClickOnToggle = this.handleClickOnToggle.bind(this);
}
function showPanel(target) {
// get panel
const activePanel = document.getElementById(
target.getAttribute('aria-controls')
);
init() {
this.toggles = queryAll(this.toggleSelector, this.element);
// set attributes on header
target.setAttribute('tabindex', 0);
target.setAttribute('aria-expanded', 'true');
// Get label, if any
this.label = queryOne(this.labelSelector, this.element);
// toggle aria-hidden and set height on panel
activePanel.setAttribute('aria-hidden', 'false');
// Bind click event on toggles
if (this.attachClickListener && this.toggles) {
this.toggles.forEach(toggle => {
toggle.addEventListener(
'click',
this.handleClickOnToggle.bind(this, toggle)
);
});
}
}
function togglePanel(target) {
// close target panel if already active
if (target.getAttribute('aria-expanded') === 'true') {
hidePanel(target);
return;
destroy() {
if (this.attachClickListener && this.toggle) {
this.toggles.forEach(toggle => {
toggle.removeEventListener('click', this.handleClickOnToggle);
});
}
showPanel(target);
}
function giveHeaderFocus(headerSet, i) {
// set active focus
headerSet[i].focus();
}
handleClickOnToggle(toggle) {
// Get target element
const target = queryOne(`#${toggle.getAttribute('aria-controls')}`);
// EVENTS
function eventHeaderClick(e) {
togglePanel(e.currentTarget);
}
// Exit if no target found
if (!target) {
throw new TypeError(
'Target has to be provided for accordion (aria-controls)'
);
}
function eventHeaderKeydown(e) {
// collect header targets, and their prev/next
const currentHeader = e.currentTarget;
const isModifierKey = e.metaKey || e.altKey;
// get context of accordion container and its children
const thisContainer = currentHeader.parentNode.parentNode;
const theseHeaders = queryAll(headerSelector, thisContainer);
const currentHeaderIndex = [].indexOf.call(theseHeaders, currentHeader);
// Get current status
const isExpanded =
this.forceClose === true ||
toggle.getAttribute('aria-expanded') === 'true';
// don't catch key events when ⌘ or Alt modifier is present
if (isModifierKey) return;
// catch enter/space, left/right and up/down arrow key events
// if new panel show it, if next/prev move focus
switch (e.keyCode) {
case 13:
case 32:
togglePanel(currentHeader);
e.preventDefault();
break;
case 37:
case 38: {
const previousHeaderIndex =
currentHeaderIndex === 0
? theseHeaders.length - 1
: currentHeaderIndex - 1;
giveHeaderFocus(theseHeaders, previousHeaderIndex);
e.preventDefault();
break;
}
case 39:
case 40: {
const nextHeaderIndex =
currentHeaderIndex < theseHeaders.length - 1
? currentHeaderIndex + 1
: 0;
giveHeaderFocus(theseHeaders, nextHeaderIndex);
e.preventDefault();
break;
}
default:
break;
// Toggle the expandable/collapsible
toggle.setAttribute('aria-expanded', !isExpanded);
if (isExpanded) {
target.setAttribute('hidden', true);
} else {
target.removeAttribute('hidden');
}
}
// BIND EVENTS
function bindAccordionEvents(accordionContainer) {
const accordionHeaders = queryAll(headerSelector, accordionContainer);
// bind all accordion header click and keydown events
accordionHeaders.forEach(accordionHeader => {
accordionHeader.addEventListener('click', eventHeaderClick);
accordionHeader.addEventListener('keydown', eventHeaderKeydown);
});
return this;
}
}
// UNBIND EVENTS
function unbindAccordionEvents(accordionContainer) {
const accordionHeaders = queryAll(headerSelector, accordionContainer);
// unbind all accordion header click and keydown events
accordionHeaders.forEach(accordionHeader => {
accordionHeader.removeEventListener('click', eventHeaderClick);
accordionHeader.removeEventListener('keydown', eventHeaderKeydown);
});
}
// DESTROY
function destroy() {
accordionContainers.forEach(accordionContainer => {
unbindAccordionEvents(accordionContainer);
});
}
// INIT
function init() {
if (accordionContainers.length) {
accordionContainers.forEach(accordionContainer => {
bindAccordionEvents(accordionContainer);
});
}
}
init();
// REVEAL API
return {
init,
destroy,
};
};
// module exports
export default accordions;
export default Accordion;

@@ -5,12 +5,14 @@ {

"license": "EUPL-1.1",
"version": "1.2.0",
"description": "ECL Accordions",
"version": "2.1.0",
"description": "ECL EC Accordion",
"main": "ec-component-accordion.js",
"module": "ec-component-accordion.js",
"style": "ec-component-accordion.scss",
"sass": "ec-component-accordion.scss",
"dependencies": {
"@ecl/ec-base": "^1.0.0",
"@ecl/ec-style-icon": "^1.2.0",
"@ecl/ec-utility-colorize": "^1.0.0",
"@ecl/generic-component-accordion": "^1.2.0"
"@ecl/ec-base": "^2.1.0"
},
"devDependencies": {
"@ecl/ec-specs-accordion": "^2.1.0"
},
"publishConfig": {

@@ -32,4 +34,3 @@ "access": "public"

],
"main": "ec-component-accordion.js",
"sass": "ec-component-accordion.scss"
"gitHead": "6068cca85e387741556239826792ca27520fcf69"
}

@@ -1,36 +0,1 @@

# Accordions
## Why and how to use this component
If you need to present a lot of content on a page, it can be divided into
sub-sections in a structured way.
The accordion component is a list of headers that can be clicked to hide or
reveal additional content. It is also possible to add an icon to the headers.
## When to use this component
* when you have a large amount of information
* on FAQ pages
## Do not use this component
* as a rule avoid hiding information as much as possible
## Resources
* WAI-ARIA Authoring Practices
* Latest Version (14 December 2016)
* [https://www.w3.org/TR/2016/WD-wai-aria-practices-1.1-20161214/#accordion](https://www.w3.org/TR/2016/WD-wai-aria-practices-1.1-20161214/#accordion)
* [https://www.w3.org/TR/2016/WD-wai-aria-practices-1.1-20161214/examples/accordion/accordion1.html](https://www.w3.org/TR/2016/WD-wai-aria-practices-1.1-20161214/examples/accordion/accordion1.html)
* Current draft (as seen on 21 June 2017)
* [https://w3c.github.io/aria-practices/#accordion](https://w3c.github.io/aria-practices/#accordion)
* [https://w3c.github.io/aria-practices/examples/accordion/accordion.html](https://w3c.github.io/aria-practices/examples/accordion/accordion.html)
* Existing libraries
* [https://frend.co/components/accordion/](https://frend.co/components/accordion/)
# Accordion

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc