How to pick element inside iframe using document.getElementById - javascript

I have a iframe like this
<iframe name="myframe1" id="myframe1" width="100%" height="100%" src="a.html">
<html>
<head></head>
<frameset name="myframe2" cols="0%, 100%" border="0" frameBorder="0" frameSpacing="0">
<frame name="page1" src="c.html" scrolling="no"></frame>
<frame name="page2" src="d.html" >
<html>
<head></head>
<body id="top">
<div id="div1">
<div id="div2">
<div id="div3">
<ul id="x">
<li>a</li>
<li>b</li>
</ul>
</div>
</div>
</div>
</body>
</html>
</frame>
</frameset>
</html>
</iframe>
I want to refer to the element "x". I tried in several ways but I couldn't find a solution.

document.getElementById('myframe1').contentWindow.document.getElementById('x')
Fiddle
contentWindow is supported by all browsers including the older versions of IE.
Note that if the iframe's src is from another domain, you won't be able to access its content due to the Same Origin Policy.

use contentDocument to achieve this
var iframe = document.getElementById('iframeId');
var innerDoc = (iframe.contentDocument)
? iframe.contentDocument
: iframe.contentWindow.document;
var ulObj = innerDoc.getElementById("ID_TO_SEARCH");

(this is to add to the chosen answer)
Make sure the iframe is loaded before you
contentWindow.document
Otherwise, your getElementById will be null.
PS: Can't comment, still low reputation to comment, but this is a follow-up on the chosen answer as I've spent some good debugging time trying to figure out I should force the iframe load before selecting the inner-iframe element.

You need to make sure the frame is fully loaded
the best way to do it is to use onload:
<iframe id="nesgt" src="" onload="custom()"></iframe>
function custom(){
document.getElementById("nesgt").contentWindow.document;
}
this function will run automatically when the iframe is fully loaded.

In my case I was trying to grab pdfTron toolbar, but unfortunately its ID changes every-time you refresh the page.
So, I ended up grabbing it with this one-liner:
const pdfToolbar = document.getElementsByTagName('iframe')[0].contentWindow.document.getElementById('HeaderItems');
As in the array written by tagName you will always have the fixed index for iFrames in your application.

Apologies I don't have enough reputations to add a comment but maybe writing an answer is ok in this case. I've been looking to change the css of some html in an Iframe. I have a bookmarklet code which works outside an iframe so I'm nearly there:
javascript:(function(){ var style = document.createElement('style'), styleContent = document.createTextNode('.notifications-list--cMVsqVbKkaXV4SQ {zoom: 0.8!important;}'); style.appendChild(styleContent); var caput = document.getElementsByTagName('head'); caput[0].appendChild(style); })();
my iframe is called xm-feed-iframe
so I guessed you'd change the code to
document.getElementById('xm-feed-iframe').contentWindow.document.getElementById('x')
But I needed to work with a class in order to change the css styles. So I guess it might be as simple as changing
var caput = document.getElementsByTagName('head')
to
var caput = document.getElementById('xm-feed-iframe').contentWindow.document.getElementsByTagName('head')
so the final code would be
javascript:(function(){ var style = document.createElement('style'), styleContent = document.createTextNode('.notifications-list--cMVsqVbKkaXV4SQ {zoom: 0.8!important;}'); style.appendChild(styleContent); var caput = document.getElementById('xm-feed-iframe').contentWindow.document.getElementsByTagName('head'); caput[0].appendChild(style); })();
And hey presto it worked. I can now delve a little deeper and add some counters hopefully to the list which appears in the iframe! :)
Any comments about the code would be most appreciated as I'm self taught!
Hope this helps someone else
Thanks
UPDATE:
Here we are - I know have a numbered list using a bookmarklet. My life will be so much easier now as I will no longer loss track of all the items I need to download. :D

Related

How to prevent HTML code from running?

I seek to embed multiple iframes on a single page without slowing the page. When I embedded a single iframe, it was running smoothly; added a second and third, and all were slower - despite only one being displayed at a time (using JScript). I presume this is due to the iframe code still executing.
How can I execute code conditionally? In my case, whenever a button is clicked.
Help is appreciated. Fiddle for the exact code I use, with actual content replaced by IDs and iframes by p's: http://jsfiddle.net/aof89Ljt/55/
HTML for the iframes:
<p id="ifr1">
ifr1
</p>
<p id="ifr2" style="display:none;">
ifr2
</p>
<p id="ifr3" style="display:none;">
ifr3
</p>
UPDATE: New JFiddle link with JScript included. End-goal description: I click a button which displays a different embedded Desmos graph, then another graph, then the first graph - in a loop, one at a time (see code). Demonstration gif: https://puu.sh/Bjpil/da9a038e11.gif
UPDATE 2: Solution found; full code: https://jsfiddle.net/32uxrhmw/49/
UPDATE 3: Greatly optimized code: https://jsfiddle.net/32uxrhmw/92/
You need to add the onclick="<your function>" event trigger to the element(s) you want to "do something".
Simple example:
<button onclick="swap()">Button</button>
<iframe style="display: none;" data-url="https://www.example.com" id="iframe">
<p>Your browser does not support iframes.</p>
</iframe>
<script>
function swap() {
e = document.getElementById('iframe'); // get iframe
url = e.dataset.url; // get desired url attribute stored in data-url
e.setAttribute("src", url); // add the iframe src with desire url
e.removeAttribute("style"); // remove styling that hid it otherwise
}
</script>
UPDATED to better apply to question.
UPDATED again to also incorporate #Joe Fitzsimmons good suggestion re handling iframe sources (in his answer).
FINAL ADDITION SEEING YOUR CODE:
Looking at your last code, it seems what you want to do is:
load page with one iframe;
then change iframe displayed when the button is clicked.
If that is what you want, you might want to use this much simpler code:
(Note: I used your code sample as a base, but haven't inserted any src urls - yours may be private, but even if not they all showed the same result so it may confuse other readers)
<style>
.tdropbtn {
background-color: white;
font-size: 16px;
border: none;
cursor: pointer;
color: #0066CC;
}
</style>
<center>
<iframe id="frame" src="https://url1" width="500px" height="400px" frameborder=0></iframe>
</center>
<div style="display:inline;">
<center>
<button onclick="swap()" class="tdropbtn">[+]</button>
</center>
</div>
<script>
var counter = 1;
var firstFrame = "https://url1";
var secondFrame = "https://url2";
var thirdFrame = "https://url3";
var e = document.getElementById("frame");
function swap() {
if (counter == 0){
e.src = firstFrame;
counter++;
}
else if (counter == 1){
e.src = secondFrame;
counter++;
}
else if (counter == 2){
e.src = thirdFrame;
counter = 0;
}
}
</script>
One idea would be to load/remove the source of the iframe onClick.
This is a rough idea of what you could do:
function Swap(id, url) {
document.getElementById(id).src = url;
}
You'd have to show and hide the iFrames as well. Hopefully this could get you on your way. I'm not exactly sure what your end goal is.

Append iframe to div without refreshing

I have a html structure like:
<div id="bar">
<iframe id="foo"></iframe>
<iframe id="foo2"></iframe>
</div>
Each iframe has javaScript running inside it.
Now: I need to add another element... <iframe id="foo3"></iframe> to the end of the div without foo & foo2 from refreshing. I thought jQueries.append() was the way to do this, but this still refreshes the original iframes (Which resets the javaScript inside the already existing iframes).
Any tips/ideas? Thanks
Below will be the code
document.getElementById("bar").innerHTML += '<iframe id="foo3"></iframe>';
Not sure if it will refresh the other iframes

Changing a divs content from within an iFrame

I have the following page layout
<div id="userscore" >test</div>
<iframe name="frameContent" id="frameContent" width="100%" height="100%" frameborder="0" />
The iFrame gets its content dynamically including its javascript.
When I try to access userscore from within the iFrame
console.log(window.parent.document.getElementById('user-score'));
I get in the console
<div id="userscore" >test</div>
When I try to use
window.parent.document.getElementById('user-score').html('Change the content');
I get
Object [object HTMLDivElement] has no method 'html'
Is there a way around this? Or can anybody shed some light as to what is going on.
A DOM-element doesn't have a method .html(). That method is an extension often seen in JavaScript-libraries like jQuery.
When using plain JavaScript you have to set the .innerHTML property if you want to alter the content of the element.
window.parent.document.getElementById('user-score').innerHTML = "New content";

show only one div within an iframe (javascript, JQuery...)

First just let me say I'm open to ideas on a different approach altogether.
I have and iframe as such:
<div id="testloadlogin">
<iframe src="../security/login.aspx" width="400" height="500"
scrolling="auto" frameborder="1">
[Your user agent does not support frames or is currently configured
not to display frames. However, you may visit
the related document.]
</iframe>
</div>
The page being loaded with the iframe has a div called loginInnerBox. I only want to display the loginInnerBox and everything inside of it.
Any ideas on how to do this? I was thinking of using Jquery or javascript of some kind to remove everything else on the page loaded by the iframe, not sure how to access that though...
Just to be clear I want everything on my page outside of the iframe to remain intact. I want the equivalent of saying $.('testloadlogin').load('../security/login.aspx' #loginInnerBox) which would just get loginInnerBox's html and place it in the testloadlogin div. However I need the back-end processing from the other page which is supported by iframe, but not by the Jquery load.
The markup of the page loaded by the iframe is
<body>
<div>
</div>.......
<div class="AspNet-Login" id="ctl00_CLPMainContent_Login1">
<div id="loginInnerBox">
<div id="loginCreds">
<table>
</table>
</div>
</div>
</div>
<div>
</div>....
</body>
Do you need more information than that?
I tried this, it had no effect:
<div class="ui-corner-all" id="RefRes">
<div id="testloadlogin">
<iframe onload="javascript:loadlogin()" id="loginiframe" src="../security/login.aspx"
scrolling="auto" frameborder="1">
[Your user agent does not support frames or is currently configured
not to display frames. However, you may visit
the related document.]
</iframe>
</div>
</div>
<script type="text/javascript">
function loadlogin() {
$('<body>*', this.contentWindow.document).not('#ctl00_CLPMainContent_Login1').hide();
}
</script>
With jQuery, you can load not just the contents of a URL, but a specific CSS selector from within that URL. This would be a much cleaner approach. It's like this.
$("#area").load("something.html #content");
Via CSS Tricks
$("iframe").contents().find("*:not(#loginInnerBox)").remove();
Be aware this would only work on iframes loaded from the same domain (same origin policy)
EDIT: Probably this removes children of loginInnerBox as well. In that case you could try to clone it before:
var iframe = $("iframe").contents(),
loginBox = iframe.find("#loginInnerBox").clone();
iframe.find("*").remove();
iframe.append(loginBox);
Something like that..
Add this to the <iframe>-elememt:
onload="$('body>*',this.contentWindow.document).not('#ctl00_CLPMainContent_Login1').hide();"
it will hide every child of the body except #ctl00_CLPMainContent_Login1
If #ctl00_CLPMainContent_Login1 contains more than the loginbox, you have to use the suggestion using clone() posted by pex.

How to access frame (not iframe) contents from jQuery

I have 2 frames in one page like this (home.html)
<frameset rows="50%, 50%">
<frame id="treeContent" src="treeContent.html" />
<frame id="treeStatus" src="treeStatus.html" />
</frameset>
and then in one frame (treeStatus.html) I have something like
<body style="margin: 0px">
<div id="statusText">Status bar for Tree</div>
</body>
I want from the top window to manipulate the div located in the child frame via jquery (e.g show and hide).
I have seen several questions like this and they suggest the following
$(document).ready(function(){
$('#treeStatus').contents().find("#statusText").hide();
});
I do not know if this works with iframes but in my case where I have simple frames it does not seem to work. The code is placed inside home.html
Here is some output from firebug console
>>> $('#treeStatus')
[frame#treeStatus]
>>> $('#treeStatus').contents()
[]
>>> $('#treeStatus').children()
[]
So how do I access frame elements from the top frame? Am I missing something here?
Answer
After combining both answers here, the correct way is
$('#statusText',top.frames["treeStatus"].document).hide();
For this to work the frame must have the name attribute apart from the id, like this:
<frameset rows="50%, 50%">
<frame id="treeContent" src="treeContent.html" />
<frame name="treeStatus" id="treeStatus" src="treeStatus.html" />
</frameset>
You could grab the Frame and div you are wanting to manipulate and pass it into a variable.
var statusText = top.frames["treeStatus"].document.getElementById('statusText');
Then you can do anything you want to it through jQuery.
$(statusText).whatever();
Though sometimes you just can't get around having to use frames, keep in mind that the <frame> tag is obsoleted in HTML5. If you ever plan on moving up to HTML5, you'll have to use iFrames.
I have nested frames. In my case, to make it work i used command:
var statusText =
top.document.getElementById("treeStatus").contentDocument.getElementById("statusText");
Then, as Charles already answered, you can do anything you want to it through jQuery:
$(statusText).whatever();
https://jamesmccaffrey.wordpress.com/2009/07/30/cross-frame-access-with-jquery/
$(document).ready(function(){
$("#Button1").click(function(){
$(parent.rightFrame.document).contents().find(‘#TextBox1’).val(‘Hello from left frame!’);
});
});
But I used :
$.post("content_right.php",{id:id},function(data)
$(parent.frames["content_right"].document.body).html(data) ;
});
For a pure jquery solution (that doesn't require top.frames etc), the following seems to work:
$('some selector for item from frame' ,$('frame selector')[0].contentDocument)
This has the advantage that it works for nested frames:
$('inner frame item selector', $('inner frame selector', $('outer frame selector')[0].contentDocument)[0].contentDocument)
I used the following successfully:
$( '#foo', top.frames['bar'].document )
(also works with nested frames that are automagically appended in top.frames)

Categories

Resources