300x250 AD TOP

adv1

Formulário de contato

21 de outubro de 2011

Tags: , , ,

Como acessar um iframe e seus elementos via jQuery?

Recentemente tive um problema no projeto pois sentiu a necessidade de acessar um valor de um input que estava dentro de um iframe. Esse tipo de situação não é tão comum, uma vez que geralmente acessamos os valores do iframe para fora.


Para acessar, de dentro de um iframe, um valor externo, utilizamos o seguinte código:
$('#idDoElementoExterno', parent.document).val();
Entretanto, nunca tínhamos passado pela situação contrária. Pesquisando um pouco descobrimos uma alternativa, porém em JavaScript. Para ficar melhor o entendimento, vamos simular uma situação aqui. Temos uma página html "A.html" e dentro da mesma existe um iframe que aponta (src) para uma página "B.html":

<!-- A.html -->
<html>
 <head>
  <title>Testando iframe - jQuery</title>
   <script language="JavaScript">
    function exibeValor() {
     // alert aqui!
    }
   </script>   
  </head>
  <body>
  <input type="button" value="Exibir valor de campo do iframe" onclick="exibeValor()"/>
  <br/>
  <iframe name="iframeTeste" id="iframeTeste" src="B.html" />
  </body>
</html>
<!-- B.html -->
<html>
 <head>
  <title>Testando iframe - jQuery</title>    
  </head>
  <body>
   Campo de teste: <input type="text" id="campoTeste" />
  </body>
</html>
Suponhamos que queremos buscar o valor digitado no campo de texto ('campoTeste') do iframe e exibir em um alert javascript o mesmo ao clicar no botão que está fora do iframe.
Para isso, precisamos implementar o seguinte código javascript na função "exibeValor()":
var valor = window.parent.iframeTeste.document.getElementById('campoTeste').value;

 alert(valor);
Entretanto, essa abordagem ainda não compreendia o que queríamos, uma vez que estávamos utilizando jQuery. Logo, encontramos a solução abaixo para o mesmo método:
var valor = $('#campoTeste', window.parent.iframeTeste.document).val();
 alert(valor);
Ainda assim, essa implementação ainda faz uso de chamada de atributos javascript bruta. Queríamos algo totalmente jQuery, e então chegamos a código:
var valor = $('#iframeTeste').contents().find('#campoTeste').val();
 alert(valor); 

Tudo ficou mais simples por causa da função contents() do jquery. Normalmente, a função retorna todos os nós filhos a partir dos elementos combinados, mas no caso de um iframe todo o documento é carregado no iframe. Agora você pode usar o find() para localizar os elementos que você precisa para trabalhar e é isso.

Update 15/01/2016


Se você estiver usando o Google Chrome como browser para efetuar os testes deste exemplo, provavelmente receberá um erro do tipo: 
Uncaught SecurityError: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "null" from accessing a frame with origin "null". Protocols, domains, and ports must match.
Isso acontece porque o Chrome tem uma política de restrição de segurança que não permite acesso a outros arquivos direto do disco rígido da sua máquina, mesmo que pertençam ao mesmo diretório/app de origem.

Existem algumas opções simples de resolver isso, vejamos:

  1. Você pode executar seus códigos via Firefox ou outro browser, uma vez que eles não impõem tais restrições;
  2. É possível ainda configurar a flag "--allow-file-access-from-files" no seu arquivo de inicialização do Chrome para habilitar tal recurso;
  3. Ou você pode hospedar suas páginas HTML em algum servidor (Apache, Tomcat, etc.) e executá-las via http://localhost/. A forma mais simples de fazer isso, se você não tiver conhecimentos avançados de servidor, é usando o módulo http-server do Node.js.

-->

24 comentários:

  1. perfeito..
    vai melhorar e muito meu framework que precisso fazer..

    ResponderExcluir
  2. eu gostaria que fosse ao contrario.
    que o botão Exibir valor de campo do iframe, adicionasse um nome no campo de texto.

    tem como mim ajudar?
    envia pra mim com o link do site.
    davidssombra@live.com

    ResponderExcluir
    Respostas
    1. Oi, desculpa a demora...

      Pra acessar qualquer componente pai de dentro de um iframe é só usar a seguinte chamada:
      $(parent, '#idDoElemento')...

      Blz?

      Excluir
  3. Muito obrigada!! me ajudou muito!!

    Claudia

    ResponderExcluir
    Respostas
    1. Oi, que bom que ajudou! Fico feliz por isso! :)

      Excluir
  4. bom dia amigo, podes me ajudar?
    eu tenho um site com frameset...

    ------------
    INDEX.html
    ------------
    [title]TITULO DO SITE[/title]
    [frameset rows="30,*" frameborder="NO" border="0" framespacing="0"]
    [frame id="topFrame" name="topFrame" scrolling="no" noresize src="ARQUIVO1.php"][/frame]
    [frame name="mainFrame" src="ARQUIVO2.php"][/frame]
    [/frameset][noframes][/noframes]

    ------------
    ARQUIVO2.php
    ------------
    [script]
    parent.document.title = "NOVO TITULO DO INDEX";
    [/script]

    ------------
    o que quero e não consegui e nem achei nada sobre isso, é pegar o titulo dinamicamente no ARQUIVO2 e passar ao arquivo INDEX.html, porém não funciona, pode me ajudar?

    troquei < por [ e > por ]

    agradeço deste já,
    Sandro.

    ResponderExcluir
    Respostas
    1. Olá Sandro, o seu cenário é bem semelhante ao que mostrei... já tentou acessar o elemento head através das funções que mostrei?

      Excluir
  5. Diogo, tudo bem? O código não funciona no Chrome, dá um erro: "Uncaught SecurityError: Blocked a frame with origin "null" from accessing a frame with origin "null". Protocols, domains, and ports must match.". Faz ideia do q pode ser?

    ResponderExcluir
    Respostas
    1. Olá Rosiene, tudo bem?

      Dá uma olhada no link: http://stackoverflow.com/questions/17950598/using-iframe-with-local-files-in-chrome

      Excluir
  6. Ola muito bom esse tutorial, só que eu tenho uma duvida eu apenas queria ir buscar ao iframe um valor que tenho no CodeBehind. Isto porque o que estou a tentar fazer é ir buscar o numero de notificações que estão dentro da iframe e mostrar no menu da pagina principal quantas notificações o usuário tem, como acontece nos mails, então o que faço é contar o numero de notificações que estão dentro da tabela e guardo numa variável é possível ir buscar essa variável e mostrar na pagina principal?

    Muito Obrigado

    ResponderExcluir
    Respostas
    1. Olá Marco,

      A sua dúvida estaria mais relacionada ao fator "buscar um valor em uma variável javascript no frame interno", é isso?

      Excluir
  7. Ola, entretanto consegui resolver o meu problema.

    Obrigado pela atenção

    ResponderExcluir

  8. Olá Diogo parabéns por este pots. Espero que me ajude. no meu arquivo. b.html em tenho um formulário com vários campos e tem uma função javascript para fazer a validação.

    Ai no arquivo. A.HTML eu tenho um botão chamado gerar O.S como eu faço para que quando eu clicar no botão gerar O.S. ele verifica os campos do arquivo b.html se estão preenchidos ou não. Ou seja eu quero que ele faça a verificação dos campos usando a função que eu utilizei.

    Aguardo um retorno.

    Att.,

    ResponderExcluir
    Respostas
    1. Opa Rodrigo, cara se entendi bem tua questão, você quer acessar os valores e validar se estão preenchidos ou não...

      Se for só isso, pode usar a função:
      var valor = $('#iframeTeste').contents().find('#campoTeste').val();
      if (valor == null || valor == '') {
      alert("Campo obrigatório");
      }

      Entendeu?

      Excluir
  9. Boa noite Diogo.

    Veja se pode me ajudar...

    Tenho um arquivo chamado restaurante.html, dentro deste existe o seguinte trecho de codigo:

    div id="TabbedPanels1" class="TabbedPanels"
    ul class="TabbedPanelsTabGroup"
    li class="TabbedPanelsTab" tabindex="0" Dados do Restaurante /li
    li class="TabbedPanelsTab" tabindex="0" Mapa /li
    /ul
    div class="TabbedPanelsContentGroup"
    div class="TabbedPanelsContent"

    /div
    div class="TabbedPanelsContent"
    iframe scrolling="no" src="Mapa.html id="frame" /iframe
    /div
    /div
    /div

    Note que dentro do iframe é chamado o arquivo Mapa.html.

    Dentro do arquivo Mapa.html eu tenho a chamada de um arquivo contendo codigo java script:

    script type="text/javascript" src="mapa.js" /script

    Dentro deste arquivo tenho codigo da API Google Maps V3 e abaixo usando jquery, quero que quando clicar nas abas do componente TabbedPanels1 (restaurante.html) acione uma função da API Google Maps:

    *****arquivo mapa.js*****
    var geocoder;
    var map;
    var marker;

    function initialize() {
    var latlng = new google.maps.LatLng(-26.257705,-48.629837);
    var options = {
    zoom: 10,
    center: latlng,
    mapTypeId: google.maps.MapTypeId.ROADMAP
    };

    map = new google.maps.Map(document.getElementById("map"), options);

    geocoder = new google.maps.Geocoder();

    marker = new google.maps.Marker({
    map: map,
    draggable: true,
    });

    marker.setPosition(latlng);
    }

    $(document).ready(function () {
    initialize();

    function carregarNoMapa(endereco) {
    geocoder.geocode({ 'address': endereco, 'region': 'BR' }, function (results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
    if (results[0]) {
    var latitude = results[0].geometry.location.lat();
    var longitude = results[0].geometry.location.lng();

    var location = new google.maps.LatLng(latitude, longitude);
    marker.setPosition(location);
    map.setCenter(location);
    map.setZoom(16);
    }
    }
    })
    }

    O codigo acima está perfeito, preciso fazer funcionar o abaixo:

    tentei de 3 formas:
    1 - Não funcionou:

    $('.TabbedPanelsTab').live('click',function(){
    alert ('teste');
    if($("#txtEndereco").val() != ""){
    carregarNoMapa($("#txtEndereco").val());
    }
    })

    2 - Não funcionou

    $(parent, '.TabbedPanelsTab').click(function(){
    alert ('teste2');
    if($("#txtEndereco").val() != ""){
    carregarNoMapa($("#txtEndereco").val());
    }
    })

    3 - Funcionou se eu utilizar o arquivo mapa.js diretamente no arquivo restaurante, utilizando o iframe tambem não funcionou:

    $('.TabbedPanelsTab').click(function(){
    alert ('teste');
    if($("#txtEndereco").val() != ""){
    carregarNoMapa($("#txtEndereco").val());
    }
    })

    ResponderExcluir
  10. iframe id="pixlr" src="http://apps.pixlr.com/express/" height="800" width="1024" frameborder="0">fechariframe

    abrescript

    $(document).ready(function(){

    $("#pixlr").load(function(){
    $("#pixlr").contents().find("#ad-wrap").css("display","none");
    });

    });
    fecha_script

    obs: tive que tirar as tags de fechamento.

    ResponderExcluir
  11. consigo por meio de um form, efetuar login dentro do iframe e deste extrair informações de uma tabela?

    ResponderExcluir
  12. Opa,

    Sim. Desde que ambos pertençam à mesma aplicação. Basta usar a função mostrada usando os seletores de acesso.

    ResponderExcluir
  13. Aqui o codigo não funcionou (nao sei se atualizaram algo no chrome).

    ResponderExcluir