iframe kullanmak zorunda olan neredeyse herkesin karşısına çıkmıştır cross-domain problemi ve bir o kadar da baş ağrıtmıştır ilk seferinde. Aynı şey benim de başıma geldiğinden biliyorum. Her şey gibi bunun da çözümü hatta çözümleri var. Kesin çözüm HTML5 postMessage. Bitti 🙂

Alex Sexton bu sunumunda birden fazla çözüm önerisiyle anlatmış ve bunları artıları ve eksileriyle ortaya koymuş. Oldukça başarılı bir anlatım olmuş.

Bunların bir kısmını denedim ve SharePoint 2010 Intranet ortamında karşılaştığım sonuçları ve nihayi çözümü yazıyorum. Yapılanları tek tek anlatmayacağım, sadece çözümü detaylandıracağım. Diğerlerini Alex Sexton’ın sunumunda daha detaylı bulabilirsiniz.

Güvenlik nedenlerinden dolayı iletişimde olacak frame‘lerin protokolleri (http, https), port numaraları (http için 80), ve host‘ları aynı olmalıdır. Aksi takdirde aşağıdaki örnekteki uyarıyla karşılaşırsınız.

Örnek şu: A domainin içindeki B domain’li bir iframe içinden bir input‘ın değerini almak ya da iframe’in içindeki bir elemana değer atamak.
Bunu denediğiniz zaman karşılaşacağınız olası uyarı mesajı şu olacaktır (jQuery mesajı):
Unsafe JavaScript attempt to access frame with URL B from frame with URL A. Domains, protocols and ports must match.

Çözüm Denemeleri:

1- window.name

Buna erişmeyi denediğimde yine aynı uyarıyı aldım.

2- document.domain

İşe yaramadı.

3- iframe içinde en üstteki katmanın domain’inde bir iframe daha açmak

iframe dışındaki domain‘i bilmiyor. URL’ine yazdırılsa bile SharePoint’in bir işlemi sonrasında URL değişiyor. Sadece tek seferinde URL alınabiliyor. Alt katmanda yine işe yaramıyor.

4- window.postMessage

Parmaklar yukarı. Aynı zamanda uygulaması en kolay çözümlerden biri. Olay temelde şu: Bir “event listener” ekliyorsunuz. O mesajın gelmesini tetikte bekliyor. Mesaj bir frame’den diğerine gönderildiği anda onu yakalıyor.

var otherWindow = document.getElementsByTagName('iframe')[0].contentWindow,
    targetDomain = 'http://garage.codersgrave.com',
    sourceDomain = 'https://codersgrave.com';

/*
 * Eğer iframe içinden dışarıya gönderilecekse
 * otherWindow = parent olmalı
 */

// Mesajın gönderileceği ekrandaki kod
otherWindow.postMessage('hoop robocop', targetDomain);


// Mesajın alınacağı ekrandaki kod
if (window.addEventListener) {
  window.addEventListener('message', receiveMessage, false);

// IE8+
} else if (window.attachEvent) {
  window.attachEvent('onmessage', receiveMessage);
}

function receiveMessage (e) {

  // Mesaj beklediğiniz adresten gelmiş ise
  if (e.origin === sourceDomain) {
    alert(e.data);
  }
}

Tarayıcı desteği: Bu örnek IE8-9, Chrome ve Firefox’da test edildi. postMessage desteklemeyen tarayıcılar için Ben Alman’ın çok güzel bir jQuery plugin‘in var. postMessage’a polling, delay ve birkaç kontrol daha eklemiş. IE6-8 ve Opera 9 desteği de veriyor.

Yararlı Kaynaklar

Siz hangi metodu kullanıyorsunuz? Bu yöntem işinize yaradı mı? Yazmaktan çekinmeyin.