File: development/modules/accordion/js/list.js
import $ from 'jquery';
import DOMModule from '../../__base/dommodule';
import Accordion from './accordion';
/** @module Modules */
const AccordionListStates = [
{name: 'init', events: {render: 'rendered'}},
{name: 'rendered', events: {start: 'running'}},
{name: 'running', events: {}}
];
// PRIVATE METHODS
const handleClick = Symbol('_handleClick');
/**
* AccordionList module
* @class Modules.AccordionList
* @constructor
* @extends Modules._DOMModule
*/
class AccordionList extends DOMModule {
constructor(options) {
super(options);
this.addStates(AccordionListStates);
this.autoOpenFirst = this.$data('accordion-openfirst') || false;
}
/**
* Creates a new AccordionList instance without the "new" keyword but does not
* initialize it
* @method of
* @static
* @for Modules.AccordionList
* @param {node|string|configs} node Node, CSS selector or configuration object
* @return {AccordionList} A new instance
*
* @example
* import AccordionList from './modules/accordion/js/list';
*
* const myList = AccordionList.of('[data-widget=AccordionList]');
* myList.render().startUp();
*/
static of (node) {
return new AccordionList(node);
}
/**
* Finds and initializes all AccordionLists on a page at once
* @method findAll
* @static
* @for Modules.AccordionList
* @param {string} selector CSS selector to match nodes against
* @return {array} A list of instances
*
* @example
* import AccordionList from './modules/accordion/js/list';
*
* AccordionList.findAll('[data-widget=AccordionList]');
*/
static findAll(selector) {
return $(selector).toArray().map((node) => {
const acc = AccordionList.of(node);
acc.render().startUp();
return acc;
});
}
/**
* Renders the inner Accordion instances and starts them
* @method render
* @for Modules.AccordionList
* @return {this} The instance
*
* @example
* import AccordionList from './modules/accordion/js/list';
*
* const myList = AccordionList.of('[data-widget=AccordionList]');
* myList.render();
*/
render() {
if (this.getState() === 'init') {
this.consume('render');
this.$accordions = this.$findChilds('[data-widget="Accordion"]').
toArray().
map((node) => {
const accordion = Accordion.of(node);
accordion.render().startUp();
return accordion;
});
this.activeAccordion = this.$accordions[0];
}
return this;
}
/**
* Attaches eventlisteners to the instance
* @method startUp
* @for Modules.AccordionList
* @return {undefined} Nothing
*
* @example
* import AccordionList from './modules/accordion/js/list';
*
* const myList = AccordionList.of('[data-widget=AccordionList]');
* myList.render().startUp();
*/
startUp() {
if (this.getState() === 'rendered') {
this.consume('start');
this.onClick('[data-accordion-action]', handleClick);
if (this.autoOpenFirst) {
this.activeAccordion.show();
}
}
}
// === PRIVATE STUFF ===
/**
* Used when an inner accordion is clicked. Takes a DOMNode and returns the
* accordion which contains the node or null
* @method _getClicked
* @for Modules.AccordionList
* @private
* @param {DOMNode} node The node to match against
* @return {Accordion|null} The matched instance or nothing
*/
_getClicked(node) {
return this.$accordions.reduce((match, acc) => {
return !match && acc.$headNode[0] === node ? acc : match;
}, null);
}
// === EVENT HANDLERS ===
[handleClick](event) {
if (event.currentTarget === this.activeAccordion.$headNode[0]) {
return null;
}
this.activeAccordion.hide();
this.activeAccordion = this._getClicked(event.currentTarget);
this.activeAccordion.show();
}
}
export default AccordionList;