ตรวจจับเมื่อโหลดเนื้อหา Iframe (ข้ามเบราว์เซอร์)


91

ฉันกำลังพยายามตรวจสอบเมื่อ iframe และเนื้อหาโหลด แต่ไม่มีโชคมากนัก แอปพลิเคชันของฉันป้อนข้อมูลในช่องข้อความในหน้าต่างหลักและอัปเดต iframe เพื่อให้ 'แสดงตัวอย่างสด'

ฉันเริ่มต้นด้วยรหัสต่อไปนี้ (YUI) เพื่อตรวจจับเมื่อเหตุการณ์โหลด iframe เกิดขึ้น

$E.on('preview-pane', 'load', function(){
    previewBody = $('preview-pane').contentWindow.document.getElementsByTagName('body')[0];
}

'Preview-pane' คือ ID ของ iframe ของฉันและฉันใช้ YUI เพื่อแนบตัวจัดการเหตุการณ์ อย่างไรก็ตามการพยายามเข้าถึงเนื้อหาในการเรียกกลับ (เมื่อโหลด iframe) ล้มเหลวฉันคิดว่าเป็นเพราะ iframe โหลดก่อนที่ตัวจัดการเหตุการณ์จะพร้อม รหัสนี้ใช้งานได้หากฉันชะลอการโหลด iframe โดยสร้างสคริปต์ php ที่สร้างโหมดสลีป

โดยทั่วไปฉันกำลังถามว่าอะไรคือแนวทางที่ถูกต้องในเบราว์เซอร์ในการตรวจจับเมื่อ iframe โหลดและเอกสารพร้อมแล้ว?


1
การเริ่มต้นด้วย YUI เป็นความคิดที่ไม่ดี (เช่นเดียวกับไลบรารี JS อื่น ๆ ) ทำไม? เพราะคุณไม่สามารถรู้ได้ว่าห้องสมุดกำลังทำอะไรอยู่ หากไม่สามารถรองรับ "โหลด" ได้เต็มที่คุณควรทำด้วยตัวเองด้วยจาวาสคริปต์ที่ชัดเจนและอ่านได้
คริสเตียน

2
คุณสามารถอ่านซอร์สโค้ดของไลบรารี @Christian ได้บ่อยครั้ง ฉันพบว่าสิ่งนี้มักจะให้คำแนะนำที่ดีเกี่ยวกับวิธีการทำด้วยตัวเองไม่ว่าคุณจะใช้การติดตั้งหรือไม่ก็ตาม
AJP

@AJP คุณเข้าใจผิดประเด็นของฉัน หากคุณกำลังทำบางสิ่งที่คุณไม่แน่ใจควรมีโค้ดน้อยลงจะดีกว่าเพื่อให้มีพื้นที่สำหรับข้อผิดพลาดน้อยลง
Christian

2
ขึ้นอยู่กับว่าคุณจะมองมันอย่างไร ฉันรู้ว่าการจัดการเหตุการณ์ของ YUI ทำงานได้ในเวลานั้นดังนั้นฉันจึงไม่ต้องกังวลกับส่วนนั้นของโค้ด ฉันยังรู้วิธีเขียนตัวจัดการ addEvent ของตัวเองไม่ใช่ว่ามันทำงานได้ดีกว่า YUI เกี่ยวกับปัญหานี้
David Snabel-Caunt

1
@Nico คำถามอ้างถึง YUI และ $ เป็นนามแฝงของ Dom wrapper ของ YUI
David Snabel-Caunt

คำตอบ:


73

เพื่อตรวจจับเมื่อโหลด iframe และเอกสารพร้อม?

เหมาะอย่างยิ่งหากคุณสามารถรับ iframe เพื่อบอกตัวคุณเองจากสคริปต์ภายในเฟรม ตัวอย่างเช่นมันสามารถเรียกใช้ฟังก์ชันหลักโดยตรงเพื่อบอกว่าพร้อม จำเป็นต้องใช้ความระมัดระวังในการเรียกใช้รหัสข้ามเฟรมเนื่องจากสิ่งต่างๆสามารถเกิดขึ้นได้ตามลำดับที่คุณไม่คาดคิด อีกทางเลือกหนึ่งคือการตั้งค่า 'var isready = true;' ในขอบเขตของตัวเองและมีสคริปต์หลัก sniff สำหรับ 'contentWindow.isready' (และเพิ่มตัวจัดการ onload ถ้าไม่มี)

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

<img id="x" ... />
<script type="text/javascript">
    document.getElementById('x').onload= function() {
        ...
    };
</script>

ไม่มีการรับประกันว่าไอเท็มจะไม่โหลดตามเวลาที่สคริปต์ทำงาน

วิธีการออกจากการแข่งขันคือ:

  1. บน IE คุณสามารถใช้คุณสมบัติ 'readyState' เพื่อดูว่ามีบางสิ่งถูกโหลดหรือไม่

  2. หากยอมรับรายการที่มีเฉพาะเมื่อเปิดใช้งาน JavaScript คุณสามารถสร้างแบบไดนามิกโดยตั้งค่าฟังก์ชันเหตุการณ์ 'onload' ก่อนตั้งค่าแหล่งที่มาและต่อท้ายหน้า ในกรณีนี้จะไม่สามารถโหลดได้ก่อนที่จะตั้งค่าการโทรกลับ

  3. วิธีที่โรงเรียนเก่ารวมไว้ในมาร์กอัป:

    <img onload="callback(this)" ... />

ตัวจัดการ 'onsomething' แบบอินไลน์ใน HTML มักเป็นสิ่งที่ผิดและควรหลีกเลี่ยง แต่ในกรณีนี้บางครั้งก็เป็นตัวเลือกที่แย่ที่สุด


ขอบคุณ. โซลูชันของฉันตรวจสอบ readyState (ถ้ามี) จากนั้นองค์ประกอบของร่างกาย innerHTML ความยาวเพื่อดูว่ามีการโหลดหรือไม่ ถ้าไม่มีให้แนบตัวจัดการเหตุการณ์โหลด ดูเหมือนจะใช้ได้ดี
David Snabel-Caunt

8
-1 - เหตุการณ์แบบอินไลน์ไม่ได้ "แย่" นั่นเป็นเพียงแฟชั่นในปัจจุบัน ในความเป็นจริงเหตุการณ์แบบอินไลน์นั้นง่ายต่อการดีบั๊กและทำความเข้าใจซึ่งแตกต่างจากคู่เวทย์มนตร์ของพวกเขา (ซึ่งในทางกลับกันนั้นง่ายต่อการแนบซ้อนและใช้งานได้อย่างราบรื่น)
คริสเตียน

1
@Christian เหตุการณ์แบบอินไลน์ยังเป็นตัวเลือกที่ดีที่สุดเมื่อคุณต้องการแนบเหตุการณ์กับทุกองค์ประกอบของรายการที่ยาวมาก เนื่องจากคุณกำลังวนลูปเพื่อสร้างรายการบนฝั่งเซิร์ฟเวอร์อยู่แล้วการแนบอินไลน์อีเวนต์ก็มีประสิทธิภาพมากขึ้นเช่นกัน
haknick

16
@haknick คุณไม่ต้องการใช้ผู้ฟังเหตุการณ์เดียวในรายการและใช้ตัวแทนเหตุการณ์หรือไม่? สิ่งนี้จะมีประสิทธิภาพมากขึ้น
David Snabel-Caunt

4
สิ่งนี้จะใช้ไม่ได้หาก iframe เป็นแบบข้ามโดเมน สคริปต์ภายใน iframe ไม่สามารถเข้าถึงหน้าต่างหลัก
Sudheer Someshwara

48

ดูนี้โพสต์บล็อก ใช้ jQuery แต่ควรช่วยคุณแม้ว่าคุณจะไม่ได้ใช้งานก็ตาม

โดยทั่วไปคุณจะเพิ่มสิ่งนี้ลงในไฟล์ document.ready()

$('iframe').load(function() {
    RunAfterIFrameLoaded();
});

น่าสนใจ แต่ปัญหาที่ฉันมีคือเหตุการณ์และเวลาในการโหลด ฉันกำลังฟังเหตุการณ์การโหลดตามคำแนะนำของบทความนั้น
David Snabel-Caunt

ฉันได้ลองใช้กับconsole.log. มันจะถูกบันทึกหลังจากโหลด iframe แล้ว
shorif2000

12

สำหรับผู้ที่ใช้ React การตรวจจับเหตุการณ์โหลด iframe ที่มาเดียวกันนั้นทำได้ง่ายเพียงแค่ตั้งค่าonLoadevent listener บนองค์ประกอบ iframe

<iframe src={'path-to-iframe-source'} onLoad={this.loadListener} frameBorder={0} />


สามารถonLoadเหตุการณ์เดียวสามารถเรียกเดียวกันแหล่งกำเนิด iframe ใช่หรือไม่
L_K

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