label-helpers.js 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.getLabelContent = getLabelContent;
  6. exports.getLabels = getLabels;
  7. exports.getRealLabels = getRealLabels;
  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. }
  26. // Based on https://github.com/eps1lon/dom-accessibility-api/pull/352
  27. function getRealLabels(element) {
  28. // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- types are not aware of older browsers that don't implement `labels`
  29. if (element.labels !== undefined) {
  30. var _labels;
  31. return (_labels = element.labels) != null ? _labels : [];
  32. }
  33. if (!isLabelable(element)) return [];
  34. const labels = element.ownerDocument.querySelectorAll('label');
  35. return Array.from(labels).filter(label => label.control === element);
  36. }
  37. function isLabelable(element) {
  38. return /BUTTON|METER|OUTPUT|PROGRESS|SELECT|TEXTAREA/.test(element.tagName) || element.tagName === 'INPUT' && element.getAttribute('type') !== 'hidden';
  39. }
  40. function getLabels(container, element, {
  41. selector = '*'
  42. } = {}) {
  43. const ariaLabelledBy = element.getAttribute('aria-labelledby');
  44. const labelsId = ariaLabelledBy ? ariaLabelledBy.split(' ') : [];
  45. return labelsId.length ? labelsId.map(labelId => {
  46. const labellingElement = container.querySelector(`[id="${labelId}"]`);
  47. return labellingElement ? {
  48. content: getLabelContent(labellingElement),
  49. formControl: null
  50. } : {
  51. content: '',
  52. formControl: null
  53. };
  54. }) : Array.from(getRealLabels(element)).map(label => {
  55. const textToMatch = getLabelContent(label);
  56. const formControlSelector = 'button, input, meter, output, progress, select, textarea';
  57. const labelledFormControl = Array.from(label.querySelectorAll(formControlSelector)).filter(formControlElement => formControlElement.matches(selector))[0];
  58. return {
  59. content: textToMatch,
  60. formControl: labelledFormControl
  61. };
  62. });
  63. }