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');
})
Related
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
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();
}
});
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);
};
});
I am using javascript to open the species_county file in a new window/tab and then jquery to change the contents of an h1 tag with id speciesTitle.
open_event_test.html
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
</head>
<body>
<p>Click the button to open a new window called "MsgWindow" with some text. </p>
<button onclick="myFunction('Yada')">Yada</button>
<script>
function myFunction(species)
{
console.log(species);
var myWindow = window.open("species_county.html", species);
myWindow.document.getElementById("speciesTitle").html(species);
}
</script>
</body>
</html>
species_county.html
<!doctype html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
</head>
<body>
<h1 id="speciesTitle">Species in County</h1>
</body>
</html>
I get error saying the element I'm grabbing has value null. I need to replace only some content. Document.write does not work because it will not open the species_county file, it will create an entirely new page.
There are a few possible issues with your script.
1) Elements Do Not Have html Method
As mentioned by beercohol, there is no such method as html() on an HTML Element. html() is a jQuery method, which is a property of a jQuery Object. In order to use this, you need to either use jQuery to select the element, or use JavaScript's native innerHTML property.
myWindow.document.getElementById("speciesTitle").innerHTML = species;
// or
$(myWindow.document).find('#speciesTitle').html(species);
2) The Window/Frame's DOM Has Not Loaded
There's a high chance that, by the time you've run the code to change the speciesTitle element, the window that you've opened has not yet finished loading its DOM. This would result in an error along the lines of:
TypeError: myWindow.document.getElementById(...) is null
You'll need to somehow make sure that you don't run the HTML-altering code until the DOM of the new window has finished loading. Traditionally, this is a job for jQuery, but here's a quick (non-cross-browser-friendly) pure JavaScript example within your myFunction method:
function myFunction (species) {
var myWindow = window.open("species_county.html", species);
myWindow.onload = function() {
// DOM has loaded
this.document.getElementById("speciesTitle").innerHTML = species;
}
}
3) Same Origin Policy
For security reasons, most browsers won't let you make adjustments to a window of another frame unless both frames come from the same origin. If you're working locally, the chances are you're not using a domain name or an IP address which match. Chrome doesn't let you make these communications over the filesystem (not by default anyway), but I have had some success with Firefox waiving Same Origin Policy between files locally on the file system. Either way, this won't work on a legitimate browser if you are attempting to communicate with a frame from a completely different domain.
For more information, see the window.open() FAQ on the MDN website. Note the part about cross-domain:
A script loaded in a window (or frame) from a distinct origin (domain
name) cannot get nor set properties of another window (or frame) or
the properties of any of its HTML objects coming from another distinct
origin (domain name).
4) Popup Blockers
It's also likely that you may run into trouble with various browser implementations of popup blockers. These will outright refuse to open the new frame, resulting in a null window object. You will first need to 'allow' your page to open a window through some configuration in the browser (usually a popup-blocker icon makes itself apparent).
The obvious problem is that html() is not a method of the Element object returned by getElementById()
https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById
https://developer.mozilla.org/en-US/docs/Web/API/Element
The property you're looking for is innerHTML instead.
https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML
Try this for your script:
<script>
function myFunction(species) {
console.log(species);
var myWindow = window.open("species_county.html", species);
myWindow.document.getElementById("speciesTitle").innerHTML = species;
}
</script>
html() is a jQuery function, so I suspect that's where you're getting confused. You don't really need jQuery just for this however, although you are including it.
You are trying to modify an element on a different page, and that's not possible with JavaScript in the way you're handling it.
One way to achieve your goal is to pass a $_GET parameter and use JavaScript on the newly loaded page to change the element.
Change this:
var myWindow = window.open("species_county.html", species);
myWindow.document.getElementById("speciesTitle").html(species);
To this:
var url = "species_county.html?species=" + encodeURIComponent(species);
window.open(url);
And then in species_county.html, look for the species parameter and change the title.
var mySpecies = location.search.split('species=')[1];
if(mySpecies !== undefined) {
document.getElementById("speciesTitle").innerHTML=mySpecies;
}
Unfortunately, shennan's 3rd idea was right, so I had to end up solving it like this:
open_event_test
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
</head>
<body>
<p>Click the button to open a new window called "MsgWindow" with some text.</p>
<button onclick="myFunction('Bombus balteatus')"><em>Bombus balteatus</em> Dahlbom</button>
<button onClick="myFunction('Bombus auricomus')"><em>Bombus auricomus</em> (Robertson)</button>
<script>
function myFunction(species)
{
var newhtml = '<!DOCTYPE html><head><meta charset="utf-8"><html><title>'+species+'</title></head><body><h1><em>'+species+'</em> in County</h1></body></html>';
var newWindow = window.open(species, '_blank');
newWindow.document.write(newhtml);
}
</script>
</body>
</html>
I'm using the Telerik RadSpell control in one of our touchscreen applications. I've managed to style it just right however the darn thing uses window.alert and window.confirm for prompting the user if they want to keep changes etc.
I want to disable these alerts without having to pull apart and modify the telerik controls.
The issue is that the spellcheck dialog uses an iframe and I can't seem to override the window.confirm function inside the iframe.
Sample Code to test overriding confirm.
<!-- mainpage.htm -->
<html>
<head>
<script type="text/javascript">
window.confirm = function(msg){ alert(msg); }
confirm("Main Page Confirm");
</script>
</head>
<body>
<iframe src="./iframepage.htm" >
</iframe>
</body>
</html>
<!-- iframepage.htm -->
<html>
<head>
<script type="text/javascript">
confirm("iframe confirm");
</script>
</head>
<body>
Some content.
</body>
</html>
Results in
Is it possible to override the javascript in an iframe from the parent? If so how?
I just shared an easier solution in the first forum, which demonstrates how to override the cancelHandler and hide the confirm dialog.
For your convenience I am pasting the solution below:
I would propose an easier way to disable the popup and it is to override the cancelHandler function. To do that follow the steps below:
1) Create a JS file named dialog.js in the root of the web application and populate it with the following function:
Telerik.Web.UI.Spell.SpellDialog.prototype.cancelHandler = function (e) {
if (this._cancel.disabled) {
return $telerik.cancelRawEvent(e);
}
//changes will be applied only if spell handler response is received, text has changed
//and the user confirms
this.closeDialog(this._spellProcessor && this._spellProcessor.textChanged() && true);
return $telerik.cancelRawEvent(e);
}
2) Save the file and set the DialogsScriptFile property of RadSpell to point to this file, e.g.
3) Test the solution.
I hope this helps.
You can get a reference to the innerwindow using javascript IFF the frame is from the same exact domain as the parent.
//Get iframe element by getElementById, frames[0], or whatever way you want
var myFrame = document.getElementById("myFrame");
//Get the window of that frame, overwrite the confirm
myFrame.contentWindow.confirm = function(msg){ alert("I overwrote it! : " + msg); }
You should be able to:
document.getElementById('iframe').contentWindow.confirm = [this is confirm in the iframe];
Perhaps something like this might work nicely for you:
document.getElementById('iframe').contentWindow.confirm = window.confirm;
This would link the confirm of the iframe to the confirm of the parent, which is nice if you already have some handling for confirms in the parent.
Note that you also will want to add some handling for possible undefined objects.
var iframe = document.getElementById('iframe');
//iframe exists
if(iframe){
var iframe_window = document.getElementById('iframe').contentWindow;
//window exists (won't if frame hasn't loaded)
if(iframe_window){
iframe_window.confirm = window.confirm;
}
}
You can take a look at the following resources, which could be helpful for your scenario:
http://www.telerik.com/community/forums/aspnet-ajax/spell/how-do-i-turn-off-the-confirm-dialog.aspx
and
http://www.telerik.com/help/aspnet-ajax/spell-client-check-finished.html
They show how to remove the RadSpell confirm and alert popups.
Best regards,
Rumen