All files / features/configuration configuration.js

100% Statements 67/67
85.71% Branches 18/21
100% Functions 7/7
100% Lines 67/67

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 682x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 24x 24x 22x 24x 24x 2x 2x 24x 24x 2x 2x 2x 2x 2x 2x 2x 2x 2x 24x 24x 24x 23x 24x 2x 2x 2x 2x 2x 2x 2x 23x 23x 23x 23x 23x 2x 2x 2x 2x 2x 2x 47x 47x 4x 38x 47x 47x  
/**
 * @typedef {object} Configuration
 *
 * Configurations of Dynamic Select boxes
 *
 * @property {number} minQueryLength - minimum number of characters in the filter
 *  text input on dropdown to filter data in the option list, defaults to 3
 * @property {number} debounceQueryDuration - number of milliseconds for the
 *   text input to wait for updates before filtering the data
 */
export const defaultValues = Object.freeze({
  minQueryLength: 3,
  debounceQueryDuration: 250,
})
 
/**
 * @param {HTMLElement} element - target element
 * @returns {Readonly<Configuration>} configurations object
 */
export function configurationOf (element) {
  return Object.freeze({
    get minQueryLength () {
      return getConfigPositiveIntegerOrZero(element, { attribute: 'data-min-query-length', config: 'minQueryLength' })
    },
    get debounceQueryDuration () {
      return getConfigPositiveIntegerOrZero(element, { attribute: 'data-debounce-query-duration', config: 'debounceQueryDuration' })
    },
  })
}
 
/**
 *
 * @param {HTMLElement} element - target Element
 * @param {object} params - object parameters
 * @param {string} params.attribute - attribute name to query for
 * @param {keyof typeof defaultValues} params.config - config property name to search for
 * @returns {number} validConfigName
 */
function getConfigPositiveIntegerOrZero (element, { attribute, config }) {
  return validPositiveIntegerPlusZeroOrNull(element.getAttribute(attribute)) ??
    validPositiveIntegerPlusZeroOrNull(getConfigFromElementConstructor(element, config)) ??
    defaultValues[config]
}
 
/**
 *
 * @param {HTMLElement} element - target Element
 * @param {keyof typeof defaultValues} config - config property name to search for
 * @returns {unknown} config value
 */
function getConfigFromElementConstructor (element, config) {
  const {constructor} = element
  const configObject = Object.hasOwn(constructor, 'config') ? constructor.config : null
  return configObject && Object.hasOwn(configObject, config) ? configObject[config] : null
}
 
/**
 *
 * @param {unknown} numericValue - target value
 * @returns {number | null} `numericValue` if integer, otherwise null
 */
function validPositiveIntegerPlusZeroOrNull (numericValue) {
  if (typeof numericValue === 'string') {
    numericValue = Number.parseFloat(numericValue)
  }
  return typeof numericValue === 'number' && Number.isInteger(numericValue) && numericValue >= 0 ? numericValue : null
}