Reputation: 2860
I have a site which has a media player embedded inside an iframe. The media player and the site are on the same domain, preventing cross-origin issues. Each page, the main page as well as the media player page, have a bit of code which finds the height and width of any parent iframe:
var height = $(parent.window).height();
var width = $(parent.window).width();
No problems so far....until:
A client wants to embed my site inside an iframe on his own site. His site is on a different domain. Now, my iframe is inside another iframe and my code is throwing cross-origin errors.
The following does not throw errors:
var test1 = parent.window; // returns my site
var test2 = window.top; // returns client site
The following does throw cross-origin errors:
var test3 = parent.window.document;
var test4 = $(parent.window);
var test5 = window.top.document;
var test6 = $(window.top);
How do I get the height of the iframe on my domain without the cross-origin errors? I'm hoping for a pure javascript/jQuery solution.
Options which will not work for my solution are:
Like in Inception, I must go deeper. Please help.
Upvotes: 1
Views: 418
Reputation: 2860
Your code is running from the iframe in the middle of the parent and the child window. So, anytime you call
window.parent
and your site is embedded inside an iframe and the parent is a different domain (Same origin policy), an error will be thrown. I would recommend first checking if the parent is the same origin. You need to wrap this check in a try catch.
NOTE: Most browsers, but not Edge, will not throw an error if the parent is http://localhost:xxx and the iframe is http://localhost:zzz where xxx is a different port number than zzz. So, you also need to manually check the origins match by comparing the protocol, domain, and port.
var isEmbeddedInCrossOriginIframe = false;
try {
var originSelf = (window.self.location.protocol + '//' +
window.self.location.hostname +
(window.self.location.port ? ':' +
window.self.location.port : '')).toLowerCase();
var originParentOrSelf = (window.parent.location.protocol + '//' +
window.parent.location.hostname +
(window.parent.location.port ? ':' +
window.parent.location.port : '')).toLowerCase();
isEmbeddedInCrossOriginIframe = originSelf != originParentOrSelf;
}
catch(err) {
isEmbeddedInCrossOriginIframe = true;
//console.log(err);
}
Your solution will then be:
var height = $(isEmbeddedInCrossOriginIframe ? window : parent.window)
.height();
var width = $(isEmbeddedInCrossOriginIframe ? window : parent.window)
.width();
Upvotes: 0
Reputation: 77063
You will need to use Javascript's messager. First, you need to define a function
like this:
function myReceiver(event) {
//Do something
}
Then you need an event listener:
window.addEventListener("message", myReceiver);
You will need something like this on both sides. Now, you can send a message like this to the iframe
:
innerWindow.contentWindow.postMessage({ message: {ResponseKey: "your response key", info1: "something1", info2: "something2"}}, innerWindow.src)
and this is how you can send a message to the parent:
window.parent.postMessage({ message: {ResponseKey: "your response key", info1: "something1", info2: "something2"}}, myorigin);
The only missing item in the puzzle is myorigin
. You will be able to find it out in your iframe
using event.origin || event.originalEvent.origin
in the message receiver event.
However, the pages using your site in their pages inside an iframe
will have to include a Javascript library which will handle the communication you need. I know how painful is this research, I have spent days when I have done it before to find out the answer.
Upvotes: 1