label-helpers.js 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.getLabels = getLabels;
  6. exports.getRealLabels = getRealLabels;
  7. exports.getLabelContent = getLabelContent;
  8. var _helpers = require("./helpers");
  9. const labelledNodeNames = ['button', 'meter', 'output', 'progress', 'select', 'textarea', 'input'];
  10. function getTextContent(node) {
  11. if (labelledNodeNames.includes(node.nodeName.toLowerCase())) {
  12. return '';
  13. }
  14. if (node.nodeType === _helpers.TEXT_NODE) return node.textContent;
  15. return Array.from(node.childNodes).map(childNode => getTextContent(childNode)).join('');
  16. }
  17. function getLabelContent(element) {
  18. let textContent;
  19. if (element.tagName.toLowerCase() === 'label') {
  20. textContent = getTextContent(element);
  21. } else {
  22. textContent = element.value || element.textContent;
  23. }
  24. return textContent;
  25. } // Based on https://github.com/eps1lon/dom-accessibility-api/pull/352
  26. function getRealLabels(element) {
  27. // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- types are not aware of older browsers that don't implement `labels`
  28. if (element.labels !== undefined) {
  29. var _labels;
  30. return (_labels = element.labels) != null ? _labels : [];
  31. }
  32. if (!isLabelable(element)) return [];
  33. const labels = element.ownerDocument.querySelectorAll('label');
  34. return Array.from(labels).filter(label => label.control === element);
  35. }
  36. function isLabelable(element) {
  37. return /BUTTON|METER|OUTPUT|PROGRESS|SELECT|TEXTAREA/.test(element.tagName) || element.tagName === 'INPUT' && element.getAttribute('type') !== 'hidden';
  38. }
  39. function getLabels(container, element, {
  40. selector = '*'
  41. } = {}) {
  42. const ariaLabelledBy = element.getAttribute('aria-labelledby');
  43. const labelsId = ariaLabelledBy ? ariaLabelledBy.split(' ') : [];
  44. return labelsId.length ? labelsId.map(labelId => {
  45. const labellingElement = container.querySelector(`[id="${labelId}"]`);
  46. return labellingElement ? {
  47. content: getLabelContent(labellingElement),
  48. formControl: null
  49. } : {
  50. content: '',
  51. formControl: null
  52. };
  53. }) : Array.from(getRealLabels(element)).map(label => {
  54. const textToMatch = getLabelContent(label);
  55. const formControlSelector = 'button, input, meter, output, progress, select, textarea';
  56. const labelledFormControl = Array.from(label.querySelectorAll(formControlSelector)).filter(formControlElement => formControlElement.matches(selector))[0];
  57. return {
  58. content: textToMatch,
  59. formControl: labelledFormControl
  60. };
  61. });
  62. }