Wykrywanie kliknięć w Iframe przy użyciu JavaScript
Rozumiem, że nie można powiedzieć, co użytkownik robi wewnątrz iframe
, jeśli jest to cross domain. To, co chciałbym zrobić, to śledzić, czy użytkownik kliknął w ogóle w iframe
. Wyobrażam sobie scenariusz, w którym na górze iframe
znajduje się niewidoczne div
, a div
po prostu przekaże Zdarzenie kliknięcia iframe
.
18 answers
Czy coś takiego jest możliwe?Nie. Wszystko, co możesz zrobić, to wykryć mysz wchodzącą do iframe i potencjalnie (choć nie niezawodnie), gdy wróci (np. próba ustalenia różnicy między wskaźnikiem przechodzącym nad reklamą w drodze gdzie indziej a utrzymującym się na reklamie).
Wyobrażam sobie scenariusz, w którym na górze iframe znajduje się niewidoczny div, a div po prostu przekaże Zdarzenie click do iframe.
Nie, Nie ma sposobu na sfałszowanie zdarzenia kliknięcia.
Łapiąc mousedown, uniemożliwisz oryginalnemu kliknięciu dotarcie do iframe. Jeśli można określić, kiedy przycisk myszy miał być naciśnięty można spróbować uzyskać niewidoczny div z drogi tak, że kliknięcie przejdzie... ale nie ma również żadnego zdarzenia, które strzela tuż przed mousedown.
Można spróbować odgadnąć, na przykład patrząc, czy wskaźnik doszedł do spoczynku, zgadując kliknięcie może nadejść. Ale jest to całkowicie zawodne, a jeśli zawiedziesz, stracisz tylko kliknięcie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-04 17:46:35
Na podstawie odpowiedzi Mohammeda Radwana wymyśliłem następujące rozwiązanie jQuery. Zasadniczo to, co robi, to śledzenie tego, co ludzie iFrame unoszą się. Następnie, jeśli okno się rozmywa, najprawdopodobniej oznacza to, że użytkownik kliknął baner iframe.
Iframe powinien być umieszczony w div z id, aby upewnić się, że wiesz, który iframe użytkownik kliknął na:<div class='banner' bannerid='yyy'>
<iframe src='http://somedomain.com/whatever.html'></iframe>
<div>
Więc:
$(document).ready( function() {
var overiFrame = -1;
$('iframe').hover( function() {
overiFrame = $(this).closest('.banner').attr('bannerid');
}, function() {
overiFrame = -1
});
... to utrzymuje overiFrame na poziomie -1, gdy żadne ramki iframe nie są zawisłe lub ustawiony "bannerid" w zawijaniu div gdy ramka iframe jest zawieszona. Wszystko co musisz zrobić, to sprawdzić, czy 'overiFrame' jest ustawiony, gdy okno się rozmywa, w ten sposób: ...
$(window).blur( function() {
if( overiFrame != -1 )
$.post('log.php', {id:overiFrame}); /* example, do your stats here */
});
});
Bardzo eleganckie rozwiązanie z drobnym minusem: jeśli użytkownik naciśnie ALT-F4 po najechaniu kursorem myszy na ramkę iFrame, zarejestruje ją jako kliknięcie. Stało się to tylko w Firefoksie, jednak IE, Chrome i Safari tego nie zarejestrowały.
Jeszcze raz dziękuję Mohammed, bardzo przydatne rozwiązanie!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-12 00:18:54
Jest to z pewnością możliwe. Działa to w Chrome, Firefox i IE 11 (i prawdopodobnie innych).
focus();
var listener = window.addEventListener('blur', function() {
if (document.activeElement === document.getElementById('iframe')) {
// clicked
}
window.removeEventListener('blur', listener);
});
Zastrzeżenie: wykrywa tylko pierwsze kliknięcie. Jak rozumiem, tylko tego chcesz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-13 11:51:30
Jest to małe rozwiązanie, które działa we wszystkich przeglądarkach, nawet IE8:
var monitor = setInterval(function(){
var elem = document.activeElement;
if(elem && elem.tagName == 'IFRAME'){
clearInterval(monitor);
alert('clicked!');
}
}, 100);
Możesz go przetestować tutaj: http://jsfiddle.net/oqjgzsm0/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-21 10:31:06
Poniższy kod pokaże ci, jeśli użytkownik kliknie / najedzie lub wyjdzie poza ramkę 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>
Musisz zastąpić src w ramce iframe własnym linkiem. Mam nadzieję, że to pomoże. Pozdrawiam, Mo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-12 12:58:50
Właśnie znalazłem to rozwiązanie... Próbowałem, podobało mi się..
Działa na cross domain iframes dla komputerów stacjonarnych i mobilnych!
Nie wiem, czy to jest niezawodne jeszcze
window.addEventListener('blur',function(){
if(document.activeElement.id == 'CrossDomainiframeId'){
//do something :-)
}
});
Happy coding
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-18 00:04:56
Można to osiągnąć za pomocą zdarzenia rozmycie na elemencie okna.
Oto wtyczka jQuery do śledzenia kliknięcia na iframes (uruchomi niestandardową funkcję zwrotną po kliknięciu iframe) : https://github.com/finalclap/iframeTracker-jquery
Użyj go tak:
jQuery(document).ready(function($){
$('.iframe_wrap iframe').iframeTracker({
blurCallback: function(){
// Do something when iframe is clicked (like firing an XHR request)
}
});
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-03 17:29:41
Zobacz http://jsfiddle.net/Lcy797h2 / dla mojego dlugiego rozwiazania ktore nie dziala niezawodnie w IE
$(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();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-30 16:37:18
Mohammed Radwan, Twoje rozwiązanie jest eleganckie. Aby wykryć kliknięcia iframe w Firefoksie i IE, możesz użyć prostej metody z dokumentem.activeElement i timer, jednak... Przeszukałem cały interwebs pod kątem metody wykrywania kliknięć na iframe w Chrome i Safari. U progu poddania się, znajduję Twoją odpowiedź. Dziękuję Panu!
Kilka porad: Odkryłem, że Twoje rozwiązanie jest bardziej niezawodne podczas bezpośredniego wywoływania funkcji init (), a nie poprzez attachOnloadEvent (). Z oczywiście aby to zrobić, musisz wywołać INIT () dopiero po iFrame html. Więc wyglądałoby to tak:
<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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-12 17:57:31
Możesz to zrobić, aby dodać zdarzenia do dokumentu nadrzędnego:
$('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);
});
});
Po prostu rozszerz listę wydarzeń o więcej wydarzeń.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-08 12:46:00
Wpadłem na sytuację, w której musiałem śledzić kliknięcia przycisku mediów społecznościowych wciśniętego przez ramkę iframe. Nowe okno zostanie otwarte po kliknięciu przycisku. Oto moje rozwiązanie:
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();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-29 17:58:31
To działa dla mnie na wszystkich przeglądarkach (wliczając Firefoksa)
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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-22 15:06:09
Http://jsfiddle.net/QcAee/406/
Po prostu utwórz niewidoczną warstwę nad ramką iframe, która powróci po kliknięciu i przejdzie w górę, gdy zdarzenie mouseleave zostanie wywołane !!
Need jQuery
To rozwiązanie nie propaguje pierwszego kliknięcia wewnątrz 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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-10 09:13:03
To zdecydowanie działa, jeśli ramka iframe pochodzi z tej samej domeny, co Twoja Strona nadrzędna. Nie testowałem go dla witryn między domenami.
$(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 */ });
Bez jQuery można spróbować czegoś takiego, ale znowu nie próbowałem tego.
window.frames['YouriFrameId'].onmousedown = function() { do something here }
Możesz nawet filtrować swoje wyniki:
$(window.frames['YouriFrameId']).mousedown(function(event){
var eventId = $(event.target).attr('id');
if (eventId == 'the-id-you-want') {
// do something
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-07 04:14:42
Wierzę, że możesz zrobić coś takiego:
$('iframe').contents().click(function(){function to record click here });
Używanie jQuery do tego celu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-12 17:10:54
Jak tam znaleźć: wykrywanie Kliknięcia w Iframe przy użyciu JavaScript
= > Możemy użyć 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');
}
})
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-20 23:43:30
Bazując na odpowiedzi Paula Drapera, stworzyłem rozwiązanie, które działa nieprzerwanie, gdy masz Iframes, które otwierają inną kartę w przeglądarce. Po powrocie strona nadal będzie aktywna, aby wykryć kliknięcie na frameworku, jest to bardzo częsta sytuacja:
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();
}
});
Kod jest prosty, Zdarzenie rozmycie wykrywa utratę ostrości po kliknięciu ramki iframe i sprawdza, czy aktywny element jest ramką iframe (jeśli masz kilka ramek iframe, możesz wiedzieć, kto został wybrany) często, gdy masz ramki reklamowe.
Drugie zdarzenie uruchamia metodę focus po powrocie do strony. służy do zdarzenia zmiany widoczności.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-25 01:21:14
Oto rozwiązanie przy użyciu sugerowanych podejść z hover+blur i active element tricks, Nie żadnych bibliotek, tylko czysty js. Działa dobrze dla FF / Chrome. Przeważnie approach jest taki sam jak zaproponowany przez @Mohammeda Radwana, z tym, że używam innej metody zaproponowanej przez @zone117x do śledzenia kliknięć iframe dla FF, ponieważ okno.focus nie działa bez dodania ustawienia użytkownika :
Prosi o przeniesienie okna na front. Może się nie udać z powodu ustawienia użytkownika i okno nie jest gwarantowane przed ta metoda zwraca.
Oto metoda złożona:
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;
});
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-04 11:46:42