web-dev-qa-db-ja.com

Chromeでのキーダウンシミュレーションは正常に起動しますが、正しいキーではありません

HTMLページの特定のtextarea要素でキーダウンイベントをシミュレートしたいです。クロムを使用しているので、変数でinitKeyboardEventを呼び出し、テキスト領域に入力するkeyCodeを渡しました。ここに私が試したものがあります:

var keyEvent = document.createEvent('KeyboardEvent');
keyEvent.initKeyboardEvent('keydown', true, false, null, 0, false, 0, false, 77, 0);
inputNode.dispatchEvent(keyEvent);

このコードでは、文字mを入力していますが、textareaはkeyCode 13これはEnterキーです。そこで、オンラインで見た値をkeyCodeValに設定するオーバーライドコードを試しましたが、成功しませんでした

var keyEvent = document.createEvent('KeyboardEvent');
Object.defineProperty(keyEvent, 'keyCode', { 
                         get : function() {
                                 return this.keyCodeVal;
                         }
                        });
keyEvent.initKeyboardEvent('keydown', true, false, null, 0, false, 0, false, 77, 0);
keyEvent.keyCodeVal = 77;
inputNode.dispatchEvent(keyEvent);

誰もがkeyCode値を設定する方法を知っていますか?

27
fabricemarcelin

とても近い...

「which」プロパティをオーバーライドする必要がありました。サンプルコードを次に示します。

Podium = {};
Podium.keydown = function(k) {
    var oEvent = document.createEvent('KeyboardEvent');

    // Chromium Hack
    Object.defineProperty(oEvent, 'keyCode', {
                get : function() {
                    return this.keyCodeVal;
                }
    });     
    Object.defineProperty(oEvent, 'which', {
                get : function() {
                    return this.keyCodeVal;
                }
    });     

    if (oEvent.initKeyboardEvent) {
        oEvent.initKeyboardEvent("keydown", true, true, document.defaultView, false, false, false, false, k, k);
    } else {
        oEvent.initKeyEvent("keydown", true, true, document.defaultView, false, false, false, false, k, 0);
    }

    oEvent.keyCodeVal = k;

    if (oEvent.keyCode !== k) {
        alert("keyCode mismatch " + oEvent.keyCode + "(" + oEvent.which + ")");
    }

    document.dispatchEvent(oEvent);
}

サンプル使用法:

Podium.keydown(65);

注:このコードは、IE、Safari、またはその他のブラウザーで動作するようには設計されていません。まあ、多分Firefoxで。 YMMV。

80
Orwellophile

Orwellophileのソリューションは機能します。

  • 最初: 'keyCode'、 'charCode'、および 'which'はSafariおよびIE9 +で読み取り専用です(少なくとも)。
  • 2番目:initKeyboardEventはやや面倒です。すべてのブラウザは異なる方法で実装します。 Webkitでも、initKeyboardEventのいくつかの異なる実装があります。また、OperaのinitKeyboardEventに「良い」方法はありません。
  • 3番目:initKeyboardEventは非推奨です。 initKeyEventまたはKeyboardEventコンストラクターを使用する必要があります。

ここで ブラウザ間のinitKeyboardEvent関数 (要点)を記述しました:

例:

var a = window.crossBrowser_initKeyboardEvent("keypress", {"key": 1, "char": "!", shiftKey: true})
alert(a.type + " | " + a.key + " | " + a.char + " | " + a.shiftKey)

そして、ここに私の DOMキーボードイベントレベル3ポリフィル クロスブラウザKeyboardEventコンストラクターがあります。

例:

var a = new KeyboardEvent("keypress", {"key": 1, "char": "!", shiftKey: true})
alert(a.type + " | " + a.key + " | " + a.char + " | " + a.shiftKey)

例2

重要なメモ1:charCode、keyCode、およびどのプロパティが非推奨になりました。したがって、crossBrowser_initKeyboardEvent no KeyboardEventコンストラクターも、一部のブラウザーではそのプロパティの正しい値が絶対に保証されていません。代わりにプロパティ「key」と「char」を使用するか、my Gist を編集して、読み取り専用charCode、keyCode、およびどのプロパティを持つブラウザーでinitEventを強制的に使用できます。

重要な注意2:keypressイベントは非推奨であり、現在のところ Keyboard Event Level 3 polyfill ではサポートされていません。つまり、keypressイベントのkeyおよびcharプロパティはランダムな値を持つことができます。この問題を下位互換性に修正する作業を行っています。

14
termi

@OrwellophileのスクリプトをGoogleで動作させるには、Chrome 26.0.1410.65(Mac OS X 10.7.5では、それが重要な場合))、1行変更する必要がありました。 initKeyboardEventのMDNドキュメント とは異なる順序でのinitKeyboardEventのパラメーター。

変更された行は次のようになります。

oEvent.initKeyboardEvent("keydown", true, true, document.defaultView, k, k, "", "", false, "");
4
Dave Land

パラメータのヒントを提供してくれた@dlandにも感謝します。ここで、適切な場所でイベントを発生させることができない場合に役立つと思います。

@Orwellophileのスクリプトは、ドキュメントでイベントを発生させます。イベントリスナーがdocumentに常に登録されているとは限りません。最後の行を次の行に変更しましたが、今では毎回ほとんど動作します。

document.activeElement.dispatchEvent(oEvent);

document.activeElementは常に、ユーザーが現在フォーカスしている要素でイベントを発生させます。

3
Ankit

上記のソリューションはすべて機能していますが、機能しないケースが1つあります。

Dartが使用されている場合、KeyboardEventsを使用するDartコードは一般的なイベントでは機能しません。

Get $ keyCodeが未定義のようなものが得られます。

これで何時間も頭を叩いた後、私は次のトリックを見つけました:

function __triggerKeyboardEvent(el, keyCode)
{
   var eventObj = document.createEventObject ?
       document.createEventObject() : document.createEvent("Events");

   var tempKeyboardObj = document.createEvent("KeyboardEvents");

   if(eventObj.initEvent){
      eventObj.initEvent("keydown", true, true);
   }
   eventObj.___Dart_dispatch_record_ZxYxX_0_ = tempKeyboardObj.___Dart_dispatch_record_ZxYxX_0_
   eventObj.keyCode = keyCode;
   eventObj.which = keyCode;

   el.dispatchEvent ? el.dispatchEvent(eventObj) : el.fireEvent("onkeydown", eventObj);

} 

Dartインターセプターをだましてイベントを実際にKeyboardEventにすることは、トリックを行いました。

WebkitベースのブラウザでDartアプリをテストしようとしている貧しい人のために、ここに置いておきます。

0
Fruch