私は以前に作成したいくつかのWebサイトを持っていますが、jqueryマウスイベントを使用しています... iPadを入手したばかりで、すべてのマウスオーバーイベントがクリックに変換されることに気付きました...たとえば、1回ではなく2回クリックする必要があります..(実際のクリックよりも最初のホバー)
これを解決するための回避策はありますか?多分私はマウスオーバー/アウトなどの代わりに使用したjqueryコマンド。ありがとう!
私は以前に作成したいくつかのWebサイトを持っていますが、jqueryマウスイベントを使用しています... iPadを入手したばかりで、すべてのマウスオーバーイベントがクリックに変換されることに気付きました...たとえば、1回ではなく2回クリックする必要があります..(実際のクリックよりも最初のホバー)
これを解決するための回避策はありますか?多分私はマウスオーバー/アウトなどの代わりに使用したjqueryコマンド。ありがとう!
回答:
これは完全にはテストされていませんが、iOSがタッチイベントを発生させるため、jQuery設定を使用していると仮定すると、これは機能する可能性があります。
$('a').on('click touchend', function(e) {
var el = $(this);
var link = el.attr('href');
window.location = link;
});
モバイルWebKit touchend
はタップの最後にイベントを発生させるので、それをリッスンtouchend
し、リンクでイベントが発生するとすぐにブラウザーをリダイレクトします。
.on
は、が推奨され.live
ます。この回答を読んだ後、コードを変更すると$('a').on('click touchend', function(e) {...})
うまく機能することがわかりました。
target="_blank"
、同じウィンドウと新しいウィンドウで開きます。
あなたの質問が何であるかは完全に明確ではありませんが、マウスのホバー効果を保持しながらダブルクリックを排除したい場合は、私のアドバイスは次のとおりです:
touchstart
してmouseenter
。mouseleave
、touchmove
およびclick
。マウスをシミュレートするために、ユーザーがタッチスクリーン(iPadなど)で指をタッチして離した場合、Webkit mobileなどのブラウザーは次のイベントを発生させます(ソース:html5rocks.comのTouch And Mouse)。
touchstart
touchmove
touchend
mouseover
mouseenter
mouseover
、mouseenter
またはmousemove
イベントをページのコンテンツを変更し、次のイベントが解雇されることはありません。mousemove
mousedown
mouseup
click
Webブラウザにマウスイベントをスキップするように指示するだけでは不可能のようです。
さらに悪いことに、マウスオーバーイベントがページコンテンツを変更した場合、クリックイベントは発生しません。これは、「Safari Webコンテンツガイド-イベントの処理」、特にOne-Fingerイベントの図6.4で説明されています。正確に「コンテンツの変更」とは、ブラウザとバージョンによって異なります。iOS 7.0では、背景色の変更はコンテンツの変更ではない(またはなくなった)ことがわかりました。
要点をまとめると:
touchstart
してmouseenter
。mouseleave
、touchmove
およびclick
。に対するアクションはありませんtouchend
。
これは明らかに、マウスイベントのために動作しますmouseenter
とmouseleave
(やや改善のバージョンmouseover
とはmouseout
)解雇され、ホバーを追加および削除します。
ユーザーが実際にclick
リンクすると、ホバー効果も削除されます。これにより、ユーザーがWebブラウザーの戻るボタンを押した場合に確実に削除されます。
これはタッチイベントでも機能します:touchstart
ホバー効果が追加されます。で「削除されません」touchend
です。これはに再度追加されますmouseenter
。これにより、コンテンツは変更されないため(既に追加されています)、click
イベントも発生し、ユーザーが再度クリックする必要なくリンクがたどられます。
ブラウザーがtouchstart
イベントとイベントの間に持つ300ミリ秒の遅延。click
ホバー効果がこの短い時間中に表示されるため、実際に使用されます。
ユーザーがクリックをキャンセルすることを決定した場合、指の動きは通常どおりに行われます。mouseleave
イベントは発生せず、ホバー効果がそのまま残るため、通常これは問題です。ありがたいことに、これはのホバー効果を削除することで簡単に修正できますtouchmove
。
それでおしまい!
FastClickライブラリなどを使用して300ミリ秒の遅延を削除することは可能ですが、これはこの質問の範囲外です。
私は次の代替案で次の問題を見つけました:
touchend
:これは、ユーザーが実際にリンクをクリックするつもりがなく、スクロールまたはズームのみを望んでいたとしても、リンクを誤ってたどります。touchend
は、後続のマウスイベントでif条件として使用される変数を設定し、その時点での状態変化を防ぎます。変数はクリックイベントでリセットされます。タッチインターフェイスでホバー効果を本当に必要としない場合、これは適切なソリューションです。残念ながら、これは、touchend
が別の理由で発生し、クリックイベントが発生せず(ユーザーがスクロールまたはズームした場合など)、その後マウスでリンクをたどろうとすると(つまり、マウスとタッチインターフェイスの両方を備えたデバイスで)機能しません。)。mouseover
or mousemove
イベント中にコンテンツが変更された後、それ以上イベントが発生しないことを示しています。結局のところ、CSSソリューションがあるようです。Safariが2回目のタッチを待機する理由は、通常:hoverイベントに割り当てる背景画像(または要素)が原因です。何も表示されない場合-問題はありません。解決策は、たとえば:hoverの背景をオーバーライドして、たとえばマウスオーバー時に表示する要素を非表示にして継承するセカンダリCSSファイル(またはJSアプローチの場合はスタイル)をiOSプラットフォームにターゲティングすることです。
これは、CSSとHTMLの例です-マウスオーバー時に星付きのラベルが付いた製品ブロック:
HTML:
<a href="#" class="s"><span class="s-star"></span>Some text here</a>
CSS:
.s {
background: url(some-image.png) no-repeat 0 0;
}
.s:hover {
background: url(some-image-r.png) no-repeat 0 0;
}
.s-star {
background: url(star.png) no-repeat 0 0;
height: 56px;
position: absolute;
width: 72px;
display:none;
}
.s:hover .s-star {
display:block;
}
解決策(セカンダリCSS):
/* CSS */
/* Keep hovers the same or hidden */
.s:hover {
background:inherit;
}
.s:hover .s-star {
display:none;
}
私のために働いたのは、ここの他の人がすでに言ったことです:
ホバーまたはマウスムーブ(私の場合はイベント)で要素を表示/非表示にしないでください。
Appleの発言は次のとおりです(https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html):
クリック可能な要素は、リンク、フォーム要素、イメージマップ領域、またはmousemove、mousedown、mouseup、またはonclickハンドラーを持つその他の要素です。
ユーザーがクリック可能な要素をタップすると、イベントはこの順序で到着します:マウスオーバー、マウスムーブ、マウスダウン、マウスアップ、クリック。また、mousemoveイベントでページのコンテンツが変更された場合、シーケンス内の後続のイベントは送信されません。この動作により、ユーザーは新しいコンテンツをタップできます。
したがって、@ woopのソリューションを使用できます。userAgentを検出し、それがiOSデバイスかどうかを確認してから、イベントをバインドします。私がこのテクニックを使用したのは、自分のニーズに合っており、ホバーイベントが必要ないときにバインドしない方が合理的だからです。
しかし... userAgentsをいじりたくない場合でも、ホバー/マウスムーブで要素を非表示/表示する場合は、次のようにネイティブjavascriptを使用してそうできることがわかりました。
$("body").on("mouseover", function() {
document.getElementsByTagName("my-class")[0].style.display = 'block'; //show element
document.querySelector(".my-selector div").style.display = 'none'; // hide element
});
これはデスクトップバージョンで機能し、モバイルバージョンでは何もしません。
そしてもう少し互換性のために...
$("body").on("mouseover", function() {
if (document.getElementsByTagName && document.querySelector) { // check compatibility
document.getElementsByTagName("my-class")[0].style.display = 'block'; //show element
document.querySelector(".my-selector div").style.display = 'none'; // hide element
} else {
$(".my-class").show();
$(".my-selector div").hide();
}
});
cdurukのソリューションは非常に効果的でしたが、私のサイトのいくつかの部分で問題が発生しました。CSSホバークラスを追加するためにすでにjQueryを使用していたため、最も簡単な解決策は、モバイルデバイスにCSSホバークラスを追加しないことです(より正確には、モバイルデバイスにない場合にのみ追加します)。
ここに一般的な考えがありました:
var device = navigator.userAgent.toLowerCase();
var ios = device.match(/(iphone|ipod|ipad)/);
if (!(ios)) {
$(".portfolio-style").hover(
function(){
$(this).stop().animate({opacity: 1}, 100);
$(this).addClass("portfolio-red-text");
},
function(){
$(this).stop().animate({opacity: 0.85}, 100);
$(this).removeClass("portfolio-red-text");
}
);
}
*説明のためにコードを削減
のmouseenter
代わりに試すのが賢明だと思いますmouseover
。これ.hover(fn,fn)
は、バインド時に内部的に使用されるものであり、通常は必要なものです。
既存のソリューションには次の問題があり、それらすべてを解決するように見える何かを見つけました。これは、クロスブラウザ、クロスデバイスを対象としており、デバイスのスニッフィングを望まないことを前提としています。
だけを使用するtouchstart
かtouchend
:
次々とmouseover
イベントをトリガーすることによる重大な影響は少なくtouchstart
なりmouseout
ますtouchmove
が、通常のブラウザの動作には影響します。次に例を示します。
touchstart
ようにmouseover
され、mouseout
次回に編touchstart
。したがって、Androidでマウスオーバーコンテンツを表示する1つの方法は、関心のある領域に触れて指を小刻みに動かし、ページを少しスクロールすることです。を扱うtouchmove
とmouseout
これが壊れます。理論的には、を使用してフラグを追加することもできますがtouchmove
、iPhoneは動きがない場合でもタッチムーブをトリガーします。理論的にはtouchstart
、touchend
イベントpageX
とを比較することはできますpageY
が、iPhoneでは、touchend
pageX
またははありませんpageY
。
ですから、残念ながらすべての拠点をカバーするのは少し複雑になります。
$el.on('touchstart', function(e){
$el.data('tstartE', e);
if(event.originalEvent.targetTouches){
// store values, not reference, since touch obj will change
var touch = e.originalEvent.targetTouches[0];
$el.data('tstartT',{ clientX: touch.clientX, clientY: touch.clientY } );
}
});
$el.on('touchmove', function(e){
if(event.originalEvent.targetTouches){
$el.data('tstartM', event.originalEvent.targetTouches[0]);
}
});
$el.on('click touchend', function(e){
var oldE = $el.data('tstartE');
if( oldE && oldE.timeStamp + 1000 < e.timeStamp ) {
$el.data('tstartE',false);
return;
}
if( $el.data('iosTouchM') && $el.data('tstartT') ){
var start = $el.data('tstartT'), end = $el.data('tstartM');
if( start.clientX != end.clientX || start.clientY != end.clientY ){
$el.data('tstartT', false);
$el.data('tstartM', false);
$el.data('tstartE',false);
return;
}
}
$el.data('tstartE',false);
理論的には、概算として1000を使用するだけでなく、長押しに使用される正確な時間を取得する方法がありますが、実際にはそれほど単純ではなく、妥当なプロキシを使用するのが最善です。
MacFreakの答えは私にとって非常に役に立ちました。これがあなたを助けるためにいくつかの実践的なコードがあります。
問題-touchendを適用すると、要素の上で指をスクロールするたびに、単にスクロールしようとしても、押したように反応します。
ホバーされたボタンを「強調表示」するためにいくつかのボタンの下の線をフェードアップするjQueryでエフェクトを作成しています。リンクをたどるにはタッチデバイスのボタンを2回押す必要があるという意味ではありません。
ここにボタンがあります:
<a class="menu_button" href="#">
<div class="menu_underline"></div>
</a>
「menu_underline」divをマウスオーバーでフェードアップさせ、マウスアウトでフェードアウトさせたい。しかし、タッチデバイスが2回ではなく1回のクリックでリンクをたどれるようにしたいのです。
解決策 -これを機能させるjQueryは次のとおりです。
//Mouse Enter
$('.menu_button').bind('touchstart mouseenter', function(){
$(this).find(".menu_underline").fadeIn();
});
//Mouse Out
$('.menu_button').bind('mouseleave touchmove click', function(){
$(this).find(".menu_underline").fadeOut();
});
このMacFreakにご協力いただき、誠にありがとうございます。
空のリスナーを追加しても機能することがわかりました。理由は聞かないでください。iOS9.3.2を搭載したiPhoneおよびiPadでテストしたところ、問題なく動作しました。
if(/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream){
var elements = document.getElementsByTagName('a');
for(var i = 0; i < elements.length; i++){
elements[i].addEventListener('touchend',function(){});
}
}
私はあなたのリンクにonmouseoverイベントがないと "思い"ます。1タップするとonmouseoverがアクティブになり、ダブルタップするとリンクがアクティブになります。しかし、idk。iPadを持っていません。ジェスチャー/タッチイベントを使用する必要があると思います。
私は同じ問題を抱えていましたが、タッチデバイスではありませんでした。このイベントは、クリックするたびにトリガーされます。イベントのキューイングについて何かがあります。
しかし、私の解決策は次のとおりです:クリックイベント(またはタッチ?)でタイマーを設定しました。リンクがXミリ秒以内に再度クリックされると、falseが返されます。
要素ごとのタイマーを設定するには、を使用できます$.data()
。
これにより、上記の@Ferdyの問題も修正される場合があります。
Modernizrを使用する場合、前述のとおり、Modernizr.touchを使用するのは非常に簡単です。
ただし、念のため、Modernizr.touchとユーザーエージェントテストを組み合わせて使用することをお勧めします。
var deviceAgent = navigator.userAgent.toLowerCase();
var isTouchDevice = Modernizr.touch ||
(deviceAgent.match(/(iphone|ipod|ipad)/) ||
deviceAgent.match(/(android)/) ||
deviceAgent.match(/(iemobile)/) ||
deviceAgent.match(/iphone/i) ||
deviceAgent.match(/ipad/i) ||
deviceAgent.match(/ipod/i) ||
deviceAgent.match(/blackberry/i) ||
deviceAgent.match(/bada/i));
function Tipsy(element, options) {
this.$element = $(element);
this.options = options;
this.enabled = !isTouchDevice;
this.fixTitle();
};
Modernizrを使用しない場合は、Modernizr.touch
上記の関数を次のように置き換えるだけです。('ontouchstart' in document.documentElement)
また、ユーザーエージェントiemobileをテストすると、検出されたMicrosoftモバイルデバイスの範囲がWindows Phoneよりも広くなります。
使用できますclick touchend
、
例:
$('a').on('click touchend', function() {
var linkToAffect = $(this);
var linkToAffectHref = linkToAffect.attr('href');
window.location = linkToAffectHref;
});
上記の例は、タッチデバイスのすべてのリンクに影響します。
特定のリンクのみをターゲットにしたい場合は、リンクにクラスを設定することでこれを行うことができます。
HTML:
<a href="example.html" class="prevent-extra-click">Prevent extra click on touch device</a>
jquery:
$('a.prevent-extra-click').on('click touchend', function() {
var linkToAffect = $(this);
var linkToAffectHref = linkToAffect.attr('href');
window.location = linkToAffectHref;
});
乾杯、
イェロエン
要素のmouseenter / mouseleave / click状態にイベントがバインドされている同様の状況に遭遇しましたが、iPhoneでは、ユーザーはまず要素をダブルクリックして最初にmouseenterイベントをトリガーし、次にもう一度クリックイベントをトリガーする必要がありました。 。
上記と同様の方法を使用してこれを解決しましたが、次のようにjQuery $ .browserプラグイン(jQuery 1.9>の場合)を使用し、.triggerイベントをmouseenterバインディングイベントに追加しました。
// mouseenter event
$('.element').on( "mouseenter", function() {
// insert mouseenter events below
// double click fix for iOS and mouseenter events
if ($.browser.iphone || $.browser.ipad) $(this).trigger('click');
});
// mouseleave event
$('.element').on( "mouseleave", function() {
// insert mouseout events below
});
// onclick event
$('.element').on( "click", function() {
// insert click events below
});
.triggerは、iPhoneまたはiPadで表示されたときに要素のmouseenter(または最初のクリック)時に.clickイベントハンドラーを起動することにより、要素をダブルクリックする必要をなくします。最もエレガントなソリューションではないかもしれませんが、私の場合はうまく機能し、すでに配置されているプラグインを利用します。これらのデバイスで既存のイベントを機能させるには、コードを1行追加する必要がありました。
ここでjQuery $ .browserプラグインを取得できます:https : //github.com/gabceb/jquery-browser-plugin
誤ってリンク上で指をスライドさせたときにリダイレクトを回避するための単なる改善。
// tablet "one touch (click)" X "hover" > link redirection
$('a').on('touchmove touchend', function(e) {
// if touchmove>touchend, set the data() for this element to true. then leave touchmove & let touchend fail(data=true) redirection
if (e.type == 'touchmove') {
$.data(this, "touchmove_cancel_redirection", true );
return;
}
// if it's a simple touchend, data() for this element doesn't exist.
if (e.type == 'touchend' && !$.data(this, "touchmove_cancel_redirection")) {
var el = $(this);
var link = el.attr('href');
window.location = link;
}
// if touchmove>touchend, to be redirected on a future simple touchend for this element
$.data(this, "touchmove_cancel_redirection", false );
});
MacFreakからインスピレーションを得て、自分に合ったものをまとめました。
このjsメソッドは、ホバーがipadにくっつくのを防ぎ、場合によってはクリックが2回のクリックとして登録されるのを防ぎます。CSSで、CSSに:hover psudoクラスがある場合は、それらを.hoverに変更します。たとえば、.some-class:hoverを.some-class.hoverに変更します。
iPadでこのコードをテストして、cssおよびjs hoverメソッドの動作の違いを確認します(ホバー効果のみ)。CSSボタンには派手なクリック警告はありません。 http://jsfiddle.net/bensontrent/ctgr6stm/
function clicker(id, doStuff) {
id.on('touchstart', function(e) {
id.addClass('hover');
}).on('touchmove', function(e) {
id.removeClass('hover');
}).mouseenter(function(e) {
id.addClass('hover');
}).mouseleave(function(e) {
id.removeClass('hover');
}).click(function(e) {
id.removeClass('hover');
//It's clicked. Do Something
doStuff(id);
});
}
function doStuff(id) {
//Do Stuff
$('#clicked-alert').fadeIn(function() {
$(this).fadeOut();
});
}
clicker($('#unique-id'), doStuff);
button {
display: block;
margin: 20px;
padding: 10px;
-webkit-appearance: none;
touch-action: manipulation;
}
.hover {
background: yellow;
}
.btn:active {
background: red;
}
.cssonly:hover {
background: yellow;
}
.cssonly:active {
background: red;
}
#clicked-alert {
display: none;
}
<button id="unique-id" class="btn">JS Hover for Mobile devices<span id="clicked-alert"> Clicked</span>
</button>
<button class="cssonly">CSS Only Button</button>
<br>This js method prevents hover from sticking on an ipad, and prevents the click registering as two clicks. In CSS, if you have any :hover in your css, change them to .hover For example .some-class:hover to .some-class.hover
手遅れですが、これは私が見つけた最も簡単な回避策の1つです。
$('body').on('touchstart','*',function(){ //listen to touch
var jQueryElement=$(this);
var element = jQueryElement.get(0); // find tapped HTML element
if(!element.click){
var eventObj = document.createEvent('MouseEvents');
eventObj.initEvent('click',true,true);
element.dispatchEvent(eventObj);
}
});
これはリンク(アンカータグ)だけでなく、他の要素でも機能します。お役に立てれば。
この短いスニペットは動作するようです。リンクがタップされたときにクリックイベントをトリガーする:
$('a').on('touchstart', function() {
$(this).trigger('click');
});
他の答えのどれも私にはうまくいきません。私のアプリには、多数のイベントリスナー、独自のチェックボックス、およびリスナーとリンクなしのリンクがあります。
私はこれを使います:
var selector = "label, a, button";
var timer;
var startX;
var startY;
$(document).on("click", selector, function (e) {
if ($(this).data("touched") === true) {
e.stopImmediatePropagation();
return false;
}
return;
}).on("touchend", selector, function (e) {
if (Math.abs(startX - e.originalEvent.changedTouches[0].screenX) > 10 || Math.abs(startY - e.originalEvent.changedTouches[0].screenY) > 10)
// user action is not a tap
return;
var $this = $(this);
// Visit: http://stackoverflow.com/questions/1694595/can-i-call-jquery-click-to-follow-an-a-link-if-i-havent-bound-an-event-hand/12801548#12801548
this.click();
// prevents double click
$this.data("touched", true);
if (timer)
clearTimeout(timer);
setTimeout(function () {
$this.data("touched", false);
}, 400);
e.stopImmediatePropagation();
return false;
}).on("touchstart", function (e) {
startX = e.originalEvent.changedTouches[0].screenX;
startY = e.originalEvent.changedTouches[0].screenY;
});
IPadのダブルクリックを解決する最も簡単な方法は、メディアクエリでホバー効果のCSSをラップすることです@media (pointer: fine)
。
@media (pointer: fine) {
a span {
display: none;
}
a:hover span {
display: inline-block;
}
}
このメディアクエリでラップされたCSSは、デスクトップにのみ適用されます。
このソリューションの説明はこちらhttps://css-tricks.com/annoying-mobile-double-tap-link-issue/
あなたはnavigator.userAgent
このようにチェックすることができます:
if(!navigator.userAgent.match(/iPhone/i) || !navigator.userAgent.match(/iPad/i)) {
//bind your mouseovers...
}
しかし、ブラックベリー、ドロイド、その他のかなりのタッチスクリーンデバイスをチェックする必要があります。userAgentにMozilla、IE、Webkit、またはOperaが含まれている場合にのみマウスオーバーをバインドすることもできますが、たとえば、DroidがそのuserAgent文字列を次のように報告するため、一部のデバイスをスクリーニングする必要があります。
Mozilla/5.0 (Linux; U; Android 2.0.1; en-us; Droid Build/ESD56) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17
iPhoneの文字列も同様です。iPhone、iPod、iPad、Android、Blackberryの画面を表示するだけの場合、ハンドヘルドの大部分を手に入れることができますが、すべてではありません。
タブレットとモバイルデバイスを除外するCSSメディアクエリを作成し、そこにホバーを置くだけです。これにはjQueryやJavaScriptは実際には必要ありません。
@media screen and (min-device-width:1024px) {
your-element:hover {
/* Do whatever here */
}
}
これをhtmlヘッドに追加して、解像度ではなく実際のピクセルで計算されることを確認してください。
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />