jQuery / JavaScript: การเข้าถึงเนื้อหาของ iframe


791

ฉันต้องการจัดการ HTML ภายใน iframe โดยใช้ jQuery

ฉันคิดว่าฉันสามารถทำได้โดยการตั้งค่าบริบทของฟังก์ชัน jQuery เป็นเอกสารของ iframe บางอย่างเช่น:

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

อย่างไรก็ตามเรื่องนี้ดูเหมือนจะไม่ทำงาน การตรวจสอบเล็กน้อยแสดงให้ฉันเห็นว่าตัวแปรในframes['nameOfMyIframe']นั้นอยู่undefinedนอกเสียจากว่าฉันจะรอสักครู่เพื่อให้โหลด iframe อย่างไรก็ตามเมื่อ iframe โหลดตัวแปรจะไม่สามารถเข้าถึงได้ (ฉันได้รับpermission deniedข้อผิดพลาด -type)

มีใครรู้บ้างเกี่ยวกับเรื่องนี้?


3
iFrame ประกอบด้วยอะไร - ตั้งค่า src เป็นโดเมนอื่นหรือไม่
James

ถ้ามันเป็นโดเมนอื่น ๆ ที่มียังคงเป็นวิธีการเข้าถึงเนื้อหาหรือลงทะเบียนเหตุการณ์
adardesign

34
ไม่เพราะนั่นจะเป็นการเขียนสคริปต์ข้ามไซต์ซึ่งถูกห้ามด้วยเหตุผลด้านความปลอดภัย วิธีแก้ปัญหาของฉันคือการใช้พรอกซี: ป้อน HTML ในคำต่อคำ IFRAME ผ่านเว็บไซต์ของฉันดังนั้นมันจึงไม่ข้ามมุมมองของเบราว์เซอร์อีกต่อไป
reinierpost

มันขึ้นข้ามเบราว์เซอร์ที่จะใช้.contentWindow.documentกว่า.documentในiframeองค์ประกอบ ฉันจะแนะนำการเปลี่ยนแปลงด้านบน
Alan H.

1
วิธีหนึ่งคือส่วนขยายของโครเมี่ยม
Muhammad Umer

คำตอบ:


384

ผมคิดว่าสิ่งที่คุณกำลังทำอยู่ภายใต้นโยบายกำเนิดเดียวกัน นี่ควรเป็นสาเหตุที่คุณได้รับอนุญาตปฏิเสธข้อผิดพลาดประเภท


6
@Pacerier ทางออกที่ดีที่สุดคือการเชื่อมโยงเนื้อหาของ iframe บนเว็บไซต์ของคุณถ้าคุณทำได้ ...
Tracker1

10
@ Tracker1: คุณสามารถแนะนำรูปแบบ / api / design ใด ๆ สำหรับการนำพร็อกซีโซลูชันนี้มาใช้ มีลิงค์ไปสู่ตัวอย่างหรือตัวอย่างการสอนหรือไม่? ฉันพยายามค้นหาแล้ว แต่หาไม่พบ
Umer Hayat

3
ในกรณีนี้เขาหมายถึงใช้เซิร์ฟเวอร์ http ที่ให้บริการหน้าโดเมนของคุณเป็นพรอกซี - ขอเนื้อหาจากเว็บไซต์บุคคลที่สามและส่งต่อในการตอบสนอง http ไปยังลูกค้า ในขณะที่คุณสามารถเดาได้ว่ามันจะส่งผลกระทบต่อการตอบสนองของไซต์ของคุณอย่างรวดเร็วเนื่องจากการร้องขอแบบขนานก่อนหน้านี้จะถูกดำเนินการแทนโดยให้เซิร์ฟเวอร์ของคุณเป็นคอขวด
รูเทอ

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 จากนั้นคุณจะได้รับ IFrame เช่นเดียวกับที่คุณได้รับเนื้อหาที่ไม่ใช้ id อื่น ๆ ด้วย jQuery: คุณเลือกแท็ก <IFrame> ที่เหมาะสมกับ CSS โดยใช้ชื่อคลาสและค่าแอตทริบิวต์เพื่อ จำกัด ให้แคบลงหากจำเป็น
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
ฉันต้องได้รับเนื้อหาเฟรมฉันไม่ให้ตั้ง ..... เมื่อฉันทำข้างต้นมันไม่ทำงานเสมอกลับร่างกายที่ว่างเปล่า
จอร์จฮันนา

3
@DarkoZ อืมจริงๆแล้วคำตอบนี้มาก่อนดังนั้นหากมีสิ่งใดคำตอบอื่น ๆ คือการคัดลอก
michaelpri

@DarkoZ: การแสดงความคิดเห็นต้นฉบับไม่ได้ทำให้ฉันอายคุณ แต่ฉันเสียเวลา 30 วินาทีในการพยายามที่จะเข้าใจปัญหาที่ไม่ใช่ประเด็น :) ดังนั้นการลบการอภิปรายทั้งหมดนี้เกี่ยวกับคำตอบการขโมยความคิดอาจจะดีที่สุด
Dan Dascalescu

ลบความคิดเห็นเพื่อป้องกันความสับสน ขอโทษ.
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: คุณสามารถส่งคุกกี้ข้อมูลที่โพสต์ส่วนหัว HTTP และอะไรก็ได้หากคุณใช้งานด้วยส่วนขยาย curl 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 "). เนื้อหา (). find ()" ไม่ทำงานด้วยเหตุผลบางอย่าง ... สิ่งเดียวกันมากกว่าสองบรรทัดทำ Dunno ทำไม แต่ใช้งานได้
neminem

30

ใช้

iframe.contentWindow.document

แทน

iframe.contentDocument

คำตอบที่ดี ใช้งานได้กับ iFrames ในโดเมนอื่น ฉันลองสิ่งนี้ในคอนโซลบน Safari และ Firefox
Aneil Mallavarapu

12
ฉันเชื่อว่าจะใช้งานได้กับโดเมนอื่นถ้าคุณทำจากคอนโซล จากสคริปต์การเข้าถึงจะไม่ได้รับอนุญาต
yincrash

นี่ควรเป็นคำตอบที่ยอมรับได้ บันทึกชีวิตของฉันและทำงานเมื่อ iframe มาจากโดเมนอื่น แม้ว่าตามที่กล่าวไว้เฉพาะในคอนโซล
Silkfire

สำหรับฉัน iframe.contentWindow.document อาจไม่ทำงาน และเมื่อมันไม่พบฉันพบว่า $ (elem) .contents (). รับ (0) ทำ
elewinso

คุณสามารถเลือก "เอกสารหลัก" ในคอนโซลของเบราว์เซอร์ เมื่อคุณเลือก "top" มันจะไม่ทำงานเป็นการเข้าถึงข้ามทาง หากคุณเลือกที่จะเข้าถึงในนามของเอกสาร iframe แน่นอนว่ามันจะให้สิทธิ์การเข้าถึงแก่คุณ เพียงเพราะคุณไม่ใช่เบราว์เซอร์ แต่เป็นเจ้าของเบราว์เซอร์
Sergei Kovalenko

26

คุณต้องแนบเหตุการณ์เข้ากับตัวจัดการโหลดของ iframe และดำเนินการ 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
หมายเหตุบางประการเกี่ยวกับรหัสนี้: คุณควรใช้ iframe.contentDocument แทน. document และคุณควรใช้. load () แทนที่จะเป็น. ready () เพื่อหลีกเลี่ยงการรอ (ไม่สมบูรณ์ แต่ดีกว่า)
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

ฉันชอบที่จะใช้ตัวแปรอื่น ๆ ในการเข้าถึง จากพาเรนต์คุณสามารถเข้าถึงตัวแปรใน child iframe $ก็เป็นตัวแปรเช่นกันและคุณสามารถรับสิทธิ์ในการโทรได้ window.iframe_id.$

ตัวอย่างเช่นwindow.view.$('div').hide()- ซ่อน div ทั้งหมดใน iframe ด้วย id 'view'

แต่มันไม่ทำงานใน FF เพื่อความเข้ากันได้ดีขึ้นคุณควรใช้

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


2

คุณลองคลาสสิกแล้วรอให้โหลดเสร็จโดยใช้ฟังก์ชั่นพร้อมในตัวของ jQuery หรือไม่

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

K


2
ใช่. ฟังก์ชั่นเตรียมพร้อมเริ่มทำงานเมื่อโหลดเฟรมหลัก - ไม่ใช่เมื่อโหลด iframe การรอคอยดูเหมือนจะเป็นปัญหาเล็กน้อย ฉันคิดว่ามันเกี่ยวกับความปลอดภัยข้ามโดเมน
rz

2

ฉันสร้างรหัสตัวอย่าง ตอนนี้คุณสามารถเข้าใจจากโดเมนที่แตกต่างกันคุณไม่สามารถเข้าถึงเนื้อหาของ iframe .. โดเมนเดียวกันเราสามารถเข้าถึงเนื้อหา iframe

ฉันแบ่งปันรหัสของคุณกับคุณกรุณาเรียกใช้รหัสนี้ตรวจสอบคอนโซล ฉันพิมพ์ภาพ src ที่คอนโซล มีสี่ iframe สอง 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)}, เนื้อหา: 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

ฉันสิ้นสุดที่นี่เพื่อค้นหาเนื้อหาของ iframe ที่ไม่มี jquery ดังนั้นสำหรับคนอื่นที่กำลังมองหานั่นเป็นเพียงแค่นี้:

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.