Original Article: (Not so) Simple ARIA Tree Views and Screen Readers
Author: accessibleculture.org

(Não tanto) Visualizações de árvore ARIA simples e leitores de tela

Comecei a testar vários leitores de tela com diferentes visualizações de árvores ARIA. Acontece que há um pouco acontecendo com leitores de tela e visualizações de árvores, então a pesquisa ficou um pouco longa. Também revela que existe uma variabilidade significativa entre leitores de tela na forma como eles lidam com diferentes visualizações de árvores ARIA. Não encontrei uma única maneira de criar uma visão de árvore simples que forneça o que eu chamaria de experiência totalmente decente em leitores de tela atuais e populares.

Contudo, tirei dos resultados do teste para desenvolver uma abordagem que eu acho que fornece o melhor suporte para as combinações atuais de leitores de tela e navegador, embora com alguns compromissos. A melhor abordagem está descrito abaixo. O exibições de árvores de exemplo e resultados de teste venha depois, se você estiver interessado.

Observe também que eu não sou um desenvolvedor JavaScript ou jQuery real por qualquer estiramento, então, enquanto os scripts por trás dos exemplos de exibição em árvore funcionam, sua construção é certamente uma espécie de naff. Ou seja, sinta-se livre para reutilizá-lo para o seu próprio fim, mas sua milhagem pode variar.

O que é uma vista em árvore?

From the WAI-ARIA 1.0 Práticas de criação:

Uma vista em árvore é um componente para navegar por listas hierárquicas. É composto por um ou mais nós de nível superior. Um nó pode ter filhos ou pode ser um nó final. Os nós com filhos podem ser expandidos ou colapsados - quando expandido, seus nós filho são visíveis. Quando colapsados, as crianças não são visíveis. Geralmente, há algum tipo de indicação visual se um nó tem filhos e pode ser expandido. Qualquer número de nós pode ser expandido por vez e os nós secundários podem conter crianças.

Esse tipo de componente de navegação deve ser familiar. Está disponível de alguma forma ou outra para visualizar e navegar as hierarquias de arquivos e arquivos nos principais sistemas operacionais. Também é usado em aplicativos da Web que incluem funcionalidade de gerenciamento de arquivos ou documentos.

Embora sejam muito comuns, as visualizações de árvores não são o mais simples dos widgets interativos, e garantir que eles sejam acessíveis aos leitores de tela, os usuários significam fornecer um bom suporte ao teclado e foco, além de transmitir informações sobre a estrutura e o estado da árvore. Felizmente, o ARIA fornece uma série de funções e propriedades que podem ser usadas para realizar isso.

Funções e propriedades do ARIA Tree View

As visualizações de árvore básicas usam os seguintes atributos ARIA:

Além de role="presentation", e atributos globais como aria-label e aria-labelledby, existem outros atributos ARIA que podem ser usados dependendo da complexidade ou propósito de uma vista em árvore. Esses incluem aria-activedescendant, aria-level, aria-owns, aria-setsize, e aria-posinset.

Foco de teclado e interação

A WAI-ARIA 1.0 seção de práticas de criação na visualização de uma árvore descreve uma variedade de comandos de teclado que devem ser disponibilizados aos usuários para que eles possam interagir com a exibição em árvore. Para a navegação básica de uma vista em árvore, os seguintes comportamentos de teclas de seta são definidos:

  • Up Arrow e Down arrow mova o foco entre nós visíveis.
  • Left arrow em um nó aberto fecha o nó.
  • Left arrow em um nó fechado ou final, move o foco para o pai do nodo.
  • Right arrow expande um nó fechado, move-se para o primeiro filho de um nó aberto ou não faz nada em um nó final.

Na vista em árvore padrão, apenas um nó deve estar no Tab ordem e focagem a qualquer momento. Isso geralmente é feito gerenciando o tabindex atributos nos itens da árvore. Um valor de "-1" remove um elemento do Tab ordem, enquanto um valor de "0" o adiciona (se não for focalizado nativamente). Como tal, apenas o nó da árvore atualmente focado deve ter tabindex="0". Todos os outros deveriam ter tabindex="-1". Quando o foco se move para um nó diferente, o tabindex os valores são atualizados em conformidade. Podemos nos referir a isso como roaming tabindex abordagem desde tabindex="0" percorre a vista da árvore com o nó focado.

Outra abordagem, e usada no melhor abordagem proposta aqui, envolve manter o foco no próprio recipiente da árvore. Todo nó é mantido fora do Tab ordem. Para acompanhar o nó está ativo, aria-activedescendant é definido no recipiente da árvore e atualizado dinamicamente com uma referência ao id do nó atualmente focado.

Comportamento ideal do leitor de tela ideal

Diferentes leitores de tela em diferentes navegadores mostram uma série de comportamentos com as visualizações de árvores ARIA. Se considerarmos todos esses comportamentos em conjunto com as funções programáticas e os estados que a ARIA fornece, sugiro que o comportamento ideal do leitor de tela com as visualizações de árvores inclua:

  • se relevante (ou seja, no JAWS, NVDA e Window-Eyes), inserindo automaticamente formas ou modo de aplicativo ao configurar o foco na árvore (veja o artigo relacionado, Widgets ARIA e Suporte em Modo Focus / Forms em JAWS e NVDA);
  • identificando o widget como uma vista em árvore ou similar ao definir o foco na árvore;
  • identificando o estado expandido / colapsado do nó quando ele recebe foco ou é recolhido / expandido;
  • indicando o nível do ramo do nó atual quando ele recebe o foco;
  • indicando o número de nós de irmão no nível de ramo atual e a posição do nó atual quando ele recebe foco (por exemplo, anunciando algo como "dois de quatro");
  • indicando o número de nós secundários quando um nó expandido recebe foco (por exemplo, anunciando algo como "três itens").

Do Cinco leitores de tela testados, Cada um mostrou pelo menos alguns destes comportamentos nos quatro exemplos e, em alguns casos, quase todos eles.

Qual é a melhor abordagem?

O melhor exemplo de abordagem

A seguinte vista em árvore aborda os problemas que foram identificados nos testes e estão descritos abaixo. Se você tem idéias sobre como melhorá-lo ou como melhor resolver algumas das deficiências que determinadas combinações de leitores de tela e de navegadores têm com as visualizações simples da árvore ARIA, compartilhe.

Esta vista em árvore funciona em todos os Leitor de tela e combinações de navegadores testados. Talvez o maior problema, conforme discutido abaixo, seja a verbosidade experimentada ao navegar na árvore com JAWS, NVDA e Window-Eyes no Internet Explorer, um problema em que não encontrei uma solução ideal que não cause simultaneamente Problemas mais graves em outros leitores de tela, especialmente VoiceOver.

Estrutura básica

As visualizações da árvore são uma maneira de navegar listas hierárquicas, então de boa forma semântica, o uso da marcação de lista para a estrutura básica da árvore é provavelmente o mais apropriado. Algumas visualizações de árvores usam div e span elementos, que funcionam bem enquanto a ARIA e JavaScript são suportados. Se não estiverem, então o usuário ficará com nada além de um monte de aninhados div e span elementos que não serão úteis.

Na melhor abordagem proposta, a exibição em árvore usa uma lista desordenada e cada item da lista possui um link aninhado. Os itens da lista têm role="treeitem", e implemente aria-selected, aria-level, e aria-expanded se tiverem filhos. O link aninhado em cada item da lista é definido com role="presentation" e tabindex="-1". Todos esses atributos são adicionados usando o JavaScript, uma vez que a funcionalidade da exibição em árvore depende dos controles de chave de seta com script.

Os links aninhados também poderiam ser substituídos por aninhados span se a sua vista em árvore particular não solicitar a utilização de links. Com este exemplo de melhor prática, não há diferença de comportamento em nenhum dos leitores de tela, exceto um aumento relativamente menor na verbosidade em Window-Eyes onde links aninhados versus span está preocupado.

A estrutura hierárquica da árvore e a relação entre os nós das folhas da criança e seus pais estão representadas no DOM estrutura. Ou seja, as listas de nó filho são crianças para o item da lista do nó pai. Se os links aninhados fossem os nós, cada lista de nó filho seria um irmão para o link do nó pai, em oposição ao filho. No final, isso realmente não parece importar para JAWS, NVDA ou ORCA, o que é bom se as listas de nó filho são crianças ou irmãos do nó pai na hierarquia DOM. Window-Eyes não importa aninhado span como os nós, mas não funciona bem com links aninhados. E O VoiceOver não gosta de links aninhados como nós.

A árvore usa aria-activedescendant (para suportar o VoiceOver). O foco se move para e permanece na própria lista de árvores. Não se move através dos nós da árvore. Em vez disso, usando as teclas de seta para selecionar ou expandir / colapsar um nó atualiza os nodos ' aria-selected e aria-expanded atributos, conforme apropriado, e a lista de árvores aria-activedescendant atributo. Pressionando Enter ou Space estabeleca location ao href do link aninhado id is referenced by aria-activedescendant.

Each child node list has role="group" para indicar que os itens que contém formam uma coleção distinta de nós que é descendente do nó pai na hierarquia de árvore. Ao mesmo tempo, porque as listas de nó filho são filhos para o item da lista do nó pai, isto leva a problemas com a forma como o Internet Explorer calcula o nome acessível do nó pai. Vejo Internet Explorer e nomes acessíveis abaixo para mais. Alguns desses comportamentos problemáticos no IE são mitigados pela configuração aria-labelledby na árvore de raiz ul para fazer referência ao título anterior. O resto pode ser facilmente resolvido usando aria-labelledby para definir o rótulo desejado para cada item de lista de nó, mas isso causa alguns Problemas sérios para o VoiceOver no Safari. Isso sugere que, uma vez que o VoiceOver suporte o roaming tabindex abordagem e pode identificar o número de crianças de cada nó, independentemente da estrutura do DOM, tornando os links aninhados os nós podem ser uma abordagem razoável.

Por uma boa estrutura de DOM e para evitar VoiceOver apresentando informações incorretas sobre a contenção do nó filho, A melhor abordagem proposta aqui usa os itens de lista para os nós, e não os links aninhados dentro deles, mesmo que isso torne as coisas um pouco detalhadas para leitores de tela no IE. Este é um julgamento.

Abordando os problemas

VoiceOver/Safari e aria-activedescendant

Como o VoiceOver no Safari atualmente só realmente oferece suporte a exibições de árvores que usam aria-activedescendant em vez de uma roaming tabindex, e uma estrutura DOM que reflete os relacionamentos nó e nó filho, o exemplo de melhor aproximação começa com isso. Qualquer outra abordagem simplesmente não funcionará corretamente com o VoiceOver.

Ao usar uma roaming tabindex abordagem com o VoiceOver, as teclas de seta moverão o foco do navegador de nó para nó e expandirão ou diminuirão os nós, mas o cursor do VoiceOver não será seguido. Ou seja, o cursor do VoiceOver não sincroniza com o cursor do navegador. Enquanto o VoiceOver anunciará mudanças no estado expandido / colapsado de um nó, ele não anunciará a etiqueta do nó atualmente focado (a menos que o cursor do VoiceOver também esteja no nó).

Não está claro se esta limitação é um bug com o VoiceOver ou com o Safari, mas a Apple foi informada disso. Minha suspeita é que é um problema do VoiceOver, pois, do que eu posso dizer, mesmo com o roaming tabindex abordagem, o Safari está passando os valores apropriados para o Mac OS X Accessibility Protocol.

Deve também notar-se que enquanto o aria-activedescendant A abordagem funciona bastante bem com o VoiceOver ao usar as teclas de seta, ele efetivamente não funciona com os comandos de navegação do VoiceOver (Ctrl + Option + arrow keys). Nem o comando VoiceOver para abrir e fechar um triângulo de divulgação (Ctrl+Option+\) trabalhe para expandir / colapsar um nó.

Felizmente, os outros quatro leitores de tela testados gerenciam bem o suficiente com o aria-activedescendant abordagem.

Internet Explorer e nomes acessíveis

O Internet Explorer cria um nome acessível para alguns elementos com um role atributo concatenando o texto de todos os elementos filho. Por exemplo, se um item da lista com role="treeitem" tem uma lista aninhada de 15 nós secundários, ao definir o foco ou selecionar esse item da lista, JAWS e NVDA lerão não apenas o texto do item da lista, mas o texto de cada um dos 15 itens da lista de nó filho, seja eles expandidos e visível ou não. O que é pior é que quando o foco se move de fora da árvore para a árvore ou um nó dentro da árvore, NVDA e Window-Eyes lerão todos os nós únicos em toda a árvore, expandidos e visíveis ou não. Isso rapidamente se distrai, especialmente em uma árvore com filiais de nodos longos. Experimente o exemplo A no IE com qualquer um desses leitores de tela e confira por você mesmo.

No IE, quando um nó recentemente selecionado está em um ramo diferente e parte de uma lista filho com role="group", NVDA lê todos os nós dentro do agrupamento e adiciona a palavra "agrupamento". Se removemos role="group" a partir da lista infantil, o NVDA simplesmente adiciona a palavra "lista" em vez de "agrupar", mas ainda lê os itens da lista do grupo. Se usarmos aria-labelledby na lista filho para fazer referência ao rótulo do nó pai, o NVDA usa esse rótulo como o nome do agrupamento, que é muito menos detalhado, embora isso agora provoque o NVDA no FF para apresentar cada lista filho como um agrupamento com o rótulo referenciado, o qual não fazia nada antes. Com esta solução, o Orca in FF se comporta de forma semelhante, pois apresenta cada lista de filhos como um "painel" em vez de um "agrupamento", usando o rótulo referenciado para especificar o painel.

Se formos um passo adiante e usamos role="presentation" na lista infantil em vez de role="group", então o NVDA não lê o agrupamento de filhos no IE. No entanto, usando role="presentation" na lista infantil em vez de role="group" provoca JAWS no FF, ao expandir um nó com crianças, para ler o rótulo de cada nó visível nessa lista infantil. Isso pode ser visto como um pequeno aumento na verbosidade para JAWS em FF para uma diminuição significativa na verbosidade para NVDA no IE. Por outro lado, como a maioria dos usuários NVDA provavelmente brincam com o Firefox, e role="group" É, penso eu, a marcação ARIA apropriada para listas de itens infantis de crianças, o exemplo de melhor abordagem aqui é válido role="group" e aplica aria-labelledby para referenciar a etiqueta do nó pai da lista filho.

Note que usando div e span elementos em vez de uma lista não resolvem esse problema com a forma como o IE calcula o nome acessível dos itens da lista de nós e como os leitores de tela retransmitizam essa informação.

Lendo a Regra 2C do Cálculo de Nome Acessível do ARIA, O comportamento do IE parece estar correto até certo ponto, embora eu não tenha certeza se deve incluir nesse cálculo descendentes que estão escondidos através de display:none e, portanto, não deve estar presente na árvore de acessibilidade. Também não tenho certeza de que esta seja a abordagem certa para itens de árvores. Eu acho que isso faz sentido para elementos interativos mais discretos, como botões e itens de menu, que não esperaria conter controles aninhados. No entanto, posso ver um caso em que itens de árvore, assim como itens de lista normais, podem razoavelmente conter um ou mais controles. Em qualquer caso, corre o comportamento ou não, faz uma experiência bastante detalhada com leitores de tela no IE.

VoiceOver não gosta da solução

Para resolver isso, a solução ideal seria garantir que tanto a árvore principal ul e cada nó da árvore li usa aria-labelled para identificar programaticamente o nome apropriado acessível para a árvore e cada nó. Em um mundo ideal, poderíamos usar aria-labelledby na principal ul para referenciar o título anterior à árvore e em cada item de lista de nós, aria-labelledby para fazer referência ao link aninhado.

Eu digo "em um mundo ideal" porque usar aria-labelledby (ou aria-label para isso) nos nós, por algum motivo, interrompe o VoiceOver de anunciar o nome do nó selecionado. Isso também faz com o VoiceOver chamar a exibição de árvore de uma caixa de listagem, ao invés de uma tabela como o VoiceOver faz convencionalmente com vistas de árvore e com a qual eu espero que a maioria dos usuários do VoiceOver estejam familiarizados.

Usando aria-labelledby na árvore principal ul, no entanto, parece não causar problemas e tem o benefício de evitar que NVDA e Window-Eyes lêem todos os nós únicos em toda a árvore quando o foco primeiro se move para a árvore. No entanto, não ouvir o nome de cada nó como um navega através da árvore com o VoiceOver é um pouco de um disjuntor de negócios, então a melhor abordagem proposta aqui não usa aria-labelledby nos nós.

Este é um compromisso significativo: para obter uma visão em árvore que funciona no VoiceOver e em outros leitores de tela importantes, os usuários do JAWS e NVDA que preferem trabalhar com o Internet Explorer terão uma experiência muito menos agradável. Permanece utilizável, mas está longe de ser ideal.

Algumas visualizações de árvore têm links aninhados dentro dos nós individuais, enquanto outros usam links aninhados para os próprios nós. Algumas árvores não incluem links, talvez substituindo-os por aninhados span. Mais uma vez, cada uma dessas abordagens pode ser feita para trabalhar em um ou mais, mas não em todos, leitores de tela. Incluí links aninhados na maioria dos exemplos de teste porque acho que eles têm seus casos de uso e o uso de links causa alguns problemas com alguns leitores de tela que vale a pena notar. Os links também fornecem um elemento padrão, nativo focalizável e acionável deve, por exemplo, JavaScript não estar habilitado.

No VoiceOver, se uma vista em árvore usar aria-activedescendant usa os links aninhados como os nós em vez dos itens da lista, cada nó com filhos é anunciado como tendo zero nós filhos fechados, o que é apenas incorreto. Usando aria-owns, combinado ou não com aria-setsize e aria-posinset, não funciona para que o VoiceOver reconheça o número de nós filhos contidos. Por esse motivo, a melhor abordagem proposta mantém os itens da lista como os nós, em vez de usar os links aninhados como os nós.

JAWS / Firefox e links aninhados

Links aninhados nos itens da lista de nó de árvore impedem JAWS no Firefox de inserindo automaticamente o modo de formulários, a menos que os links tenham role="presentation". Como tal, em nosso exemplo de melhor abordagem, os links aninhados são definidos com role="presentation. Se sua exibição em árvore não requer links aninhados, o que pode não depender da finalidade da sua exibição em árvore e da funcionalidade que você está tentando fornecer, então não há necessidade de se preocupar com isso. Por exemplo, se os itens da árvore estiverem aninhados span Em vez de links, JAWS no FF entra automaticamente no modo de formulários.

Enquanto role="presentation" nos links aninhados ajuda JAWS no Firefox a entrar automaticamente no modo de formulários, ele faz Window-Eyes mais detalhado. Na melhor abordagem proposta, que usa links aninhados com role="presentation", se o nó selecionado for parte de um ramo de nó filho, o Window-Eyes no IE lê os rótulos de todos os nós nesse ramo filho, sejam eles visíveis ou não, assim como JAWS e NVDA fazem no IE. Se os links forem trocados por aninhados span, então Window-Eyes comporta-se muito bem e não lê mais todos os nomes de nó filho. Isso acontece apenas em Window-Eyes, no entanto. Se links aninhados ou span, JAWS e NVDA comportam o mesmo com este exemplo de melhor abordagem no IE. Novamente, dependendo do seu caso de uso, você pode querer ir com aninhado span em vez de links.

Numeração do nível do ramo

Onde se indica o nível do ramo de um nó focado, alguns leitores de tela, por padrão, identificam o ramo do nó da raiz como nível zero, enquanto outros o chamam de nível um. Em JAWS e VoiceOver, o ramo superior da árvore é considerado nível zero. NVDA apenas no Firefox, bem como Window-Eyes e Orca, considere que o ramo do nó raiz seja o nível um. NVDA no IE não indica o nível de ramo atual do nó.

Pode-se definir aria-level em um nó para identificar o nível de ramificação desejado, embora isso não funcione em todos os leitores de tela. Por exemplo, configurando aria-level="1" Em nós de primeiro nível, o VoiceOver, bem como o JAWS no IE, mas não no Firefox, anunciarão que esses nós estão no nível um, em vez de no zero. Isso proporciona um comportamento mais consistente em todos os leitores de tela e, portanto, é implementado na melhor abordagem proposta aqui.

Indicando a Contenção Infantil

Somente o JAWS no IE e o VoiceOver indicam o número de nós filhos de um nó expandido. Seria ótimo se isso pudesse ser abordado usando algo como aria-posinset com aria-setsize, mas esses atributos não parecem ter nenhum efeito em nenhuma das combinações do leitor de tela e do navegador, onde o número de nós filho não é anunciado.

NVDA e Internet Explorer 10

No IE10, a interação do NVDA com as visualizações de árvores que utilizam aria-activedescendant parece um tanto quebrado. Isso parece ser um problema do IE10, conforme o NVDA executa conforme o esperado no IE9. Basicamente, no IE10, o NVDA não entra automaticamente no modo de aplicativo quando o foco é definido como um nó na árvore. O modo de aplicação automática pode ser forçado por configuração role="application" no recipiente da árvore, mas isso não torna o resto da árvore utilizável com NVDA no IE10. Mesmo se alguém conseguir entrar no modo de aplicação, o acesso total a cada nó na árvore não parece possível.

Então, este é outro compromisso significativo: uma visão em árvore que funciona em todos os leitores de tela testados não funcionará de forma útil com o NVDA no IE10. Ao mesmo tempo, isso provavelmente não é o pior do mundo, já que a maioria dos usuários do NVDA provavelmente trabalha com o Firefox.

Juntando tudo

Tendo em conta todas as questões descritas acima, tentei propor uma abordagem para a construção de visualizações de árvores que funcionem em todas as combinações populares de leitores de tela e navegador, ao mesmo tempo que minimizam os efeitos negativos do comportamento particular de cada leitor de tela. Eu não estou muito feliz com isso, pois apresenta algum comportamento desagradável para leitores de tela no IE para suportar limitações significativas no tratamento do VoiceOver das visualizações de árvores.

Novamente, se você tiver outra abordagem que você acha que gerencia essas questões melhor, ou se você perceber algo que eu perdi, por favor me avise. Há tanta variação nas formas em que se pode marcar uma vista em árvore e como diferentes leitores de tela e navegadores lidam com eles que não é improvável que tenha esquecido algo.

Testando o Comportamento do Leitor de Tela Real

Para testar o suporte ao leitor de tela para WAI-ARIA vista de árvore, Eu criei quatro exemplos simples. Na verdade, criei muitos outros exemplos, apenas para tentar ou descartar possíveis soluções para alguns dos problemas descobertos. Mas eu estou apenas incluindo os quatro exemplos abaixo, pois eles revelam os principais problemas que minha melhor abordagem proposta tenta abordar.

Cada um dos exemplos é uma visão de árvore simples, de seleção única, em oposição a uma árvore de seleção múltipla onde mais de um item pode ser selecionado ao mesmo tempo. Nestes exemplos, apenas um item de árvore pode ser selecionado por vez. Isso significa que o item da árvore com foco também é identificado como selecionado usando aria-selected="true".

Os exemplos são todas as variações de outras visualizações de árvore de exemplo que podem ser encontradas na web, como Exemplo de Árvore 3 da iCITA, Widget da árvore de componentes acessíveis jQuery-ui de Hans Hillen, e Exemplo de árvore ARIA de James Craig.

Leitores de tela testados

Os exemplos foram testados com o seguinte leitor de tela e combinações de navegador para o quão bem eles exibiram os seis comportamentos ideais para as visualizações da árvore ARIA acima mencionado:

  • tanto JAWS 14 como NVDA 2012.3.1 com o Internet Explorer 9 e o Firefox 19 no Windows 7 e o Internet Explorer 10 no Windows 8
  • Window-Eyes 8.1 com o Internet Explorer 10 e o Firefox 19, ambos no Windows 8
  • VoiceOver com o Safari 6.0.2 no Mac OS X 10.8.2 (Mountain Lion) e 10.7.5 (Lion)
  • Orca 3.4.2 com o Firefox 19 no Ubuntu 12.04

Observe que nas tabelas de resultados para cada exemplo, a menos que indicado de outra forma, o comportamento do JAWS no IE9 é o mesmo que seu comportamento no IE10. O mesmo acontece com NVDA no IE9 e IE10.

Certifique-se também de ler as notas associadas aos resultados de teste de cada exemplo, uma vez que estes discutem comportamentos adicionais e problemas não cobertos nas tabelas de resultados.

Exemplo A

Exemplo A usa uma lista simples não ordenada com role="tree". Os itens da lista individual são atribuídos role="treeitem", e aninhado span elementos. Usando os comandos básicos do teclado, o foco se move do item da lista para o item da lista. O item da lista ou o nó com foco tem aria-selected="true", enquanto todos os outros nós estão configurados para aria-selected="false".

O estado aberto ou fechado de nós com crianças é indicado visualmente com ícones positivos e negativos bastante padrão carregados como imagens de fundo CSS em um vazio div. Embora provavelmente não seja necessário, para garantir que eles estejam escondidos dos leitores de tela, aria-hidden="true" é usado. Os usuários do mouse podem clicar nesses ícones para alternar o estado expandido / colapsado do nó. Usuários de teclado, é claro, usam as teclas de seta.

Quando um nó com crianças é expandido, é aria-expanded O atributo é alterado de "falso" para "verdadeiro", eo ícone de alternância visível é atualizado de um sinal de mais para um sinal de menos para refletir o estado do nó. A lista infantil (role="group") que anteriormente estava escondido usando display:none, está configurado para display:block. O uso de aria-hidden não é exigido como display:none já serve para ocultar esse conteúdo de todos os usuários e tecnologias de assistência.

Este padrão de atualização dos atributos relevantes em nós e grupos de nós filhos ocorre de forma mais ou menos da mesma maneira com todos os exemplos apresentados aqui.

Aqui está um exemplo de código do exemplo A:

<ul class="tree" role="tree">
   
<li role="treeitem" aria-expanded="true" aria-selected="true" tabindex="0" class="hasChildren">
     
<div class="toggle expanded" aria-hidden="true"></div>
     
<span class="">Flora</span>
     
<ul class="children" role="group" style="display: block;">
         
<li role="treeitem" aria-expanded="false" aria-selected="false" tabindex="-1" class="hasChildren">
           
<div class="toggle collapsed" aria-hidden="true"></div>
           
<span>Trees</span>
           
<ul class="children" role="group" style="display: none;">
               
<li role="treeitem" aria-selected="false" tabindex="-1" class="noChildren">
                 
<span>Maple</span>
               
</li>
               ...
           
</ul>
         
</li>
         ...
     
</ul>
   
</li>
   ...
</ul>
Resultados do teste para o exemplo A
Suporte do leitor de tela para o exemplo de árvore View A
Screen Reader/Browser Inicia o modo de aplicação no foco Identifica a vista de árvore ou similar Identifica o estado Expandido / Recusado do Nó Indica o Nível de Filial do Nó Indica a posição do nó entre os nós de irmão Indica o Número de Crianças do Nó Expandido
JAWS em IE9/10 Sim Sim, mas apenas no modo Procurar Sim Sim Sim, mas apenas para nós colapsados ou finais Sim
JAWS em FF19 Sim Sim, mas apenas no modo Procurar Sim Sim Sim Não
NVDA em IE9/10 Sim Sim Sim Não Não Não
NVDA em FF19 Sim Sim Sim Sim Sim Não
Window-Eyes em IE10 Sim Sim Sim Sim Sim Não
Window-Eyes em FF19 Sim Sim Sim Sim Sim Não
VoiceOver em Safari 6.0.2 N/A Árvore identificada como uma tabela Não Não Não Não
Orca em FF19 N/A Sim Sim Sim Não Não

Notas de resultado para o exemplo A

JAWS e Exemplo A
  • Tanto no IE quanto no FF, ao entrar na vista em árvore, JAWS fornece instruções de interação, "Para mover ou expandir itens, use as teclas de seta". Esse comportamento é comum para JAWS em todos os exemplos apresentados aqui.
  • Somente no IE, ao definir o foco ou expandir / colapsar um nó com filhos, o JAWS lê cada nó filho, seja ele expandido e visível ou não. Isso é bastante detalhado e distorcido, e tem a ver com uma concatenação interessante que o IE faz com o nome acessível de alguns elementos configurados com um role atributo. Efetivamente, o nome acessível para o li com role="treeitem" torna-se uma string contendo o texto de cada elemento filho, incluindo listas de crianças aninhadas escondidas usando display:none. Configuração aria-labelledby ao id do item da lista aninhado span elemento resolve isso.
  • Lendo Regra 2C do Cálculo de Nome Acessível do ARIA, O comportamento do IE parece estar correto, embora eu não tenha certeza se deve incluir nesse cálculo descendentes que estão escondidos através de display:none e, portanto, não deve estar presente na árvore de acessibilidade.
NVDA e Exemplo A
  • Quando primeiro foco de configuração para qualquer nó na árvore no IE, NVDA lê todos os nós únicos na árvore, expandidos e visíveis ou não. Novamente, usando aria-labelledby na lista principal da árvore resolve isso.
  • Quando o foco muda de ramificação e é movido para um nó em uma lista filho com role="group", ele lê todos os nós dentro do agrupamento e adiciona a palavra "agrupamento". Se removemos role="group" a partir da lista infantil, o NVDA simplesmente adiciona a palavra "lista" em vez de "agrupar", mas ainda lê os itens da lista do grupo. Se usarmos aria-labelledby na lista filho para fazer referência ao rótulo do nó pai, então o NVDA usa esse rótulo como o nome do agrupamento, que é muito menos detalhado. Ainda melhor, se usarmos role="presentation" na lista infantil em vez de role="group", então NVDA não lê o agrupamento filho. No entanto, isso causa JAWS no FF, ao expandir um nó com crianças, para ler o rótulo de cada nó infantil visível.
  • Além disso, no IE, ao definir o foco em um nó com filhos, NVDA lê todos os nó filhos, seja ele expandido e visível ou não. Isto é, além da NVDA primeira leitura todos os nós em uma lista filho com role="group" Quando o foco primeiro se move para um nó nesse agrupamento.
  • NVDA não indica o número de itens filho em um nó expandido. Usando aria-setsize não tem nenhum efeito.
Window-Eyes e Exemplo A
  • No IE, ao primeiro foco de configuração para um nó dentro da árvore, Window-Eyes lê todos os nós da árvore, visíveis e expandidos ou não. Configurando aria-labelledby no principal da árvore ul pára que isso aconteça.
  • Depois de mover o foco para um nó em um ramo diferente, o Window-Eyes anuncia o nível do ramo do nó, que ele chama de "profundidade".
VoiceOver e Exemplo A
  • Curiosamente, o VoiceOver identifica árvores como tabelas e identifica o número de linha equivalente do nó selecionado. Isso é pelo menos consistente com a forma como o VoiceOver lida com as visualizações da árvore no Finder no Mac OS X, então espero que os usuários do VoiceOver estejam familiarizados com isso. Ainda assim, acho um pouco estranho.
  • Navegar com as teclas de seta move o foco do navegador de nó para nó, mas o cursor do VoiceOver não segue o foco do navegador. Você pode expandir / colapsar nós usando as teclas de seta e o VoiceOver anunciará qual número de linha é expandido / colapsado, mas não o conteúdo de texto do nó, tornando este exemplo de exibição de árvore efetivamente inutilizável neste caso. Não está claro se este é um WebKit ou um bug do VoiceOver, mas a Apple foi informada disso.
  • Por outro lado, o uso dos comandos de navegação do VoiceOver para mover o cursor do VoiceOver de um nó para outro faz com que o VoiceOver anuncie o nome do nó, a posição eo estado expandido / colapsado, mas o foco do navegador não segue e mantenha a sincronia com o cursor do VoiceOver. O comando VoiceOver (Ctrl+Option+\expandrequest e collapserequest eventos IndieUI são suportados.
Orca e Exemplo A
  • Orca não indica o número de itens secundários em um nó expandido. Usando aria-setsize não tem nenhum efeito.
  • Orca não indica o número de nós de irmão no nível de ramo atual ou a posição entre eles do nó com foco. Usando aria-posinset com aria-setsize não tem efeito.

Exemplo B

Exemplo B é uma lista desordenada com role="tree", como o exemplo A, mas os itens da lista têm links aninhados, e são os links que são definidos com role="treeitem". O foco se move através dos links, e os links ' aria-selected os valores são atualizados em conformidade. Para evitar que a semântica dos itens da lista interfira, cada um li tem role="presentation.

Observe que os agrupamentos de nós filho não são aninhados como descendentes diretos de seus nós pai, quais são os links com @ role = "treeitem". Em vez disso, eles são irmãos no link. Isso não parece prejudicar JAWS, NVDA ou ORCA, que atribuem relações apropriadas entre itens de árvore e seus agrupamentos de sub-nó. Pode ter algum efeito no VoiceOver, mas o VoiceOver não funciona com esta estrutura de exibição de árvore em nenhum caso.

Resultados do teste para o exemplo B
Comportamento do Leitor de Tela com Vista de Árvore Exemplo B
Screen Reader/Browser Inicia o modo de aplicação no foco Identifica a vista de árvore ou similar Identifica o estado Expandido / Recusado do Nó Indica o Nível de Filial do Nó Indica a posição do nó entre os nós de irmão Indica o Número de Crianças do Nó Expandido
JAWS no IE9 / 10 Sim Sim, mas apenas no modo Procurar Sim Sim Sim, mas apenas para nós colapsados ou finais Sim
JAWS no FF19 Sim Sim, mas apenas no modo Procurar Sim Sim Sim Não
NVDA in IE9/10 Sim Sim Sim Não Não Não
NVDA no FF19 Sim Sim Sim Sim Sim Não
Window-Eyes no IE10 Não Sim Sim Sim Sim Não
Window-Eyes no FF19 Sim Sim Sim Sim Sim Não
VoiceOver no Safari 6.0.2 N/A Árvore identificada como uma tabela Não Não Não Não
Orca no FF19 N/A Sim Sim Sim Não Não

Notas de resultados para o exemplo B

JAWS e Exemplo B

Os resultados do exemplo B são iguais aos do exemplo A, com uma grande exceção: porque os links aninhados, e não os itens da lista, são definidos com role="treeitem", definir foco ou expandir / colapsar um nó não faz com que o JAWS leia todos os seus nós filho.

NVDA e Exemplo B

Os resultados são iguais aos do exemplo A, exceto que, adicionalmente, no IE, ao definir o foco para um nó, que é um link neste exemplo, o NVDA lê o link href valor.

Window-Eyes e exemplo B

Os resultados para Window-Eyes no exemplo B são os mesmos que no exemplo A, exceto que no IE:

  • Quando a primeira configuração do foco para um nó na árvore, Window-Eyes não entra automaticamente no modo de formulários; e,
  • Quando o foco é definido como um nó, Window-Eyes, como o NVDA, lê o link href valor.
VoiceOver e Exemplo B

O comportamento do VoiceOver no exemplo B é o mesmo que no exemplo A.

Orca e Exemplo B

O comportamento da Orca no exemplo B é o mesmo que no exemplo A.

Exemplo C

Exemplo C é como o exemplo B, na medida em que os itens da lista possuem links aninhados. Nesse caso, no entanto, os itens da lista são os nós e configurados com role="treeitem". O foco se move através dos itens da lista. Ativando um item de árvore pressionando Enter ou Space esteabelece location para o link aninhado href valor.

Resultados do teste para o exemplo C
Comportamento do Leitor de Tela com Vista de Árvore Exemplo C
Screen Reader/Browser Inicia o modo de aplicação no foco Identifica a vista de árvore ou similar Identifica o estado Expandido / Recusado do Nó Indica o Nível de Filial do Nó Indica a posição do nó entre os nós de irmão Indica o Número de Crianças do Nó Expandido
JAWS em IE9/10 Sim Sim, mas apenas no modo Procurar Sim Sim Sim, mas apenas para nós colapsados ou finais Sim
JAWS no FF19 Sim, mas veja as notas Sim, mas apenas no modo Procurar Sim Sim Sim Não
NVDA no IE9/10 Sim Sim Sim Não Não Não
NVDA in FF19 Sim Sim Sim Sim Sim Não
Window-Eyes no IE10 Sim Sim Sim Sim Sim Não
Window-Eyes no FF19 Sim Sim Sim Sim Sim Não
VoiceOver no Safari 6.0.2 N/A Árvore identificada como uma tabela Não Não Não Não
Orca no FF19 N/A Sim Sim Sim Não Não

Notas de resultado para o exemplo C

JAWS e o exemplo C
  • No IE, como no exemplo A, o JAWS lê todos os nós filhos, expandidos e visíveis ou não, ao definir o foco ou expandir / colapsar um nó com filhos.
  • Em FF, ao primeiro foco de configuração para um nó na árvore, JAWS entrará automaticamente no modo de formulários only if os links aninhados dentro dos itens da lista são definidos com role="presentation". Caso contrário, é necessário inserir manualmente o modo de formulários, acertando Enter no nó focado. Alternativamente, pode-se desligar o Cursor Virtual PC da JAWS. Usando aninhado span Em vez de links aninhados, evita esse problema.
NVDA e o exemplo C

O comportamento do NVDA no exemplo C é o mesmo que no exemplo A.

Window-Eyes e exemplo C

Window-Eyes' comportamento no exemplo C é o mesmo que no exemplo A.

VoiceOver e o exemplo C

O comportamento do VoiceOver no exemplo C é o mesmo que nos exemplos A e B.

Orca e o exemplo C

O comportamento da Orca no exemplo C é o mesmo que nos exemplos A e B, com uma grande exceção: uma vez que o foco é definido para um nó final que contém um link, o foco é definido como o próprio link. Nesse ponto, as teclas de seta moverão o foco do link para o link, mas não do nó para o nó, exigindo assim que os comandos de navegação Orca (Orca Modificador + teclas de seta) mudem de nó, enquanto as teclas de seta esquerda e direita continuam a expandir / colapso de nós com crianças. No entanto, configurando role="presentation" nos links aninhados resolve esse problema para a Orca. Isso não é um grande problema, já que os links não são focalizáveis de qualquer maneira porque estão configurados com tabindex="-1" para forçar o foco nos itens da lista, que atuam como os nós da árvore.

Exemplo D

Exemplo D é como o exemplo C, na medida em que os itens da lista são os itens da árvore, mas se afasta dos três exemplos anteriores em que ele usa aria-activedescendant. O foco não percorre os nós da árvore, mas permanece na própria árvore. Com foco na árvore, usando as teclas de seta atualiza a árvore aria-activedescendant valor para o id do nó selecionado, que está configurado com aria-selected="true". Pressionando Enter ou Space sets location ao href valor do link aninhado id é referenciado por aria-activedescendant.

Resultados do teste para o exemplo D
Comportamento do Leitor de Tela com Vista de Árvore Exemplo A
Screen Reader/Browser Inicia o modo de aplicação no foco Identifica a vista de árvore ou similar Identifica o estado Expandido / Recusado do Nó Indica o Nível de Filial do Nó Indica a posição do nó entre os nós de irmão Indica o Número de Crianças do Nó Expandido
JAWS no IE9/10 Sim Sim, mas apenas no modo Procurar Sim Sim Sim, mas apenas para nós colapsados ou finais Sim
JAWS no FF19 Sim, mas veja as notas Sim, mas apenas no modo Procurar Sim Sim Sim Não
NVDA no IE9/10 — veja as notas Sim, mas veja as notas Sim Sim Não Não Não
NVDA no FF19 Sim Sim Sim Sim Sim Não
Window-Eyes no IE10 Sim Sim Sim Sim Sim Não
Window-Eyes no FF19 Sim Sim Sim Sim Sim Não
VoiceOver no Safari 6.0.2 N/A Árvore identificada como uma tabela Sim mas veja as notas Sim Não Sim
Orca no FF19 N/A Sim Sim Sim Não Não

Notas de resultado para o exemplo D

JAWS e Exemplo D

O comportamento no exemplo D é o mesmo que no exemplo C: No FF, os links aninhados dentro dos nós da árvore do item da lista precisam role="presentation", senão JAWS não entra automaticamente no modo de formulários. No entanto, na FF, sem role="presentation" nos links, insira o modo de formulários. No entanto, na FF, sem Enter no nó atualmente selecionado serve apenas para alternar imediatamente o modo de formulários ativado e desativado novamente ao mesmo tempo. No entanto, desligar manualmente o Cursor Virtual PC do JAWS faz o trabalho para fornecer acesso à vista em árvore. Novamente, se aninhado spans are used instead of links, this is not an issue.

NVDA e Exemplo D
  • No IE9, o NVDA executa efetivamente o mesmo que nos exemplos A e C. No entanto, no IE10, a interação com este exemplo de vista de árvore parece um tanto quebrada. Isso parece ser um problema do IE10, conforme o NVDA executa conforme o esperado no IE9. Basicamente, no IE10, o NVDA não entra automaticamente no modo de aplicativo quando o foco é configurado para a árvore. Mesmo que se consegue entrar no modo de aplicação (pressionando Down arrow e depois Tab uma vez que o foco é configurado para o contêiner da árvore), o acesso total a cada nó na árvore não parece possível.
  • Em um teste rápido usando IE10 com uma variação no exemplo D sem links aninhados dentro dos itens da lista, como pode ser encontrado com Exemplo de exemplo de árvore ARIA de James Craig, Os resultados são muito parecidos: enquanto o exemplo de James usa role="application", o que automaticamente força o NVDA no modo de aplicação, permanece que nenhum dos nós é anunciado pelo NVDA, tornando a exibição de árvore efetivamente inutilizável.
  • No IE9, ao selecionar (aka configuração aria-activedescendant para o id de) um nó com filhos, NVDA lê todos os nós filhos, expandidos e visíveis ou não. Ele também faz isso neste exemplo sempre que se expande ou colapsa um nó. Configuração aria-labelledby ao id do texto do link aninhado resolve isso, embora isso cause sérios problemas com o VoiceOver. E mesmo assim, a criança lida com role="group" ainda é lido pelo NVDA quando um nó em um novo grupo de lista filho é selecionado. Se desejado, isso pode ser abordado pela configuração aria-labelledby na lista da criança ul, ou usando role="presentation" em vez de role="group".
  • Na FF, o comportamento do NVDA com o exemplo D é o mesmo que com os exemplos A, B e C.
Window-Eyes e Exemplo D

Window-Eyes' O comportamento no exemplo D é o mesmo que nos exemplos A e C.

VoiceOver e Exemplo D

  • Esse é o único exemplo em que o VoiceOver funciona com a visualização em árvore. Parece que, pelo menos por enquanto, o VoiceOver não suporta o roaming tabindex abordagem onde o foco realmente se move de um nó para outro, mas requer o uso de aria-activedescendant no recipiente da árvore para apontar para o nó atualmente selecionado.
  • Uma vez que o VoiceOver identifica a árvore como uma tabela, quando um nó selecionado com filhos é expandido / colapsado, o VoiceOver anuncia o número de linhas que foram adicionadas ou removidas e o número da linha do nó atualmente selecionado.
  • Quando o foco é definido pela primeira vez na vista em árvore, o VoiceOver não anuncia o rótulo do descendente atualmente ativo. Uma vez que o nó descendente ativo muda através das teclas de seta, no entanto, o VoiceOver anuncia seu rótulo. Desde a adicionando aria-labelledby para os nós causa problemas com o VoiceOver , não encontrei uma maneira de superar essa pequena limitação.
Orca e Exemplo D

O comportamento da Orca no exemplo D é o mesmo que nos exemplos A e B.

Reconhecimentos

Muito obrigado a James Craig para obter conselhos sobre as visualizações de árvores ARIA em geral e fornecer um exemplo que funcionou no Safari com o VoiceOver e para Todd Kloots para informações úteis e discussão, e teste o VoiceOver no Mac OS X Lion.


O conteúdo neste sítio de página é autorizado de acordo com uma Licença de Povo criativa Attribution-NonCommercial-ShareAlike 3.0