私はjqueryマウスイベントを使用するいくつかのウェブサイトを以前に構築しました...私はiPadを手に入れましたが、すべてのマウスオーバーイベントがクリックで翻訳されることに気づきました...たとえば、1回ではなく2回クリックする必要があります..(実際のクリックよりも最初のホバー)
これを解決する準備ができていますか?たぶん、マウスオーバー/アウトなどの代わりに私が使用しているjqueryコマンドです。ありがとう!
これを完全にはテストしていませんが、iOSがタッチイベントを起動するので、jQueryの設定になっていると仮定すると、これは機能します。
$('a').on('click touchend', function(e) {
var el = $(this);
var link = el.attr('href');
window.location = link;
});
アイデアは、Mobile WebKitがタップの最後にtouchend
イベントを発生させるので、それをリッスンし、リンク上でtouchend
イベントが発生するとすぐにブラウザーをリダイレクトします。
あなたの質問が何であるかは完全に明確ではありませんが、マウスのホバー効果を維持しながらダブルクリックを排除したい場合、私のアドバイスは次のとおりです:
touchstart
およびmouseenter
にホバー効果を追加します。mouseleave
、touchmove
、およびclick
のホバー効果を削除します。マウスをシミュレートするために、ユーザーがタッチスクリーン(iPadなど)でタッチして指を離すと、Webkitモバイルなどのブラウザーは次のイベントを起動します(ソース: Touch And Mouse on html5rocks.com):
touchstart
touchmove
touchend
mouseover
mouseenter
mouseover
、mouseenter
、またはmousemove
イベントがページコンテンツを変更する場合、以下のイベントは発生しません。mousemove
mousedown
mouseup
click
単にマウスイベントをスキップするようにウェブブラウザに指示することは不可能と思われます。
さらに悪いことに、マウスオーバーイベントがページコンテンツを変更した場合、 Safari Webコンテンツガイド-イベントの処理 で説明されているように、クリックイベントは発生しません。特に、One -指イベント。まさに「コンテンツの変更」とは、ブラウザーとバージョンによって異なります。 iOS 7.0の場合、背景色の変更はコンテンツの変更ではない(またはもはやない)ことがわかりました。
要点をまとめると:
touchstart
およびmouseenter
にホバー効果を追加します。mouseleave
、touchmove
、およびclick
のホバー効果を削除します。touchend
にはアクションがないことに注意してください!
これは、マウスイベントに対して明らかに機能します。mouseenter
およびmouseleave
(mouseover
およびmouseout
のわずかに改善されたバージョン)が起動され、ホバーを追加および削除します。
ユーザーが実際にリンクをclick
sした場合、ホバー効果も削除されます。これにより、ユーザーがWebブラウザーの戻るボタンを押すと、確実に削除されます。
これはタッチイベントでも機能します。touchstart
にホバー効果が追加されます。 touchend
では '' 'not' ''が削除されます。これはmouseenter
に再び追加され、これによりコンテンツの変更が発生しないため(既に追加されている)、click
イベントも発生し、ユーザーが再度クリックする必要なくリンクがたどられます!
ブラウザーがtouchstart
イベントとclick
の間に持つ300ミリ秒の遅延は、ホバー効果がこの短い時間の間に表示されるため、実際に有効に使用されます。
ユーザーがクリックをキャンセルすることを決定した場合、指を動かすと通常どおりにキャンセルされます。通常、これはmouseleave
イベントが発生しないため問題であり、ホバー効果はそのまま残ります。ありがたいことに、これはtouchmove
のホバー効果を削除することで簡単に修正できます。
それでおしまい!
たとえば、 FastClickライブラリ を使用して300ミリ秒の遅延を削除することもできますが、これはこの質問の範囲外です。
私は、次の代替案で次の問題を発見しました。
touchend
:でクリックイベントをエミュレートします。ユーザーが実際にクリックする意図なしに、スクロールまたはズームのみしたい場合でも、これはリンクを誤ってたどります。リンク。touchend
に設定され、後続のマウスイベントでif条件として使用され、状態の変化を防ぎますある時点。変数はクリックイベントでリセットされます。これは、タッチインターフェイスでホバー効果を本当に必要としない場合、適切なソリューションです。残念ながら、touchend
が別の理由で発生し、クリックイベントが発生しない場合(たとえば、ユーザーがスクロールまたはズームした場合)は機能しません。その後、マウスでリンクをたどろうとしますインタフェース)。mouseover
またはmousemove
イベント中にコンテンツが変更された後、それ以上イベントが発生しないことを説明しています。iPad/iPhoneダブルクリックの問題 および モバイルブラウザーでホバー効果を無効にする も参照してください。
結局CSSソリューションがあるようです。 Safariが2回目のタッチを待機する理由は、通常: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ハンドラーを持つ他の要素です。
ユーザーがクリック可能な要素をタップすると、イベントはmouseover、mousemove、mousedown、mouseup、clickの順に到着します。また、mousemoveイベントでページのコンテンツが変更された場合、シーケンス内の後続のイベントは送信されません。この動作により、ユーザーは新しいコンテンツ。
したがって、@ woopのソリューションを使用できます。userAgentを検出し、それがiOSデバイスかどうかを確認してから、イベントをバインドします。私がこのテクニックを使用することになったのは、それが私のニーズに合っていて、望まないときにホバーイベントをバインドしないほうが理にかなっているからです。
しかし... userAgentsをいじりたくなくても、hover/mousemoveで要素を非表示/表示する場合は、次のようにネイティブ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のソリューションは非常に効果的でしたが、私のサイトのいくつかの部分で問題を引き起こしました。私はすでにjQueryを使用してCSSホバークラスを追加していたため、最も簡単な解決策は、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");
}
);
}
*説明のためにコードを削減
過度に複雑にする必要はありません。
$('a').on('touchend', function() {
$(this).click();
});
mouseenter
の代わりにmouseover
を試すのが賢明だと思います。これは、.hover(fn,fn)
にバインドするときに内部的に使用されるものであり、通常は必要なものです。
MacFreakの答えは私にとって非常に役に立ちました。役立つ場合の実践的なコードを次に示します。
PROBLEM-適用touchendは、要素上で指をスクロールするたびに、過去にスクロールしようとしても、押したように応答することを意味します。
JQueryを使用して、いくつかのボタンの下の行をフェードアップして、ホバーされたボタンを「強調表示」するエフェクトを作成しています。リンクをたどるためにタッチデバイスでボタンを2回押す必要があるという意味ではありません。
ボタンは次のとおりです。
<a class="menu_button" href="#">
<div class="menu_underline"></div>
</a>
「menu_underline」divは、マウスオーバーでフェードアップし、マウスアウトでフェードアウトするようにします。しかし、タッチデバイスが2回ではなく1回のクリックでリンクをたどることができるようにしたいと思います。
SOLUTION-これを機能させる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に関するご協力に感謝します。
既存のソリューションには次の問題があり、それらすべてを解決するように思われる何かを見つけました。これは、クロスブラウザ、クロスデバイスを狙っており、デバイスのスニッフィングを望まないことを前提としています。
touchstart
またはtouchend
のみを使用:
mouseover
でtouchstart
イベントをトリガーし、mouseout
でtouchmove
イベントをトリガーしても、重大な結果は少なくなりますが、通常のブラウザーの動作には干渉します。例:
touchstart
の指の位置をmouseover
のように扱います。これは、次のmouseout
でtouchstart
edになります。したがって、Androidでマウスオーバーコンテンツを表示する1つの方法は、関心のある領域に触れて指を小刻みに動かし、ページをわずかにスクロールすることです。 touchmove
をmouseout
として扱うと、これが壊れます。理論的には、touchmove
でフラグを追加することはできますが、動きがない場合でもiPhoneはtouchmoveをトリガーします。理論的には、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を使用する代わりに、長押しに使用される正確な時間を取得する方法がありますが、実際にはそれほど単純ではなく、合理的なプロキシを使用するのが最善です 。
リンクにはonmouseoverイベントがありません。1タップでonmouseoverがアクティブになり、ダブルタップでリンクがアクティブになります。しかし、idk。 iPadを持っていません。ジェスチャー/タッチイベントを使用する必要があると思います。
空のリスナーを追加しても機能することがわかりました。理由を聞かないでください。ただし、iOS 9.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(){});
}
}
この短いスニペットは機能しているようです。リンクがタップされたときにクリックイベントをトリガーします。
$('a').on('touchstart', function() {
$(this).trigger('click');
});
誤ってリンク上で指をスライドさせたときにリダイレクトを回避するための改善点です。
// 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ホバーメソッドの動作の違いを確認します(ホバー効果のみ)。 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
私は同じ問題を抱えていましたが、タッチデバイスではありませんでした。クリックするたびにイベントがトリガーされます。イベントのキューイングなどについて何かがあります。
しかし、私の解決策は次のようなものでした:クリックイベント(またはタッチ?)でタイマーを設定します。 X ms以内にリンクが再度クリックされた場合、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;
});
乾杯、
イェロエン
タッチスクロールを中断せずにリンクを機能させるには、jQuery Mobileの「タップ」イベントでこれを解決します。
$('a').not('nav.navbar a').on("tap", function () {
var link = $(this).attr('href');
if (typeof link !== 'undefined') {
window.location = link;
}
});
イベントが要素のmouseenter/mouseleave/click状態にバインドされているのに似た状況に陥りましたが、iPhoneでは、ユーザーが要素をダブルクリックして最初にmouseenterイベントをトリガーし、次に再度clickイベントを発生させる必要がありました。
上記と同様の方法を使用してこれを解決しましたが、次のように、jQuery $ .browserプラグイン(jQuery 1.9>の場合)を使用し、mouseenterバインディングイベントに.triggerイベントを追加しました。
// 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
これは、jquery uiドロップダウンがあるときに機能します
if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
$('.ui-autocomplete').off('menufocus hover mouseover');
}
他の答えのどれも私にはうまくいきません。私のアプリには、多くのイベントリスナー、独自のチェックボックス、およびリスナーとリスナーのないリンクを持つリンクがあります。
私はこれを使用します:
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;
});
私は遅すぎます、私は知っていますが、これは私が見つけた最も簡単な回避策の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);
}
});
これは、リンク(アンカータグ)だけでなく、他の要素でも機能します。お役に立てれば。