Get all elements inside iframe tag - javascript

this is my part of code now i'm using iframe tag and loaded epub on iframe tag
then i don't know how to get all elements inside iframe tag.
jQuery(document).ready(function($) {
var tmp = $('#epub_loader iframe').contents().find('body').html();
alert(tmp);
});
<iframe id="epub_loader" href="test.epub" ></iframe>
`

Assuming both your frames are on the same domain and there is no restriction with Same Domain Policy, you can use the following code from the "parent" frame to get an element in the "child" iframe (in your case body tag).
Pseudo code, you need to actually point to your iframe DOM by id:
var html = document.getElementById('iframe').contentDocument.body.innerHTML;
Notes: In case iframe is on a different domain, you have limited access for browser security reasons.

The thing you need is to wait document will be fully loaded coz you are used iframe,then you should call ....
jQuery(document).ready(function() {
window.onload = function () { //call when iframe is fully loaded
var tmp = $('#epub_loader').contents().find('body').html();
alert(tmp);
};
});

Related

Get element in an HTML document within another HTML document [duplicate]

I have this HTML code:
<html>
<head>
<script type="text/javascript">
function GetDoc(x)
{
return x.document ||
x.contentDocument ||
x.contentWindow.document;
}
function DoStuff()
{
var fr = document.all["myframe"];
while(fr.ariaBusy) { }
var doc = GetDoc(fr);
if (doc == document)
alert("Bad");
else
alert("Good");
}
</script>
</head>
<body>
<iframe id="myframe" src="http://example.com" width="100%" height="100%" onload="DoStuff()"></iframe>
</body>
</html>
The problem is that I get message "Bad". That mean that the document of iframe is not got correctly, and what is actualy returned by GetDoc function is the parent document.
I would be thankful, if you told where I do my mistake. (I want to get document hosted in IFrame.)
Thank you.
You should be able to access the document in the IFRAME using the following code:
document.getElementById('myframe').contentWindow.document
However, you will not be able to do this if the page in the frame is loaded from a different domain (such as google.com). This is because of the browser's Same Origin Policy.
The problem is that in IE (which is what I presume you're testing in), the <iframe> element has a document property that refers to the document containing the iframe, and this is getting used before the contentDocument or contentWindow.document properties. What you need is:
function GetDoc(x) {
return x.contentDocument || x.contentWindow.document;
}
Also, document.all is not available in all browsers and is non-standard. Use document.getElementById() instead.
In case you get a cross-domain error:
If you have control over the content of the iframe - that is, if it is merely loaded in a cross-origin setup such as on Amazon Mechanical Turk - you can circumvent this problem with the <body onload='my_func(my_arg)'> attribute for the inner html.
For example, for the inner html, use the this html parameter (yes - this is defined and it refers to the parent window of the inner body element):
<body onload='changeForm(this)'>
In the inner html :
function changeForm(window) {
console.log('inner window loaded: do whatever you want with the inner html');
window.document.getElementById('mturk_form').style.display = 'none';
</script>
You can also use:
document.querySelector('iframe').contentDocument

Write inline javascript in iframe

I have code that can be reduced to this:
<script>
function write_to_iframe(){
let nw = document.getElementById("mysrc");
let myframe = document.getElementById("myframe");
myframe.contentWindow.document.body.innerHTML = nw.innerHTML;
}
</script>
<iframe id="myframe" width="230" height="95"></iframe>
<div id="mysrc">
<script>
function hello(){
alert("hello world");
}
</script>
SayHello<br>
</div>
It writes the code in the div to the iframe. That part seems to work. However, when I click the SayHello link in the iframe I get a javascript error that the function hello() cannot be found.
What is going wrong here? And how can I declare an inline javascript function in the frame that works.
I am not interested in external javascript files or code that puts everything in the link (like onclick="javascript:alert('hi');").
I would reconsider using an iframe with innerHTML and trying to call a function in the main document from it. The support can vary in different browsers, iframes access to its parent is very limited. If both those things are on the same domain then you don't break CORS policy and you can do more but still there are better options.
If you insist on using iframe, I would consider creating an external path for it (same domain) ex. iframe/embed.html put HTML there normally, then change location after click triggered inside to iframe/embed.html#callHello. And in main document I would add eventListner to detect location change.
const iframe = document.getElementById("iframeId");
window.open("https://example.com/iframe/embed.html", "iframeId");
iframe.addEventListener("load", () => {
if (iframe.contentWindow.location.href.includes('#callHello')) {
hello();
}
});

Open <div> popup outside iFrame

Info: I was working on it for so long, I have a webpage that contains an iframe. Inside that iframe i have opened a page (application) from my own site.
Question: I'm trying to get the <div class = "ps-lightbox"> </ div> inside that iframe out of the iframe. but i cant figure it out with jQuery..
I know it sounds confusing. But I hope you understand my explanation.
Does anyone know how to fix this? You could save my day..
Screenshot of the webpage <
You can not access the elements which are not part of iframe document. But if you have iframe of your own website then window.postMessage can do the trick.
Consider below example:
mainPage.html
<html>
<head>
<script type="text/javascript">
window.addEventListener("message", function(evnet){
if(event.type === "GET_SOME_ELEMENT"){
var iframeWindow = document.getElementsById("iframe1")[0].contentWindow;
iframeWindow.postMessage("POST_SOME_ELEMENT", "TARGET_ORIGIN", {element: $(".some-element")}
}
});
<script/>
</head>
<body>
<div class="some-element"/>
<iframe id="iframe1" src="iframePage.html"/>
</body>
</html>
iframePage.html
<html>
<head>
<script type="text/javascript">
if(window.parent){
window.parent.postMessage("GET_SOME_ELEMENT", "TARGET_ORIGIN");
window.addEventListener("message", function(evnet){
if(event.type === "POST_SOME_ELEMENT"){
console.log(event.data.element);
}
});
}
<script/>
</head>
</html>
The exact question is how to do it with pure JavaScript, not with jQuery.
But I always use the solution that can be found in jQuery's source code. It's just one line of native JavaScript.
For me, it's the best, easily readable and even afaik the shortest way to get the content of the iframe.
First get your iframe
var iframe = document.getElementById('id_description_iframe');
// or
var iframe = document.querySelector('#id_description_iframe');
And then use jQuery's solution
var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
It works even in the Internet Explorer which does this trick during
the contentWindow property of the iframe object. Most other browsers
use the contentDocument property and that is the reason why we proof
this property first in this OR condition. If it is not set to try
contentWindow.document.
Select elements in iframe
Then you can usually use getElementById() or even querySelectorAll() to select the DOM-Element from the iframeDocument:
if (!iframeDocument) {
throw "iframe couldn't be found in DOM.";
}
var iframeContent = iframeDocument.getElementById('frameBody');
// or
var iframeContent = iframeDocument.querySelectorAll('#frameBody');
Call functions in the iframe
Get just the window element from iframe to call some global functions, variables or whole libraries (e.g. jQuery):
var iframeWindow = iframe.contentWindow;
// you can even call jQuery or other frameworks
// if it is loaded inside the iframe
iframeContent = iframeWindow.jQuery('#frameBody');
// or
iframeContent = iframeWindow.$('#frameBody');
// or even use any other global variable
iframeWindow.myVar = window.myVar;
// or call a global function
var myVar = iframeWindow.myFunction(param1 /*, ... */);
Note
All this is possible if you observe the same-origin policy.
This might help you
var html = $(".ps-lightbox").contents().find("body").html()
And btw, you can get access to iframe's content only from the same origin due to XSS protection
Make sure your code is inside jQuery ready event.
// This won't work
$("#iframe").contents().find('.ps-lightbox');
// This will work
$(function() {
$("#iframe").contents().find('.ps-lightbox');
})

javascript proper way to call function

I'm not good in javascript but I find examples and usually understand it. But this is driving me crazy for the last hour. What I'm trying to do is to embed the list.php file to my mainpage.html using the IFRAME. This list.php is showing some links and when I click the link the result should be shown in another place on main page (I'm targeting some div). And those 3 functions are placed inside list.php file.
If I do this:
function autoscroll() {
window.parent.parent.scrollTo(0,0);
}
function resizeIframe(obj) {
obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
}
function url2div(url,target){
parent.document.getElementById(target).innerHTML = '<iframe style="width:100%;height:100%;" scrolling="no" frameborder="1" onload="javascript:resizeIframe(this); javascript:autoscroll();" src="' + url + '" />';
}
So if I call the autoscroll() function within my IFRAME like this
onload="javascript:autoscroll();"
autoscroll doesn't work (everything else is working).
But if I put it directly in IFRAME like this:
onload="javascript:window.parent.parent.scrollTo(0,0);"
then it works!
What's wrong with first approach?
It sounds like you're putting the script element in your main page, but then trying to use it in an iframe on the page. Also, you're using window.parent.parent which goes two levels up the containment hierarchy, which seems suspicious.
The iframe and the main window are two different environments. Globals (like your autoscroll) in the main page are not in scope for the iframe's code.
The iframe can access the parent window's globals, provided they're from the same origin, via the parent symbol:
parent.autoscroll();
Then use window, or window.paren, depending on whether you want to scroll the parent or its parent.
It's all about being relative to the document in which the script is included.
Since that was clear as mud: Let's assume your goal is to scroll the main window that the iframe is in:
Option 1: Put it in the iframe (probably best):
In the main window:
Nothing.
In the iframe
<script language="JavaScript">
function autoscroll() {
window.parent.scrollTo(0,0); // <== Only one `parent`, if you want the iframe's parent
}
</script>
and
onload="autoscroll();"
Or:
Option 2: Put it in the main window:
In the main window:
<script language="JavaScript">
function autoscroll() {
window.scrollTo(0,0); // <== No `parent` at all, if you want the main window
}
</script>
In the iframe:
onload="parent.autoscroll();"

Reload an IFRAME without adding to the history

I'm changing an IFRAME's src in order to reload it, its working fine and firing the onload event when its HTML loads.
But it adds an entry to the history, which I don't want. Is there any way to reload an IFRAME and yet not affect the history?
Using replace() is only an option with your own domain iframes. It fails to work on remote sites (eg: a twitter button) and requires some browser-specific knowledge to reliably access the child window.
Instead, just remove the iframe element and construct a new one in the same spot. History items are only created when you modify the src attribute after it is in the DOM, so make sure to set it before the append.
Edit: JDandChips rightly mentions that you can remove from DOM, modifiy, and re-append. Constructing fresh is not required.
You can use javascript location.replace:
window.location.replace('...html');
Replace the current document with the
one at the provided URL. The
difference from the assign() method is
that after using replace() the current
page will not be saved in session
history, meaning the user won't be
able to use the Back button to
navigate to it.
Like Greg said above, the .replace() function is how to do this. I can't seem to figure out how to reply to his answer*, but the trick is to reference the iFrames contentWindow property.
var ifr = document.getElementById("iframeId");
ifr.contentWindow.location.replace("newLocation.html");
*Just learned I need more reputation to comment on an answer.
An alternative method to recreating the iframe would be to remove the iframe from the DOM, change the src and then re add it.
In many ways this is similar to the replace() suggestion, but I had some issues when I tried that approach with History.js and managing states manually.
var container = iframe.parent();
iframe.remove();
iframe.attr('src', 'about:blank');
container.append(iframe);
One solution is to use the object tag rather than the iframe tag.
Replacing this:
<iframe src="http://yourpage"/>
By this:
<object type="text/html" data="http://yourpage"/>
will allow you to update the data attribute without affecting the history. This is useful if you use a declarative framework such as React.js where you are not supposed to do any imperative command to update the DOM.
More details on differences between iframe and object: Use of Iframe or Object tag to embed web pages in another
Try to use this function to replace old iframe with new iframe which is copied from old one:
function setIFrameSrc(idFrame, url) {
var originalFrame = document.getElementById(idFrame);
var newFrame = document.createElement("iframe");
newFrame.id = originalFrame.getAttribute("id");
newFrame.width = originalFrame.getAttribute("width");
newFrame.height = originalFrame.getAttribute("height");
newFrame.src = url;
var parent = originalFrame.parentNode;
parent.replaceChild(newFrame, originalFrame);
}
Use it like this:
setIFrameSrc("idframe", "test.html");
This way will not add URL of iframe to browser history.
Use the replace method to bypass the addition of the iframe's URL to history:
HTML:
<iframe id="myIframe" width="100%" height="400" src="#"></iframe>
JavaScript:
var ifr = document.getElementById('mIframe')
if (ifr) {
ifr.contentWindow.location.replace('http://www.blabla.com')
}
JDandChips answer worked for me on a cross origin iframe (youtube), here it is in vanilla JS (without JQuery):
const container = iframe.parentElement;
container.removeChild(iframe);
iframe.setAttribute('src', 'about:blank');
container.appendChild(iframe);
The most simple and fast loading solution
Use window.location.replace to not update the history when loading the page or the frame.
For links it looks like this:
<a href="#" onclick="YourTarget.location.replace ('http://www.YourPage.com');">
The targeted Link</a>
or
<a href="javascript:YourTarget.location.replace ('http://www.YourPage.com');">
The targeted Link</a>
But if you want it not to act from link but to act automatically when loading the frame then from the iframe you should put this in the iframe file body section:
onload="window.location.replace ('http://www.YourPage.com');"
If for some reason the onload does not load in the iframe then put your target frame name instead of window in the syntax like this:
onload="YourTarget.location.replace ('http://www.YourPage.com');"
NOTE: For this script all onclick, onmouseover, onmouseout , onload and href="javascript:" will work.
#JDandChips has a great answer above, but the syntax should be updated from parent() to parentElement:
var container = iframe.parentElement;
iframe.remove();
iframe.attr('src', 'about:blank');
container.append(iframe);

Categories