Phát hiện khi nội dung Iframe đã tải (Trình duyệt chéo)


90

Tôi đang cố gắng phát hiện khi một iframe và nội dung của nó đã tải nhưng không gặp nhiều may mắn. Ứng dụng của tôi nhận một số đầu vào trong các trường văn bản trong cửa sổ mẹ và cập nhật iframe để cung cấp 'bản xem trước trực tiếp'

Tôi đã bắt đầu với mã sau (YUI) để phát hiện khi sự kiện tải iframe xảy ra.

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

'khung xem trước' là ID của khung nội tuyến của tôi và tôi đang sử dụng YUI để đính kèm trình xử lý sự kiện. Tuy nhiên, việc cố gắng truy cập phần nội dung trong lệnh gọi lại của tôi (khi tải iframe) không thành công, tôi nghĩ vì iframe tải trước khi trình xử lý sự kiện sẵn sàng. Mã này hoạt động nếu tôi trì hoãn việc tải iframe bằng cách đặt tập lệnh php tạo ra nó ở chế độ ngủ.

Về cơ bản, tôi đang hỏi đâu là cách tiếp cận chính xác trên các trình duyệt để phát hiện khi iframe đã tải và tài liệu của nó đã sẵn sàng?


1
Bắt đầu với YUI là một ý tưởng tồi (cũng như bất kỳ thư viện JS nào khác). Tại sao? Bởi vì bạn không thể biết thư viện đó đang làm gì. Nếu họ không thể hỗ trợ "tải" đầy đủ, tốt hơn bạn nên tự mình làm điều đó bằng javascript rõ ràng và dễ đọc.
Christian

2
Bạn thường có thể đọc mã nguồn của thư viện @Christian. Tôi thấy điều này thường cung cấp cho bạn các mẹo tuyệt vời về cách tự thực hiện bất kể sau đó bạn có sử dụng cách triển khai của chúng hay không.
AJP

@AJP Bạn đã hiểu sai quan điểm của tôi. Nếu bạn đang làm điều gì đó mà bạn không chắc chắn, tốt hơn là nên có ít mã hơn để có ít chỗ cho lỗi hơn.
Christian

2
Phụ thuộc vào cách bạn nhìn vào nó. Tôi biết rằng xử lý sự kiện của YUI đã hoạt động vào thời điểm đó, vì vậy tôi không phải lo lắng về phần đó của mã. Tôi cũng biết cách viết trình xử lý addEvent của riêng mình, không phải là nó hoạt động tốt hơn YUI về vấn đề này.
David Snabel-Caunt

1
@Nico Câu hỏi đề cập đến YUI và $ là bí danh cho trình bao bọc Dom của YUI.
David Snabel-Caunt

Câu trả lời:


73

để phát hiện khi iframe đã tải và tài liệu của nó đã sẵn sàng chưa?

Thật lý tưởng nếu bạn có thể lấy iframe cho bạn biết chính nó từ một tập lệnh bên trong khung. Ví dụ, nó có thể gọi trực tiếp một hàm cha để thông báo rằng nó đã sẵn sàng. Luôn luôn cần sự cẩn thận khi thực thi mã xuyên khung vì mọi thứ có thể xảy ra theo thứ tự mà bạn không mong đợi. Một thay thế khác là đặt 'var isready = true;' trong phạm vi riêng của nó và có đoạn mã cha mẹ cho 'contentWindow.isready' (và thêm trình xử lý onload nếu không).

Nếu vì lý do nào đó, việc tài liệu iframe cùng hoạt động là không thực tế, thì bạn đã gặp phải vấn đề load-race truyền thống, cụ thể là ngay cả khi các phần tử nằm ngay cạnh nhau:

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

không có gì đảm bảo rằng mục sẽ không được tải vào thời điểm tập lệnh thực thi.

Các cách thoát khỏi cuộc đua tải là:

  1. trên IE, bạn có thể sử dụng thuộc tính 'readyState' để xem liệu thứ gì đó đã được tải chưa;

  2. nếu mục chỉ có sẵn khi bật JavaScript là được chấp nhận, bạn có thể tạo động, đặt chức năng sự kiện 'onload' trước khi đặt nguồn và thêm vào trang. Trong trường hợp này, nó không thể được tải trước khi lệnh gọi lại được thiết lập;

  3. theo cách cũ để đưa nó vào phần đánh dấu:

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

Các trình xử lý nội tuyến 'onsomething' trong HTML hầu như luôn luôn là điều sai và cần tránh, nhưng trong trường hợp này, đôi khi đó là lựa chọn ít tệ nhất.


Cảm ơn. Giải pháp của tôi kiểm tra readyState (nếu tồn tại), sau đó đến độ dài phần tử nội dung bên trongHTML để xem nó đã được tải chưa. Nếu không, hãy đính kèm trình xử lý sự kiện tải. Có vẻ hoạt động ổn
David Snabel-Caunt

8
-1 - sự kiện nội tuyến không phải là "xấu", đó chỉ là mốt hiện nay. Trên thực tế, các sự kiện nội tuyến dễ gỡ lỗi và dễ hiểu hơn, không giống như các đối tác ma thuật của chúng (mặt khác, dễ gắn, xếp chồng và sử dụng liền mạch hơn).
Christian

1
@Christian, các sự kiện nội tuyến cũng là lựa chọn tốt nhất khi bạn cần đính kèm một sự kiện vào mọi phần tử của một danh sách rất dài. Vì bạn đã lặp lại để tạo danh sách ở phía máy chủ, nên đính kèm sự kiện nội tuyến cũng hiệu quả hơn nhiều.
haknick

16
@haknick Bạn có muốn sử dụng một trình nghe sự kiện duy nhất trong danh sách và sử dụng đại biểu sự kiện không? Điều này sẽ hiệu quả hơn.
David Snabel-Caunt

4
Điều này sẽ không hoạt động nếu iframe là miền chéo. Tập lệnh bên trong iframe không thể truy cập cửa sổ mẹ.
Sudheer Someshwara,

48

Xem bài đăng trên blog này . Nó sử dụng jQuery, nhưng nó sẽ giúp bạn ngay cả khi bạn không sử dụng nó.

Về cơ bản, bạn thêm điều này vào document.ready()

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

Thật thú vị, nhưng vấn đề tôi gặp phải là với các sự kiện tải và thời gian. Tôi đang lắng nghe sự kiện tải theo lời khuyên của bài báo đó.
David Snabel-Caunt

tôi đã thử cái này với console.log. nó được ghi lại sau khi iframe được tải.
shorif2000,

12

Đối với những người sử dụng React, việc phát hiện một sự kiện tải iframe có cùng nguồn gốc cũng đơn giản như thiết lập trình xử lý onLoadsự kiện trên phần tử iframe.

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


Có thể onLoadsự kiện chỉ có thể kích hoạt cho iframe cùng nguồn gốc?
L_K

2

Đối với bất kỳ ai sử dụng Ember, điều này sẽ hoạt động như mong đợi:

<iframe onLoad={{action 'actionName'}}  frameborder='0' src={{iframeSrc}} />
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.