เรียกใช้โค้ด JavaScript ใน iframe จากหน้าพาเรนต์


615

โดยทั่วไปฉันมีการiframeฝังตัวในหน้าและiframeมีบางจาวาสคริปต์ที่ฉันจำเป็นต้องเรียกใช้จากหน้าหลัก

ตรงกันข้ามตอนนี้ค่อนข้างง่ายที่คุณจะต้องโทร parent.functionName()แต่น่าเสียดายที่ฉันต้องการสิ่งที่ตรงกันข้าม

โปรดทราบว่าปัญหาของฉันไม่ได้มีการเปลี่ยนแปลงแหล่งที่มาURLของแต่การเรียกฟังก์ชั่นที่กำหนดไว้ในiframeiframe


42
บันทึกย่อของคุณเกี่ยวกับ parent.fuctioName () แก้ไขปัญหาการเรียกใช้ฟังก์ชันใน HTML หลักของ iframe Thanx!
CyberFonic

1
หมายเหตุเมื่อทำการดีบั๊กคุณสามารถทำสิ่งต่าง ๆ เช่น window.location.href หรือ parent.location.href เพื่อดู url ของ iframe ถ้าคุณต้องการตรวจสอบว่าคุณมีการอ้างอิงถึง iframe ที่คุณกำลังมองหา
AaronLS

ดูคำตอบของ @le dorfier ... ทำงานได้อย่างสมบูรณ์แบบสำหรับฉัน
ErickBest

คำตอบ:


542

สมมติว่า id ของ iFrame ของคุณคือ "targetFrame" และฟังก์ชั่นที่คุณต้องการโทรคือtargetFunction():

document.getElementById('targetFrame').contentWindow.targetFunction();

นอกจากนี้คุณยังสามารถเข้าถึงกรอบใช้แทนwindow.framesdocument.getElementById

// this option does not work in most of latest versions of chrome and Firefox
window.frames[0].frameElement.contentWindow.targetFunction(); 

3
ทำงานใน FF 7 Chrome 12 8/9 IE และ Safari (ไม่แน่ใจว่ารุ่นนี้)
ดาร์ซี

3
วิธีแก้ปัญหานี้ใช้ไม่ได้กับแกดเจ็ตของฉันนี่คือรหัสของฉันdocument.getElementById('remote_iframe_0').contentWindow.my.create_element_gadg‌​et('verify_user');"remote_iframe_0 ถูกสร้างขึ้นโดยโปรแกรมโดยเซิร์ฟเวอร์ apache shindig แต่window.parent.document.getElementById('remote_iframe_0').contentWindow.my.create_element_gadg‌​et('verify_user');"ใช้ได้
J Bourne

3
@Dirty Henry คุณหมายถึงอะไรโดย "ฟังก์ชั่น jQuery?" jQuery เป็นห้องสมุด JavaScript
Joel Anair

8
@JellicleCat นั่นเป็นเพราะหน้าผู้ปกครองและ iframe มีโฮสต์ที่แตกต่างกันทำให้เป็น cross-origin frame เนื่องจากข้อความบอกคุณ ตราบใดที่โปรโตคอลโดเมนและพอร์ตของหน้าหลักและ iframe ตรงกันทุกอย่างจะทำงานได้ดี
Mark Amery

1
ฉันเพิ่มตัวอย่างเกี่ยวกับวิธีการใช้วิธี window.frames ที่กล่าวถึง
Elijah Lynn

145

มีนิสัยใจคอบางอย่างที่ต้องระวังที่นี่

  1. HTMLIFrameElement.contentWindowอาจเป็นวิธีที่ง่ายกว่า แต่ก็ไม่ใช่คุณสมบัติมาตรฐานและเบราว์เซอร์บางตัวไม่รองรับ นี่เป็นเพราะมาตรฐาน HTML ระดับ DOM 1 ไม่มีอะไรจะพูดเกี่ยวกับwindowวัตถุ

  2. นอกจากนี้คุณยังสามารถลองHTMLIFrameElement.contentDocument.defaultViewใช้เบราว์เซอร์รุ่นเก่าที่อนุญาตให้ใช้งานได้ แต่ IE ไม่สามารถทำได้ ถึงกระนั้นมาตรฐานก็ไม่ได้บอกอย่างชัดเจนว่าคุณได้รับwindowวัตถุกลับมาด้วยเหตุผลเดียวกับ (1) แต่คุณสามารถรับเบราว์เซอร์เพิ่มเติมได้สองสามรุ่นที่นี่ถ้าคุณสนใจ

  3. window.frames['name']การส่งคืนหน้าต่างเป็นอินเทอร์เฟซที่เก่าแก่ที่สุดและน่าเชื่อถือที่สุด แต่คุณต้องใช้แอname="..."ททริบิวต์เพื่อให้ได้เฟรมตามชื่อซึ่งน่าเกลียด / เลิกใช้ / เปลี่ยนผ่านเล็กน้อย ( id="..."น่าจะดีกว่า แต่ IE ก็ไม่ชอบ)

  4. window.frames[number]มีความน่าเชื่อถือมาก แต่การรู้ว่าดัชนีที่ถูกต้องนั้นเป็นกลอุบาย คุณสามารถไปกับสิ่งนี้เช่น ถ้าคุณรู้ว่าคุณมี iframe เพียงอันเดียวในหน้า

  5. เป็นไปได้อย่างสิ้นเชิงที่เด็ก iframe ยังไม่ได้โหลดหรือมีสิ่งอื่นผิดพลาดที่ทำให้ไม่สามารถเข้าถึงได้ คุณอาจพบว่าการย้อนลำดับการติดต่อสื่อสารทำได้ง่ายกว่านั่นคือให้เด็ก iframe แจ้งwindow.parentสคริปต์เมื่อโหลดเสร็จแล้วและพร้อมที่จะโทรกลับ โดยการส่งผ่านหนึ่งในวัตถุของตัวเอง (เช่นฟังก์ชั่นการโทรกลับ) ไปยังสคริปต์ผู้ปกครองนั้นผู้ปกครองสามารถสื่อสารโดยตรงกับสคริปต์ใน iframe ได้โดยไม่ต้องกังวลว่า HTMLIFrameElement เกี่ยวข้องกับอะไร


13
สิ่งที่ยอดเยี่ยม! โดยเฉพาะอย่างยิ่งข้อเสนอแนะของคุณ 5. แสดงว่ามีค่าอย่างยิ่ง มันช่วยแก้ไขอาการปวดหัวได้มากเมื่อฉันพยายามเข้าถึงฟังก์ชั่น iFrame จากผู้ปกครองใน Chrome การส่งผ่านฟังก์ชั่นวัตถุออกจาก iFrame ทำให้มันทำงานเหมือนมีเสน่ห์ใน Chrome, FF และแม้แต่ IE จาก 9 ลงไปที่ 7 และทำให้ง่ายต่อการตรวจสอบว่าฟังก์ชั่นโหลดมาแล้ว ขอบคุณ!
Jpsy

หมายเลข 3 ใช้ได้ แต่ดีกว่าถ้าคุณทำเช่น @le dorfier ใส่ไว้ในความคิดเห็นของเขา สังเกตmethode()ส่วนที่
ErickBest

โปรดทราบว่าเนื่องจากข้อ จำกัด ด้านความปลอดภัยในเบราว์เซอร์ที่ทันสมัย ​​(ทดสอบ FF29 และ Chrome34) มันมีความสำคัญมากสำหรับการโทรหาฟังก์ชั่นของคุณ เพียงแค่เรียกใช้ฟังก์ชันจากแท็กสคริปต์หรือ $ (เอกสาร) .ready () จะไม่ทำงาน แทนที่จะวางสายไว้ในแท็ก onload ของร่างกายหรือใน <a href="javascript:doit();"> ทำ </a> ตามที่แนะนำในที่อื่น ๆ (ดูstackoverflow.com/questions/921387/… ) การส่งการเรียกฟังก์ชันไปยังสคริปต์เป็นการเรียกกลับยังใช้งานได้
titusn

@chovy: ไม่เห็นคำชี้แจงในคำตอบของวิเวกเกี่ยวกับเรื่องนี้
bobince

66

การเรียกฟังก์ชั่น parent JS จากiframeเป็นไปได้ แต่เฉพาะเมื่อทั้งพาเรนต์และเพจที่โหลดในiframeนั้นมาจากโดเมนเดียวกันเช่น abc.com และทั้งคู่กำลังใช้โปรโตคอลเดียวกันนั่นคือทั้งคู่เปิดอยู่http://หรือhttps://หรือ

การโทรจะล้มเหลวในกรณีที่กล่าวถึงด้านล่าง:

  1. เพจระดับบนและหน้า iframe มาจากโดเมนที่ต่างกัน
  2. พวกเขากำลังใช้โปรโตคอลที่แตกต่างกันอย่างใดอย่างหนึ่งอยู่ใน http: // และอื่น ๆ ที่อยู่บน https: //

วิธีหลีกเลี่ยงข้อ จำกัด นี้จะไม่ปลอดภัยอย่างยิ่ง

ตัวอย่างเช่นสมมติว่าฉันลงทะเบียนโดเมน superwinningcontest.com แล้วส่งลิงก์ไปยังอีเมลของผู้คน เมื่อพวกเขาโหลดหน้าหลักขึ้นมาฉันสามารถซ่อนบางอย่างiframeไว้ที่นั่นและอ่านฟีด Facebook ของพวกเขาตรวจสอบธุรกรรม Amazon หรือ PayPal ล่าสุดหรือ - หากพวกเขาใช้บริการที่ไม่ได้ใช้ความปลอดภัยเพียงพอ - โอนเงินออกจากพวกเขา บัญชี นั่นเป็นสาเหตุที่ JavaScript ถูก จำกัด ให้ใช้โดเมนเดียวกันและโปรโตคอลเดียวกัน


6
วิธีแก้ปัญหาคือใช้en.wikipedia.org/wiki/Cross-document_messaging
Laramie

ไม่มีใครทราบว่าโดเมนย่อยอื่นจะทำให้สิ่งนี้ล้มเหลวหรือไม่ ฉันมีปัญหาในการดีบักปัญหาที่ฉันเชื่อว่าเกี่ยวข้องกับสิ่งนี้ - iframe กำลังเรียกใช้ฟังก์ชันหน้าต่างหลัก แต่การโทรไม่ได้เกิดขึ้น
Jake

1
หมายเหตุมันจะล้มเหลวสำหรับหมายเลขพอร์ตที่แตกต่างกัน ie abc.com:80! = abc.com:8080
prasanthv

31

ใน IFRAME ทำให้ฟังก์ชันของคุณเป็นวัตถุหน้าต่างแบบสาธารณะ:

window.myFunction = function(args) {
   doStuff();
}

สำหรับการเข้าถึงจากหน้าหลักให้ใช้สิ่งนี้:

var iframe = document.getElementById("iframeId");
iframe.contentWindow.myFunction(args);

คำตอบที่ดี ไม่แน่ใจเกี่ยวกับการประชุมที่นี่ ฉันมีคำถามติดตาม ถ้าฉันควรเริ่มคำถามใหม่ฉันจะ ฉันมีปัญหาหนึ่งข้อ iframe ของหน้าของฉันบรรจุแบบไดนามิก มันมีปุ่มซึ่งเหตุการณ์ก็เรียกonclick() window.print()มันพิมพ์เนื้อหาของสิ่งที่iframeดีที่สุด แต่เมื่อฟังก์ชั่นสาธารณะของหน้า iframe เรียกwindow.print()และถ้าหน้าหลักเรียกฟังก์ชั่นสาธารณะเนื้อหาของผู้ปกครองจะถูกพิมพ์ ฉันจะรหัสนี้ได้อย่างไรเพื่อให้การเรียกไปยังwindow.print()ฟังก์ชันสาธารณะทำงานเหมือนกับที่onclickเกิดขึ้นในเหตุการณ์
คาร์ล

1
@Karl onclickคุณไม่ต้องการที่จะเรียกร้อง iframe.contentWindow.print()คุณต้องการที่จะเรียก
Tomalak

น่าเสียดายที่มันใช้ไม่ได้ บางทีฉันควรเริ่มคำถามใหม่และบันทึกรหัสของฉัน? ไม่ว่าจะด้วยวิธีใดเนื้อหาของเพจระดับบนก็จะพิมพ์เช่นกัน document.getElementById('myFrame').contentWindow.print();' and the pubic function printContent () `(ไม่ใช่ตัวจัดการเหตุการณ์ oncick) ที่การโทรwindow.print()เรียกว่าวิธีนี้:document.getElementById('myFrame').contentWindow.printContent();
Karl

1
@Karl - ใช่แล้วจะเป็นการดีที่สุดที่จะเริ่มคำถามใหม่ ยกเว้นว่าหน้าต่างหลักอยู่ในโดเมนที่แตกต่างจาก iframe จากนั้นไม่มีอะไรที่คุณเคยพยายามจะทำงาน
Tomalak

สิ่งที่ฉันรายงานที่นี่น่าจะเป็นปัญหา IE (การทดสอบใน IE8) ไม่มีปัญหาใน Chrome รุ่นปัจจุบัน ยังไม่ได้ทดสอบเบราว์เซอร์อื่น ๆ สำหรับผู้ที่สนใจดูjsFiddleนี้(ฉันคิดว่านี่เป็นตัวอย่างที่ดีของการโหลด iframe แบบไดนามิกและการเรียกฟังก์ชันสาธารณะจากผู้ปกครอง)
Karl

20

หากเป้าหมายของ iFrame และเอกสารที่มีอยู่ในโดเมนที่แตกต่างกันวิธีการโพสต์ก่อนหน้านี้อาจไม่ทำงาน แต่มีวิธีแก้ไข:

ตัวอย่างเช่นหากเอกสาร A มีองค์ประกอบ iframe ที่มีเอกสาร B และสคริปต์ในเอกสาร A การเรียก postMessage () บนวัตถุหน้าต่างของเอกสาร B ดังนั้นเหตุการณ์ข้อความจะถูกไล่ออกจากวัตถุนั้นทำเครื่องหมายว่ามาจากหน้าต่างของ document A. สคริปต์ในเอกสาร A อาจมีลักษณะดังนี้:

var o = document.getElementsByTagName('iframe')[0];
o.contentWindow.postMessage('Hello world', 'http://b.example.org/');

เพื่อลงทะเบียนตัวจัดการเหตุการณ์สำหรับเหตุการณ์ที่เข้ามาสคริปต์จะใช้ addEventListener () (หรือกลไกที่คล้ายกัน) ตัวอย่างเช่นสคริปต์ในเอกสาร B อาจมีลักษณะดังนี้:

window.addEventListener('message', receiver, false);
function receiver(e) {
  if (e.origin == 'http://example.com') {
    if (e.data == 'Hello world') {
      e.source.postMessage('Hello', e.origin);
    } else {
      alert(e.data);
    }
  }
}

สคริปต์นี้ตรวจสอบโดเมนก่อนว่าเป็นโดเมนที่คาดไว้จากนั้นตรวจดูข้อความที่แสดงต่อผู้ใช้หรือตอบกลับโดยส่งข้อความกลับไปที่เอกสารที่ส่งข้อความตั้งแต่แรก

ผ่านhttp://dev.w3.org/html5/postmsg/#web-messaging


1
easyXDMให้สิ่งที่เป็นนามธรรมผ่าน PostMessage สำหรับเบราว์เซอร์รุ่นเก่า (รวมถึงทางเลือก Flash (LocalConnection) สำหรับไดโนเสาร์ปากแข็ง
JonnyReeves

1
เยี่ยมมาก ... หลังจากลองตอบคำถามข้างต้นในที่สุดฉันก็ได้รับคำตอบขอบคุณ!
vkGunasekaran

9

เพียงบันทึกฉันได้พบปัญหาเดียวกันวันนี้ แต่เวลานี้หน้าถูกฝังในวัตถุไม่ใช่ iframe (เนื่องจากเป็นเอกสาร XHTML 1.1) นี่คือวิธีการทำงานกับวัตถุ:

document
  .getElementById('targetFrame')
  .contentDocument
  .defaultView
  .targetFunction();

(ขออภัยสำหรับตัวแบ่งบรรทัดที่น่าเกลียดไม่พอดีในบรรทัดเดียว)


8

IFRAME ควรอยู่ในframes[]ชุดสะสม ใช้สิ่งที่ชอบ

frames['iframeid'].method();

คำตอบนี้สามารถใช้ข้อมูลเพิ่มเติมได้อย่างแน่นอนเนื่องจากมีข้อควรพิจารณาอื่น ๆ สำหรับหนึ่งฉันคิดว่า dev ต้องสร้างmethodคุณสมบัติของwindowวัตถุของ iframe
matty

8

Quirksmode มีโพสต์เกี่ยวกับเรื่องนี้การโพสต์เกี่ยวกับเรื่องนี้

เนื่องจากหน้านี้เสียและสามารถเข้าถึงได้ผ่าน archive.org เท่านั้นฉันจึงทำซ้ำที่นี่:

IFrames

ในหน้านี้ฉันให้ภาพรวมโดยย่อของการเข้าถึง iframes จากหน้าเว็บที่พวกเขาเปิดอยู่ ไม่น่าแปลกใจที่มีข้อควรพิจารณาบางอย่างเกี่ยวกับเบราว์เซอร์

iframe เป็นเฟรมแบบอินไลน์เฟรมที่ในขณะที่มีหน้าที่แยกออกมาอย่างสมบูรณ์พร้อม URL ของตัวเองจะถูกวางไว้ในหน้า HTML อื่น สิ่งนี้ให้ความเป็นไปได้ที่ดีมากในการออกแบบเว็บ ปัญหาคือการเข้าถึง iframe เช่นโหลดหน้าใหม่เข้ามา หน้านี้อธิบายวิธีการทำ

กรอบหรือวัตถุ?

คำถามพื้นฐานคือ iframe ถูกมองว่าเป็นเฟรมหรือเป็นวัตถุ

  • ตามที่อธิบายไว้ในหน้าบทนำสู่เฟรมหากคุณใช้เฟรมเบราว์เซอร์จะสร้างลำดับชั้นของเฟรมให้คุณ (top.frames[1].frames[2]และเช่นนั้น) iframe เหมาะสมกับลำดับชั้นของเฟรมนี้หรือไม่?
  • หรือเบราว์เซอร์เห็น iframe เป็นเพียงวัตถุอื่นวัตถุที่เกิดขึ้นมีคุณสมบัติ src หรือไม่ ในกรณีนี้เราต้องใช้การเรียก DOM แบบมาตรฐาน(เช่นdocument.getElementById('theiframe'))เพื่อเข้าถึง) ในเบราว์เซอร์ทั่วไปอนุญาตให้ใช้มุมมองทั้งสองบน iframes 'ของจริง' (ฮาร์ดโค้ด) แต่สร้าง iframe ไม่ได้เนื่องจากเฟรม

แอตทริบิวต์ NAME

กฎที่สำคัญที่สุดคือการให้ iframe ใด ๆ ที่คุณสร้างแอตทริบิวต์แม้ว่าคุณจะยังใช้nameid

<iframe src="iframe_page1.html"
    id="testiframe"
    name="testiframe"></iframe>

เบราว์เซอร์ส่วนใหญ่ต้องการnameคุณลักษณะเพื่อให้ iframe เป็นส่วนหนึ่งของลำดับชั้นของเฟรม เบราว์เซอร์บางตัว (โดยเฉพาะ Mozilla) จำเป็นต้องใช้idเพื่อให้สามารถเข้าถึง iframe เป็นวัตถุได้ ด้วยการกำหนดแอตทริบิวต์ทั้งสองให้กับ iframe ทำให้ตัวเลือกของคุณเปิดอยู่ แต่อยู่ไกลมีความสำคัญมากกว่าnameid

เข้าไป

ไม่ว่าคุณจะเข้าถึง iframe เป็นวัตถุและเปลี่ยนมันsrcหรือคุณเข้าถึง iframe เป็นเฟรมและเปลี่ยนมันlocation.hrefเป็นกรอบและการเปลี่ยนแปลงของ

document.getElementById ('iframe_id'). src = 'newpage.html'; frames ['iframe_name']. location.href = 'newpage.html'; ไวยากรณ์ของเฟรมเป็นที่นิยมมากกว่าเนื่องจาก Opera 6 รองรับ แต่ไม่ใช่ไวยากรณ์ของวัตถุ

การเข้าถึง iframe

ดังนั้นสำหรับประสบการณ์ข้ามเบราว์เซอร์ที่สมบูรณ์คุณควรตั้งชื่อ iframe และใช้

frames['testiframe'].location.href

วากยสัมพันธ์ เท่าที่ฉันรู้ว่าสิ่งนี้ใช้ได้เสมอ

การเข้าถึงเอกสาร

การเข้าถึงเอกสารภายใน iframe นั้นค่อนข้างง่ายหากคุณใช้nameคุณลักษณะนี้ การนับจำนวนของการเชื่อมโยงในเอกสารใน iframe frames['testiframe'].document.links.lengthที่ทำ

สร้าง iframes

เมื่อคุณสร้าง iframe ผ่านW3C DOMนั้น iframe จะไม่ถูกป้อนเข้าไปในframesอาร์เรย์ทันทีและframes['testiframe'].location.hrefไวยากรณ์จะไม่ทำงานทันที เบราว์เซอร์ต้องการเวลาเล็กน้อยก่อนที่ iframe จะปรากฎในอาร์เรย์เวลาที่สคริปต์ไม่สามารถทำงานได้

document.getElementById('testiframe').srcไวยากรณ์ทำงานได้ดีในทุกสถานการณ์

targetแอตทริบิวต์ของการเชื่อมโยงไม่ทำงานทั้งที่มี iframe ที่สร้างยกเว้นในโรงละครโอเปราแม้ว่าฉันให้สร้าง iframe ทั้งฉันและnameid

การขาดtargetการสนับสนุนหมายความว่าคุณต้องใช้ JavaScript เพื่อเปลี่ยนเนื้อหาของ iframe ที่สร้างขึ้น แต่เนื่องจากคุณต้องการ JavaScript ต่อไปเพื่อสร้างมันขึ้นมาตั้งแต่แรกฉันไม่เห็นปัญหานี้มากนัก

ขนาดตัวอักษรใน iframes

บั๊ก Explorer 6 ที่อยากรู้อยากเห็นเท่านั้น:

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


5
ดูเหมือนว่าลิงก์จะใช้งานไม่ได้
zaphod

1
และเพื่อทำให้เรื่องแย่ลงฉันไม่สามารถหาหน้าเว็บที่เกี่ยวข้องในโหมด quirksmode ได้
stricjux


7

ฉันพบวิธีแก้ปัญหาที่สง่างามทีเดียว

อย่างที่คุณพูดมันค่อนข้างง่ายที่จะรันโค้ดที่อยู่ในเอกสารพาเรนต์ และนั่นคือฐานของรหัสของฉันทำตรงข้าม

เมื่อโหลด iframe ของฉันฉันเรียกใช้ฟังก์ชันที่อยู่บนเอกสารพาเรนต์ส่งผ่านอาร์กิวเมนต์เพื่ออ้างอิงถึงฟังก์ชันโลคัลซึ่งอยู่ในเอกสารของ iframe ตอนนี้เอกสารพาเรนต์มีการเข้าถึงฟังก์ชัน iframe โดยตรงผ่านการอ้างอิงนี้

ตัวอย่าง:

บนผู้ปกครอง:

function tunnel(fn) {
    fn();
}

ใน iframe:

var myFunction = function() {
    alert("This work!");
}

parent.tunnel(myFunction);

เมื่อโหลด iframe จะเรียก parent.tunnel (YourFunctionReference) ซึ่งจะเรียกใช้ฟังก์ชันที่ได้รับในพารามิเตอร์

ง่ายโดยไม่ต้องจัดการกับวิธีการที่ไม่ได้มาตรฐานจากเบราว์เซอร์ต่างๆ


สวัสดีคุณสามารถยืนยันได้ว่า "วิธีนี้ง่ายโดยไม่ต้องจัดการกับวิธีที่ไม่ได้มาตรฐานจากเบราว์เซอร์ต่างๆ"
Milche Patern

1
ฉันใช้วิธีนี้กับโครงการต่าง ๆ ดูเหมือนว่าจะทำงานได้ดีมาก ฉันไม่ได้ทดสอบเบราว์เซอร์ทั้งหมดเป็นการส่วนตัว แต่ฉันไม่เคยได้รับรายงานข้อผิดพลาดเลย
Julien L

ทำงานได้อย่างมีเสน่ห์ IE 11, Chrome ~ 50
Augustas

1
เดาว่าไม่ใช่ข้ามโดเมนใช่ไหม?
Tushar Shukla

@TusharShukla แต่น่าเสียดายที่ไม่ใช่มันไม่ใช่
jeff-h

6

คำตอบบางส่วนเหล่านี้ไม่ได้แก้ไขปัญหา CORS หรือไม่ชัดเจนที่คุณวางโค้ดไว้เพื่อให้การสื่อสารเป็นไปได้

นี่คือตัวอย่างที่เป็นรูปธรรม สมมติว่าฉันต้องการคลิกปุ่มบนเพจระดับบนและทำสิ่งนั้นใน iframe นี่คือวิธีที่ฉันจะทำมัน

parent_frame.html

<button id='parent_page_button' onclick='call_button_inside_frame()'></button>

function call_button_inside_frame() {
   document.getElementById('my_iframe').contentWindow.postMessage('foo','*');
}

iframe_page.html

window.addEventListener("message", receiveMessage, false);

function receiveMessage(event)
    {
      if(event) {
        click_button_inside_frame();
    }
}

function click_button_inside_frame() {
   document.getElementById('frame_button').click();
}

หากต้องการไปยังทิศทางอื่น (คลิกปุ่มภายใน iframe to call method นอก iframe) เพียงแค่เปลี่ยนตำแหน่งที่โค้ดขนาดสั้นนั้นอยู่

document.getElementById('my_iframe').contentWindow.postMessage('foo','*');

สำหรับสิ่งนี้:

window.parent.postMessage('foo','*')

4

ดำเนินการต่อกับคำตอบของ JoelAnair :

เพื่อความทนทานยิ่งขึ้นให้ใช้ดังนี้:

var el = document.getElementById('targetFrame');

if(el.contentWindow)
{
   el.contentWindow.targetFunction();
}
else if(el.contentDocument)
{
   el.contentDocument.targetFunction();
}

ทำงานเหมือนมีเสน่ห์ :)


3

คำตอบของ Folin Nitin Bansal

และสำหรับความทนทานที่มากขึ้น:

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 el = document.getElementById('targetFrame');

var frame_win = getIframeWindow(el);

if (frame_win) {
  frame_win.targetFunction();
  ...
}
...


2

สิ่งที่เหมือนกัน แต่วิธีที่ง่ายขึ้นเล็กน้อยจะเป็นวิธีการรีเฟรชหน้าผู้ปกครองจากหน้าภายใน iframe เพียงเรียกใช้ฟังก์ชันของเพจระดับบนเพื่อเรียกใช้ฟังก์ชันจาวาสคริปต์เพื่อโหลดหน้าเว็บซ้ำ:

window.location.reload();

หรือทำสิ่งนี้โดยตรงจากหน้าใน iframe:

window.parent.location.reload();

ทั้งงาน



1

หากคุณต้องการเรียกใช้ฟังก์ชัน JavaScript บนพาเรนต์จาก iframe ที่สร้างโดยฟังก์ชันอื่นเช่น shadowbox หรือ lightbox

คุณควรพยายามใช้ประโยชน์จากwindowวัตถุและเรียกใช้ฟังก์ชันแม่:

window.parent.targetFunction();

ฉันเชื่อว่า OP กำลังพยายามไปในทิศทางอื่น
CommandZ

-3

ใช้ฟังก์ชันต่อไปนี้เพื่อเรียกใช้ฟังก์ชันของเฟรมในเพจระดับบน

parent.document.getElementById('frameid').contentWindow.somefunction()
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.