59

I have an iframe on a page, coming from a 3rd party (an ad). I'd like to fire a click event when that iframe is clicked in (to record some in-house stats). Something like:

$('#iframe_id').click(function() {
    //run function that records clicks
});

..based on HTML of:

<iframe id="iframe_id" src="http://something.com"></iframe>

I can't seem to get any variation of this to work. Thoughts?

Justin Lucente
  • 1,151
  • 1
  • 8
  • 9

13 Answers13

40

There's no 'onclick' event for an iframe, but you can try to catch the click event of the document in the iframe:

document.getElementById("iframe_id").contentWindow.document.body.onclick = 
function() {
  alert("iframe clicked");
}

EDIT Though this doesn't solve your cross site problem, FYI jQuery has been updated to play well with iFrames:

$('#iframe_id').on('click', function(event) { });

Update 1/2015 The link to the iframe explanation has been removed as it's no longer available.

Note The code above will not work if the iframe is from different domain than the host page. You can still try to use hacks mentioned in comments.

Dan
  • 55,715
  • 40
  • 116
  • 154
Traveling Tech Guy
  • 27,194
  • 23
  • 111
  • 159
  • 2
    Thanks, this works nicely, but only for content from my domain. If I try to load in 3rd party content from another domain, the click event doesn't fire. I've ran into some other posts on the web mentioning something similar...basically, you can play with iframe content, but only if its your own. I would definitely be dealing with only 3rd party content. Hmm, any other ideas? – Justin Lucente Oct 23 '09 at 18:24
  • 6
    Yes, actually. Try putting a transparent div on top of the iframe (use position: absolute). You can then catch clicks on that div. Don't forget to pass them down to the iframe (works only if it's a simple iframe content - if it contains its own even handling - don't use this method). – Traveling Tech Guy Oct 23 '09 at 19:34
  • Just to update: I've tried the absolute positioning, and all events were ignored if there was 3rd party content in the iframe. I don't think this one is going to happen, but I greatly appreciate the fact that you put forth some help. – Justin Lucente Oct 27 '09 at 20:09
  • No problem - that's what we're here for :) Sorry it didn't work out. – Traveling Tech Guy Oct 28 '09 at 04:51
  • @JustinLucente Are you sure the div was OVER and not UNDER the iframe? Try setting the z-index if you aren't. – 11684 Apr 29 '12 at 18:02
  • The link in the answer is dead. – alex Jan 27 '15 at 03:14
  • Indeed it is - this link is from 2009, and I guess that blog is no longer up :(. Will update answer. – Traveling Tech Guy Jan 27 '15 at 19:24
  • 1
    Archive.org is our friend. ;^) [Archived blog link](https://web.archive.org/web/20120229033746/http://brandonaaron.net/blog/2009/05/14/jquery-edge-better-support-for-other-windows-and-documents) – ruffin Sep 24 '15 at 17:03
  • @TravelingTechGuy You don't mention how to pass the click event down to the iframe. From what I understand, pointer-events: none will stop the click event from triggering on the transparent div, making the transparent div pointless, so I don't know how to get the event to trigger both on the iframe and on the transparent div. – RaisinBranCrunch Apr 14 '17 at 16:15
19

I was trying to find a better answer that was more standalone, so I started to think about how JQuery does events and custom events. Since click (from JQuery) is just any event, I thought that all I had to do was trigger the event given that the iframe's content has been clicked on. Thus, this was my solution

$(document).ready(function () {
    $("iframe").each(function () {
        //Using closures to capture each one
        var iframe = $(this);
        iframe.on("load", function () { //Make sure it is fully loaded
            iframe.contents().click(function (event) {
                iframe.trigger("click");
            });
        });

        iframe.click(function () {
            //Handle what you need it to do
        });
    });
});
albertjan
  • 7,739
  • 6
  • 44
  • 74
Kevin
  • 557
  • 4
  • 18
16

Try using this : iframeTracker jQuery Plugin, like that :

jQuery(document).ready(function($){
    $('.iframe_wrap iframe').iframeTracker({
        blurCallback: function(){
            // Do something when iframe is clicked (like firing an XHR request)
        }
    });
});
Vince
  • 3,274
  • 2
  • 26
  • 28
9

It works only if the frame contains page from the same domain (does not violate same-origin policy)

See this:

var iframe = $('#your_iframe').contents();

iframe.find('your_clicable_item').click(function(event){
   console.log('work fine');
});
7

You could simulate a focus/click event by having something like the following. (adapted from $(window).blur event affecting Iframe)

$(window).blur(function () {
  // check focus
  if ($('iframe').is(':focus')) {
    console.log("iframe focused");
    $(document.activeElement).trigger("focus");// Could trigger click event instead
  }
  else {
    console.log("iframe unfocused");
  }                
});

//Test
$('#iframe_id').on('focus', function(e){
  console.log(e);
  console.log("hello im focused");
})
Justin Fenn
  • 71
  • 1
  • 3
2

None of the suggested answers worked for me. I solved a similar case the following way:

<a href="http://my-target-url.com" id="iframe-wrapper"></a>
<iframe id="iframe_id" src="http://something.com" allowtrancparency="yes" frameborder="o"></iframe>

The css (of course exact positioning should change according to the app requirements):

#iframe-wrapper, iframe#iframe_id {
  width: 162px;
  border: none;
  height: 21px;
  position: absolute;
  top: 3px;
  left: 398px;
}
#alerts-wrapper {
  z-index: 1000;
}

Of course now you can catch any event on the iframe-wrapper.

ramigg
  • 1,287
  • 1
  • 15
  • 16
  • 2
    This will prevent all clicks from registering in the iframe. – Jeff Ryan Jul 28 '14 at 23:28
  • You are right. It will route all clicks to the iframe-wrapper element. This works for me because in my case the iframe has no interactive elements, I need it just for display. – ramigg Jul 29 '14 at 07:57
1

You can use this code to bind click an element which is in iframe.

jQuery('.class_in_iframe',jQuery('[id="id_of_iframe"]')[0].contentWindow.document.body).on('click',function(){ 
 console.log("triggered !!")
});
mst
  • 466
  • 5
  • 17
1

This will allow you to target a specfic element in the iframe such as button or text fields or practically anything as on method allows you to put selector as an argument

$(window).load(function(){
    $("#ifameid").contents().on('click' , 'form input' , function(){
            console.log(this);
    });
});
Rahul Jain
  • 11
  • 1
0

Maybe somewhat old but this could probably be useful for people trying to deal with same-domain-policy.

let isOverIframe = null;
$('iframe').hover(function() {
        isOverIframe = true;
    }, function() {
        isOverIframe = false;
    });

$(window).on('blur', function() {
    if(!isOverIframe)
        return;

    // ...
});

Based on https://gist.github.com/jaydson/1780598

Moldevort
  • 193
  • 1
  • 9
0

You may run into some timing issues depending on when you bind the click event but it will bind the event to the correct window/document. You would probably get better results actually binding to the iframe window though. You could do that like this:

    var iframeWin = $('iframe')[0].contentWindow;
    iframeWin.name = 'iframe';
    $(iframeWin).bind('click', function(event) {
        //Do something
        alert( this.name + ' is now loaded' );
    });
Santosh Dangare
  • 685
  • 1
  • 4
  • 15
-1

This may be interesting for ppl using Primefaces (which uses CLEditor):

document.getElementById('form:somecontainer:editor')
.getElementsByTagName('iframe')[0].contentWindow
.document.onclick = function(){//do something}

I basically just took the answer from Travelling Tech Guy and changed the selection a bit .. ;)

salgmachine
  • 519
  • 1
  • 3
  • 14
-1

Solution that work for me :

var editorInstance = CKEDITOR.instances[this.editorId];

            editorInstance.on('focus', function(e) {

                console.log("tadaaa");

            });
maxiplay
  • 427
  • 1
  • 5
  • 13
-3

You can solve it very easily, just wrap that iframe in wrapper, and track clicks on it.

Like this:

<div id="iframe_id_wrapper"> <iframe id="iframe_id" src="http://something.com"></iframe> </div>

And disable pointer events on iframe itself.

#iframe_id { pointer-events: none; }

After this changes your code will work like expected.

$('#iframe_id_wrapper').click(function() { //run function that records clicks });