[javascript] Detect click event inside iframe

I'm writing a plugin for TinyMCE and have a problem with detecting click events inside an iframe.

From my search I've come up with this:

Loading iframe:

<iframe src='resource/file.php?mode=tinymce' id='filecontainer'></iframe>

HTML inside iframe:

<input type=button id=choose_pics value='Choose'>

jQuery:

//Detect click
$("#filecontainer").contents().find("#choose_pic").click(function(){
    //do something      
}); 

Other posts I've seen usually have a problem with different domains (this hasn't). But, still, the event isn't detected.

Can something like this be done?

This question is related to javascript jquery html iframe tinymce

The answer is


If anyone is interested in a "quick reproducible" version of the accepted answer, see below. Credits to a friend who is not on SO. This answer can also be integrated in the accepted answer with an edit,... (It has to run on a (local) server).

<html>
<head>
<title>SO</title>
<meta charset="utf-8"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>

<style type="text/css">
html,
body,
#filecontainer {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<iframe src="http://localhost/tmp/fileWithLink.html" id="filecontainer"></iframe>

<script type="text/javascript">
$('#filecontainer').load(function(){

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

  iframe.find("a").click(function(){
    var test = $(this);
    alert(test.html());
  });
});
</script>
</body>
</html>

fileWithLink.html

<html>
<body>
<a href="https://stackoverflow.com/">SOreadytohelp</a>
</body>
</html>

In my case there were two jQuery's, for the inner and outer HTML. I had four steps before I could attach inner events:

  1. wait for outer jQuery to be ready
  2. wait for iframe to load
  3. grab inner jQuery
  4. wait for inner jQuery to be ready

$(function() {   // 1. wait for the outer jQuery to be ready, aka $(document).ready
    $('iframe#filecontainer').on('load', function() {   // 2. wait for the iframe to load
        var $inner$ = $(this)[0].contentWindow.$;   // 3. get hold of the inner jQuery
        $inner$(function() {   // 4. wait for the inner jQuery to be ready
            $inner$.on('click', function () {   // Now I can intercept inner events.
                // do something
            });
        });
    });
});

The trick is to use the inner jQuery to attach events. Notice how I'm getting the inner jQuery:

        var $inner$ = $(this)[0].contentWindow.$;

I had to bust out of jQuery into the object model for it. The $('iframe').contents() approach in the other answers didn't work in my case because that stays with the outer jQuery. (And by the way returns contentDocument.)


I'm not sure, but you may be able to just use

$("#filecontainer #choose_pic").click(function() {
    // do something here
});

Either that or you could just add a <script> tag into the iframe (if you have access to the code inside), and then use window.parent.DoSomething() in the frame, with the code

function DoSomething() {
    // do something here
}

in the parent. If none of those work, try window.postMessage. Here is some info on that.


In my case, I was trying to fire a custom event from the parent document, and receive it in the child iframe, so I had to do the following:

var event = new CustomEvent('marker-metrics', {
    detail: // extra payload data here
});
var iframe = document.getElementsByTagName('iframe');
iframe[0].contentDocument.dispatchEvent(event)

and in the iframe document:

document.addEventListener('marker-metrics', (e) => {
  console.log('@@@@@', e.detail);
});

Just posting in case it helps someone. For me, the following code worked perfect:

$(document).ready(function(){
     $("#payment_status_div").hide();
     var iframe = $('#FileFrame').contents();
     iframe.find("#take_payment").click(function(){
         $("#payment_status_div").show("slow");
     });
});

Where 'FileFrame' is the iframe id and 'take_payment' is the button inside iframe. Since my form inside the iframe is posted to a different domain, when used load, I got an error message saying:

Blocked a frame with origin "https://www.example.com" from accessing a frame with origin "https://secure-test.worldpay.com". Protocols, domains, and ports must match.


The tinymce API takes care of many events in the editors iframe. I strongly suggest to use them. Here is an example for the click handler

// Adds an observer to the onclick event using tinyMCE.init
tinyMCE.init({
   ...
   setup : function(ed) {
      ed.onClick.add(function(ed, e) {
           console.debug('Iframe clicked:' + e.target);
      });
   }
});

$("#iframe-id").load( function() {
    $("#iframe-id").contents().on("click", ".child-node", function() {
        //do something
    });
});

I know this is old but the ID's don't match in your code one is choose_pic and one is choose_pics:

<input type=button id=choose_pics value='Choose'>

$("#filecontainer").contents().find("#choose_pic").click(function(){
    //do something      
}); 

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to jquery

How to make a variable accessible outside a function? Jquery assiging class to th in a table Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Getting all files in directory with ajax Bootstrap 4 multiselect dropdown Cross-Origin Read Blocking (CORB) bootstrap 4 file input doesn't show the file name Jquery AJAX: No 'Access-Control-Allow-Origin' header is present on the requested resource how to remove json object key and value.?

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to iframe

Getting all files in directory with ajax YouTube Autoplay not working Inserting the iframe into react component How to disable auto-play for local video in iframe iframe refuses to display iFrame onload JavaScript event YouTube iframe embed - full screen Change New Google Recaptcha (v2) Width load iframe in bootstrap modal Responsive iframe using Bootstrap

Examples related to tinymce

Detect click event inside iframe Remove style attribute from HTML tags jQuery and TinyMCE: textarea value doesn't submit JQuery to load Javascript file dynamically