Cara mengakses Iframe induk dari JavaScript

170

Yah, saya punya IFrame, yang memanggil halaman domain yang sama. Masalah saya adalah saya ingin mengakses beberapa informasi dari iframe induk ini dari halaman yang disebut ini (dari JavaScript). Bagaimana saya bisa mengakses Iframe ini?

Detail: Ada beberapa Iframe seperti ini, yang dapat memuat halaman yang sama, karena saya memprogram lingkungan Windows. Saya bermaksud untuk menutup Iframe ini, itu sebabnya saya perlu tahu mana yang harus saya tutup dari dalam dirinya. Saya memiliki array yang menyimpan referensi untuk Iframe ini.

EDIT: Di sana iframe dihasilkan secara dinamis

José Leal
sumber
bahkan jika iframe dihasilkan secara dinamis, Anda dapat menetapkan id unik baru dengan menggunakan semacam penghitung, akhirnya Anda tidak perlu tahu ID, tetapi Anda dapat mencari dengan mudah, lihat jawaban saya.
Akash Kava

Jawaban:

138

Anda juga dapat mengatur nama dan ID ke nilai yang sama

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

sehingga Anda akan dapat menggunakan kode berikutnya di dalam halaman anak

parent.document.getElementById(window.name);
Akuatik
sumber
16
Mungkin tidak jelas untuk semua orang, tetapi dengan metode ini Anda dapat mengakses objek pustaka dari orang tua (hanya jika orang tua telah memuat pustaka). Contoh: akses jQuery dengan orangtua. $ ('#
Something
1
Solusi ini kompatibel dengan mode kebiasaan kompatibilitas IE5 +.
Slayner
Bahkan di 2016, ini berfungsi dengan baik sebagai bagian dari solusi untuk masalah IE mencetak konten yang iframeterlalu kecil. Tapi mengapa itu berhasil? window.namemengembalikan sebuah string. Apa yang berbeda tentang menggunakan window.namedaripada hanya meneruskan nama id sebagai string yang tidak berfungsi.)?
Karl
3
Hai, itu tidak berjalan dengan Chrome 59 ..: VM111: 1 Tidak DOMException: Memblokir bingkai dengan asal " xxx " dari mengakses bingkai asal-silang.
Didier68
Chrome melihat file dalam folder yang sama dengan asal silang jika CORS tidak disetel. Mereka mengatakan itu untuk keamanan. Pengaturan CORS memerlukan server. Berikan pesan kepada pengguna untuk menyiapkan server atau mengubah browser jika Chrome terdeteksi.
90

Cukup panggil window.frameElementdari halaman berbingkai Anda. Jika halaman tidak dalam bingkai maka frameElementakan menjadi null.

Cara lain (memasukkan elemen jendela ke dalam bingkai kurang sepele) tetapi demi kelengkapan:

/**
 * @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;
}
Ian Carter
sumber
2
Terima kasih! Bekerja pada IE 6+, FF dan Chrome!
rustyx
11
window.frameElementkembali nullketika jendela dan iframe memiliki domain yang berbeda, yaitu pesan lintas asal.
Qwerty
@Qwerty, apakah Anda menemukan solusi?
Ajay Patidar
@ DjayPatidar saya pikir saya menyerah. :(
Qwerty
78

Saya akan merekomendasikan menggunakan API postMessage .

Di iframe Anda, hubungi:

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

Di halaman Anda termasuk iframe Anda dapat mendengarkan acara seperti ini:

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

    }, false);

By the way, juga dimungkinkan untuk melakukan panggilan ke jendela lain, dan tidak hanya iframe.

Baca lebih lanjut tentang API postMessage di blog John Resigs di sini

Kenneth Lynne
sumber
7
Saya pikir ini jelas jawaban terbaik, <iframe>isinya tidak harus tahu apa-apa tentang orang tua dan sebaliknya. Mereka hanya harus mematuhi kontrak pesan sederhana. Luar biasa!
mfeineis
1
<iframe> masih harus mengetahui domain induknya, bukan?
Homr Zodyssey
1
@HomrZodyssey Domain induk hanya tersedia sebagai mekanisme keamanan, jika tidak diketahui, Anda dapat mengatur '*'.
Amir Ali Akbari
Gunakan '*'pada klien. Setiap solusi lain memberikan kesalahan pada browser Chrome yang memperlakukan file dalam folder klien sebagai bukan Asal Sama karena server tidak disiapkan. Ini adalah solusi terbaik dan satu - satunya : dyn-web.com/tutorials/iframes/postmessage
30

Pertanyaan lama, tapi saya hanya punya masalah yang sama dan menemukan cara untuk mendapatkan iframe. Ini hanyalah masalah pengulangan melalui array frame jendela [] dan menguji konten setiap frame di jendela terhadap jendela tempat kode Anda berjalan. Contoh:

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

Atau, menggunakan jQuery:

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

Metode ini menyimpan menugaskan ID untuk setiap iframe, yang baik dalam kasus Anda karena mereka dibuat secara dinamis. Saya tidak dapat menemukan cara yang lebih langsung, karena Anda tidak bisa mendapatkan elemen iframe menggunakan window.parent - langsung ke elemen jendela induk (melewatkan iframe). Jadi perulangan melalui mereka sepertinya satu-satunya cara, kecuali jika Anda ingin menggunakan ID.

bahan_15939
sumber
1
Pembaruan: ini tidak berfungsi persis seperti yang diiklankan, dan saya harus menggunakan contentWindow.document === dokumen. Tidak tahu kenapa. Juga di beberapa browser saya menggunakan contentDocument. Ya saya suka itu!
Christophe
1
Maaf, diakui saya hanya mengujinya di Firefox. :) Namun saya sudah sukses menggunakan metode jQuery dan contentWindow di beberapa browser.
ingredient_15939
1
Pembaruan: Saya menemukan bahwa Anda juga dapat menggunakan window.frameElement, tetapi saya tidak yakin browser mana yang mendukungnya.
Christophe
2
Saya rasa jenis barang ini tidak berfungsi lagi; Anda mendapatkan kesalahan lintas asal.
Andrew Mao
@AndrewMao pertanyaannya adalah tentang dokumen asal yang sama, jadi tidak ada alasan untuk mendapatkan masalah lintas asal.
Christophe
21

Anda dapat menggunakan parentuntuk mengakses halaman induk. Jadi untuk mengakses suatu fungsi adalah:

var obj = parent.getElementById('foo');
kemiller2002
sumber
1
Kevin, masalahnya adalah TAHU id. Saya punya beberapa Iframe, dan saya ingin mengaksesnya dari kode di dalam
José Leal
Masih mendapatkan "Blocked a frame with origin" other-localhost: 8000 "dari mengakses bingkai cross-origin."
user2568374
13

Setelah id iframe diatur, Anda dapat mengakses iframe dari dokumen dalam seperti yang ditunjukkan di bawah ini.

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

Berfungsi dengan baik di IE, Chrome dan FF.

Akash Kava
sumber
Ini sepertinya cara berbelit-belit untuk melakukanvar iframe = frameElement
Oriol
frameElement mengembalikan objek dalam konteks jendela saat ini, tetapi parent.document.getElementById (frameElement.id) mengembalikan objek dalam konteks jendela induk, Anda tidak dapat menjalankan fungsi javascript jendela induk dengan frameElement, coba dalam jsfiddle dan beri saya dan contoh jika Anda bisa .
Akash Kava
6

Mungkin hanya digunakan

window.parent

ke iframe Anda untuk mendapatkan bingkai panggilan / windows. Jika Anda memiliki beberapa bingkai panggilan, Anda dapat menggunakan

window.top
Clawfire
sumber
3

Coba ini, dalam bingkai induk Anda mengatur Anda IFRAME seperti ini:

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

Perhatikan bahwa id dari setiap frame dilewatkan sebagai jangkar di src.

kemudian di html batin Anda, Anda dapat mengakses id dari frame itu dimuat melalui location.hash:

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

maka Anda dapat mengakses parent.document.getElementById () untuk mengakses tag iframe dari dalam iframe

Mark Porter
sumber
Ya, ini akan menjadi solusi yang paling logis, tapi kadang-kadang saya harus mengubah src dari iframe .. dan melewati hash ini atau GET parameter setiap permintaan tidak baik ..
José Leal
mengapa itu buruk untuk melewatkan hash setiap kali? Itu hanya terlihat oleh browser, bukan server, dan itu tidak mempengaruhi caching seperti yang dilakukan parameter get.
Mark 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;
}
Alex
sumber