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보다 .document온 iframe요소입니다. 위의 변경 사항을 제안하겠습니다.
— 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.