Skip to content

Commit

Permalink
Replace calls to appendChild with new option in createElement
Browse files Browse the repository at this point in the history
Allows regrouping code for creating components a little more,
as well as getting rid of a couple of loops over child nodes
  • Loading branch information
romaricpascal committed Dec 17, 2024
1 parent 27b7a41 commit d7f1a99
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 48 deletions.
9 changes: 8 additions & 1 deletion packages/govuk-frontend/src/govuk/common/create-element.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,20 @@
* @template {keyof HTMLElementTagNameMap} TagName
* @param {TagName} tagName - Type of element to create
* @param {{[key: string]: string}} [attributes] - Attributes to set on the element
* @param {Node[]} [children] - The list of child nodes for the element
* @returns {HTMLElementTagNameMap[TagName]} Created element
*/
export function createElement(tagName, attributes = {}) {
export function createElement(tagName, attributes = {}, children) {
const el = document.createElement(tagName)
Object.entries(attributes).forEach(([name, value]) => {
el.setAttribute(name, value)
})

if (children) {
for (const child of children) {
el.appendChild(child)
}
}

return el
}
Original file line number Diff line number Diff line change
Expand Up @@ -245,30 +245,32 @@ export class Accordion extends ConfigurableComponent {
*/
createShowHideToggle() {
// Create an inner container to limit the width of the focus state
const $showHideToggleFocus = createElement('span', {
class: 'govuk-accordion__section-toggle-focus'
})

$showHideToggleFocus.appendChild(
createElement('span', {
class: iconClass
})
)
$showHideToggleFocus.appendChild(
createElement('span', {
class: sectionToggleTextClass
})
const $showHideToggleFocus = createElement(
'span',
{
class: 'govuk-accordion__section-toggle-focus'
},
[
createElement('span', {
class: iconClass
}),
createElement('span', {
class: sectionToggleTextClass
})
]
)

const $showHideToggle = createElement('span', {
class: 'govuk-accordion__section-toggle',
// Tell Google not to index the 'show' text as part of the heading. Must be
// set on the element before it's added to the DOM.
// See https://developers.google.com/search/docs/advanced/robots/robots_meta_tag#data-nosnippet-attr
'data-nosnippet': ''
})

$showHideToggle.appendChild($showHideToggleFocus)
const $showHideToggle = createElement(
'span',
{
class: 'govuk-accordion__section-toggle',
// Tell Google not to index the 'show' text as part of the heading. Must be
// set on the element before it's added to the DOM.
// See https://developers.google.com/search/docs/advanced/robots/robots_meta_tag#data-nosnippet-attr
'data-nosnippet': ''
},
[$showHideToggleFocus]
)

return $showHideToggle
}
Expand All @@ -282,23 +284,25 @@ export class Accordion extends ConfigurableComponent {
createHeadingText($span) {
// Create an inner heading text container to limit the width of the focus
// state
const $headingTextFocus = createElement('span', {
class: 'govuk-accordion__section-heading-text-focus'
})

// span could contain HTML elements which need moving to the new span
// (see https://www.w3.org/TR/2011/WD-html5-20110525/content-models.html#phrasing-content)
Array.from($span.childNodes).forEach(($child) =>
$headingTextFocus.appendChild($child)
const $headingTextFocus = createElement(
'span',
{
class: 'govuk-accordion__section-heading-text-focus'
},
// span could contain HTML elements which need moving to the new span
// (see https://www.w3.org/TR/2011/WD-html5-20110525/content-models.html#phrasing-content)
Array.from($span.childNodes)
)

// Create container for heading text so it can be styled
const $headingText = createElement('span', {
class: sectionHeadingTextClass,
id: $span.id
})

$headingText.appendChild($headingTextFocus)
const $headingText = createElement(
'span',
{
class: sectionHeadingTextClass,
id: $span.id
},
[$headingTextFocus]
)

return $headingText
}
Expand All @@ -316,24 +320,21 @@ export class Accordion extends ConfigurableComponent {
createSummarySpan($summary) {
// Create an inner summary container to limit the width of the summary
// focus state
const $summarySpanFocus = createElement('span', {
class: 'govuk-accordion__section-summary-focus'
})

const $summarySpan = createElement('span')
const $summarySpanFocus = createElement(
'span',
{
class: 'govuk-accordion__section-summary-focus'
},
Array.from($summary.childNodes)
)

$summarySpan.appendChild($summarySpanFocus)
const $summarySpan = createElement('span', {}, [$summarySpanFocus])

// Get original attributes, and pass them to the replacement
for (const attr of Array.from($summary.attributes)) {
$summarySpan.setAttribute(attr.name, attr.value)
}

// Copy original contents of summary to the new summary span
Array.from($summary.childNodes).forEach(($child) =>
$summarySpanFocus.appendChild($child)
)

return $summarySpan
}

Expand Down

0 comments on commit d7f1a99

Please sign in to comment.