Cross domain iframe content load detection - javascript

I have a rather interesting problem. I have a parent page that will create a modal jquery dialog with an iframe contained within the dialog. The iframe will be populated with content from a 3rd party domain. My issue is that I need to create some dialog level javascript that can detect if the content of the iframe loaded successfully and if it hasn't within a 5 second time frame, then to close the dialog and return the user to the parent page.
I have researched numerous solutions and only two are of any true value.
Get the remote site to include a javascript line of document.domain = 'our-domain.com'.
Use a URL Fragment hack, but again I would need the request that the remote site
able to modify the URL by appending '#some_value' to the end of the URL and my dialog window would have to poll the URL until it either sees it or times out.
Are these honestly the only options I have to work with? Is there not a simpler way to just detect this?
I have been researching if there's a way to poll for http response errors, but this still remains confined to the same restrictions.
Any help would be immensely appreciated.
Thanks

The easiest way (if you can get code added to the external sites) is to have them add an invisible iframe pointing to a special html file on your domain. This could then use parent.parent.foo() to notify the original window about the load event.
Listening for the "load" event will only tell you if the window loaded, not what was loaded or if the document is ready for interaction.

Nicholas Zakas has an article about detecting if an iframe loaded: http://www.nczonline.net/blog/2009/09/15/iframes-onload-and-documentdomain/. Basically you have this code snippet:
var iframe = document.createElement("iframe");
iframe.src = "simpleinner.htm";
if (iframe.attachEvent){
iframe.attachEvent("onload", function(){
alert("Local iframe is now loaded.");
});
} else {
iframe.onload = function(){
alert("Local iframe is now loaded.");
};
}
document.body.appendChild(iframe);
I haven't tested it, but I'm pretty sure jQuery should be able to handle it by doing something like $("#iframe").load(function () { alert("Local iframe is now loaded."); });

You could try using postMessage for communication between frames.
This will require the remote site to include some specific JavaScript to post a message to the parent document when it has finished loading.

It's possible to do this with an onload handler on the iframe itself. Unfortunately (surprise!) IE makes it difficult. The only way I could get this to work was to compose HTML for the iframe, then append it to the document with innerHTML. Then I have to poll to see when the iframe appears in the DOM, which varies depending on if the page is loading. Here's a link to the source: http://svn.openlaszlo.org/openlaszlo/trunk/lps/includes/source/iframemanager.js
See create(), __finishCreate() and gotload(). Feel free to take a copy of this and use it yourself!
Regards,
Max Carlson
OpenLaszlo.org

This is how I detected the loading of a Cross-Domain Iframe,
Set a unique id for the iframe ( U may use any sort of identifier, it doesn't matter )
<iframe id="crossDomainIframe" src=""> </iframe>
Set window event listener:
document.getElementById("crossDomainIframe").addEventListener('load',
function actionToPerform(){
//Do your onLoad actions here
}
)

In any case you will need some sort of cooperation from the other domain's server, as you are trying to abuse the Same Origin Policy (SOP)
The first solution document.domain=... won't work if domains are different. It works only for subdomains and ports, as described in the link above.
The only option that allows cross domain communication without polling is JSONP or script injection with a JS function callback. This method is available in all Google APIs and works well.
We've explained on our blog a way to sandbox those calls in an iframe to secure them. While postMessage is better now, the window.name hack has the advantage of working on old browsers.
Ironically, SOP does not prevent you to POST anything to another domain. But you won't be able to read the response.

Related

Is there a way to retrieve an ajax response sent from an iframe?

I was wondering if there is any way to retrieve the response of an ajax request sent from an iframe.
The iframe does something like the following:
script in iframe sends an ajax request
iframe gets a response, and updates content within iframe
What I would like to do is to intercept that request outside of the iframe, and use that information to update the page.
If you go into chrome's dev tools, and go to the network tab, you can see the request/response that the iframe makes. It would be nice if there is a window event or something similar that triggers everytime a response comes in on the page.
NOTE: the iframe is a page that is not in the same domain.
If the child iframe is in a different domain to the parent, you can't really do anything that's going to work across browsers. See jasonjifly's answer below for techniques that will work on some browsers assuming you have control over the client scripts on both frames.
If the parent and child are on the same domain, then you can achieve what you are looking for.
For example, assuming you're using jquery, you could have this code in your iframe:
$.ajax(function() {
.....
complete: function() {
window.parent.onAjaxComplete('Hi there');
}
});
Along with this code in your parent frame:
function onAjaxComplete(msg)
{
alert(msg);
}
To achieve similar results in a cross-domain scenario you could have the parent frame poll the server. When the server receives an ajax request from the child iframe it could then alert the parent page via the polling service. Obviously this would only be suitable if you have control over the services called by the child iframe.
In theory, it's forbidden to communicate between two cross domain iframe, due to the same-origin policy, please refer to this page: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Same_origin_policy_for_JavaScript
Before HTML5, we have some workarounds:
If you just want to use iframe to get cross domain data, you can use JQuery:JSONP, the essence is using . "" allows executing a cross domain javascript.
Another way is "An iframe in an iframe in an iframe", you can refer to this page: http://blog.cakemail.com/the-iframe-cross-domain-policy-problem/
HTML5:
window.postMessage, refer to this page: https://developer.mozilla.org/en-US/docs/Web/API/window.postMessage
HTML5 CORS, you need to configure server, refer to this page: http://www.html5rocks.com/en/tutorials/cors/
My recommendation is using solution 1, it can work on almost all mainstream browsers.
(function() {
var origOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
this.addEventListener('load', function() {
var json = $.parseJSON(this.responseText);
});
origOpen.apply(this, arguments);
};
})();

Update URL from inside an iFrame

is it possible for javascript inside an iFrame to update the URL (hash) of the parent page (and retrieve it)
Does it have any permissions?
To further explain, I have no hosting for this domain, I can only set up an Iframe. I also cannot use a DNS config to get that page to display because of limitations of my hoster.
I also cannot transfer the domain to them to make that work because my clients wants to keep control of the domain.
Thank you for your help!
If the <iframe> page is within the same domain, probably yes. Otherwise you don't get access to the parent page due to cross-domain restrictions.
You can change the URL of the parent page though:
top.location.href = 'http://www.example.com';
due to security constraints you will not be able to access properties of the parent window IF the domain,port or protocol is different than the one in the iframe.
To be short, the answer is NO.
Your script works only inside the context of that iframe.
If you try for example,
var loc = document.location;
you will see what I mean.
One solution is that when you give the other side your iframe, you should add a script in witch you can do whatever you want, because it runs on their domain.
Maybe dynamically create the source of your iframe and stuff.

Need to change #src of a parent iframe from within child iframe

I have the following HTML markup (don't ask....)
- document //main site
- <iframe> //my site
- <iframe> //site within my site
- <frame>
- <a onclick="JavaScript:parent.parent.location.href='http://bla.com;return false;'">
Basically, main site is calling my site in an iframe. I, in turn, also have an iframe on my site where I'm calling 3rd site. The third site has a frameset with a frame in it that has a link. When clicking on this link, it has to change the url of my site. My site and my child site are on the same domain. When I'm running my site as "stand-alone" (not in iframe) the above code works fine in all browsers.
Once I open my site in an iframe of the main site, it looks like the above code is trying to change the source of the main site. In FireFox I get a console message "Access to property denied". In IE it opens up a new window with my site not in the main site anymore.
What is the correct JavaScript to change the #src attribute on my site when I'm within an iframe?
You are banging your head against the wall that is the same origin policy here. This is XSS country and strictly forbidden, no way around it, unless both domains agree to talk together.
You can read more about cross domain communication using iframes, but again, unless the different domain agree to talk together, you are out of luck.
Although this might seem frustrating, be glad of this rule next time you use homebanking ;)
Can you try something like this
<document> //main site
<iframe id="my_iframe"> //your site
<iframe> //site within your site
<frame>
<a onclick="JavaScript:Top.document.getElementById('my_iframe').location.href='http://bla.com;return false;'">
Top refers to the main window, and then getElementById('my_iframe') will give you your iframe element.
I believe that you're trying to do communication between different pages.
You may take a look this API: HTML5 Cross Document Messaging
Basically, if you want to tell the parent iframe to navigate to a certain url, you can do this:
In the site within my site html:
// onclick of your anchor, post message (an event) with an expected origin
window.postMessage("http://bla.com", "www.sitewithinmysite.com");
In my site html:
// listen to the event "message"
window.addEventListener("message", messageHandler, true);
function messageHandler(e) {
// only recognize message from this origin
if (e.origin === "www.sitewithinmysite.com") {
// then you can navigate your page with the link passed in
window.location = e.data;
}
}
You might want to have the pages communicate using AJAX. Have the site that needs to change its URL listen by long polling to to a node.js server.

Is it possible to use jQuery to grab the HTML of another web page into a div?

I am trying to integrate with the FireShot API to given a URL, grab HTML of another web page into a div then take a screenshot of it.
Some things I will need to do after getting the HTML
grab <link> & <script> from <head>
grab <body> into <div>
But 1st, it seems when I try to do a
$.get("http://google.com", function(data) { ... });
I get a 200 in firebug colored red. I think it has to do with sites not allowing you to grab their page with JS? Then is opening a window the best I can do? But how might I control the other page with jQuery or call fsapi on that page?
UPDATE
I tried to do something like below to do something when the new window is ready, but FireBug says "Permission denied to access property 'document'"
w = window.open($url.val());
setTimeout(function() { // if I dont do this, I always get about:blank, is there a better way around this?
$(w.document).ready(function() {
console.log(w.document.body);
});
}, 1000);
I believe the cross-site security setup within Javascript is basically blocking this. You'd likely have to proxy the content through your own domain.
There are a couple other options I think for break the cross-site security constraints, but I'm not sure I'd promote them.
If the "another page" locates within the same domain of your hosting page, yes, you can. Please refer to jQuery's $().load() API.
Otherwise, you're disallowed to do so by the browser's Cross-Site Security Policy. At this moment, you can choose to use iFrame instead of DIV.
Some jQuery plugins, e.g. thickbox provides ability to load pages to appropriate container automatically.
Unless I am correct, I do not believe you can AJAX a page cross domain (e.g. from domain1.com to domain2.com). To get around this, you can have a PHP "proxy" script that does the "getting" of the page and then pass it to JS.
For example, in JS you would get() http://mydomain.com/get/?domain=http://google.com and then do what you need to do!

Jquery/javascript detection if iframe can be loaded

I have iframes with OpenX ads I server from another server/domain.
When something happens to this ad server the main server doesn't load whole contents because the domain that openx loads in iframe is not responding. I always thought that iframe works independently from the main site but it doesn't if the domain doesn't answer at all...
Anyway can main site detect somehow that a url in iframe is not responding and skips loading iframe and show the rest of the site?
How about loading the iFrame once the website is loaded? It's pretty easy to do this using jQuery (or even plain javascript using the window.load event).
So rather than wanting to 'detect' whether the iFrame has loaded, you can load it AFTER the rest of the website has completed loading. (sorry for excessive use of word 'load')
In jQuery, you can simply attach the url to the iFrame on the document.ready event.
A blank iFrame
<iframe id="iframe-ad" width="200"></iframe>
Simple jQuery to load the URL on document.ready
<script type="text/javascript">
$(document).ready(function() {
$("#iframe-ad").attr("src", "http://www.google.com");
});
</script>
Unfortunately there is no easy way to do this unless they are served from the same domain. I know there is a way to get let the javascript inside the iframe perform some actions on the parent document it is contained in, but I am not really sure how...
It is not possible, because of Same origin policy, there are some "gaps" in some browsers. But this is not going to recommend!
Might not make for the best experience, but you can make a local redirect file. something like:
<iframe src="http://www.mydomain.com/redir?url=http://www.theirdomain.com/ads"/>
then the redir page just returns
<script>
location.href = "${url}";
</script>
That way as long as your server is responding, everything else will continue as normal while the iframe redirects?
How about if I don't have iframe just javascript originating from different domain? If the domain is not responding javascript holds the page back not to load. Is there a way to prevent that?

Categories