151

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

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

4

23 に答える 23

181

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

const message = document.getElementById("message");

// main document must be focused in order for window blur to fire when the iframe is interacted with. 
// There's still an issue that if user interacts outside of the page and then click iframe first without clicking page, the following logic won't run. But since the OP is only concerned about first click this shouldn't be a problem.
window.focus()

window.addEventListener("blur", () => {
  setTimeout(() => {
    if (document.activeElement.tagName === "IFRAME") {
      message.textContent = "clicked " + Date.now();
      console.log("clicked");
    }
  });
}, { once: true });
<div id="message"></div>
<iframe width="50%" height="300" src="//example.com"></iframe>

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

于 2014-04-22T22:09:22.527 に答える
113

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を押すと、クリックとしてログに記録されます。これはFireFoxでのみ発生しましたが、IE、Chrome、Safariは登録しませんでした。

再びモハメッド、非常に便利なソリューションに感謝します!

于 2011-11-12T00:18:54.817 に答える
112

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

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

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

于 2015-08-21T10:31:06.757 に答える
39

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

いいえ。できることは、マウスがiframeに入るのを検出することだけです。また、マウスが戻ってきたときに(つまり、どこか別の場所で広告を通過するポインターと、長引くことの違いを理解しようとする)可能性があります。広告上)。

iframeの上に非表示のdivがあり、divがクリックイベントをiframeに渡すシナリオを想像してみてください。

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

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

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

于 2010-03-04T17:46:35.717 に答える
37

次のコードは、ユーザーが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。

于 2010-06-13T09:44:11.103 に答える
12

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

デスクトップとモバイルのクロスドメインiframeで動作します!

それが絶対確実かどうかはまだわかりません

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

ハッピーコーディング

于 2015-06-18T00:04:56.667 に答える
5

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();
于 2013-02-14T23:52:16.850 に答える
5

これは、ウィンドウ要素のぼかしイベントを使用して実現できます。

これは、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)
        }
    });
});
于 2013-04-03T17:29:41.443 に答える
4

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>

于 2016-05-10T09:07:14.983 に答える
4

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

于 2016-09-18T15:53:22.400 に答える
3

モハメッド・ラドワン、あなたのソリューションはエレガントです。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>
于 2011-06-12T17:43:43.143 に答える
3

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

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

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

于 2013-04-08T12:46:00.197 に答える
3

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();
于 2014-01-29T17:58:31.090 に答える
3

上記の回答と、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 );
    });
于 2019-09-20T06:44:31.530 に答える
1

これは、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
  }
});
于 2012-04-07T04:14:42.973 に答える
1

すべてのクリックをキャッチできます。クリックするたびに、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>

JSFiddle

于 2020-04-13T16:16:25.663 に答える
0

そこにあるように:JavaScriptを使用してIframeへのクリックを検出

=> iframeTrackerを使用できます-jquery

$('.carousel-inner .item').each(function(e) {
    var item = this;
    var iFrame = $(item).find('iframe');
    if (iFrame.length &gt; 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 =&gt; OK');
            }
        });
        console.log('IFrameTrackingRegistred =&gt; OK');
    }
})
于 2018-01-20T23:43:30.000 に答える
0

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

コードは単純で、blurイベントは、iframeがクリックされたときにフォーカスが失われたことを検出し、アクティブな要素がiframeであるかどうかをテストします(複数のiframeがある場合は、誰が選択されたかを知ることができます)。 。

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

于 2018-08-25T01:21:14.177 に答える
0

これは、ホバー+ブラーとアクティブな要素のトリックを使用した提案されたアプローチを使用したソリューションです。ライブラリではなく、純粋なjsだけです。FF/Chromeで正常に動作します。window.focusは追加のユーザー設定なしでは機能しないため、@ zone117xによって提案された別の方法を使用してFFのiframeクリックを追跡することを除いて、ほとんどのアプローチは@MohammedRadwanが提案したものと同じです。

窓を正面に持ってくるように要求します。ユーザー設定が原因で失敗する可能性があり、このメソッドが戻る前にウィンドウが最前面にあるとは限りません。

複合メソッドは次のとおりです。

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;
            });
    }
}
于 2018-10-04T11:46:42.200 に答える
0

仮定-

  1. スクリプトはiframeの外で実行されますが、最も外側のwindow.topウィンドウでは実行されません。(最も外側のウィンドウの場合、他のぼかしソリューションで十分です)
  2. 新しいページが開かれ、現在のページ/新しいタブの新しいページが置き換えられ、コントロールが新しいタブに切り替わります。

これは、ソースフルiframeとソースレス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内にある場合、クリックが考慮されます

于 2020-07-30T14:14:31.310 に答える
0

同僚と私は、Brian Trumpsettと同様の問題を抱えており、このスレッドが非常に役立つことがわかりました。キオスクにはiframe内にアニメーションがあり、タイマーを設定するにはページのアクティビティを追跡する必要があります。

ここで提案されているように、クリックを追跡するのではなく、クリックごとにフォーカスの変更を検出して元に戻します。次のコードは、SafariとChromeを使用するmacOSでは問題ありませんが、FireFoxでは機能しません(なぜですか?)。

var eventListener = window.addEventListener('blur', function() {
if (document.activeElement.classList && document.activeElement.classList[0] == 'contentiFrame') {
    refresh(); //function you want to call on click
            setTimeout(function(){ window.focus(); }, 1);
}
    window.removeEventListener('blur', eventListener );
});

問題は、WindowsではChromeでもFireFoxでも動作しないため、キオスクが機能しないことです。なぜそれが機能しないのか知っていますか?Windowsで動作させるためのソリューションはありますか?

于 2021-03-21T14:13:36.073 に答える
0

私のアプローチは、上記のPaulDraperによって提案されたものと似ていました。ただし、コードの実行に間に合うようにactiveElementが更新されなかったため、Firefoxでは機能しませんでした。少し待ちます。

これは、iframeにタブで移動した場合にも発生します。私のユースケースでは問題ありませんが、そのキーを押すためにフィルタリングすることができます。

addEventListenerOnIframe() {
    window.addEventListener('blur', this.onBlur);
}


onBlur = () => {
    setTimeout(() => {
        let activeElement = document.activeElement;
        let iframeElement = document.querySelector('iframe');
        if (activeElement === iframeElement) {
            
            //execute your code here

            //we only want to listen for the first time we click into the iframe
            window.removeEventListener('blur', this.onBlur);
        }
    }, 500);
};
于 2021-07-22T13:47:42.370 に答える
-1

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

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

これを実現するためにjQueryを使用します。

于 2011-07-12T17:10:54.150 に答える