194

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

Brett DeWoody
  • 59,771
  • 29
  • 135
  • 184
José Leal
  • 7,989
  • 9
  • 35
  • 54
  • even if iframes are generated dynamically, you can assign a new unique id by using some sort of counter, finally you dont need to know ID, but you can search easily, see my answer. – Akash Kava Jun 21 '12 at 14:00

9 Answers9

155

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);
Aquatic
  • 5,084
  • 3
  • 24
  • 28
  • 19
    Maybe it is not obvious for everyone, but with this method you can access a library object of the parent (only if the parent has already loaded the library). Example: access jQuery with parent.$('#something') – Zsolti Oct 31 '13 at 14:34
  • 1
    This solution is compatible with IE5+ compatibility quirks mode. – Slayner Apr 19 '16 at 09:19
  • Even in 2016, this works great as part of a solution for the problem of IE printing the contents of an `iframe` too small. But why does it work? `window.name` returns a string. What's different about using `window.name` than just passing the id name as a string which doesn't work.)? – Karl Oct 02 '16 at 20:24
  • 5
    Hi, it doesn't run with Chrome 59.. :VM111:1 Uncaught DOMException: Blocked a frame with origin "http://xxx" from accessing a cross-origin frame. – Didier68 Jul 28 '17 at 15:28
  • Chrome see files in same folder as cross-origin if not CORS is set. They say it is for security. Setting CORS need a server. Give users a message to set up a server or change browser if Chrome is detected. –  Aug 17 '19 at 09:09
108

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;
}
Rob W
  • 341,306
  • 83
  • 791
  • 678
Ian Carter
  • 1,111
  • 1
  • 7
  • 4
96

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

Kenneth Lynne
  • 15,461
  • 12
  • 63
  • 79
  • 7
    I think this is clearly the best answer, the ` – mfeineis Jun 05 '14 at 10:03
  • 1
    The – Homr Zodyssey Jun 01 '16 at 20:06
  • 1
    @HomrZodyssey The parent domain is only available as a safety mechanism, if not known, you can set `'*'`. – Amir Ali Akbari Nov 01 '17 at 08:26
  • Use `'*'` on clients. Every other solutions give error on a Chrome browser treating files in clients folder as not be Same Origin because a server is not set up. This is the best and *only* solution: https://www.dyn-web.com/tutorials/iframes/postmessage –  Aug 17 '19 at 11:18
  • DOMException: Blocked a frame with origin "null" from accessing a cross-origin frame. – savram Aug 08 '21 at 21:52
33

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.

ingredient_15939
  • 3,022
  • 7
  • 35
  • 55
  • 1
    Update: this didn't work exactly as advertised, and I had to use contentWindow.document===document. No idea why. Also in some browsers I used contentDocument. Well, I like that! – Christophe May 06 '11 at 05:47
  • 1
    Apologies, admittedly I only tested it in Firefox. :) However I've had success using the jQuery method and contentWindow in multiple browsers. – ingredient_15939 Aug 23 '11 at 12:44
  • 1
    Update: I found out that you can also use window.frameElement, but I am not sure which browsers support it. – Christophe Dec 09 '11 at 05:09
  • 2
    I don't think this type of stuff works anymore; you get a cross-origin error. – Andrew Mao Jun 02 '14 at 23:03
  • @AndrewMao the question is about same origin documents, so no reason to get cross-origin issues. – Christophe Sep 23 '15 at 16:33
24

you can use parent to access the parent page. So to access a function it would be:

var obj = parent.getElementById('foo');
Machavity
  • 30,841
  • 27
  • 92
  • 100
kemiller2002
  • 113,795
  • 27
  • 197
  • 251
15

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.

Akash Kava
  • 39,066
  • 20
  • 121
  • 167
  • This seems a convoluted way of doing `var iframe = frameElement` – Oriol Dec 05 '15 at 16:47
  • 1
    frameElement returns object in current window context, but parent.document.getElementById(frameElement.id) returns object in parent window context, you can't run parent window's javascript functions with frameElement, try it in jsfiddle and give me and example if you can. – Akash Kava Dec 05 '15 at 17:25
8

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
Clawfire
  • 499
  • 1
  • 6
  • 14
3

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

Mark Porter
  • 1,650
  • 9
  • 9
  • Yes, this would be the most logical solution, but sometimes I need to change the src of the iframe.. and passing this hash or GET parameter each request is not good.. – José Leal Jun 01 '09 at 17:14
  • 1
    why is it bad to pass the hash each time? It is only visible to the browser, not the server, and it doesn't affect caching like a get parameter would. – Mark Porter Jun 01 '09 at 17:59
-2
// 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;
}
Alex
  • 1