Skip to content

Commit

Permalink
Add items inside Section, instead of using SectionItem
Browse files Browse the repository at this point in the history
This approach is more consistent with our other components such
as Tabs which deals with multiple items and has a single function.
This approach also avoids having to pass Accordion as reference to
AccordionSection.(But having multiple functions is valid too and we
might employ it in future when building quite complex JavaScript
components that need to retain state in multiple places.)

This commit:
- Creates items inside Section init and binds them
- Defines $sections at top level
- Moves header related functionality to a single function
  • Loading branch information
hannalaakso committed Aug 30, 2018
1 parent cbb8674 commit 4fad5c1
Showing 1 changed file with 43 additions and 51 deletions.
94 changes: 43 additions & 51 deletions src/components/accordion/accordion.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,27 @@ import '../../vendor/polyfills/Element/prototype/classList'

function Accordion ($module) {
this.$module = $module
this.$sections = $module.querySelectorAll('.govuk-accordion__section')
}

Accordion.prototype.init = function () {
this.sections = []

var accordionSections = this.$module.querySelectorAll('.govuk-accordion__section')

var accordion = this

for (var i = accordionSections.length - 1; i >= 0; i--) {
accordion.sections.push(new AccordionSection(accordionSections[i], accordion))
};
nodeListForEach(this.$sections, function ($section) {
// Set header attributes
var header = $section.querySelector('.govuk-accordion__section-header')
this.setHeaderAttributes(header)

var sectionExpanded = $section.classList.contains('govuk-accordion__section--expanded')
$section.setAttribute('aria-expanded', sectionExpanded)

/* Remove this class now, as the `aria-expanded` attribute is being used
to store expanded state instead. */
if (sectionExpanded) {
this.$module.classList.remove('govuk-accordion__section--expanded')
}
// Handle events
header.addEventListener('keypress', this.onKeyPressed.bind(this, $section))
header.addEventListener('click', this.onToggleExpanded.bind(this, $section))
}.bind(this))

var accordionControls = document.createElement('div')
accordionControls.setAttribute('class', 'govuk-accordion__controls')
Expand Down Expand Up @@ -70,12 +79,13 @@ Accordion.prototype.setOpenCloseButtonExpanded = function (expanded) {
}

Accordion.prototype.updateOpenAll = function () {
var sectionsCount = this.sections.length
var $sections = this.$sections
var sectionsCount = $sections.length

var openSectionsCount = 0

for (var i = this.sections.length - 1; i >= 0; i--) {
if (this.sections[i].expanded()) {
for (var i = $sections.length - 1; i >= 0; i--) {
if (this.isExpanded($sections[i])) {
openSectionsCount += 1
}
};
Expand All @@ -87,59 +97,41 @@ Accordion.prototype.updateOpenAll = function () {
}
}

function AccordionSection (element, accordion) {
this.$module = element
this.accordion = accordion
this.setup()
}

AccordionSection.prototype.setup = function () {
var sectionExpanded = this.$module.classList.contains('govuk-accordion__section--expanded')

this.$module.setAttribute('aria-expanded', sectionExpanded)

var header = this.$module.querySelector('.govuk-accordion__section-header')
header.addEventListener('click', this.toggleExpanded.bind(this))
header.addEventListener('keypress', this.keyPressed.bind(this))
header.setAttribute('tabindex', '0')
header.setAttribute('role', 'button')

var icon = document.createElement('span')
icon.setAttribute('class', 'govuk-accordion--icon')

header.appendChild(icon)

/* Remove this class now, as the `aria-expanded` attribute is being used
to store expanded state instead. */
if (sectionExpanded) {
this.$module.classList.remove('govuk-accordion__section--expanded')
}
}

AccordionSection.prototype.toggleExpanded = function () {
var expanded = (this.$module.getAttribute('aria-expanded') === 'true')
Accordion.prototype.onToggleExpanded = function ($section) {
var expanded = ($section.getAttribute('aria-expanded') === 'true')

this.setExpanded(!expanded)
this.accordion.updateOpenAll()
this.setExpanded(!expanded, $section)
this.updateOpenAll()
}

AccordionSection.prototype.keyPressed = function (event) {
Accordion.prototype.onKeyPressed = function (section, event) {
if (event.key === ' ' || event.key === 'Enter') {
event.preventDefault()
this.toggleExpanded()
this.onToggleExpanded(section)
}
}

AccordionSection.prototype.expanded = function () {
return (this.$module.getAttribute('aria-expanded') === 'true')
Accordion.prototype.isExpanded = function ($section) {
return ($section.getAttribute('aria-expanded') === 'true')
}

AccordionSection.prototype.setExpanded = function (expanded) {
this.$module.setAttribute('aria-expanded', expanded)
// Toggle aria-expanded when section opened/closed
Accordion.prototype.setExpanded = function (expanded, $section) {
$section.setAttribute('aria-expanded', expanded)

// This is set to trigger reflow for IE8, which doesn't
// always reflow after a setAttribute call.
this.$module.className = this.$module.className
}

Accordion.prototype.setHeaderAttributes = function ($header) {
$header.setAttribute('tabindex', '0')
$header.setAttribute('role', 'button')

var icon = document.createElement('span')
icon.setAttribute('class', 'govuk-accordion--icon')

$header.appendChild(icon)
}

export default Accordion

0 comments on commit 4fad5c1

Please sign in to comment.