マウスがjQueryの要素の上にあるかどうかを確認するにはどうすればよいですか?


265

これをjQueryですばやく簡単に行う方法はありますか?

マウスオーバーイベントは他の目的で既に使用しているため、使用したくありません。マウスが特定の瞬間に要素の上にあるかどうかを知る必要があるだけです。

「IsMouseOver」関数があった場合のみ、私はこのようなことをしたいと思います。

function hideTip(oi) {
    setTimeout(function() { if (!IsMouseOver(oi)) $(oi).fadeOut(); }, 100);
}

5
ほとんどの目的では、与えられた答えで十分ですが、マウスイン/アウトでは不十分な場合があります。たとえば、マウスがメニューヘッドまたはメニューボディのいずれかの上にないときにメニューを非表示にします。
マーカスダウニング

私は回答で説明されている方法を使用して、アニメーション化された遅延クローズドロップダウンを開くアイコン(ボタン境界のマウスイベント)を操作しました。アイコンとドロップダウンの両方で遅延/キャンセル遅延を処理するには、jqueryのtriggerHandlerメソッドを使用します。完全に十分です。
mothmonsterman 2009

#マーカス:メニューを非表示にする場合、それについてより良い方法は何ですか?
coderama

私の答えを参照してくださいstackoverflow.com/questions/9827095/...
Sanne

最良の答えが解決策としてマークされていれば、私はこれに投票したでしょう。
BBaysinger

回答:


97

マウスアウトでタイムアウトを設定してフェードアウトし、戻り値をオブジェクトのデータに保存します。次に、データに値がある場合は、マウスオーバーでタイムアウトをキャンセルします。

フェードアウトのコールバック時にデータを削除します。

子のマウスオーバー/マウスアウトが発生したときにメニューに対して起動しないため、mouseenter / mouseleaveを使用する方が実際には安価です。


7
@Arthurがここでやった、まだもっと情報が必要ですか?stackoverflow.com/a/1670561/152640
mothmonsterman

270

このコードは、ハッピータイムハリーと私が言おうとしていることを示しています。マウスが入るとツールチップが表示され、マウスが離れるとツールチップが消えるまでの遅延が設定されます。遅延がトリガーされる前にマウスが同じ要素に入ると、前に保存したデータを使用してトリガーが消える前に破棄します。

$("someelement").mouseenter(function(){
    clearTimeout($(this).data('timeoutId'));
    $(this).find(".tooltip").fadeIn("slow");
}).mouseleave(function(){
    var someElement = $(this),
        timeoutId = setTimeout(function(){
            someElement.find(".tooltip").fadeOut("slow");
        }, 650);
    //set the timeoutId, allowing us to clear this trigger if the mouse comes back over
    someElement.data('timeoutId', timeoutId); 
});


126

警告:is(':hover')jquery 1.8以降では非推奨です。解決策については、この投稿を参照してください。

次の回答を使用することもできます:https : //stackoverflow.com/a/6035278/8843で、マウスが要素の上にあるかどうかをテストします。

$('#test').click(function() {
    if ($('#hello').is(':hover')) {
        alert('hello');
    }
});

5
これは...(アフィク)どこにも文書化されていないと(メニューなど)を動的に示す要素を持つ正確ではないようです
lambinator

12
jQuery 1.9.1の時点で壊れています!! 代わりにIvoのソリューションを使用してください
mathheadinclouds 2013年

1
キャッチされなかったエラー:構文エラー、認識されない式:サポートされていない疑似:ホバー
Julio Marins、2015年

1
警告:hover有効なjQueryセレクタではありません: api.jquery.com/category/selectors(ソース:bugs.jquery.com/ticket/11574
Pang

1
ブラウザがサポートしている場合は引き続き機能しますdocument.querySelectorAll(':hover')
ekuusela

34

jQueryのhoverイベントを使用して、手動で追跡できます。

$(...).hover(
    function() { $.data(this, 'hover', true); },
    function() { $.data(this, 'hover', false); }
).data('hover', false);

if ($(something).data('hover'))
    //Hovered!

1
なぜdata()を使用し、add / removeclass()を使用しないのですか?1つは他よりもパフォーマンスが高いですか?
psychotik 2010年

2
@psychotik:はい。$.data文字列操作は含まれません。
10

:私はクラスでこれを包んstackoverflow.com/questions/1273566/...
ripper234

24

私はこれとまったく同じものが必要だったので(少し複雑な環境で、「mouseenter」と「mouseleaves」の多くが適切に機能していなかったソリューションでは)、メソッドismouseoverを追加する小さなjqueryプラグインを作成しました。これまでのところ、かなりうまくいきました。

//jQuery ismouseover  method
(function($){ 
    $.mlp = {x:0,y:0}; // Mouse Last Position
    function documentHandler(){
        var $current = this === document ? $(this) : $(this).contents();
        $current.mousemove(function(e){jQuery.mlp = {x:e.pageX,y:e.pageY}});
        $current.find("iframe").load(documentHandler);
    }
    $(documentHandler);
    $.fn.ismouseover = function(overThis) {  
        var result = false;
        this.eq(0).each(function() {  
                var $current = $(this).is("iframe") ? $(this).contents().find("body") : $(this);
                var offset = $current.offset();             
                result =    offset.left<=$.mlp.x && offset.left + $current.outerWidth() > $.mlp.x &&
                            offset.top<=$.mlp.y && offset.top + $current.outerHeight() > $.mlp.y;
        });  
        return result;
    };  
})(jQuery);

次に、ドキュメントの任意の場所で次のように呼び出して、trueまたはfalseを返します。

$("#player").ismouseover()

IE7 +、Chrome 1 +、Firefox 4でテストし、正常に動作しています。


mouseenter(Chrome)では動作しないようです-codepen.io/anon/pen/kcypB
wrygiel

完璧です。不透明度オーバーレイで要素の下にあるオブジェクトをターゲティングする問題を解決する、即座に呼び出される関数式(IIFE)。鮮やかさ!これありがとう。
Alexander Dixon

10

jQueryでは.is( ':hover')を使用できるため、

function IsMouseOver(oi)
{
   return $(oi).is(':hover');
}

OPで要求された機能を提供する最も簡潔な方法になります。

注:上記はIE8以下では機能しません

IE8で機能する簡潔な代替手段として(IE9のIE8モードを信頼できる場合)、$(...).hover(...)場所全体をトリガーせず、要素のセレクターを知る必要もありません(その場合、Ivoの回答の方が簡単です)。

function IsMouseOver(oi)
{
    return oi.length && 
           oi.parent()
             .find(':hover')
             .filter(function(s){return oi[0]==this})
             .length > 0;
}

これは有効なjQueryセレクタではありません!人々はこの方法を提案するのをやめなければなりません。それはどこにでもあり、IE8と互換性がありません。
サンネ14

IE8の解決策については、他の回答を参照してください
サンネ14

2
ので、それは好奇心旺盛だ@Sanne $(':hover') IE8で仕事を。これは有効なCSS2疑似セレクターなので、機能するはずです。
2014

7

私はSLaksのアイデアを取り入れ、それを少人数のクラスにまとめました。

function HoverWatcher(selector){
  this.hovering = false;
  var self = this; 

  this.isHoveringOver = function() { 
    return self.hovering; 
  } 

    $(selector).hover(function() { 
      self.hovering = true; 
    }, function() { 
      self.hovering = false; 
    }) 
} 

var box1Watcher = new HoverWatcher('#box1');
var box2Watcher = new HoverWatcher('#box2');



$('#container').click(function() {
  alert("box1.hover = " + box1Watcher.isHoveringOver() +
        ", box2.hover = " + box2Watcher.isHoveringOver());
});

6

これの将来の発見者のためにちょうど参考にしてください。

私はこれとそれ以上のことができるjQueryプラグインを作成しました。私のプラグインでは、現在カーソルが置かれているすべての要素を取得するには、単に次のようにします。

$.cursor("isHover"); // will return jQ object of all elements the cursor is 
                     // currently over & doesn't require timer

先ほど触れたように、他にもたくさんの用途があります。

ここでjsFiddleが見つかりました


5

コメントできないので、これを答えとして書きます!

CSSセレクター ":hover"とホバーイベントの違いを理解してください!

":hover"はcssセレクターであり$("#elementId").is(":hover")、このように使用すると実際にイベントとともに削除されましたが、その意味ではjQueryイベントホバーとはまったく関係ありません。

コード化した$("#elementId:hover")場合、要素はマウスでホバーしたときにのみ選択されます。上記のステートメントは、純粋で正当なcss選択でこの要素を選択するときに、すべてのjQueryバージョンで機能します。

一方、イベントホバーは

$("#elementId").hover(
     function() { 
         doSomething(); 
     }
); 

実際、jQuery 1.8として非推奨になりました。ここでは、jQuery Webサイトの状態です。

イベント名「hover」が使用されている場合、イベントサブシステムはイベント文字列で「mouseenter mouseleave」に変換します。これはいくつかの理由で迷惑です:

セマンティクス:ホバリングは、マウスが要素に出入りすることと同じではありません。発砲する前に、ある程度の減速または遅延があることを意味します。イベント名:添付されたハンドラーによって返されるevent.typeはホバーではなく、mouseenterまたはmouseleaveのいずれかです。他のイベントはこれを行いません。「hover」の名前の併用:「hover」という名前のイベントを添付して、.trigger( "hover")を使用してイベントを起動することはできません。ドキュメントはすでにこの名前を「新しいコードには強く非推奨」と呼んでいますが、正式には1.8で非推奨にし、最終的には削除したいと思います。

彼らが使用法を削除した理由is( ":hover")は不明ですが、まあ、あなたはまだ上記のように使用できます。

(function ($) {
   /** 
    * :hover selector was removed from jQuery 1.8+ and cannot be used with .is(":hover") 
    * but using it in this way it works as :hover is css selector! 
    *
    **/
    $.fn.isMouseOver = function() {
        return $(this).parent().find($(this).selector + ":hover").length > 0;
    };
})(jQuery);

ああ、私タイムアウトバージョンを推奨ません。これは非常に複雑になるためです。他に方法がない場合は、この種のものにタイムアウト機能を使用し、すべての場合の95%で別の方法があると信じてください。

私がそこのカップルの人々を助けることができれば幸いです。

グリーツアンディ


2

お二人に感謝します。ある時点で、マウスがまだ要素の上にあるかどうかを検出しようとするのをやめなければなりませんでした。私はそれが可能であることを知っていますが、達成するには多くのコードが必要になる場合があります。

少し時間がかかりましたが、私はあなたの両方の提案を受け入れ、私に役立つ何かを思いつきました。

簡単な(ただし機能的な)例を次に示します。

$("[HoverHelp]").hover (
    function () {
        var HelpID = "#" + $(this).attr("HoverHelp");
        $(HelpID).css("top", $(this).position().top + 25);
        $(HelpID).css("left", $(this).position().left);
        $(HelpID).attr("fadeout", "false");
        $(HelpID).fadeIn();
    },
    function () {
        var HelpID = "#" + $(this).attr("HoverHelp");
        $(HelpID).attr("fadeout", "true");
        setTimeout(function() { if ($(HelpID).attr("fadeout") == "true") $(HelpID).fadeOut(); }, 100);
    }
);

そして、これをいくつかのテキストで機能させるには、これが私がしなければならないすべてです:

<div id="tip_TextHelp" style="display: none;">This help text will show up on a mouseover, and fade away 100 milliseconds after a mouseout.</div>

This is a <span class="Help" HoverHelp="tip_TextHelp">mouse over</span> effect.

多くの豪華なCSSとともに、これはいくつかの非常に素晴らしいマウスオーバーヘルプツールチップを許可します。ちなみに、チェックボックスとテキストの間にわずかな隙間があるため、マウスを動かすとヘルプが点滅するため、マウスアウトの遅延が必要でした。しかし、これは魅力のように機能します。フォーカス/ぼかしイベントについても同様のことを行いました。


2

私はこれに使用されるタイムアウトをよく見ますが、イベントのコンテキストでは、次のように座標を見ることができませんか?:

function areXYInside(e){  
        var w=e.target.offsetWidth;
        var h=e.target.offsetHeight;
        var x=e.offsetX;
        var y=e.offsetY;
        return !(x<0 || x>=w || y<0 || y>=h);
}

コンテキストによっては、areXYInside(e)を呼び出す前に(this == e.target)を確認する必要がある場合があります。

fyi-私はdragLeaveハンドラー内でこのアプローチを使用して、子要素に移動することによってdragLeaveイベントがトリガーされなかったことを確認しています。まだ親要素内にいることを何らかの方法で確認しないと、本当に親を離れた場合にのみ意図されているアクションを誤って実行する可能性があります。

編集:これは良いアイデアですが、一貫して十分に機能しません。おそらく、いくつかの小さな調整が必要です。


2

jQuery子divに特定のクラスがあるかどうかをテストできます。次に、特定のdivの上にマウスを置いたり外したりしたときにそのクラスを適用することで、ページ上の別の要素の上にマウスを置いた場合でも、マウスがその上にあるかどうかをテストできます。ポップアップでdivの間にスペースがあったため、これを使用しました。ポップアップのスペースの上にマウスを移動しているときではなく、ポップアップから離れたときにポップアップを閉じたいだけでした。したがって、コンテンツdiv(ポップアップが終了した)でマウスオーバー関数を呼び出しましたが、コンテンツdivにマウスオーバーしたときにポップアップ関数の外側にあるときにのみ、閉じる関数がトリガーされました!

$( "。pop-up")。mouseover(function(e)
    {
    $(this).addClass( "over");
    });

$( "。pop-up")。mouseout(function(e)
    {
    $(this).removeClass( "over");
    });


$( "#mainContent")。mouseover(function(e){
            if(!$( "。expanded")。hasClass( "over")){
            Drupal.dhtmlMenu.toggleMenu($( "。expanded"));
        }
    });


2

これが最も簡単な方法です。

  function(oi) 
  {
   if(!$(oi).is(':hover')){$(oi).fadeOut(100);}
  }

2

jqueryに依存せず、ネイティブDOM matches APIを使用する手法を次に示します。ベンダープレフィックスを使用して、IE9に戻るブラウザーをサポートします。詳細については、caniuse.comのmatchselectorを参照してください。

まず、次のように、matchesSelector関数を作成します。

var matchesSelector = (function(ElementPrototype) {
var fn = ElementPrototype.matches ||
          ElementPrototype.webkitMatchesSelector ||
          ElementPrototype.mozMatchesSelector ||
          ElementPrototype.msMatchesSelector;

return function(element, selector) {
  return fn.call(element, selector);
};

})(Element.prototype);

次に、ホバーを検出するには:

var mouseIsOver = matchesSelector(element, ':hover');

1

私はあなたが必要とするかもしれないすべての詳細で、別の質問でこれに答えました:

jQueryを使用して要素にホバーしているIFを検出します(執筆時点では99の賛成票があります)。

基本的には、次のようなことができます。

var ishovered = oi.is(":hover");

これoiは、が1つの要素を含むjQueryオブジェクトである場合にのみ機能します。一致する要素が複数ある場合は、各要素に適用する必要があります。次に例を示します。

var hoveredItem = !!$('ol>li').filter(function() { return $(this).is(":hover"); });
                  // not .filter(':hover'), as we can't apply :hover on multiple elements

これはjQuery 1.7以降でテストされました。


1

マウスが要素内にあるかどうかを確認するのに役立つ関数を次に示します。あなたがしなければならない唯一のことは、ライブマウスに関連付けられたEventObjectを持つことができる関数を呼び出すことです。このようなもの:

$("body").mousemove(function(event){
     element_mouse_is_inside($("#mycontainer", event, true, {});
});

ソースコードは、githubまたは投稿の下部にあります。

https://github.com/mostafatalebi/ElementsLocator/blob/master/elements_locator.jquery.js

function element_mouse_is_inside  (elementToBeChecked, mouseEvent, with_margin, offset_object)
{
    if(!with_margin)
    {
        with_margin = false;
    }
    if(typeof offset_object !== 'object')
    {
        offset_object = {};
    }
    var elm_offset = elementToBeChecked.offset();
    var element_width = elementToBeChecked.width();
    element_width += parseInt(elementToBeChecked.css("padding-left").replace("px", ""));
    element_width += parseInt(elementToBeChecked.css("padding-right").replace("px", ""));
    var element_height = elementToBeChecked.height();
    element_height += parseInt(elementToBeChecked.css("padding-top").replace("px", ""));
    element_height += parseInt(elementToBeChecked.css("padding-bottom").replace("px", ""));
    if( with_margin)
    {
        element_width += parseInt(elementToBeChecked.css("margin-left").replace("px", ""));
        element_width += parseInt(elementToBeChecked.css("margin-right").replace("px", ""));
        element_height += parseInt(elementToBeChecked.css("margin-top").replace("px", ""));
        element_height += parseInt(elementToBeChecked.css("margin-bottom").replace("px", ""));
    }

    elm_offset.rightBorder = elm_offset.left+element_width;
    elm_offset.bottomBorder = elm_offset.top+element_height;

    if(offset_object.hasOwnProperty("top"))
    {
        elm_offset.top += parseInt(offset_object.top);
    }
    if(offset_object.hasOwnProperty("left"))
    {
        elm_offset.left += parseInt(offset_object.left);
    }
    if(offset_object.hasOwnProperty("bottom"))
    {
        elm_offset.bottomBorder += parseInt(offset_object.bottom);
    }
    if(offset_object.hasOwnProperty("right"))
    {
        elm_offset.rightBorder += parseInt(offset_object.right);
    }
    var mouseX = mouseEvent.pageX;
    var mouseY = mouseEvent.pageY;

    if(  (mouseX > elm_offset.left && mouseX < elm_offset.rightBorder)
        && (mouseY > elm_offset.top && mouseY < elm_offset.bottomBorder) )
    {
        return true;
    }
    else
    {
        return false;
    }
}

0

'Happytime harry'の発言を拡張して、必ず.data()jquery関数を使用してタイムアウトIDを格納してください。これは、後で同じ要素で 'mouseenter'がトリガーされたときにタイムアウトIDを非常に簡単に取得できるようにするためであり、ツールチップが消えるトリガーを排除できます。


0

jQueryのmouseenterイベントとmouseleaveイベントを使用できます。マウスが目的の領域に入ったときにフラグを設定し、領域から離れたときにフラグを設定解除できます。


1
それが私が考えていたことです。SLaksが示唆するように$ .data()を使用することは、これを達成するための良い方法のようです。
JamesBrownIsDead 2010年

0

このトピックのアイデアを組み合わせてこれを思いつきました。これはサブメニューの表示/非表示に役立ちます。

$("#menu_item_a").mouseenter(function(){
   clearTimeout($(this).data('timeoutId'));
   $("#submenu_a").fadeIn("fast");
}).mouseleave(function(){
   var menu_item = $(this);

   var timeoutId = setTimeout(function(){
      if($('#submenu_a').is(':hover'))
      {
        clearTimeout(menu_item.data('timeoutId'));
      }
      else
      {
        $("#submenu_a").fadeOut("fast");
      }
   }, 650);

    menu_item.data('timeoutId', timeoutId); 
});

 $("#submenu_a").mouseleave(function(){
   $(this).fadeOut("fast");
 });

私のために働くようです。これが誰かを助けることを願っています。

編集:今、このアプローチの実現はIEで正しく機能していません。


0

上記の提案はどれも使用できませんでした。
なぜ私のソリューションを好むのですか?
このメソッドは、あなたが選択した任意の時点でマウスが要素上にあるかどうかをチェックします
Mouseenterhoverは便利ですが、mouseenterは、要素がマウスの下に移動したときではなく、マウスを動かした場合にのみトリガーされます。
:ホバーはかなり甘いですが... IE

だから私はこれをします:

いいえ1.必要に応じて移動するたびにマウスのx、y位置を保存します。
いいえ2.クエリに一致する要素の上にマウスがあるかどうかを確認します... mouseenterイベントのトリガーなど

// define mouse x, y variables so they are traced all the time
var mx = 0; //  mouse X position
var my = 0; //  mouse Y position

// update mouse x, y coordinates every time user moves the mouse
$(document).mousemove(function(e){
    mx = e.pageX;
    my = e.pageY;
});

// check is mouse is over an element at any time You need (wrap it in function if You need to)
$("#my_element").each(function(){
    boxX = $(this).offset().left;
    boxY = $(this).offset().top;
    boxW = $(this).innerWidth();
    boxH = $(this).innerHeight();
    if ((boxX <= mx) &&
        (boxX + 1000 >= mx) &&
        (boxY <= my) &&
        (boxY + boxH >= my))
    {
        // mouse is over it so you can for example trigger a mouseenter event
        $(this).trigger("mouseenter");
    }
});

0

上記の人気のある役立つアーサーゴールドスミスの回答についてのメモ:IEでマウスをある要素から別の要素に(少なくともIE 9まで)移動している場合、新しい要素に次の要素がある場合、これが正しく機能しないことがあります透明な背景(デフォルトでは透明になります)。私の回避策は、新しい要素に透明な背景画像を与えることでした。



-1

is(':visible');jqueryで使用でき、$( '。item:hover')の場合はJqueryでも機能します。

これはhtmコードのスニペットです:

    <li class="item-109 deeper parent">
<a class="root" href="/Comsopolis/index.php/matiers"><span>Matiers</span></a>
<ul>
<li class="item-110 noAff">
<a class=" item sousMenu" href="/Comsopolis/index.php/matiers/tsdi">
<span>Tsdi</span>
</a>
</li>
<li class="item-111 noAff">
<a class="item" href="/Comsopolis/index.php/matiers/reseaux">
<span>Réseaux</span>
</a>
</li>
</ul>
</li>

そしてこれはJSコードです:

$('.menutop > li').hover(function() {//,.menutop li ul

    $(this).find('ul').show('fast');

},function() {
    if($(this).find('ul').is(':hover'))
    $(this).hide('fast');

});

 $('.root + ul').mouseleave(function() {
    if($(this).is(':visible'))
    $(this).hide('fast');

});

これは私が話していたものです:)


1
質問との関係がわかりません。
Andrew Barber

マウスオーバーから出て非表示の要素を表示するときにこれを使用し、遅延後、非表示/表示するターゲット要素にマウスが入ると表示されるかどうかを確認できます
ucefkh

1
あなたはその質問をとてもよく読んだとは思いません。これは彼が必要としているものではありません。
Andrew Barber

1
あなたがやっていることに関連していない、この質問。(どうやら(
アンドリューバーバー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.