determining iframe div distance from parent window top - javascript

I have a div inside an iframe (no problems with origin policy as both the documents are from same application/domain). I need to figure out the distance of the div from parent window top. The iframe also has scrollbar, so that's one thing to consider too.
I can't produce a semi-working jsfiddle because of the cross origin policies (iframe.contentWindow won't be available), but here's the non-working fiddle anyway.
I have an embedded iframe in the fiddle:
<iframe src="https://noc2spam.github.io/embed.html?ddd" style="display:block; border:0; width:300px; height:200px; overflow:scroll"></iframe>
The following screenshot might give you an idea of what I exactly need.
I have already tried some of the answers which do not seem work for iframes. As for example, this does not work. What is the most convenient way of doing this?

In order to get the offset from top of the div contained in the iframe you have to SUM the DIV offset inside the IFRAME to the offset of the IFRAME inside the mainWindow.
To do so in Jquery (and postMessage between iframe and MainWindow):
/**
supposed:
#example-iframe = id of iframe
#example-div = id of DIV inside the iframe
*/
/** main.html -- top page */
$("#example-iframe")[0].contentWindow.postMessage({
cmd:"getDivDistance"
});
window.onmessage = function(e){
var msg = JSON.parse(e.data)
switch(msg.cmd){
case "setDivDistance":
var frametop = $("#example-iframe").offset().top
var totaltop = frametop + msg.top;
alert("MY TOP IS "+totaltop);
break;
}
};
/** frame.html -- iframe page*/
window.onmessage = function(e){
var msg = JSON.parse(e.data)
switch(msg.cmd){
case "getDivDistance":
window.top.postMessage({
cmd:"setDivDistance",
top:$("#example-div").offest().top
});
break;
}
}

Related

page has different height when inside an iframe

I've googled a bit and there were a few leads, but I couldn't get any of those leads to work:
I have a page that has an iframe with the src pointing to an external page (cross domain). When the child/iframed page loads, it posts a message of its height. I put a console.log of the height in the javascript. If I open that page in a separate window (type the iframe's src URL in a separate tab, in other words), the console logs the expected height.
However, when I open the parent page with the iframe, the console logs either 0 or a very incorrect value of 150. I've looked through the css and html, and I don't have any specifications of 150.. Anyone have a clue what's going on here?
Abstracted code:
Parent HTML:
...
<iframe src="example.childpage.com" scrolling="no" frameBorder="0"></iframe>
...
Parent Javascript:
...
$(document).ready(function(){
window.addEventListener('message', function(m){
var messageData = m.data;
if(messageData.type=='document-loaded' &&
messageData.hasOwnProperty('height'){
resize_iframe(messageData.height); //function defined else where
//and works
};
});
...
IFrame Javascript:
...
$(document).ready(function(){
var body = document.body;
var html = document.documentElement;
var maxHeight = Math.max(body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight);
//Logs height correctly when opened in a separate window but not when
//iframed
console.log("POSTING HEIGHT", maxHeight);
window.parent.postMessage({'type':'document-loaded', 'height': maxHeight},
PARENT_HOST_URL); //PARENT_HOST_URL defined elsewhere
});
...
I realize I have a mixture of jquery and vanilla javascript here; I've done both $(document).height() and the Math.max() shown above to get the height, but both ways still have the same issue.
Much thanks!
ok I finally found a good solution:
$('iframe').load(function() {
this.style.height =
this.contentWindow.document.body.offsetHeight + 'px';
});
Because some browsers (older Safari and Opera) report onload completed before CSS renders you need to set a micro Timeout and blank out and reassign the iframe's src.
$('iframe').load(function() {
setTimeout(iResize, 50);
// Safari and Opera need a kick-start.
var iSource = document.getElementById('your-iframe-id').src;
document.getElementById('your-iframe-id').src = '';
document.getElementById('your-iframe-id').src = iSource;
});
function iResize() {
document.getElementById('your-iframe-id').style.height =
document.getElementById('your-iframe-
id').contentWindow.document.body.offsetHeight + 'px';
}
I had a function that looped through not-yet-accessible elements and called $(element).hide() on them -- which sets the style display: none.
Turns out calculating the height of an element is respective of its visibility on the actual page, regardless of it being in an iframe. So the browser couldn't see it, so the height was being miscalculated (still weird it was returning a random 150px value). That explains why it was calculating correctly on a separate page.
Instead of doing hide(), I just set the visibility to hidden and that fixed my issue of getting the incorrect heights.

Set iframe height dynamically

I am trying fit a iframe that is linked with a search, so i can get a iframe result between 0px and 9750px in height depending on search properties.
How can i make the height dynamical? I have tried getting the table properties inside the iframe but without success.
Basically i want to know how to get the height of the content I get from the iframe. Not the iframe itself.
<script type="text/javascript">
function iframeLoaded() {
var iFrameID = document.getElementById('idIframe');
if(iFrameID) {
// here you can make the height, I delete it first, then I make it again
iFrameID.height = "";
iFrameID.height = iFrameID.contentWindow.document.body.scrollHeight + "px";
}
}
</script>
When I try to do this i get this eror "Uncaught DOMException: Blocked a frame with origin "http://localhost:52191" from accessing a cross-origin frame."
you can't get the iframe size because cross domain issue , but i think this library can solve the problem.
iframe-resizer

iframe inside a div. scrolling the div not working

I know that trying to scroll the iframe itself in not the way to go and instead i should be scrolling the div. Thing is it doesn't work. What is wrong with this code? Is it a google thing? I'm using the custom search so it shows up in the frame but I know google and frames don't like to play with each other.
HTML
<div id="googleframe"><iframe id="googleseo" src="http://www.google.com/custom?q=hey+there&btnG=Search"></iframe></div>
JS
var seoFrame = document.getElementById('googleseo');
seoFrame.src = googleSearch;
seoFrame.onload = function () {
document.getElementById('googleframe').scrollTop = 300;
}
}
It was a CSS issue. The iframe wasn't long enough to scroll. It was the same height as my div so I made it longer and it works perfectly.
This is due to the scrollTop referencing the iframe, not the body within the frame. The iframe itself doesn't have a scrollbar, it's the document within it.
Fiddle of it working http://jsfiddle.net/ebzxzgmo/
var seoFrame = document.getElementById('googleseo');
var elem = (seoFrame.contentDocument||seoFrame.contentWindow.document).documentElement;
elem.getElementsByTagName('body')[0].scrollTop = 300;
Notice that it's requesting jsfiddle. Browsers block accessing the DOM of iframes from other domains.
Reference for scrolling cross domain: Scroll a cross-domain child iframe?

Resize iframe height according to resizable content

I have an iframe and I want to re-size the height according to the content which may resize if user makes certain actions.
I don't want a scroll bar so it appears as a normal page
Use a div instead of an iFrame. Try posting some sample code so we can help you more. Generally, you cannot resize an iframe based on its content.
scrollHeight is the major property to retrieve the height of the IFRAME's content like this:
contentWindow.document.body.scrollHeight
After the IFRAME is loaded, you can then change the height by doing the following:
<script type="text/javascript">
function resizeIframe() {
var iFrameID = document.getElementById('idIframe');
if(iFrameID) {
var cont = iFrameID.contentWindow.document.body || frame.contentDocument.body
// here you can make the height
iFrameID.height = cont.scrollHeight + "px";
}
}
</script>
On the IFRAME load event, you can call this function:
But sure..iframe should not be loaded from other website

Making an iframe take vertical space

I would like to have an iframe take as much vertical space as it needs to display its content and not display a scrollbar. Is it at all possible ?
Are there any workarounds?
This should set the IFRAME height to its content's height:
<script type="text/javascript">
the_height = document.getElementById('the_iframe').contentWindow.document.body.scrollHeight;
document.getElementById('the_iframe').height = the_height;
</script>
You may want to add scrolling="no" to your IFRAME to turn off the scrollbars.
edit: Oops, forgot to declare the_height.
The workaround is not to use <iframe> and preprocess code on server-side.
Also check out this thread: How does the DiggBar dynamically resize its iframe's height based on content not on their domain?.
It addresses the same question.
This CSS snippet should remove the vertical scrollbar:
body {
overflow-x: hidden;
overflow-y: hidden;
}
I'm not sure yet about having it take up as much vertical space as it needs, but I'll see if I can't figure it out.
Adding a DOCTYPE declaration to the IFRAME source document will help to calculate the correct value from the line
document.getElementById('the_iframe').contentWindow.document.body.scrollHeight
see W3C DOCTYPE for examples
I was having problems with both IE and FF as it was rendering the iframe document in 'quirks' mode, until I added the DOCTYPE.
FF/IE/Chrome support: The .scrollHeight doesnt work with Chrome so I have come up with a javascript example using jQuery to set all IFRAME heights on a page based on the iframes content. NOTE: This is for reference pages within the your current domain.
<script type="text/javascript">
$(document).ready(function(){
$('iframe').each(function(){
var context = $(this);
context.load(function(event){ // attach the onload event to the iframe
var body = $(this.contentWindow.document).find('body');
if (body.length > 0 && $(body).find('*').length > 0) { // check if iframe has contents
context.height($(body.get(0)).height() + 20);
} else {
context.hide(); // hide iframes with no contents
}
});
});
});
</script>

Categories