ARIAUtils.js 8.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. let _id=0;export function nextId(prefix){return(prefix||'')+ ++_id;}
  2. export function bindLabelToControl(label,control){const controlId=nextId('labelledControl');control.id=controlId;label.setAttribute('for',controlId);}
  3. export function markAsAlert(element){element.setAttribute('role','alert');element.setAttribute('aria-live','polite');}
  4. export function markAsButton(element){element.setAttribute('role','button');}
  5. export function markAsCheckbox(element){element.setAttribute('role','checkbox');}
  6. export function markAsCombobox(element){element.setAttribute('role','combobox');}
  7. export function markAsModalDialog(element){element.setAttribute('role','dialog');element.setAttribute('aria-modal','true');}
  8. export function markAsGroup(element){element.setAttribute('role','group');}
  9. export function markAsLink(element){element.setAttribute('role','link');}
  10. export function markAsMenuButton(element){markAsButton(element);element.setAttribute('aria-haspopup',true);}
  11. export function markAsProgressBar(element,min=0,max=100){element.setAttribute('role','progressbar');element.setAttribute('aria-valuemin',min);element.setAttribute('aria-valuemax',max);}
  12. export function markAsTab(element){element.setAttribute('role','tab');}
  13. export function markAsTabpanel(element){element.setAttribute('role','tabpanel');}
  14. export function markAsTree(element){element.setAttribute('role','tree');}
  15. export function markAsTreeitem(element){element.setAttribute('role','treeitem');}
  16. export function markAsTextBox(element){element.setAttribute('role','textbox');}
  17. export function markAsMenu(element){element.setAttribute('role','menu');}
  18. export function markAsMenuItem(element){element.setAttribute('role','menuitem');}
  19. export function markAsMenuItemSubMenu(element){markAsMenuItem(element);element.setAttribute('aria-haspopup',true);}
  20. export function markAsList(element){element.setAttribute('role','list');}
  21. export function markAsListitem(element){element.setAttribute('role','listitem');}
  22. export function markAsListBox(element){element.setAttribute('role','listbox');}
  23. export function markAsMultiSelectable(element){element.setAttribute('aria-multiselectable','true');}
  24. export function markAsOption(element){element.setAttribute('role','option');}
  25. export function markAsRadioGroup(element){element.setAttribute('role','radiogroup');}
  26. export function markAsHidden(element){element.setAttribute('aria-hidden','true');}
  27. export function markAsSlider(element,min=0,max=100){element.setAttribute('role','slider');element.setAttribute('aria-valuemin',String(min));element.setAttribute('aria-valuemax',String(max));}
  28. export function markAsHeading(element,level){element.setAttribute('role','heading');element.setAttribute('aria-level',level);}
  29. export function markAsPoliteLiveRegion(element){element.setAttribute('aria-live','polite');}
  30. export function setPlaceholder(element,placeholder){if(placeholder){element.setAttribute('aria-placeholder',placeholder);}else{element.removeAttribute('aria-placeholder');}}
  31. export function markAsPresentation(element){element.setAttribute('role','presentation');}
  32. export function markAsStatus(element){element.setAttribute('role','status');}
  33. export function ensureId(element){if(!element.id){element.id=nextId('ariaElement');}}
  34. export function setAriaValueText(element,valueText){element.setAttribute('aria-valuetext',valueText);}
  35. export function setAriaValueNow(element,value){element.setAttribute('aria-valuenow',value);}
  36. export function setAriaValueMinMax(element,min,max){element.setAttribute('aria-valuemin',min);element.setAttribute('aria-valuemax',max);}
  37. export function setControls(element,controlledElement){if(!controlledElement){element.removeAttribute('aria-controls');return;}
  38. ensureId(controlledElement);element.setAttribute('aria-controls',controlledElement.id);}
  39. export function setChecked(element,value){element.setAttribute('aria-checked',!!value);}
  40. export function setCheckboxAsIndeterminate(element){element.setAttribute('aria-checked','mixed');}
  41. export function setExpanded(element,value){element.setAttribute('aria-expanded',!!value);}
  42. export function unsetExpandable(element){element.removeAttribute('aria-expanded');}
  43. export function setHidden(element,value){element.setAttribute('aria-hidden',!!value);}
  44. export const AutocompleteInteractionModel={inline:'inline',list:'list',both:'both',none:'none',};export function setAutocomplete(element,interactionModel=AutocompleteInteractionModel.none){element.setAttribute('aria-autocomplete',interactionModel);}
  45. export function setSelected(element,value){element.setAttribute('aria-selected',!!value);}
  46. export function setInvalid(element,value){if(value){element.setAttribute('aria-invalid',value);}else{element.removeAttribute('aria-invalid');}}
  47. export function setPressed(element,value){element.setAttribute('aria-pressed',!!value);}
  48. export function setValueNow(element,value){element.setAttribute('aria-valuenow',value);}
  49. export function setValueText(element,value){element.setAttribute('aria-valuetext',value);}
  50. export function setProgressBarValue(element,valueNow,valueText){element.setAttribute('aria-valuenow',valueNow);if(valueText){element.setAttribute('aria-valuetext',valueText);}}
  51. export function setAccessibleName(element,name){element.setAttribute('aria-label',name);}
  52. const _descriptionMap=new WeakMap();export function setDescription(element,description){if(_descriptionMap.has(element)){_descriptionMap.get(element).remove();}
  53. element.removeAttribute('data-aria-utils-animation-hack');if(!description){_descriptionMap.delete(element);element.removeAttribute('aria-describedby');return;}
  54. const descriptionElement=createElement('span');descriptionElement.textContent=description;descriptionElement.style.display='none';ensureId(descriptionElement);element.setAttribute('aria-describedby',descriptionElement.id);_descriptionMap.set(element,descriptionElement);const contentfulVoidTags=new Set(['INPUT','IMG']);if(!contentfulVoidTags.has(element.tagName)){element.appendChild(descriptionElement);return;}
  55. const inserted=element.insertAdjacentElement('afterend',descriptionElement);if(inserted){return;}
  56. element.setAttribute('data-aria-utils-animation-hack','sorry');element.addEventListener('animationend',()=>{if(_descriptionMap.get(element)!==descriptionElement){return;}
  57. element.removeAttribute('data-aria-utils-animation-hack');element.insertAdjacentElement('afterend',descriptionElement);},{once:true});}
  58. export function setActiveDescendant(element,activedescendant){if(!activedescendant){element.removeAttribute('aria-activedescendant');return;}
  59. console.assert(element.hasSameShadowRoot(activedescendant),'elements are not in the same shadow dom');ensureId(activedescendant);element.setAttribute('aria-activedescendant',activedescendant.id);}
  60. const AlertElementSymbol=Symbol('AlertElementSybmol');export function alert(message,element){const document=element.ownerDocument;if(!document[AlertElementSymbol]){const alertElement=document.body.createChild('div');alertElement.style.position='absolute';alertElement.style.left='-999em';alertElement.style.width='100em';alertElement.style.overflow='hidden';alertElement.setAttribute('role','alert');alertElement.setAttribute('aria-atomic','true');document[AlertElementSymbol]=alertElement;}
  61. document[AlertElementSymbol].textContent=message.trimEndWithMaxLength(10000);}
  62. self.UI=self.UI||{};UI=UI||{};self.UI.ARIAUtils={nextId,bindLabelToControl,markAsAlert,markAsButton,markAsCheckbox,markAsCombobox,markAsModalDialog,markAsGroup,markAsLink,markAsMenuButton,markAsProgressBar,markAsTab,markAsTabpanel,markAsTree,markAsTreeitem,markAsTextBox,markAsMenu,markAsMenuItem,markAsMenuItemSubMenu,markAsList,markAsListitem,markAsListBox,markAsMultiSelectable,markAsOption,markAsRadioGroup,markAsHidden,markAsSlider,markAsHeading,markAsPoliteLiveRegion,setPlaceholder,markAsPresentation,markAsStatus,ensureId,setAriaValueText,setAriaValueNow,setAriaValueMinMax,setControls,setChecked,setCheckboxAsIndeterminate,setExpanded,unsetExpandable,setHidden,AutocompleteInteractionModel,setAutocomplete,setSelected,setInvalid,setPressed,setProgressBarValue,setValueNow,setValueText,setAccessibleName,setDescription,setActiveDescendant,alert,};