How to get iframe src page title and then set main page title
If you want to do it using jQuery:
var title = $("#frame_id").contents().find("title").html();
$(document).find("title").html(title);
You can do it only when pages are on the same domain, otherwise it's useless.
Granting that iframes src and the parent document src are the same domain:
Parent document:
<html>
<head><title>Parent</title>
<body>
<iframe id="f" src="someurl.html"></iframe>
<script>
//if the parent should set the title, here it is
document.title = document.getElementById('f').contentWindow.document.title;
</script>
</body>
</html>
someurl.html:
<html>
<head><title>Child</title>
<body>
<script>
//if the child wants to set the parent title, here it is
parent.document.title = document.title;
//or top.document.title = document.title;
</script>
</body>
</html>
Unless the webpage is in the iframe is from the same domain as the containing page, it is impossible.
If they do have the same domain, then try the following:
document.title = document.getElementById("iframe").documentElement.title;
One way you can share title and location:
document.write('<iframe src="http://www.yourwebsite.com/home.html?title='+document.title+'&url='+window.location+'" frameborder="0" scrolling="no"></iframe>');
and then you can read the parameters on home.html page.
This can be done using event listeners on the page. It's not particularly elegant, but the browsers I have tried it with support it (so IE9+, Firefox, Chrome).
In your main site page add the following javascript:
function setPageTitle(event) {
var newPageTitle = event.data
// your code for setting the page title and anything else you're doing
}
addEventListener('message', setPageTitle, false);
In the iFrame, you'll then need to have the following script:
var targetOrigin = "http://your.domain.com"; // needed to let the browser think the message came from your actual domain
parent.postMessage("New page title", targetOrigin); // this will trigger the message listener in the parent window
Related
I have a main (parent) page that hosts 3 iframes that are under the same domain. The iframe's src attribute is added on a click event, so the iframe's aren't loaded until needed.
What I want is when I click a certain div on my main page, it will trigger a click on a specific div that's located inside all 3 iframes at the same time.
I have tried the following code in my parent page:
function myFunction() {
var iframe = document.getElementById("iframe1");
var elmnt = iframe.contentWindow.document.getElementById("btn").click()
}
and repeated it twice more for iframe's #iframe2 and #iframe3. However, it didn't work unless I loaded the iframes in order that they're written on my page. (i.e the click event on #iframe2 didn't execute until after #iframe1's event). This is a problem as I'm unable to control what iframe visitors will load first. I tried giving them separate function() names, but the same thing occurred - only one iframe was effected at a time. Note, this worked fine when I tested it out with the iframe's already having their src's like normal, just not when they're added manually.
I also tried adding this in the iframe pages:
parent.document.getElementById('btn').onclick = function(){
document.getElementById('btn').click();
}
However, this only works on the first iframe that is loaded (i.e if #iframe2 is loaded first, then the iframe1's and iframe3's event wont execute)
Is there any other solutions I could try? My purpose is creating a day and night toggle with classList.toggle, and I want all the iframes css to be toggled at the same time, with the toggle button
being on the main page.
(I prefer vanilla javascript for my main page, but am fine with jQuery on the iframe pages)
You are dynamically loading iframe's src suppose user loads <iframe3> but your code is written such a way that it tries to do something with <div> inside <iframe1> (which isn't loaded yet) what will happen? It will throw error and break the execution that's why it's not working for you what you need is to first look whether they are currently there
Also you are using var iframe = document.getElementById("iframe1"); but I don't see any id on the fiddle you posted
Try this
<body>
<style>
body {
background:#fff;
color:#000
}
body.toggled
{
background:#000;
color:#fff
}
</style>
<div id="btn">click here to toggle css</div>
<p>page content</p>
add src to iframe one<br>
add src to iframe two<br>
add src to iframe three
<p>iframe 1:</p>
<iframe src="about:blank" id="iframe1" name="iframe1"></iframe>
<p>iframe 2:</p>
<iframe src="about:blank" id="iframe2" name="iframe2"></iframe>
<p>iframe 3:</p>
<iframe src="about:blank" id="iframe3" name="iframe3"></iframe>
</body>
<script>
document.querySelector('#btn').addEventListener('click', function(e) {
[].map.call(document.querySelectorAll('body,a'), function(el) {
el.classList.toggle('toggled');
});
var iframe1 = document.getElementById("iframe1");
var iframe1btn = iframe1.contentWindow.document.getElementById("btn");
if(iframe1btn) //<-- check if that element really exists within <iframe>
iframe1.contentWindow.document.getElementById("btn").click()
// you could've also used <iframe>'s loaded event but this is better way
var iframe2 = document.getElementById("iframe2");
var iframe2btn = iframe2.contentWindow.document.getElementById("btn");
if(iframe2btn)
iframe2.contentWindow.document.getElementById("btn").click()
var iframe3 = document.getElementById("iframe3");
var iframe3btn = iframe3.contentWindow.document.getElementById("btn");
if(iframe3btn)
iframe3.contentWindow.document.getElementById("btn").click()
});
</script>
I am not particularly sure what you got wrong on, but I think I understand what you want to do. To reproduce this example, please create a HTML file (with name index.html) in your local PC and run this file on your browser:
<!DOCTYPE html>
<html>
<head>
<style>
body {
background: #fff;
color: #000;
}
body.toggled {
background: #000;
color: #fff;
}
</style>
</head>
<body>
<div id="btn">click here to toggle css</div>
<p>page content</p>
add src to iframe one<br>
add src to iframe two<br>
add src to iframe three
<p>iframe 1:</p>
<iframe src="about:blank" name="iframe1"></iframe>
<p>iframe 2:</p>
<iframe src="about:blank" name="iframe2"></iframe>
<p>iframe 3:</p>
<iframe src="about:blank" name="iframe3"></iframe>
<script>
let outerBody = document.querySelector('body')
let toggleButton = document.querySelector('#btn')
let iframes = document.querySelectorAll('iframe')
let anchors = document.querySelectorAll('a')
toggleButton.addEventListener('click', () => {
let body = document.querySelector('body')
body.classList.toggle('toggled')
Array.from(iframes).forEach(iframe => {
toggleIframe(iframe)
})
})
Array.from(iframes).forEach(iframe => {
iframe.addEventListener('load', e => {
toggleIframe(iframe)
})
})
Array.from(anchors).forEach(anchor => {
anchor.addEventListener('click', e => {
let targetedIframe = document.querySelector(`iframe[name=${anchor.target}]`)
targetedIframe.src = './index.html'
})
})
function toggleIframe(iframe) {
let iframeBody = iframe.contentWindow.document.querySelector('body')
let iframeToggleButton = iframe.contentWindow.document.querySelector('#btn')
let isOuterBodyToggled = outerBody.classList.contains('toggled')
let isIframeBodyToggled = iframeBody.classList.contains('toggled')
if (isOuterBodyToggled && iframeToggleButton && !isIframeBodyToggled)
iframeToggleButton.click()
else if (!isOuterBodyToggled && iframeToggleButton && isIframeBodyToggled)
iframeToggleButton.click()
}
</script>
</body>
</html>
I changed your a's href to empty (#). I also changed your JS file. Basically, I specified the as to change the source of its associated iframe when it's clicked with addEventListener('click'). Also, each time I click on the outerBody's (parent browsing context) button, I will also toggle its containing iframes' body by performing a click on the iframes' buttons. That already works. However, your problem was that you don't know when the iframes will be loaded. There's a function for that, addEventListener('load') on your iframes. When an iframe is loaded (an iframe will be loaded again when its source is changed), I will use that event listener to check if its parent browsing context's body is toggled. If it is, then simply toggle the iframe's body too by performing click.
Voila, it works. As mentioned, please try pasting the code above to your local file in your PC and run it in a browser.
<html>
<body>
<!-- <iframe id="iff" srcdoc="<div>ok</div>"></iframe> -->
<iframe id="iff" src="data:text/html;charset=utf-8,%3Cdiv%3Eok%3C%2Fdiv%3E"></iframe>
<script>
console.log(document.getElementById('iff').contentWindow.document)
</script>
</body>
</html>
I set srcdoc (tried src also) of <iframe>, but cannot access the real document of the iframe (tried iframeElement.contentDocument also). Chrome outputs (also tried Firefox):
I see in Get IFrame's document, from JavaScript in main document that I cannot get the document of a cross-domain iframe, and also learned from Which is the difference between srcdoc="..." and src="data:text/html,..." in an <iframe>? that src and srcdoc behaves different about cross-domain behavior. But I tried both, none works.
2. When I append a child to the document body of an iframe (with src attribute set), the DOM updates but it doesnt show on screen.
Try something like:
window.frames['iff'].document.myvar;
This can be useful if you look for the iframe with the url:
var x=getIframeID("cool.php");
x.contentWindow.callafunction();
function getIframeID(iframeurl) {
var iFs = top.document.getElementsByTagName('iframe');
var x, i = iFs.length;
while ( i-- ){
x = iFs[i];
if(iframeurl.indexOf(x.src)>=0) return (x.id);
if (x.src == iframeurl) return (x.id);
}
return("");
}
I have a page on www.domain.com and another page on sub.domain.com. sub.domain.com will be shown on www.domain.com in an iframe. I'm trying to dynamically calculate the height of this iframe based on the content of the iframe.
<iframe onload="calcHeight();" id="iframe" src="sub.domain.com"></iframe>
<script type="text/javascript">
function calcHeight()
{
//find the height of the internal page
document.domain = 'domain.com';
var the_height=parent.document.getElementById('iframe').contentWindow.document.body.scrollHeight +25;
//change the height of the iframe
parent.document.getElementById('iframe').height=the_height;
}
</script>
The src page DOES contain document.domain= 'domain.com';
It's working on all major browser besides IE9, which gives me an access denied on the javascript above. All solutions I read is dynamically adding the document.domain line to the iframe source, but as said, this is already in my static iframe source.
Whats wrong?
-edit-
Based on the suggestion I now have this on www.domain.com
<script type="text/javascript">
document.domain="domain.com";
</script>
<iframe style="border:0px;width:100%;" onload="calcHeight();" id="iframe" src="sub.domain.com"></iframe>
<script>
// IE hack
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE");
if (msie > -1) {
var source = "javascript:'<script>window.onload=function(){document.write(\\'<script>document.domain=\\\"" + document.domain + "\\\";<\\\\/script>\\');document.close();return \\\"+url+\\\";};<\/script>'";
$('#iframe').attr("src", source);
}
// End IE hack
function calcHeight()
{
//find the height of the internal page
var the_height=parent.document.getElementById('iframe').contentWindow.document.body.scrollHeight +25;
//change the height of the iframe
parent.document.getElementById('iframe').height=the_height;
}
</script>
-edit 2-
Based on the last remarks I now have this
<script type="text/javascript">
document.domain="domain.com";
url="sub.domain.com";
function calcHeight()
{
//find the height of the internal page
var the_height=parent.document.getElementById('iframe').contentWindow.document.body.scrollHeight +25;
//change the height of the iframe
parent.document.getElementById('iframe').height=the_height;
}
</script>
<iframe style="border:0px;width:100%;" onload="calcHeight();" id="iframe" src="javascript:'<script>window.onload=function(){document.write(\'<script>document.domain=\'domain.com\';<\\/script>\');document.close();return \'+url+\';};</script>'"></iframe>
Now I don't see the source page anymore.
Sorry, but because i had the same problem and i solved in this way can i ask you to try it exactly in this way:
var url = $('#iframe').attr("src");
if (isMSIE() == true) {
url = "javascript:'<script>window.onload=function(){document.write(\\'<script>document.domain=\\\"" + document.domain + "\\\";<\\\\/script>\\');document.close();return \\\"+url+\\\";};<\/script>'";
}
$('#iframe').attr("src", url);
The problem seems related to IE and what i did was to substitute the url whith a dynamic javascript that change the domain and return the url of iframe
Mainly, what happened to my customer was that the iframe appeared too little that is the motivatoin I used this approach:
Moreover the iframe from IE source:
<iframe width="300" class="vytmn-frame" id="iframe" src="javascript:'<script>window.onload=function(){document.write(\'<script>document.domain=\"localhost\";<\\/script>\');document.close();return \"+url+\";};</script>'" frameborder="0" scrolling="yes" horizontalscrolling="no" verticalscrolling="yes"></iframe>
In other words my problem was i to permit a full sized iframe because the iframe itself was shown by the browser too little and so invisible.
Sorry and I hope this time i gave you whaat i did.
It is unusefull to calculate the height: you have no access to the document inside the iframe. Sorry again.
I have a element as below inside the document, I could get the iframe element by document.getElementById('iframe_id'), but how to get the element inside this iframe? I tried iframeElement.contentWindow, and the returned DOMWindow has no properties. Also tried iframeElement.docuemnt and iframeElement.contentDocument, both of them are undefined. How can I get it? I am using the latest Chrome in my experiment.
Here is the iframe element
<iframe id='iframe_id'>
<html>
<body>many content here</body>
</html>
</iframe>
You can ONLY interrogate content in an iframe if the content has the same protocol, domain and port number as the script that interrogates it. It is called SAME ORIGIN
If that is the case, then this code will show the content. If not - you cannot access the iframe from a normal script in a normal html page
Demo - tested in IE8, Chrome 13 and Fx6
function showIframeContent(id) {
var iframe = document.getElementById(id);
try {
var doc = (iframe.contentDocument)? iframe.contentDocument: iframe.contentWindow.document;
alert(doc.body.innerHTML);
}
catch(e) {
alert(e.message);
}
return false;
}
<iframe id='iframe_id1' src="javascript:parent.somehtml()"> </iframe>
<br/>
Show
<hr/>
<iframe id='iframe_id2' src="http://plungjan.name/"> </iframe>
<br/>
Show
<hr/>
Having:
var iframe = document.getElementById('iframe_id');
To get the content document you can use:
var contDoc = iframe.contentDocument || iframe.contentWindow.document;
Then you can search for your element inside the iframe by id.
You should be able to access it by document.getElementById('yourIFrame').document.getElementById('yourElement')
I'm currently developing a Toolbar from Google Chrome. Basically it's a toolbar that i'm injecting in every web pages by using a Content-Script. Technically the toolbar is materializd by a iframe that include all the components like button, dropMenu,... Here is the script you make this :
// Take down the webPage
document.getElementsByTagName('body')[0].style.marginTop = '39px';
var body = $('body'),
toolbarURL = chrome.extension.getURL("yourtoolbar.html"),
iframe = $('<iframe id="YourToolbarFrame" scrolling="no" src="'+toolbarURL+'">');
// Insertion
body.append(iframe);
// Effect
$("#YourToolbarFrame").hide().fadeIn(800);
But right now i'm trying to add some component on this iframe for example a button but it didn't work...
var yt = $("#YourToolbarFrame");
var newButton = $('<input type="image" src="images/pop.ico" name="InstantMessage" width="23" height="23">');
yt.append(newButton);
The body of the iframe look like this :
<body>
<div class="default">
// COMPONENTS
</div>
</body>
Hope someone can provide me some help ! :)
You have to wait until the iframe loaded. E.g.:
iframe.load(function() {
var newButton = ...;
$(this).contents().find('body').append(newButton);
}).appendTo('body');
Not sure how Chrome handles the same-origin policy for content scripts though.
Since you're using jQuery, you could try using
$('#YourToolbarFrame').contents().find('body').append(newButton);
Or if you don't want to append to the body directly, use any other element in the find() statement.