autocomplete-matches.js 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. import { sanitize } from '../commons/text';
  2. import standards from '../standards';
  3. import { isVisible } from '../commons/dom';
  4. function autocompleteMatches(node, virtualNode) {
  5. const autocomplete = virtualNode.attr('autocomplete');
  6. if (!autocomplete || sanitize(autocomplete) === '') {
  7. return false;
  8. }
  9. const nodeName = virtualNode.props.nodeName;
  10. if (['textarea', 'input', 'select'].includes(nodeName) === false) {
  11. return false;
  12. }
  13. // The element is an `input` element a `type` of `hidden`, `button`, `submit` or `reset`
  14. const excludedInputTypes = ['submit', 'reset', 'button', 'hidden'];
  15. if (
  16. nodeName === 'input' &&
  17. excludedInputTypes.includes(virtualNode.props.type)
  18. ) {
  19. return false;
  20. }
  21. // The element has a `disabled` or `aria-disabled="true"` attribute
  22. const ariaDisabled = virtualNode.attr('aria-disabled') || 'false';
  23. if (
  24. virtualNode.hasAttr('disabled') ||
  25. ariaDisabled.toLowerCase() === 'true'
  26. ) {
  27. return false;
  28. }
  29. // The element has `tabindex="-1"` and has a [[semantic role]] that is
  30. // not a [widget](https://www.w3.org/TR/wai-aria-1.1/#widget_roles)
  31. const role = virtualNode.attr('role');
  32. const tabIndex = virtualNode.attr('tabindex');
  33. if (tabIndex === '-1' && role) {
  34. const roleDef = standards.ariaRoles[role];
  35. if (roleDef === undefined || roleDef.type !== 'widget') {
  36. return false;
  37. }
  38. }
  39. // The element is **not** visible on the page or exposed to assistive technologies
  40. if (
  41. tabIndex === '-1' &&
  42. virtualNode.actualNode &&
  43. !isVisible(virtualNode.actualNode, false) &&
  44. !isVisible(virtualNode.actualNode, true)
  45. ) {
  46. return false;
  47. }
  48. return true;
  49. }
  50. export default autocompleteMatches;