jQuery / JavaScript : iframe의 내용에 액세스


791

jQuery를 사용하여 iframe 내부의 HTML을 조작하고 싶습니다.

jQuery 함수의 컨텍스트를 iframe의 문서로 설정 하여이 작업을 수행 할 수 있다고 생각했습니다.

$(function(){ //document ready
    $('some selector', frames['nameOfMyIframe'].document).doStuff()
});

그러나 이것은 작동하지 않는 것 같습니다. 에서 변수가 검사 쇼 날의 비트 frames['nameOfMyIframe']입니다 undefined내가 부하에 iframe을 위해 잠시 기다려하지 않는. 그러나 iframe 이로 드되면 변수에 액세스 할 수 없습니다 ( permission denied유형 오류가 발생 함).

누구든지 이것에 대한 해결 방법을 알고 있습니까?


3
iFrame에는 무엇이 포함되어 있습니까? src가 다른 도메인으로 설정되어 있습니까?
James

다른 도메인 인 경우에도 콘텐츠에 액세스하거나 이벤트를 등록 할 수있는 방법이
있습니까

34
아니요. 크로스 사이트 스크립팅이므로 보안상의 이유로 금지되어 있습니다. 내 솔루션은 프록시를 사용하는 것이 었습니다. IFRAME의 HTML을 내 사이트를 통해 그대로 제공하여 더 이상 브라우저의 관점에서 사이트 간 교차하지 않도록하십시오.
reinierpost

그것은 사용하기 더 크로스 브라우저의 .contentWindow.document보다 .documentiframe요소입니다. 위의 변경 사항을 제안하겠습니다.
Alan H.

1
한 가지 방법은 크롬 확장입니다
Muhammad Umer

답변:


384

나는 당신이하고있는 일이 동일한 원산지 정책의 대상이라고 생각합니다 . 권한 거부 유형 오류가 발생 하는 이유 입니다.


6
@Pacerier 최선의 방법은 당신이 할 수 있다면 귀하의 사이트에 iframe의 내용을 프록시하는 것입니다 ...
Tracker1

10
@ Tracker1 :이 프록시 솔루션을 구현하기위한 모든 프레임 워크 / api / 디자인 패턴을 제안 할 수 있습니까? 예제 또는 튜토리얼 등의 링크가 있습니까? 검색을 시도했지만 찾을 수 없습니다.
Umer Hayat 2016

3
이 경우 도메인의 페이지를 제공하는 http 서버를 프록시로 사용합니다. 타사 사이트에서 콘텐츠를 요청하고 http 응답에서 클라이언트에게 전달합니다. 짐작할 수 있듯이 이전 병행 요청이 서버와 병행하여 잠재적 병목 현상으로 실행되므로 사이트의 응답 속도에 빠르게 영향을줍니다.
rutherford

1
@Pacerier 잠재적으로 여기에 허용되는 답변의 방법 중 하나 : stackoverflow.com/questions/3076414/… 또는 다른 방법 (예 : 자신의 도메인을 프록시로 사용).
Mark Amery

4
기록을 위해 비슷한 것을 설정했습니다. 결과가 엄청나게 느려지지 않게하려면 자산 요청 (CSS / JS / 이미지)을 원래 웹 사이트로 직접 라우팅하도록 프록시 서버를 설정하십시오. HTML 요청 만 관리합니다. 나는 지금 localhost에서 먼 사이트를 탐색하고 있으며 그것은 절대적으로 투명합니다 :)
neemzy

985

<iframe>도메인이 동일한 도메인 인 경우 다음 과 같이 요소에 쉽게 액세스 할 수 있습니다.

$("#iFrame").contents().find("#someDiv").removeClass("hidden");

참고


157
동일한 원산지 정책에 대해 아는 것이 좋지만 이것이 OP가 원하는 것을 수행하는 답변입니다. 왜 다른 답변이 올바른 답변으로 선택 되었습니까?
Jason Swett

2
오리진에서 HTML을 가져 오려면 프록시를 사용해야합니다. 예를 들어, johnchapman.name/…
mhenry1384

7
@ JasonSwett, 내 생각에 OP의 문제는 실제로입니다. same origin policy이 경우이 답변은 그를위한 해결책이 아닙니다.
ANeves

3
@fizzbuzz 그런 다음 jQuery를 사용하여 다른 id-less 컨텐츠를 얻는 것과 같은 방법으로 IFrame을 얻습니다. 필요한 경우 클래스 이름과 속성 값을 사용하여 CSS로 적절한 <IFrame> 태그를 선택합니다.
Auspex

2
iframe에 컨텐츠 라는 메소드가 없습니다 .
Renan

88

.contents()jQuery의 메소드를 사용할 수 있습니다 .

.contents()iframe을 메인 페이지와 같은 도메인에있는 경우 방법은 또한, iframe이 내용 문서를 가져올 수 있습니다.

$(document).ready(function(){
    $('#frameID').load(function(){
        $('#frameID').contents().find('body').html('Hey, i`ve changed content of <body>! Yay!!!');
    });
});

2
본문을 설정하지 않기 위해 i 프레임 콘텐츠를 가져와야합니다 ..... 위의 작업을 수행하면 항상 작동하지 않습니다. 빈 본문
George Hanna

3
@DarkoZ 음, 실제로이 답변이 먼저 나왔으니, 다른 답변이 사본
이라면

@DarkoZ : 원래 의견을 남기는 것이 당신을 부끄러워하지는 않았지만, 문제가 아닌 것을 이해하려고 30 초 정도 낭비했습니다 :) 따라서 표절 답변에 대한이 모든 토론을 제거하는 것이 가장 좋습니다.
Dan Dascalescu 2016 년

혼란을 방지하기 위해 댓글이 삭제되었습니다. 사과.
Darko Z

43

iframe src가 다른 도메인에서 온 경우에도 계속 수행 할 수 있습니다. 외부 페이지를 PHP로 읽고 도메인에서 에코해야합니다. 이처럼 :

iframe_page.php

<?php
    $URL = "http://external.com";

    $domain = file_get_contents($URL);

    echo $domain;
?>

그런 다음과 같은 것 :

display_page.html

<html>
<head>
  <title>Test</title>
 </head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>

<script>

$(document).ready(function(){   
    cleanit = setInterval ( "cleaning()", 500 );
});

function cleaning(){
    if($('#frametest').contents().find('.selector').html() == "somthing"){
        clearInterval(cleanit);
        $('#selector').contents().find('.Link').html('ideate tech');
    }
}

</script>

<body>
<iframe name="frametest" id="frametest" src="http://yourdomain.com/iframe_page.php" ></iframe>
</body>
</html>

위는 액세스 거부 등이없는 iframe을 통해 외부 페이지를 편집하는 방법의 예입니다.


12
물론, 서버는 사용자의 브라우저가 아닌 원격 페이지를 가져 오기 때문에 쿠키는 원격 페이지로 전송되지 않습니다. YMMV.
마크 파울러

1
@Mark : curl 확장으로 쿠키, 게시 된 데이터, HTTP 헤더 및 기타를 구현하면 쿠키를 쉽게 보낼 수 있습니다. php.net/manual/en/book.curl.php
geon

2
@geon : 그러나 브라우저는 외부 도메인에 대한 쿠키를 PHP 스크립트로 보내지 않습니다
ysth

6
@basysmith주의하십시오 : 존재하는 이유 same origin policy가 있으며,이 답변의 제안은 그것에 영향을받지 않습니다.
ANeves

1
이런 식으로하는 것이 불법입니까?
Tallboy

32

나는이 방법을 더 깨끗하게 발견한다.

var $iframe = $("#iframeID").contents();
$iframe.find('selector');

엉덩이를 저장했습니다. "$ ("# iframe "). contents (). find ()"를 사용하여 미쳤습니다. 어떤 이유로 작동하지 않았습니다. 왜 그런지 모르겠지만 작동합니다.
neminem 2016 년

30

사용하다

iframe.contentWindow.document

대신에

iframe.contentDocument

좋은 대답입니다. 다른 도메인의 iFrame에서 작동합니다. Safari와 Firefox의 콘솔에서 시도했습니다.
Aneil Mallavarapu

12
콘솔에서 수행하는 경우 다른 도메인에서만 작동한다고 생각합니다. 스크립트에서 액세스가 허용되지 않습니다.
yincrash

이것이 정답입니다. iframe이 다른 도메인에있을 때 내 생명을 구하고 작동합니다. 언급했듯이 콘솔에서만.
silkfire

나를 위해 iframe.contentWindow.document가 항상 작동하지는 않습니다. 그리고 그것이 $ (elem) .contents (). get (0)하는 것을 발견하지 못하면
elewinso

브라우저 콘솔에서 "루트 문서"를 선택할 수 있습니다. "상단"을 선택하면 교차 출처 액세스로 작동하지 않습니다. iframe 도큐멘트를 대신하여 액세스하도록 선택하면 물론 액세스 할 수 있습니다. 브라우저가 아니라 브라우저 소유자이기 때문입니다.
Sergei Kovalenko

26

이벤트를 iframe의 onload 핸들러에 첨부하고 거기에서 js를 실행하여 iframe에 액세스하기 전에로드가 완료되었는지 확인해야합니다.

$().ready(function () {
    $("#iframeID").ready(function () { //The function below executes once the iframe has finished loading
        $('some selector', frames['nameOfMyIframe'].document).doStuff();
    });
};

위의 내용은 '아직로드되지 않은'문제를 해결하지만 권한과 관련하여 다른 도메인의 iframe에서 페이지를로드하는 경우 보안 제한으로 인해 페이지에 액세스 할 수 없습니다.


이것은 좋은 생각입니다. 사실 당신이 대답 한대로 시도했습니다. 그러나 거부 된 권한을 해결하지 못합니다 (iframe 항목에 액세스하기 전에 기다려야하는 문제를 해결합니다)
rz.

실제로 ... 신경 쓰지 마라.이 작업을 수행 할 때조차도 대기가 여전히 필요한 것 같습니다.
rz.

준비 기능이 작동합니다. 그러나 iframe의 내용이로드 될 때까지 기다리지 않고 iframe 자체의 내용을 호출했을 때만 부모 문서에 대해서만 나타납니다. 나는 또한 그것이 동일한 원산지 정책 때문이라고 생각합니다.
rz.

3
이 코드에 대한 몇 가지 참고 사항 : .document 대신 iframe.contentDocument를 사용해야하고 대기를 피하려면 .ready () 대신 .load ()를 사용해야합니다. (완벽하지는 않지만 더 좋습니다)
Rodrigo Queiro

21

window.postMessage를 사용하여 페이지와 iframe 사이의 함수 (도메인 간)를 호출 할 수 있습니다.

선적 서류 비치

page.html

<!DOCTYPE html>
<html>
<head>
    <title>Page with an iframe</title>
    <meta charset="UTF-8" />
    <script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
    <script>
    var Page = {
        id:'page',
        variable:'This is the page.'
    };

    $(window).on('message', function(e) {
        var event = e.originalEvent;
        if(window.console) {
            console.log(event);
        }
        alert(event.origin + '\n' + event.data);
    });
    function iframeReady(iframe) {
        if(iframe.contentWindow.postMessage) {
            iframe.contentWindow.postMessage('Hello ' + Page.id, '*');
        }
    }
    </script>
</head>
<body>
    <h1>Page with an iframe</h1>
    <iframe src="iframe.html" onload="iframeReady(this);"></iframe>
</body>
</html>

iframe.html

<!DOCTYPE html>
<html>
<head>
    <title>iframe</title>
    <meta charset="UTF-8" />
    <script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
    <script>
    var Page = {
        id:'iframe',
        variable:'The iframe.'
    };

    $(window).on('message', function(e) {
        var event = e.originalEvent;
        if(window.console) {
            console.log(event);
        }
        alert(event.origin + '\n' + event.data);
    });
    $(window).on('load', function() {
        if(window.parent.postMessage) {
            window.parent.postMessage('Hello ' + Page.id, '*');
        }
    });
    </script>
</head>
<body>
    <h1>iframe</h1>
    <p>It's the iframe.</p>
</body>
</html>

4

다른 변형을 사용하여 액세스하는 것을 선호합니다. 부모에서 자식 iframe의 변수에 액세스 할 수 있습니다. $또한 변수이며 그냥 호출에 액세스 할 수 있습니다 window.iframe_id.$

예를 들어 window.view.$('div').hide()-id가 'view'인 iframe에서 모든 div를 숨 깁니다.

그러나 FF에서는 작동하지 않습니다. 더 나은 호환성을 위해서는

$('#iframe_id')[0].contentWindow.$


2

jQuery의 내장 준비 기능을 사용하여로드가 완료 될 때까지 기다리면서 클래식을 사용해 보셨습니까?

$(document).ready(function() {
    $('some selector', frames['nameOfMyIframe'].document).doStuff()
} );

케이


2
예. 준비 기능은 iframe이로드 될 때가 아니라 메인 프레임이로드 될 때 실행을 시작합니다. 그래도 대기는 문제의 작은 부분 인 것 같습니다. 도메인 간 보안과 관련이 있다고 생각합니다.
rz.

2

샘플 코드를 만듭니다. 이제 다른 도메인에서 iframe의 콘텐츠에 액세스 할 수없는 경우를 쉽게 이해할 수 있습니다. iframe 콘텐츠에 액세스 할 수있는 동일한 도메인

나는 당신에게 내 코드를 공유합니다.이 코드를 실행하여 콘솔을 확인하십시오. 콘솔에서 이미지 src를 인쇄합니다. iframe에는 4 개의 iframe이 있고 동일한 도메인에서 2 개의 iframe이 있고 다른 도메인에서 2 개의 iframe이 있습니다. 두 개의 이미지 src ( https://www.google.com/logos/doodles/2015/googles-new-logo -5078286822539264.3-hp2x.gif

https://www.google.com/logos/doodles/2015/arbor-day-2015-brazil-5154560611975168-hp2x.gif ) 콘솔에서 두 가지 권한 오류 (2 오류 : 속성 '문서 액세스 권한이 거부되었습니다' '

... irstChild)}, contents : function (a) {return m.nodeName (a, "iframe")? a.contentDocument ...

)는 타사 iframe에서 나옵니다.

<body id="page-top" data-spy="scroll" data-target=".navbar-fixed-top">
<p>iframe from same domain</p>
  <iframe frameborder="0" scrolling="no" width="500" height="500"
   src="iframe.html" name="imgbox" class="iView">

</iframe>
<p>iframe from same domain</p>
<iframe frameborder="0" scrolling="no" width="500" height="500"
   src="iframe2.html" name="imgbox" class="iView1">

</iframe>
<p>iframe from different  domain</p>
 <iframe frameborder="0" scrolling="no" width="500" height="500"
   src="https://www.google.com/logos/doodles/2015/googles-new-logo-5078286822539264.3-hp2x.gif" name="imgbox" class="iView2">

</iframe>

<p>iframe from different  domain</p>
 <iframe frameborder="0" scrolling="no" width="500" height="500"
   src="http://d1rmo5dfr7fx8e.cloudfront.net/" name="imgbox" class="iView3">

</iframe>

<script type='text/javascript'>


$(document).ready(function(){
    setTimeout(function(){


        var src = $('.iView').contents().find(".shrinkToFit").attr('src');
    console.log(src);
         }, 2000);


    setTimeout(function(){


        var src = $('.iView1').contents().find(".shrinkToFit").attr('src');
    console.log(src);
         }, 3000);


    setTimeout(function(){


        var src = $('.iView2').contents().find(".shrinkToFit").attr('src');
    console.log(src);
         }, 3000);

         setTimeout(function(){


        var src = $('.iView3').contents().find("img").attr('src');
    console.log(src);
         }, 3000);


    })


</script>
</body>

1

jquery없이 iframe의 내용을 얻으려고 여기에 왔으므로 다른 사람이 찾는 것은 다음과 같습니다.

document.querySelector('iframe[name=iframename]').contentDocument

1

이 솔루션은 iFrame과 동일하게 작동합니다. 다른 웹 사이트에서 모든 내용을 가져올 수있는 PHP 스크립트를 만들었으며 가장 중요한 부분은 사용자 정의 jQuery를 해당 외부 내용에 쉽게 적용 할 수 있다는 것입니다. 다른 웹 사이트에서 모든 내용을 가져올 수있는 다음 스크립트를 참조한 다음 cusom jQuery / JS도 적용 할 수 있습니다. 이 컨텐츠는 모든 요소 또는 페이지 내 어디에서나 사용할 수 있습니다.

<div id='myframe'>

  <?php 
   /* 
    Use below function to display final HTML inside this div
   */

   //Display Frame
   echo displayFrame(); 
  ?>

</div>

<?php

/* 
  Function to display frame from another domain 
*/

function displayFrame()
{
  $webUrl = 'http://[external-web-domain.com]/';

  //Get HTML from the URL
  $content = file_get_contents($webUrl);

  //Add custom JS to returned HTML content
  $customJS = "
  <script>

      /* Here I am writing a sample jQuery to hide the navigation menu
         You can write your own jQuery for this content
      */
    //Hide Navigation bar
    jQuery(\".navbar.navbar-default\").hide();

  </script>";

  //Append Custom JS with HTML
  $html = $content . $customJS;

  //Return customized HTML
  return $html;
}

0

더욱 견고하게하기 위해 :

function getIframeWindow(iframe_object) {
  var doc;

  if (iframe_object.contentWindow) {
    return iframe_object.contentWindow;
  }

  if (iframe_object.window) {
    return iframe_object.window;
  } 

  if (!doc && iframe_object.contentDocument) {
    doc = iframe_object.contentDocument;
  } 

  if (!doc && iframe_object.document) {
    doc = iframe_object.document;
  }

  if (doc && doc.defaultView) {
   return doc.defaultView;
  }

  if (doc && doc.parentWindow) {
    return doc.parentWindow;
  }

  return undefined;
}

...
var frame_win = getIframeWindow( frames['nameOfMyIframe'] );

if (frame_win) {
  $(frame_win.contentDocument || frame_win.document).find('some selector').doStuff();
  ...
}
...
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.