JavaScript'ten üst Iframe'e erişme


170

Aynı etki alanı sayfasını çağıran bir IFrame'im var. Benim sorunum, bu üst Iframe bazı bilgilere bu çağrılan sayfadan (JavaScript) erişmek istiyorum. Bu Iframe'e nasıl erişebilirim?

Ayrıntılar: Bir Windows ortamını programladığım için, bunun gibi aynı sayfanın yüklü olabileceği birkaç Iframe vardır. Bu Iframe'i kapatmayı planlıyorum, bu yüzden onun içinden hangisini kapatmam gerektiğini bilmem gerekiyor. Bu iframe'ler referansları tutan bir dizi var.

EDIT: Dinamik olarak üretilen iframe'ler var


iframe'ler dinamik olarak oluşturulmuş olsa bile, bir çeşit sayaç kullanarak yeni bir benzersiz kimlik atayabilirsiniz, sonunda kimliği bilmenize gerek yoktur, ancak kolayca arama yapabilirsiniz, cevabımı görün.
Akash Kava

Yanıtlar:


138

Ayrıca adı ve kimliği eşit değerlere ayarlayabilirsiniz

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

böylece alt sayfada bir sonraki kodu kullanabileceksiniz

parent.document.getElementById(window.name);

16
Belki herkes için açık değildir, ancak bu yöntemle üst öğenin bir kitaplık nesnesine erişebilirsiniz (yalnızca üst öğe kitaplığı önceden yüklediyse). Örnek: jQuery ile üst
öğeye

1
Bu çözüm IE5 + uyumluluk tuhaflıkları modu ile uyumludur.
Slayner

2016'da bile, bu, IE'nin iframeçok küçük içeriklerini yazdırma sorununa yönelik bir çözümün parçası olarak harika çalışıyor . Ama neden çalışıyor? window.namebir dize döndürür. Kullanmayla ilgili window.name, kimlik adını çalışmayan bir dize olarak iletmekten farklı olan nedir?
Karl

3
Merhaba, Chrome 59 ile çalışmaz ..: VM111: 1 Yakalanmayan DOMException: " xxx " orijinli bir karenin çapraz menşe çerçeveye erişmesini engelledi .
Didier68

Chrome, CORS ayarlanmadıysa çapraz klasörle aynı klasördeki dosyaları görür. Güvenlik için derler. CORS ayarı için bir sunucu gerekir. Chrome algılanırsa kullanıcılara bir sunucu kurmaları veya tarayıcıyı değiştirmeleri için bir mesaj verin.

90

Sadece window.frameElementçerçeveli sayfanızdan arayın . Sayfa bir çerçeve içinde değilse o frameElementzaman olacaktır null.

Diğer yol (pencere elemanını bir çerçevenin içine almak daha az önemsizdir) ancak tamlık uğruna:

/**
 * @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
Teşekkürler! IE 6+, FF ve Chrome'da çalışır!
rustyx

11
window.frameElementnullpencere ve iframe farklı alan adlarına sahip olduğunda, yani çapraz kaynak mesajlaşma olduğunda döner .
Qwerty

@Qwerty herhangi bir çözüm buldunuz mu?
Ajay Patidar

@AjayPatidar Sanırım vazgeçtim. :(
Qwerty

79

PostMessage API'sini kullanmanızı tavsiye ederim .

İframe'inizde arayın:

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

İframe'i eklediğiniz sayfada aşağıdaki gibi etkinlikleri dinleyebilirsiniz:

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

    }, false);

Bu arada, sadece iframe'leri değil, diğer pencerelere çağrı yapmak da mümkündür.

John Resigs blogunda postMessage API'sı hakkında daha fazla bilgiyi buradan edinebilirsiniz


7
Bence bu açıkça en iyi cevap, <iframe>içeriklerin ebeveynler hakkında hiçbir şey bilmeleri gerekmiyor. Sadece basit mesaj sözleşmesine uymak zorundalar. Müthiş!
mfeineis

1
<iframe> hala ebeveynin alan adını bilmelidir, değil mi?
Homr Zodyssey

1
@HomrZodyssey Ana etki alanı yalnızca bir güvenlik mekanizması olarak kullanılabilir, bilinmiyorsa ayarlayabilirsiniz '*'.
Amir Ali Akbari

'*'İstemcilerde kullanın . Diğer tüm çözümler, bir sunucu ayarlanmadığı için istemciler klasöründeki dosyaları Aynı Köken olarak görmeyen bir Chrome tarayıcısında hata verir. Bu en iyi ve tek çözüm: dyn-web.com/tutorials/iframes/postmessage

30

Eski soru, ama ben sadece aynı sorunu vardı ve iframe almak için bir yol buldum. Bu sadece üst pencerenin frames [] dizisi üzerinden yineleme ve her karenin contentWindow'unu kodunuzun çalıştığı pencereye karşı test etme meselesidir. Misal:

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

Veya jQuery kullanarak:

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

Bu yöntem, her iframe'e bir kimlik atamayı kaydeder; bu, dinamik olarak oluşturuldukları için sizin durumunuzda iyidir. Daha doğrudan bir yol bulamadım, çünkü window.parent kullanarak iframe öğesini alamazsınız - doğrudan üst pencere öğesine (iframe'i atlayarak) gider. Bu nedenle, kimlik kullanmak istemediğiniz sürece, bunların içinden geçmek tek yol gibi görünüyor.


1
Güncelleme: Bu tam olarak ilan edildiği gibi çalışmadı ve contentWindow.document === belgesini kullanmak zorunda kaldım. Neden olduğu hakkında bir fikrim yok. Ayrıca bazı tarayıcılarda contentDocument kullandım. Bunu beğendim!
Christophe

1
Özür dilerim, itiraf ki sadece Firefox'ta test ettim. :) Ancak birden çok tarayıcıda jQuery yöntemi ve contentWindow kullanarak başarılı oldum.
ingredient_15939

1
Güncelleme: window.frameElement'i de kullanabileceğinizi öğrendim, ancak hangi tarayıcıların desteklediğinden emin değilim.
Christophe

2
Bu tür şeylerin artık işe yaradığını sanmıyorum; çapraz kaynak hatası alıyorsunuz.
Andrew Mao

@AndrewMao soru aynı kaynak belgeler hakkında, bu yüzden çapraz kaynak sorunları almak için bir neden yoktur.
Christophe

21

parentüst sayfaya erişmek için kullanabilirsiniz . Yani bir fonksiyona erişmek için:

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

1
Kevin, sorun kimliği bilmektir. Birkaç Iframes var ve onlara içindeki koddan erişmek istiyorum
José Leal

Yine de " other-localhost: 8000 " kaynağına sahip bir çerçeveyi çapraz menşe çerçeveden erişmeye devam edin. "
user2568374

13

İframe kimliği ayarlandıktan sonra, iç çerçeveden iframe'e aşağıda gösterildiği gibi erişebilirsiniz.

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

IE, Chrome ve FF'de iyi çalışır.


Bu kıvrımlı bir şekilde yapılıyor gibi görünüyorvar iframe = frameElement
Oriol

frameElement nesneyi geçerli pencere bağlamında döndürür, ancak parent.document.getElementById (frameElement.id), üst pencere bağlamında nesneyi döndürür, üst pencerenin javascript işlevlerini frameElement ile çalıştıramazsınız, jsfiddle'da deneyin ve bana örnek verin .
Akash Kava

6

Belki sadece kullanın

window.parent

çağıran çerçeveyi / pencereleri almak için iframe'inize ekleyin. Birden fazla arama çerçeveniz varsa,

window.top

3

Bunu deneyin, ana çerçevenizde IFRAME'leri şöyle ayarlayın:

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

Her karenin kimliğinin src'de bir çapa olarak iletildiğini unutmayın.

iç html'nizde yüklendiği çerçevenin kimliğine location.hash üzerinden erişebilirsiniz:

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

iframe etiketine iframe içinden erişmek için parent.document.getElementById () öğesine erişebilirsiniz.


Evet, bu en mantıklı çözüm olurdu, ama bazen iframe src değiştirmek gerekir .. ve bu karma veya GET parametresini geçen her istek iyi değil ..
José Leal

her seferinde hash'ı geçmek neden kötü? Sunucu tarafından değil, yalnızca tarayıcı tarafından görülebilir ve bir get parametresinin yaptığı gibi önbelleğe almayı etkilemez.
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;
}
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.