O Auxclick está chegando ao Chrome 55

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 clicks 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);