I am experimenting with making a website where I have two iframes with other webpages side by side, and would only like to show a certain part of these websites.
Trying to edit the innerHTML of these websites throws errors regarding cross-page security problems.
How can I run Javascript inside these iFrames in a safe manner? If this is not possible, is there a good atlernative for iFrames where I can have to websites side-by-side?
It's not important for me to be able to edit both iFrames, only one of them need to be editable.
An iframe is just a 'hole' in your page that displays another web page inside of it. The contents of the iframe are not in any shape or form part of your parent page.
If your iframe is loaded from the same domain as your parent, then you can access the DOM of the document in the iframe from the parent.
Considering the iframe is from the same domain, Try using the below code and see if it works. The below code will add CSS changes to the iframe. If this works for you, then you can run javascript as well.
<script>
var iframe = document.getElementById("frame1");
$('iframe').load( function() {
$('iframe').contents().find("head")
.append($("<style type='text/css'> .lt{display:none;} </style>"));
});
</script>
If you are getting "permission denied type errors.", I think what you are doing is subject to the same-origin policy. This should be the reason why you are getting permission denied type errors.
Here you can check the possible solutions.
Unable to access iframe content (same-origin policy)
Related
I'm trying to automate interactions with a website that I don't control. Notably for this discussion, the page from the site contains several iframes. For example, consider the source of the imaginary (but comparable) page https://www.chicken.com/a/b/hamburger.aspx to look something like:
<html>
...
<iframe id="iframe_a" src="meatloaf.aspx"></iframe>
<iframe id="iframe_b" src="stuffing.aspx"></iframe>
...
</html>
Notably, the 'src' attributes of the iframes are relative, so they are to be loaded from the original domain (www.chicken.com/a/b/ in this case) and there doesn't seem to be any 'Same Origin' issues, since I can login to the site and interact with it just fine. However, this all changes when I try to interact with the iframes using the Chrome dev console. For instance, this is what happens when I try to get the contents of one of the iframes using jQuery:
$('#iframe_a').contents()
jquery-1.11.3.min.js:2 Uncaught DOMException: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "https://www.chicken.com" from accessing a cross-origin frame.(…)
My (wrong) intuition is that since the sources of these iframes is the same domain as is the original page, that javascript interactions in the console should be under the auspices of that original domain, and everything should be fine. But clearly I'm not understanding the nuances of Same Origin. Can someone enlighten me about how it works in this case? And perhaps suggest a way to manipulate the contents of this iframe from a running browser?
I'm developing an application that is feed a URL containing a session token from an API. This URL will grant the user of the application the ability to view search results from 3rd party databases via the API.
The issue that I'm facing is that when presenting the results (The URL) in an iframe it looks very ugly due to the iframe's scroll bar. I've poked about got the usual Google results, but I'm finding I'm quite stumped as to how to expand the iframe's height to match the incoming content.
I found an example of exactly what I'd like to happen but on trying to replicate the code I'm having no luck.
The link in question ... As you can see the page loads an iframe into a basic HTML table and expands to accommodate the size of the content in the iframe.
Here's the source code for the HTML:
<html>
<body>
<table width="100%" border=1>
<tr><td>Header</td></tr>
<tr><td>Navigation</td></tr>
<tr><td>
<iframe onload="resize(this)" src="/test/phpinfo.php">
</iframe>
</td></tr>
<tr><td>footer</td></tr>
</table>
<script>
function resize(elem){
var outer=elem;
var inner=elem.contentDocument.documentElement;
outer.style.border="0";
outer.style.overflow="hidden";
outer.style.height=Number(inner.scrollHeight+10)+"px";
outer.style.width=Number(inner.scrollWidth+10)+"px";
}
</script>
</body>
</html>
Nothing special right? But copypasta of the code (obviously changing the src) does nothing. I feel like I'm taking crazy pills here, this should be 2 second job, but it's not working for me. This is all client side stuff, right? No voodoo magic happening on the server.
So ladies and gentlemen, what am I doing wrong, or how can I better do this? Please bear in mind that I have no ability to effect the HTML in the iframe as it is served up via an API and I can't touch it.
Thank you
EDIT : This is the reason it won't work Same Origin Policy.
you can only access the iframe contentDocument with javascript when iframe origin and the iframe src origin equal and matches each other.
otherwise the browser dont allow you to access the inner contentDocument
Blocked a frame with origin "http://example.de" from accessing
a frame with origin "http://otherorigin.example.de". Protocols,
domains, and ports must match.
your posted example page origin
http://frank.bridgewater.edu/test/iframeResize/
and iframe src origin
http://frank.bridgewater.edu/test/phpinfo.php
matches (equal origins). so here it is working and the script can access the iframe contentDocument
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.
HI, i got a simple html page, localy with an iframe. the iframe includes a generated page which got a javascript function. i know want to call that function. of course, im getting "permission denied". so since im new to js and all that stuff i dont know if it's actually possible to do that. give me some hints for searching or a nice solution.
i do cal lthe func like: parent.myiframe.myfunc();
I guess the page in the iframe resides on another server / domain. Modern browser do not allow "cross site scripting", see: http://de.wikipedia.org/wiki/Cross-Site_Scripting
If possible, move the site in the iframe to the same server. An alternative (workaround) would be to proxy the page on the local server, so that that for the client it seems to be loaded from the same domain.
Edit: This is also called a "Same Origin Policy". You can only call java script functions in a document that is:
from the same domain (www.mydomain.com)
from the same subdomain (mail.mydomain.com <- no go!)
both use the same port (p.Ex.
accessing a http://... document from
a http*s*:// document won't work).
There might be another workaround if you have access to the iframe's source:
Change the iframe domain to the same as the outer frame's, by applying:
document.domain = "domain.com";
in the iframe source (see http://ajaxian.com/archives/how-to-make-xmlhttprequest-calls-to-another-server-in-your-domain for more information).
Also there is a Draft for "Cross-Origin Resource Sharing" (http://www.w3.org/TR/cors/) that is already partially implemented in several browser, see: http://www.webdavsystem.com/ajax/programming/cross_origin_requests
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.