jQuery/Javascript: set border of iframe from inside iframe - javascript

I have an iframe and I want to set it's border to zero.
But I want to do this from inside the iframe, using javascript or jQuery.
How to do this? Many thanks in advance,

If the parent is on a different origin, you can't do it, because access to the parent's content is forbidden by the Same Origin Policy.
If the parent document is on the same origin, this should do it:
(function() {
var frames = window.parent.document.getElementsByTagName("iframe"),
index,
frame;
for (index = 0; index < frames.length; ++index) {
frame = frames[index];
if (frame.contentWindow == window) {
frame.frameBorder = "none";
}
}
})();
Live example | source of parent | source of frame
Note that it's important to use == rather than === when comparing the window properties (unusually, window is special).

You can do it by $(parent.document).find('#myIframe').css('border', 'xxxx'); - But as pointed out by the comment above, both the pages (main one as well as the one shown in the iframe) should be in the same domain - otherwise you'll end up with a security exception because of same origin policy.

Alternatively you can use parent.$
parent.$("iframe").prop("frameborder", 0); // This will change all iframes
parent.$("#IframeID").prop("frameborder", 0); // This will change single iframe

Related

Can't get elements of child window after window.open() [duplicate]

A simple task in JavaScript is to open a new window and writing inside. But I need to write in a dom element, a div with an ID.
var novoForm = window.open("somform.html", "wFormx", "width=800,height=600,location=no,menubar=no,status=no,titilebar=no,resizable=no,");
Than I try something...
var w = novoForm.innerWidth;
var h = novoForm.innerHeight;
novoForm.document.getElementById("monitor").innerHTML = 'Janela: '+w+' x '+h;
I did it to see if the object "novoForm" is valid. But nothing is written in "monitor" div. I also try using onload event with no success. I'm wondering if it's some security restriction or am I missing something...
You've done it right, but you do need to be sure to use onload (or poll), because it takes a moment for the page to get loaded in the new window.
Here's a full working example: Live Copy | Source
(function() {
document.getElementById("theButton").onclick = function() {
var novoForm = window.open("http://jsbin.com/ugucot/1", "wFormx", "width=800,height=600,location=no,menubar=no,status=no,titilebar=no,resizable=no,");
novoForm.onload = function() {
var w = novoForm.innerWidth;
var h = novoForm.innerHeight;
novoForm.document.getElementById("monitor").innerHTML = 'Janela: '+w+' x '+h;
};
};
})();
I'm wondering if it's some security restriction or am I missing something...
Not in your example as shown, no, because the page is clearly being loaded from the same origin. If the URL were from a different origin, then yes, you'd be running into the Same Origin Policy, which prohibits cross-origin scripting. You can relax that via the document.domain property, having both the window containing the code above and the window being loaded setting document.domain to the same value. From the link above:
If two windows (or frames) contain scripts that set domain to the same value, the same-origin policy is relaxed for these two windows, and each window can interact with the other. For example, cooperating scripts in documents loaded from orders.example.com and catalog.example.com might set their document.domain properties to “example.com”, thereby making the documents appear to have the same origin and enabling each document to read properties of the other.
More about document.domain can be found on MDN. Note that it only works where both documents share a common parent domain, e.g., so it works for app1.example.com and app2.example.com if they both set to example.com, but not for example1.com and example2.com because they have not common value they can set.
Alternatively, this is a solution:
var novoForm = window.open("somform.html", "wFormx", "width=800,height=600,location=no,menubar=no,status=no,titilebar=no,resizable=no,");
var teste = function(){
var mon = novoForm.document.getElementById("monitor");
if(typeof(mon)!="undefined"){
//novoForm.alert("Achei!");
var h = novoForm.innerHeight;
var strh = String(h - 40 - 30)+'px';
novoForm.document.getElementById("pagina").style.height = strh;
novoForm.document.getElementById("monitor").innerHTML = '<p class="legenda">© NetArts | gustavopi</p>';
clearInterval(id);
}
}
var id = setInterval(teste, 100);
This will do the job. Not a "pretty" solution to me, but it works!
Depends on what url you try to load into the new window. #T.J is right on that. Also note that if you just want to load a blank document you can load "about:blank" into the url. The only difference is that you would use outerWidth since you haven't loaded an actual document.
var novoForm = window.open("about:blank", "wFormx", "width=800,height=600,location=no,menubar=no,status=no,titilebar=no,resizable=no,");
var w = novoForm.outerWidth;
var h = novoForm.outerHeight;
novoForm.document.body.innerHTML = 'Janela: '+w+' x '+h;

Access parent frame from IFRAME using JavaScript [duplicate]

Well, I have an IFrame, which calls a same domain page.
My problem is that I want to access some information from this parent Iframe from this called page (from JavaScript). How can I access this Iframe?
Details: There are several Iframes just like this one, that can have the same page loaded, because I am programming a Windows environment. I intend to close this Iframe, that's why I need to know which I should close from inside him. I have an array keeping references to these Iframes.
EDIT: There iframes are generated dynamically
Also you can set name and ID to equal values
<iframe id="frame1" name="frame1" src="any.html"></iframe>
so you will be able to use next code inside child page
parent.document.getElementById(window.name);
Simply call window.frameElement from your framed page.
If the page is not in a frame then frameElement will be null.
The other way (getting the window element inside a frame is less trivial) but for sake of completeness:
/**
* #param f, iframe or frame element
* #return Window object inside the given frame
* #effect will append f to document.body if f not yet part of the DOM
* #see Window.frameElement
* #usage myFrame.document = getFramedWindow(myFrame).document;
*/
function getFramedWindow(f)
{
if(f.parentNode == null)
f = document.body.appendChild(f);
var w = (f.contentWindow || f.contentDocument);
if(w && w.nodeType && w.nodeType==9)
w = (w.defaultView || w.parentWindow);
return w;
}
I would recommend using the postMessage API.
In your iframe, call:
window.parent.postMessage({message: 'Hello world'}, 'http://localhost/');
In the page you're including the iframe you can listen for events like this:
window.addEventListener('message', function(event) {
if(event.origin === 'http://localhost/')
{
alert('Received message: ' + event.data.message);
}
else
{
alert('Origin not allowed!');
}
}, false);
By the way, it is also possible to do calls to other windows, and not only iframes.
Read more about the postMessage API on John Resigs blog here
Old question, but I just had this same issue and found a way to get the iframe. It's simply a matter of iterating through the parent window's frames[] array and testing each frame's contentWindow against the window in which your code is running. Example:
var arrFrames = parent.document.getElementsByTagName("IFRAME");
for (var i = 0; i < arrFrames.length; i++) {
if (arrFrames[i].contentWindow === window) alert("yay!");
}
Or, using jQuery:
parent.$("iframe").each(function(iel, el) {
if(el.contentWindow === window) alert("got it");
});
This method saves assigning an ID to each iframe, which is good in your case as they are dynamically created. I couldn't find a more direct way, since you can't get the iframe element using window.parent - it goes straight to the parent window element (skipping the iframe). So looping through them seems the only way, unless you want to use IDs.
you can use parent to access the parent page. So to access a function it would be:
var obj = parent.getElementById('foo');
Once id of iframe is set, you can access iframe from inner document as shown below.
var iframe = parent.document.getElementById(frameElement.id);
Works well in IE, Chrome and FF.
Maybe just use
window.parent
into your iframe to get the calling frame / windows. If you had multiple calling frame, you can use
window.top
Try this, in your parent frame set up you IFRAMEs like this:
<iframe id="frame1" src="inner.html#frame1"></iframe>
<iframe id="frame2" src="inner.html#frame2"></iframe>
<iframe id="frame3" src="inner.html#frame3"></iframe>
Note that the id of each frame is passed as an anchor in the src.
then in your inner html you can access the id of the frame it is loaded in via location.hash:
<button onclick="alert('I am frame: ' + location.hash.substr(1))">Who Am I?</button>
then you can access parent.document.getElementById() to access the iframe tag from inside the iframe
// just in case some one is searching for a solution
function get_parent_frame_dom_element(win)
{
win = (win || window);
var parentJQuery = window.parent.jQuery;
var ifrms = parentJQuery("iframe.upload_iframe");
for (var i = 0; i < ifrms.length; i++)
{
if (ifrms[i].contentDocument === win.document)
return ifrms[i];
}
return null;
}

QuerySelector for Web Elements Inside iframe

Edit: New title.
What I'm looking for is a document.querySelector for elements inside an iframe.
I've done quite a bit of Googling for an answer and finally I'm stumped.
I'm trying to query inside an iframe. I'm building string selectors to be used in Selenium and usually I just inspect the element with Firebug, and use document.querySelectorAll("theStringIBuid");
But it doesn't work with elements inside iframes. I've tried all of the below to get an element "radiobutton1" inside the "page-iframe" iframe.
var elem1 = ".page-iframe";
console.log(elem1);
var elem2 = ".radiobutton1";
console.log(elem2);
document.querySelectorAll(elem1+elem2+"");
document.querySelectorAll('.page-iframe').contentWindow.document.body.querySelectorAll('.radiobutton1')
document.getElementById('.page-iframe').contentWindow.document.body.innerHTML;
[].forEach.call( document.querySelectorAll('.page-iframe'),
function fn(elem){
console.log(elem.contentWindow.document.body.querySelectorAll('.radiobutton1')); });
var contentWindow = document.getElementById('.page-iframe').contentWindow
var contentWindow = document.querySelectorAll('.page-iframe')
var contentWindow = document.querySelectorAll('.page-iframe')[0].contentWindow
Thanks-
simple es6 adapted from h3manth:
document.querySelectorAll('iframe').forEach( item =>
console.log(item.contentWindow.document.body.querySelectorAll('a'))
)
if the original page's url isn't at the same domain with the iframe content, the javascript will treat the iframe as a black box, meaning it will not see anything inside it.
You can do this:
document.querySelector("iframe").contentWindow.document.querySelector("button")
https://m.youtube.com/watch?v=-mNp3-UX9Qc
You can simply use
document.querySelector("iframe").contentDocument.body.querySelector("#btn")
First query selector is to select the iframe. Then we can access ifram dom using content document and use the 2nd query selector to select the element inside iframe.
Here's a snippet for diving into same-origin frames (ie-compatible ES5):
function findInFramesRec(selector, doc) {
var hit = doc.querySelector(selector);
if (hit) return hit;
var frames = Array.prototype.slice.call(doc.frames);
for(var i = 0; (i < frames.length) && !hit ; i++) {
try {
if (!frames[i] || !frames[i].document) continue;
hit = findInFramesRec(selector, frames[i].document);
} catch(e) {}
}
return hit;
}
This dives into both frameset frames and iframes alike. It may even survive (though not enter) cross origin frames.

How to share a data between a window and a frame in JavaScript

This is WebKit browsers specific (meaning that I only need to make it work in WebKit specific, i.e. iOS/Android browsers, but I'm testing in Chrome).
I have a page. The page loads one or more iframes, with contents from another domain. I need to receive messages (using postMessage()) from these iframes, and I need to be able to identify which iframe a specific message came from.
I can't find a way to do that that does not involve throwing something the iframe URL that the iframe contents then can pass back to me. I would like to not have to meddle with the URL, as there is no guarantee I can safely do that (redirects can throw the parameters out, for example).
I tried something that I thought was reasonable. When I create the iframe element (it's done from J/S), I associated a property with the element, let's say 'shared_secret'. When I get the message event back from the frame, I tried to locating the element that the calling frame was created with, and reading that property.
function onMessage(evt) {
var callerId = evt.source.frameElement.shared_secret;
// ....
}
window.addEventListener(message, onMessage);
var frameEl = document.createElement('iframe');
frameEl.shared_secret = 'sommething blue';
frameEl.src = 'http://aliens.com/my.html';
somewhereInMyDoc.appendChild(frameEl);
When the frame loads, it will run:
window.parent.postMessage('do you know who I am?', '*');
However, frameElement turns out undefined in the above onMessage(). I guess for the security reasons, it does work perfectly when the parent/child are from the same domain.
And it's actually ironic. Parent window can not access event.source.frameElement because event.source is an alien window. iFrame window can not call window.frameElement, because frameElement is in an alien window. So nobody can get access to it.
So, is there something that I can use as a token that I can set on a newly loaded frame, and somehow get back?
Thank you.
For people looking for some code, here is what I used to find the iframe who sent the message :
/**
* Returns the iframe corresponding to a message event or null if not found.
*
* 'e' is the event object
*/
function getFrameTarget (e) {
var frames = document.getElementsByTagName('iframe'),
frameId = 0,
framesLength = frames.length;
for (; frameId < framesLength; frameId++) {
if (frames[frameId].contentWindow === e.source) {
return frames[frameId];
}
}
return null;
}
Thanks to Pawel Veselov and DMoses !
This should be credited to https://stackoverflow.com/users/695461/dmoses.
You can actually compare the content window object of the frame element to the event.source of the message event, and the comparison will yield TRUE if they are, in fact, the same.
So, to solve my particular problem, I'll need to keep the list of frame elements that I've created (sprinkling them, if needed, with whatever additional properties), and when the event comes in, iterating through all, looking for one that has its contentWindow property equal to the event.source property.
UPDATE
We did, through encountering some nasty bugs, also found out that you should put an 'id' on the iframe created from within the parent window. Especially if that window is itself in an iframe. Otherwise, certain (Android 4.x being known for sure) browsers will yield true comparison even if the message is being received from a completely different child frame.

How to identify if a webpage is being loaded inside an iframe or directly into the browser window?

I am writing an iframe based facebook app. Now I want to use the same html page to render the normal website as well as the canvas page within facebook. I want to know if I can determine whether the page has been loaded inside the iframe or directly in the browser?
Browsers can block access to window.top due to same origin policy. IE bugs also take place. Here's the working code:
function inIframe () {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
}
top and self are both window objects (along with parent), so you're seeing if your window is the top window.
When in an iframe on the same origin as the parent, the window.frameElement method returns the element (e.g. iframe or object) in which the window is embedded. Otherwise, if browsing in a top-level context, or if the parent and the child frame have different origins, it will evaluate to null.
window.frameElement
? 'embedded in iframe or object'
: 'not embedded or cross-origin'
This is an HTML Standard with basic support in all modern browsers.
if ( window !== window.parent )
{
// The page is in an iframe
}
else
{
// The page is not in an iframe
}
I'm not sure how this example works for older Web browsers but I use this for IE, Firefox and Chrome without an issue:
var iFrameDetection = (window === window.parent) ? false : true;
RoBorg is correct, but I wanted to add a side note.
In IE7/IE8 when Microsoft added Tabs to their browser they broke one thing that will cause havoc with your JS if you are not careful.
Imagine this page layout:
MainPage.html
IframedPage1.html (named "foo")
IframedPage2.html (named "bar")
IframedPage3.html (named "baz")
Now in frame "baz" you click a link (no target, loads in the "baz" frame) it works fine.
If the page that gets loaded, lets call it special.html, uses JS to check if "it" has a parent frame named "bar" it will return true (expected).
Now lets say that the special.html page when it loads, checks the parent frame (for existence and its name, and if it is "bar" it reloads itself in the bar frame. e.g.
if(window.parent && window.parent.name == 'bar'){
window.parent.location = self.location;
}
So far so good. Now comes the bug.
Lets say instead of clicking on the original link like normal, and loading the special.html page in the "baz" frame, you middle-clicked it or chose to open it in a new Tab.
When that new tab loads (with no parent frames at all!) IE will enter an endless loop of page loading! because IE "copies over" the frame structure in JavaScript such that the new tab DOES have a parent, and that parent HAS the name "bar".
The good news, is that checking:
if(self == top){
//this returns true!
}
in that new tab does return true, and thus you can test for this odd condition.
The accepted answer didn't work for me inside the content script of a Firefox 6.0 Extension (Addon-SDK 1.0): Firefox executes the content script in each: the top-level window and in all iframes.
Inside the content script I get the following results:
(window !== window.top) : false
(window.self !== window.top) : true
The strange thing about this output is that it's always the same regardless whether the code is run inside an iframe or the top-level window.
On the other hand Google Chrome seems to execute my content script only once within the top-level window, so the above wouldn't work at all.
What finally worked for me in a content script in both browsers is this:
console.log(window.frames.length + ':' + parent.frames.length);
Without iframes this prints 0:0, in a top-level window containing one frame it prints 1:1, and in the only iframe of a document it prints 0:1.
This allows my extension to determine in both browsers if there are any iframes present, and additionally in Firefox if it is run inside one of the iframes.
I'm using this:
var isIframe = (self.frameElement && (self.frameElement+"").indexOf("HTMLIFrameElement") > -1);
Use this javascript function as an example on how to accomplish this.
function isNoIframeOrIframeInMyHost() {
// Validation: it must be loaded as the top page, or if it is loaded in an iframe
// then it must be embedded in my own domain.
// Info: IF top.location.href is not accessible THEN it is embedded in an iframe
// and the domains are different.
var myresult = true;
try {
var tophref = top.location.href;
var tophostname = top.location.hostname.toString();
var myhref = location.href;
if (tophref === myhref) {
myresult = true;
} else if (tophostname !== "www.yourdomain.com") {
myresult = false;
}
} catch (error) {
// error is a permission error that top.location.href is not accessible
// (which means parent domain <> iframe domain)!
myresult = false;
}
return myresult;
}
Best-for-now Legacy Browser Frame Breaking Script
The other solutions did not worked for me. This one works on all browsers:
One way to defend against clickjacking is to include a "frame-breaker" script in each page that should not be framed. The following methodology will prevent a webpage from being framed even in legacy browsers, that do not support the X-Frame-Options-Header.
In the document HEAD element, add the following:
<style id="antiClickjack">body{display:none !important;}</style>
First apply an ID to the style element itself:
<script type="text/javascript">
if (self === top) {
var antiClickjack = document.getElementById("antiClickjack");
antiClickjack.parentNode.removeChild(antiClickjack);
} else {
top.location = self.location;
}
</script>
This way, everything can be in the document HEAD and you only need one method/taglib in your API.
Reference: https://www.codemagi.com/blog/post/194
I actually used to check window.parent and it worked for me, but lately window is a cyclic object and always has a parent key, iframe or no iframe.
As the comments suggest hard comparing with window.parent works. Not sure if this will work if iframe is exactly the same webpage as parent.
window === window.parent;
Since you are asking in the context of a facebook app, you might want to consider detecting this at the server when the initial request is made. Facebook will pass along a bunch of querystring data including the fb_sig_user key if it is called from an iframe.
Since you probably need to check and use this data anyway in your app, use it to determine the the appropriate context to render.
function amiLoadedInIFrame() {
try {
// Introduce a new propery in window.top
window.top.dummyAttribute = true;
// If window.dummyAttribute is there.. then window and window.top are same intances
return !window.dummyAttribute;
} catch(e) {
// Exception will be raised when the top is in different domain
return true;
}
}
Following on what #magnoz was saying, here is a code implementation of his answer.
constructor() {
let windowLen = window.frames.length;
let parentLen = parent.frames.length;
if (windowLen == 0 && parentLen >= 1) {
this.isInIframe = true
console.log('Is in Iframe!')
} else {
console.log('Is in main window!')
}
}
It's an ancient piece of code that I've used a few times:
if (parent.location.href == self.location.href) {
window.location.href = 'https://www.facebook.com/pagename?v=app_1357902468';
}
If you want to know if the user is accessing your app from facebook page tab or canvas check for the Signed Request. If you don't get it, probably the user is not accessing from facebook.
To make sure confirm the signed_request fields structure and fields content.
With the php-sdk you can get the Signed Request like this:
$signed_request = $facebook->getSignedRequest();
You can read more about Signed Request here:
https://developers.facebook.com/docs/reference/php/facebook-getSignedRequest/
and here:
https://developers.facebook.com/docs/reference/login/signed-request/
This ended being the simplest solution for me.
<p id="demofsdfsdfs"></p>
<script>
if(window.self !== window.top) {
//run this code if in an iframe
document.getElementById("demofsdfsdfs").innerHTML = "in frame";
}else{
//run code if not in an iframe
document.getElementById("demofsdfsdfs").innerHTML = "no frame";
}
</script>
if (window.frames.length != parent.frames.length) { page loaded in iframe }
But only if number of iframes differs in your page and page who are loading you in iframe. Make no iframe in your page to have 100% guarantee of result of this code
Write this javascript in each page
if (self == top)
{ window.location = "Home.aspx"; }
Then it will automatically redirects to home page.

Categories