auxclick が Chrome 55 に登場

クリックが click ではないのはどのような場合ですか?複雑なユーザー インターフェースを扱うウェブ デベロッパーにとって、これは抽象的な哲学的な質問ではありません。カスタムのマウス入力動作を実装する場合は、ユーザーの意図を念頭に置くことが重要です。たとえば、ユーザーがマウスの中ボタンでリンクをクリックした場合、そのリンクのコンテンツを含む新しいタブを開こうとしていると推測できます。ユーザーがランダムな UI 要素を中ボタンでクリックした場合、誤ってクリックされたと想定してその入力を無視できますが、メインボタンのクリックは UI からのレスポンスをトリガーすることが想定されます。

これらの微妙なインタラクションを 1 つの click イベント リスナーでモデル化することは可能ですが、少し手間がかかります。MouseEventbutton プロパティを明示的に確認して、プライマリ ボタンを表す 0 に設定されているか、他の値に設定されているか(通常、1 は中央のボタンを表します)を確認する必要があります。ただし、button プロパティを明示的にチェックするデベロッパーは多くないため、どのボタンが押されたかに関係なく、すべての click を同じように処理するコードが作成されることになります。

Chrome 55 以降では、プライマリ以外のボタンでクリックされたときに、auxclick という新しいタイプの MouseEvent がトリガーされます。この新しいイベントに伴い、click イベントの動作も変更されます。このイベントは、メインの左ボタンが押された場合にのみ発生します。これらの変更により、ウェブ デベロッパーが MouseEvent.button プロパティを明示的にチェックしなくても、必要なクリック タイプにのみ応答するイベント ハンドラを簡単に作成できるようになります。

誤検出を低減する

前述のように、auxclick を作成する理由の 1 つは、「中ボタンクリックでタブを開く」動作を誤ってオーバーライドするカスタム click ハンドラのデプロイを回避するためでした。たとえば、History API を使用してロケーション バーを書き換え、カスタムのシングルページ ナビゲーションを実装する click イベント ハンドラを作成したとします。次のような形式になります。

document.querySelector('#my-link').addEventListener('click', event => {
    event.preventDefault();
    // ...call history.pushState(), use client-side rendering, etc....
});

カスタム ロジックは、マウスのプライマリ ボタンによってトリガーされたときに意図したとおりに動作する可能性がありますが、そのコードが中ボタンがクリックされたときに実行されると、誤検出になります。新しい動作が導入される前は、新しいタブを開くデフォルトのアクションがブロックされ、ユーザーの期待に反していました。ハンドラの開始時に event.button === 0 を明示的にチェックし、その場合にのみコードを実行することもできますが、忘れがちで、その必要性に気付かないこともあります。

必要なコードのみを実行する

誤検出が減る一方で、auxclick コールバックは、実際にプライマリ以外のマウスボタンがクリックされた場合にのみ実行されます。新しいタブを開く前に適切なリンク先 URL を計算する必要があるコードがある場合は、auxclick をリッスンし、そのロジックをコールバックに含めることができます。マウスのメインボタンがクリックされたときに実行されるオーバーヘッドが発生しません。

ブラウザのサポートと互換性

この新しい動作は現在、Chrome 55 でのみ実装されています。最初の提案で述べたように、ウェブ デベロッパー コミュニティからのフィードバック(肯定的なものも否定的なものも)をお待ちしています。標準化プロセスに携わる担当者とフィードバックを共有するには、GitHub の問題を報告するのが最善の方法です。

デベロッパーは、auxclick が広く利用可能になるまで待たなくても、マウスイベントを処理するためのベスト プラクティスに沿って対応できます。click イベント ハンドラの開始時に MouseEvent.button プロパティの値を確認することで、適切なアクションを実行できます。次のパターンでは、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);