Skip to content

Commit

Permalink
Ensure JSDoc blocks for source are complete
Browse files Browse the repository at this point in the history
All blocks are documented with a description, params, optional return (or throws) types and “this” where instantiated or bound
  • Loading branch information
colinrotherham committed Dec 15, 2022
1 parent a44596f commit f7f7f78
Show file tree
Hide file tree
Showing 14 changed files with 267 additions and 65 deletions.
27 changes: 17 additions & 10 deletions src/govuk/common/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*
* @param {NodeListOf<Element>} nodes - NodeList from querySelectorAll()
* @param {nodeListIterator} callback - Callback function to run for each node
* @returns {undefined}
* @returns {void}
*/
export function nodeListForEach (nodes, callback) {
if (window.NodeList.prototype.forEach) {
Expand Down Expand Up @@ -52,7 +52,7 @@ export function generateUniqueID () {
* (e.g. {'i18n.showSection': 'Show section'}) and combines them together, with
* greatest priority on the LAST item passed in.
*
* @returns {object} A flattened object of key-value pairs.
* @returns {Object<string, string>} A flattened object of key-value pairs.
*/
export function mergeConfigs (/* configObject1, configObject2, ...configObjects */) {
/**
Expand All @@ -61,16 +61,21 @@ export function mergeConfigs (/* configObject1, configObject2, ...configObjects
* each of our objects, nor transform our dataset from a flat list into a
* nested object.
*
* @param {object} configObject - Deeply nested object
* @returns {object} Flattened object with dot-separated keys
* @param {Object<string, any>} configObject - Deeply nested object
* @returns {Object<string, string>} Flattened object with dot-separated keys
*/
var flattenObject = function (configObject) {
// Prepare an empty return object
var flattenedObject = {}

// Our flattening function, this is called recursively for each level of
// depth in the object. At each level we prepend the previous level names to
// the key using `prefix`.
/**
* Our flattening function, this is called recursively for each level of
* depth in the object. At each level we prepend the previous level names to
* the key using `prefix`.
*
* @param {Object<string, any>} obj - Object to flatten
* @param {string} [prefix] - Optional dot-separated prefix
*/
var flattenLoop = function (obj, prefix) {
// Loop through keys...
for (var key in obj) {
Expand Down Expand Up @@ -118,9 +123,11 @@ export function mergeConfigs (/* configObject1, configObject2, ...configObjects
* Extracts keys starting with a particular namespace from a flattened config
* object, removing the namespace in the process.
*
* @param {object} configObject - The object to extract key-value pairs from.
* @param {Object<string, any>} configObject - The object to extract key-value pairs from.
* @param {string} namespace - The namespace to filter keys with.
* @returns {object} Flattened object with dot-separated key namespace removed
* @returns {Object<string, string>} Flattened object with dot-separated key namespace removed
* @throws {Error} Config object required
* @throws {Error} Namespace string required
*/
export function extractConfigByNamespace (configObject, namespace) {
// Check we have what we need
Expand Down Expand Up @@ -155,5 +162,5 @@ export function extractConfigByNamespace (configObject, namespace) {
* @param {Element} value - The current node being iterated on
* @param {number} index - The current index in the iteration
* @param {NodeListOf<Element>} nodes - NodeList from querySelectorAll()
* @returns {undefined}
* @returns {void}
*/
83 changes: 68 additions & 15 deletions src/govuk/components/accordion/accordion.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ var ACCORDION_TRANSLATIONS = {
* @class
* @param {HTMLElement} $module - HTML element to use for accordion
* @param {AccordionConfig} [config] - Accordion config
* @this {Accordion}
*/
function Accordion ($module, config) {
this.$module = $module
Expand Down Expand Up @@ -75,7 +76,9 @@ function Accordion ($module, config) {
this.sectionContentClass = 'govuk-accordion__section-content'
}

// Initialize component
/**
* Initialise component
*/
Accordion.prototype.init = function () {
// Check for module
if (!this.$module) {
Expand All @@ -90,7 +93,9 @@ Accordion.prototype.init = function () {
this.updateShowAllButton(areAllSectionsOpen)
}

// Initialise controls and set attributes
/**
* Initialise controls and set attributes
*/
Accordion.prototype.initControls = function () {
// Create "Show all" button and set attributes
this.$showAllButton = document.createElement('button')
Expand Down Expand Up @@ -123,7 +128,9 @@ Accordion.prototype.initControls = function () {
}
}

// Initialise section headers
/**
* Initialise section headers
*/
Accordion.prototype.initSectionHeaders = function () {
// Loop through section headers
nodeListForEach(this.$sections, function ($section, i) {
Expand All @@ -141,6 +148,12 @@ Accordion.prototype.initSectionHeaders = function () {
}.bind(this))
}

/**
* Construct section header
*
* @param {HTMLDivElement} $headerWrapper - Section header wrapper
* @param {number} index - Section index
*/
Accordion.prototype.constructHeaderMarkup = function ($headerWrapper, index) {
var $span = $headerWrapper.querySelector('.' + this.sectionButtonClass)
var $heading = $headerWrapper.querySelector('.' + this.sectionHeadingClass)
Expand Down Expand Up @@ -237,15 +250,23 @@ Accordion.prototype.constructHeaderMarkup = function ($headerWrapper, index) {
$heading.appendChild($button)
}

// When a section is opened by the user agent via the 'beforematch' event
/**
* When a section is opened by the user agent via the 'beforematch' event
*
* @param {Event} event - Generic event
*/
Accordion.prototype.onBeforeMatch = function (event) {
var $section = event.target.closest('.' + this.sectionClass)
if ($section) {
this.setExpanded(true, $section)
}
}

// When section toggled, set and store state
/**
* When section toggled, set and store state
*
* @param {HTMLElement} $section - Section element
*/
Accordion.prototype.onSectionToggle = function ($section) {
var expanded = this.isExpanded($section)
this.setExpanded(!expanded, $section)
Expand All @@ -254,7 +275,9 @@ Accordion.prototype.onSectionToggle = function ($section) {
this.storeState($section)
}

// When Open/Close All toggled, set and store state
/**
* When Open/Close All toggled, set and store state
*/
Accordion.prototype.onShowOrHideAllToggle = function () {
var $module = this
var $sections = this.$sections
Expand All @@ -269,7 +292,12 @@ Accordion.prototype.onShowOrHideAllToggle = function () {
$module.updateShowAllButton(nowExpanded)
}

// Set section attributes when opened/closed
/**
* Set section attributes when opened/closed
*
* @param {boolean} expanded - Section expanded
* @param {HTMLElement} $section - Section element
*/
Accordion.prototype.setExpanded = function (expanded, $section) {
var $icon = $section.querySelector('.' + this.upChevronIconClass)
var $showHideText = $section.querySelector('.' + this.sectionShowHideTextClass)
Expand Down Expand Up @@ -320,12 +348,21 @@ Accordion.prototype.setExpanded = function (expanded, $section) {
this.updateShowAllButton(areAllSectionsOpen)
}

// Get state of section
/**
* Get state of section
*
* @param {HTMLElement} $section - Section element
* @returns {boolean} True if expanded
*/
Accordion.prototype.isExpanded = function ($section) {
return $section.classList.contains(this.sectionExpandedClass)
}

// Check if all sections are open
/**
* Check if all sections are open
*
* @returns {boolean} True if all sections are open
*/
Accordion.prototype.checkIfAllSectionsOpen = function () {
// Get a count of all the Accordion sections
var sectionsCount = this.$sections.length
Expand All @@ -336,7 +373,11 @@ Accordion.prototype.checkIfAllSectionsOpen = function () {
return areAllSectionsOpen
}

// Update "Show all sections" button
/**
* Update "Show all sections" button
*
* @param {boolean} expanded - Section expanded
*/
Accordion.prototype.updateShowAllButton = function (expanded) {
var $showAllIcon = this.$showAllButton.querySelector('.' + this.upChevronIconClass)
var $showAllText = this.$showAllButton.querySelector('.' + this.showAllTextClass)
Expand All @@ -354,8 +395,12 @@ Accordion.prototype.updateShowAllButton = function (expanded) {
}
}

// Check for `window.sessionStorage`, and that it actually works.
var helper = {
/**
* Check for `window.sessionStorage`, and that it actually works.
*
* @returns {boolean} True if session storage is available
*/
checkForSessionStorage: function () {
var testString = 'this is the test string'
var result
Expand All @@ -370,7 +415,11 @@ var helper = {
}
}

// Set the state of the accordions in sessionStorage
/**
* Set the state of the accordions in sessionStorage
*
* @param {HTMLElement} $section - Section element
*/
Accordion.prototype.storeState = function ($section) {
if (this.browserSupportsSessionStorage) {
// We need a unique way of identifying each content in the Accordion. Since
Expand All @@ -390,7 +439,11 @@ Accordion.prototype.storeState = function ($section) {
}
}

// Read the state of the accordions from sessionStorage
/**
* Read the state of the accordions from sessionStorage
*
* @param {HTMLElement} $section - Section element
*/
Accordion.prototype.setInitialState = function ($section) {
if (this.browserSupportsSessionStorage) {
var $button = $section.querySelector('.' + this.sectionButtonClass)
Expand All @@ -409,11 +462,11 @@ Accordion.prototype.setInitialState = function ($section) {
/**
* Create an element to improve semantics of the section button with punctuation
*
* @returns {HTMLSpanElement} DOM element
*
* Adding punctuation to the button can also improve its general semantics by dividing its contents
* into thematic chunks.
* See https://github.com/alphagov/govuk-frontend/issues/2327#issuecomment-922957442
*
* @returns {HTMLElement} DOM element
*/
Accordion.prototype.getButtonPunctuationEl = function () {
var $punctuationEl = document.createElement('span')
Expand Down
11 changes: 6 additions & 5 deletions src/govuk/components/button/button.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ var DEBOUNCE_TIMEOUT_IN_SECONDS = 1
* JavaScript enhancements for the Button component
*
* @class
* @param {HTMLElement} $module - The element this component controls
* @param {ButtonConfig} config - Button config
* @param {HTMLElement} $module - HTML element to use for button
* @param {ButtonConfig} [config] - Button config
* @this {Button}
*/
function Button ($module, config) {
if (!$module) {
Expand Down Expand Up @@ -51,7 +52,7 @@ Button.prototype.init = function () {
*
* See https://github.com/alphagov/govuk_elements/pull/272#issuecomment-233028270
*
* @param {KeyboardEvent} event
* @param {KeyboardEvent} event - Keydown event
*/
Button.prototype.handleKeyDown = function (event) {
var target = event.target
Expand All @@ -69,8 +70,8 @@ Button.prototype.handleKeyDown = function (event) {
* stops people accidentally causing multiple form submissions by double
* clicking buttons.
*
* @param {MouseEvent} event
* @returns {undefined | false} - Returns undefined, or false when debounced
* @param {MouseEvent} event - Mouse click event
* @returns {undefined | false} Returns undefined, or false when debounced
*/
Button.prototype.debounce = function (event) {
// Check the button that was clicked has preventDoubleClick enabled
Expand Down
3 changes: 2 additions & 1 deletion src/govuk/components/button/button.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ describe('/components/button', () => {
* Examples don't do this and we need it to have something to submit
*
* @param {import('puppeteer').Page} page - Puppeteer page object
* @returns {undefined}
* @returns {Promise<undefined>}
*/
function trackClicks (page) {
return page.evaluate(() => {
Expand All @@ -82,6 +82,7 @@ describe('/components/button', () => {
/**
* Gets the number of times the form was submitted
*
* @param {import('puppeteer').Page} page - Puppeteer page object
* @returns {number} Number of times the form was submitted
*/
function getClicksCount (page) {
Expand Down
3 changes: 2 additions & 1 deletion src/govuk/components/character-count/character-count.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ var CHARACTER_COUNT_TRANSLATIONS = {
* of the available characters/words has been entered.
*
* @class
* @param {HTMLElement} $module - The element this component controls
* @param {HTMLElement} $module - HTML element to use for character count
* @param {CharacterCountConfig} [config] - Character count config
* @this {CharacterCount}
*/
function CharacterCount ($module, config) {
if (!$module) {
Expand Down
12 changes: 9 additions & 3 deletions src/govuk/components/checkboxes/checkboxes.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ import '../../vendor/polyfills/Function/prototype/bind.mjs'
*
* @class
* @param {HTMLElement} $module - HTML element to use for checkboxes
* @this {Checkboxes}
*/
function Checkboxes ($module) {
this.$module = $module
this.$inputs = $module.querySelectorAll('input[type="checkbox"]')
}

/**
* Initialise Checkboxes
* Initialise component
*
* Checkboxes can be associated with a 'conditionally revealed' content block –
* for example, a checkbox for 'Phone' could reveal an additional form field for
Expand Down Expand Up @@ -62,11 +63,12 @@ Checkboxes.prototype.init = function () {
// for example if they are added to the page dynamically, so sync now too.
this.syncAllConditionalReveals()

// Handle events
$module.addEventListener('click', this.handleClick.bind(this))
}

/**
* Sync the conditional reveal states for all inputs in this $module.
* Sync the conditional reveal states for all checkboxes in this $module.
*/
Checkboxes.prototype.syncAllConditionalReveals = function () {
nodeListForEach(this.$inputs, this.syncConditionalRevealWithInputState.bind(this))
Expand Down Expand Up @@ -96,6 +98,8 @@ Checkboxes.prototype.syncConditionalRevealWithInputState = function ($input) {
*
* Find any other checkbox inputs with the same name value, and uncheck them.
* This is useful for when a “None of these" checkbox is checked.
*
* @param {HTMLElement} $input - Checkbox input
*/
Checkboxes.prototype.unCheckAllInputsExcept = function ($input) {
var allInputsWithSameName = document.querySelectorAll('input[type="checkbox"][name="' + $input.name + '"]')
Expand All @@ -110,11 +114,13 @@ Checkboxes.prototype.unCheckAllInputsExcept = function ($input) {
}

/**
* Uncheck exclusive inputs
* Uncheck exclusive checkboxes
*
* Find any checkbox inputs with the same name value and the 'exclusive' behaviour,
* and uncheck them. This helps prevent someone checking both a regular checkbox and a
* "None of these" checkbox in the same fieldset.
*
* @param {HTMLInputElement} $input - Checkbox input
*/
Checkboxes.prototype.unCheckExclusiveInputs = function ($input) {
var allInputsWithSameNameAndExclusiveBehaviour = document.querySelectorAll(
Expand Down
Loading

0 comments on commit f7f7f78

Please sign in to comment.