Memanggil fungsi jendela induk dari iframe

282

Saya ingin memanggil fungsi JavaScript jendela induk dari iframe.

<script>
    function abc()
    {
        alert("sss");
    }
</script>

<iframe id="myFrame">
    <a onclick="abc();" href="#">Call Me</a>
</iframe>
Arjun Singh
sumber
1
Saya tidak akan dapat menunjukkan apa pun sekarang (2016), saya tidak tahu apakah bower yang lebih tua akan mendukung
Weijing Jay Lin

Jawaban:

438
<a onclick="parent.abc();" href="#" >Call Me </a>

Lihat window.parent

Mengembalikan referensi ke induk dari jendela saat ini atau subframe.

Jika sebuah jendela tidak memiliki induk, properti induknya adalah referensi untuk dirinya sendiri.

Ketika jendela dimuat dalam <iframe>, <object>atau <frame>, induknya adalah jendela dengan elemen embedding jendela.

rahul
sumber
17
Selalu perhatikan bahwa dokumen induk dan dokumen iframe harus cocok dengan protokol dan nama domain. Jika tidak terjadi maka Anda akan mendapatkan kesalahan keamanan karena tidak diizinkan memiliki skrip lintas domain.
a4bike
M hanya ingin tahu yang mana yang alertakan dipanggil; alertfungsi orang tua atau fungsi iframe alert, jika parent.abc();dipanggil iframe?
Prakhar Mishra
@PrakharMishra Jangan bingung. parent berarti parent.
Sahu V Kumar
3
@ a4bike untuk skenario seperti itu, window.postMessage()(atau window.parent.postMessage()) ada. Periksa @Andrii jawab
Fr0zenFyr
81

Baru-baru ini saya harus mencari tahu mengapa ini tidak berhasil juga.

Javascript yang ingin Anda panggil dari iframe anak harus di kepala orang tua. Jika ada di badan, skrip tidak tersedia dalam cakupan global.

<head>
    <script>
    function abc() {
        alert("sss");
    }
    </script>
</head>
<body>
    <iframe id="myFrame">
        <a onclick="parent.abc();" href="#">Click Me</a>
    </iframe>
</body>

Semoga ini bisa membantu siapa saja yang menemukan masalah ini lagi.

Ash Clarke
sumber
1
Tak satu pun dari teknik yang disebutkan dalam pos ini berfungsi di Chrome. Ada solusi untuk ini?
Kumar Kush
3
Jika saya ingat dengan benar, saya tidak bisa menjalankan ini seperti yang diharapkan jika iframe memiliki domain yang berbeda dengan induknya. Maaf ini bukan solusi, tetapi mungkin menjelaskan mengapa itu tidak berfungsi.
Ash Clarke
1
Iya. Saya tahu itu karena domain yang berbeda, tetapi apakah tidak ada cara untuk mengatasi ini?
Kumar Kush
1
Saya baru saja memposting apa yang mungkin menjadi solusi untuk masalah Anda. Lihatlah jawaban yang lain.
Ash Clarke
1
Sesuai dengan aturan penentuan kebijakan asal yang sama (lihat: en.wikipedia.org/wiki/... ), subdomain dianggap sebagai nama host yang berbeda dengan subdomain suatu domain. Jika Anda belum melakukannya, Anda bisa mencoba mengatur document.domain ke subdomain?
Ash Clarke
73

Window.postMessage ()

Metode ini dengan aman memungkinkan cross-originkomunikasi.

Dan jika Anda memiliki akses ke kode halaman induk maka metode induk apa pun dapat dipanggil serta data apa pun dapat diteruskan langsung dari Iframe. Ini adalah contoh kecil:

Halaman induk:

if (window.addEventListener) {
    window.addEventListener("message", onMessage, false);        
} 
else if (window.attachEvent) {
    window.attachEvent("onmessage", onMessage, false);
}

function onMessage(event) {
    // Check sender origin to be trusted
    if (event.origin !== "http://example.com") return;

    var data = event.data;

    if (typeof(window[data.func]) == "function") {
        window[data.func].call(null, data.message);
    }
}

// Function to be called from iframe
function parentFunc(message) {
    alert(message);
}

Kode iframe:

window.parent.postMessage({
    'func': 'parentFunc',
    'message': 'Message text from iframe.'
}, "*");
// Use target origin instead of *

PEMBARUAN:

Catatan keamanan:

Selalu berikan target tertentu, BUKAN *, jika Anda tahu di mana dokumen jendela lain harus berada. Gagal memberikan target spesifik mengungkapkan data yang Anda kirim ke situs berbahaya apa pun yang tertarik (komentar oleh ZalemCitizen ).

Referensi:

Andrii Verbytskyi
sumber
1
Saya lebih suka menggunakan ini daripada yang lain. Terutama karena lebih masuk akal untuk menggunakan iframe pada cross origin docs (walaupun programmer lebih sering mengeksploitasi iframe) dan memberikan dukungan luas untuk fungsi ini pada browser.
Fr0zenFyr
1
Terima kasih! Saya selalu harus menghabiskan satu jam atau lebih untuk kembali dan meneliti bagaimana melakukan pengiriman pesan dengan contoh yang rumit dan bertele-tele. Ini bekerja dalam 60 detik. Terima kasih untuk contoh yang ringkas dan to the point.
RandallTo
2
layak untuk meningkatkan itu (dari MDN web docs ): Selalu berikan targetOrigin spesifik, bukan *, jika Anda tahu di mana dokumen jendela lain harus berada. Gagal memberikan target spesifik mengungkapkan data yang Anda kirim ke situs berbahaya apa pun yang tertarik
ZalemCitizen
20

Saya telah memposting ini sebagai jawaban terpisah karena tidak terkait dengan jawaban saya yang ada.

Masalah ini baru-baru ini dipangkas lagi untuk mengakses induk dari iframe yang merujuk subdomain dan perbaikan yang ada tidak berhasil.

Kali ini jawabannya adalah mengubah document.domain dari halaman induk dan iframe menjadi sama. Ini akan menipu pemeriksaan kebijakan asal yang sama dengan berpikir bahwa mereka hidup berdampingan pada domain yang sama persis (subdomain dianggap sebagai host yang berbeda dan gagal dalam pemeriksaan kebijakan asal yang sama).

Masukkan yang berikut ini ke <head>halaman di iframe agar sesuai dengan domain induk (sesuaikan untuk tipe dokumen Anda).

<script>
    document.domain = "mydomain.com";
</script>

Harap dicatat bahwa ini akan menimbulkan kesalahan pada pengembangan host lokal, jadi gunakan cek seperti berikut untuk menghindari kesalahan:

if (!window.location.href.match(/localhost/gi)) {
    document.domain = "mydomain.com";
} 
Ash Clarke
sumber
dan bagaimana dengan pengujian ini di localhost? ada solusi untuk itu?
Umesh Awasthi
Lihat: "Harap dicatat bahwa ini akan menimbulkan kesalahan pada pengembangan localhost, jadi gunakan cek seperti berikut untuk menghindari kesalahan"
Ash Clarke
2
Perlu dicatat bahwa (setidaknya di Google Chrome) baik orang tua dan anak HARUS SET document.domain bahkan jika salah satunya sudah "benar"! Contoh: Induk adalah example.comiframe abc.example.com, maka kedua induk dan iframe harus memanggildocument.domain = "example.com"
KillerX
Ya itu benar, saya membuat salah ketik di sini: "halaman di iframe sama." harus "halaman dan iframe sama." ..... Terima kasih!
Ash Clarke
untuk if () mengapa Anda tidak hanya menggunakan if (document.domain! = "mydomain.com"? Juga, saya bingung, apakah <script> ada di jendela induk atau iFrame? Juga, mengatur document.domain di iFrame menghasilkan "Gagal menetapkan properti 'domain' di 'Dokumen': 'localhost' bukan akhiran dari 'sc-localhost'.
user2568374
18

Kamu bisa memakai

window.top

lihat berikut ini.

<head>
    <script>
    function abc() {
        alert("sss");
    }
    </script>
</head>
<body>
    <iframe id="myFrame">
        <a onclick="window.top.abc();" href="#">Click Me</a>
    </iframe>
</body>
Vinothkumar Arputharaj
sumber
Saat mencoba memanggil parent.custom_function (); dari iframe tidak berfungsi, Anda mungkin menemukan window.top.custom_function (); akan bekerja. Bekerja untuk saya karena beberapa alasan aneh. Script javas saya di jendela induk semuanya tertanam di footer, saya membaca di suatu tempat bahwa menyertakan file javascript di footer menyebabkan masalah parent.custom_function () tidak berfungsi.
Friso Horstman
@Vinothkumar, satu pertanyaan tolong, yang merupakan perbedaan antara memanggil "window.top.abc ()" dari hanya memanggil "abc ()", terima kasih sebelumnya =)
Zilev av
@Zilev av Seluruh utas utas ini memanggil fungsi dalam dokumen induk dari iframe anak. Itulah bedanya. Memanggil abc()hanya akan berfungsi jika function abc()dideklarasikan di iframe sebagai lawan dari halaman induk. window.top.abc()keluar dari iframe ke dalam dokumen induk.
Sean Kendle
3

Tambahan lain untuk mereka yang membutuhkannya. Solusi Ash Clarke tidak berfungsi jika mereka menggunakan protokol yang berbeda jadi pastikan bahwa jika Anda menggunakan SSL, iframe Anda menggunakan SSL juga atau itu akan merusak fungsinya. Solusinya memang berhasil untuk domain itu sendiri, jadi terima kasih untuk itu.

Devon
sumber
2

Solusi yang diberikan oleh Ash Clarke untuk subdomain berfungsi dengan baik, tetapi harap dicatat bahwa Anda harus menyertakan document.domain = "mydomain.com"; di kedua kepala halaman iframe dan kepala halaman induk, sebagaimana dinyatakan dalam tautan yang sama memeriksa kebijakan asal

Perpanjangan penting untuk kebijakan asal yang sama diterapkan untuk akses DOM JavaScript (tetapi tidak untuk sebagian besar rasa lain dari pemeriksaan asal-sama) adalah bahwa dua situs yang berbagi domain tingkat atas yang sama dapat memilih untuk berkomunikasi meskipun gagal dengan "host yang sama" periksa dengan saling mengatur masing-masing properti DOM document.domain masing-masing untuk fragmen kanan yang sama dari nama host mereka saat ini. Sebagai contoh, jika http://en.example.com/ dan http://fr.example.com/ keduanya mengatur document.domain ke "example.com", mereka akan dari titik itu pada asal-usul yang dianggap sama untuk tujuan manipulasi DOM.

Frato
sumber
Ya itu benar, saya membuat salah ketik di sini: "halaman di iframe sama." harus "halaman dan iframe sama." ..... Terima kasih!
Ash Clarke
bagaimana dengan menjalankan file di komputer lokal? apa nilainya document.domain?
Raptor
Akan localhostatau alamat ip mesin (biasanya 127.0.0.1), tergantung pada apa yang ada di bilah alamat url.
Ash Clarke
2

parent.abc () hanya akan berfungsi di domain yang sama karena tujuan keamanan. Saya mencoba solusi ini dan milik saya bekerja dengan sempurna.

<head>
    <script>
    function abc() {
        alert("sss");
    }

    // window of the iframe
    var innerWindow = document.getElementById('myFrame').contentWindow;
    innerWindow.abc= abc;

    </script>
</head>
<body>
    <iframe id="myFrame">
        <a onclick="abc();" href="#">Click Me</a>
    </iframe>
</body>

Semoga ini membantu. :)

Remotigue Seph
sumber
Ini juga benar-benar hanya digunakan untuk dokumen iframe, menambah komplikasi besar jika Anda perlu merujuk ke kontrol pada formulir induk.
Paul
1

Dengan Firefox dan Chrome Anda dapat menggunakan:

<a href="whatever" target="_parent" onclick="myfunction()">

Jika fungsi saya hadir di iframe dan di induk, yang orangtua akan dipanggil.

kepingan salju
sumber
itu tidak bekerja. Ini demo saya: dotku.github.io/tech/html/iframe/iframe_function_container.html
Weijing Jay Lin
Seperti yang dinyatakan oleh Ash Clarke, javascript yang ingin Anda panggil dari iframe anak harus di kepala orang tua.
kepingan salju
Jawaban yang diterima tidak perlu skrip berada di kepala. Saya tidak menguji apakah solusi ini juga tidak lagi membutuhkan skrip di kepala atau tidak.
Guy Schalnat
0

Sementara beberapa solusi ini mungkin berhasil, tidak ada yang mengikuti praktik terbaik. Banyak yang menetapkan variabel global dan Anda mungkin menemukan diri Anda melakukan panggilan ke beberapa variabel induk atau fungsi, yang mengarah ke namespace yang berantakan dan rentan.

Untuk menghindari ini, gunakan pola modul. Di jendela induk:

var myThing = {
    var i = 0;
    myFunction : function () {
        // do something
    }
};

var newThing = Object.create(myThing);

Kemudian, di iframe:

function myIframeFunction () {
    parent.myThing.myFunction();
    alert(parent.myThing.i);
};

Ini mirip dengan pola yang dijelaskan dalam bab Inheritance dari teks mani Crockford, "Javascript: The Good Parts." Anda juga dapat mempelajari lebih lanjut di halaman w3 untuk praktik terbaik Javascript. https://www.w3.org/wiki/JavaScript_best_practices#Avoid_globals

William J. Littlefield
sumber