Code Monkey home page Code Monkey logo

accname's People

Contributors

a11ydoer avatar accdc avatar adampage avatar aleventhal avatar billybonks avatar carmacleod avatar cookiecrook avatar cyns avatar daniel-montalvo avatar github-actions[bot] avatar jaragunde avatar jasonkiss avatar jnurthen avatar joanmarie avatar kasperisager avatar klown avatar marcoscaceres avatar melsumner avatar nolanlawson avatar oisinnolan avatar patrickhlauke avatar pkra avatar plehegar avatar richschwer avatar scottaohara avatar spectranaut avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

accname's Issues

Concatenate non identical sources for ACCNAME and AccDescription Computation

Here's a thread

Bryan says:

I'd like to verify the expectation for the following testable statement.

<input type="text" aria-label="LabelText" title="TitleText" id="test" aria-describedby="descid"><div id="descid">DescriptionText</div>
Current results:
accName: "LabelText"```` ``accDesc: "DescriptionText"
The title is lost. Is this the expected result?

Stephan says

I understood this as override accepted by the group ever since the very beginning.
Not clear where exactly this is handled in the accessible description computation requirements.
Personally, I feel unhappy with this override.

David Says

It is the expected result because the title is a swing attribute that fills an empty accname or accdesciption
My preference would be that if it is different then it is a concatenation with the accdescrption...
There a lot if override errors in the wild

Bryan says

I understand, and have always thought the invisible loss of accessible information was strange.
Should this be raised as an issue to be added to the naming computation, or should this be ignored as something everybody knows and just deals with?

“The trick is redundancy... can the user agents recognize identical strings of information and not pass that through”

If this is dealt with in the spec, I’m sure this can be done, since it is already happening in some browsers when the description and name properties match, so description is suppressed so that only name is set. Technically this is possible, it just needs to be dealt with in the algorithm.

David Says:

I filed a bug against Chrome to have them show the title attribute on tab keyboard focus...
With respect to the original question there is also the same issue with aria-errormessage and aria-describedby I expect.
The fact is in the real world the title attribute is used a lot... and if browsers can suppress a redundant title (or aria-describedby etc.) and let additional content pass through, this would be desirable...

The suggestion

Change the computation to let non redundant sources pass through the accessibility tree and be concatenated to the AccName or AccDescription as appropriate.

  • if an html label and an aria-labelledby are used, they will be concatenated in the accname if they are not identical.
  • If an aria-error-message and aria-describedby are on a field they will both be concatenated in the accdescription
  • if a title attribute offers more information and there is already an accdescription then it will be concatenated if it is not identical.

A way to specify labelledby/describedy without requiring an id

(I realize that something like this is not the current priority and apologize if this is the wrong forum for such a proposal or if there exists such a mechanism that I am unaware of.)

Generating ids for aria-labelledby and aria-describedby can be difficult.

In a CMS it's not uncommon for two versions of a document to be rendered on a page from the same or similar templates. Consider the teaser for a blog entry listed in both "recent posts" in the sidebar and under "related content" in the footer of the current article. It's natural to code the teaser template similar to

<article aria-labelledby=blog-teaser-{{ id }}-title>
  <span id=blog-teaser-{{ id }}-title>{{ title }}</span>
  <!-- etc. -->

Simple, straightforward, and wrong. This template needs to know not just its content but it's context in order to generate a unique id. Worse, it's possible that the above works for many years until the "related content" section is added and it happens that an article is listed in both.

There are workarounds but they can be laborious or create their own problems. Even so, it assumes someone notices that there is a problem to work around.

I would like something like this:

<section aria-labelledby-child>
  <span aria-labels-parent><!-- etc. -->

An element with the aria-labelledby-child attribute computes its label from descendant elements marked aria-labels-parent.

The search for such children would need to end at a child that also has an aria-labelledby-child. That is, given

<section aria-labelledby-child>
  <span aria-labels-parent>A</span>
  <article aria-labelledby-child>
    <span aria-labels-parent>B</span>
  </article>
  <span aria-labels-parent>C</span>
</section>

The section is labelled "A C" and the article "B".

And similarly for aria-describedby-child and aria-described-parent.

There are, of course, still things that can go wrong, if one attribute is used without the other, but I believe it would solve more problems than it causes and be easier to get right in the common case.

While there are a lot of aria attributes that take an id, aria-labelledby and aria-describedby have some interesting commonalities:

  • the label/description is almost always a descendant of what is being labeled/described (whether it is specified as the label/description or not)
  • they are, in my experience, both
    • the most often used on a page
    • the least likely to be unique

Perhaps a more general mechanism is required, but something like the described fits my use cases and tracks with my experience.

Strange results for selects in labels

Consider the following two examples (calculating the accessible name for the select elements):

<label for="checkbox">
  label
  <select>
   <option selected>foo</option>
   <option>bar</option>
  </select>
</label>
<input type="checkbox" id="checkbox">

In this case the condition for step 5 applies, so the result is "foo".

<label>
  label
  <select>
   <option selected>foo</option>
   <option>bar</option>
  </select>
</label>

In this case, the condition for step 5 does not apply (<select> is embedded in its own label, not of another widget), but the condition of step 6 does apply (<select> is a descendant of a <label> element). So the result here is "label foo bar".

Did I miss something? My guess is that controlls are supposed to be ignored after step 5 completely, but I could not find anything about that in the spec.

MathML in an accessible name

The 1.1 spec states that the accessible name's final output is a flat string:

The string contains only character data; it does not contain any markup.

This makes sense if the goal is to remove things like font size and other tags that would be irrelevant when spoken.

But what about MathML? For example, when a student takes a multiple choice test, MathML could be used in buttons, checkbox labels, aria alerts, or other widgets.

I would recommend that it pass through intact to the the Accessibility API, so that a screen reader can apply its own speech rules to it, and/or display the appropriate braille representation of the math.

A simple example that would benefit: 23 (two to the third power). MathML is the only way currently to ensure this is displayed properly in braille, and also spoken correctly. It seems unfair to exclude it from the accessible name.

Another alternative: expect the user agent to run the MathML through its own speech engine to replace it with an appropriately flattened text string. This is less ideal for braille readers, but still better than the last option.

The last option (and the current state of things, generally): drop the math completely, as though it was just another irrelevant style tag. But this doesn't seem like the right answer.

Some guidance in this spec would be appreciated.

AccName-AAM: Include title attribute (as part of description computation) in Text Alternative Computation

From @devarship on June 2, 2017 17:57

Reference: http://www.w3.org/TR/accname-aam-1.1/#mapping_additional_nd_te

Purpose: Consider including title attribute as part of the accessible description calculation besides aria-describedby.

Rationale Follows (test environment: Win 7, JAWS 17, NVDA 2017, IE 11):

When using title attribute with valid label, label becomes the acc name and title gets appended to the label as acc description, with the output (Label [acc name] -> title). This is similar to when label and aria-describedby are used where the accumulated text is in the same order as when title was present, but replaced with the IDREF of aria-describedby (Label [acc name] -> aria-describedby [IDREF]).

However, when both aria-describedby and title are present, aria-describedby takes precedence. Both JAWS and NVDA support the finding.

Since both NVDA and JAWS treat title as additive and similar to aria-describedby, I think the following sections should be updated:

4.2 Description Computation (http://www.w3.org/TR/accname-aam-1.1/#mapping_additional_nd_description)-- include title attribute besides aria-describedby.

4.3.1 Terminology (http://www.w3.org/TR/accname-aam-1.1/#terminology) - under 2 B, a third bullet should be added to establish precedence level when title and aria-describedby are present.

thanks,
Devarshi

Copied from original issue: w3c/aria#584

Accessible name calc doesn't clearly say what happens with invalid reference or empty

From @mraccess77 on January 25, 2017 17:20

if computing a name, and the current node has a non-empty aria-labelledby attribute, and the current node is not already part of an aria-labelledby traversal, process its IDREFs in the order they occur:

First part: The term "non-empty aria-labelledby" attribute is not clear. Are you talking about an empty aria-labeleldby or aria-labelledby that points to something that is empty?

Second part: Even if it's implied that an invalid reference would then have an empty result -- it should clearly say valid aria-labelledby reference. Some would argue that an invalid reference passes and then we'd have an empty acc name. What should happen with an invalid reference is that the logic should proceed to the next step and get the acc name from something else if available -- it shouldn't stop.

Copied from original issue: w3c/aria#515

The handling of multiple label elements on one form field is unclear

From the way that the naming computation is written, it is unclear what is meant to happen when more than one label element is associated with a form field, such as an implicit one that surrounds an input element, and another that has a matching 'for' attribute that references the ID of the same input element.

We need to standardize how this should be handled by browsers. Once this is done, I'll update the Accessible Name Computation Prototype with the expected behavior at
https://github.com/accdc/w3c-alternative-text-computation
so it can produce accurate test results when this is encountered.

The relevant thread recently discussed on the ARIA Working Group maillist follows.

-----Original Message-----
From: Tobias Bengfort Sent: Monday, February 12, 2018 11:40 AM

Hi,

On 12/02/18 18:57, Bryan Garaventa wrote:

I don't understand what this means though: "This means that there can
be more than one label for a labelable element. These labels should be
processed in source order."

Are you referring to the DOM source order?

Do you mean that both of these would be treated differently and have
different names?

This is a test

As opposed to:

a test

This is

Because determining source order will be very expensive from a
processing perspective and unreliable in practice because this could
relate to anything such as use within data tables.

Yes, this is exactly what I mean. Note that it is not my personal opinion. This is defined in the HTML spec.

I can not really judge whether this is expensive or not. However, browsers have to implement this calculation for HTMLInputElement.labels anyway.

Tobias

-----Original Message-----
From: Bryan Garaventa
Sent: Monday, February 12, 2018 9:57 AM

No problem, I'll add one later today. I wasn't sure if this was a spec issue or an interpretation issue.

Tobias,
I don't understand what this means though: " This means that there can be more than one label for a labelable element. These labels should be processed in source order."

Are you referring to the DOM source order?

Do you mean that both of these would be treated differently and have different names?

<label>
This is
<input id="lbl" />
</label>
<label for="lbl">a test</label>

As opposed to:

<label for="lbl">a test</label>
<label>
This is
<input id="lbl" />
</label>

Because determining source order will be very expensive from a processing perspective and unreliable in practice because this could relate to anything such as use within data tables.

Clarify hidden nodes with child nodes, referenced by aria-labelledby

The spec does not make any allowance for hidden child nodes referenced with aria-labelledby.

<input aria-labelledby="a">
<div id="a" hidden>
   <span>Text</span>
</div>

Reading the algorithm the input should have no accessible name as the span is not directly references by aria-labelledby but is hidden.

When testing Chrome and Firefox they both return an accessible name of Text.

We should fix the algorithm to match the browser implementations.

Where is accessible name and descriptions defined?

https://w3c.github.io/accname/#accessible-name-and-description-mapping says

Information concerning name and description accessibility API mappings, including relationships, such as labelled-by/label-for and described-by/description-for, is documented in the Core Accessibility API Mappings specification [CORE-AAM-1.1].

which says

The editor's draft of the Core Accessibility API Mappings 1.1 is published from a new location

ok. https://w3c.github.io/core-aam/#accessible-names-and-descriptions

For more detail, see the Accessible Name and Description Computation and API Mappings specification.

The editor's draft of the Accessible Name and Description Computation 1.1 is published from a new location

and we're back where we started. What's up?

example under 2.C

Refer to example under 2.C:

Snippet:

<a id="file_row1" href="./files/Documentation.pdf">Documentation.pdf</a>
<span role="button" tabindex="0" id="del_row1" 
aria-label="Delete" aria-labelledby="del_row1 file_row1">
</span>
....
<a id="file_row2" href="./files/HolidayLetter.pdf">HolidayLetter.pdf</a>
<span role="button" tabindex="0" id="del_row2" 
aria-label="Delete" aria-labelledby="del_row2 file_row2">
</span>

Consider using input type button, instead of role button:

<a id="file_row1" href="./files/Documentation.pdf">Documentation.pdf</a>
<input type="button" id="del_row1" aria-label="Delete" aria-labelledby="del_row1 file_row1" value="button 1">
...
<a id="file_row2" href="./files/HolidayLetter.pdf">HolidayLetter.pdf</a>
<input type="button" id="del_row2" aria-label="Delete" aria-labelledby="del_row2 file_row2" value="button 2">

Mention <br> element

<div>foo<br>bar</div>

I would expect the accessible name of that element to be "foo bar" (with a space where the <br> element was). However, I do not see how the <br> element is handled in the spec.

Maybe a step roughly like this could be added between 7 and 8:

Otherwise, if the current node represents some kind of whitespace (e.g. the <br> element in HTML), return a string containing a single space.

TAC should cover rendered descendants from external sources: svg, iframe, etc.

https://www.w3.org/WAI/ARIA/track/actions/1379

Might want to make this a UA "SHOULD" requirement if we don't have two implementations. I'm also not sure how explicit we can make this, because it relies on host language rules, but for example:

  1. <iframe> with no in-document label could get its label from the "html > head > title" element of the iframe source.

  2. <img src="foo.svg"> with no label could get its label from the "svg > title" element of the displayed image source.

  3. <script src="foo"> (edge case example from the thread) would not apply because the source content is never rendered in any context.

WCAG/ACCNAME discrepancy with `<img alt="" title="foo">

From @cookiecrook on July 7, 2017 9:25

The following text in ACCNAME:

"Otherwise, use the value as specified by a host language attribute."

Seems to literally means the value even if it's empty, which does not leave the exception covered by WCAG Success Criteria H67: https://www.w3.org/TR/WCAG20-TECHS/H67.html

For each image that should be ignored: Check that title attribute is either absent or empty. Check that alt attribute is present and empty. ...

Furthermore, both Blink and Gecko allow this behavior. WebKit currently matches the HTML-AAM and ACCNAME specs, but will likely change to match the other browser's behavior. https://webkit.org/b/173870

Test case 7 here:
https://bugs.webkit.org/attachment.cgi?id=314203

Copied from original issue: w3c/aria#602

Clarification on the accessible description computation when aria-describedby refers to an element with nameFrom=author

Given this code example

<label for="phone-number">
    Enter your phone number
    <input type="text" id="phone-number" aria-describedby="phone-error" />
</label>
<div id="phone-error" role="alert">
    Sorry, that area code is not valid
</div>

Most screen reader + browser combinations return nothing as the accessible description for #phone-number. However, many developers (reasonably) expect the description to be the contents of the #phone-error. I'm seeing this pattern more frequently in the wild.

This is because aria-describedby references an element with role="alert". The ARIA 1.1 spec states that the name of role="alert" is from the author. The accname spec states that name from author is derived from aria-label or aria-labelledby attributes, while "name from content" is derived from the content of the element.

However, Step 2F of accname-1.1 states "Otherwise, if the current node's role allows name from content, or if the current node is referenced by aria-labelledby, aria-describedby, or is a native host language text alternative element (e.g. label in HTML), or is a descendant of a native host language text alternative element... [compute as name from content]"

The key is "Or if the current node is referenced by aria-labelledby, aria-describedby..."

Therefore I read that to mean that the content should be returned as the description because it is referenced by aria-describedby. Yes, role="alert" will get its accessible name from the author, but when it doesn't have a name from the author and is referenced via aria-describedby, its contents must be returned.

Is my understanding correct? Since most screen reader and browser combinations seem to disagree with my interpretation, I'd like to get this clarified so that the issue can be addressed appropriately.

Need clarity on computation involving first traversal

Example (after 2nd bullet under 2 B) -- http://www.w3.org/TR/accname-aam-1.1/#mapping_additional_nd_te is not clear because only element3 has innertext. The calculation changes when element1 and element2 have innertext (or acc name derived from another aria attribute).

It says: "element2 has no accessible name. The computation involves a first traversal of its aria-labelledby leading to element1, but element1's aria-labelledby is not subsequently followed."

Here is a modified example using buttons:

<button type="button" id="el1" aria-labelledby="el3">test1</button>
<button type="button" id="el2" aria-labelledby="el1">test 2</button>
<button type="button" id="el3"> hello </button>

  • Results (based on above example):
  1. JAWS 18 and NVDA (IE11): The accessible name of button#2 is test1 (aria-labelledby of button#2 references button#1, returns the acc name 'test1', and stops the traversal).

  2. VO and Chrome: The accessible name of button#2 is hello (aria-labelledby of button#2 references button#1, traverses to button#3, and returns the acc name 'hello').

Does CSS textual content include unicode characters?

In Step F ii, what exactly is meant by "CSS textual content"?

Does this include Unicode characters? Often Unicode characters in the private use range are used for the purpose of font icons. These Unicode characters would then be included as step F and a screen reader may try to interpret the Unicode character. For example, Voiceover will say "unpronounceable" when it comes across a Unicode character for which it has no definition.

Should the algorithm only be concerned with ASCII characters?

Sanity check needed for test cases 659 and 660

(Edited to reflect the fact that not a single user agent is producing the results we currently have in the expectations, namely "foo bar baz".)

Test case:

<style type="text/css">
  label:before { content: "foo"; }
  label:after { content: "baz"; }
</style>
<label for="test" title="bar">
  <input id="test" name="test" title="buz">
</label>

Starting the algorithm:

Step 1.  Set the root node to the input with id of "test"
         Set the current node to the root node (i.e. the input)
         Set the total accumulated text to the empty string ("")
Step 2A. N/A: The current node is NOT hidden.
Step 2B. N/A: Computing a name, but current node lacks aria-labelledby
Step 2C. N/A: Computing a name, but current node lacks aria-label
Step 2D. Applicable: "The current node's native markup provides an 
         attribute (e.g. title) or element (e.g. HTML label) that
         defines a text alternative.

Aside: The current node in this test case has both a title and an HTML label. So we defer to the HTML-AAM whose section 5.1.1 says we should prefer the label element.

What AccName Step 2D says we should do is: "return that alternative in the form of a flat string as defined by the host language". In the comment which follows, AccName says: "For example, in HTML, the img element's alt attribute defines a text alternative string, and the label element provides text for the referenced form element."

It's unclear to me what "return that alternative in the form of a flat string as defined by the host language" means. Does it mean, calculate the accessible name of the label, or return the displayed text of the label? From testing, it seems that most user agents are going with the displayed text, so apparently I'm not the only one.

Anyhoo.... Let's assume calculate.

Step 1.  Set the root node to the label
         Set the current node to the root node (i.e. the label)
         Set the total accumulated text to the empty string ("")
Step 2A. N/A: The current node is NOT hidden.
Step 2B. N/A: Computing a name, but current node lacks aria-labelledby
Step 2C. N/A: Computing a name, but current node lacks aria-label
Step 2D. Applicable? The current node (label) does have a title....

Assuming 2D is applicable, we are instructed to return that alternative in the form of a flat string as defined by the host language". The alternative (title) is "bar". So we exit the inner calculation returning "bar". That's the result for the outer calculation.

Personally, I don't think "bar" should be the result, but the algorithm seems to make it possible.

As for what we'd need to do to reach the point where we include the rendered text ("foo" and "baz" along with the title "bar"), I think we have to reach 2F when calculating the alternative for the label. So in the spirit of thoroughness, let's assume 2D is NOT applicable in the inner calculation (i.e. title is not a valid alternative for a label element).

Step 2E. N/A: Current node is the label; not a control embedded within
         a label or element directly referenced by aria-labelledby.
Step 2F. Applicable: label is a native host language text alternative.

Ok, here we go:

Step 2F   i.  Set the accumulated text to the empty string.
Step 2F  ii.  Prepend the before without a space ("foo")
              Append the after without a space ("baz")
Step 2F iii.  Then it has us descend the children. The only child is the
              input we're trying to calculate the name of.
Step 2F  iv.  Return the accumulated text.

Where do we get the title ("bar") from?? In other words, it seems to me that even if we make it to 2F (which I'm not convinced we do), I don't see anything which says grab the title. And of all the user agents, only Gecko is including the "bar". None of the user agents are including the "bar". The test case was recently modified making the title of the input "buz" instead of "bar" for clarity. With that modification, Gecko now returns "foo buz baz" rather than "foo bar baz".

All of this said, I'm sure I'm missing something. So please explain where in the algorithm above I'm doing the wrong thing. Thanks!

accname-aam clarify hidden

From @jnurthen on November 6, 2017 23:38

Step 2A states

If the current node is hidden

Where hidden is defined as

Indicates that the element is not visible, perceivable, or interactive to any user. An element is considered hidden if it or any one of its ancestor elements is not rendered or is explicitly hidden.

Please clarify if a node is hidden using aria-hidden whether it should be included in the accessible name calculation.

Copied from original issue: w3c/aria#658

Clarify the accname calculation only applies if stated in native AAMs

Example - https://w3c.github.io/html-aam/#img-element

states:
5.10.1 img Element Accessible Name Computation

  • If the img element has an aria-label or an aria-labelledby attribute the accessible name is to be calculated using the algorithm defined in Accessible Name and Description: Computation and API Mappings 1.1.
  • Otherwise use alt attribute
  • Otherwise use title attribute
  • If none of the above yield a usable text string there is no accessible name

So accname only applies if aria-label and/or labelledby are specified.

Nooby question: Form field value or form field name?

I was wondering if someone could help me understand the following test case:

if given
  <h2 id="test">
  Country of origin:
  <input role="combobox" type="text" title="Choose your country." value="United States">
  </h2>
then the accessible name of the element with id of "test" is "Country of origin: United States"

Why in this example, would the value attribute be used rather than the title? It seems to me that in step 2D, the title is selected therefore step 2E is never reached. It certainly seems like I'm missing something, but I can't find what it might be.

Clarification needed on "is not part of an aria-labelledby traversal"

In step A, there is a clause that checks if the current node "is not part of an aria-labelledby traversal". The note about whether another aria-labelledby is encountered is definitely a helpful distinction.

However, this clause can be interpreted such that if an element is referenced more than once, that element should be skipped on subsequent encounters.

Example:
<button aria-labelledby="id1 id1">submit</button>
According to my interpretation of the algorithm, the second id reference shouldn't be traversed, since the element was already part of a traversal the first time it was encountered.

If this is true, then many implementations of the algorithm are incorrect. If not true, then the TAC needs clarification or rewording.

This issue is similar to issue #33

Clarify adding additional whitespace

Consider the following two HTML snippets:

<div>foo</div>
<div>bar</div>
<div>foo</div><div>bar</div>

The text node between the two <div> elements (containing only whitespace) in the first snippet does not influence the visual result. However, the accessible name (according to the current spec) of the first snippet would be "foo bar", that of the second "foobar".

The current algorithm leaves all control with authors. However, many authors are not aware that this kind of whitespace is significant. Many browsers add additional whitespace around block elements to counter this inconsitency. There are some questions about this:

  • There is more than just block and inline. In which cases do we add additional whitespace? table? inline-block?
  • Should CSS be considered when calculating the display property or should the initial value be used?

ARIA Spec could be more flexible when elements with "nameFrom:author" are left unlabeled by the author

I received the following bug report from a member of my team.

Summary:
Web AX, VoiceOver: When browsing list of articles using VO Articles rotor on [site redacted], VO announces each item as "Article" without speaking headline

Steps To Reproduce:

  1. Turn on VoiceOver.
  2. Open Safari and browse to [site redacted].
  3. Press VO-U to bring up rotors.
  4. Press VO-Right arrow repeatedly to select “Articles” rotor.
  5. Explore rotor items by pressing VO-Down arrow.

Results:
When using VO’s Articles rotor, VO does show all the articles presented on [site redacted], but only speaks each item as “Article” without providing any additional info, such as the article’s headline. For better clarity, VO should speak some additional information here.

Upon closer inspection, the articles are not labeled but they all have a heading in close proximity to the start of the article element. For the sake of the user, we could probably work around this web page error heuristically in either WebKit or VoiceOver, but the ARIA spec appears to explicitly discourage this.

The ARIA spec could add some language explicitly allowing user agents to heuristically determine the label for unlabeled elements whose label has not been set by the author. In this case, the most logical choice would be to find the first heading in the article.

Perhaps: "User Agents MAY use heuristics to determine the label of an unlabeled element, if the role characteristics include nameFrom: author. For example, browsers may set the label of an unlabeled dialog to be the first heading in that dialog."

Consider adding hooks/extension points to native host languages

AccName mentions native host language elements and attributes (see, for instance, step 2D in the computation). But it doesn't cover all possible host language name sources, nor does it point to the owning specs (e.g. HTML-AAM, SVG-AAM, etc.) This is a source of confusion.

It would be great if we could point to native host language specs -- and do so in a non-normative fashion, because those host language specs already have a normative dependency on AccName; we don't want the reverse.

Accname-AAM: Alt text computation should distinguish between nameFrom contents during root node calculation versus recursive calculation.

From @klown on February 7, 2017 20:28

Moving from tracker's ISSUE-642:

Alt text computation should distinguish between nameFrom contents during root node calculation versus recursive calculation. For example, it makes sense to calculate the nameFrom contents on the current element, but it doesn't necessarily make sense to concatenate all the subgroup contents recursively into the current element's computed label.

Copied from original issue: w3c/aria#523

Relation to HTML-AAM not obvious

I was not sure whether to post this issue on accname or html-aam, so maybe it needs to be moved.

The HTML Accessibility API Mappings (html-aam) document has a long section on Accessible Name and Description Computation that overwrites some aspect of this specification. This is not obvious when reading the accname specification. I think a note should be added.

On top of that, splitting the algorithm across two documents makes it even more complex. I understand that this is necessary to split out the bits that are specific to HTML. But it leads to some strange results. Consider the following example:

<input type="text" title="test" hidden />
  • If you ignore html-aam, rule 2A applies and the empty string is returned.
  • If you do not ignore html-aam, the accname algorithm is completely ignored (because no aria-label or aria-labelledby attribute is present) and the title "test" is returned instead.

I am not sure if this effect is intentional.

Clarification of cross reference "proceed to 2F.i"

In step 8 of the computation, the Rec states:

Otherwise, if the current node is a descendant of an element whose Accessible Name or Accessible Description is being computed, and contains descendants, proceed to 2F.i.

However, there are no letter references. Could you please confirm what this is referencing?

Consolidating issues for handling whitespace where the spec algorithm breaks down

As requested in the last ARIA Caucus meeting, I've copied out the relevant text alternative algorithm below and edited the text accordingly. The spec text is the same, but embedded notes starting with "BG Note:" identify where content was inserted.

To summarize, when writing the AccName Computation Prototype, I ran across many of the same issues encountered by browser implementors, where specific steps as given by the algorithm cannot be followed exactly without introducing results that contradict common sense outcomes, or deviate from the expected results by end users. So to address this, I had to insert processes that deal with these scenarios without deviating from the steps of the algorithm.

So the goal, which is the same one that browser implementors are having to solve right now as well, is to provide the most accessible results that fit the highest percentage of scenarios and that meet the general expectations of the widest range of people possible in order to provide the most reliable results that are easily human readable by end users. This is the highest point that we can raise this bar, because we have to accept that it is literally impossible to account for every bleeding edge case or for non-standard implementations that intentionally diverge from general majority expectations.

The AccName Computation Prototype
https://github.com/whatsock/w3c-alternative-text-computation
already includes all of the additional features noted below.

I've attached a test page to this issue so you can download and run the AccName Prototype code locally by editing the test example as desired, which loads the latest executable code directly from GitHub to reproduce the examples as noted inline.
CreateYourOwn.zip

[Spec text]

  1. Compute the text alternative for the current node:

A. If the current node is hidden and is not directly referenced by aria-labelledby or aria-describedby, nor directly referenced by a native host language text alternative element (e.g. label in HTML) or attribute, return the empty string.

B. Otherwise:

• if computing a name, and the current node has an aria-labelledby attribute that contains at least one valid IDREF, and the current node is not already part of an aria-labelledby traversal, process its IDREFs in the order they occur:

• or, if computing a description, and the current node has an aria-describedby attribute that contains at least one valid IDREF, and the current node is not already part of an aria-describedby traversal, process its IDREFs in the order they occur:

BG Note: After computing the completed name for each aria-labelledby or aria-describedby reference using the algorithm steps below, a space is added at the beginning and end of the returned name to prevent unwanted concatenation with other ID refs or returned names from other nodes if applicable. E.G JS: (Name = " " + Name + " ";) This fulfills the expectation that, in the vast majority of cases, each referenced ID will be visually seperated and should not be mashed together without contextually differentiating each part.

i. Set the accumulated text to the empty string.
ii. For each IDREF:
a. Set the current node to the node referenced by the IDREF.
b. Compute the text alternative of the current node beginning with step 2. Set the result to that text alternative.
c. Append the result, with a space, to the accumulated text.
iii. Return the accumulated text.

C. Otherwise, if computing a name, and if the current node has an aria-label attribute whose value is not the empty string, nor, when trimmed of white space, is not the empty string:

• If traversal of the current node is due to recursion and the current node is an embedded control as defined in step 2E, ignore aria-label and skip to rule 2E.

• Otherwise, return the value of aria-label.

BG Note: After returning the value of aria-label, a space is added at the beginning and end of the returned name to prevent unwanted concatenation with other elements like so (Name = " " + Name + " ";), but this is only done if the current node is the same as root node. If the current node is an element being parsed recursively as a child of root node however, then no additional spacing is added. This is meant to handle situations like the following when processing the name for H1:

<h1>(<span aria-label="B">Q</span><span aria-label="E">E</span><span aria-label="G">D</span>)</h1>

Where the name of heading should be "(BEG)", and not "( B E G )".

D. Otherwise, if the current node's native markup provides an attribute (e.g. title) or element (e.g. HTML label) that defines a text alternative, return that alternative in the form of a flat string as defined by the host language, unless the element is marked as presentational (role="presentation" or role="none").

BG Note: After returning the value of label on form fields, or alt on images, or title, a space is added at the beginning and end of the returned name to prevent unwanted concatenation with other elements, like so (Name = " " + Name + " ";). This is needed to prevent alt and title attributes on images from being mashed together with adjacent content, which is the most desirable result in the vast majority of cases for end users.

E. Otherwise, if the current node is a control embedded within the label (e.g. the label element in HTML or any element directly referenced by aria-labelledby) for another widget, where the user can adjust the embedded control's value, then include the embedded control as part of the text alternative in the following manner:

BG Note: After returning the widget value using the algorithm below, a space is added at the beginning and end of the returned name to prevent unwanted concatenation with other elements, like so (Name = " " + Name + " ";). This is needed to prevent the values of visually separated controls from being mashed together with adjacent controls or content, which is the most desirable result in the vast majority of cases for end users.

• If the embedded control has role textbox, return its value.

• If the embedded control has role menu button, return the text alternative of the button.

• If the embedded control has role combobox, return the text alternative of the chosen option.

BG Note: As we discussed earlier, listbox needs to be added here to support embedded value parsing of selected options to cover scenarios when listbox is standalone or embedded within a combobox. However, we also need to add grid and tree here as well to account for the same thing, because these too are now supported as child widgets in ARIA 1.1. Otherwise, value will be returned for listbox but not for tree or grid as expected, even though all of these use aria-selected as the selection mechanism. Support for all these combinations has already been added in the AccName Prototype to account for the supported widgets of role=combobox.

• If the embedded control has role range (e.g., a spinbutton or slider):
• If the aria-valuetext property is present, return its value,
• Otherwise, if the aria-valuenow property is present, return its value,
• Otherwise, use the value as specified by a host language attribute.

F. Otherwise, if the current node's role allows name from content, or if the current node is referenced by aria-labelledby, aria-describedby, or is a native host language text alternative element (e.g. label in HTML), or is a descendant of a native host language text alternative element:

BG Note: After returning name from content for the current node, a space is added at the beginning and end of the returned name to prevent unwanted concatenation with other elements, like so (Name = " " + Name + " ";), but this only occurs when current node is determined to be a block level type element. Otherwise, no spacing is added. This is needed to prevent the content of visually separated controls from being mashed together with adjacent elements, while also making sure that inline text nodes and inline elements are not undesirably seperated. This is important to ensure that the following examples return the correct results:

<b>T<i>e</i>st</b> = "Test"
<div>T<br>e<div>st</div></div> = "T e st"

i. Set the accumulated text to the empty string.

ii. Check for CSS generated textual content associated with the current node and include it in the accumulated text. The CSS :before and :after pseudo elements can provide textual content for elements that have a content model.
• For :before pseudo elements, User agents MUST prepend CSS textual content, without a space, to the textual content of the current node.
• For :after pseudo elements, User agents MUST append CSS textual content, without a space, to the textual content of the current node.

BG Note: This spec text contradicts the intended purpose of pseudo elements and what people can use them for, and introduces accessibility issues if the naming computation doesn't account for them. As such, to account for block level versus inline styling properties that are acceptable within pseudo elements, the following is done instead. After returning the pseudo element content, a space is added at the beginning of :after and at the end of :before to prevent unwanted concatenation with other visually seperated content, but this only occurs when the pseudo element includes block level properties. Otherwise, no spacing is added. This is needed to account for fluid layouts where visually seperated content can be reliably conveyed within the accessibility tree, while also preserving default feedback for standard inline representations.

iii. For each child node of the current node:
a. Set the current node to the child node.
b. Compute the text alternative of the current node beginning with step 2. Set the result to that text alternative.
c. Append the result to the accumulated text.

iv. Return the accumulated text.
Important: Each node in the subtree is consulted only once. If text has been collected from a descendant, but is referenced by another IDREF in some descendant node, then that second, or subsequent, reference is not followed. This is done to avoid infinite loops.

G. Otherwise, if the current node is a Text node, return its textual contents.

H. Otherwise, if the current node is a descendant of an element whose Accessible Name or Accessible Description is being computed, and contains descendants, proceed to 2F.i.

I. Otherwise, if the current node has a Tooltip attribute, return its value.

BG Note: After returning the tooltip, a space is added at the beginning and end of the returned name to prevent unwanted concatenation with other elements, like so (Name = " " + Name + " ";). This is needed to prevent visually separate content from being mashed together with adjacent content, which is the most desirable result in the vast majority of cases for end users.

Unclear "Otherwise"

Each step starts with the word "otherwise". For me, it is not completely clear what this means. I can imagine three different interpretations:

  1. The conditions of the previous steps did not apply
  2. The previous steps had empty results
  3. The previous steps had empty results (except for whitespace)

I think it should be made clear which of these is intended.

Step D needs clarification

Why is [title] mentioned in step D? Title should not be considered until the end of the calculation (step I).

If title were considered at step D for all html elements, that would put title before a name-from-content element's subtree (step F).

Example:
<button title="there">hello</button>
As currently written, the algorithm would produce an accName/accDesc of "there hello".
Real world screen reader testing produces "hello there".

Should title only be used in step D for specific HTML elements, such as an iframe? If so clarification is needed as to what those elements are.

Furthermore, in step D, it would be helpful to have a significant amount of clarification for all native html elements. For example, when a form element has an associated label, should it only grab the innerText of the label, or should the algorithm be treating the label like a name from content element, recursively traversing through the label's child nodes? Also, should the algorithm consider whether the label has an aria-label or title attribute?

Change title in 2D to alt

2D States

Otherwise, if the current node's native markup provides an attribute (e.g. title) or element (e.g. HTML label) that defines a text alternative, return that alternative in the form of a flat string as defined by the host language, unless the element is marked as presentational (role="presentation" or role="none").

Comment:
For example, in HTML, the img element's alt attribute defines a text alternative string, and the label element provides text for the referenced form element. In SVG2, the desc and title elements provide a description of their parent element.

The first line's use of title is confusing as title normally falls into 2I (tooltip attribute). I suggest changing title in the first line to alt as alt is the very definition of a native alternative.

aria-label is used when computing accessible description in Chrome/Firefox/Safari

Step 2C

Otherwise, if computing a name, and if the current node has an aria-label attribute whose value is not the empty string, nor, when trimmed of white space, is not the empty string:
If traversal of the current node is due to recursion and the current node is an embedded control as defined in step 2E, ignore aria-label and skip to rule 2E.
Otherwise, return the value of aria-label.

Note that it says "if computing a name", which means that this step does nothing when computing a description.

Given this markup:

<div id=x aria-label="foo">bar</div>
<button aria-describedby=x>button</button>

In Chrome and Firefox, when inspecting the button in devtools, has the description "foo". Using the Accessibility Inspector in macOS to inspect the button in Safari, the "Help" property is "foo".

Is the spec wrong, or are the implementations wrong?

Step 2.F.iii.c doesn't say if result should be appended with or without a space

Step 2.F.iii.c doesn't say if result should be appended with or without a space. The rest of the algorithm is more specific.

Related to this are the tests like:

  <div id="test" role="link" tabindex="0">
   ...
    (<span>Q</span><span>E</span><span>D</span>)
   ...
  </div>

Some implementations are turning that portion into "( QED )" and others into "( Q E D )". The expectation is "(QED)" (sans spaces). That seems to imply that 2.F.iii.c should be an append without spaces. If that is indeed the case, what would be the expectation if the above snippet instead said:

    (<span aria-label="Quod">Q</span><span aria-label="erat">E</span><span aria=label="demonstrandum">D</span>)

What if buttons were used instead of spans? What if divs were used instead of spans? What if there's a mix?

Edit: What if the middle span were instead a text input. We have this test case:

if given
  <input type="radio" id="test">
  <label for="test">foo<input type="text" value="bar">baz</label>
then the accessible name of the element with id of "test" is "foo bar baz"

I'm pretty sure the part of the algorithm which dictates calculating name from content of the label is also 2.F. And in that case our expectation is the insertion of a space.

I realize the whitespace situation is a mess, but clarification on the above would be helpful in terms of fixing implementations -- assuming they indeed need to be fixed (i.e. because our "(QED)" expectations are correct).

Question on implicit label and TAC

In the following code snippet regarding an implicit label, what would the total accumulated text based on TAC be?

<label for="nam" id="first">
<input id="nam" type="checkbox" aria-labelledby="first sup1 sup2">
  Name
  <br>
  <div id="sup1">First</div>
  <div id="sup2">Last</div>
  
  </label>

This is a depressing example as there are better techniques to code this checkbox with support text. Still, the algorithm should be able to handle it.

Would the total accumulated text be "Name First Last First Last" or "Name First Last"?

2.B says:
"if computing a name, and the current node has an aria-labelledby attribute that contains at least one valid IDREF, and the current node is not already part of an aria-labelledby traversal, process its IDREFs in the order they occur..."

AccName algorithm doesn't account for specific roles and how these need to be treated differently when computing name from content

The following code block is an excerpt from the Naming Computation Prototype at
https://raw.githubusercontent.com/WhatSock/w3c-alternative-text-computation/8767d9a9250443ca0297acc4646411a13b3f24b1/docs/Sample%20JavaScript%20Recursion%20Algorithm/recursion.js

It reflects a discussion on the ARIA WG list regarding this topic referenced at
https://lists.w3.org/Archives/Public/public-aria/2017Jun/0057.html

This has a fundamental impact on the recursion algorithm, but it is not detailed within the spec, and it really should be.

These are rules that dictate when and how name from content should be computed, and for which roles they apply.

	var isException = function(node, refNode) {
		if (!refNode || !node || refNode.nodeType !== 1 || node.nodeType !== 1) {
			return false;
		}

		// Always include name from content when the referenced node matches list1, as well as when child nodes match those within list3
		var list1 = {
			roles: ['link', 'button', 'checkbox', 'option', 'radio', 'switch', 'tab', 'treeitem', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'cell', 'columnheader', 'rowheader', 'tooltip', 'heading'],
			tags: ['a', 'button', 'summary', 'input', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'menuitem', 'option', 'td', 'th']
		};

		// Never include name from content when current node matches list2
		var list2 = {
			roles: ['application', 'alert', 'log', 'marquee', 'timer', 'alertdialog', 'dialog', 'banner', 'complementary', 'form', 'main', 'navigation', 'region', 'search', 'article', 'document', 'feed', 'figure', 'img', 'math', 'toolbar', 'menu', 'menubar', 'grid', 'listbox', 'radiogroup', 'textbox', 'searchbox', 'spinbutton', 'scrollbar', 'slider', 'tablist', 'tabpanel', 'tree', 'treegrid', 'separator'],
			tags: ['article', 'aside', 'body', 'select', 'datalist', 'optgroup', 'dialog', 'figure', 'footer', 'form', 'header', 'hr', 'img', 'textarea', 'input', 'main', 'math', 'menu', 'nav', 'section']
		};

		// As an override of list2, conditionally include name from content if current node is focusable, or if the current node matches list3 while the referenced parent node matches list1.
		var list3 = {
			roles: ['combobox', 'term', 'definition', 'directory', 'list', 'group', 'note', 'status', 'table', 'rowgroup', 'row', 'contentinfo'],
			tags: ['dl', 'ul', 'ol', 'dd', 'details', 'output', 'table', 'thead', 'tbody', 'tfoot', 'tr']
		};

		var inList = function(node, list) {
			var role = node.getAttribute('role');
			var tag = node.nodeName.toLowerCase();
			return (
				list.roles.indexOf(role) >= 0 ||
				(!role && list2.tags.indexOf(tag) >= 0)
			);
		};

		if (inList(node, list2)) {
			return true;
		} else if (inList(node, list3)) {
			if (node === refNode) {
				return !isFocusable(node);
			} else {
				return !inList(refNode, list1);
			}
		} else {
			return false;
		}
	};

[AccName AAM] reinforcing "name" vs "description", split out algorithm into two

From @patrickhlauke on March 30, 2017 21:9

Currently, in the glossary http://w3c.github.io/aria/accname-aam/accname-aam.html#glossary there is a good distinction between "Accessible name" and "Accessible description". However, these two distinct concepts ("name" and "description") could really do with being more explicitly defined in their own prose section http://w3c.github.io/aria/accname-aam/accname-aam.html#mapping_additional_nd - maybe reusing/summarising their key nature, how ATs use them, etc from those glossary definitions.

In particular, the fact that the name is effectively always needed for interactive controls (xref https://www.w3.org/TR/aria-in-html/#fifth), and that an element that has no name but just a description is not ok in that context, would be good to add very explicitly.

Lastly, while it's space-saving to have the algorithm cover both name and description at the same time in http://w3c.github.io/aria/accname-aam/accname-aam.html#mapping_additional_nd_te, it doesn't exactly make it immediately obvious to follow (since every step then needs its own "if computing the name..." / "if computing the description..." prefixes). Perhaps splitting out the algorithm into two algorithms - one for name, one for description - and clarifying situations in which both results may be combined and exposed together as the overall text alternative may be clearer?

Copied from original issue: w3c/aria#544

accname-aam: step 2E, rule for button can cause infinite loop

From @cyns on April 29, 2016 19:52

We should remove the special case for button in step 2E because it can cause an infinite loop.

Consider the following markup:

<a href="javascript:void(0)" aria-role="button" aria-labelledby="myLabel" id="foo">Products</a>
<div id="myLabel" role="button">Content</div>

By following the algorithm as described in http://www.w3.org/TR/accname-aam-1.1/, name calculation ends up in an infinite loop when calculating the name of the tag.

A. (Step 1) - start with the empty string
B. (Step 2A) - Element is not hidden, so proceed
B. (Step 2B) - There is an aria-labelledby tag, so compute the Text Alternative of what aria-labelledby references (in this case, the div with role button)
Now compute the Text Alternative for "myLabel" and use that as the tag's name.
C. (Step 1') Start with the empty string
D. (Step 2A') Not hidden, so proceed
D. (Step 2B') Since I'm already part of an aria-labelledby traversal, skip this step
E. (Step 2C') No aria-label, so skip this step as well
F. (Step 2D') No native markup representation, so skip this step
G. (Step 2E') - We are "within the label of another widget", and Role is button, so "return the text alternative of the button." - that is what is currently being calculated, so this step is redundant. If we were to start over here on Text Alternative, we'd never escape the loop. The correct behavior is simply to proceed with the Text Alternative that we're in the process of calculating. So the button role just needs to be removed from the list of special cases here.

Copied from original issue: w3c/aria#357

Each step should contain clause to check result for empty string

Each step in the algorithm should check whether the accumulated text it has collected is empty. If empty, it should proceed to the next step.

Such a check is occurring on Step C:

Otherwise, if computing a name, and if the current node has an aria-label attribute whose value is not the empty string, nor, when trimmed of white space, is not the empty string:…

However, other steps do not mention such a check.

As currently written, if step B were to generate an empty string, the algorithm would stop at Step B and there would be no accessible name.
Example:

<button aria-labelledby="id1">submit<button>
<div id="id1"></div>

accname-aam need to clarify aria-owns in Step 2F

From @jnurthen on March 21, 2017 21:9

Need to clarify if aria-owns should be taken into account in step 2F (iii - a).

When talking about "child node"

  • Chrome includes nodes owned through use of aria-owns
  • FF only considers DOM children

To be honest I don't care what the result is - but I want consistency. Please clarify.

(see bug https://bugs.chromium.org/p/chromium/issues/detail?id=702811 logged against Chrome)

Copied from original issue: w3c/aria#538

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.