Nested iframes, AKA Iframe Inception - javascript

Using jQuery I am trying to access div id="element".
<body>
<iframe id="uploads">
<iframe>
<div id="element">...</div>
</iframe>
</iframe>
</body>
All iframes are on the same domain with no www / non-www issues.
I have successfully selected elements within the first iframe but not the second nested iframe.
I have tried a few things, this is the most recent (and a pretty desperate attempt).
var iframe = jQuery('#upload').contents();
var iframeInner = jQuery(iframe).find('iframe').contents();
var iframeContent = jQuery(iframeInner).contents().find('#element');
// iframeContent is null
Edit:
To rule out a timing issue I used a click event and waited a while.
jQuery().click(function(){
var iframe = jQuery('#upload').contents().find('iframe');
console.log(iframe.find('#element')); // [] null
});
Any ideas?
Thanks.
Update:
I can select the second iframe like so...
var iframe = jQuery('#upload').contents().find('iframe');
The problem now seems to be that the src is empty as the iframe is generated with javascript.
So the iframe is selected but the content length is 0.

Thing is, the code you provided won't work because the <iframe> element has to have a "src" property, like:
<iframe id="uploads" src="http://domain/page.html"></iframe>
It's ok to use .contents() to get the content:
$('#uploads).contents() will give you access to the second iframe, but if that iframe is "INSIDE" the http://domain/page.html document the #uploads iframe loaded.
To test I'm right about this, I created 3 html files named main.html, iframe.html and noframe.html and then selected the div#element just fine with:
$('#uploads').contents().find('iframe').contents().find('#element');
There WILL be a delay in which the element will not be available since you need to wait for the iframe to load the resource. Also, all iframes have to be on the same domain.
Hope this helps ...
Here goes the html for the 3 files I used (replace the "src" attributes with your domain and url):
main.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>main.html example</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
$(function () {
console.log( $('#uploads').contents().find('iframe').contents().find('#element') ); // nothing at first
setTimeout( function () {
console.log( $('#uploads').contents().find('iframe').contents().find('#element') ); // wait and you'll have it
}, 2000 );
});
</script>
</head>
<body>
<iframe id="uploads" src="http://192.168.1.70/test/iframe.html"></iframe>
</body>
iframe.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>iframe.html example</title>
</head>
<body>
<iframe src="http://192.168.1.70/test/noframe.html"></iframe>
</body>
noframe.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>noframe.html example</title>
</head>
<body>
<div id="element">some content</div>
</body>

var iframeInner = jQuery(iframe).find('iframe').contents();
var iframeContent = jQuery(iframeInner).contents().find('#element');
iframeInner contains elements from
<div id="element">other markup goes here</div>
and iframeContent will find for elements which are inside of
<div id="element">other markup goes here</div>
(find doesn't search on current element) that's why it is returning null.

Hey I got something that seems to be doing what you want a do. It involves some dirty copying but works. You can find the working code here
So here is the main html file :
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
Iframe = $('#frame1');
Iframe.on('load', function(){
IframeInner = Iframe.contents().find('iframe');
IframeInnerClone = IframeInner.clone();
IframeInnerClone.insertAfter($('#insertIframeAfter')).css({display:'none'});
IframeInnerClone.on('load', function(){
IframeContents = IframeInner.contents();
YourNestedEl = IframeContents.find('div');
$('<div>Yeepi! I can even insert stuff!</div>').insertAfter(YourNestedEl)
});
});
});
</script>
</head>
<body>
<div id="insertIframeAfter">Hello!!!!</div>
<iframe id="frame1" src="Test_Iframe.html">
</iframe>
</body>
</html>
As you can see, once the first Iframe is loaded, I get the second one and clone it. I then reinsert it in the dom, so I can get access to the onload event. Once this one is loaded, I retrieve the content from non-cloned one (must have loaded as well, since they use the same src). You can then do wathever you want with the content.
Here is the Test_Iframe.html file :
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div>Test_Iframe</div>
<iframe src="Test_Iframe2.html">
</iframe>
</body>
</html>
and the Test_Iframe2.html file :
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div>I am the second nested iframe</div>
</body>
</html>

You probably have a timing issue. Your document.ready commend is probably firing before the the second iFrame is loaded. You dont have enough info to help much further- but let us know if that seems like the possible issue.

You should use live method for elements which are rendered later, like colorbox, hidden fields or iframe
$(".inverter-value").live("change",function() {
elem = this
$.ajax({
url: '/main/invertor_attribute/',
type: 'POST',
aysnc: false,
data: {id: $(this).val() },
success: function(data){
// code
},
dataType: 'html'
});
});

I think the best way to reach your div:
var your_element=$('iframe#uploads').children('iframe').children('div#element');
It should work well.

If browser supports iframe, then DOM inside iframe come from src attribute of respective tag. Contents that are inside iframe tag are used as a fall back mechanism where browser does not supports iframe tag.
Ref: http://www.w3schools.com/tags/tag_iframe.asp

I guess your problem is that jQuery is not loaded in your iframes.
The safest approach is to rely on pure DOM-based methods to parse your content.
Or else, start with jQuery, and then once inside your iframes, test once if typeof window.jQuery == 'undefined', if it's true, jQuery is not enabled inside it and fallback on DOM-based method.

Related

Calling iframe link from other js file not working

I created an iframe in vex6.html and a js file in styles.gq/test.js and in that file there is the link and id but when I try to call the code in html it does not work.
Here is my code for vex6.html
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<script type="text/javascript" src="https://styles.gq/test.js" ></script>
<iframe id="vex6" width="100%" height="500" style="border:1px solid black;"></iframe>
</body>
</html>
here is my js code
document.getElementById("vex3").src
= "https://www.obviousplays.tk/gfiles/vex3";
document.getElementById("vex4").src
= "https://www.obviousplays.tk/gfiles/vex4";
document.getElementById("vex5").src
= "https://www.obviousplays.tk/gfiles/vex5";
document.getElementById("vex6").src
= "https://www.obviousplays.tk/Gfiles6/vex6";
document.getElementById("slope").src
= "https://www.obviousplays.tk/gfiles/slope";
I expected an iframe but instead there seems to be no link for the iframe
it is also spitting out the error cannot set properties of null (setting(src))
Add the line
<script type="text/javascript" src="https://styles.gq/test.js</script> after the iframe tag.
Worked for me.
Error in console: "script.js:3 Uncaught TypeError: Cannot set properties of null (setting 'src')"
Your script is loaded before the iframe content, meaning that you're trying to initialize the source of an unidentified object.
Solution: Place the <script> tag below your iframe. It is a good practice to place <script> tags at the bottom of the <body> tag so we can always access loaded content. However, sometimes it takes the contents a little bit more time until they fully load (despite placing the <script> tag at the bottom of the page). I'd suggest wrapping your code in window.onload = () {} It will ensure that all contents are loaded before firing the code.
<body>
<iframe id="vex3" width="100%" height="500" style="border:1px solid black;"></iframe>
<script type="text/javascript" src="https://styles.gq/test.js"></script>
</body>
Your code is fine and should work (pardon for criticizing). Anytime you seem to use repetitive code, it means that it can be simplified/automated like so:
window.onload = () => {
// Target all <iframe> tags.
iframes = document.querySelectorAll('iframe');
// Loop through list of <iframe> nodes.
Array.from(iframes).map(iframe => {
// Update <iframe>'s attribute "src" to the origin URL,
// and use the iframe's attribute "id" value as the final source.
iframe.setAttribute('src', `https://www.obviousplays.tk/gfiles/${iframe.id}`)
});
}

How to get reference to the iframe from which script html tag was generated?

I have small snippet that is inside iframe and generates script html tag and appends it to the window.top.document.head.
Now I want to know how do I check from within potato.js from which iframe it was generated from once it is already loaded?
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<iframe>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script>
(function() {
var s = document.createElement('script');
s.setAttribute('type','text/javascript');
s.setAttribute('src','https://test.com/potato.js');
window.top.document.head.appendChild(s);
})();
</script>
</body>
</html>
</iframe>
</body>
</html>
Edit: I can not change this code inside the iframe
That information isn't stored automatically.
The only way I can think of would be to add an expando-prop to the script with a reference to the current window (i.e. the frame's window)…
s.sourceWindow = window;
… then read that from within potato.js …
const sourceWindow = document.currentScript.sourceWindow;
… and then loop over all the frames (window.frames) looking for a match.
Since you are using window.top and not window.parent you might need to be recursive there.

How do I call the JavaScript function properly?

<!DOCTYPE html>
<html lang="en">
<head>
<title>JavaScript Example</title>
<script>
function displayString() {
return "<h1>Main Heading</h1>"
}
displayString();
document.write("Execute during page load from the head<br>");
</script>
</head>
<body>
<script>
document.write("Execute during page load from the body<br>");
</script>
</body>
</html>
So this is my problem. No matter where I put the displayString(), the h1 just never seems to show up on the browser. Can anybody please help me see where I am wrong? I am new to JavaScript. Oh, and what I am trying to do is to call the function.
You need to write the returned String to the document:
<!DOCTYPE html>
<html lang="en">
<head>
<title>JavaScript Example</title>
<script>
function displayString() {
return "<h1>Main Heading</h1>"
}
document.write(displayString());
document.write("Execute during page load from the head<br>");
</script>
</head>
<body>
<script>
document.write("Execute during page load from the body<br>");
</script>
</body>
</html>
No matter where I put the displayString(), the h1 just never seems to
show up on the browser.
If you wish to add a new element to a document, several approaches are available:
document.write (effectively deprecated)
.innerHTML (sometimes useful, but can be slow)
DOM API - recommended approach
The recommended approach is to use the DOM API.
DOM stands for Document Object Model. Essentially it's the markup of your document represented as a tree-like structure of nodes. There are many DOM API functions which allow you to:
add
remove
append
prepend
insert
update
new DOM nodes.
Any DOM node may be added, removed or updated, including:
parent elements
child elements
sibling elements
element attributes
ids, classNames, classLists
custom data-* attributes
text nodes
Here is an example:
function displayMainHeading () {
let mainHeading = document.createElement('h1');
mainHeading.textContent = 'Main Heading';
document.body.prepend(mainHeading);
}
displayMainHeading();
<p>Paragraph 1</p>
<p>Paragraph 2</p>
Further Reading
This is a good primer to get you started:
A Beginners Guide To DOM Manipulation by Iqra Masroor

How to access a method of parent window of an Iframe [Chrome browser ]

I tried many times and many ways to call the method from inside the iframe while not yet successful to do so. please see below,
main.html : consisting the two iframe
iframe-1 linked with a index.html from where i want to call a method of main.html or want to change the src of second iframe.
main.html
<html>
<head> </head>
<body>
<iframe id="iframe-1" src="index.html"></iframe>
<iframe id="iframe-2" ></iframe>
</body>
</html>
index.html
<html> <head>
<script type="text/javascript">
$(document).ready(function(){
// How to access the method of main.html and change the iframe src
});
</script>
</head> <body>
......
</body> </html>
Note : tried parent.methodName(), window.parent.methodName() not working
#EDIT : success on IE & MOZILLA but getting error on Chrome ( Cannot call method 'getElementById' of undefined )
You should try with
document.getElementById("iframe-1").contentWindow.func();
or
var $f = $("#myIFrame");
var fd = $f[0].document || $f[0].contentWindow.document; // document of iframe
fd.MyFunction(); // run function
Docs
I am keeping this short.
As you are looking forward for the iframes/frames on same document[window sharing]. To access a variable defined in one document inside another document.You have to use document.importNode(original Node as in other document,boolean) method as per DOM 2.
Do something like this for javacript code ...
iframe=document.getElementsTagName("iframe")[0];
documentI(original variable/node present here)-
OriginalNode=iframe.contentWindow.document.getElementsByTagName(//Tag name of Node//)
documentII(node to be cloned here)- iframe.contentWindow.document.importNode(OriginalNode,True)
Node can be created of any method,property or object in any iframe by simple DOM methods.
This would work
index.html
<html>
<head>
<script type="text/javascript">
function run() {
window.parent.document.getElementById("iframe-2").src = "/test.html";
}
</script>
</head>
<body onload="run();">
</body>
</html>
How about this?
Or create a method inside main.html and access it using:
window.parent.methodname();
Ron.
ps. window.parent.methodname(); works perfectly for me when I have a method in main.html
main.html
<html>
<head> </head>
<script>
function foo() {
alert(1);
}
</script>
<body>
<iframe id="iframe-1" src="index.html"></iframe>
<iframe id="iframe-2" ></iframe>
</body>
</html>

JavaScript: find dimensions of iframe body

I have a web page which embeds another page in an iframe. I want a JavaScript function in the outer document to fetch the size, in pixels, of the document in the iframe.
I have been exploring the DOM and the only attributes I can find relating to width and height give the height of the iframe itself, which is smaller than the document inside it.
e.g.
<iframe src="tall_page.php" id="my_iframe" style="height: 101px"></iframe>
...
var i = document .getElementById ("my_iframe");
i = i .contentDocument .body;
alert (i .offsetHeight); // or scrollHeight or clientHeight
The above will give "101". The value I am after is the size of the whole content document, not the frame -- and not just the <body>: if the CSS gives html{padding:x} for example, I want this to be inorporated.
How do I get this value?
Using jQuery this should work:
var height = $("my_iframe").height();
var width = $("my_iframe").width();
Hope that helps
I got it to work using the contentWindow object.
I think the idea here is to get the width/height of an
element that you set inside the iframe. In my example,
I set the iframe body to 3000px using css, and got it to work.
Keep in mind that since you're accessing an iframe's data,
you need to adhere to the same origin policy
Here is my example:
iframe.html
<!DOCTYPE html>
<html lang='en'>
<head>
<title>My Iframe</title>
</head>
<body id='mybody' style='width:3000px;'>
Hello!
</body>
</html>
index.html
<!DOCTYPE html>
<html lang='en'>
<head>
<title>My Test</title>
<script>
window.onload = function() {
var f = document.getElementById('myiframe');
console.dir(f.contentWindow.document.getElementById('mybody').clientWidth);
}
</script>
</head>
<body>
<iframe id='myiframe' src='iframe.html' height='480' width='640'>
</iframe>
</body>
</html>
Hope that helps.

Categories

Resources