Cách truy cập Iframe gốc từ JavaScript


170

Chà, tôi có một IFrame, gọi một trang tên miền giống nhau. Vấn đề của tôi là tôi muốn truy cập một số thông tin từ Iframe gốc này từ trang được gọi này (từ JavaScript). Làm cách nào tôi có thể truy cập Iframe này?

Chi tiết: Có một số Iframe giống như trang này, có thể tải cùng một trang, vì tôi đang lập trình môi trường Windows. Tôi dự định đóng Iframe này, đó là lý do tại sao tôi cần biết tôi nên đóng cái gì từ bên trong anh ta. Tôi có một mảng giữ các tham chiếu đến các Iframes này.

EDIT: Có iframe được tạo động


ngay cả khi iframe được tạo động, bạn có thể chỉ định id duy nhất mới bằng cách sử dụng một số loại bộ đếm, cuối cùng bạn không cần biết ID, nhưng bạn có thể tìm kiếm dễ dàng, xem câu trả lời của tôi.
Akash Kava

Câu trả lời:


138

Ngoài ra, bạn có thể đặt tên và ID thành các giá trị bằng nhau

<iframe id="frame1" name="frame1" src="any.html"></iframe>

vì vậy bạn sẽ có thể sử dụng mã tiếp theo trong trang con

parent.document.getElementById(window.name);

16
Có thể nó không rõ ràng đối với mọi người, nhưng với phương pháp này, bạn có thể truy cập một đối tượng thư viện của cha mẹ (chỉ khi cha mẹ đã tải thư viện). Ví dụ: truy cập jQuery với cha mẹ. $ ('#
Something

1
Giải pháp này tương thích với chế độ quirks tương thích IE5 +.
Slayner

Ngay cả trong năm 2016, điều này hoạt động tuyệt vời như là một phần của giải pháp cho vấn đề IE in nội dung iframequá nhỏ. Nhưng tại sao nó hoạt động? window.nametrả về một chuỗi. Có gì khác khi sử dụng thay window.namevì chỉ chuyển tên id thành một chuỗi không hoạt động.)?
Karl

3
Xin chào, nó không chạy với Chrome 59 ..: VM111: 1 Uncaught DOMException: Bị chặn một khung có nguồn gốc " xxx " khi truy cập vào khung có nguồn gốc chéo.
Didier68

Chrome xem các tệp trong cùng thư mục là nguồn gốc chéo nếu không đặt CORS. Họ nói nó là để bảo mật. Cài đặt CORS cần một máy chủ. Cung cấp cho người dùng thông báo để thiết lập máy chủ hoặc thay đổi trình duyệt nếu Chrome được phát hiện.

90

Đơn giản chỉ cần gọi window.frameElementtừ trang đóng khung của bạn. Nếu trang không nằm trong một khung thì frameElementsẽ có null.

Một cách khác (lấy phần tử cửa sổ bên trong một khung ít tầm thường hơn) nhưng để hoàn thiện:

/**
 * @param f, iframe or frame element
 * @return Window object inside the given frame
 * @effect will append f to document.body if f not yet part of the DOM
 * @see Window.frameElement
 * @usage myFrame.document = getFramedWindow(myFrame).document;
 */
function getFramedWindow(f)
{
    if(f.parentNode == null)
        f = document.body.appendChild(f);
    var w = (f.contentWindow || f.contentDocument);
    if(w && w.nodeType && w.nodeType==9)
        w = (w.defaultView || w.parentWindow);
    return w;
}

2
Cảm ơn! Hoạt động trên IE 6+, FF và Chrome!
rustyx

11
window.frameElementtrả về nullkhi cửa sổ và iframe có các miền khác nhau, tức là nhắn tin có nguồn gốc chéo.
Qwerty

@Qwerty bạn đã tìm được giải pháp nào chưa?
Ajay Patidar

@AjayPatidar Tôi nghĩ rằng tôi đã từ bỏ. :(
Qwerty

78

Tôi sẽ khuyên bạn nên sử dụng API postMessage .

Trong iframe của bạn, hãy gọi:

window.parent.postMessage({message: 'Hello world'}, 'http://localhost/');

Trong trang bạn đang bao gồm iframe bạn có thể nghe các sự kiện như thế này:

window.addEventListener('message', function(event) {
      if(event.origin === 'http://localhost/')
      {
        alert('Received message: ' + event.data.message);
      }
      else
      {
        alert('Origin not allowed!');
      }

    }, false);

Nhân tiện, cũng có thể thực hiện các cuộc gọi đến các cửa sổ khác, và không chỉ iframe.

Đọc thêm về API postMessage trên blog John Resigs tại đây


7
Tôi nghĩ rằng đây rõ ràng là câu trả lời tốt nhất, <iframe>nội dung không cần phải biết gì về phụ huynh và ngược lại. Họ chỉ phải tuân theo hợp đồng tin nhắn đơn giản. Tuyệt vời!
mfeineis

1
<Iframe> vẫn phải biết tên miền của cha mẹ, phải không?
Homr Zodyssey

1
@HomrZodyssey Tên miền mẹ chỉ có sẵn như một cơ chế an toàn, nếu không biết, bạn có thể đặt '*'.
Amir Ali Akbari

Sử dụng '*'cho khách hàng. Mọi giải pháp khác đều có lỗi trên trình duyệt Chrome xử lý các tệp trong thư mục máy khách là Không cùng nguồn gốc vì máy chủ không được thiết lập. Đây là giải pháp tốt nhất và duy nhất : dyn-web.com/tutorials/iframes/postmessage

30

Câu hỏi cũ, nhưng tôi chỉ gặp vấn đề tương tự và tìm cách lấy iframe. Đó chỉ đơn giản là vấn đề lặp qua các khung [] của cửa sổ cha mẹ và kiểm tra từng nội dung của khung hìnhWindow đối với cửa sổ nơi mã của bạn đang chạy. Thí dụ:

var arrFrames = parent.document.getElementsByTagName("IFRAME");
for (var i = 0; i < arrFrames.length; i++) {
  if (arrFrames[i].contentWindow === window) alert("yay!");
}

Hoặc, sử dụng jQuery:

parent.$("iframe").each(function(iel, el) {
  if(el.contentWindow === window) alert("got it");
});

Phương pháp này lưu việc gán ID cho từng iframe, rất tốt trong trường hợp của bạn vì chúng được tạo động. Tôi không thể tìm thấy một cách trực tiếp hơn, vì bạn không thể lấy phần tử iframe bằng window.parent - nó đi thẳng đến phần tử cửa sổ cha mẹ (bỏ qua iframe). Vì vậy, lặp qua chúng dường như là cách duy nhất, trừ khi bạn muốn sử dụng ID.


1
Cập nhật: điều này không hoạt động chính xác như quảng cáo và tôi đã phải sử dụng tài liệu contentWindow.document ===. Không biết tại sao. Ngoài ra trong một số trình duyệt tôi đã sử dụng contentDocument. Chà, tôi thích điều đó!
Barshe

1
Xin lỗi, phải thừa nhận rằng tôi chỉ thử nghiệm nó trong Firefox. :) Tuy nhiên, tôi đã thành công khi sử dụng phương thức jQuery và contentWindow trong nhiều trình duyệt.
thành

1
Cập nhật: Tôi phát hiện ra rằng bạn cũng có thể sử dụng window.frameEuity, nhưng tôi không chắc trình duyệt nào hỗ trợ nó.
Barshe

2
Tôi không nghĩ loại công cụ này hoạt động nữa; bạn nhận được một lỗi xuất xứ chéo.
Andrew Mao

@AndrewMao câu hỏi là về các tài liệu gốc giống nhau, vì vậy không có lý do gì để có được các vấn đề về nguồn gốc chéo.
Christophe

21

bạn có thể sử dụng parentđể truy cập trang cha. Vì vậy, để truy cập một chức năng, nó sẽ là:

var obj = parent.getElementById('foo');

1
Kevin, vấn đề là BIẾT id. Tôi có một số Iframes và tôi muốn truy cập chúng từ mã bên trong
José Leal

Vẫn nhận được "Bị chặn một khung có nguồn gốc" other-localhost: 8000 "khi truy cập vào khung có nguồn gốc chéo."
dùng2568374

13

Khi id của iframe được đặt, bạn có thể truy cập iframe từ tài liệu bên trong như được hiển thị bên dưới.

var iframe = parent.document.getElementById(frameElement.id);

Hoạt động tốt trong IE, Chrome và FF.


Đây có vẻ là một cách làm phức tạpvar iframe = frameElement
Oriol

frameEuity trả về đối tượng trong ngữ cảnh cửa sổ hiện tại, nhưng Parent.document.getEuityById (frameEuity.id) trả về đối tượng trong ngữ cảnh cửa sổ cha, bạn không thể chạy các hàm javascript của cửa sổ cha mẹ với frameEuity, hãy thử nó trong jsfiddle và cho tôi và ví dụ nếu bạn có thể .
Akash Kava

6

Có lẽ chỉ cần sử dụng

window.parent

vào iframe của bạn để lấy khung / cửa sổ gọi. Nếu bạn có nhiều khung gọi, bạn có thể sử dụng

window.top

3

Hãy thử điều này, trong khung cha mẹ của bạn thiết lập IFRAME như thế này:

<iframe id="frame1" src="inner.html#frame1"></iframe>
<iframe id="frame2" src="inner.html#frame2"></iframe>
<iframe id="frame3" src="inner.html#frame3"></iframe>

Lưu ý rằng id của mỗi khung được truyền dưới dạng neo trong src.

sau đó trong html bên trong của bạn, bạn có thể truy cập id của khung mà nó được tải thông qua location.hash:

<button onclick="alert('I am frame: ' + location.hash.substr(1))">Who Am I?</button>

sau đó bạn có thể truy cập Parent.document.getEuityById () để truy cập thẻ iframe từ bên trong iframe


Vâng, đây sẽ là giải pháp hợp lý nhất, nhưng đôi khi tôi cần thay đổi src của iframe .. và truyền tham số băm hoặc GET này cho mỗi yêu cầu là không tốt ..
José Leal

Tại sao nó là xấu để vượt qua băm mỗi lần? Nó chỉ hiển thị với trình duyệt chứ không phải máy chủ và nó không ảnh hưởng đến bộ nhớ đệm như tham số get.
Đánh dấu Porter

-1
// just in case some one is searching for a solution
function get_parent_frame_dom_element(win)
{
    win = (win || window);
    var parentJQuery = window.parent.jQuery;
    var ifrms = parentJQuery("iframe.upload_iframe");
    for (var i = 0; i < ifrms.length; i++)
    {
        if (ifrms[i].contentDocument === win.document)
            return ifrms[i];
    }
    return null;
}
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.