Quando um clique não é um click
? Para um desenvolvedor da Web que trabalha em uma interface de usuário
complexa, essa não é uma questão filosófica abstrata. Se você estiver implementando
um comportamento personalizado de entrada do mouse, é fundamental manter a intenção do usuário em mente. Se um usuário
clicar em um link com o botão do meio do mouse, por exemplo, é
razoável presumir que ele queria abrir uma nova guia com o conteúdo
do link. Se um usuário clicar com o botão do meio em um elemento de interface aleatório, você pode
supor que foi acidental e ignorar essa entrada. Já um clique no botão
principal deve acionar uma resposta da interface.
É possível, mas um pouco complicado, modelar essas interações com nuances usando um
único listener de eventos click
. Você precisa verificar explicitamente a propriedade
button
do
MouseEvent
,
para saber se ela foi definida como 0
, representando o botão principal,
em vez de qualquer outra coisa, com 1
geralmente representando o botão do
meio, e assim por diante. No entanto, poucos desenvolvedores verificam explicitamente a
propriedade button
, o que leva a um código que processa todos
os click
s de maneira idêntica, independentemente de qual botão foi pressionado.
A partir do Chrome 55, um novo tipo de MouseEvent
, chamado auxclick
, é acionado
em resposta a todos os cliques feitos com um botão não principal. Acompanhando esse novo
evento, há uma mudança correspondente no comportamento do evento click
: ele só
é acionado quando o botão principal do mouse é pressionado. Esperamos que essas mudanças
facilitem a criação de manipuladores de eventos que respondam apenas
ao tipo de cliques que interessam aos desenvolvedores da Web, sem precisar verificar especificamente
a propriedade MouseEvent.button
.
Reduzir falsos positivos
Como mencionado, uma das motivações para criar auxclick
foi evitar a implantação de
gerenciadores click
personalizados que substituem por engano o comportamento "clique do botão do meio abre uma guia". Por exemplo, imagine que você tenha criado um manipulador de eventos click
que
usa a API History
para reescrever a barra de localização e implementar navegações personalizadas de página única. Ele
pode ficar assim:
document.querySelector('#my-link').addEventListener('click', event => {
event.preventDefault();
// ...call history.pushState(), use client-side rendering, etc....
});
Sua lógica personalizada pode funcionar conforme o esperado quando acionada pelo botão principal
do mouse, mas se esse código for executado quando um botão do meio for clicado, será
um falso positivo. Antes do novo comportamento, você impedia a ação padrão
de abrir uma nova guia, o que contraria as expectativas do usuário.
Embora seja possível verificar explicitamente event.button === 0
no início do
gerenciador e executar o código apenas se esse for o caso, é fácil esquecer ou
nunca perceber que isso é necessário.
Executar apenas o código necessário
O lado negativo de menos falsos positivos é que os callbacks auxclick
só serão
executados quando um botão não principal do mouse for clicado. Se você tiver um código
que precise, por exemplo, calcular um URL de destino adequado antes de
abrir uma nova guia, poderá detectar auxclick
e incluir essa lógica no seu
callback. Ele não vai gerar a sobrecarga de execução quando o botão principal do mouse
for clicado.
Suporte e compatibilidade do navegador
No momento, esse novo comportamento está implementado apenas no Chrome 55. Como mencionado na proposta inicial, o feedback (positivo e negativo) da comunidade de desenvolvedores da Web é bem-vindo. Registrar um problema do GitHub é a melhor maneira de compartilhar esse feedback com as pessoas que estão trabalhando no processo de padronização.
Enquanto isso, os desenvolvedores não precisam esperar que auxclick
esteja amplamente
disponível para seguir algumas práticas recomendadas para processar eventos do mouse. Se você conferir
o valor da propriedade MouseEvent.button
no início do
gerenciador de eventos click
, poderá garantir que está tomando as medidas adequadas. O
padrão a seguir processa os cliques primários e auxiliares de maneira diferente, independente de haver ou não suporte nativo para auxclick
:
function handlePrimaryClick(event) {
// ...code to handle the primary button click...
}
function handleAuxClick(event) {
// ...code to handle the auxiliary button click….
}
document.querySelector('#my-link').addEventListener('click', event => {
if (event.button === 0) {
return handlePrimaryClick(event);
}
// This provides fallback behavior in browsers without auxclick.
return handleAuxClick(event);
});
// Explicitly listen for auxclick in browsers that support it.
document.querySelector('#my-link').addEventListener('auxclick', handleAuxClick);