Técnicas para as WCAG 2.0

Ir para o conteúdo (Pressione a tecla Enter)

Técnicas de Scripting do lado do cliente para as WCAG 2.0

Esta página Web lista as Técnicas de Scripting do lado do cliente de Técnicas para as WCAG 2.0: Técnicas e Falhas para as Directrizes de Acessibilidade para o Conteúdo da Web 2.0. Para informação sobre as técnicas, consulte Introdução às Técnicas para as WCAG 2.0. Para uma lista das técnicas utilizadas em outras tecnologias, consulte o Índice.


Índice



SCR1: Permitir ao utilizador prolongar o limite de tempo predefinido

Aplicabilidade

Limites de tempo que são controlados por scripting do lado do cliente.

Esta falha está relacionada com:

Descrição

O objectivo desta técnica é permitir ao utilizador prolongar o limite de tempo predefinido, fornecendo um mecanismo para prolongar o tempo quando os scripts fornecerem a funcionalidade com limites de tempo predefinidos. Para permitir ao utilizador solicitar um limite de tempo mais alargado, o script pode fornecer um formulário (por exemplo), permitindo ao utilizador introduzir um limite de tempo prolongado, ou indicar que é necessário mais tempo. Caso seja utilizado para avisar o utilizador que um limite de tempo está prestes a expirar (consulte SCR16: Fornecer um script que avise o utilizador que um limite de tempo está prestes a expirar), este formulário pode ser disponibilizado numa caixa de diálogo de aviso. O utilizador pode prolongar o limite de tempo para, no mínimo, 10 vezes o limite de tempo predefinido, permitindo ao utilizador indicar o tempo adicional necessário ou permitindo, repetidamente, ao utilizador prolongar o limite de tempo.

Exemplos

  • Uma página Web contém estatísticas actuais do mercado de acções e está definida para actualização periódica. Quando o utilizador recebe um aviso antes da primeira actualização, é-lhe fornecida uma opção para prolongar o período de tempo entre actualizações.

  • Num jogo de xadrez online, um limite de tempo é atribuído a cada jogador para realizar cada jogada. Quando o jogador recebe um aviso de que o tempo está prestes a expirar para efectuar esta acção, é-lhe fornecida uma opção para aumentar o tempo.

Recursos

Testes

Procedimento

  1. Numa página Web que utilize scripts para fazer cumprir um limite de tempo, aguarde que o tempo limite expire.

  2. Determine se foi fornecida uma opção para prolongar o limite de tempo.

Resultados Esperados

  • O passo 2 é verdadeiro e é fornecido mais tempo para completar a interacção.


SCR2: Utilizar processadores de eventos redundantes de teclado e rato

Aplicabilidade

HTML e XHTML com suporte de scripting.

Esta técnica está relacionada com:

Descrição

O objectivo desta técnica é demonstrar, utilizando eventos independentes de dispositivos, como alterar uma imagem decorativa em resposta a um evento do rato ou do foco. Utilize os eventos onmouseover e onmouseout para alterar uma imagem decorativa quando o cursor do rato se move sobre um elemento, ou se afasta dele, na página. Além disso, utilize os eventos onfocus e onblur para alterar uma imagem decorativa quando o elemento recebe e perde o foco.

O exemplo seguinte tem uma imagem decorativa à frente de um elemento anchor. Quando o utilizador move o cursor do rato sobre a etiqueta anchor, a imagem decorativa à frente do “anchor” é alterada. Quando o cursor do rato se afasta do elemento anchor, a imagem volta à sua versão original. O mesmo efeito de alteração de imagem ocorre quando o utilizador fornece o foco do teclado ao elemento anchor. Ao receber o foco, a imagem altera-se, quando o foco é perdido a imagem volta à versão original. Isto é conseguido anexando processadores de evento onmouseover, onmouseout, onfocus e onblur ao elemento anchor. O processador de evento é uma função JavaScript designada por updateImage(), que altera o atributo src da imagem. O updateImage() é chamado em resposta aos eventos onmouseover, onmouseout, onfocus e onblur.

Cada imagem recebe um id exclusivo. Este id exclusivo é transmitido ao updateImage() juntamente com um valor booleano, que indica qual a imagem que vai ser utilizada: updateImage(imgId, isOver);. O valor booleano verdadeiro é transmitido quando o cursor do rato se encontra sobre o elemento anchor, ou quando este recebe o foco. Um valor falso é transmitido quando o cursor do rato é removido do elemento anchor, ou quando este perde o foco. A função updateImage() utiliza o id da imagem para carregar a imagem e, em seguida, altera o atributo src com base no valor booleano. É de salientar que, visto que a imagem tem uma finalidade decorativa, tem um atributo alt nulo.

Nota: Recomenda-se que utilize imagens que sejam semelhantes em tamanho e especifique os atributos height e width no elemento image. Isto impede quaisquer alterações ao esquema da página quando a imagem é actualizada. Este exemplo utiliza imagens que são idênticas em tamanho.

Exemplos

Exemplo 1

Código Exemplo:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"  "http://www.w3.org/TR/html4/loose.dtd">
 <html lang="en">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
 <title>Changing Image Source in a Device Independent Manner</title>
 <script type="text/javascript">
 /* This function will change the image src of an image element.
  * param imgId - the id of the image object to change
  * param isOver - true when mouse is over or object has focus,
  *                false when mouse move out or focus is lost
 */
 function updateImage(imgId, isOver) {
   var theImage = document.getElementById(imgId);
   if (theImage != null) { //could use a try/catch block for user agents supporting at least JavaScript 1.4
                           // These browsers support try/catch - NetScape 6, IE 5, Mozilla, Firefox
      if (isOver) {
        theImage.setAttribute("src","yellowplus.gif");
      }
      else {
        theImage.setAttribute("src","greyplus.gif");
      }
   }
 }
 </script>
 </head>
 <body>
 <p>Mouse over or tab to the links below and see the image change.</p>
 <a href="http://www.w3.org/wai" onmouseover="updateImage('wai', true);" onfocus="updateImage('wai', true);"
   onmouseout="updateImage('wai',false);" onblur="updateImage('wai',false);">
 <img src="greyplus.gif" border="0" alt="" id="wai">
   W3C Web Accessibility Initiative</a> &
 <a href="http://www.w3.org/International/" onmouseover="updateImage('i18n', true);" 
   onfocus="updateImage('i18n',true);" onmouseout="updateImage('i18n',false);"
   onblur="updateImage('i18n',false);">
   <img src="greyplus.gif" border="0" alt="" id="i18n">
   W3C Internationalization</a>
 </body>
 </html>

Testes

Procedimento

Carregue a página Web e teste os eventos utilizando o rato e o teclado.

  1. Verifique se a imagem "padrão" é apresentada como esperado quando a página Web é carregada.

  2. Utilizando o Rato

    1. Desloque o cursor do rato sobre o elemento que contém os processadores de eventos (neste exemplo, é um elemento anchor). Verifique se a imagem altera para a imagem esperada.

    2. Afaste o cursor do rato do elemento. Verifique se a imagem altera de novo para a imagem "padrão".

  3. Utilizando o Teclado

    1. Utilize o teclado para colocar o foco no elemento que contém os processadores de eventos. Verifique se a imagem altera para a imagem esperada.

    2. Utilize o teclado para remover o foco do elemento (normalmente, deslocando o foco para outro elemento). Verifique se a imagem altera para a imagem “padrão”.

  4. Verifique se a disposição dos outros elementos na página não é afectada quando a imagem é alterada.

Resultados Esperados

  • Todos os passos acima são verdadeiros.


SCR14: Utilizar scripts para tornar opcionais os alertas não essenciais

Aplicabilidade

Tecnologias de scripting que utilizem alertas de scripting para comunicação não urgente.

Esta técnica está relacionada com:

Descrição

O objectivo desta técnica é apresentar uma caixa de diálogo que contém uma mensagem (alerta) para o utilizador. Quando o alerta é apresentado, recebe o foco e o utilizador tem de activar o botão OK na caixa de diálogo para a fechar. Visto que estes alertas fazem com que o foco altere, podem distrair o utilizador, sobretudo quando utilizados para informação não urgente. Os alertas utilizados para fins não urgentes, tais como apresentar a citação do dia, sugestões de utilização úteis, ou a contagem decrescente para um evento em particular, não são apresentados, a não ser que o utilizador os active através de uma opção fornecida na página Web.

Esta técnica atribui uma variável JavaScript global para guardar as preferências do utilizador para apresentar alertas. O valor predefinido é falso. Uma função “wrapper” é criada para verificar o valor desta variável antes de apresentar o alerta. Todas as chamadas para apresentar um alerta são feitas a esta função wrapper, em vez de se chamar a função alert() directamente. No início da página, é fornecido um botão para que o utilizador active a apresentação de alertas na página. Esta técnica funciona numa base de visita-a-visita. Cada vez que uma página é carregada, os alertas são desactivados e o utilizador tem de os activar manualmente. Em alternativa, o autor pode utilizar cookies para guardar as preferências do utilizador em todas as sessões.

Exemplos

Exemplo 1

O script seguinte apresenta uma citação numa caixa de alerta, de dez em dez segundos, se o utilizador seleccionar o botão "Activar os Alertas". O utilizador pode desactivar as citações de novo seleccionado "Desactivar os Alertas".

Código Exemplo:

<script type="text/javascript">
var bDoAlerts = false;  // global variable which specifies whether to 
                                       // display alerts or not
/* function to enable/disable alerts.
 * param boolean bOn - true to enable alerts, false to disable them.
*/
function modifyAlerts(isEnabled) {
   bDoAlerts = isEnabled;
}
/* wrapper function for displaying alerts.  Checks the value of bDoAlerts
*and only calls the alert() function when bDoAlerts is true.
*/
function doAlert(aMessage) {
    if (bDoAlerts) {
       alert(aMessage);
    }
}
// example usage - a loop to display famous quotes.
var gCounter = -1;  // global to store counter
// quotes variable would be initialized with famous quotations
var quotes = new Array("quote 1", "quote 2", "quote 3", "quote 4", "quote 5");
function showQuotes() {
   if (++gCounter &gt;= quotes.length) {
     gCounter = 0;
   }
   doAlert(quotes[gCounter]);
   setTimeout("showQuotes();", 10000);
}
showQuotes();
</script>

No corpo de uma página, inclua uma forma de activar e desactivar os alertas. Este é um exemplo:

Código Exemplo:

<body>
<p>Press the button below to enable the display of famous quotes 
using an alert box<br />
<button id="enableBtn" type="button" onclick="modifyAlerts(true);">
Turn Alerts On</button><br />
<button id="disableBtn" type="button" onclick="modifyAlerts(false);">
Turn Alerts Off</button></p>

Este é um exemplo prático deste código: Demonstração de Alertas.

Testes

Procedimento

Para uma página Web que suporte interrupções não urgentes utilizando um alerta JavaScript:

  1. Carregue a página Web e verifique se os alertas não urgentes não são apresentados.

  2. Verifique se existe um mecanismo para activar os alertas não urgentes.

  3. Active os alertas não urgentes e verifique se estes são apresentados.

Resultados Esperados

  • Para uma página Web que suporte interrupções não urgentes utilizando um alerta JavaScript, os passos 1, 2 e 3 acima são verdadeiros.


SCR16: Fornecer um script que avise o utilizador que um limite de tempo está prestes a expirar

Aplicabilidade

Limites de tempo controlados por script.

Esta técnica está relacionada com:

Descrição

O objectivo desta técnica é notificar os utilizadores de que está prestes a terminar o tempo para completar uma interacção. Quando os scripts fornecem uma funcionalidade que tem limites de tempo, o script pode incluir uma funcionalidade para avisar o utilizador de que os limites de tempo estão iminentes e fornecer um mecanismo para solicitar mais tempo. No mínimo 20 segundos antes de ocorrer o limite de tempo, o script fornece uma caixa de diálogo de confirmação que indica que o limite de tempo está iminente, e pergunta ao utilizador se pretende mais tempo. Se a resposta do utilizador for "sim", o limite de tempo é redefinido. Se a resposta for "não", ou se o utilizador não responder, o limite de tempo expira.

Esta técnica envolve limites de tempo definidos através do método window.setTimeout() . Se, por exemplo, o limite de tempo for definido para expirar em 60 segundos, pode definir o limite de tempo para 40 segundos e fornecer a caixa de diálogo de confirmação. Quando a caixa de diálogo de confirmação surge, um novo limite de tempo é definido para os restantes 20 segundos. Ao expirar o "limite do período de tolerância”, é executada a acção que deveria ter sido executada no final do limite de tempo de 60 segundos.

Exemplos

Exemplo 1

Uma página com as cotações da Bolsa utiliza o script para actualizar a página a cada 5 minutos, para garantir que as estatísticas mais recentes permaneçam disponíveis. Vinte segundos antes de o período de cinco minutos expirar, surge uma caixa de diálogo de confirmação a perguntar se o utilizador necessita de mais tempo antes de a página actualizar. Isto permite ao utilizador ter conhecimento da actualização iminente e, se assim o pretender, evitá-la.

Código Exemplo:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"<url>http://www.w3.org/TR/html4/loose.dtd">http://www.w3.org/TR/html4/loose.dtd</title>">
<html lang="en">
<head>
<title>Stock Market Quotes</title>
<script type="text/javascript">
<!--
function timeControl() {
	// set timer for 4 min 40 sec, then ask user to confirm.
	setTimeout('userCheck()', 280000);
}
function userCheck() {
	// set page refresh for 20 sec
	var id=setTimeout('pageReload()', 20000);
	// If user selects "OK" the timer is reset 
	// else the page will refresh from the server.
	if (confirm("This page is set to refresh in 20 seconds. 
	Would you like more time?"))
	{
	clearTimeout(id);
	timeControl();
	}
}
function pageReload() {
	window.location.reload(true);
}
timeControl();
-->
</script>
</head>
<body>
<h1>Stock Market Quotes</h1>
 ...etc...
</body>
</html>

Testes

Procedimento

Numa página Web que tenha um limite de tempo controlado por um script:

  1. Carregue a página e programe um temporizador com 20 segundos a menos que o limite de tempo.

  2. Quando o temporizador parar, verifique se é apresentada uma caixa de diálogo de confirmação a avisar que o limite de tempo está prestes a expirar.

Resultados Esperados

  • O passo 2 é verdadeiro.


SCR18: Fornecer validação e alertas do lado do cliente

Aplicabilidade

Conteúdo que valida a entrada de dados por parte do utilizador.

Esta técnica está relacionada com:

Descrição

O objectivo desta técnica é validar a entrada de dados por parte do utilizador à medida que os valores são introduzidos em cada campo, através de scripting do lado do cliente. Se forem encontrados erros, uma caixa de diálogo de alerta descreve a natureza do erro no texto. Assim que o utilizador fechar a caixa de diálogo de alerta, é útil se o script colocar o foco do teclado no campo no qual ocorreu o erro.

Exemplos

Exemplo 1

O script seguinte verifica se uma data válida foi introduzida no controlo do formulário.

Código Exemplo:

<label for="date">Date:</label>
<input type="text" name="date" id="date" 
onchange="if(isNaN(Date.parse(this.value))) 
alert('This control is not a valid date. 
Please re-enter the value.');" />

Testes

Procedimento

Para campos de formulário que requeiram entrada de dados específica:

  1. Introduza dados inválidos.

  2. Verifique se é fornecido um alerta a descrever o erro.

Resultados Esperados

  • O passo 2 é verdadeiro.


SCR19: Utilizar um evento onchange num elemento select sem provocar uma alteração de contexto

Aplicabilidade

HTML e XHTML com suporte para scripting. Esta técnica utiliza a estrutura try/catch do JavaScript 1.4.

Esta técnica está relacionada com:

Notas de Apoio para o Agente de Utilizador e para a Tecnologia de Apoio

Esta técnica foi testada no Windows XP utilizando JAWS 7.0 e WindowEyes 5.5, tanto com Firefox 1.5 como IE 6. Note que o JavaScript tem de estar activado no browser.

Descrição

O objectivo desta técnica é demonstrar como utilizar correctamente um evento onchange com um elemento select para actualizar outros elementos na página Web. Esta técnica não provoca uma alteração de contexto. Quando existe um ou mais elementos select na página Web, um evento onchange numa das páginas pode actualizar as opções noutro elemento select na página Web. Todos os dados requeridos pelos elementos select são incluídos na página Web.

É importante salientar que o item de selecção que é modificado surge após o elemento select accionador na ordem de leitura da página Web. Isto garante que as tecnologias de apoio reconhecem a alteração e os utilizadores encontram os novos dados quando o elemento modificado recebe o foco. Esta técnica depende do suporte JavaScript no agente de utilizador.

Exemplos

Exemplo 1

Este exemplo contém dois elementos select. Quando um item é seleccionado no primeiro elemento select, as escolhas no outro elemento select são actualizadas apropriadamente. O primeiro elemento select contém uma lista de continentes. O segundo elemento select contém uma lista parcial de países localizados no continente seleccionado. Existe um evento onchange associado ao elemento select do continente. Quando a selecção de continente é alterada, os itens no elemento select do país são modificados utilizando JavaScript através do Modelo de Objecto de Documento (DOM). Todos os dados necessários, a lista de países e de continentes, são incluídos na página Web.

Desrição geral do código:

  • Variável de matriz countryLists que contém a lista dos países para cada continente no elemento select accionador.

  • Função countryChange() que é invocada pelo evento onchange do elemento select de continente.

  • O código XHTML para criar os elementos select no corpo da página Web.

Código Exemplo:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 
  <head> 
    <meta http-equiv="content-type" content="text/xhtml; charset=utf-8" /> 
    <title>Dynamic Select Statements</title> 
<script type="text/javascript">
 //<![CDATA[ 
 // array of possible countries in the same order as they appear in the country selection list 
 var countryLists = new Array(4) 
 countryLists["empty"] = ["Select a Country"]; 
 countryLists["North America"] = ["Canada", "United States", "Mexico"]; 
 countryLists["South America"] = ["Brazil", "Argentina", "Chile", "Ecuador"]; 
 countryLists["Asia"] = ["Russia", "China", "Japan"]; 
 countryLists["Europe"]= ["Britain", "France", "Spain", "Germany"]; 
 /* CountryChange() is called from the onchange event of a select element. 
 * param selectObj - the select object which fired the on change event. 
 */ 
 function countryChange(selectObj) { 
 // get the index of the selected option 
 var idx = selectObj.selectedIndex; 
 // get the value of the selected option 
 var which = selectObj.options[idx].value; 
 // use the selected option value to retrieve the list of items from the countryLists array 
 cList = countryLists[which]; 
 // get the country select element via its known id 
 var cSelect = document.getElementById("country"); 
 // remove the current options from the country select 
 var len=cSelect.options.length; 
 while (cSelect.options.length > 0) { 
 cSelect.remove(0); 
 } 
 var newOption; 
 // create new options 
 for (var i=0; i<cList.length; i++) { 
 newOption = document.createElement("option"); 
 newOption.value = cList[i];  // assumes option string and value are the same 
 newOption.text=cList[i]; 
 // add the new option 
 try { 
 cSelect.add(newOption);  // this will fail in DOM browsers but is needed for IE 
 } 
 catch (e) { 
 cSelect.appendChild(newOption); 
 } 
 } 
 } 
//>>
</script>
</head>
<body>
  <noscript>This page requires JavaScript be available and enabled to function properly</noscript>
  <h1>Dynamic Select Statements</h1>
  <label for="continent">Select Continent</label>
  <select id="continent" onchange="countryChange(this);">
    <option value="empty">Select a Continent</option>
    <option value="North America">North America</option>
    <option value="South America">South America</option>
    <option value="Asia">Asia</option>
    <option value="Europe">Europe</option>
  </select>
  <br/>
  <label for="country">Select a country</label>
  <select id="country">
    <option value="0">Select a country</option>
  </select>
</body>
 </html>

Este é um exemplo prático: Selecção Dinâmica

Recursos

Os recursos são indicados apenas a título informativo, não implica que tenham sido aprovados.

(actualmente, não existe nenhuma indicada)

Testes

Procedimento

  1. Navegue até ao elemento trigger accionador (neste exemplo, é o utilizado para seleccionar os continentes) e altere o valor do elemento select.

  2. Navegue até ao elemento select que é actualizado pelo accionador (neste exemplo, é o utilizado para seleccionar os países).

  3. Verifique se os valores de opção equivalentes são apresentados no outro elemento select.

  4. Navegue até ao o elemento select accionador, navegue nas opções, mas não altere o valor.

  5. Verifique se os valores de opção equivalentes ainda são apresentados no elemento associado.

Recomendamos que os elementos select sejam testados com uma tecnologia de apoio para verificar se as alterações ao elemento associado são reconhecidas.

Resultados Esperados

  • Os passos 3 e 5 são verdadeiros.


SCR20: Utilizar o teclado e outras funções específicas do dispositivo

Aplicabilidade

Aplica-se a todos os conteúdos que utilizem Script para implementar funcionalidades.

Esta técnica está relacionada com:

Descrição

O objectivo desta técnica é ilustrar a utilização de eventos específicos de teclado e de rato com um código que tenha uma função de scripting associada a um evento. Utilizar os eventos específicos de teclado e de rato em conjunto garante que o conteúdo pode ser utilizado por vários dispositivos. Por exemplo, um script pode desempenhar a mesma acção quando é detectado um "keypress" ao clicar num botão do rato. Esta técnica excede os requisitos do Critério de Sucesso em relação ao acesso por teclado ao incluir não só o acesso por teclado como através de outros dispositivos.

Em JavaScript, os processadores de eventos mais utilizados são o onblur, onchange, onclick, ondblclick, onfocus, onkeydown, onkeypress, onkeyup, onload, onmousedown, onmousemove, onmouseout, onmouseover, onmouseup, onreset, onselect, onsubmit, onunload. Algumas funções específicas do rato têm uma função específica do teclado correspondente lógica (tais como 'onmouseover' e 'onfocus'). O processador de eventos do teclado tem de ser fornecido para executar a mesma função que o processador de eventos do rato.

A tabela seguinte sugere processadores de eventos do teclado para fazer corresponder aos processadores de eventos do rato.

Correspondências de Processadores de Dispositivos
Utilize... ...com
mousedown keydown
mouseup keyup
click [1] keypress [2]
mouseover focus
mouseout blur

1 Embora click seja, em princípio, um processador de eventos do rato, a maioria dos agentes de utilizador HTML e XHTML processam este evento quando o controlo é activado, independentemente de este ter sido activado pelo rato ou pelo teclado. Na prática, não é necessário duplicar este evento. É incluído aqui por uma questão de organização, visto que os agentes de utilizador que não são em HTML apresentam esta função.

2 Visto que o processador de eventos keypress reage a qualquer tecla, deve primeiro efectuar uma verificação para garantir que a tecla Enter foi pressionada antes de processar o evento. Caso contrário, o processador de eventos é executado sempre que o utilizador pressiona qualquer tecla, até mesmo a tecla de tabulação, para sair do controlo, e isto não é normalmente desejável.

Algumas funções específicas do rato (tais como dblclick e mousemove) não têm uma função específica do teclado correspondente. Isto significa que algumas funções podem ter de ser implementadas de modo diferente para cada dispositivo (por exemplo, incluir vários botões para executar, através do teclado, as funções específicas do rato equivalentes implementadas).

Exemplos

Exemplo 1

Neste exemplo de um link de imagem, a imagem é alterada quando o utilizador coloca o ponteiro sobre a imagem. Para fornecer aos utilizadores de teclado uma experiência semelhante, a imagem é também alterada quando o utilizador utiliza a tabulação para aceder à imagem.

Código Exemplo:

<a href="menu.php" onmouseover="swapImageOn('menu')" onfocus="swapImageOn('menu')" 
onmouseout="swapImageOff('menu')" onblur="swapImageOff('menu')"> 
<img id="menu" src="menu_off.gif" alt="Menu" /> 
</a>

Exemplo 2

Este exemplo apresenta uma imagem para a qual o teclado pode ser utilizado para activar a função. O evento do rato onclick é duplicado por um evento do teclado onkeypressapropriado. O atributo tabindex garante que o teclado tem uma paragem de tabulação na imagem. Note que, neste exemplo, a função nextPage() deve verificar se a tecla pressionada foi a tecla Enter, caso contrário responde a todas as acções do teclado enquanto a imagem receber o foco, o que não é o comportamento pretendido.

Código Exemplo:

<img onclick="nextPage();" onkeypress="nextPage();" tabindex="0" src="arrow.gif" 
alt="Go to next page"> 

Nota: Este exemplo utiliza tabindex num elemento img . Apesar de isto ser actualmente inválido, é fornecido como técnica de transição para fazer com esta funcionalidade fique operacional.

Recursos

Os recursos são indicados apenas a título informativo, não implica que tenham sido aprovados.

Testes

Procedimento

  1. Localize todas as funcionalidades interactivas.

  2. Verifique se todas as funcionalidades interactivas podem ser acedidas utilizando apenas o teclado.

Resultados Esperados

  • O passo 2 é verdadeiro.


SCR21: Utilizar funções do Modelo de Objecto de Documento (DOM) para adicionar conteúdo a uma página

Aplicabilidade

ECMAScript utilizado em HTML e XHTML.

Esta técnica está relacionada com:

Notas de Apoio para o Agente de Utilizador e para a Tecnologia de Apoio

Este exemplo foi testado com êxito no Windows XP com IE 6 e Firefox 1.5.0.1, utilizando JAWS 7 e WindowEyes 5.5. Note que, ao adicionar novos conteúdos a uma página, os leitores de ecrã podem não ler automaticamente o novo conteúdo. Para garantir que o novo conteúdo é lido, coloque o foco no novo elemento, ou certifique-se de que o foco é colocado sob o local actual e de que será encontrado quando o utilizador continuar a percorrer a página.

Descrição

O objectivo desta técnica é demonstrar como utilizar as funções do Modelo de Objecto de Documento (DOM) para adicionar conteúdos a uma página, em vez de utilizar document.write ou object.innerHTML. O método document.write() não funciona com XHTML quando é fornecido com o tipo de MIME correcto (application/xhtml+xml) e a propriedade innerHTML não fizer parte da especificação do DOM. Por isso, deve ser evitado. Se as funções do DOM forem utilizadas para adicionar o conteúdo, os agentes de utilizador podem aceder ao DOM para recuperar o conteúdo. A função createElement() pode ser utilizada para criar elementos no DOM. A função createTextNode() é utilizada para criar texto associado aos elementos. As funções appendChild(), removeChild(), insertBefore() e replaceChild() são utilizadas para adicionar e remover elementos e nós. As outras funções do DOM são utilizadas para atribuir atributos aos elementos criados.

Nota: Ao adicionar elementos que podem receber o foco no documento, não adicione atributos tabindex para definir, de forma explícita, a ordem de tabulação, visto que isto pode causar problemas quando se adiciona elementos que podem receber o foco no meio de um documento. Permita que a ordem de tabulação predefinida seja atribuída ao novo elemento, não definindo um atributo tabindex de forma explícita.

Exemplos

Exemplo 1

Este exemplo demonstra a utilização de scripting do lado do cliente para validar um formulário. Se forem encontrados erros, as mensagens de erro apropriadas são apresentadas. O exemplo utiliza as funções do DOM para adicionar a notificação de erro, que consiste num título, num parágrafo curto a explicar que ocorreu um erro e numa lista de erros ordenada. O conteúdo do título apresenta-se como um link, para que possa ser utilizado para chamar a atenção do utilizador para o erro, utilizando o método do foco. Cada item na lista está escrito também como um link que coloca o foco no campo do formulário com erro quando se segue um link.

Por uma questão de simplicidade, o exemplo valida apenas dois campos de texto, mas pode facilmente ser alargado para se tornar num processsador de formulário genérico. A validação do lado do cliente não deve ser o único meio de validação, e deve ser apoiada pela validação do lado do servidor. As vantagens da validação do lado do cliente são que pode fornecer feedback imediato ao utilizador para que este não tenha de esperar que os erros sejam devolvidos pelo servidor, ajudando a reduzir tráfego desnecessário no servidor.

Este é o script que adiciona os processadores de eventos ao formulário. Se o scripting estiver desactivado, a função validateNumbers() é invocada para executar a validação do lado do cliente antes de o formulário ser submetido ao servidor. Se o não estiver desactivado, o formulário é submetido de imediato ao servidor e a validação também deve ser implementada no servidor.

Código Exemplo:

window.onload = initialise;
function initialise()
{
  // Ensure we're working with a relatively standards compliant user agent
  if (!document.getElementById || !document.createElement || !document.createTextNode)
    return;

  // Add an event handler for the number form
  var objForm = document.getElementById('numberform');
  objForm.onsubmit= function(){return validateNumbers(this);};
}

Esta é a função de validação. Note a utilização das funções do DOM createElement(), createTextNode() e appendChild() para criar os elementos de mensagem de erro.

Código Exemplo:

function validateNumbers(objForm)
{
  // Test whether fields are valid
  var bFirst = isNumber(document.getElementById('num1').value);
  var bSecond = isNumber(document.getElementById('num2').value);
  // If not valid, display errors
  if (!bFirst || !bSecond)
  {
    var objExisting = document.getElementById('validationerrors');
    var objNew = document.createElement('div');
    var objTitle = document.createElement('h2');
    var objParagraph = document.createElement('p');
    var objList = document.createElement('ol');
    var objAnchor = document.createElement('a');
    var strID = 'firsterror';
    var strError;
    // The heading element will contain a link so that screen readers
    // can use it to place focus - the destination for the link is 
    // the first error contained in a list
    objAnchor.appendChild(document.createTextNode('Errors in Submission'));
    objAnchor.setAttribute('href', '#firsterror');
    objTitle.appendChild(objAnchor);
    objParagraph.appendChild(document.createTextNode('Please review the following'));
    objNew.setAttribute('id', 'validationerrors');
    objNew.appendChild(objTitle);
    objNew.appendChild(objParagraph);
    // Add each error found to the list of errors
    if (!bFirst)
    {
      strError = 'Please provide a numeric value for the first number';
      objList.appendChild(addError(strError, '#num1', objForm, strID));
      strID = '';
    }
    if (!bSecond)
    {
      strError = 'Please provide a numeric value for the second number';
      objList.appendChild(addError(strError, '#num2', objForm, strID));
      strID = '';
    }
    // Add the list to the error information
    objNew.appendChild(objList);
    // If there were existing errors, replace them with the new lot,
    // otherwise add the new errors to the start of the form
    if (objExisting)
      objExisting.parentNode.replaceChild(objNew, objExisting);
    else
    {
      var objPosition = objForm.firstChild;
      objForm.insertBefore(objNew, objPosition);
    }
    // Place focus on the anchor in the heading to alert
    // screen readers that the submission is in error
    objAnchor.focus();
    // Do not submit the form
    objForm.submitAllowed = false;
    return false;
  }
  return true;
}

// Function to validate a number
function isNumber(strValue)
{
  return (!isNaN(strValue) && strValue.replace(/^\s+|\s+$/, '') !== '');
} 

Em seguida, estão as funções de ajuda para criar a mensagem de erro e para colocar o foco no campo de formulário associado.

Código Exemplo:

// Function to create a list item containing a link describing the error
// that points to the appropriate form field
function addError(strError, strFragment, objForm, strID)
{
  var objAnchor = document.createElement('a');
  var objListItem = document.createElement('li');
  objAnchor.appendChild(document.createTextNode(strError));
  objAnchor.setAttribute('href', strFragment);
  objAnchor.onclick = function(event){return focusFormField(this, event, objForm);};
  objAnchor.onkeypress = function(event){return focusFormField(this, event, objForm);};
  // If strID has a value, this is the first error in the list
  if (strID.length > 0)
    objAnchor.setAttribute('id', strID);
  objListItem.appendChild(objAnchor);
  return objListItem;
}

// Function to place focus to the form field in error
function focusFormField(objAnchor, objEvent, objForm)
{
  // Allow keyboard navigation over links
  if (objEvent && objEvent.type == 'keypress')
    if (objEvent.keyCode != 13 && objEvent.keyCode != 32)
      return true;
  // set focus to the form control
  var strFormField = objAnchor.href.match(/[^#]\w*$/);
  objForm[strFormField].focus();
  return false;
}

Este é o HTML para o formulário de exemplo.

Código Exemplo:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
	<title>ECMAScript Form Validation</title>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<script type="text/javascript" src="validate.js"></script>
</head>
<body>
<h1>Form Validation</h1>
<form id="numberform" method="post" action="form.php">
<fieldset>
<legend>Numeric Fields</legend>
<p>
<label for="num1">Enter first number</label>
<input type="text" size="20" name="num1" id="num1">
</p>
<p>
<label for="num2">Enter second number</label>
<input type="text" size="20" name="num2" id="num2">
</p>
</fieldset>
<p>
<input type="submit" name="submit" value="Submit Form">
</p>
</form>
</body>
</html>

Este exemplo limita-se ao scripting do lado do cliente e deve ser suportado através da validação do lado do cliente. Este exemplo limita-se à criação de mensagens de erro quando o scripting do lado do cliente está disponível.

Este é um link para um exemplo prático: Validação de Formulário

Recursos

Os recursos são indicados apenas a título informativo, não implica que tenham sido aprovados.

(actualmente, não existe nenhuma indicada)

Testes

Procedimento

Para as páginas que criam um novo conteúdo de forma dinâmica:

  1. Verifique o código fonte e se o novo conteúdo não foi criado utilizando document.write(), innerHTML, outerHTML, innerText ou outerText.

Resultados Esperados

  • O passo 1 é verdadeiro.


SCR22: Utilizar scripts para controlar o modo intermitente e pará-lo em cinco segundos ou menos

Aplicabilidade

Tecnologias que suportem o modo intermitente do conteúdo controlado por script.

Esta técnica está relacionada com:

Descrição

O objectivo desta técnica é controlar o modo intermitente através do script para que possa ser definido para parar em menos de cinco segundos pelo script. O script é utilizado para iniciar o efeito intermitente do conteúdo, controlar a possibilidade de alternar entre estados visíveis e ocultos e também parar o efeito em cinco segundos ou menos. A função setTimeout() pode ser utilizada para alternar o conteúdo intermitente entre estados visíveis e ocultos e parar quando o número de iterações entre eles totalizar quase cinco segundos.

Exemplos

Exemplo 1

Este exemplo utiliza JavaScript para controlar o modo intermitente de alguns conteúdos HTML e XHTML. O JavaScript cria o efeito intermitente alterando o estado de visibilidade do conteúdo. Controla o início do efeito e pára-o em cinco segundos.

Código Exemplo:

...
<div id="blink1" class="highlight">New item!</div>
<script type="text/javascript">
<!--
// blink "on" state
function show()
{
	if (document.getElementById)
	document.getElementById("blink1").style.visibility = "visible";
}
// blink "off" state
function hide()
{
	if (document.getElementById)
	document.getElementById("blink1").style.visibility = "hidden";
}
// toggle "on" and "off" states every 450 ms to achieve a blink effect
// end after 4500 ms (less than five seconds)
for(var i=900; i < 4500; i=i+900)
{
	setTimeout("hide()",i);
	setTimeout("show()",i+450);
}
-->
</script>
 ... 

Este é um exemplo prático deste código: Utilizar script para controlar o modo intermitente.

Testes

Procedimento

Para cada ocorrência de conteúdo em modo intermitente:

  1. Programe o temporizador para 5 segundos no início do efeito intermitente.

  2. Quando o temporizador parar, verifique se o efeito intermitente parou.

Resultados Esperados

  • Para cada ocorrência do conteúdo em modo intermitente, o passo 2 é verdadeiro.


SCR24: Utilizar a optimização progressiva para abrir novas janelas a pedido do utilizador

Aplicabilidade

HTML 4.01 e XHTML 1.0.

Esta técnica está relacionada com:

Descrição

O objectivo desta técnica é evitar a confusão que pode ser causada pelo aparecimento de novas janelas que não foram solicitadas pelo utilizador. A abertura repentina de novas janelas pode desorientar ou não ser percebida totalmente por alguns utilizadores. Se o tipo de documento não permitir o atributo target (não existe em HTML 4.01 Strict nem em XHTML 1.0 Strict), ou se o programador preferir não o utilizar, as novas janelas podem ser abertas com ECMAScript. O exemplo seguinte demonstra como abrir novas janelas com script: adiciona um processador de eventos a um link (elementoa ) e avisa o utilizador que o conteúdo vai abrir uma nova janela.

Exemplos

Exemplo 1:

Marcação:

O script está incluído no cabeçalho do documento e o link dispõe de um id que pode ser utilizado como hook pelo script.

Código Exemplo:

<script type="text/javascript" src="popup.js"></script>
…
<a href="help.html" id="newwin">Show Help</a

Script:

Código Exemplo:

      
// Use traditional event model whilst support for event registration
// amongst browsers is poor.
window.onload = addHandlers;

function addHandlers()
{
  var objAnchor = document.getElementById('newwin');

  if (objAnchor)
  {
    objAnchor.firstChild.data = objAnchor.firstChild.data + ' (opens in a new window)';
    objAnchor.onclick = function(event){return launchWindow(this, event);}
    // UAAG requires that user agents handle events in a device-independent manner
    // but only some browsers do this, so add keyboard event to be sure
    objAnchor.onkeypress = function(event){return launchWindow(this, event);}
  }
}

function launchWindow(objAnchor, objEvent)
{
  var iKeyCode, bSuccess=false;

  // If the event is from a keyboard, we only want to open the
  // new window if the user requested the link (return or space)
  if (objEvent && objEvent.type == 'keypress')
  {
    if (objEvent.keyCode)
      iKeyCode = objEvent.keyCode;
    else if (objEvent.which)
      iKeyCode = objEvent.which;

    // If not carriage return or space, return true so that the user agent
    // continues to process the action
    if (iKeyCode != 13 && iKeyCode != 32)
      return true;
  }

  bSuccess = window.open(objAnchor.href);

  // If the window did not open, allow the browser to continue the default
  // action of opening in the same window
  if (!bSuccess)
    return true;

  // The window was opened, so stop the browser processing further
  return false;
}

Recursos

Os recursos são indicados apenas a título informativo, não implica que tenham sido aprovados.

Testes

Procedimento

  1. Active cada link no documento para verificar se abre uma nova janela.

  2. Para cada link que abra uma nova janela, verifique se utiliza script para realizar as seguintes tarefas:

    1. indicar se o link abre numa nova janela,

    2. utilizar processadores de eventos independentes do dispositivo, e

    3. permitir que o browser abra o conteúdo na mesma janela se uma nova janela não for aberta.

Resultados Esperados

  • O passo 2 é verdadeiro.


SCR26: Introduzir conteúdo dinâmico no Modelo de Objecto de Documento imediatamente a seguir ao elemento accionador

Aplicabilidade

HTML e XHTML, script.

Esta técnica está relacionada com:

Descrição

O objectivo desta técnica é colocar elementos da interface de utilizador inseridos no Modelo de Objecto de Documento (DOM), de modo a que a ordem de tabulação e a ordem de leitura do leitor de ecrã sejam definidas correctamente pelo comportamento predefinido do agente de utilizador. Esta técnica pode ser utilizada para qualquer elemento da interface de utilizador que esteja oculto ou visível, tais como menus e caixas de diálogo.

A ordem de leitura num leitor de ecrã baseia-se na ordem dos elementos HTML ou XHTML no Modelo de Objecto de Documento, tal como a ordem de tabulação predefinida. Esta técnica introduz um novo conteúdo no DOM imediatamente a seguir ao elemento que foi activado para accionar o script. O elemento accionador tem de ser um link ou um botão, e o script tem de ser invocado a partir do seu evento onclick. Estes elementos podem receber o foco de forma nativa e o seu evento onclick é independente do dispositivo. O foco permanece no elemento activado e o novo conteúdo, introduzido após o mesmo, surge imediatamente a seguir na ordem de tabulação e na ordem de leitura do leitor de ecrã.

Note que esta técnica funciona para actualizações síncronas. Para actualizações assíncronas (por vezes chamadas AJAX), é necessária uma técnica adicional para informar a tecnologia de apoio que o conteúdo assíncrono foi introduzido.

Exemplos

Exemplo1

Este exemplo cria um menu quando se clica num link, e coloca-o após o link. O evento onclick do link é utilizado para invocar o script ShowHide, apresentando um ID para o novo menu como parâmetro.

Código Exemplo:

<a href="#" onclick="ShowHide('foo',this)">Toggle</a>

O script ShowHide cria um div que contém o novo menu e introduz-lhe um link. A última linha representa o núcleo do script. Localiza o objecto principal do elemento que accionou o script e anexa o div criado por este como um novo objecto subordinado ao elemento principal. Isto faz com que o novo div surja no DOM após o link. Quando o utilizador pressiona a tecla de tabulação, o foco desloca-se para o primeiro item que pode receber o foco no menu, ou seja, o link criado.

Código Exemplo:

function ShowHide(id,src)
{
	var el = document.getElementById(id);
	if (!el)
	{
		el = document.createElement("div");
		el.id = id;
		var link = document.createElement("a");
		link.href = "javascript:void(0)";
		link.appendChild(document.createTextNode("Content"));
		el.appendChild(link);
		src.parentElement.appendChild(el);
	}
	else
	{
		el.style.display = ('none' == el.style.display ? 'block' : 'none');
	}
}

O CSS é utilizado para fazer com que o div e o link se assemelhem a um menu.

Testes

Procedimento

  1. Localize todas as áreas da página que accionem caixas de diálogo que não sejam janelas de pop-up.

  2. Verifique se as caixas de diálogo são accionadas a partir do evento click de um botão ou a partir de um link.

  3. Utilizando uma ferramenta que permita inspeccionar o DOM gerado pelo script, verifique se a caixa de diálogo surge em seguida no DOM.

Resultados Esperados

  • Os passos 2 e 3 são verdadeiros.


SCR27: Reordenar as secções da página utilizando o Modelo de Objecto de Documento

Aplicabilidade

HTML e XHTML, script.

Esta técnica está relacionada com:

Descrição

O objectivo desta técnica é fornecer um mecanismo para reordenar o componente que é altamente utilizável e acessível. Os dois mecanismos mais comuns para reordenar servem para remeter os utilizadores para uma página de configuração, onde podem numerar os componentes, ou permitir aos utilizadores arrastar e largar os componentes no local pretendido. O método arrastar e largar é muito mais utilizável, visto que o utilizador pode organizar os itens no seu lugar, um de cada vez, e ter uma noção do resultado. Infelizmente, a funcionalidade arrastar e largar depende da utilização de um rato. Esta técnica permite aos utilizadores interagir com um menu nos componentes, para ordenar a sua localização de uma forma independente do dispositivo. Pode ser utilizada em vez de, ou em conjunto com, a funcionalidade arrastar e alargar, utilizada para reordenar o conteúdo.

O menu é uma lista de links que utiliza o evento onclick independente do dispositivo para accionar os scripts que reordenam o conteúdo. O conteúdo é reordenado no Modelo de Objecto de Documento (DOM), não apenas visualmente, para que fique na ordem correcta para todos os dispositivos.

Exemplos

Exemplo 1

Este exemplo apresenta a reordenação para cima e para baixo. Esta abordagem pode também ser utilizada para reordenar em duas dimensões, adicionando opções para a esquerda e para a direita.

Os componentes neste exemplo são itens de lista não ordenados. As listas não ordenadas são um modelo semântico muito bom para conjuntos de itens semelhantes, tal como estes componentes. A abordagem do menu pode também ser utilizada para outros tipos de agrupamentos.

Os módulos são itens de lista e cada módulo, para além do conteúdo em elementos div, dispõe de um menu representado como lista encaixada.

Código Exemplo:

<ul id="swapper">
    <li id="black">
        <div class="module">
            <div class="module_header">
                <!-- menu link -->
                <a href="#" onclick="ToggleMenu(event);">menu</a>
                <!-- menu -->
                <ul class="menu">
                    <li><a href="#" onclick="OnMenuClick(event)" 
                        onkeypress="OnMenuKeypress(event);">up</a></li>
                    <li><a href="#" onclick="OnMenuClick(event)" 
                        onkeypress="OnMenuKeypress(event);">down</a></li>
                </ul>
            </div>
            <div class="module_body">
                Text in the black module
            </div>
        </div>
    </li>
    ...
</ul>

Visto termos abordado a apresentação e ocultação de menus nas amostras em árvore simples, focamos aqui apenas o código que troca os módulos. Depois de harmonizar os eventos e cancelar a acção do link predefinida, iniciamos o trabalho. Em primeiro lugar, definimos um conjunto de variáveis locais para os elementos com os quais vamos trabalhar: o menu, o módulo a ser reordenado e o menuLink. Em seguida, depois de verificar a direcção da reordenação, tentamos encontrar o nó para efectuar a troca. Se encontrarmos um, invocamos swapNode() para trocar os nossos dois módulos e PositionElement() para mover o menu absolutamente posicionado juntamente com o módulo e, em seguida, colocamos o foco de novo no item de menu que deu início a toda a acção.

Código Exemplo:

function MoveNode(evt,dir)
{
    HarmonizeEvent(evt);
    evt.preventDefault();

    var src = evt.target;
    var menu = src.parentNode.parentNode;
    var module = menu.parentNode.parentNode.parentNode;
    var menuLink = module.getElementsByTagName("a")[0];
    var swap = null;
    
    switch(dir)
    {
        case 'up':
        {
            swap = module.previousSibling;
            while (swap && swap.nodeType != 1)
            {
                swap = swap.previousSibling;
            }
            break;
        }
        case 'down':
        {
            swap = module.nextSibling;
            while (swap && swap.nodeType != 1)
            {
                swap = swap.nextSibling;
            }
            break;
        }
    }
    if (swap && swap.tagName == node.tagName)
    {
        module.swapNode(swap);
        PositionElement(menu,menuLink,false,true);
    }
    src.focus();
}

O CSS utilizado para a troca de nó não é muito diferente do utilizado para as amostras em árvore anteriores, apresentando alguns ajustes em termos de tamanho e de cor nos módulos e no menu pequeno.

Código Exemplo:

ul#swapper { margin:0px; padding:0px; list-item-style:none; }
ul#swapper li { padding:0; margin:1em; list-style:none; height:5em; width:15em; 
    border:1px solid black; }
ul#swapper li a { color:white; text-decoration:none; font-size:90%; }

ul#swapper li div.module_header { text-align:right; padding:0 0.2em; }
ul#swapper li div.module_body { padding:0.2em; }

ul#swapper ul.menu { padding:0; margin:0; list-style:none; background-color:#eeeeee; 
    height:auto; position:absolute; text-align:left; border:1px solid gray; display:none; }
ul#swapper ul.menu li { height:auto; border:none; margin:0; text-align:left; 
    font-weight:normal; width:5em; }
ul#swapper ul.menu li a { text-decoration:none; color:black; padding:0 0.1em; 
    display:block; width:100%; }

Testes

Procedimento

  1. Localize todos os componentes na Unidade da Web que possam ser reordenados através da funcionalidade arrastar e largar.

  2. Verifique se existe também um mecanismo para os reordenar, utilizando conjuntos de menus de listas de links.

  3. Verifique se os menus estão incluídos nos itens reordenáveis no DOM.

  4. Verifique se os scripts utilizados para reordenar são accionados apenas a partir do evento onclick de links.

  5. Verifique se os itens são reordenados no DOM, não apenas visualmente.

Resultados Esperados

  • Os passos 2 a 5 são verdadeiros.


SCR28: Utilizar um menu expansível para ignorar blocos de conteúdo

Aplicabilidade

Tecnologias que forneçam scripting do lado do cliente.

Esta técnica está relacionada com:

Descrição

Esta técnica permite aos utilizadores ignorar material repetido, colocando esse material num menu que pode ser expandido ou fechado mediante o controlo do utilizador. O utilizador pode ignorar o material repetido fechando o menu. O utilizador invoca um controlo da interface de utilizador para ocultar ou remover os elementos do menu. A secção Recursos apresenta várias técnicas para menus, barras de ferramentas e árvores, que podem ser utilizadas para fornecer um mecanismo para ignorar a navegação.

Nota: Abordagens semelhantes podem ser implementadas utilizando scripting do lado do servidor e carregando de novo uma versão modificada da página Web.

Exemplos

Exemplo 1

Os links de navegação no topo da página Web são entradas num menu, implementadas utilizando HTML, CSS e Javascript. Quando a barra de navegação é expandida, os links de navegação ficam disponíveis ao utilizador. Quando a barra de navegação é fechada, os links não ficam disponíveis.

Código Exemplo:

...

  <script type="text/javascript">
  function toggle(id){
    var n = document.getElementById(id);
    n.style.display =  (n.style.display != 'none' ? 'none' : '' );
  }
  </script>

 ...

  <a href="#" onclick="toggle("navbar")">Toggle Navigation Bar</a>

  <ul> id="navbar">
  <li><a href="http://target1.html">Link 1</a></li>
  <li><a href="http://target2.html">Link 2</a></li>
  <li><a href="http://target3.html">Link 3</a></li>
  <li><a href="http://target4.html">Link 4</a></li>
  </ul>

 ...

Este é um exemplo prático deste código: Alternar a barra de navegação utilizando um link .

Exemplo 2

O índice para um conjunto de páginas Web é repetido no início de cada página Web. Um botão no início do índice permite ao utilizador remover ou restaurar o índice na página.

Código Exemplo:

...

   <script type="text/javascript">
  function toggle(id){
    var n = document.getElementById(id);
    n.style.display =  (n.style.display != 'none' ? 'none' : '' );
  }
  </script>

  ...

  <button onclick="return toggle('toc');">Toggle Table of Contents</button>
  <div id="toc">
    ...
  </div>

 ...

Este é um exemplo prático deste código: Alternar o índice utilizando um botão.

Recursos

Os recursos são indicados apenas a título informativo, não implica que tenham sido aprovados.

Testes

Procedimento

  1. Verifique se alguns controlos da interface de utilizador permitem que o conteúdo repetido seja expandido ou fechado.

  2. Verifique se quando o conteúdo é expandido, faz parte do conteúdo determinado de forma programática num local lógico na ordem de leitura.

  3. Verifique se quando o conteúdo é fechado, não faz parte do conteúdo determinado de forma programática.

Resultados Esperados

  • Todos os passos acima são verdadeiros.


SCR29: Adicionar acções acessíveis por teclado a elementos HTML estáticos

Aplicabilidade

HTML e XHTML, Script.

Esta técnica está relacionada com:

Notas de Apoio para o Agente de Utilizador e para a Tecnologia de Apoio

HTML 4.01 apenas define o atributo tabindex para a, area, button, input, object, select e textarea, e limita o respectivo valor para o intervalo entre 0 e 32767. A utilização de tabindex com outros tipos de elemento e o valor tabindex -1 são suportados no Internet Explorer 5.01 e posterior, no Firefox 1.5 e posterior, no Opera 9.5 e posterior e no Camino. Tenha em atenção que modificar o foco através do script pode originar um comportamento imprevisível nos leitores de ecrã que utilizam um cursor virtual.

Descrição

O objectivo desta técnica é demonstrar como fornecer acesso por teclado, para um controlo da interface de utilizador que seja implementado por acções, a elementos HTML estáticos, tais como div ou span. Esta técnica garante que o elemento pode receber foco, definindo o atributo tabindex, e garante que a acção pode ser accionada a partir do teclado, fornecendo um processador onkeyup ou onkeypress além de um processador onclick .

Quando o atributo tabindex tem o valor 0, o elemento pode receber foco através do teclado e é incluído na ordem de tabulação do documento. Quando o atributo tabindex tem o valor -1, não é possível utilizar a tecla de tabulação para percorrer até ao elemento, mas o foco pode ser definido de forma programática, utilizando element.focus().

Como os elementos HTML estáticos não têm acções associadas, não é possível fornecer uma explicação ou implementação alternativas em ambientes nos quais o scripting não está disponível. Esta técnica só deve ser utilizada em ambientes que suportem o scripting do lado do cliente.

Nota: Estes controlos da interface de utilizador têm de continuar a cumprir o Critério de Sucesso 4.1.2. A aplicação desta técnica sem fornecer igualmente a função, o nome e o estado do controlo da interface de utilizador irá resultar na Falha F59: Falha do Critério de Sucesso 4.1.2 devido à utilização de script para tornar div ou span num controlo da interface de utilizador em HTML.

Exemplos

Exemplo 1: Adicionar uma acção JavaScript a um elemento div

São atribuídos ao elemento div existente na página um atributo id exclusivo e um atributo tabindex com o valor 0. Um script utiliza o Modelo de Objecto de Documento (DOM) para localizar o elemento div através do respectivo id e adiciona os processadores onclick e onkeyup . O processador onkeyup irá invocar a acção quando a tecla Enter for pressionada. Tenha em atenção que o elemento div tem de ser carregado no DOM antes de poder ser localizado e modificado. Normalmente, isto é efectuado invocando o script a partir do evento onload do elemento body . O script para adicionar os processadores de evento só é executado se o agente de utilizador suportar JavaScript e o tiver activado.

Código Exemplo:

...
<script type="text/javascript">
 // this is the function to perform the action. This simple example toggles a message.
 function doSomething(event) {
   var msg=document.getElementById("message");
   msg.style.display = msg.style.display=="none" ? "" : "none";
   //return false from the function to make certain that the href of the link does not get invoked
   return false;
 }
 // this is the function to perform the action when the Enter key has been pressed.  
 function doSomethingOnEnter(event) {
   var key = 0;
   // Determine the key pressed, depending on whether window.event or the event object is in use
   if (window.event) {
     key = window.event.keyCode;
   } else if (event) {
     key = event.keyCode;
   }
   // Was the Enter key pressed?
   if (key == 13) {
     return doSomething(event);
   } 
   // The event has not been handled, so return true
   return true;
 }
 // This setUpActions() function must be called to set the onclick and onkeyup event handlers onto the existing 
 // div element. This function must be called after the div element with id="active" has been loaded into the DOM.
 // In this example the setUpActions() function is called from the onload event for the body element.
 function setUpActions() {
   // get the div object
   var active=document.getElementById("active");
   // assign the onclick handler to the object.
   // It is important to return false from the onclick handler to prevent the href attribute
   // from being followed after the function returns.
   active.onclick=doSomething;
   // assign the onkeyup handler to the object.
   active.onkeyup=doSomethingOnEnter;
 }
 </script>

 <body onload="setUpActions();">
 <p>Here is the link to modify with a javascript action:</p>
 <div>
  <span id="active" tabindex="0">Do Something</span>
 </div>
 <div id="message">Hello, world!</div>
 ...

Este é um exemplo prático deste código: Criar Divs com Acções utilizando JavaScript.

Recursos

Testes

Procedimento

Num agente de utilizador que suporte Scripting:

  1. Clique no controlo com o rato.

  2. Verifique se a acção de scripting é executada correctamente.

  3. Verifique se é possível navegar até ao controlo e fornecer foco ao mesmo através do teclado.

  4. Coloque o foco do teclado sobre o controlo.

  5. Verifique se pressionar ENTER invoca a acção de scripting.

Resultados Esperados

  • Todos os passos são verdadeiros.


SCR30: Utilizar scripts para alterar o texto do link

Aplicabilidade

Scripting do lado do cliente utilizado com HTML e XHTML.

Esta técnica está relacionada com:

Descrição

A finalidade desta técnica é permitir que os utilizadores disponham de informações adicionais no texto dos links, de modo a que os links possam ser compreendidos fora de contexto.

Alguns utilizadores preferem links que sejam independentes, em que não haja necessidade de explorar o contexto do link. Outros utilizadores consideram que incluir as informações de contexto em cada link é repetitivo e que reduz a sua capacidade de utilizar um sítio da Web. Entre os utilizadores das tecnologias de apoio, a resposta ao grupo de trabalho sobre o que é preferível ficou dividida. Esta técnica permite aos utilizadores escolher a abordagem que melhor satisfaça as suas necessidades.

É fornecido um link no início da página que irá expandir o texto dos links existentes na página, de modo a não ser necessário contexto adicional para compreender a finalidade dos mesmos. A compreensão da finalidade do link expandido directamente a partir do texto do mesmo tem de ser sempre possível.

Esta técnica só expande os links para a visualização actual da página. Também é possível, e em alguns casos aconselhável, guardar esta preferência num cookie ou perfil de utilizador do lado do servidor, de modo a que os utilizadores só tenham de efectuar a selecção uma vez por sítio da Web.

Exemplos

Exemplo 1

Este exemplo utiliza Javascript para adicionar informações contextuais directamente ao texto de um link. A classe do link é utilizada para determinar qual o texto a adicionar. Quando o link "Expandir Links" é activado, cada link existente na página é testado para ver se é necessário texto adicional.

Código Exemplo:

...
<script>
 var linkContext = {
   "hist":" version of The History of the Web",
   "cook":" version of Cooking for Nerds"
 };

 function doExpand() {
   var links = document.links;
   var link;

   for (link in links) {
     var cn = links[link].className;
     if (linkContext[cn]) {
       links[link].appendChild(document.createTextNode(linkContext[cn]));
     }
   }
 }
</script>

<h1>Books for download</h1>
<p><a href="#" onclick="doExpand();">Expand Links</a></p>

<ul>
<li>The History of the Web: 
<a href="history.docx" class="hist">Word</a>, 
<a href="history.pdf" class="hist">PDF</a>, 
<a href="history.html" class="hist">HTML</a>
</li>

<li>Cooking for Nerds: 
<a href="history.docx" class="cook">Word</a>, 
<a href="history.pdf" class="cook">PDF</a>, 
<a href="history.html" class="cook">HTML</a>
</li>
</ul>

 ...

Testes

Procedimento

  1. Verifique se existe um link no início da página para expandir os links.

  2. Se o link identificado no passo 1 for um link, verifique se pode ser identificado apenas a partir do texto do link.

  3. Localize quaisquer links existentes na página que não possam ser identificados apenas a partir do texto do link.

  4. Active o controlo identificado no passo 1.

  5. Verifique se a finalidade dos links identificados no passo 3 pode agora ser identificada apenas a partir do texto do link.

Resultados Esperados

  • Os passos 1, 2 e 5 são verdadeiros.


SCR31: Utilizar script para alterar a cor de fundo ou o limite do elemento que recebe o foco

Aplicabilidade

HTML e XHTML, CSS, Script.

Esta técnica está relacionada com:

Notas de Apoio para o Agente de Utilizador e para a Tecnologia de Apoio

Esta técnica pode ser utilizada em agentes de utilizador que não suportem a pseudo-classe :focus, mas que suportem o script, incluindo o Microsoft Internet Explorer.

Descrição

A finalidade desta técnica é permitir ao autor utilizar JavaScript para aplicar CSS, de modo a tornar o indicador de foco mais visível do que o normal. Quando um elemento recebe foco, a cor de fundo ou o limite são alterados para o tornar visualmente distinto. Quando o elemento deixa de receber o foco, regressa ao seu estilo normal. Esta técnica pode ser utilizada em qualquer agente de utilizador HTML que suporte Script e CSS, independentemente de suportar ou não a pseudo-classe :focus.

Exemplos

Exemplo 1

Neste exemplo, quando o link recebe o foco, o seu fundo fica amarelo. Quando perde o foco, o amarelo é removido. Tenha em atenção que se o link tiver uma cor de fundo, deverá utilizar essa cor em vez de "" no script.

Código Exemplo:

...
<script>
 function toggleFocus(el)
 {
  el.style.backgroundColor =  el.style.backgroundColor=="yellow" ? "inherit" : "yellow";
 }
</script>

 ...

<a href="example.html" onfocus="toggleFocus(this)" onblur="toggleFocus(this)">focus me</a>
 ...

Testes

Procedimento

  1. Utilize a tecla de tabulação para percorrer cada elemento existente na página.

  2. Verifique se o indicador de foco é visível.

Resultados Esperados

  • O passo 2 é verdadeiro.


SCR32: Fornecer validação do lado do cliente e acrescentar texto de erro através do DOM

Aplicabilidade

Script utilizado com HTML ou XHTML.

Esta técnica está relacionada com:

Descrição

O objectivo desta técnica é apresentar uma mensagem de erro quando há uma falha na validação do lado do cliente de um campo de formulário. Os elementos anchor são utilizados para apresentar as mensagens de erro numa lista e são inseridos acima dos campos que devem ser validados. Os elementos anchor são utilizados nas mensagens de erro, de modo a que o foco possa ser colocado nas mensagens de erro, chamando a atenção do utilizador para as mesmas. O href dos elementos anchor contém um link na página que faz referência aos campos onde foram detectados erros.

Numa aplicação implementada, se Javascript estiver desactivado, não ocorrerá a validação do lado do cliente. Por conseguinte, esta técnica só será considerada de tipo suficiente em situações em que seja suportado o scripting para a conformidade, ou quando as técnicas de validação do lado do servidor também sejam utilizadas para detectar quaisquer erros e devolver a página com informações sobre os campos que apresentam erros.

Exemplos

Exemplo 1

Este exemplo valida os campos obrigatórios, bem como os campos onde é necessário um formato específico. Quando um erro é detectado, o script insere uma lista de mensagens de erro no DOM e desloca o foco para as mesmas.

Captura de ecrã que mostra mensagens de erro para vários campos que não foram preenchidos correctamente. As mensagens de erro são apresentadas como uma lista de links junto ao topo do formulário.

Código HTML e Javascript.

Este é o HTML para o formulário exemplo.

Código Exemplo:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <title>Form Validation</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <link href="css/validate.css" rel="stylesheet" type="text/css"/>
        <script type="text/javascript" src="scripts/validate.js"/>
    </head>
    <body>

        <h1>Form Validation</h1>

        <p>The following form is validated before being submitted if scripting is available,
            otherwise the form is validated on the server. All fields are required, except those
            marked optional. If errors are found in the submission, the form is cancelled and 
            a list of errors is displayed at the top of the form.</p>

        <p> Please enter your details below. </p>

        <h2>Validating Form</h2>

        <form id="personalform" method="post" action="index.php">
            <div class="validationerrors"/>
            <fieldset>
                <legend>Personal Details</legend>
                <p>
                    <label for="forename">Please enter your forename</label>
                    <input type="text" size="20" name="forename" id="forename" class="string"
                        value=""/>
                </p>
                <p>
                    <label for="age">Please enter your age</label>
                    <input type="text" size="20" name="age" id="age" class="number" value=""/>
                </p>
                <p>
                    <label for="email">Please enter your email address</label>
                    <input type="text" size="20" name="email" id="email" class="email" value=""/>
                </p>
            </fieldset>
            <p>
                <input type="submit" name="signup" value="Sign up"/>
            </p>
        </form>
        <h2>Second Form</h2>
        <form id="secondform" method="post" action="index.php#focuspoint">
            <div class="validationerrors"/>
            <fieldset>
                <legend>Second Form Details</legend>
                <p>
                    <label for="suggestion">Enter a suggestion</label>
                    <input type="text" size="20" name="suggestion" id="suggestion" 
                      class="string" value=""/>
                </p>
                <p>
                    <label for="optemail">Please enter your email address (optional)</label>
                    <input type="text" size="20" name="optemail" id="optemail"
                        class="optional email" value=""/>
                </p>
                <p>
                    <label for="rating">Please rate this suggestion</label>
                    <input type="text" size="20" name="rating" id="rating" 
                      class="number" value=""/>
                </p>
                <p>
                    <label for="jibberish">Enter some jibberish (optional)</label>
                    <input type="text" size="20" name="jibberish" id="jibberish" value=""/>
                </p>

            </fieldset>
            <p>
                <input type="submit" name="submit" value="Add Suggestion"/>
            </p>
        </form>
    </body>
</html> 

Este é o Javascript que executa a validação e introduz as mensagens de erro:

Código Exemplo:

window.onload = initialise;

function initialise()
{
   var objForms = document.getElementsByTagName('form');
   var iCounter;

   // Attach an event handler for each form
   for (iCounter=0; iCounter<objForms.length; iCounter++)
   {
      objForms[iCounter].onsubmit = function(){return validateForm(this);};
   }
}


// Event handler for the form
function validateForm(objForm)
{
   var arClass = [];
   var iErrors = 0;
   var objField = objForm.getElementsByTagName('input');
   var objLabel = objForm.getElementsByTagName('label');
   var objList = document.createElement('ol');
   var objError, objExisting, objNew, objTitle, objParagraph, objAnchor, objPosition;
   var strLinkID, iFieldCounter, iClassCounter, iCounter;

   // Get the id or name of the form, to make a unique
   // fragment identifier
   if (objForm.id)
   {
      strLinkID = objForm.id + 'ErrorID';
   }
   else
   {
      strLinkID = objForm.name + 'ErrorID';
   }

   // Iterate through input form controls, looking for validation classes
   for (iFieldCounter=0; iFieldCounter<objField.length; iFieldCounter++)
   {
      // Get the class for the field, and look for the appropriate class
      arClass = objField[iFieldCounter].className.split(' ');
      for (iClassCounter=0; iClassCounter<arClass.length; iClassCounter++)
      {
         switch (arClass[iClassCounter])
         {
            case 'string':
               if (!isString(objField[iFieldCounter].value, arClass))
               {
                  if (iErrors === 0)
                  {
                     logError(objField[iFieldCounter], objLabel, objList, strLinkID);
                  }
                  else
                  {
                     logError(objField[iFieldCounter], objLabel, objList, '');
                  }
                  iErrors++;
               }
               break;
            case 'number':
               if (!isNumber(objField[iFieldCounter].value, arClass))
               {
                  if (iErrors === 0)
                  {
                     logError(objField[iFieldCounter], objLabel, objList, strLinkID);
                  }
                  else
                  {
                     logError(objField[iFieldCounter], objLabel, objList, '');
                  }
                  iErrors++;
               }
               break;

            case 'email' :
               if (!isEmail(objField[iFieldCounter].value, arClass))
               {
                  if (iErrors === 0)
                  {
                     logError(objField[iFieldCounter], objLabel, objList, strLinkID);
                  }
                  else
                  {
                     logError(objField[iFieldCounter], objLabel, objList, '');
                  }
                  iErrors++;
               }
               break;
         }
      }
   }

   if (iErrors > 0)
   {
      // If not valid, display error messages
      objError = objForm.getElementsByTagName('div');
      
      // Look for existing errors
      for (iCounter=0; iCounter<objError.length; iCounter++)
      {
         if (objError[iCounter].className == 'validationerrors')
         {
            objExisting = objError[iCounter];
         }
      }

      objNew = document.createElement('div');
      objTitle = document.createElement('h2');
      objParagraph = document.createElement('p');
      objAnchor = document.createElement('a');

      if (iErrors == 1)
      {
         objAnchor.appendChild(document.createTextNode('1 Error in Submission'));
      }
      else
      {
         objAnchor.appendChild(document.createTextNode(iErrors + ' Errors in Submission'));
      }
      objAnchor.href = '#' + strLinkID;
      objAnchor.className = 'submissionerror';

      objTitle.appendChild(objAnchor);
      objParagraph.appendChild(document.createTextNode('Please review the following'));
      objNew.className = 'validationerrors';

      objNew.appendChild(objTitle);
      objNew.appendChild(objParagraph);
      objNew.appendChild(objList);
      
      // If there were existing error, replace them with the new lot,
      // otherwise add the new errors to the start of the form
      if (objExisting)
      {
         objExisting.parentNode.replaceChild(objNew, objExisting);
      }
      else
      {
         objPosition = objForm.firstChild;
         objForm.insertBefore(objNew, objPosition);
      }

      // Allow for latency
      setTimeout(function() { objAnchor.focus(); }, 50);
      
      // Don't submit the form
      objForm.submitAllowed = false;
      return false;
   }

   // Submit the form
   return true;
}

// Function to add a link in a list item that points to problematic field control
function addError(objList, strError, strID, strErrorID)
{
   var objListItem = document.createElement('li');
   var objAnchor = document.createElement('a');
   
   // Fragment identifier to the form control
   objAnchor.href='#' + strID;

   // Make this the target for the error heading
   if (strErrorID.length > 0)
   {
      objAnchor.id = strErrorID;
   }

   // Use the label prompt for the error message
   objAnchor.appendChild(document.createTextNode(strError));
   // Add keyboard and mouse events to set focus to the form control
   objAnchor.onclick = function(event){return focusFormField(this, event);};
   objAnchor.onkeypress = function(event){return focusFormField(this, event);};
   objListItem.appendChild(objAnchor);
   objList.appendChild(objListItem);
}

function focusFormField(objAnchor, objEvent)
{
   var strFormField, objForm;

   // Allow keyboard navigation over links
   if (objEvent && objEvent.type == 'keypress')
   {
      if (objEvent.keyCode != 13 && objEvent.keyCode != 32)
      {
         return true;
      }
   }

   // set focus to the form control
   strFormField = objAnchor.href.match(/[^#]\w*$/);
   objForm = getForm(strFormField);
   objForm[strFormField].focus();
   return false;
}

// Function to return the form element from a given form field name
function getForm(strField)
{
   var objElement = document.getElementById(strField);

   // Find the appropriate form
   do
   {
      objElement = objElement.parentNode;
   } while (!objElement.tagName.match(/form/i) && objElement.parentNode);

   return objElement;
}

// Function to log the error in a list
function logError(objField, objLabel, objList, strErrorID)
{
   var iCounter, strError;

   // Search the label for the error prompt
   for (iCounter=0; iCounter<objLabel.length; iCounter++)
   {
      if (objLabel[iCounter].htmlFor == objField.id)
      {
         strError = objLabel[iCounter].firstChild.nodeValue;
      }
   }

   addError(objList, strError, objField.id, strErrorID);
}

// Validation routines - add as required

function isString(strValue, arClass)
{
   var bValid = (typeof strValue == 'string' && strValue.replace(/^\s*|\s*$/g, '') 
     !== '' && isNaN(strValue));

   return checkOptional(bValid, strValue, arClass);
}

function isEmail(strValue, arClass)
{
   var objRE = /^[\w-\.\']{1,}\@([\da-zA-Z\-]{1,}\.){1,}[\da-zA-Z\-]{2,}$/;
   var bValid = objRE.test(strValue);

   return checkOptional(bValid, strValue, arClass);
}

function isNumber(strValue, arClass)
{
   var bValid = (!isNaN(strValue) && strValue.replace(/^\s*|\s*$/g, '') !== '');

   return checkOptional(bValid, strValue, arClass);
}

function checkOptional(bValid, strValue, arClass)
{
   var bOptional = false;
   var iCounter;

   // Check if optional
   for (iCounter=0; iCounter<arClass.length; iCounter++)
   {
      if (arClass[iCounter] == 'optional')
      {
         bOptional = true;
      }
   }

   if (bOptional && strValue.replace(/^\s*|\s*$/g, '') === '')
   {
      return true;
   }

   return bValid;
   } 

Este é um exemplo prático desta técnica implementada utilizando PHP, Javascript, CSS e XHTML: Exemplo de Validação do Formulário.

Testes

Procedimento

Crie mensagens de erro utilizando marcas anchor e scripts apropriados através da técnica acima.

  1. Carregue a página.

  2. Introduza um valor válido nos campos associados a uma mensagem de erro e verifique se não são apresentadas quaisquer mensagens de erro.

  3. Introduza um valor inválido nos campos associados a uma mensagem de erro e verifique se é apresentada a mensagem de erro correcta para o campo.

  4. Verifique se as mensagens de erro recebem foco.

  5. Introduza um valor válido nos campos associados à mensagem de erro apresentada e verifique se a mensagem de erro é removida.

  6. Repita o procedimento para todos os campos com mensagens de erro associadas criadas através de marcas anchor.

Nota: Recomendamos que também execute o procedimento acima utilizando uma tecnologia de apoio.

Resultados Esperados

  • Os passos 2, 3, 4 e 5 são verdadeiros.


SCR33: Utilizar o script para deslocar o conteúdo e fornecer um mecanismo para colocá-lo em pausa

Aplicabilidade

Tecnologias que suportem deslocamento de conteúdo controlado por scripts.

Esta técnica está relacionada com:

Descrição

O objectivo desta técnica é fornecer uma forma para os utilizadores pararem conteúdo em deslocamento quando o deslocamento é criado por um script. O conteúdo em deslocamento pode ser difícil ou impossível de ler por utilizadores com baixa visão ou incapacidades cognitivas. Algumas pessoas também podem distrair-se com o movimento, dificultando-lhes a concentração noutras partes da página Web.

Exemplos

Exemplo 1

Neste exemplo, são utilizados CSS e Javascript para apresentar visualmente algum texto em deslocamento. É incluído um link para colocar o deslocamento em pausa.

Esta implementação irá apresentar todo o texto e omitir o link quando Javascript ou CSS não forem suportados ou estiverem inactivos.

O código seguinte é uma versão corrigida do Deslocamento Acessível de webSemantic (a partir de Julho de 2008).

O componente XHTML:

Código Exemplo:

...
<div id="scroller">
<p id="tag">This text will scroll and a Pause/Scroll link will be present 
when Javascript and CSS are supported and active.</p>
</div>
 ...

O componente CSS:

Código Exemplo:

...
body {font:1em verdana,sans-serif; color:#000; margin:0}

/* position:relative and overflow:hidden are required */
#scroller { position:relative; overflow:hidden; width:15em; border:1px solid #008080; }

/* add formatting for the scrolling text */
#tag { margin:2px 0; }

/* #testP must also contain all text-sizing properties of #tag  */
#testP { visibility:hidden; position:absolute; white-space:nowrap; } 

/* used as a page top marker and to limit width */
#top { width:350px; margin:auto; }
 ...

O componente JavaScript:

Código Exemplo:

var speed=50        // speed of scroller
var step=3          // smoothness of movement
var StartActionText= "Scroll"  // Text for start link
var StopActionText = "Pause"   // Text for stop link

var x, scroll, divW, sText=""

function onclickIE(idAttr,handler,call){
  if ((document.all)&&(document.getElementById)){idAttr[handler]="Javascript:"+call}
}

function addLink(id,call,txt){
  var e=document.createElement('a')
  e.setAttribute('href',call)
  var linktext=document.createTextNode(txt)
  e.appendChild(linktext)
  document.getElementById(id).appendChild(e)
}

function getElementStyle() {
    var elem = document.getElementById('scroller');
    if (elem.currentStyle) {
        return elem.currentStyle.overflow;
    } else if (window.getComputedStyle) {
        var compStyle = window.getComputedStyle(elem, '');
        return compStyle.getPropertyValue("overflow");
    }
    return "";
}

function addControls(){
// test for CSS support first 
// test for the overlow property value set in style element or external file
if (getElementStyle()=="hidden") {
  var f=document.createElement('div');
  f.setAttribute('id','controls');
  document.getElementById('scroller').parentNode.appendChild(f);
  addLink('controls','Javascript:clickAction(0)',StopActionText);
  onclickIE(document.getElementById('controls').childNodes[0],"href",'clickAction(0)');
  document.getElementById('controls').style.display='block';
  }
}

function stopScroller(){clearTimeout(scroll)}

function setAction(callvalue,txt){
  var c=document.getElementById('controls')
  c.childNodes[0].setAttribute('href','Javascript:clickAction('+callvalue+')')
  onclickIE(document.getElementById('controls').childNodes[0],"href",'clickAction

('+callvalue+')')
  c.childNodes[0].firstChild.nodeValue=txt
}

function clickAction(no){
  switch(no) {
    case 0:
      stopScroller();
      setAction(1,StartActionText);
      break;
    case 1:
      startScroller();
      setAction(0,StopActionText);
  }
}

function startScroller(){
  document.getElementById('tag').style.whiteSpace='nowrap'
  var p=document.createElement('p')
  p.id='testP'
  p.style.fontSize='25%' //fix for mozilla. multiply by 4 before using
  x-=step
  if (document.getElementById('tag').className) p.className=document.getElementById

('tag').className
  p.appendChild(document.createTextNode(sText))
  document.body.appendChild(p)
  pw=p.offsetWidth
  document.body.removeChild(p)
  if (x<(pw*4)*-1){x=divW}
  document.getElementById('tag').style.left=x+'px'
  scroll=setTimeout('startScroller()',speed)
}

function initScroller(){
  if (document.getElementById && document.createElement && document.body.appendChild) {
    addControls();
    divW=document.getElementById('scroller').offsetWidth;
    x=divW;
    document.getElementById('tag').style.position='relative';
    document.getElementById('tag').style.left=divW+'px';
    var ss=document.getElementById('tag').childNodes;
    for (i=0;i<ss.length;i++) {sText+=ss[i].nodeValue+" "};
    scroll=setTimeout('startScroller()',speed);
  }
}

function addLoadEvent(func) {
  if (!document.getElementById | !document.getElementsByTagName) return
  var oldonload = window.onload
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      oldonload()
      func()
    }
  }
}

addLoadEvent(initScroller)

Recursos

Os recursos são indicados apenas a título informativo, não implica que tenham sido aprovados.

Testes

Procedimento

  1. Verifique se é fornecido um mecanismo para colocar em pausa o conteúdo em deslocamento.

  2. Utilize esse mecanismo para colocar em pausa o conteúdo em deslocamento.

  3. Verifique se o deslocamento parou e não reinicia automaticamente.

  4. Verifique se é fornecido um mecanismo para reiniciar o conteúdo em pausa.

  5. Utilize esse mecanismo para reiniciar o conteúdo em deslocamento.

  6. Verifique se o deslocamento foi retomado a partir do ponto onde parou.

Resultados Esperados

  • Os passos 3 e 6 são verdadeiros.


SCR34: Calcular o tamanho e a posição de modo a ficarem ajustados ao tamanho do texto

Aplicabilidade

Scripting do lado do cliente.

Esta técnica está relacionada com:

Notas de Apoio para o Agente de Utilizador e para a Tecnologia de Apoio

O cálculo do tamanho e da posição pode ser complexo e diferentes browsers podem produzir diferentes resultados. Isto pode ocorrer quando o estilo CSS mistura o preenchimento, as margens e as larguras de um objecto, ou quando mistura um valor desfasado e claro, por ex., offsetWidth e largura. Alguns destes comportam-se de forma diferente na reacção ao zoom (ampliar/reduzir). Para obter uma explicação sobre a diferença entre o Internet Explorer 6 e posterior e as versões anteriores do Internet Explorer, consulte MSDN: Arranjar a Caixa Em Vez de Ler o Contéudo Fora Dela (página em inglês) .

Descrição

O objectivo desta técnica é calcular o tamanho e a posição dos elementos, de modo a serem ajustados correctamente à medida que o tamanho do texto é ajustado.

Existem quatro propriedades em JavaScript que ajudam a determinar o tamanho e a posição dos elementos:

  • offsetHeight (a altura do elemento em pixéis)

  • offsetWidth (a largura do elemento em pixéis)

  • offsetLeft (a distância do elemento da esquerda do respectivo elemento principal (offsetParent) em pixéis)

  • offsetTop (a distância do elemento do topo do respectivo elemento principal (offsetParent) em pixéis)

Calcular a altura e a largura utilizando offsetHeight e offsetWidth é simples, mas para calcular as posições à esquerda e superior de um objecto como valores absolutos, é necessário considerar o elemento principal. A função calculatePosition abaixo é executada em todos os nós principais de um elemento para apresentar um valor final. A função utiliza dois parâmetros, objElement (o nome do elemento em questão), e a propriedade offset (offsetLeft ou offsetTop):

Exemplos

Exemplo 1

A função Javascript:

Código Exemplo:

function calculatePosition(objElement, strOffset)
{
    var iOffset = 0;

    if (objElement.offsetParent)
    {
        do 
        {
            iOffset += objElement[strOffset];
            objElement = objElement.offsetParent;
        } while (objElement);
    }

    return iOffset;
}

O exemplo seguinte ilustra a utilização da função acima, alinhando um objecto debaixo de um objecto de referência, à mesma distância da esquerda:

Código Exemplo:

// Get a reference object
var objReference = document.getElementById('refobject');
// Get the object to be aligned
var objAlign = document.getElementById('lineup');

objAlign.style.position = 'absolute';
objAlign.style.left = calculatePosition(objReference, 'offsetLeft') + 'px';
objAlign.style.top = calculatePosition(objReference, 'offsetTop') + objReference.offsetHeight + 'px'; 

Recursos

Os recursos são indicados apenas a título informativo, não implica que tenham sido aprovados.

Testes

Procedimento

  1. Abra uma página que tenha sido concebida para ajustar os tamanhos das caixas à medida que o tamanho do texto é alterado.

  2. Aumente o tamanho do texto até 200% utilizando o ajuste do tamanho do texto do browser (não a funcionalidade de zoom (ampliar/reduzir).

  3. Verifique o texto para se certificar de que o tamanho da caixa de texto é ajustado de modo a acomodar o tamanho do texto.

  4. Certifique-se de que não existe texto "cortado" ou que tenha desaparecido como resultado do aumento do tamanho do texto.

Resultados Esperados

  • Os passos 3 e 4 são verdadeiros.


SCR35: Tornar as acções acessíveis por teclado utilizando o evento onclick de âncoras e botões

Aplicabilidade

Scripts utilizados com HTML ou XHTML.

Esta técnica está relacionada com:

Descrição

O objectivo desta técnica é demonstrar como invocar uma função de scripting de modo a ser acessível por teclado, associando-a a um controlo acessível por teclado. Para garantir que as acções de script podem ser invocadas a partir do teclado, estão associadas a elementos HTML "accionáveis de forma nativa" (links e botões). O evento onclick destes elementos é independente do dispositivo. Apesar de "onclick" parecer estar associado ao rato, o evento onclick está, na realidade, associado à acção predefinida de um link ou botão. A acção predefinida ocorre quando o utilizador clica no elemento com um rato, mas também ocorre quando o utilizador coloca o foco sobre o elemento e pressiona a tecla Enter ou Space, e quando o elemento é accionado através da API de acessibilidade.

Embora esta técnica dependa do scripting do lado do cliente, é aconselhável fornecer uma explicação ou implementação alternativas para ambientes nos quais o scripting não esteja disponível. Ao utilizar elementos anchor para invocar uma acção JavaScript, é fornecida uma explicação ou implementação alternativas através do atributo href . Ao utilizar botões, é fornecida através de um formulário.

Exemplos

Exemplo 1

Link que executa um script e não tem qualquer alternativa para browsers que não suportam scripts. Esta abordagem só deve ser utilizada quando o script for dependente de uma Tecnologia Suportada por Acessibilidade.

Apesar de não pretender navegar a partir deste link, tem de utilizar o atributo href no elemento a, de modo a torná-lo num link verdadeiro e a obter os eventos correctos. Neste caso, é utilizado "#" como o destino do link, mas pode utilizar o que quiser. Este link nunca será navegado.

A expressão "return false;" no fim da função de processamento de eventos doStuff() indica ao browser para não navegar até ao URI. Sem ela, a página seria actualizada após a execução do script.

Código Exemplo:

<script> 
function doStuff()
 {
  //do stuff
    return false;
  }
</script>
<a href="#" onclick="return doStuff();">do stuff</a>

Exemplo 2

Link que executa um script, mas navega até outra página quando o script não está disponível. Esta abordagem só pode ser utilizada por sítios da Web que não dependam de scripts se o destino de navegação fornecer a mesma funcionalidade do script. Este exemplo é idêntico ao exemplo 1, com a excepção de que o respectivo href está agora definido para uma página real, dostuff.htm. Dostuff.htm tem de fornecer a mesma funcionalidade do script. A expressão "return false;" no fim da função de processamento de eventos doStuff() indica ao browser para não navegar até ao URI. Sem ela, o browser iria navegar até dostuff.htm após a execução do script.

Código Exemplo:

<script> 
function doStuff() 
 {  
  //do stuff  
  return false; 
 }
</script>
<a href="dostuff.htm" onclick="return doStuff();">do stuff</a>

Está disponível um exemplo prático deste código. Consulte Criar Links de Acção utilizando JavaScript.

Exemplo 3

Botão que executa um script e encaminha para um formulário para os utilizadores sem scripts. Esta abordagem só pode ser utilizada por sítios da Web que não dependam de scripts se o formulário fornecer a mesma funcionalidade do script. A expressão onsubmit="return false;" impede a submissão do formulário.

Código Exemplo:

<script>
  function doStuff()
 {
     //do stuff
 }
</script>
<form action="doStuff.aspx" onsubmit="return false;">
 <input type="submit" value="Do Stuff" onclick="doStuff();" />
</form>

Está disponível um exemplo prático deste código. Consulte Criar Botões de Acção utilizando JavaScript.

Exemplo 4

Botão que executa um script, implementado com input type="image". Tenha em atenção que tem de adicionar um atributo title ao input para fornecer um equivalente de texto para a imagem. Esta abordagem só deve ser utilizada quando o script for dependente.

Código Exemplo:

<script>
  function doStuff()
  {
     //do stuff
   return false;
  }
</script>
<input  type="image"  src="stuff.gif"  title="Do stuff"  onclick="return doStuff();" />

Exemplo 5

Botão que executa um script, implementado com input type="submit", input type="reset" ou input type="button". Esta abordagem só deve ser utilizada quando o script for dependente.

Código Exemplo:

<input type="submit" onclick="return doStuff();" value=”Do Stuff” />

Exemplo 6

Botão que executa um script, implementado com button/button. Isto é útil quando pretende mais controlo sobre o aspecto do botão. Neste exemplo em particular, o botão contém um ícone e algum texto. Esta abordagem só deve ser utilizada quando o script for dependente.

Código Exemplo:

<button onclick="return doStuff();">
 <img src="stuff.gif" alt="stuff icon">
 Do Stuff
</button>

Recursos

Testes

Procedimento

Para todas as acções de script associadas a elementos a, button ou input :

  1. Num agente de utilizador que suporte Scripting

    • Clique no controlo com o rato.

    • Verifique se a acção de scripting é executada correctamente.

    • Se o controlo for um elemento anchor, verifique se o URI existente no atributo href do elemento anchor não é invocado.

    • Verifique se é possível navegar até ao controlo e fornecer foco ao mesmo através do teclado.

    • Coloque o foco do teclado sobre o controlo.

    • Verifique se pressionar ENTER invoca a acção de scripting.

    • Se o controlo for um elemento anchor, verifique se o URI existente no atributo href do elemento anchor não é invocado.

  2. Num agente de utilizador que não suporte Scripting

    • Clique no controlo com o rato.

    • Se o controlo for um elemento anchor, verifique se o URI existente no atributo href do elemento anchor é invocado.

    • Verifique se é possível navegar até ao controlo e fornecer foco ao mesmo através do teclado.

    • Coloque o foco do teclado sobre o controlo.

    • Se o controlo for um elemento anchor, verifique se pressionar ENTER invoca o URI do atributo href do elemento anchor.

Resultados Esperados

  • Todos os passos acima são verdadeiros.


SCR36: Fornecer um mecanismo para permitir aos utilizadores apresentar texto em movimento, em deslocamento ou em actualização automática numa janela ou área estáticas

Aplicabilidade

Qualquer tecnologia que mova, coloque em modo intermitente ou actualize texto e possa criar um bloco de texto estático.

Esta técnica está relacionada com:

Descrição

Algumas páginas Web apresentam texto em deslocamento porque o espaço disponível é limitado. Deslocar o texto numa pequena janela de texto disponibiliza o conteúdo para os utilizadores que conseguem ler rapidamente, mas origina problemas para os utilizadores que lêem mais lentamente ou utilizam tecnologias de apoio. Esta técnica fornece um mecanismo para parar o movimento e tornar todo o bloco de texto disponível de forma estática. O texto pode ser disponibilizado numa janela separada ou numa secção (maior) da página. Assim os utilizadores podem ler o texto à velocidade desejada.

Esta técnica não se aplica quando o texto que está em movimento não pode ser apresentado todo de uma vez no ecrã (por ex., uma longa conversa num chat).

Nota: Esta técnica pode ser utilizada em conjunto com uma técnica de mudança de estilo para apresentar uma página que seja uma versão alternativa em conformidade para conteúdo que não esteja em conformidade. Para mais informações, consulte C29: Utilizar um comutador de estilo para fornecer uma versão alternativa em conformidade (CSS) e Noções sobre Versões Alternativas em Conformidade .

Exemplos

Exemplo 1: Expandir Texto em Deslocamento no Local

Um grande bloco de texto é deslocado através de uma pequena área da página. Um botão permite ao utilizador parar o deslocamento e visualizar todo o bloco de texto.

Nota: Este código exemplo requer que CSS e JavaScript estejam activados e disponíveis.

O componente CSS:

Código Exemplo:

#scrollContainer {
        visibility: visible;
        overflow: hidden;
        top: 50px; left: 10px;
        background-color: darkblue;
      }
      .scrolling {
        position: absolute;
        width: 200px;
        height: 50px;
      }
      .notscrolling {
        width: 500px;
        margin:10px;
      }
      #scrollingText {
        top: 0px;
        color: white;
      }
      .scrolling #scrollingText {
        position: absolute;
      }
      </a> 

O script e o conteúdo HTML:

Código Exemplo:

<script type="text/javascript">

      var tid;
      function init() {
        var st = document.getElementById('scrollingText');
        st.style.top = '0px';
        initScrolling();
      }
      function initScrolling () {
        tid = setInterval('scrollText()', 300);
      }
      function scrollText () {
        var st = document.getElementById('scrollingText');
        if (parseInt(st.style.top) > (st.offsetHeight*(-1) + 8)) {
          st.style.top = (parseInt(st.style.top) - 5) + 'px';
        } else {
          var sc = document.getElementById('scrollContainer');
          st.style.top = parseInt(sc.offsetHeight) + 8 + 'px';
        }
      }
      function toggle() {
        var scr = document.getElementById('scrollContainer');
        if (scr.className == 'scrolling') {
          scr.className = 'notscrolling';
          clearInterval(tid);
           document.getElementById('scrollButton').value="Shrink";
        } else {
          scr.className = 'scrolling';
          initScrolling();
          document.getElementById('scrollButton').value="Expand";
        }
      }
  <input type="button" id="scrollButton" value="Expand" onclick="toggle()" />
  <div id="scrollContainer" class="scrolling">
    <div id="scrollingText" class="on">
    .... Text to be scrolled ...
    </div>
  </div>
 ...

Este é um exemplo prático deste código: Expandir Texto em Deslocamento no Local.

Testes

Não existem testes disponíveis para esta técnica.


SCR37: Criar Caixas de Diálogo Personalizadas de uma Forma Independente do Dispositivo

Aplicabilidade

HTML e XHTML utilizados com script.

Esta técnica está relacionada com:

Descrição

Muitas vezes, os programadores dos sítios da Web pretenderem criar caixas de diálogo que não utilizem as janelas de pop-up fornecidas pelo browser. Normalmente, isto é efectuado juntando os conteúdos da caixa de diálogo num div e colocando o div acima do conteúdo da página, utilizando a ordem z e o posicionamento absoluto em CSS.

Para estarem acessíveis, estas caixas de diálogo têm de seguir algumas regras simples:

  1. Accionar o script que apresenta a caixa de diálogo a partir do evento onclick de um link ou botão.

  2. Colocar a caixa de diálogo div no Modelo de Objecto de Documento (DOM) imediatamente a seguir ao elemento que a accionou. O elemento accionador irá manter o foco, e a introdução do conteúdo da caixa de diálogo a seguir a esse elemento irá fazer com que o conteúdo dentro da caixa de diálogo seja o seguinte na ordem de leitura do leitor de ecrã e o seguinte na ordem de tabulação. A caixa de diálogo ainda pode ser posicionada em qualquer outra parte da página. Isto pode ser efectuado mediante a criação da caixa de diálogo em HTML e ocultando-a com CSS, conforme ilustrado no exemplo abaixo, ou inserindo-a imediatamente a seguir ao elemento accionador com o script.

  3. Garantir que o HTML dentro da caixa de diálogo div cumpre a mesma norma de acessibilidade do restante conteúdo.

Também é recomendável, mas nem sempre necessário, que o link de apresentação alterne entre a funcionalidade de abertura e fecho da caixa de diálogo, e que feche a caixa de diálogo quando esta deixar de receber o foco do teclado.

Exemplos

Exemplo 1: Um botão de opções que abre uma caixa de diálogo

O HTML para este exemplo inclui um elemento accionador, neste caso um botão, e um div que funciona como a frame para a caixa de diálogo.

O elemento accionador é um botão e o script é accionado a partir do evento onclick. Isto envia os eventos apropriados para o sistema operativo de modo a que a tecnologia de apoio tenha conhecimento da alteração efectuada no DOM.

Neste exemplo, os botões Submeter e Repor da caixa de diálogo ocultam o div.

Código Exemplo:

...
<button onclick="TogglePopup(event,true)"
	name="pop0001">Options</button>

<div class="popover" id="pop0001">
  <h3>Edit Sort Information</h3>
  <form action="default.htm" onsubmit="this.parentNode.style.display='none'; return false;" onreset="this.parentNode.style.display='none'; return false;">
    <fieldset>
      <legend>Sort Order</legend> 
      <input type="radio" name="order" id="order_alpha" /><label for="order_alpha">Alphabetical</label>
      <input type="radio" name="order" id="order_default" checked="true" /><label for="order_default">Default</label>
    </fieldset>
<div class="buttons">
  <input type="submit" value="OK" />
  <input type="reset" value="Cancel" />
</div>
</form>

</div>
 ...

Os elementos div, heading e form são estilizados com CSS para parecerem uma caixa de diálogo.

Código Exemplo:

...
a { color:blue; }
a.clickPopup img { border:none; width:0; }

div.popover { position:absolute; display:none; border:1px outset; background-color:beige; font-size:80%; background-color:#eeeeee; color:black; }
div.popover h3 { margin:0; padding:0.1em 0.5em; background-color:navy; color:white; }
#pop0001 { width:20em; }
#pop0001 form { margin:0; padding:0.5em; }
#pop0001 fieldset { margin-bottom:0.3em; padding-bottom:0.5em; }
#pop0001 input, #pop0001 label { vertical-align:middle; }
#pop0001 div.buttons { text-align:right; }
#pop0001 div.buttons input { width:6em; }
 ...

O script alterna a apresentação da caixa de pop-up div, mostrando-a e ocultando-a.

Código Exemplo:

...
function TogglePopup(evt,show)
{
	HarmonizeEvent(evt);
	var src = evt.target;
	if ("click" == evt.type)
	{
		evt.returnValue = false;
	}
	var popID = src.getAttribute("name");
	if (popID)
	{
		var popup = document.getElementById(popID);
		if (popup)
		{
			if (true == show)
			{
				popup.style.display = "block";
			}
			else if (false == show)
			{
				popup.style.display = "none";
			}
			else
			{
				popup.style.display = "block" == popup.style.display ? "none" : "block";
			}
			if ("block" == popup.style.display)
			{
				//window.alert(document.documentElement.scrollHeight);
				popup.style.top = ((document.documentElement.offsetHeight - popup.offsetHeight) / 2 ) + 'px';
				popup.style.left = ((document.documentElement.offsetWidth - popup.offsetWidth) / 2) + 'px';
			}
		}
	}
}

function SubmitForm(elem)
{ 
	elem.parentNode.style.display='none'; 
	return false;
}

function ResetForm(elem)
{ 
	elem.parentNode.style.display='none'; 
	return false;
}
 ...

Está disponível um exemplo prático, Um botão de opções que abre uma caixa de diálogo.

Recursos

Os recursos são indicados apenas a título informativo, não implica que tenham sido aprovados.

Testes

Procedimento

  1. Localize todas as áreas da página que accionam caixas de diálogo que não são janelas de pop-up.

  2. Verifique se as caixas de diálogo podem ser abertas utilizando a tecla de tabulação para percorrer a área e pressionando a tecla Enter.

  3. Verifique se, uma vez aberta, a caixa de diálogo é a seguinte na ordem de tabulação.

  4. Verifique se as caixas de diálogo são accionadas a partir do evento click de um botão ou link.

  5. Utilizando uma ferramenta que permita analisar o DOM gerado por scripts, verifique se a caixa de diálogo é a seguinte no DOM.

Resultados Esperados

  • Os passos 2, 3, 4 e 5 são verdadeiros.