select the immediate parent element of an iframe from the iframe - javascript

I have the markup below:
<html>
<body>
<div class="aaa"></div>
<div class="aaa"></div>
<div class="aaa">
<iframe>
<form id="myform">
</form>
</iframe>
</div>
<div class="aaa"></div>
</body>
</html>
On loading the iframe, it contains the form '#myform'.
Upon submission of the form, I need to run a certain callback based on the div.aaa that is the immediate parent of the iframe.
Any solution based on parent.document cannot help me much, since I do not know the ID of the div.aaa.
What I'd like to do is something like $('#myform').closest('div.aaa'), but, of course, this fails because any element beyond the iframe window itself cannot be accessed in this fashion.
How can I best access this iframe's immediate parent div, which is actually an element in it's parent document?
Both parent and iframe are of same origin.

You can jump up to the parent window and look for specific iframe in parent document by matching frame element contentWindow to known window inside the iframe
Something like:
$(window.parent.document).find('iframe').filter(function() {
return this.contentWindow === window;
}).parent().doSomething()
DEMO

I would recommend to use .closest('.aaa'). But if you could assign a unique identifier you may use .parent('.uniq_selector') that is a bit more performant.

Related

Using getElementByID or QuerySelector from inside iFrame does not work

I have a really weird behaviour right now in production which is that, on a Single Sign-On login page (we are the SSO provider), some JS selectors instructions are not working when the page is loaded through an iFrame on another website.
The selectors are executed on the login page template, on my side (the SSO side), they are not executed on the page hosting the iFrame. Still, they return null.
HTML code:
<document>
<body>
<script>
if (window.parent != window) {
window.document.getElementById('content').style.padding = '0';
}
</script>
<div class="container">
<main id="content" class="flex-column">
<div class="sib-login-title">
You need to login to access this page
</div>
</main>
</div>
</body>
</document>
The code here is really basic because I extracted the base elements, what's weird is that, when accessing my login page in the browser and executing the getElementById in the console, it works:
window.document.getElementById("content");
<main id="content" class="flex-column">
Same code from the script tag when the page is loaded through an iframe returns:
?next=/authorize/%3Fclient_id%xxxxxxxxxxxxxxxx%26response_type%3Dcode%26scope%3Dopenid%2520profile%2520email%2520preferred_username%2520roles%26redirect_uri%3Dhttps%3A//xxxxxxxx/auth:42 Uncaught TypeError: Cannot read properties of null (reading 'style')
I want to emphasize that this script tag is really on the document loaded through the iframe, not on the parent document loading the iframe, so I really do not get why.
I checked a lot of questions on SO but they are all asking how to access elements inside the iframe from the parent document, that's not my scenario here.
Any ideas ? Something I forgot about ?
Thanks in advance.
The JavaScript is trying to reference the element before it exists (it exists a couple of lines later, so you're just a bit keen).
You just need to put things in the correct order, like this:
#content {
padding: 100px;
}
<div class="container">
<main id="content" class="flex-column">
<div class="sib-login-title">
You need to login to access this page
</div>
</main>
</div>
<script>
if (window.parent != window) {
document.getElementById('content').style.padding = '0';
}
</script>

Jquery .load() only parent and ignore children

So, I am trying to load picture from another page using Jquery .load(), now the element I am trying to load has multiple children element which also load on current page, now obviously I could hide those divs but first I want to know if there's way to only grab parent div and leave out children.
I have tried using parent() method but since .load() works differently, it didn't work as intended. (Unless I missed something)
$('#myNewDiv').load('/robots .heading-image');
Here's HTML code from the other page
<div class="heading-image" style="background-image:url(imagelinkhere.png)">
<div class="heading-image_cover">
<div class="left">
<div class="heading-image title">Heading Title</div>
<div class="heading-image desc">I am a desc</div>
</div>
<div class="right">
<div class="heading-image stat">Stat text</div>
</div>
</div>
</div>
That's the code I am using right now, but .heading-image has multiple child elements as mentioned above.
To sum up, I need to load only parent element and ignore all child elements of the div mentioned above without having to load those children on current page and hide them (If possible)
From what I understand, your goal seems to be to copy the empty div to a new page, while maintaining the background image associated with the <div> tag.
The simplest approach would be to add to a stylesheet in which both of the pages can reach. For example:
CSS
.heading-image{
background-image:url(imagelinkhere.png);
}
JavaScript
$('#myNewDiv').html("<div class="heading-image"></div>");
Then in the head of both HTML documents, have <link rel="stylesheet" href="style.css"> to point towards the correct stylesheet for both pages.
If you just want the empty <div class="heading-image"></div> you could use the load() complete callback to empty it:
$('#myNewDiv').load('/robots .heading-image', function(){
// new html exists in page now, 'this' is #myNewDiv element
$(this).find('.heading-image').empty();
});
If there are resources inside that element like images, videos etc that you don't want to load in page you could also parse the :
$.get('/robots').then(function(html){
var $hImage = $(html).find('.heading-image').empty();
$('#myNewDiv').html($hImage)
});
With all that said I don't see why you need to extract an empty element from another page and can't just do:
$('#myNewDiv').html('<div class="heading-image"></div>')

How to use javascript to locate and click an element in an iFrame

Using Javascript in a webBrowser Control in a form, How do I switch to a iFrame
<iframe id="ContentFrame" class="contentIFrame" onload="checkComplementaryPage()" onmouseover="hoverMenu('dividers')" name="ContentFrame" src="HomeContainer.aspx" scrolling="auto" frameborder="0"></iframe><div id="footer" class="footer">
and then locate and click on an element inside that iFrame?
<div class="innerItem50L">
<input type="submit" name="btnPunch" value="punch" id="btnPunch" style="CURSOR:hand;" />
</div>
I am new to programming and am starting with c#. I know even less about Javascript...
Using the following thread as an example:
Make an event happen in child iframe to the parent window in JavaScript?
You could do the following:
$('#ContentFrame').contents().find('#btnPunch').click();
Note: The iframe's source has to be from the same domain, and contents must be loaded so you should put it after window load.

Hiding a div that contains an iframe

I have a div that contains the iframe, this iframe loads a URL which shows a page.
Within the iframe, i have a close button which when clicked, hides the div. But I am unable to access the div from within the iframe.
My code as below
<div class="app" id="modalOverlay" style="background-color:rgba(0,0,0,0.5);position:absolute;z-index:1;width:100%;height:100%;top: 0;left: 0;">
<div id="modalContainer" style="position:absolute;z-index:2;margin: -250px 0 0 -250px;top: 50%;left: 50%;background-color: #222;width: 500px;height: 500px;">
<a class="close" style="position:relative;top:-10px;z-index:3">Close</a>
<iframe src="http://www.local.dev/api/v1/track" frameborder="0" style="width:500px;height:500px;position:relative;top:-20px">
</iframe>
</div>
</div>
Within the iframe src view, i load a js which uses jquery
$(document).on('click','.close',function(){
$(document).closest('.app').remove();
});
Anyway to do this?
you can use:
$('#modalContainer', window.parent.document);
second parameter is the context in which to search.
$(document).on('click','.close',function(){
$('.app', window.parent.document).remove();
});
Try something like this:
$('#divtohide', window.parent.document).hide();
Or something like this:
$("#InFrameId").on('click', function() {
$('#divtohide', window.parent.document).hide();
});
EDIT: based on the recent update to your question if the frame is from a different domain, browser will flag this as XSS and you may not be able to do much. One way you can run scripts is if the server of the iframe is configured to send the X-XSS-Protection header with correct value.
This can be done with child to parent frame messaging.
Have the parent frame listen for a message.
<div id="myDiv">
<iframe src="childFrame.html" id="frame1"></iframe>
</div>
<script>
window.onmessage = function(e) {
if(e.data == "close") $("#myDiv").toggle();
}
</script>
The child frame can send a message to the parent frame.
<button onclick="parent.postMessage('close', '*');">Hide</button>
See my gist: https://gist.github.com/sfarthin/9140403
DhruvJoshi's method will have the browser flag this as a XSS attack.
Simply you can't, according to your code, I think your iframe comes from different domain, so a frame from different domain cant access to parent page.
Therefore you may consider using nodejs or maybe, you should read this: Cross domain iframe issue or a search with "crossdomain iframe" keywords will lead you to what you need.

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.

Categories

Resources