cross domain iframe resize for firefox 3.6.10 - javascript

Is there any way to resize a cross domain iframe according to its content, that would work in Firefox 3.6.10?
I thought that the postMessage command works, but a solution I found works in Firefox 12 but not in Firefox 3.6.10. Or maybe that's not the problem.
As I wrote in another question, youtube seems to be just embedding the content of the iframe in the page for the comment section, that's how it gets resized dynamically. And this would basically solve every iframe issue too, since the HTML would be embedded in the website's local HTML, and no same origin policy would block anything. When I asked about this, I didn't get answers though.
So thank you in advance, or if you don't like when people say that, I would be grateful if someone would helped.
And I CAN control the content inside the frame too!
(I need this for a script that makes youtube look like around 2012, so more people could be grateful too.)

You might try looking at this on GitHub.
https://github.com/davidjbradshaw/iframe-resizer

solution i found/modified:
in the page which contains the iframe:
<script type="text/javascript">
function resizeCrossDomainIframe(id, other_domain) {
var iframe = document.getElementById(id);
window.addEventListener('message', function(event) {
if (event.origin !== other_domain) return;
if (isNaN(event.data)) return;
var height = parseInt(event.data) + 32;
iframe.height = height + "px";
}, false);
}
in the iframe code:
<iframe id="my_iframe" onload="resizeCrossDomainIframe('my_iframe', '**whatever domain your iframe content is on**');"></iframe>
for continuous resizing, i put this in the page containing the iframe:
<script>
var interval = setInterval(function(){
resizeCrossDomainIframe('my_iframe', '**whatever domain your iframe content is on**');
}, 100);
</script>
on the iframe content page:
<script>
window.onload = function() {
window.parent.postMessage(document.body.scrollHeight, '**whatever domain your iframe containing page is on**');
}
</script>
and this for continuous resizing:
<script>
var interval2 = setInterval(function(){
window.parent.postMessage(document.body.scrollHeight, '**whatever domain your iframe containing page is on**');
}, 100);
</script>
CORRECTION: the first interval script isnt needed, since the eventlistener executes the function every time a message is sent to it. it would just cause slowness

Related

Remove id from iframe

I have an iframe of a certain page from a site that I'm using, but I don't want all the parts of that page to be displayed with the iframe. Particularly, there's a navigation sidebar on the page that I don't want to be in the iframe. I'm trying to achieve this with the javascript seen below, but I can't quite figure it out.
<iframe width="800" height="800" src="scores/new?site_id=193">
<script>
var element = document.getElementById("sidebar-wrapper");
element.parentNode.removeChild(element);
</script>
</iframe>
For security reasons you can't run javascript through iframes. There are some exceptions if you're on the same domain but for the most part you should really avoid it.
If the iframe isn't a site you can control then there's pretty much nothing you can do. If you do control the other site and it's a different domain you might be able to work with the postMessage functions.
Edit: Check out the docs that Mozilla has up here https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
You'd need to create a listener on the inside that handles a message and hides your sidebar. Then on the parent send a message to the iframe to trigger that function.
Parent:
var iframe = document.getElementById('#iframeID');
iframe.contentWindow.postMessage('iframeTrigger');
Iframe:
window.addEventListener('iframeTrigger', hideSidebar);
function hideSidebar() {
//do stuff
}
You can insert a control in the iframed page
//inside the iframed page
var iframe = (function() {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
})();
if(iframe === true) {
var element = document.getElementById("sidebar-wrapper");
element.parentNode.removeChild(element);
}
Hope this could suit your need.
This should work theoretically, and it works in console. But this doesn't work in the HTML, although you are trying it from the same domain, because of security reasons. I just wanted to tell my view and I tried this:
<iframe src="http://output.jsbin.com/figujeyiyo" frameborder="0" id="ifrm">
Sorry, iframes not supported.
</iframe>
<script>
console.log(document.getElementById("ifrm").contentDocument.documentElement.getElementsByTagName("div"));
e = document.getElementById("ifrm").contentDocument.documentElement.getElementsByTagName("div")[0];
console.log(e);
e.parentNode.removeChild(element);
</script>
You need to execute the code when the page loads, you can do it like this:
document.addEventListener('DOMContentLoaded', function() {
var element = document.getElementById("sidebar-wrapper");
element.parentNode.removeChild(element);
});

How can I resize the iframe without page refresh?

I have some swf embedded in iframe but only if the page is refreshed the iframe is resized, then if I select other one then will show as all swf not only the animation the background as well. This is what I am using
if ( 'resizeIframe' === $('#onPlayAction').val() ) {
var ifrEl = $('div.player-container iframe.page-iframe')[0];
$(ifrEl).show();
ifrEl.src = htmlPageBrowserUri;
ifrEl.onload = function() {
ifrEl.width = ifrEl.contentWindow.document.body.scrollWidth;
ifrEl.height = ifrEl.contentWindow.document.body.scrollHeight;
}
}
There are three ways to do this.
You can change the size on every window resize
$(window).on('resize', function (){
ifrEl.width = ... ;
ifrEl.height = ... ;
})
You can use some jQuery plugins like iFrame Resizer
You can use some nifty css tricks. Go search for responsive iframes using css and you will find a ton of good answers.
I hope this all helps you.
I suspect the issue with your code might be thses two lines :
ifrEl.src = htmlPageBrowserUri;
ifrEl.onload = function() {
The problem being that the first line set s the frame address, but second line sets the onload event immediately, probably before the page has loaded ? So when the page does load, the line setting onload event has already run & so doens't get set.
I don't quite understand the text in your question (sorry!) but the code below successfully resizes an iframe - it's run 'onload' in the frame's page:
<body onload="setParent()">
In case it's relevant, the iframe itself has attributes:
<iframe id="neckfinishframe" style="width:100%;overflow-x:hidden" src=".. etc">
In my case I'm only concerned about height. Width is 100%.
In the iFrame page, this code runs from the onload event to amend the iframe height to be whatever the height of the page is, plus a bit. This is intended to avoid showing a set of scroll bars within the iframe.
function setParent() {
// runs onload in iframe page
// in my case I have to run it from the frame page because I need to know the page rendered height in order to set the iframe height
var f;
try {f = parent.getElementById("neckfinishframe")} catch (e) {};
if (f != null) f.style.height=(this.document.body.scrollHeight+30)+"px";
}
Note - I haven't tried this cross- browser but I know it works in IE.

Javascript --> iframe resizing using postMessage method

I'm trying to understand another Stackoverflow answer (cross-domain iframe resizer?) that purports to solve how to resize an iframe (hosted on a domain separate from the domain it's embedded in) according to its height. Wondering if anyone could answer my questions below.
THE SOLUTION:
Iframe:
<!DOCTYPE html>
<head>
</head>
<body onload="parent.postMessage(document.body.scrollHeight, 'http://target.domain.com');">
<h3>Got post?</h3>
<p>Lots of stuff here which will be inside the iframe.</p>
</body>
</html>
The parent page which contains the iframe (and would like to know its height):
<script type="text/javascript">
function resizeCrossDomainIframe(id, other_domain) {
var iframe = document.getElementById(id);
window.addEventListener('message', function(event) {
if (event.origin !== other_domain) return; // only accept messages from the specified domain
if (isNaN(event.data)) return; // only accept something which can be parsed as a number
var height = parseInt(event.data) + 32; // add some extra height to avoid scrollbar
iframe.height = height + "px";
}, false);
}
</script>
<iframe src='http://example.com/page_containing_iframe.html' id="my_iframe" onload="resizeCrossDomainIframe('my_iframe', 'http://example.com');">
</iframe>
MY QUESTIONS:
http://target.domain.com refers to the domain the iframe is
embedded within, right? NOT the domain that the iframe is hosted on?
In the function resizeCrossDomainIframe(id, other_domain) { line, I'm not supposed to interchange "id" with the id of the iframe and "other_domain" with the domain name that the iframe is hosted on, right? They're only parameters that I specify later when I call the function.
Instead of using onload within the iframe tag, I wrote the equivalent in jQuery, which loads on the page that embeds the iframe:
$('#petition-embed').load(function() {
resizeCrossDomainIframe('petition-embed','http://target.domain.com');
});
I added brackets around return:
if (event.origin !== other_domain) {return;} // only accept messages from the specified domain
if (isNaN(event.data)) {return;} // only accept something which can be parsed as a number
Does that look right?
I needed to do something similar, and found this example that seems simpler: using postmessage to refresh iframe's parent document
Here is what I ended up with in the iframe:
window.onload = function() {
window.parent.postMessage(document.body.scrollHeight, 'http://targetdomain.com');
}
And in the receiving parent:
window.addEventListener('message', receiveMessage, false);
function receiveMessage(evt){
if (evt.origin === 'http://sendingdomain.com') {
console.log("got message: "+evt.data);
//Set the height on your iframe here
}
}

Event when iframe finishes loading [duplicate]

I need to execute a callback when an IFRAME has finished loading. I have no control over the content in the IFRAME, so I can't fire the callback from there.
This IFRAME is programmaticly created, and I need to pass its data as a variable in the callback, as well as destroy the iframe.
Any ideas?
EDIT:
Here is what I have now:
function xssRequest(url, callback)
{
var iFrameObj = document.createElement('IFRAME');
iFrameObj.src = url;
document.body.appendChild(iFrameObj);
$(iFrameObj).load(function()
{
document.body.removeChild(iFrameObj);
callback(iFrameObj.innerHTML);
});
}
This callsback before the iFrame has loaded, so the callback has no data returned.
First up, going by the function name xssRequest it sounds like you're trying cross site request - which if that's right, you're not going to be able to read the contents of the iframe.
On the other hand, if the iframe's URL is on your domain you can access the body, but I've found that if I use a timeout to remove the iframe the callback works fine:
// possibly excessive use of jQuery - but I've got a live working example in production
$('#myUniqueID').load(function () {
if (typeof callback == 'function') {
callback($('body', this.contentWindow.document).html());
}
setTimeout(function () {$('#frameId').remove();}, 50);
});
I am using jQuery and surprisingly this seems to load as I just tested and loaded a heavy page and I didn't get the alert for a few seconds until I saw the iframe load:
$('#the_iframe').load(function(){
alert('loaded!');
});
So if you don't want to use jQuery take a look at their source code and see if this function behaves differently with iframe DOM elements, I will look at it myself later as I am interested and post here. Also I only tested in the latest chrome.
I have had to do this in cases where documents such as word docs and pdfs were being streamed to the iframe and found a solution that works pretty well. The key is handling the onreadystatechanged event on the iframe.
Lets say the name of your frame is "myIframe". First somewhere in your code startup (I do it inline any where after the iframe) add something like this to register the event handler:
document.getElementById('myIframe').onreadystatechange = MyIframeReadyStateChanged;
I was not able to use an onreadystatechage attribute on the iframe, I can't remember why, but the app had to work in IE 7 and Safari 3, so that may of been a factor.
Here is an example of a how to get the complete state:
function MyIframeReadyStateChanged()
{
if(document.getElementById('myIframe').readyState == 'complete')
{
// Do your complete stuff here.
}
}
The innerHTML of your iframe is blank because your iframe tag doesn't surround any content in the parent document. In order to get the content from the page referred to by the iframe's src attribute, you need to access the iframe's contentDocument property. An exception will be thrown if the src is from a different domain though. This is a security feature that prevents you from executing arbitrary JavaScript on someone else's page, which would create a cross-site scripting vulnerability. Here is some example code the illustrates what I'm talking about:
<script src="http://prototypejs.org/assets/2009/8/31/prototype.js" type="text/javascript"></script>
<h1>Parent</h1>
<script type="text/javascript">
function on_load(iframe) {
try {
// Displays the first 50 chars in the innerHTML of the
// body of the page that the iframe is showing.
// EDIT 2012-04-17: for wider support, fallback to contentWindow.document
var doc = iframe.contentDocument || iframe.contentWindow.document;
alert(doc.body.innerHTML.substring(0, 50));
} catch (e) {
// This can happen if the src of the iframe is
// on another domain
alert('exception: ' + e);
}
}
</script>
<iframe id="child" src="iframe_content.html" onload="on_load(this)"></iframe>
To further the example, try using this as the content of the iframe:
<h1>Child</h1>
Google
<p>Use the preceeding link to change the src of the iframe
to see what happens when the src domain is different from
that of the parent page</p>
I wanted to hide the waiting spinner div when the i frame content is fully loaded on IE, i tried literally every solution mentioned in Stackoverflow.Com, but with nothing worked as i wanted.
Then i had an idea, that when the i frame content is fully loaded, the $(Window ) load event might be fired. And that exactly what happened. So, i wrote this small script, and worked like magic:
$(window).load(function () {
//alert("Done window ready ");
var lblWait = document.getElementById("lblWait");
if (lblWait != null ) {
lblWait.style.visibility = "false";
document.getElementById("divWait").style.display = "none";
}
});
Hope this helps.
This function will run your callback function immediately if the iFrame is already loaded or wait until the iFrame is completely loaded.
This also addresses the following issues:
Chrome initializes every iFrame with an about:blank page which will have readyState == "complete". Later, it will replace `about:blank with the actual iframe src value. So, the initial value of readyState will not represent the readyState of your actual iFrame. Therefore, besides checking for readyState value, this function also addresses the about:blank issue.
DOMContentLoaded event doesn't work with iFrame. So it uses the load event for running the callback function if iFrame isn't already loaded. The load event is equivalent to readyState == "complete" which has been used to check whether iFrame is already loaded. So, in any scenario, the callback function will run after iFrame is fully loaded.
iFrame src can have redirects and therefore load a page different from the original src url. This function will also work in that scenario.
Pass in your callback function that you want to run when the iFrame finishes loading and the <iframe> element to this function:
function iframeReady(callback, iframeElement) {
const iframeWindow = iframeElement.contentWindow;
if ((iframeElement.src == "about:blank" || (iframeElement.src != "about:blank" && iframeWindow.location.href != "about:blank")) && iframeWindow.document.readyState == "complete") {
callback();
} else {
iframeWindow.addEventListener("load", callback);
}
}
I had a similar problem as you. What I did is that I use something called jQuery. What you then do in the javascript code is this:
$(function(){ //this is regular jQuery code. It waits for the dom to load fully the first time you open the page.
$("#myIframeId").load(function(){
callback($("#myIframeId").html());
$("#myIframeId").remove();
});
});
It seems as you delete you iFrame before you grab the html from it. Now, I do see a problem with that :p
Hope this helps :).
I have a similar code in my projects that works fine.
Adapting my code to your function, a solution could be the following:
function xssRequest(url, callback)
{
var iFrameObj = document.createElement('IFRAME');
iFrameObj.id = 'myUniqueID';
document.body.appendChild(iFrameObj);
iFrameObj.src = url;
$(iFrameObj).load(function()
{
callback(window['myUniqueID'].document.body.innerHTML);
document.body.removeChild(iFrameObj);
});
}
Maybe you have an empty innerHTML because (one or both causes):
1. you should use it against the body element
2. you have removed the iframe from the your page DOM
I think the load event is right.
What is not right is the way you use to retreive the content from iframe content dom.
What you need is the html of the page loaded in the iframe not the html of the iframe object.
What you have to do is to access the content document with iFrameObj.contentDocument.
This returns the dom of the page loaded inside the iframe, if it is on the same domain of the current page.
I would retreive the content before removing the iframe.
I've tested in firefox and opera.
Then i think you can retreive your data with $(childDom).html() or $(childDom).find('some selector') ...
I've had exactly the same problem in the past and the only way I found to fix it was to add the callback into the iframe page. Of course that only works when you have control over the iframe content.
Using onload attrbute will solve your problem.
Here is an example.
function a() {
alert("Your iframe has been loaded");
}
<iframe src="https://stackoverflow.com" onload="a()"></iframe>
Is this what you want?
Click here for more information.

Javascript callback when IFRAME is finished loading?

I need to execute a callback when an IFRAME has finished loading. I have no control over the content in the IFRAME, so I can't fire the callback from there.
This IFRAME is programmaticly created, and I need to pass its data as a variable in the callback, as well as destroy the iframe.
Any ideas?
EDIT:
Here is what I have now:
function xssRequest(url, callback)
{
var iFrameObj = document.createElement('IFRAME');
iFrameObj.src = url;
document.body.appendChild(iFrameObj);
$(iFrameObj).load(function()
{
document.body.removeChild(iFrameObj);
callback(iFrameObj.innerHTML);
});
}
This callsback before the iFrame has loaded, so the callback has no data returned.
First up, going by the function name xssRequest it sounds like you're trying cross site request - which if that's right, you're not going to be able to read the contents of the iframe.
On the other hand, if the iframe's URL is on your domain you can access the body, but I've found that if I use a timeout to remove the iframe the callback works fine:
// possibly excessive use of jQuery - but I've got a live working example in production
$('#myUniqueID').load(function () {
if (typeof callback == 'function') {
callback($('body', this.contentWindow.document).html());
}
setTimeout(function () {$('#frameId').remove();}, 50);
});
I am using jQuery and surprisingly this seems to load as I just tested and loaded a heavy page and I didn't get the alert for a few seconds until I saw the iframe load:
$('#the_iframe').load(function(){
alert('loaded!');
});
So if you don't want to use jQuery take a look at their source code and see if this function behaves differently with iframe DOM elements, I will look at it myself later as I am interested and post here. Also I only tested in the latest chrome.
I have had to do this in cases where documents such as word docs and pdfs were being streamed to the iframe and found a solution that works pretty well. The key is handling the onreadystatechanged event on the iframe.
Lets say the name of your frame is "myIframe". First somewhere in your code startup (I do it inline any where after the iframe) add something like this to register the event handler:
document.getElementById('myIframe').onreadystatechange = MyIframeReadyStateChanged;
I was not able to use an onreadystatechage attribute on the iframe, I can't remember why, but the app had to work in IE 7 and Safari 3, so that may of been a factor.
Here is an example of a how to get the complete state:
function MyIframeReadyStateChanged()
{
if(document.getElementById('myIframe').readyState == 'complete')
{
// Do your complete stuff here.
}
}
The innerHTML of your iframe is blank because your iframe tag doesn't surround any content in the parent document. In order to get the content from the page referred to by the iframe's src attribute, you need to access the iframe's contentDocument property. An exception will be thrown if the src is from a different domain though. This is a security feature that prevents you from executing arbitrary JavaScript on someone else's page, which would create a cross-site scripting vulnerability. Here is some example code the illustrates what I'm talking about:
<script src="http://prototypejs.org/assets/2009/8/31/prototype.js" type="text/javascript"></script>
<h1>Parent</h1>
<script type="text/javascript">
function on_load(iframe) {
try {
// Displays the first 50 chars in the innerHTML of the
// body of the page that the iframe is showing.
// EDIT 2012-04-17: for wider support, fallback to contentWindow.document
var doc = iframe.contentDocument || iframe.contentWindow.document;
alert(doc.body.innerHTML.substring(0, 50));
} catch (e) {
// This can happen if the src of the iframe is
// on another domain
alert('exception: ' + e);
}
}
</script>
<iframe id="child" src="iframe_content.html" onload="on_load(this)"></iframe>
To further the example, try using this as the content of the iframe:
<h1>Child</h1>
Google
<p>Use the preceeding link to change the src of the iframe
to see what happens when the src domain is different from
that of the parent page</p>
I wanted to hide the waiting spinner div when the i frame content is fully loaded on IE, i tried literally every solution mentioned in Stackoverflow.Com, but with nothing worked as i wanted.
Then i had an idea, that when the i frame content is fully loaded, the $(Window ) load event might be fired. And that exactly what happened. So, i wrote this small script, and worked like magic:
$(window).load(function () {
//alert("Done window ready ");
var lblWait = document.getElementById("lblWait");
if (lblWait != null ) {
lblWait.style.visibility = "false";
document.getElementById("divWait").style.display = "none";
}
});
Hope this helps.
This function will run your callback function immediately if the iFrame is already loaded or wait until the iFrame is completely loaded.
This also addresses the following issues:
Chrome initializes every iFrame with an about:blank page which will have readyState == "complete". Later, it will replace `about:blank with the actual iframe src value. So, the initial value of readyState will not represent the readyState of your actual iFrame. Therefore, besides checking for readyState value, this function also addresses the about:blank issue.
DOMContentLoaded event doesn't work with iFrame. So it uses the load event for running the callback function if iFrame isn't already loaded. The load event is equivalent to readyState == "complete" which has been used to check whether iFrame is already loaded. So, in any scenario, the callback function will run after iFrame is fully loaded.
iFrame src can have redirects and therefore load a page different from the original src url. This function will also work in that scenario.
Pass in your callback function that you want to run when the iFrame finishes loading and the <iframe> element to this function:
function iframeReady(callback, iframeElement) {
const iframeWindow = iframeElement.contentWindow;
if ((iframeElement.src == "about:blank" || (iframeElement.src != "about:blank" && iframeWindow.location.href != "about:blank")) && iframeWindow.document.readyState == "complete") {
callback();
} else {
iframeWindow.addEventListener("load", callback);
}
}
I had a similar problem as you. What I did is that I use something called jQuery. What you then do in the javascript code is this:
$(function(){ //this is regular jQuery code. It waits for the dom to load fully the first time you open the page.
$("#myIframeId").load(function(){
callback($("#myIframeId").html());
$("#myIframeId").remove();
});
});
It seems as you delete you iFrame before you grab the html from it. Now, I do see a problem with that :p
Hope this helps :).
I have a similar code in my projects that works fine.
Adapting my code to your function, a solution could be the following:
function xssRequest(url, callback)
{
var iFrameObj = document.createElement('IFRAME');
iFrameObj.id = 'myUniqueID';
document.body.appendChild(iFrameObj);
iFrameObj.src = url;
$(iFrameObj).load(function()
{
callback(window['myUniqueID'].document.body.innerHTML);
document.body.removeChild(iFrameObj);
});
}
Maybe you have an empty innerHTML because (one or both causes):
1. you should use it against the body element
2. you have removed the iframe from the your page DOM
I think the load event is right.
What is not right is the way you use to retreive the content from iframe content dom.
What you need is the html of the page loaded in the iframe not the html of the iframe object.
What you have to do is to access the content document with iFrameObj.contentDocument.
This returns the dom of the page loaded inside the iframe, if it is on the same domain of the current page.
I would retreive the content before removing the iframe.
I've tested in firefox and opera.
Then i think you can retreive your data with $(childDom).html() or $(childDom).find('some selector') ...
I've had exactly the same problem in the past and the only way I found to fix it was to add the callback into the iframe page. Of course that only works when you have control over the iframe content.
Using onload attrbute will solve your problem.
Here is an example.
function a() {
alert("Your iframe has been loaded");
}
<iframe src="https://stackoverflow.com" onload="a()"></iframe>
Is this what you want?
Click here for more information.

Categories

Resources