Como acessar o Iframe pai a partir do JavaScript

170

Bem, eu tenho um IFrame, que chama uma mesma página de domínio. Meu problema é que desejo acessar algumas informações desse iframe pai a partir desta página chamada (do JavaScript). Como posso acessar este Iframe?

Detalhes: Existem vários iframes como este, que podem ter a mesma página carregada, porque estou programando um ambiente Windows. Pretendo fechar esse Iframe, é por isso que preciso saber o que devo fechar de dentro dele. Eu tenho uma matriz mantendo referências a esses iframes.

EDIT: Existem iframes gerados dinamicamente

José Leal
fonte
mesmo que iframes sejam gerados dinamicamente, você pode atribuir um novo ID exclusivo usando algum tipo de contador. Finalmente, você não precisa saber o ID, mas pode pesquisar facilmente, veja minha resposta.
Akash Kava

Respostas:

138

Também é possível definir nome e ID com valores iguais

<iframe id="frame1" name="frame1" src="any.html"></iframe>

então você poderá usar o próximo código na página filho

parent.document.getElementById(window.name);
Aquático
fonte
16
Talvez não seja óbvio para todos, mas com esse método você pode acessar um objeto de biblioteca do pai (apenas se o pai já tiver carregado a biblioteca). Exemplo: acessar o jQuery com o pai. $ ('#
Something
1
Esta solução é compatível com o modo de peculiaridades de compatibilidade IE5 +.
Slayner
Mesmo em 2016, isso funciona muito bem como parte de uma solução para o problema do IE imprimir o conteúdo de um iframetamanho muito pequeno. Mas por que isso funciona? window.nameretorna uma string. O que há de diferente em usar do window.nameque apenas passar o nome do ID como uma string que não funciona.)?
Karl
3
Olá, ele não roda com o Chrome 59 ..: VM111: 1 DOMException não capturado: impediu que um quadro com origem " xxx " acesse um quadro de origem cruzada.
Didier68
O Chrome vê os arquivos na mesma pasta que a origem cruzada, se não o CORS estiver definido. Eles dizem que é por segurança. A configuração do CORS precisa de um servidor. Envie aos usuários uma mensagem para configurar um servidor ou alterar o navegador se o Chrome for detectado.
90

Basta ligar window.frameElementda sua página emoldurada. Se a página não estiver em um quadro, frameElementserá null.

A outra maneira (obter o elemento da janela dentro de um quadro é menos trivial), mas por uma questão de integridade:

/**
 * @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;
}
Ian Carter
fonte
2
Obrigado! Funciona no IE 6+, FF e Chrome!
Rustyx
11
window.frameElementretorna nullquando window e iframe têm domínios diferentes, como mensagens de origem cruzada.
Qwerty
@ Qwerty você encontrou alguma solução?
Ajay Patidar
@AjayPatidar Acho que desisti. :(
Qwerty
78

Eu recomendaria o uso da API postMessage .

No seu iframe, ligue para:

window.parent.postMessage({message: 'Hello world'}, 'http://localhost/');

Na página você está incluindo o iframe, pode ouvir eventos como este:

window.addEventListener('message', function(event) {
      if(event.origin === 'http://localhost/')
      {
        alert('Received message: ' + event.data.message);
      }
      else
      {
        alert('Origin not allowed!');
      }

    }, false);

A propósito, também é possível fazer chamadas para outras janelas, e não apenas iframes.

Leia mais sobre a API postMessage no blog de John Resigs aqui

Kenneth Lynne
fonte
7
Eu acho que essa é claramente a melhor resposta, o <iframe>conteúdo não precisa saber nada sobre os pais e vice-versa. Eles só precisam obedecer ao contrato de mensagem simples. Impressionante!
precisa saber é
1
O <iframe> ainda precisa conhecer o domínio dos pais, certo?
Homr Zodyssey
1
@HomrZodyssey O domínio pai está disponível apenas como um mecanismo de segurança, se não for conhecido, você pode definir '*'.
Amir Ali Akbari #
Use '*'em clientes. Todas as outras soluções dão erro em um navegador Chrome ao tratar os arquivos na pasta clientes como não sendo a mesma origem, porque um servidor não está configurado. Esta é a melhor e única solução: dyn-web.com/tutorials/iframes/postmessage
30

Pergunta antiga, mas eu só tive esse mesmo problema e encontrei uma maneira de obter o iframe. É simplesmente uma questão de iterar pela matriz de quadros [] da janela pai e testar o contentWindow de cada quadro na janela em que seu código está sendo executado. Exemplo:

var arrFrames = parent.document.getElementsByTagName("IFRAME");
for (var i = 0; i < arrFrames.length; i++) {
  if (arrFrames[i].contentWindow === window) alert("yay!");
}

Ou, usando jQuery:

parent.$("iframe").each(function(iel, el) {
  if(el.contentWindow === window) alert("got it");
});

Esse método economiza a atribuição de um ID a cada iframe, o que é bom no seu caso, pois eles são criados dinamicamente. Não consegui encontrar uma maneira mais direta, já que você não pode obter o elemento iframe usando window.parent - ele vai diretamente para o elemento da janela pai (ignorando o iframe). Então, percorrê-los parece a única maneira, a menos que você queira usar IDs.

ingrediente_15939
fonte
1
Atualização: isso não funcionou exatamente como anunciado, e eu tive que usar o documento contentWindow.document ===. Não faço ideia do porquê. Também em alguns navegadores eu usei contentDocument. Bem, eu gosto disso!
Christophe
1
Desculpas, reconhecidamente eu só testei no Firefox. :) No entanto, tive sucesso usando o método jQuery e o contentWindow em vários navegadores.
ingredient_15939
1
Atualização: descobri que você também pode usar o window.frameElement, mas não tenho certeza de quais navegadores o suportam.
Christophe
2
Eu não acho que esse tipo de coisa funcione mais; você recebe um erro de origem cruzada.
Andrew Mao
@AndrewMao a pergunta é sobre os mesmos documentos de origem, então não há razão para obter problemas de origem cruzada.
Christophe
21

você pode usar parentpara acessar a página pai. Portanto, para acessar uma função, seria:

var obj = parent.getElementById('foo');
kemiller2002
fonte
1
Kevin, o problema é saber o id. Tenho vários iframes, e eu quero acessá-los de dentro do código
José Leal
Ainda assim, "O bloqueio de um quadro com origem" other-localhost: 8000 "acessa um quadro de origem cruzada".
User2568374
13

Depois que o id do iframe estiver definido, você poderá acessar o iframe no documento interno, como mostrado abaixo.

var iframe = parent.document.getElementById(frameElement.id);

Funciona bem no IE, Chrome e FF.

Akash Kava
fonte
Esta parece ser uma forma complicada de fazervar iframe = frameElement
Oriol
frameElement retorna o objeto no contexto atual da janela, mas parent.document.getElementById (frameElement.id) retorna o objeto no contexto da janela pai, você não pode executar as funções javascript da janela pai com frameElement, tente no jsfiddle e dê um exemplo, se puder .
Akash Kava
6

Talvez apenas use

window.parent

no iframe para obter o quadro de chamada / janelas. Se você tinha vários quadros de chamada, pode usar

window.top
Garra
fonte
3

Tente isso, em seu quadro pai, configure IFRAMEs assim:

<iframe id="frame1" src="inner.html#frame1"></iframe>
<iframe id="frame2" src="inner.html#frame2"></iframe>
<iframe id="frame3" src="inner.html#frame3"></iframe>

Observe que o ID de cada quadro é passado como uma âncora no src.

então, em seu html interno, você pode acessar o ID do quadro em que ele é carregado via location.hash:

<button onclick="alert('I am frame: ' + location.hash.substr(1))">Who Am I?</button>

você pode acessar parent.document.getElementById () para acessar a tag iframe de dentro do iframe

Mark Porter
fonte
Sim, esta seria a solução mais lógica, mas às vezes eu preciso mudar o src do iframe .. e passar este hash ou GET parâmetro cada pedido não é bom ..
José Leal
por que é ruim passar o hash toda vez? É visível apenas para o navegador, não para o servidor, e não afeta o armazenamento em cache como um parâmetro get faria.
Mark Porter
-1
// 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
fonte