Pregunta

Yo entiendo que no es posible decir lo que el usuario está haciendo dentro de un iframe si se trata de dominios. Lo que me gustaría hacer es realizar un seguimiento de si el usuario ha hecho clic en absoluto en el iframe. Me imagino un escenario donde hay una div invisibles en la parte superior de la iframe y la div se acaba luego pasar el evento de clic a la iframe.

Es algo como esto posible? Si es así, entonces ¿cómo puedo hacerlo? El iframes son anuncios, así que no tengo control sobre las etiquetas que se utilizan.

¿Fue útil?

Solución

  

Es algo como esto posible?

No. Todo lo que se puede hacer es detectar el ratón de entrar en el iframe, y potencialmente (aunque no de forma fiable) cuando se trata de vuelta (es decir. Tratando de averiguar la diferencia entre el puntero pasa sobre el anuncio en su camino a otro lugar frente al persistente en el ad).

  

Me imagino un escenario en el que hay un div invisible en la parte superior del marco flotante y el div se acaba luego pasar el evento click para el iframe.

No, no hay manera de falsificar un evento de clic.

Por agarrar la mousedown desea evitar el clic original a partir de llegar al marco flotante. Si se pudiera determinar cuando el botón del ratón estaba a punto de ser presionado usted podría tratar de conseguir el div invisible fuera del camino para que el clic iría a través ... pero también hay ningún evento que dispara justo antes de una mousedown.

Se podría tratar de adivinar, por ejemplo, mirando a ver si el puntero ha llegado a descansar, adivinando un clic podría estar a punto de llegar. Pero es totalmente fiable, y si no se acaba de perder a sí mismo un click-through.

Otros consejos

Esto es ciertamente posible. Esto funciona de Chrome, Firefox e IE 11 (y probablemente otros).

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

jsFiddle


Advertencia: Esto sólo se detecta la primera posición. Según tengo entendido, es decir todo lo que quiera.

Sobre la base de la respuesta de Mohammed Radwan me ocurrió la siguiente solución jQuery. Básicamente lo que hace es no perder de vista lo que la gente se ciernen iFrame. Entonces, si las faltas de definición de ventana que medios más probables que el usuario hace clic en el banner de marco flotante.

el iframe debe ser puesto en un div con un id, para asegurarse de que sabe lo que iframe el usuario hace clic en:

<div class='banner' bannerid='yyy'>
    <iframe src='http://somedomain.com/whatever.html'></iframe>
<div>

así:

$(document).ready( function() {
    var overiFrame = -1;
    $('iframe').hover( function() {
        overiFrame = $(this).closest('.banner').attr('bannerid');
    }, function() {
        overiFrame = -1
    });

... esto mantiene overiFrame a -1 cuando se cernían Sin marcos, o el conjunto 'bannerid' en el div de envasado una vez se asoma un iframe. Todo lo que tiene que hacer es comprobar si 'overiFrame' se establece cuando las faltas de definición de ventanas, así: ...

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

solución muy elegante con un pequeño inconveniente: si un usuario presiona ALT-F4 cuando se pasa el ratón sobre un marco flotante se registrará como un clic. Esto sólo ocurrió en Firefox sin embargo, Internet Explorer, Chrome y Safari no se registraron ella.

Gracias de nuevo Mohammed, solución muy útil!

Este es pequeña solución que funciona en todos los navegadores, incluso IE8:

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

Puedes probarlo aquí: http://jsfiddle.net/oqjgzsm0/

El siguiente código le mostrará si el usuario haga clic / vuelo estacionario o desplazarse fuera del marco flotante: -

<!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>

Es necesario sustituir el src en el marco flotante con su propio enlace. Espero que esto ayudará. Saludos, Mo.

Sólo encontró esta solución ... Lo probé, me encantó ..

Obras para iframes entre dominios para escritorio y móviles mediante

No sé si es a prueba de tontos todavía

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

feliz de codificación

Se puede lograr esto mediante el uso de la falta de definición en caso de elemento de ventana.

Aquí es un plugin de jQuery para el seguimiento, haga clic en marcos flotantes (que se disparará una función de devolución de llamada personalizado cuando se hace clic en un iframe): https://github.com/finalclap/iframeTracker-jquery

El uso de esta manera:

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/ para mi solución de largo aliento que no lo hace funcionar de forma fiable en 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, Su solución es elegante. Para detectar iframe hace clic en Firefox e IE, se puede utilizar un método simple con document.activeElement y un temporizador, sin embargo ... He buscado en todo el interwebs de un método para detectar clics en un iframe en Chrome y Safari. Al borde de renunciar, encuentro la respuesta. Gracias, señor!

Algunos consejos: He encontrado la solución a ser más fiable cuando se llama a la función init () directamente, en lugar de a través de attachOnloadEvent (). Por supuesto, para hacer eso, debe llamar a init () sólo después de que el HTML iframe. Por lo tanto, sería algo como:

<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>

Se puede hacer esto a los eventos de la burbuja de documento padre:

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

Sólo extender la eventlist para más eventos.

me encontré con una situación en la que tenía que realizar un seguimiento de los clics en un botón de medios de comunicación social aspirado a través de un iframe. se abre una nueva ventana cuando se hace clic en el botón. Aquí estaba mi solución:

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

Esto funciona para mí en todos los navegadores (Firefox incluido)

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/

Simplemente haga una capa invisible sobre el iframe que se remontan al hacer clic y listo cuando se despedirá de evento open !!
Necesidad jQuery

esta solución no se propagan primera posición dentro de marco flotante!

$("#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>

Esto definitivamente funciona si el marco flotante es del mismo dominio que el sitio primario. Yo no lo he probado para los sitios de varios dominios.

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

Sin jQuery que podría intentar algo como esto, pero de nuevo no he probado esto.

window.frames['YouriFrameId'].onmousedown = function() { do something here }

Incluso puede filtrar los resultados:

$(window.frames['YouriFrameId']).mousedown(function(event){   
  var eventId = $(event.target).attr('id');      
  if (eventId == 'the-id-you-want') {
   //  do something
  }
});

Creo que se puede hacer algo como:

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

usando jQuery para lograr esto.

Como encontrar allí: Detectar Haga clic en el marco flotante utilizando JavaScript

=> Podemos usar 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');
    }
})

Con base en la respuesta de Paul Draper, he creado una solución que trabajar de forma continua cuando se tiene marcos que otra pestaña abierta en el navegador. Cuando regresa la página continuará siendo activa para detectar el clic sobre el marco, esta es una situación muy común:

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

El código es simple, el evento desenfoque detectar la pérdida de foco cuando se hace clic en el iframe, y prueba si el elemento activo es el iframe (si tiene varios iframe se puede saber que fue seleccionado) esta situación es frecuente cuando se tienen marcos publicitarios.

El segundo evento de disparo de un método de enfoque cuando regrese a la página. se utiliza el evento de cambio de visibilidad.

Aquí está la solución utilizando enfoques sugeridos con vuelo estacionario + desenfoque y trucos elemento activo, no cualquier bibliotecas, sólo js puros. Funciona bien para FF / cromo. Parcialmente approache es igual que @Mohammed Radwan propuso, excepto que yo uso diferente método propuesto por @ zone117x para rastrear iframe hacer clic para FF, porque window.focus no funciona sin la adición configuración de usuario :

  

Hace una petición para traer la ventana al frente. Se puede fallar debido a   la configuración del usuario y la ventana no se garantiza que sea más frontal antes   este devuelve el método.

Aquí es el método compuesto:

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 combinación anterior respuesta con posibilidad de hacer clic una y otra vez sin hacer clic iframe exterior.

    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 );
    });
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top