web-dev-qa-db-ja.com

JavaScriptを使用したタブキー押下のシミュレーション

ユーザーが何かをクリックしたときにTabキーを押したかのようにブラウザを動作させたいのですが。クリックハンドラーで、次のアプローチを試しました。

var event = document.createEvent('KeyboardEvent');
event.initKeyEvent("keypress", true, true, null, false, false, false, false, 9, 0);
this.input.focus()[0].dispatchEvent(event);

そしてjQuery:

this.input.focus().trigger({ type : 'keypress', which : 9 });

...私が取ったもの ここ

最初のアプローチが最善の策のようですが、うまくいきません。最後の2つのパラメーターを98、98に変更すると、実際、入力ボックスに「b」と入力されます。しかし、9、0、9、9(前者はMDC Webサイトから直接取得したもの)はどちらも、FF3でのfirebugで次のエラーを発生させます。

Permission denied to get property XULElement.popupOpen
[Break on this error] this.input.focus()[0].dispatchEvent(event);

Permission denied to get property XULElement.overrideValue
[Break on this error] this.input.focus()[0].dispatchEvent(event);

Permission denied to get property XULElement.selectedIndex
[Break on this error] this.input.focus()[0].dispatchEvent(event);

Permission denied to set property XULElement.selectedIndex
[Break on this error] this.input.focus()[0].dispatchEvent(event);

そのような(「そのような」の明確な定義がない)イベントは「信頼できない」と聞いたことがあり、これがこれらのエラーを説明している可能性があります。

2番目のアプローチでは、event.whichとして入力した値は、event.whichとして渡されますが、効果はありません(9ではなく98を使用しても、ボックスに「b」は入力されません)。eventを設定しようとすると渡したオブジェクトの.dataは、イベントがトリガーされたときに未定義になります。以下は、それを表示するために使用しているコードです。

$('#hi').keypress(function(e) {
  console.log(e);
});

他のアイデアはありますか?

21
Kev

私が最終的に行った解決策は、手動で管理したい領域のいずれかの側に「フォーカススティーラー」div(tabindex = -1--フォーカスを設定できますが、最初はタブで移動できません)を作成することです。焦点。次に、バブリングの真のイベントリスナーを配置して、領域全体に焦点を合わせてぼかします。エリアにフォーカスが発生すると、tabindex値は-1に変更され、ブラーが発生すると、0に変更されます。つまり、エリアにフォーカスしているときに、タブまたはShiftキーを押しながらタブを外すことができます。正しく他のページ要素またはブラウザUI要素に行き着きますが、そこから焦点を合わせるとすぐに、フォーカススティーラーはタブ可能になり、焦点を合わせると手動領域が正しく設定され、最後の要素に焦点が移ります。手動領域の一方の端またはもう一方の端をクリックしたかのように。

4
Kev

これは、ポップアップカレンダーとポップアップユニット/値の重みセレクターの2つのカスタムコントロールにWebアプリで使用したソリューションです(テキストボックスをクリックすると、2つの選択でdivがポップアップします)

function tab_focus(elem)
  var fields = elem.form.getElements()
  for(var i=0;i<fields.length;i++) {
    if(fields[i].id == elem.id){
      for(i=i+1;i<fields.length;i++){
        if(fields[i].type != 'hidden'){
          fields[i].focus()
          return    
        }
      }
      break;
    }
  }
  elem.form.focusFirstElement();
}

これはPrototypeフレームワークを使用しており、パラメーターとして拡張要素(つまり、$( 'thing_id'))を想定しています。

要素が属するフォームを取得し、それ自体が見つかるまでフォームの要素をループします。

次に、非表示になっていない最初の要素を探し、フォーカスを渡します。

フォームの後に要素がない場合は、フォーカスをフォームの最初の要素に戻します。代わりに、document.formsを介してページ上の次のフォームを見つけることができましたが、ほとんどのページは単一のフォームを使用しています。

3
Tilendor

この問題を解決する 単純なjQueryプラグイン を作成しました。 jQuery UIの「:tabbable」セレクターを使用して、次の「tabbable」要素を見つけて選択します。

使用例:

// Simulate tab key when element is clicked 
$('.myElement').bind('click', function(event){
    $.tabNext();
    return false;
});
1
Mark Lagendijk

実は、メジャーなPITAであっても、道はあると思います。他の人のウィジェットにドロップするので、jQueryを使用して事後にこれらを追加するのではなく、すべての要素が、当然タブストップであっても、何らかの形で適切な順序でXtabindexを持っていることを確認できます。 HTMLまたは他の初期の建築基準法でそれを正しく指定することができます。次に、フォーム全体に実際のタブインデックスが作成されます。フォーカスがありますが、キーの押下を吸収し、タブまたはShift + Tabの場合は、Xtabindexに基づいて偽のフォーカスを移動します。フォームの最後の要素(または最初の要素のShift + Tab)でTabキーを押すと、キーストロークが妨げられないため、ブラウザーはキーボードを使用してフォーム外の他のページまたはブラウザーUI要素に適切にフォーカスできます。

このアプローチがどのような意図しない副作用をもたらすかを推測することしかできません。

実際、それを使用して最後の要素のタブを偽造することはまだできないので、それは解決策でさえありません。

1
Kev

これらのエラーはオートコンプリートによるものだと思います。イベントをディスパッチする前に、オートコンプリート属性を「オフ」に設定することで、それらをオフにできる場合があります。

setAttribute('autocomplete','off')
0
Justin Meyer