Bir iframe'den üst pencere işlevini çağırma


282

Bir iframe'den üst pencere JavaScript işlevini çağırmak istiyorum.

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

<iframe id="myFrame">
    <a onclick="abc();" href="#">Call Me</a>
</iframe>

1
Şu anda hiçbir şey gösteremiyorum (2016), eski bower'ın herhangi birini destekleyip desteklemeyeceğini bilmiyorum
Weijing Jay Lin

Yanıtlar:


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

Pencereye bakın.

Geçerli pencerenin veya alt çerçevenin üst öğesine bir başvuru döndürür.

Bir pencerenin üst öğesi yoksa, üst özelliği kendisine bir referanstır.

Bir pencere bir <iframe>, <object>veya içine yüklendiğinde <frame>, üst öğesi öğenin pencereyi gömdüğü penceredir.


17
Her zaman üst belgenin ve iframe belgesinin protokol ve etki alanı adıyla eşleşmesi gerektiğini dikkate alın. Bu gerçekleşmezse, alanlar arası komut dosyası oluşturmaya izin verilmediğinden bir güvenlik hatası alırsınız.
a4bike

Sadece iki alerts'den hangisinin çağrıldığını merak ediyorum ; üst alertveya üst çerçeve alertişlevi, parent.abc();iframe denirse?
Prakhar Mishra

@PrakharMishra Kafanız karışmasın. ebeveyn, ebeveyn anlamına gelir.
Sahu V Kumar

3
Bu tür senaryolar için @ a4bike window.postMessage()(veya window.parent.postMessage()) vardır. @Andrii cevap
Fr0zenFyr

81

Geçenlerde bunun neden işe yaramadığını öğrenmek zorunda kaldım.

Alt iframe'den aramak istediğiniz javascript'in ebeveynin başında olması gerekir. Gövde içindeyse, komut dosyası genel kapsamda kullanılamaz.

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

Umarım bu sorunla tekrar karşılaşan herkese yardımcı olur.


1
Bu yayında belirtilen tekniklerin hiçbiri Chrome'da çalışmaz. Bunun için bir çözüm var mı?
Kumar Kush

3
Doğru hatırlıyorsam, iframe'in üst öğe için farklı bir alan adı varsa, beklendiği gibi çalışmasını sağlayamadım. Üzgünüz, bu bir çözüm değil, ama neden işe yaramadığını açıklayabilir.
Ash Clarke

1
Evet. Bunun farklı alanlar nedeniyle olduğunu biliyorum, ama bu sorunu çözmenin bir yolu yok mu?
Kumar Kush

1
Sorununuz için geçici bir çözüm olabilir. Diğer cevaba bir göz atın.
Ash Clarke

1
Aynı başlangıç ​​politikası belirleme kurallarına göre (bkz: en.wikipedia.org/wiki/… ), alt alanlar, bir alan adının alt alan adından farklı bir ana bilgisayar adı olarak kabul edilir. Henüz yapmadıysanız, sadece alt etki alanına document.domain ayarlamayı deneyebilirsiniz?
Ash Clarke

73

Window.postMessage ()

Bu yöntem güvenli bir şekilde cross-originiletişimi sağlar .

Üst sayfa koduna erişiminiz varsa, herhangi bir üst yöntem çağrılabilir ve herhangi bir veri doğrudan buradan iletilebilir Iframe. İşte küçük bir örnek:

Ana sayfa:

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);
}

Iframe kodu:

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

GÜNCEL:

Güvenlik notu:

*Diğer pencerenin belgesinin nerede olması gerektiğini biliyorsanız , her zaman belirli bir targetOrigin değil NOT . Belirli bir hedef sağlanamaması, ilgili kötü amaçlı sitelere gönderdiğiniz verileri açıklar ( ZalemCitizen tarafından yapılan yorum ).

Referanslar:


1
Bunu başkaları üzerinde kullanmayı tercih ederim. Özellikle çapraz kökenli belgelerde iframe'lerin kullanılması daha mantıklı olduğu için (programcılar iframe'lerden daha sık kullanılmasa da) ve tarayıcılarda bu işlev için geniş destek verdiler.
Fr0zenFyr

1
Teşekkürler! Her zaman bir saat veya daha fazla zaman harcamam ve karmaşık, ayrıntılı örneklerle mesajlaşmayı nasıl yapacağımı araştırmam gerekiyor. Bu 60 saniye içinde çalıştı. Kısa ve öz olan bir örnek için teşekkürler.
RandallTo

2
( MDN web belgelerinden ): Diğer pencerenin belgesinin nerede olması gerektiğini biliyorsanız, * değil her zaman belirli bir targetOrigin sağlayın. Belirli bir hedef
sağlanamadığında

20

Mevcut cevabımla ilgisiz olduğu için bunu ayrı bir cevap olarak gönderdim.

Bir alt alana başvuruda bulunan iframe'den bir üst öğeye erişmek için bu sorun yakın zamanda yeniden kırpıldı ve mevcut düzeltmeler işe yaramadı.

Bu kez yanıt, üst sayfanın document.domain ve iframe'inin aynı olmasıydı. Bu , tam olarak aynı alanda birlikte var olduklarını düşünmek için aynı başlangıç ​​politikası kontrollerini kandırır (alt alanlar farklı bir ana bilgisayar olarak kabul edilir ve aynı başlangıç ​​politikası kontrolünde başarısız olur).

Aşağıdaki takın <head>ana alanı ile eşleşmesi iframe'de sayfanın (sizin doctype için ayarlayın).

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

Bunun localhost geliştirilmesinde bir hata oluşturacağını lütfen unutmayın, bu nedenle hatayı önlemek için aşağıdaki gibi bir kontrol kullanın:

if (!window.location.href.match(/localhost/gi)) {
    document.domain = "mydomain.com";
} 

ve bunu localhost'ta test etmeye ne dersiniz? bunun için herhangi bir geçici çözüm var mı?
Umesh Awasthi

Bakınız: "Bunun localhost geliştirmesine bir hata atacağını lütfen unutmayın, bu yüzden hatayı önlemek için aşağıdaki gibi bir kontrol kullanın"
Ash Clarke

2
(En azından Google Chrome'da) hem ebeveynin hem de çocuğun bunlardan biri zaten "doğru" olsa bile document.domain ayarlaması GEREKİR! Örnek: Veli edilir example.comiframe'dir abc.example.comardından ebeveyn hem ve iframe çağırmalıdırdocument.domain = "example.com"
KillerX

Evet doğru, burada bir yazım hatası yaptım: "iframe'deki sayfa aynı olsun." "sayfa ve iframe aynı olmalı" olmalıdır. ..... Teşekkürler!
Ash Clarke

if () için neden sadece (document.domain! = "alan_adim.com.tr" ifadesini kullanmıyorsunuz? Ayrıca, kafam karıştıysa, <script> ana pencerede mi yoksa iFrame'de mi? iFrame'deki document.domain, "Document"
öğesinde

18

Kullanabilirsiniz

window.top

aşağıdakilere bakın.

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

Parent.custom_function () öğesini çağırmaya çalışırken; iframe çalışmazsa window.top.custom_function (); çalışacak. Benim için garip bir nedenden dolayı çalışıyor. Üst pencerede benim javascripts tüm altbilgi gömülü, ben altbilgi javascript dosyaları dahil sorunun parent.custom_function () çalışmıyor neden bir yerde okudum.
Friso Horstman

@Vinothkumar, bir soru lütfen, "window.top.abc ()" ile sadece "abc ()" çağrılması arasındaki
farktır

@Zilev av Bu iş parçacığının tüm noktası, alt iframe'den üst belgedeki bir işlevi çağırıyor. Aradaki fark bu. Arama abc(), yalnızca üst sayfada aksine iframe'defunction abc() bildirilmişse çalışır . iframe'den üst belgeye ayrılır. window.top.abc()
Sean Kendle

3

İhtiyacı olanlar için başka bir ek. Ash Clarke'ın çözümü, farklı protokoller kullanıyorsa çalışmaz, bu nedenle SSL kullanıyorsanız, iframe'inizin SSL kullandığından veya işlevi bozacağından emin olun. Onun çözümü alanların kendisi için işe yaradı, bu yüzden bunun için teşekkürler.


2

Ash Clarke tarafından alt alanlar için verilen çözüm harika çalışıyor, ancak lütfen document.domain = "mydomain.com"; aynı orijin politikası kontrolleri bağlantısında belirtildiği gibi iframe sayfasının başlığında ve üst sayfanın başlığında

JavaScript DOM erişimi için uygulanan aynı başlangıç ​​politikasının önemli bir uzantısı (ancak aynı kaynaklı kontrollerin diğer tatlarının çoğu için değil), ortak bir üst düzey alan adı paylaşan iki sitenin "aynı ana bilgisayar" ın başarısız olmasına rağmen iletişim kurmayı seçebilmesidir. ilgili document.domain DOM mülklerini, mevcut ana bilgisayar adlarının aynı nitelikli, sağ taraftaki parçasına karşılıklı olarak ayarlayarak kontrol edin. Örneğin, http://en.example.com/ ve http://fr.example.com/ her ikisi de document.domain öğesini "example.com" olarak ayarlarsa, bu noktadan itibaren, DOM manipülasyonunun amacı.


Evet doğru, burada bir yazım hatası yaptım: "iframe'deki sayfa aynı olsun." "sayfa ve iframe aynı olmalı" olmalıdır. ..... Teşekkürler!
Ash Clarke

dosyaları yerel bilgisayarda çalıştırmaya ne dersiniz? değeri document.domainnedir?
Raptor

Bu olacak localhostveya makinenin (tipik bir ip adresi 127.0.0.1), url adres çubuğuna ne bağlı.
Ash Clarke

2

parent.abc () yalnızca güvenlik nedeniyle aynı alanda çalışır. Bu geçici çözümü denedim ve benim mükemmel çalıştı.

<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>

Bu yardımcı olur umarım. :)


Bu aynı zamanda sadece iframe'in belgesi için herhangi bir kullanımdır ve üst formdaki denetimlere başvurmanız gerekiyorsa büyük komplikasyonlar ekler.
Paul

1

Firefox ve Chrome ile şunları kullanabilirsiniz:

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

Hem iframe hem de üst öğede işlevim varsa, üst işlev çağrılır.



Ash Clarke tarafından belirtildiği gibi, çocuk iframe'inden aramak istediğiniz javascriptin ebeveynin başında olması gerekir.
kar tanesi

Kabul edilen cevabın, betiğin kafasında olması gerekmez. Bu çözümün artık betiğin kafasında olması gerekip gerekmediğini test etmedim.
Guy Schalnat

0

Bu çözümlerin bazıları işe yarayabilirken, hiçbiri en iyi uygulamaları takip etmiyor. Birçoğu genel değişkenler atar ve kendinizi birden çok üst değişkene veya işleve çağrı yaparak dağınık, savunmasız bir ad alanına yönlendirebilirsiniz.

Bundan kaçınmak için bir modül deseni kullanın. Üst pencerede:

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

var newThing = Object.create(myThing);

Ardından, iframe içinde:

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

Bu, Crockford'un "Javascript: İyi Parçalar" metninin miras bölümünde açıklanan kalıplara benzer. Javascript'in en iyi uygulamaları için w3 sayfasından da daha fazla bilgi edinebilirsiniz. https://www.w3.org/wiki/JavaScript_best_practices#Avoid_globals

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.