0

This question has been asked a lot, and the answers are usually similar.

In basic terms, I need a function to perform when the contents of an iframe are clicked.

For the purposes of this demonstration, I have http://mydomain.com/iframe.html which contains an iframe with an ID of "iframeID" and a source of http://mydomain.com.

This code works:

jQuery(document).ready(function(){
    $('#iframeID').contents().click(function(event) {
        console.log('Clicked! ' + event.pageX + ' - ' + event.pageY);
    });
});

But, this code only works in Internet Explorer. I need a solution that will work in all browsers.

The good news is, this is all on the same domain so if I need to put additional code in either the iframe source or my iframe.html then that's fine. I just need it to work cross-browser.

One other point to note, is I have a desire for this to work across subdomains.

I know it won't work with different domains, but as I understand it, subdomains should be fine? Any extra steps required for that to work?

Any help gratefully received!

SpongeBobPHPants
  • 641
  • 7
  • 19
  • 1
    Is using Cross-Document-Messaging (XDM) an option? It works for IE8 and newer and all modern browers. https://developer.mozilla.org/en-US/docs/DOM/window.postMessage And if you need support for older browsers you can check out: http://easyxdm.net/wp/ See also: http://stackoverflow.com/questions/7652646/how-to-properly-use-postmessage-to-do-cross-domain-messaging-with-html5-and-mode – jacobq Sep 18 '12 at 13:22
  • Looks worth exploring. I don't fully understand it, but the example code is something I can play with. IE8+ is fine - they made browsers before IE8? :-P If you have a practical example based on the original code I posted that would be awesome. – SpongeBobPHPants Sep 18 '12 at 13:34
  • I posted an example. I didn't analyze your original code, but I tried to make it very generic and easy to adapt. Hope it's helpful – jacobq Sep 18 '12 at 14:53

2 Answers2

1

Here is an example I've put together on jsFiddle that demonstrates one way to use XDM: This is the demo and it includes this fiddle as a child iframe

HTML (parent):

<h1>Parent window</h1>
<input id="message-for-child" type="text" value="" placeholder="(message for child)">
<button id="parent-to-child-button">Send to child</button>
<br>
<p id="parent-message"></p>
<br>
<iframe id="child" src="http://fiddle.jshell.net/quant/G2uq6/show/"></iframe>

JavaScript (parent):

// parent_on_message(e) will handle the reception of postMessages (a.k.a. cross-document messaging or XDM).
function parent_on_message(e) {
    console.log("parent_on_message event fired: ", e);
    // You really should check origin for security reasons
    // https://developer.mozilla.org/en-US/docs/DOM/window.postMessage#Security_concerns
    if (e.origin.search(/^http[s]?:\/\/.*\.jshell\.net/) != -1
        && !($.browser.msie && $.browser.version <= 7)) {
        var returned_pair = e.data.split('=');
        if (returned_pair.length != 2)
            return;
        if (returned_pair[0] === 'message-for-parent') {
            $("p#parent-message").html(returned_pair[1]);
        }
        else
            console.log("Parent received invalid message");
    }
}

jQuery(document).ready(function($) {
    // Setup XDM listener (except for IE < 8)
    if (!($.browser.msie && $.browser.version <= 7)) {
        // Connect the parent_on_message(e) handler function to the receive postMessage event
        if (window.addEventListener)
            window.addEventListener("message", parent_on_message, false);
        else
            window.attachEvent("onmessage", parent_on_message);
    }


    $("button#parent-to-child-button").on("click", function(e) {
        console.log("Sending: " + $("input#message-for-child").attr("value"));
        $("iframe#child").get(0).contentWindow.postMessage('message-for-child=' + $("input#message-for-child").attr("value"), '*');
        
    });

        
});

HTML (child):

<h1>Child</h1>
<input id="message-for-parent" type="text" value="" placeholder="(message for parent)">
<button id="child-to-parent-button">Send to parent</button>
<br>
<p id="child-message"></p>

JavaScript (child):

// child_on_message(e) will handle the reception of postMessages (a.k.a. cross-document messaging or XDM).
function child_on_message(e) {
    console.log("child_on_message event fired: ", e);
    // You really should check origin for security reasons
    // https://developer.mozilla.org/en-US/docs/DOM/window.postMessage#Security_concerns
    if (e.origin.search(/^http[s]?:\/\/.*\.jshell\.net/) != -1
        && !($.browser.msie && $.browser.version <= 7)) {
        var returned_pair = e.data.split('=');
        if (returned_pair.length != 2)
            return;
        if (returned_pair[0] === 'message-for-child') {
            $("p#child-message").html(returned_pair[1]);
        }
        else
            console.log("Child received invalid message");
    }
}

jQuery(document).ready(function($) {
    // Setup XDM listener (except for IE < 8)
    if (!($.browser.msie && $.browser.version <= 7)) {
        // Connect the child_on_message (e) handler function to the receive postMessage event
        if (window.addEventListener)
            window.addEventListener("message", child_on_message , false);
        else
            window.attachEvent("onmessage", child_on_message );
    }


    $("button#child-to-parent-button").on("click", function(e) {
        console.log("Sending: " + $("input#message-for-parent").attr("value"));
        parent.window.postMessage('message-for-parent=' + $("input#message-for-parent").attr("value"), '*');
        
    });

        
});

Further reading:

Community
  • 1
  • 1
jacobq
  • 11,209
  • 4
  • 40
  • 71
  • Awesome work. I can't thank you enough... I literally can't. I don't have enough rep to upvote, but I will try this out and make it more specific to my needs and if I have no other questions I will be marking this as the answer at the easliest opportunity. – SpongeBobPHPants Sep 18 '12 at 15:00
  • I'm glad you like it! The standard words of caution still apply though: never take an SO answer as a substitute for learning about the underlying technologies. This code comes with no guarantees or warranties of any kind :) – jacobq Sep 18 '12 at 15:05
  • Of course. I learn so much from SO. Whether it be questions I ask, or answers I find by searching. It's an awesome place and it's made awesome by people like you who give up their time to provide great answers. I will learn a lot from this. – SpongeBobPHPants Sep 18 '12 at 15:12
  • Ok, I thought this might be enough to work out what I really need to do. But I think I've confused myself now. What I really want is, that when a link is clicked within the iframe, that the link will load in the parent window. Of course the default behaviour is to open the link in the child iframe. A variation of the code I posted in my original message works when links are clicked but only in IE. Are we still looking at XDM here? I'd prefer not to modify the code in the child frame (if possible). Sorry for the run around :( – SpongeBobPHPants Sep 18 '12 at 18:14
  • Are you talking about something like this? window.top.location.href="//www.google.com"; Or are you saying that you want all "regular" links in the iframe to open in the top window? http://jsfiddle.net/quant/HfKQz/25/ – jacobq Sep 18 '12 at 19:28
  • You don't even need XDM for that link behavior: just set a handler for clicks on links and override the default behavior: http://jsfiddle.net/quant/VtaBg/ and http://jsfiddle.net/quant/HfKQz/26/ – jacobq Sep 18 '12 at 19:35
1

If you just want to make links in the iframe open in the top window instead of inside of the iframe check out How to force link from iframe to be opened in the parent window

Just put this in the head of the iframe HTML:

<base target="_parent" />
Community
  • 1
  • 1
jacobq
  • 11,209
  • 4
  • 40
  • 71
  • Fansatic work - why is it sometimes the most simple things that stare you in the face the best solutions? I have marked your original answer as the answer because it most accurately answered my original question. However, ironically, something this simple will be all I need. Excellent work and sorry for not being more concise with my question – SpongeBobPHPants Sep 18 '12 at 21:42