JavaScript、Ajax、HTML5(API)、Ruby…Web及び関連技術の実験&情報公開&制作物紹介。

【提案】onkeypressの正しい併用の仕方!

前エントリー(onkeypress、乱用禁止!)からの続きです。
お暇なら、前エントリーからお読みください。

onkeypress イベント属性の正しい指定の仕方を提案します。
主に『onclickと同時にonkeypressイベント属性を指定する場合の正しい指定の仕方』という視点での提案です。
ざっくりとまとめると、対処法としては以下の3パターンがあります。

  1. onkeypressは使わない!(onkeypressの指定を削除する)
  2. onkeypressイベントハンドラにフィルターをかける
  3. その他(個別の対応が必要)

【2007/05/02】追記。

まずは分類

現状はびこっている onkeypress の指定の仕方を分類してみました。
それぞれにたいして、対処法が上述のA?Cのいずれに当てはまるかを後述します。

  1. 初めから onkeypress が単独で使用されている場合
  2. onclick と onkeypress が同時に指定され、その内容が同じの場合
    1. ボタン要素(<input type="button"?>、<button ?>)、およびアンカー要素(<a href="?"?>)の場合
    2. それ以外の要素(<span>、<div>等)の場合
  3. onclick と onkeypress が同時に指定され、その内容が異なる場合

初めから onkeypress が単独で使用されている場合

対処法: C. その他(個別の対応が必要)

元々『onclick 属性を設定した場合は onkeypress 属性を同時に設定することがアクセシビリティ上好ましいとされています』という不確かな情報を元に両方設定している場合に対する対処法の提案なので、この場合は本来対象外です。
ただ必要に応じて、onkeypress で指定しているスクリプトの内容について精査して、前回のエントリーで言及したような
『元々のキーに与えられている機能が抑えられてしまったり、別の機能が与えられてしまったりして、結果的にユーザビリティが低下してしまう』
といったことが起こっていないか検証する必要はあります。

onclick と onkeypress が同時に指定され、その内容が同じの場合

ボタン要素(<input type="button"?>、<button ?>)、およびアンカー要素(<a href="?"?>)の場合

対処法1: A. onkeypressは使わない!(onkeypressの指定を削除する)

一般的なビジュアルブラウザ(ボタンをきちんとボタンの形で表示するブラウザ、要するにほとんどの方が日常使用しているWebブラウザ)では、ボタンの上にフォーカスがあるときに、[Enter]キー・[Return]キー・スペースキーのいずれかが押されると、そのボタンがクリックされたときと同じ動作をするようになっています。
またアンカー(リンク)も、その上にフォーカスがあるときに[Enter]や[Return]を押すと、多くブラウザでやはりクリック時と同じ動作をします。
つまり、これらの要素にはブラウザ本来の機能としてキーボードユーザビリティが提供されているのです。だから、onkeypress属性をわざわざ指定する必要はありません。

対処法2: B. onkeypressイベントハンドラにフィルターをかける

「対処法1」では「不要」と書きましたが、ひょっとしたら、JavaScriptには対応しているけれど基本的なキーボードユーザビリティを提供していない(ボタン上で[Enter]キーを押しても何も動作しない)ブラウザがあるかも知れません。
また、[Enter]キー押下などのキーボード操作では onclick イベントを拾ってくれないブラウザ、というのも存在するかも知れません。
そういったものまで想定するのなら、onkeypress イベント属性の設定は必要です。
ただし、そのまま onclick と同じモノを指定してはもちろんダメ。先述の『元々のキーに与えられている機能が抑えられてしまったり、別の機能が与えられてしまったりして、結果的にユーザビリティが低下してしまう』という現象が起きてしまいますので。
具体的な対処法は、以下のそれ以外の要素(<span>、<div>等)の場合の対処法を参照してください。

それ以外の要素(<span>、<div>等)の場合

対処法: B. onkeypressイベントハンドラにフィルターをかける

これらの要素では、[Enter]や[Return]キーが押されても同じ動作になるというキーボードユーザビリティが初めから提供されているとは限りません。
というより、ブラウザの実装に依りますが、まずそのような機能は提供されていないと考えた方が良いと思います。
(Operaではそのような機能が実装されちゃってますが。)
そこでこれらの要素には、抜本的な対策が必要となります。

例えば、以下のようなソースを想定します:

<script type="text/javascript">
function clickAction() {
    alert('DUMMY!');
}
</script>
<a href="javascript:void(0);" onclick="clickAction();">Click Here!</a>

(説明のしやすさを考えてアンカー要素(<a>)にonclickを指定しました。)
これは実際に表示すると↓こうなります。

Click Here!

「Click Here!」と書かれているリンクをクリックすると、ダイアログで「DUMMY!」と表示されます。
<a>のリンクになっているので、このままでも多くのブラウザでは、リンク上にフォーカスを持っていって[Enter]キーを押せば同じようにダイアログで「DUMMY!」と表示されるはずです。

続いて、onkeypress で全く同じモノを指定してみましょう。

<script type="text/javascript">
function clickAction() {
    alert('DUMMY!');
}
</script>
<a href="javascript:void(0);" onclick="clickAction();" onkeypress="clickAction();">Click Here!</a>

表示は↓、見た目は同じです。

Click Here!

クリックしたときの動作も同じです。
でも、キーを押したとき、特に[Enter]キー以外を押したときの動作に注意。
例えば、[Tab]キーか、スペースキーを押してみましょう。
少なくともいずれかの場合に、やはり「DUMMY!」というダイアログが表示されてしまったのではないでしょうか?
これが、『元々のキーに別の機能が与えられてしまってユーザビリティが低下している状態』です。
([Tab]キーは「次のリンクに移る」、スペースキーは「画面下へスクロール」という機能が期待されるキーです。)

ここからが本題。このonkeypressイベントに、フィルターをかけます。
ここでいうフィルターとは、「どのキーが押されたかによって処理を分けること」という意味です。
具体的には↓こうします。

<script type="text/javascript">
function keyPressFilter(evt) {
    var keyCode;
    if (evt) {
        keyCode = evt.keyCode;
    } else {
        keyCode = event.keyCode;
    }
    // ↓[Enter]キーが押されたかどうかの判定
    if (keyCode != 10 && keyCode != 13) {
        return true;
    } else {
        clickAction();
        return false;
    }
}
function clickAction() {
    alert('DUMMY!');
}
</script>
<a href="javascript:void(0);" onclick="clickAction();" onkeypress="return keyPressFilter(event);">Click Here!</a>

少々長くなってしまいました。
でも見た目は↓やはり何ら変わりはありません。

Click Here!

クリックしたときの動作も同じです。
そして、キーを押したときの動作はというと。
リンク上にフォーカスがある状態で[Enter]以外のキーが押されても、ダイアログは出現せず、そのキー本来の機能が有効になっているのが確認できると思います。

ポイントは、ソース中に「// ↓[Enter]キーが押されたかどうかの判定」と書かれている箇所。
ここで、押されたキーがキーコードの10番もしくは13番(=いずれかが[Enter]キー。通常13番)に該当するかどうかを判定しています。
該当しなければ、イベント処理をスルー(return true;)し、該当すれば onclick のときと同じイベントハンドラを呼び出しています。
これによって、[Enter]キーが押されたときだけ目的の処理が行われるようになりました。

一応、念のため。
なぜ[Enter]キーのときだけ、としたかというと。
『リンクをクリックする』という操作に対応するキーボード操作として一番妥当なのが『[Enter]キーを押下する』だと思われるからです。
これがボタンなら、つまり『ボタンをクリックする』なら、他に『スペースキーを押下する』も選択肢にくわえなければならないでしょう。
スペースキーのキーコードは通常32番なので、先ほどの条件分岐を以下のようにする必要があります。

     :
    // ↓[Enter]キーもしくはスペースキーが押されたかどうかの判定
    if (keyCode != 10 && keyCode != 13 && keyCode != 32) {
     :

onclick と onkeypress が同時に指定され、その内容が異なる場合

対処法: C. その他(個別の対応が必要)

この場合は、「onkeypress の場合は onclick とは別の動作をする」という指定か、初めから「特定のキーが押されたときにだけ onclick と同じ動作をする」という指定がされているものとおもわれます。
そうならば、おそらく何の対処も要らないと思われます。
一応、onkeypress で指定されているイベントハンドラの内部を検証する必要はあると思います。

まとめ

基本的には、「onclick 属性のしてある要素に onkeypress も指定する」という思想は、現状では妄信に近いものです。
めんどくさければ「onclick を指定してあれば onkeypress は指定しない」のが一番です。onclick が指定されていれば、世の中のWebサイト閲覧者の9割は(例えキーボード操作を強いられようとも)そんなに困らないような作りになっていますから。つまりその方がよっぽど『高ユーザビリティを保てるようになっている』のですから。

それでも、より高い操作性を求めたり、将来的なモノを見越したりして、「キーボード操作でもマウス操作と同じユーザビリティを提供しているんだということを、ソースに明確に記述することで示したい」という方は、ぜひこの記事を参考にしてください。

また「現状、何も知らずに言われるがママに『onclickとonkeypressを併用』しちゃってるけれど、どうしたらよいでしょう?」という方には、現状を多少なりとも改善する方法、ただし今回のエントリーのようなめんどくさい記述ができる限り不要な解決方法を改めてご紹介(ご提供)する予定です次のエントリーでご紹介(ご提供)します
(少々お待ちを。。。)

onkeypressをお行儀良くする追加スクリプト

カテゴリ

月別 アーカイブ

OpenID対応しています OpenIDについて

このブログ記事について

このページは、あんちもん2が2007年4月30日 10:43に書いたブログ記事です。

ひとつ前のブログ記事は「onkeypress、乱用禁止!」です。

次のブログ記事は「onkeypressをお行儀良くする追加スクリプト」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。