JavaScript Temelleri

Bölüm 18

Belge Çözümleyicisi Nesne Modeli (Browser Object Model) (BOM)

Bölüm 18 Sayfa 5

18.5 - window Nesnesinin Olay Yöneticileri

Olay yöneticileri etkileşimli programlamanın ana öğeleridir. Olay yönetiicleri, bir olayı gözler ve bu olay oluştuğunda, programlandıkları işlemi gerçekleştirirler. Bu konuya gelinceye kadar, programlarımızda onload(), onclick(), gibi olay yöneticilerini kullandık ve çalışmalarını programlarımızda izledik. Bu bölümde ise, konuyu daha yakından incelemek ve belge çözümleyicilerin en çok kullanılanlarının ortak olarak destekledileri olay yöneticilerini tanıtmaya çalışacağız.

Olay yöneticileri on,, sözcüğü ile başlarlar. Bir Web sayfasında, iki türlü, olay yöneticisi kullanılabilir. bunlardan ilki (X)HTML kodlama diline ait olay yöneticileridir. (X)HTML kodlama dili, karakter yazılımına duyarlı olmadığından, (X)HTML kodlama diline ait olay yöneticileri, onClick, onLoad gibi yazılabilirler. (X)HTML kodlama diline ait olay yöneticilerinin değeri, üst düzey programlama alanında oldukları varsayılan JavaScript programlama adımlarıdır. Bu içerik ile tüm JavaScript programının yazılımını gerçekleştirme olanağı bulunabilir. Yine de, bu işlev için <script>program içeriği...</script> şeklinde script elementinin kullanılması ve olay yöneticilerine sadece belirli bir fonksiyonun çalıştırılması yükümlüğünün verilmesi çok daha alışılmış bir yazılım stilidir.

Bir Web sayfasının kodlarında, (X)HTML olay yöneticilerine JavaScript kodlarının yazılması, sayfanın kod bütünlüğünü bozar, Kod karışıklığının önlenmesi, bu çalışmada daha önce bir çok kez üzerinde durduğumuz bir iyi yazım stilidir. Kod karışıklığının önlenmesi prensibi, bir Web sayfasının kodlarında sadece (X)HTML kodlarının bulunmasını, sayfa ile ile ilgili tüm diğer kodların kendi özel dosyalarında bulunmasını ve sayfaya iliştirilmelerini öngörür. Biz de çalışmalarımızda bu prensibi uygulamaya özen gösteriyoruz. Sorumlu bir programcıdan da bu beklenir.

Kod karışıklığının önlenmesi prensibi, sayfa ile ilgili tüm JavaScript program adımlarının ayrı bir JavaScript program dosyasında gerçeleştirilmesini öngördüğünden, olay yöneticilerine JavaScript fonksiyonlarının atanması, Web sayfasında, (X)HTML kodlama dilinin olay yöneticilerinin kullanılmaması, bunun yerine, sayfaya bağlantılı olan JavaScript program dosyasında, JavaScript programlama dilinde bulunan olay yöneticilerinin kullanılmasını gerektirir. JavaScript programlama dili, karakter yazılımına duyarlı olduğundan, JavaScript olay yöneticilerinin programlarda tanımlandıkları karakterlerle kulanılmaları gerekir.

18.5.1 - Ortak Olarak Desteklenen Olay Yöneticileri

Inernet Explorer ve FireFox gibi Gecko motoru kullanan belge yöneticilerinin ortak olarak destekledikleri olay yöneticileri, aşağıda belirtilmiştir. Programların ortak olarak desteklenebilmeleri için sadece bu olay yöneticilerinin kullanılmış olmaları gerekir.

Tablo : 18-7 - window Nesnesinin Ortak Olarak Desteklenen Olay Yöneticileri
Olay Yöneticisi İşlev
onabort Terketme eylemi ile bir işlemi başlatır.
onbeforeunload Pencerenin terkedilmesinden önce gerçekleşecek işlemleri başlatır.
onblur Pencerenin üzerinden ilgi odağının kaldırılması ile gerçekleşecek işlemleri başlatır.
onchange Bir değişmenin gerçekleşmesi ile öngörülen işlemleri başlatır.
onclick Bir tıklama ile gerçekleşecek işlemleri başlatır.
oncontextmenu Bir sağ tıklama ile öngörülen işlemleri başlatır.
onerror Bir hatanın oluşması ile gerçekleşecek işlemleri başlatır.
onfocus Pencerenin üzerine ilgi odağı oluşması ile gerçekleşecek işlemleri başlatır.
onkeydown Bir tuşun indirilmesi ile gerçekleşecek işlemleri başlatır.
onkeyup Bir tuşun kaldırılması ile gerçekleşecek işlemleri başlatır.
onload Bir nesnenin yüklenmsi ile gerçekleşecek işlemleri başlatır.
onmousedown Mouse'un indirilmesi ile gerçekleşecek işlemleri başlatır.
onmousemove Mouse'un yer değiştirmesi ile gerçekleşecek işlemleri başlatır.
onmouseout Mouse'un göstermemesi ile gerçekleşecek işlemleri başlatır.
mouseover Mouse'un nesnenin üstünden geçmesi ile gerçekleşecek işlemleri başlatır.
mouseup Mouse'un basılı halden çıkması ile gerçekleşecek işlemleri başlatır.
onreset Kullanıcının bir formu resetlemesi ile gerçekleşecek işlemleri başlatır.
onresize Pencernin boyutlarının değiştirilmesi ile gerçekleşecek işlemleri başlatır.
onscroll sayfanın kaydırılması ile gerçekleşecek işlemleri başlatır.
onselect Seçilme ile gerçekleşecek işlemleri başlatır.
onsubmit Bir formun sunulması ile gerçekleşecek işlemleri başlatır.
onunload Boşaltma ile gerçekleşecek işlemleri başlatır.

18.5.2 - Olay Yöneticilerine İşlev Bağlanması

JavaScript programlama dilinde, olay yöneticilerine işlev bağlanması (event delegation) üç ayrı yöntemle yapılabilir. Bu yöntemler sırası ile FireFox ve Gecko motorunu kullanan tüm belge çözümleyiciler tarafından desteklenen W3C yöntemi, ikincisi sadece Internet Explorer tararfından desteklenen Microsoft Metodu, üçüncüsü ise, ortak olarak desteklenen olay yöneticilerinin kullanılması koşulu ile, ECMA-262 spesifikasyonunu destekleyen tüm belge çözümleyiciler tarafından desteklenen, bu konuya gelinceye kadar tüm programlarımızda uygulamakta olduğumuz, JavaScript yöntemi ile olay yöneticilerine işlev bağlanmasıdır. Sonuncu yöntemi çoğu programlaramızda, örnek olarak, son b18.4.4-uyg-1-js.htm sayfasında yazılımı verilmiş olan programda uygulanmış olduğundan, burada sadece ilk iki yöntem üzerinde durulacaktır.

Klasik JavaScript yöntemi ile olay yöneticilerine işlev bağlanması, fazla oranda sistem belleğiin kullanılmasına neden olur. Bunun en çarpıcı örneği, Internet Explorer'in bellek sızıntısı (memeory leak) sorunudur. Bu sorunun azaltılması, sadece gerekli elementlerin olay yöneticilerine işlev bağlanması (evant delegation) yöntemini gündeme getirmiştir. Bu konuda W3C kendi DOM sistematiği içinde bir yöntem geliştirmiştir. Bu aslında çok detaylı olan bu yöntemin sadece, addEventListener() metodunu inceleyeceğiz. Ne yazık ki bu metot, sadece FireFox ve Gecko motorunu benimseyen belge çözümleyiciler tarafından kullanılmaktadır.

W3C metodu, olayın tüm sayfa yapısı içinde teperden doruğa doğru yayınlanmasını ve tekrar başa dönüşü (bubbling phase) (kabarcıklanma fazı) öngörmektedir. Yakalama, kullanıcının öngördüğü fazda yapılabilir, fakat genel olarak geri dönüş fazı kullanılmaktadır.

W3C yönteminin addEventListener() metodunun kullanılış şekli aşağıdaki gibidir:

addEventListener(olay yöneticisi, olay fonksiyonu, yakalamanın haber verme vaya geri dönüş fazında yapılacağı); 
		

şeklindedir. Bu parametreler,

olay yöneticisi : karakter dizgisi tipinde bir değişken, 'click' gibi, olay yöneticisinin on öneki olmadan karakter dizgisi olarak yazılması.

olay fonksiyonu : birŞeylerYap() fonksiyonu gibi bir fonksiyonun kopyası olan birŞeylerYap (parantezsiz) ifadesi. Böylece this sözcüğü çağıran nesneyi çağrıştırır.Bu parametre bir anonim fonksiyon da olabilir. Örnek:

function renkDeğiştir() {
this.style.color = 'red';
}
		

son parametre: true ise yakalama gidişte, false ise, yakalama dönüşte yapılır. Hangisinde yapılacağı hakkında bir fikriniz yoksa false kullanın. Metodun kullanım örneği,

addEventListener('click', renkDeğiştir, false);
		

şeklindedir. Metot geriye bir değer döndürmez, fakat uygulanmsı olumlu geçerse, yani uygulandığı belge çözümleyici metodu destekliyor ise, geriye true aksi halde false döndürür. Bu metodun kullanımı üzerinde detaylı bir açıklama quirksmode.org sitesinde yapılmıştır.

Microsoft, W3C modelini desteklemek yerine kendi modelini ileriye sürme yolunu seçmiştir. Fakat, kendi yöntemi, W3C yöntemi kadar detaylı değildir. Örnek olarak, yakalamanın gidiş veya dönüşte yapılacağı üzerine bir belirleme yapmak olanağı tanınmamıştır. Bu konudaki ileri uygulamalarda bu bir eksiklik olarak kabul edilmektedir. Microsoft yöntemi, attachEvent() metodunu tanılar. Bu metodun kullanımı,

attachEvent(olay yöneticisi, olay fonksiyonu); 
		

şeklindedir. Olay yöneticisi parametresi, burada karakter dizigisi olarak olay yöneticisinin tam tanımıdır. Fonksiyon parametresi ise addEventListener() metodunda olduğu gibidir. Burada gerçekleşme varsayılan olarak sadece geri dönüş (kabarcıklanma) fazında yapılmaktadır. İkinci parametrede fonksiyonun kopyası değil, bellek referansı bulunmaktadır ve bundan dolayı this sözcüğü çağıran fonksiyonu değil window nesnesini çağrıştırdığından, burada yararlı değildir. Metot geriye bir değer döndürmez, fakat uygulanması olumlu geçerse, yani uygulandığı belge çözümleyici metodu destekliyor ise, geriye true aksi halde false döndürür.

Klasik JavaScript yöntemi ile, bir olay yöneticisine sadece bir tek fonksiyon atanması olanağı bulunmaktadır. Eğer birden fazla fonksiyonun çalışması öngörülecekse, bu fonksiyonlar tek bir fonksiyonun içeriğinden çağrılır. Daha önce incelediğimiz, ve bdelib.js kitaplığında bulunan, sayfaYüklendiktenSonraÇalıştır() fonksiyonu, bu yöntemi uygulamaktaydı. Olay yöneticisilerine ileri olay bağlama yöntemleri olarak adlandırılan, Microsoft ve W3C yöntemleri, istendiği kadar fonksiyonu bir tek olay yöneticisi ile ilişkilendirebilmektedir.

Microsoft ve W3C yöntemleri, farklı tipte belge çözümleyicilerce desteklendiğinden her ikisinin de ortak olarak desteklenme şansı bulunmamaktadır. Fakat, güncel eğilim, belge çözümleyicilerle değil, metotların desteklenmesi ile ilgilenmek olduğundan, burada da aynı prensip uygulanabilir. Yani, bir programa her iki metot da alınabilir. Program hangi tür belge çözümleyicide çalışırsa çalışsın, belge çözümleyicisi desteklediği metodu çalıştırır diğer metodu görmezden gelir.

Aşağıda JavaScript kodları görülmekte olan program, 'onclick' olay yöneticisine, içerikDeğiştir() adlı bir fonksiyonu ileri tekniklerle bağlamayı sağlamaktadır. Bu program, eğer Internet Explorer ve eşdeğerleri türünden belge çözümleyicilerde çalıştırılırsa, olay bağlamasını Microsoft'un öngördüğü element.attacEvent() fonksiyonunu, eğerGecko motorunu kullanan belge çözümleyicilerde çalıştırılırsa, olay bağlamasını W3C'nin öngördüğü element.addEventListener() fonksiyonunu uygulayarak gerçekleştirmektedir. Program kodları,


/* <![CDATA[  */

function MesajGöster() {
var _gizli = true;

this.sınırlama = function() {
if(_gizli ) {
kutlama();
}
_gizli = false;
}
}

function kutlama() {
var mesajKutusu =document.getElementById('mesaj'),
kutlamaMesajı = 'Doğum Gününüz Kutlu Olsun !';
mesajKutusu.appendChild(document.createtextNode(kutlamaMesajı));
}

function başlat() {
var düğme =document.getElementById('klik'),
bildiri =new MesajGöster();

// Eğer Belge Çözümleyici FireFox ise (GECKO Motoru)
if (window.addEventListener) {
düğme.addEventListener('click', bildiri.sınırlama, false);
}

// Eğer Belge Çözümleyici Internet Explorer İse
else if (window.attachEvent) {
düğme.attachEvent('onclick', bildiri.sınırlama);
}
}


// Eğer Belge Çözümleyici FireFox ise (GECKO Motoru)
if (window.addEventListener) {
window.addEventListener('load', başlat , false);
}

// Eğer Belge Çözümleyici Internet Explorer İse
else if (window.attachEvent) {
window.attachEvent('onload', başlat);
}

/* ]]>  */
		

şeklindedir. Yukarıdaki program, uygulama sayfasına bağlantılı olarak çalışmakta ve bu uygulama sayfası, başta IE 8, Firefox 3, Opera 10, Safari 4 ve Chrome 2 olmak üzere tüm belge çözümleyicilerde sorunsuz olarak çalışmaktadır.

Yukarıdaki programda, önemli olan başka bir özellik, tıklama etkisinin sınırlandırılmasıdır. Program her sayfa yüklenmesi ile sadece bir kez mesaj yazılması işlemine izin vermektedir. Bunun için, MesajGöster() yapılandırıcı fonksiyonunun _gizli adlı özel değişkeninden yararlanmaktadır. Düğmenin tıklama olayına bir foksiyon değil bir metot bağlanmaktadır. Bu metot, mesajı yazdırdıktan sonra, özel değişkenin değerini değiştirmekte ve bu şekilde, sayfa yeniden yüklenmedikçe, kullanıcı sadece bir kez mesaj yazdırabilmektedir.

Yukarıdaki program, hiçbir program kitaplığından yararlanmamaktadır ve tamamen kendi kendine yeten bir programdır. Program Gecko temelli belge çözüleyicilerde addEventListener() IE ile attachEvent() metotlarını uygulamaktadır. Bu şekilde olay yöneticilerine ileri düzey işlev bağlanması ile önemli ölçüde bellek sızıntısı sorununun etkisini azaltma olanağı bulunabilmektedir.

JavaScript fonksiyonunu, sayfa yüklendikten sonra çalıştıran program adımları, tek bir fonksiyon halinde düzenlenmiş ve bdelib fonksiyon kitaplığına eklenmiştir. Bu fonksiyonun yazılımı aşağıda verilmiştir.

/* <![CDATA[  */

function sayfaYüklenmesiTamamlandıktanSonraÇalıştır(başlangıçFonksiyonu) {

// Eğer Belge Çözümleyici FireFox ise (GECKO Motoru)

if (window.addEventListener) {
window.addEventListener('load', başlangıçFonksiyonu , false);
}

// Eğer Belge Çözümleyici Internet Explorer İse

else if (window.attachEvent) {
window.attachEvent('onload', başlangıçFonksiyonu);
}
}

/* ]]>  */
		

Yukarıda yazılımı görülen sayfaYüklenmesiTamamlandıktanSonraÇalıştır(başlangıçFonksiyonu) fonksiyonu, bdelib.js kitaplığının kullanıldığı her programda serbestçe çağrılabilir ve sayfa yüklendikten sonra belirtilen fonksiyon çağrılır. Bu fonksiyon daha önce Simon Willison tarafından düzenlenmiş olan fonksiyonun bir alternatifidir. Eğer bdelib.js kitaplığı kullanılmayacaksa, o vakit bu fonksiyonun içeriğinin yukarıdaki programda kullanıldığı gibi program sayfasında bulundurulması yeterli olacaktır.

Genel olarak bir sayfa öğesine bir olay dinleyicisinin bağlanması aşağıda görüldüğü gibi yapılabilir.

function olayDinleyicisiEkle(birim, olay, etkinlik) {

// Eğer Belge Çözümleyici FireFox ise (GECKO Motoru)

if (window.addEventListener) {
birim.addEventListener(olay, etkinlik , false);
}

// Eğer Belge Çözümleyici Internet Explorer İse

else if (window.attachEvent) {
olay = 'on' + olay;
birim.attachEvent(olay, etkinlik);
}
}
		

Bu fonksiyon bdelib.js kitaplığına alınmıştır ve örnek olarak, olayDinleyicisiEkle(window, 'load', başlat); şeklinde kullanılır.

Bir program öğesine hiçbir hazır fonksiyon kullanılmadan da olay yöneticileri atanabilir. Bunun bir örneği aşağıda verilmiştir:

function başlat () {
// Programlar Buradan Başlatılmaktadır !
...
}

window.onload = başlat;
		

Burada atanacak fonksiyonu () işlemcisi ile belirtmemek gerekir, çünkü bu durumda fonksiyonun referansı değil, geri döndüreceği değer olay yöneticisine atanır ve fonksiyon atamadan sonra otomatik olarak, yani olayın gerçekleşmesi beklenmeden çalıştırılmış olur.

Bu konuda burada sadece en gerekli olan metotlar üzerinde durulabilmiştir. Daha geniş açıklamalar Internet Explorer için, MSDN ve Firefox ile GECKO temelli belge çözümleyiciler için, GECKO DOM Reference kaynakları incelenmelidir.