Rileva Clicca in Iframe utilizzando JavaScript
-
24-09-2019 - |
Domanda
ho capito che non è possibile dire ciò che l'utente sta facendo all'interno di un iframe
se è di dominio croce. Quello che vorrei fare è monitorare se l'utente fa clic a tutti nella iframe
. Immagino uno scenario in cui v'è una div
invisibile sulla parte superiore del iframe
e la div
sarà solo quindi passare l'evento click al iframe
.
E 'qualcosa di simile a questo possibile? Se lo è, allora come potrei fare a questo proposito? Il iframes
sono annunci, quindi non ho alcun controllo sui tag che vengono utilizzati.
Soluzione
E 'qualcosa di simile a questo possibile?
No. Tutto quello che puoi fare è di rilevare il mouse andare in iframe, e potenzialmente (anche se non in modo affidabile) quando si tratta di nuovo fuori (es. Cercando di capire la differenza tra il puntatore passa sopra l'annuncio sulla sua strada da qualche altra parte contro persistente sul annuncio).
Mi immagino uno scenario in cui c'è un div invisibile sulla parte superiore del iframe e il div sarà solo quindi passare l'evento click per l'iframe.
No, non c'è modo di falsificare un evento click.
Per la cattura del mousedown che ci impedisce l'originale click di raggiungere l'iframe. Se si potesse determinare quando il pulsante del mouse stava per essere premuto si potrebbe cercare di ottenere il div invisibile fuori del modo in modo che il clic sarebbe passare attraverso ... ma c'è anche nessun caso che gli incendi appena prima di un mousedown.
Si potrebbe provare a indovinare, ad esempio, cercando di vedere se il puntatore è venuto a riposare, indovinare un click potrebbe essere sul punto di venire. Ma è del tutto inaffidabile, e se non si riesce hai solo te stesso perso un click-through.
Altri suggerimenti
Questa è certamente possibile. Questo funziona in Chrome, Firefox, e IE (e probabilmente altri) 11.
focus();
var listener = window.addEventListener('blur', function() {
if (document.activeElement === document.getElementById('iframe')) {
// clicked
}
window.removeEventListener('blur', listener);
});
Caveat: Questo rileva solo al primo scatto. Mi pare di capire, che è tutto quello che vuoi.
In base a risposta di Mohammed Radwan mi si avvicinò con la seguente soluzione jQuery. Fondamentalmente ciò che fa è tenere traccia di quello iFrame persone sono in bilico. Poi, se le sfocature finestra che molto probabilmente significa che l'utente cliccato il banner iframe.
l'iframe dovrebbe essere messo in un div con un id, per assicurarsi di sapere che iframe l'utente fa clic su:
<div class='banner' bannerid='yyy'>
<iframe src='http://somedomain.com/whatever.html'></iframe>
<div>
così:
$(document).ready( function() {
var overiFrame = -1;
$('iframe').hover( function() {
overiFrame = $(this).closest('.banner').attr('bannerid');
}, function() {
overiFrame = -1
});
... questo mantiene overiFrame a -1 quando non sono iFrames libravano, o 'bannerid' insieme nel div avvolgimento quando un iframe gli passa. Tutto quello che dovete fare è controllare se 'overiFrame' è impostato quando lo sfocature finestra, in questo modo: ...
$(window).blur( function() {
if( overiFrame != -1 )
$.post('log.php', {id:overiFrame}); /* example, do your stats here */
});
});
soluzione molto elegante con un minore rovescio della medaglia: se un utente preme ALT-F4 quando si passa il mouse su un iFrame si registrerà come un click. Questo è accaduto solo in Firefox, però, IE, Chrome e Safari non hanno registrato esso.
Grazie ancora Mohammed, soluzione molto utile!
Questa è piccola soluzione che funziona in tutti i browser, anche IE8:
var monitor = setInterval(function(){
var elem = document.activeElement;
if(elem && elem.tagName == 'IFRAME'){
clearInterval(monitor);
alert('clicked!');
}
}, 100);
È possibile verificare qui: http://jsfiddle.net/oqjgzsm0/
Il codice seguente vi mostrerà se l'utente clicca / hover o spostare fuori dalla 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>
È necessario sostituire lo src del iframe con il proprio collegamento. Spero che questo vi aiuterà. Saluti, Mo.
Appena trovato questa soluzione ... Ho provato, mi è piaciuto ..
Opere per iframe dominio trasversali per desktop e! Mobili
Non so se è infallibile ancora
window.addEventListener('blur',function(){
if(document.activeElement.id == 'CrossDomainiframeId'){
//do something :-)
}
});
codifica Felice
È possibile raggiungere questo obiettivo utilizzando l'evento sfocatura elemento della finestra.
Ecco un plugin jQuery per il monitoraggio click sul iframe (che verrà generato una funzione di callback personalizzata quando un IFRAME si fa clic): https://github.com/finalclap/iframeTracker-jquery
Usa in questo modo:
jQuery(document).ready(function($){
$('.iframe_wrap iframe').iframeTracker({
blurCallback: function(){
// Do something when iframe is clicked (like firing an XHR request)
}
});
});
http://jsfiddle.net/Lcy797h2/ per la mia soluzione prolisso che non lo fa funzionare in modo affidabile in 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();
Mohammed Radwan, La vostra soluzione è elegante. Per rilevare iframe scatta in Firefox e IE, è possibile utilizzare un metodo semplice con document.activeElement e un timer, però ... Ho cercato in tutto l'interwebs per un metodo per rilevare i clic su un iframe in Chrome e Safari. Al punto di rinunciare, ho trovato la risposta. Grazie, signore!
Alcuni consigli: Ho trovato la soluzione per essere più affidabile quando si chiama la funzione init () direttamente, piuttosto che attraverso attachOnloadEvent (). Naturalmente per fare questo, è necessario chiamare init () solo dopo che il codice HTML iframe. Quindi sarebbe simile:
<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>
Si può fare questo ad eventi bolla al documento principale:
$('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);
});
});
Basta estendere l'EventList per più eventi.
mi sono imbattuto in una situazione in cui ho dovuto monitorare i clic su un pulsante social media tirato attraverso un iframe. Una nuova finestra potrebbe essere aperto quando il pulsante è stato premuto. Qui era la mia soluzione:
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();
Questo funziona per me su tutti i browser (incluso 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>
http://jsfiddle.net/QcAee/406/
Basta fare uno strato invisibile sopra l'iframe che vanno indietro quando cliccare e andare su quando sarà licenziato evento mouseLeave !!
Necessità jQuery
questa soluzione non si propagano primo clic all'interno 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>
Questo funziona sicuramente se l'iframe è dallo stesso dominio come il vostro sito padre. Non ho ancora testato per i siti cross-domain.
$(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 */ });
Senza jQuery si potrebbe provare qualcosa di simile, ma ancora una volta non ho provato questo.
window.frames['YouriFrameId'].onmousedown = function() { do something here }
È anche possibile filtrare i risultati:
$(window.frames['YouriFrameId']).mousedown(function(event){
var eventId = $(event.target).attr('id');
if (eventId == 'the-id-you-want') {
// do something
}
});
Io credo che si può fare qualcosa di simile:
$('iframe').contents().click(function(){function to record click here });
utilizzando jQuery per raggiungere questo obiettivo.
Per quanto trovato lì: rilevare Clicca in Iframe utilizzando JavaScript
=> Possiamo usare 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');
}
})
In base nella risposta di Paul Draper, ho creato una soluzione che opera continuamente quando si ha Iframe che aprono un'altra scheda nel browser. Quando si torna alla pagina continuerà ad essere attivo per rilevare il clic sopra il quadro, questa è una situazione molto comune:
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();
}
});
Il codice è semplice, l'evento sfocatura di rilevare la perdita di messa a fuoco quando l'iframe viene cliccato, e verificare se l'elemento attivo è l'iframe (se si dispone di più iframe si può sapere che è stato selezionato) questa situazione è frequente quando si hanno cornici pubblicità.
Il secondo trigger dell'evento un metodo di messa a fuoco quando si torna alla pagina. viene utilizzato l'evento di modifica visibilità.
Ecco la soluzione utilizzando approcci suggeriti con hover + sfocatura e trucchi elemento attivo, non tutte le librerie, a soli js puri. Funziona bene per FF / Chrome. Per lo più approache è lo stesso come proposto @Mohammed Radwan, se non che io uso diversa metodologia proposta da @ zone117x per tenere traccia iframe clicca per FF, perché window.focus non funziona senza aggiunta impostazioni utente :
fa una richiesta per portare la finestra in primo piano. Si potrebbe non riuscire a causa di le impostazioni utente e la finestra non è garantito di essere in primo piano prima di Questo metodo restituisce.
Ecco metodo composto:
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;
});
}
}
La combinazione di sopra di risposta con possibilità di cliccare più volte senza fare clic iframe fuori.
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 );
});