私が欠けているjQueryでこれを行うための迅速かつ簡単な方法はありますか?
Mouseoverイベントは他の用途に使用しているため、使用したくありません。与えられた瞬間にマウスが要素の上にあるかどうかを知る必要があるだけです。
"IsMouseOver"関数がある場合に限り、私はこのようなことをしたいのですが。
function hideTip(oi) {
setTimeout(function() { if (!IsMouseOver(oi)) $(oi).fadeOut(); }, 100);
}
マウスアウトでタイムアウトをフェードアウトに設定し、戻り値をオブジェクト内のデータに格納します。その後、マウスオーバー時にデータに値がある場合はタイムアウトを解除してください。
フェードアウトのコールバックでデータを削除します。
Mouseenter/mouseleaveは、子供がマウスオーバーまたはマウスアウトされたときにメニューに対して起動されないため、実際にはそれほど高価ではありません。
このコードは、 happytime harry と何を言っているのかを示しています。マウスが入るとツールチップが出て、マウスが離れるとツールチップは消えるまでの遅延を設定します。遅延がトリガーされる前にマウスが同じ要素に入った場合は、以前に保存したデータを使用して、トリガーが消える前にトリガーを破棄します。
$("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);
});
清潔でエレガントなホバーチェック
if ($('#element:hover').length != 0) {
// do something ;)
}
警告:is(':hover')
はjquery 1.8以降では非推奨です。解決策については この投稿 をご覧ください。
また、この答えを使用することができます: https://stackoverflow.com/a/6035278/8843 マウスが要素にホバーしているかどうかをテストする:
$('#test').click(function() {
if ($('#hello').is(':hover')) {
alert('hello');
}
});
JQueryのhover
イベントを使って手動で追跡することができます。
$(...).hover(
function() { $.data(this, 'hover', true); },
function() { $.data(this, 'hover', false); }
).data('hover', false);
if ($(something).data('hover'))
//Hovered!
これと全く同じようなものが必要でした(もう少し複雑な環境では、 'mouseenters'と '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()
IE 7以降、Chrome 1以降、Firefox 4でテストしましたが、正常に動作しています。
JQueryでは、.is( ':hover')を使用できます。
function IsMouseOver(oi)
{
return $(oi).is(':hover');
}
これで、OPで要求された機能を提供する最も簡潔な方法になります。
注:上記はIE 8以下では機能しません
IE8で動く(IE9のIE8のmodusを信頼できるならば)それほど簡潔ではない代替案として、そして至る所で$(...).hover(...)
を起動することなく、そうするか、要素のセレクターを知る必要はありません(その場合、Ivoの答えはより簡単です)。
function IsMouseOver(oi)
{
return oi.length &&
oi.parent()
.find(':hover')
.filter(function(s){return oi[0]==this})
.length > 0;
}
私は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());
});
ちなみにこれの今後の発見者のために。
私はこれ以上のことができるjQueryプラグインを作りました。私のプラグインでは、カーソルが現在置かれているすべての要素を取得するには、単に次のようにします。
$.cursor("isHover"); // will return jQ object of all elements the cursor is
// currently over & doesn't require timer
私が述べたように、それはあなたが で見ることができるように他の用途もたくさんありますjsFiddleがここに見つかりました
私はコメントできないので、答えとしてこれを書くつもりです!
CSSセレクタ ":hover"とホバーイベントの違いを理解してください。
":hover"はCSSセレクタであり、この$("#elementId").is(":hover")
のように使用されると実際にイベントとともに削除されましたが、それはつまりjQueryイベントのホバーとは無関係です。
$("#elementId:hover")
をコーディングした場合、要素はマウスでホバーしたときにのみ選択されます。上記のステートメントは、純粋で合法的なCSSを選択してこの要素を選択するときに、すべてのjQueryバージョンで機能します。
一方であるイベントホバー
$("#elementId").hover(
function() {
doSomething();
}
);
jQuery 1.8としてここで実際にdeprecadedされていますjQueryウェブサイトからの状態:
イベント名 "hover"が使用されている場合、イベントサブシステムはそれをイベント文字列内の "mouseenter mouseleave"に変換します。これはいくつかの理由で迷惑です。
意味論:ホバリングはマウスが要素を出入りするのと同じではなく、発射までにある程度の減速または遅延を意味します。イベント名:アタッチされたハンドラによって返されるevent.typeはホバーではなく、mouseenterまたはmouseleaveです。これ以外のイベントはありません。 "hover"という名前を選択する: "hover"という名前のイベントを添付し、.trigger( "hover")を使用してそれを起動することはできません。ドキュメントではすでにこの名前を「新しいコードには推奨しない」と呼んでいますが、正式には1.8では廃止し、最終的には削除したいと思います。
なぜ彼らが使用法を削除したのか( ":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%が他の方法があります !
私はそこにカップルの人々を助けることができると思います。
Greetz Andy
これはjqueryに頼らずネイティブDOM matches
API を使うテクニックです。 IE9に戻るブラウザをサポートするためにベンダープレフィックスを使用します。詳細については、caniuse.comの matchesselector を参照してください。
まず、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');
タイムアウトがよく使用されていますが、イベントのコンテキストでは、座標を見ることはできません。
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)を確認する必要があるかもしれません。
最後に、dragLeaveイベントが子要素に入ることによってトリガーされなかったことを確認するために、dragLeaveハンドラー内でこのアプローチを使用することを検討しています。あなたがどうしてもあなたがまだ親要素の中にいることを確認しないなら、あなたはあなたが本当に親を去ったときだけ意図されている行動を誤って取るかもしれません。
編集:これはいい考えですが、一貫して動作しません。おそらくいくつかの小さな調整があります。
どの子divにも特定のクラスがある場合、jQuery
でテストできます。次に、特定のdivをマウスオーバーして出したときにそのクラスを適用することで、ページ上の別の要素にマウスオーバーしたときでも、マウスが上にあるかどうかをテストできます。これは、ポップアップ内のdiv間にスペースがあるために使用しました。ポップアップ内のスペースの上にマウスを移動したときではなく、ポップアップから移動したときにのみポップアップを閉じたかったのです。そこで、私はcontent divに対してマウスオーバー機能(ポップアップが終わったところ)を呼び出しましたが、それはcontent divをマウスオーバーしたとき、そしてそれがポップアップの外側にあったときにだけ閉じる機能を引き起こすでしょう!
$( "。pop-up")。mouseover(関数(e) { $(this).addClass( "over"); [[ [(____)]}); [ ] $( "。pop-up")。マウスアウト(関数(e) { $(this).removeClass) ( "over"); }); $( "#mainContent")。mouseover(function(e){[.____。if (!$( "。extended")。hasClass( "over")){[.____。Drupal.dhtmlMenu.toggleMenu($( "。expansion")); } } );
あなたの両方に感謝します。ある時点で、マウスがまだ要素の上にあるかどうかを検出しようとすることをあきらめなければなりませんでした。私はそれが可能であることを知っています、しかし達成するために多すぎるコードを必要とするかもしれません。
それは少し時間がかかりましたが、私はあなたの提案の両方を取り、私のために働くであろう何かを思い付きました。
これは単純化された(しかし機能的な)例です。
$("[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と共に、これはとても素晴らしいマウスオーバーヘルプツールチップを可能にします。ちなみに、チェックアウトとテキストの間に小さな隙間があり、マウスを動かすとヘルプが点滅するため、マウスアウトに遅延が必要でした。しかし、これは魅力のように機能します。私はフォーカス/ぼかしイベントについても同様のことをしました。
これが最も簡単な方法です。
function(oi)
{
if(!$(oi).is(':hover')){$(oi).fadeOut(100);}
}
私はあなたが必要とするかもしれないすべての詳細で、これを別の質問で答えました:
jQuery を使って要素上にホバリングしているIFを検出する(執筆時点では99の投票があります)
基本的には、次のようなことができます。
var ishovered = oi.is(":hover");
これは、oi
が単一の要素を含む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以降でテストされました。
私はこのトピックからのアイデアを組み合わせてこれを思いつきました、それはサブメニューを見せる/隠すのに役立ちます:
$("#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で正しく機能していません。
'Happytime harry'が言ったことを拡張して、タイムアウトIDを格納するために必ず.data()jquery関数を使用してください。これは、後で同じ要素で 'mouseenter'がトリガーされたときにタイムアウトIDを非常に簡単に取得できるようにするためです。これにより、ツールチップが消えるのを防ぐことができます。
上記の提案はどれも使用できませんでした。
なぜ私は自分の解決策を好むのですか?
このメソッドは、あなたが選択した時間にマウスが の要素の上にあるかどうかをチェックします 。
Mouseenter および :hover はクールですが、mouseenterはユーザーがマウスを移動した場合にのみトリガーされ、要素がマウスの下に移動した場合はトリガーされません。
:ホバーはかなり甘いけど... IE
だから私はこれを行います:
いいえ1. 必要に応じてマウスのx、y位置を移動するたびに保存します。
いいえ2. mouseがクエリに一致する要素のいずれかの上にあるかどうかを確認します... 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");
}
});
上記の一般的で役立つArthur Goldsmithの答えについてのメモ:IE内でマウスをある要素から別の要素に移動している場合(少なくともIE 9まで)新しい要素が透明な背景を持っている場合(デフォルトではそうなるでしょう)、これを正しく動作させるのは困難です。私の回避策は新しい要素に透明な背景画像を与えることでした。
JQueryのmouseenterイベントとmouseleaveイベントを使用できます。マウスが目的の領域に入ったときにフラグを設定し、領域から出たときにフラグを設定解除することができます。
これは、マウスが要素の内側にあるかどうかを確認するのに役立つ関数です。あなたがするべき唯一のことは、ライブのマウス関連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;
}
}