web-dev-qa-db-ja.com

JavaScriptを使用してIframeへのクリックを検出する

クロスドメインの場合、ユーザーがiframe内で何をしているのかを伝えることができないことを理解しています。ユーザーがiframeでクリックしたかどうかを追跡したいと思います。 divの上に非表示のiframeがあり、divがクリックイベントをiframeに渡すシナリオを想像します。

このようなことは可能ですか?もしそうなら、私はそれについてどうやって行きますか? iframesは広告であるため、使用されるタグを制御することはできません。

111
Russ Bradberry

このようなことは可能ですか?

いいえ。できるのは、マウスがiframeに入るのを検出することと、(確実ではありませんが)戻ってきたときを検出することです(つまり、他の場所で広告を通過するポインタと残り時間の差を計算しようとすることです)広告で)。

Iframeの上に非表示のdivがあり、divがクリックイベントをiframeに渡すシナリオを想像します。

いいえ、クリックイベントを偽造する方法はありません。

マウスダウンをキャッチすると、元のクリックがiframeに到達するのを防ぐことができます。マウスボタンが押されようとしていることを判別できた場合、クリックが通過するように見えないdivを邪魔にならないようにすることができますが、マウスダウンの直前に発生するイベントもありません。

たとえば、ポインターが静止したかどうかを確認することで、クリックしようとしていると推測して推測することができます。しかし、それは完全に信頼性が低く、失敗すると、クリックスルーを失ってしまいます。

36
bobince

これは確かに可能です。これは、Chrome、Firefox、およびIE 11(およびおそらくその他)で動作します。

focus();
var listener = window.addEventListener('blur', function() {
    if (document.activeElement === document.getElementById('iframe')) {
        // clicked
    }
    window.removeEventListener('blur', listener);
});

JSFiddle


警告:これは最初のクリックのみを検出します。私が理解するように、それはあなたが望むすべてです。

129
Paul Draper

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に「bannerid」が設定されます。あなたがしなければならないのは、次のように、ウィンドウがぼやけたときに「overiFrame」が設定されているかどうかをチェックすることです...

    $(window).blur( function() {
        if( overiFrame != -1 )
            $.post('log.php', {id:overiFrame}); /* example, do your stats here */
    });
});

マイナーな欠点を伴う非常にエレガントなソリューション:ユーザーがiFrameの上にマウスを置いたときにALT-F4を押すと、クリックとしてログに記録されます。 IE、Chrome、およびSafariは登録しませんでしたが、これはFireFoxでのみ発生しました。

Mohammed、非常に便利なソリューションに再び感謝します!

106
patrick

これは、IE8を含むすべてのブラウザーで機能する小さなソリューションです。

var monitor = setInterval(function(){
    var elem = document.activeElement;
    if(elem && elem.tagName == 'IFRAME'){
        clearInterval(monitor);
        alert('clicked!');
    }
}, 100);

ここでテストできます: http://jsfiddle.net/oqjgzsm0/

74
Dmitry Kochin

次のコードは、ユーザーがクリック/ホバーするか、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。

35
Mohammed Radwan

ちょうどこの解決策を見つけました...私はそれを試してみました、私はそれを愛していました..

デスクトップおよびモバイル向けのクロスドメインiframeで動作します!

まだ絶対確実かどうかわからない

window.addEventListener('blur',function(){
      if(document.activeElement.id == 'CrossDomainiframeId'){
        //do something :-)
      }
});

ハッピーコーディング

10
Tony

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();

これを実現するには、ウィンドウ要素で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)
        }
    });
});
5
Vince

Mohammed Radwan、あなたのソリューションはエレガントです。 FirefoxとIEでiframeのクリックを検出するには、document.activeElementとタイマーを使用した簡単なメソッドを使用できます。ただし、ChromeとSafari。あきらめる寸前で、あなたの答えを見つけます。ありがとうございます!

いくつかのヒント: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>
3
zone117x

これはすべてのブラウザ(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>

3
sidanmor

私は、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();
3
pizza-r0b

これを実行して、イベントを親ドキュメントにバブルできます。

$('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);
    });
});

より多くのイベントのイベントリストを拡張するだけです。

3
Taner Topal

http://jsfiddle.net/QcAee/406/

クリックすると元に戻り、mouseleaveイベントが発生すると上に移動する非表示のレイヤーを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>
2
r1si

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
  }
});
1
Jonathan Tonge

そこにあるように: 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');
    }
})
0
Mickaël

ここでは、ホバー+ぼかしとアクティブな要素のトリックを使用した推奨アプローチを使用したソリューションを示します。ライブラリではなく、純粋なjsです。 FF/Chromeで正常に動作します。 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;
            });
    }
}
0
slesh

私はあなたが次のようなことができると信じています:

$('iframe').contents().click(function(){function to record click here });

jQueryを使用してこれを実現します。

0
Daniel Sellers

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がクリックされたときにフォーカスの喪失を検出し、アクティブな要素がiframeかどうかをテストします(複数のiframeがある場合、誰が選択されたかを知ることができます)。 。

2番目のイベントは、ページに戻ったときにフォーカスメソッドをトリガーします。可視性変更イベントに使用されます。

0
freedeveloper