iframe
クロスドメインの場合、ユーザーが何をしているのかわかりません。私がやりたいのは、ユーザーがでクリックしたかどうかを追跡することですiframe
。私は目に見えないがあるシナリオを想像div
の上をiframe
し、div
ちょうどそのにクリックイベントを渡しますiframe
。
このようなことは可能ですか?もしそうなら、それから私はそれについてどうやって行きますか?iframes
広告ですので、私は使用されているタグを制御することはできません。
iframe
クロスドメインの場合、ユーザーが何をしているのかわかりません。私がやりたいのは、ユーザーがでクリックしたかどうかを追跡することですiframe
。私は目に見えないがあるシナリオを想像div
の上をiframe
し、div
ちょうどそのにクリックイベントを渡しますiframe
。
このようなことは可能ですか?もしそうなら、それから私はそれについてどうやって行きますか?iframes
広告ですので、私は使用されているタグを制御することはできません。
回答:
このようなことは可能ですか?
いいえ。できることは、マウスがiframeに入るのを検出することであり、(確実ではありませんが)戻ってきたとき(つまり、途中で広告を通過するポインターと他の場所のポインターの違いを解決しようとすること)です。広告に)。
iframeの上に目に見えないdivがあり、divがクリックイベントをiframeに渡すシナリオを想像します。
いいえ、クリックイベントを偽造する方法はありません。
マウスダウンをキャッチすることで、元のクリックがiframeに到達しないようにします。マウスボタンが押されようとするタイミングを特定できた場合、非表示のdivを邪魔にならないようにして、クリックが通過するようにすることができますが、マウスが押される直前に発生するイベントもありません。
たとえば、ポインタが止まっているかどうかを確認して、クリックが来るかどうかを推測することで、推測を試みることができます。しかし、それは完全に信頼性が低く、失敗した場合は、クリックスルーを失うだけです。
これは確かに可能です。これは、Chrome、Firefox、IE 11(およびその他)で機能します。
focus();
var listener = window.addEventListener('blur', function() {
if (document.activeElement === document.getElementById('iframe')) {
// clicked
}
window.removeEventListener('blur', listener);
});
警告:これは最初のクリックのみを検出します。私が理解しているように、それはあなたが望むすべてです。
blur
イベントがないため(iframeのイベントは発生しません)、これは複数のiframeへのクリックの検出には使用できません。
Mohammed Radwanの回答に基づいて、次のjQueryソリューションを思いつきました。基本的には、何がiFrameの人々がホバリングしているのかを追跡することです。次に、ウィンドウがぼやけている場合は、ユーザーがiframeバナーをクリックした可能性が高いです。
ユーザーがクリックしたiframeがわかるように、iframeをID付きのdivに配置する必要があります。
<div class='banner' bannerid='yyy'>
<iframe src='http://somedomain.com/whatever.html'></iframe>
<div>
そう:
$(document).ready( function() {
var overiFrame = -1;
$('iframe').hover( function() {
overiFrame = $(this).closest('.banner').attr('bannerid');
}, function() {
overiFrame = -1
});
...これにより、iFrameがホバーされない場合はoveriFrameが-1に維持され、iframeがホバーされる場合はラッピングdivに「バナー」が設定されます。次のように、ウィンドウがぼやけたときに 'overiFrame'が設定されているかどうかを確認するだけです。
$(window).blur( function() {
if( overiFrame != -1 )
$.post('log.php', {id:overiFrame}); /* example, do your stats here */
});
});
マイナーな欠点がある非常にエレガントなソリューション:ユーザーがiFrameの上にマウスを置いたときにALT-F4を押すと、クリックとしてログに記録されます。これはFireFoxでのみ発生しましたが、IE、Chrome、Safariでは登録されませんでした。
Mohammed、非常に便利なソリューションに再度感謝します!
setTimeout(function(){ window.focus(); }, 0);
。これで、ユーザーはクリックし、iframeにフォーカスを置き、スクリプトはそのフォーカスを引き戻し、今後のクリックからのフォーカスの変更をさらに監視できるようになりました。
これは、IE8を含むすべてのブラウザーで機能する小さなソリューションです。
var monitor = setInterval(function(){
var elem = document.activeElement;
if(elem && elem.tagName == 'IFRAME'){
clearInterval(monitor);
alert('clicked!');
}
}, 100);
ここでテストできます:http : //jsfiddle.net/oqjgzsm0/
次のコードは、ユーザーがクリック/ホバーするか、iframeの外に移動したかどうかを示します。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Detect IFrame Clicks</title>
<script type="text/javascript">
$(document).ready(function() {
var isOverIFrame = false;
function processMouseOut() {
log("IFrame mouse >> OUT << detected.");
isOverIFrame = false;
top.focus();
}
function processMouseOver() {
log("IFrame mouse >> OVER << detected.");
isOverIFrame = true;
}
function processIFrameClick() {
if(isOverIFrame) {
// replace with your function
log("IFrame >> CLICK << detected. ");
}
}
function log(message) {
var console = document.getElementById("console");
var text = console.value;
text = text + message + "\n";
console.value = text;
}
function attachOnloadEvent(func, obj) {
if(typeof window.addEventListener != 'undefined') {
window.addEventListener('load', func, false);
} else if (typeof document.addEventListener != 'undefined') {
document.addEventListener('load', func, false);
} else if (typeof window.attachEvent != 'undefined') {
window.attachEvent('onload', func);
} else {
if (typeof window.onload == 'function') {
var oldonload = onload;
window.onload = function() {
oldonload();
func();
};
} else {
window.onload = func;
}
}
}
function init() {
var element = document.getElementsByTagName("iframe");
for (var i=0; i<element.length; i++) {
element[i].onmouseover = processMouseOver;
element[i].onmouseout = processMouseOut;
}
if (typeof window.attachEvent != 'undefined') {
top.attachEvent('onblur', processIFrameClick);
}
else if (typeof window.addEventListener != 'undefined') {
top.addEventListener('blur', processIFrameClick, false);
}
}
attachOnloadEvent(init);
});
</script>
</head>
<body>
<iframe src="www.google.com" width="100%" height="1300px"></iframe>
<br></br>
<br></br>
<form name="form" id="form" action=""><textarea name="console"
id="console" style="width: 100%; height: 300px;" cols="" rows=""></textarea>
<button name="clear" id="clear" type="reset">Clear</button>
</form>
</body>
</html>
iframe内のsrcを独自のリンクに置き換える必要があります。これがお役に立てば幸いです。よろしく、MO
ちょうどこの解決策を見つけた...私はそれを試してみました、私はそれが大好きでした。
デスクトップとモバイルのクロスドメインiframeで動作します!
誰にでもできるかどうかまだわからない
window.addEventListener('blur',function(){
if(document.activeElement.id == 'CrossDomainiframeId'){
//do something :-)
}
});
ハッピーコーディング
これは、window要素のblurイベントを使用して実現できます。
以下は、iframeのクリックを追跡するためのjQueryプラグインです(iframeがクリックされたときにカスタムコールバック関数を起動します):https : //github.com/finalclap/iframeTracker-jquery
次のように使用します。
jQuery(document).ready(function($){
$('.iframe_wrap iframe').iframeTracker({
blurCallback: function(){
// Do something when iframe is clicked (like firing an XHR request)
}
});
});
IEで確実に動作しない長い解決策については、http://jsfiddle.net/Lcy797h2/を参照してください
$(window).on('blur',function(e) {
if($(this).data('mouseIn') != 'yes')return;
$('iframe').filter(function(){
return $(this).data('mouseIn') == 'yes';
}).trigger('iframeclick');
});
$(window).mouseenter(function(){
$(this).data('mouseIn', 'yes');
}).mouseleave(function(){
$(this).data('mouseIn', 'no');
});
$('iframe').mouseenter(function(){
$(this).data('mouseIn', 'yes');
$(window).data('mouseIn', 'yes');
}).mouseleave(function(){
$(this).data('mouseIn', null);
});
$('iframe').on('iframeclick', function(){
console.log('Clicked inside iframe');
$('#result').text('Clicked inside iframe');
});
$(window).on('click', function(){
console.log('Clicked inside window');
$('#result').text('Clicked inside window');
}).blur(function(){
console.log('window blur');
});
$('<input type="text" style="position:absolute;opacity:0;height:0px;width:0px;"/>').appendTo(document.body).blur(function(){
$(window).trigger('blur');
}).focus();
これはすべてのブラウザー(Firefoxを含む)で動作します
https://gist.github.com/jaydson/1780598
https://jsfiddle.net/sidanmor/v6m9exsw/
var myConfObj = {
iframeMouseOver : false
}
window.addEventListener('blur',function(){
if(myConfObj.iframeMouseOver){
console.log('Wow! Iframe Click!');
}
});
document.getElementById('idanmorblog').addEventListener('mouseover',function(){
myConfObj.iframeMouseOver = true;
});
document.getElementById('idanmorblog').addEventListener('mouseout',function(){
myConfObj.iframeMouseOver = false;
});
<iframe id="idanmorblog" src="https://sidanmor.com/" style="width:400px;height:600px" ></iframe>
<iframe id="idanmorblog" src="https://sidanmor.com/" style="width:400px;height:600px" ></iframe>
Mohammed Radwan、あなたのソリューションはエレガントです。FirefoxとIEでiframeのクリックを検出するには、document.activeElementとタイマーを使用する簡単な方法を使用できますが、ChromeとSafariでiframeのクリックを検出する方法をインターネット全体で検索しました。あきらめる寸前で、私はあなたの答えを見つけます。ありがとうございます!
ヒント:attachOnloadEvent()ではなくinit()関数を直接呼び出す方が、ソリューションの信頼性が高いことがわかりました。もちろん、これを行うには、iframe htmlの後でのみinit()を呼び出す必要があります。したがって、次のようになります。
<script>
var isOverIFrame = false;
function processMouseOut() {
isOverIFrame = false;
top.focus();
}
function processMouseOver() { isOverIFrame = true; }
function processIFrameClick() {
if(isOverIFrame) {
//was clicked
}
}
function init() {
var element = document.getElementsByTagName("iframe");
for (var i=0; i<element.length; i++) {
element[i].onmouseover = processMouseOver;
element[i].onmouseout = processMouseOut;
}
if (typeof window.attachEvent != 'undefined') {
top.attachEvent('onblur', processIFrameClick);
}
else if (typeof window.addEventListener != 'undefined') {
top.addEventListener('blur', processIFrameClick, false);
}
}
</script>
<iframe src="http://google.com"></iframe>
<script>init();</script>
これを行うと、イベントを親ドキュメントにバブリングできます。
$('iframe').load(function() {
var eventlist = 'click dblclick \
blur focus focusin focusout \
keydown keypress keyup \
mousedown mouseenter mouseleave mousemove mouseover mouseout mouseup mousemove \
touchstart touchend touchcancel touchleave touchmove';
var iframe = $('iframe').contents().find('html');
// Bubble events to parent
iframe.on(eventlist, function(event) {
$('html').trigger(event);
});
});
イベントリストを拡張して、さらに多くのイベントを表示します。
iframeを通じてプルされたソーシャルメディアボタンのクリックを追跡しなければならない状況に遭遇しました。ボタンをクリックすると、新しいウィンドウが開きます。これが私の解決策です:
var iframeClick = function () {
var isOverIframe = false,
windowLostBlur = function () {
if (isOverIframe === true) {
// DO STUFF
isOverIframe = false;
}
};
jQuery(window).focus();
jQuery('#iframe').mouseenter(function(){
isOverIframe = true;
console.log(isOverIframe);
});
jQuery('#iframe').mouseleave(function(){
isOverIframe = false;
console.log(isOverIframe);
});
jQuery(window).blur(function () {
windowLostBlur();
});
};
iframeClick();
http://jsfiddle.net/QcAee/406/
クリックすると元に戻り、マウスリーブイベントが発生すると上に移動するiframeの上に非表示のレイヤーを作成するだけです。
jQueryが必要
このソリューションは、iframe内の最初のクリックを伝播しません!
$("#invisible_layer").on("click",function(){
alert("click");
$("#invisible_layer").css("z-index",-11);
});
$("iframe").on("mouseleave",function(){
$("#invisible_layer").css("z-index",11);
});
iframe {
width: 500px;
height: 300px;
}
#invisible_layer{
position: absolute;
background-color:trasparent;
width: 500px;
height:300px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="message"></div>
<div id="invisible_layer">
</div>
<iframe id="iframe" src="//example.com"></iframe>
これは、iframeが親サイトと同じドメインのものである場合に確実に機能します。クロスドメインサイトではテストしていません。
$(window.frames['YouriFrameId']).click(function(event){ /* do something here */ });
$(window.frames['YouriFrameId']).mousedown(function(event){ /* do something here */ });
$(window.frames['YouriFrameId']).mouseup(function(event){ /* do something here */ });
jQueryがなければ、このようなことを試すことができますが、ここでも試していません。
window.frames['YouriFrameId'].onmousedown = function() { do something here }
結果をフィルタリングすることもできます。
$(window.frames['YouriFrameId']).mousedown(function(event){
var eventId = $(event.target).attr('id');
if (eventId == 'the-id-you-want') {
// do something
}
});
上記の回答と、iframeの外側をクリックせずに何度もクリックする機能を組み合わせます。
var eventListener = window.addEventListener('blur', function() {
if (document.activeElement === document.getElementById('contentIFrame')) {
toFunction(); //function you want to call on click
setTimeout(function(){ window.focus(); }, 0);
}
window.removeEventListener('blur', eventListener );
});
すべてのクリックをキャッチできます。アイデアは、クリックするたびにiFrameの外側の要素にフォーカスをリセットすることです。
<input type="text" style="position:fixed;top:-1000px;left:-1000px">
<div id="message"></div>
<iframe id="iframe" src="//example.com"></iframe>
<script>
focus();
addEventListener('blur', function() {
if(document.activeElement = document.getElementById('iframe')) {
message.innerHTML += 'Clicked';
setTimeout(function () {
document.querySelector("input").focus();
message.innerHTML += ' - Reset focus,';
}, 1000);
}
});
</script>
そこにあるように: JavaScriptを使用してiframeへのクリックを検出する
=> iframeTracker-jqueryを使用できます:
$('.carousel-inner .item').each(function(e) {
var item = this;
var iFrame = $(item).find('iframe');
if (iFrame.length > 0) {
iFrame.iframeTracker({
blurCallback: function(){
// Do something when iFrame is clicked (like firing an XHR request)
onItemClick.bind(item)(); // calling regular click with right context
console.log('IFrameClick => OK');
}
});
console.log('IFrameTrackingRegistred => OK');
}
})
Paul Draperの回答に基づいて、ブラウザーで他のタブを開くiframeがある場合に継続的に機能するソリューションを作成しました。フレームワーク上でのクリックを検出するためにページをアクティブのままに戻すと、これは非常に一般的な状況です。
focus();
$(window).blur(() => {
let frame = document.activeElement;
if (document.activeElement.tagName == "IFRAME") {
// Do you action.. here frame has the iframe clicked
let frameid = frame.getAttribute('id')
let frameurl = (frame.getAttribute('src'));
}
});
document.addEventListener("visibilitychange", function () {
if (document.hidden) {
} else {
focus();
}
});
コードはシンプルで、iframeがクリックされたときにフォーカスが失われたことをblurイベントが検出し、アクティブな要素がiframeであるかどうかをテストします(複数のiframeがある場合、誰が選択されたかを知ることができます)。この状況は、宣伝フレームがある場合によく起こります。 。
2番目のイベントは、ページに戻ったときにフォーカスメソッドをトリガーします。可視性変更イベントを使用します。
これは、ホバー+ブラーとアクティブエレメントトリックを使用した推奨アプローチを使用したソリューションです。ライブラリではなく、純粋なjsです。FF / Chromeで正常に動作します。ほとんどのアプローチは@Mohammed Radwanと同じですが、@ zone117xによって提案された別の方法を使用してFFのiframeクリックを追跡しますが、ユーザー設定を追加しないとwindow.focusが機能しないためです。
窓を前面に出すように要求します。ユーザー設定が原因で失敗する可能性があり、このメソッドが戻る前にウィンドウが最前面にあるとは限りません。
これが複合メソッドです:
function () {
const state = {};
(function (setup) {
if (typeof window.addEventListener !== 'undefined') {
window.addEventListener('load', setup, false);
} else if (typeof document.addEventListener !== 'undefined') {
document.addEventListener('load', setup, false);
} else if (typeof window.attachEvent !== 'undefined') {
window.attachEvent('onload', setup);
} else {
if (typeof window.onload === 'function') {
const oldonload = onload;
window.onload = function () {
oldonload();
setup();
};
} else {
window.onload = setup;
}
}
})(function () {
state.isOverIFrame = false;
state.firstBlur = false;
state.hasFocusAcquired = false;
findIFramesAndBindListeners();
document.body.addEventListener('click', onClick);
if (typeof window.attachEvent !== 'undefined') {
top.attachEvent('onblur', function () {
state.firstBlur = true;
state.hasFocusAcquired = false;
onIFrameClick()
});
top.attachEvent('onfocus', function () {
state.hasFocusAcquired = true;
console.log('attachEvent.focus');
});
} else if (typeof window.addEventListener !== 'undefined') {
top.addEventListener('blur', function () {
state.firstBlur = true;
state.hasFocusAcquired = false;
onIFrameClick();
}, false);
top.addEventListener('focus', function () {
state.hasFocusAcquired = true;
console.log('addEventListener.focus');
});
}
setInterval(findIFramesAndBindListeners, 500);
});
function isFF() {
return navigator.userAgent.search(/firefox/i) !== -1;
}
function isActiveElementChanged() {
const prevActiveTag = document.activeElement.tagName.toUpperCase();
document.activeElement.blur();
const currActiveTag = document.activeElement.tagName.toUpperCase();
return !prevActiveTag.includes('BODY') && currActiveTag.includes('BODY');
}
function onMouseOut() {
if (!state.firstBlur && isFF() && isActiveElementChanged()) {
console.log('firefox first click');
onClick();
} else {
document.activeElement.blur();
top.focus();
}
state.isOverIFrame = false;
console.log(`onMouseOut`);
}
function onMouseOver() {
state.isOverIFrame = true;
console.log(`onMouseOver`);
}
function onIFrameClick() {
console.log(`onIFrameClick`);
if (state.isOverIFrame) {
onClick();
}
}
function onClick() {
console.log(`onClick`);
}
function findIFramesAndBindListeners() {
return Array.from(document.getElementsByTagName('iframe'))
.forEach(function (element) {
element.onmouseover = onMouseOver;
element.onmouseout = onMouseOut;
});
}
}
仮定 -
これはソースフルとソースレスの両方のiframeで機能します
var ifr = document.getElementById("my-iframe");
var isMouseIn;
ifr.addEventListener('mouseenter', () => {
isMouseIn = true;
});
ifr.addEventListener('mouseleave', () => {
isMouseIn = false;
});
window.document.addEventListener("visibilitychange", () => {
if (isMouseIn && document.hidden) {
console.log("Click Recorded By Visibility Change");
}
});
window.addEventListener("beforeunload", (event) => {
if (isMouseIn) {
console.log("Click Recorded By Before Unload");
}
});
新しいタブが開かれる/同じページがアンロードされ、マウスポインターがiframe内にある場合、クリックが考慮されます