CSSの「:hover」をアクティブにする純粋なJavaScriptでマウスオーバーをシミュレートするにはどうすればよいですか?


82

mouseoverChromeでシミュレートするコードを見つけようとしていますが、「マウスオーバー」リスナーが起動されても、CSSの「ホバー」宣言が設定されることはありません。

私もやってみました:

//Called within mouseover listener
theElement.classList.add("hover");

しかし、要素をそのhover宣言で宣言されているものに変更するものは何もないようです。

これは可能ですか?


6
@PSL彼がやりたいのは:hover、要素の状態を強制することだと思います。
Benjamin Gruenbaum 2013年

1
@BenjaminGruenbaumうんあなたは正しい。私は誤解しました。
PSL 2013年

1
これは重複ではありません。もう1つの質問はjQueryについてです。この質問は純粋なJSについてです。
チャックルバット2014

1
@MonkOQにはjQueryタグが含まれていました。これは重複しています。
JasonMArcher 2014

1
@JasonMArcher質問(およびその回答)は純粋なJSに関するものです。彼らがそれを間違えた可能性が高いと思いませんか。
チャックルバット2014

回答:


106

できません。信頼できるイベントではありません。

ユーザー操作の結果として、またはDOMの変更の直接の結果として、ユーザーエージェントによって生成されたイベントは、DocumentEvent.createEventを介してスクリプトによって生成されたイベントに付与されない特権を持つユーザーエージェントによって信頼されます。 ( "Event")メソッド、Event.initEvent()メソッドを使用して変更、またはEventTarget.dispatchEvent()メソッドを介してディスパッチされます。信頼できるイベントのisTrusted属性の値はtrueですが、信頼できないイベントのisTrusted属性の値はfalseです。

クリックイベントまたはDOMActivateイベントを除いて、ほとんどの信頼できないイベントはデフォルトのアクションをトリガーしないはずです

クラスを追加し、mouseover / mouseoutイベントで手動で追加/削除する必要があります。


4
@ティム、それは実際には理由に答えていません。それは質問を変えるだけです。
Pacerier 2015年

7
@Pacerierは、ユーザーによって開始されたものではないため、信頼できるイベントではありません。それはそう言う権利が私の答えでは上記の引用で。それは文字通り答えが始まるものです。
Benjamin Gruenbaum 2015年

1
@BenjaminGruenbaum、「クリックイベントまたはDOMActivateイベントを除い」を引用しています。この例外リストに含まれないほど「ホバー」の特別な点は何ですか?「フォーカス」と呼んでも「ホバー」と呼べないのはなぜですか?これらは私たちが答えなければならない質問です他の何かに答えることはただ質問を変えることです。
Pacerier 2015年

1
ホバー(およびドラッグアンドドロップのクリックまたはマウスの上下と組み合わせて)は、ユーザーのシステムを乗っ取ったように動作または表示される可能性があるため(自動化のケースを無視した場合)、サポートするのは理想的ではないと思います。[言うことはできませんが]をクリックすると、ターゲットのフォームフィールドまたは要素にオートフォーカスできるようになります。たとえば、データが欠落しているか正しくないテキストフィールド(フォームフィールドの検証チェックなど)など、サイトデザイナーがユーザーにフォーカスしてもらいたい場合です。しかし、それは私の仮定です。
デビッド

2
はい、ばかげているように聞こえますが、フォーカスがユーザーの操作によって引き起こされたように見せることができます。実際には、ブラウザAPIは喜んで仕様に違反し、フォーカスを無視して、信頼できないイベントとしてクリックします(少なくともChrome)。たとえば、Chrome拡張機能の拡張機能インストールボタンのクリックをシミュレートして、何が起こるかを確認してください:)
Benjamin Gruenbaum 2015

37

次のようにマウスオーバーイベントをシミュレートできます。

HTML

<div id="name">My Name</div>

JavaScript

var element = document.getElementById('name');
element.addEventListener('mouseover', function() {
  console.log('Event triggered');
});

var event = new MouseEvent('mouseover', {
  'view': window,
  'bubbles': true,
  'cancelable': true
});

element.dispatchEvent(event);

おかげで、私が必要としたのは泡だけでした!開発者コンソールのインスペクターで要素を右クリックし、「コンソールで使用」(Firefox)または「グローバル変数として保存」(Chrome)を実行します。次に、たとえば temp0.dispatchEvent(new MouseEvent('mouseover', {bubbles: true})) 、マウスオーバーでのみ表示されるツールチップやその他のコンテンツのスタイリングに非常に役立ちます。
デニス・ハウ

これは素晴らしいです。
rebelliard

1
@DenisHoweそのユースケースについては:hov、devtoolsのスタイルインスペクターの上部にあるボタンを確認する必要があります。これにより、検査対象の要素で任意の疑似クラスをアクティブ化できます。
ハロー

17

バックグラウンド

自動テストを作成しようとしているときにこの質問に遭遇し、特定のページの特定の要素セットがすべて受信し、ホバーイベントでcssによって設定されたcssプロパティのセットがあることを確認しました。

上記の回答は完全に説明していますが、JSによってホバーイベントをトリガーしてから対象のcss値をプローブすることができない理由は、最初の質問「CSSをアクティブ化する純粋なJavaScriptでマウスオーバーをシミュレートするにはどうすればよいですか」に回答します。 :ホバー」?」部分的にのみ。

免責事項

これはパフォーマンスの高いソリューションではありません。パフォーマンスが問題にならない自動テストにのみ使用します。

解決

simulateCssEvent = function(type){
    var id = 'simulatedStyle';

    var generateEvent = function(selector){
        var style = "";
        for (var i in document.styleSheets) {
            var rules = document.styleSheets[i].cssRules;
            for (var r in rules) {
                if(rules[r].cssText && rules[r].selectorText){
                    if(rules[r].selectorText.indexOf(selector) > -1){
                        var regex = new RegExp(selector,"g")
                        var text = rules[r].cssText.replace(regex,"");
                        style += text+"\n";
                    }
                }
            }
        }
        $("head").append("<style id="+id+">"+style+"</style>");
    };

    var stopEvent = function(){
        $("#"+id).remove();
    };

    switch(type) {
        case "hover":
            return generateEvent(":hover");
        case "stop":
            return stopEvent();
    }
}

説明

generateEventは、すべてのcssファイルを読み取り、:hoverを空の文字列に置き換えて適用します。これには、すべての:hoverスタイルが適用されるという効果があります。これで、ハウリングされたスタイルをプローブし、シミュレーションを停止して初期状態に戻すことができます。

シートからを取得してelement.css(...)を実行することにより、対象の要素だけでなくドキュメント全体にホバー効果を適用するのはなぜですか?

そのようにすると、スタイルはインラインで適用され、これは他のスタイルをオーバーライドしますが、元のcssホバースタイルではオーバーライドされない可能性があります。

単一の要素のホバーをどのようにシミュレートしますか?

これはパフォーマンスが良くないので、しない方がよいでしょう。必要に応じて、そのスタイルが要素に適用されるかどうかをelement.is(selectorOfInterest)で確認し、それらのスタイルのみを使用することができます。

ジャスミンでは、たとえば次のことを実行できます。

describe("Simulate CSS Event", function() {
    it("Simulate Link Hover", function () {
      expect($("a").css("text-decoration")).toBe("none");
      simulateCssEvent('hover');
      expect($("a").css("text-decoration")).toBe("underline");
      simulateCssEvent('stop');
      expect($("a").css("text-decoration")).toBe("none");
    });
});

1
この答えは素晴らしいです!残念ながら、Chromeがクロスオリジンリクエストへのアクセスを制限しているため、他のホストから提供されたスタイルシートのあるページのChromeの最近のバージョンでは失敗します。この:)をサポートするソリューションのための私の答えを参照してください
FThompson

6

この場合、私が通常行うことは、javascript ..を使用してクラスを追加し、このクラスに同じCSSものをアタッチすることです。:hover

使ってみてください

theElement.addEventListener('onmouseover', 
    function(){ theElement.className += ' hovered' });

または古いブラウザの場合:

theElement.onmouseover = function(){theElement.className += ' hovered'};

もちろんonmouseout、要素を離れるときに「ホバーされた」クラスを削除するために使用する必要があります。


これはOPが要求することを実行しませんが、おそらく正しい方向に沿って多かれ少なかれです。最新のイベントハンドラーアタッチメント手法を使用することをお勧めします。
とがった2013年

申し訳ありませんが、誤解されている質問
Yotam Omer 2013年

@Pointyの質問は、純粋なjavascriptを要求します。それ以外の方法でイベントを添付するにはどうすればよいですか?
Yotam Omer 2013

2
十分じゃない?これは「純粋な」JavaScriptであり、実際にはイベントのハンドラーとして関数をアタッチします。Internet Explorerでは、(ほぼ)同等のものattachEvent()が使用されます。
とがった2013年

言及する価値があります。IE9と10がサポートされてaddEventListenerおり、イベントを添付するのに最適な方法attachEventです。シミングはIE8(およびそれ以下)でのみ必要です。Yotam、onmouseover属性を直接設定して(イベントリスナーを追加するのではなく)別のハンドラーを追加すると、現在設定されているイベントが上書きされます。違いについては、この質問を参照してください。
Benjamin Gruenbaum 2013年

4

CSS疑似クラスを要素に適用できるライブラリであるpseudo:stylerを使用できます。

(async () => {
  let styler = new PseudoStyler();
  await styler.loadDocumentStyles();
  document.getElementById('button').addEventListener('click', () => {
    const element = document.getElementById('test')
    styler.toggleStyle(element, ':hover');
  })
})();

免責事項:私はこのライブラリの共著者です。特に、ページのCSSルールを制御できない可能性のあるChrome拡張機能で使用するために、クロスオリジンスタイルシートを追加でサポートするように設計されています。


1
これはwindow.getComputedStyle(<youElement>)、疑似スタイルを設定した後で組み合わせた場合でも、実際にはかなりうまく機能しているようです。ありがとう!
Daniel Veihelmann

2

dom操作後にCSSを検査することを想定していますが、マウスをdevtoolsに戻すとすぐに、そのhtml要素でイベントがアクティブになりません。おそらく、JavaScriptイベント用のdevtoolsに:hoverオプションのようなものが必要です。それは存在しませんが、シミュレートすることができます。

  1. devtoolsを開き、クリックしてアクティブにします。
  2. 関心のある要素でイベントをトリガーします。
  3. マウスを動かさずに、ctrl + shift + pでdevtoolsコマンドパネルを開き、キーボードで「JavaScriptを無効にする」を選択します。

javascriptが無効になっているため、要素を再度変更する機会はありません。devtoolsに移動して、ホバーしたり、クリックしたり、何か他のことをしたりしているかのように、cssとhtmlを調べることができます。完了したら、もう一度コマンドパネルに移動し、[JavaScriptを有効にする]を選択します。


きちんとしたテクニックですが、私があなたの意図を誤解しない限り、これすでにdevtoolsに存在します!Chrome / ChromiumとFirefoxのdevtoolsの両方:hovで、スタイルインスペクターの上部([フィルター]入力ボックスの横)にボタンがあります。クリックすると:hov:それぞれが擬似クラスで標識し、チェックボックスのシリーズを展開し:active:focus:focus-within:hover、と:visited。そして、これらのボックスのいずれかをチェックすると、検査対象の要素でそれぞれの疑似クラスがアクティブになります。
ハロー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.