Dinamik HTML
26 Kasım 2007
W3C DOM
DOM (Document Object Model) ekrandaki öğelere erişim yöntemidir. "document.layers", "document.all" ve "document.getElementById" tanımları değişik tarayıcılar için öğe erişim yöntemleridir. Değişik kullanım biçimlerini standart altına almak için W3C, var olan tarayıcılardaki özellikleri kullanmıştır. Bu özellikler IE 5 ve NS 6'da vardır (NS 6'daki eksikler aynı sürüm içinde tamamlanmıştır)..
Consortium'un hedefi tabi ki standart kurulmasıdır. Burada katmanlara erişim ve değişimleri incelenir. W3C DOM, sayfadaki hemen herşeyle ilgilenir. Bu nedenle sayfadaki herşeyi değiştirebilirsiniz ama önerilen hiçbir zaman "document.write" kullanmamanızdır. Teknik yapı hakkında daha çok bilgi edinmek isterseniz Document Object Model Core sayfalarına bakabilirsiniz. HTML komutları ve nitelikleri ve bazı HTML komutları için değişik kullanım biçimleri burada sözü edilen sayfalarda anlatılmıştır. Document Object Model HTML. Sıradüzensel YapıDOM için anahtar sıradüzensel yapı ve aile ağacı görünümüdür ("family tree-like" structure). "document" gerçek sayfayı ve içeriğini tanımlar. Ağacın en tepesi burasıdır ve herşey onun altında yer alır. Örneğin <HTML> biçimi document altındadır ve <HEAD> biçimi <HTML> biçimi altındadır ve o da daha önce belirtildiği gibi document; altındadır vb.... DOM anlamını ve ne olduğu konusunu öğrenmek için burada aile ağacı anlatılır. Aile ağacının en tepesinde "document" vardır. DOM ağacının dallarına "nodes." (düğüm) denir. Aslında bir sayfadaki her öğeye düğüm denir. <li>, <p>, ve <td> biçimleri düğüm örneklerindendir. Aslında align="center", (bir ölçüye kadar) düğümdür. Niteliğin değeri bile ("center" gibi) düğümdür. Aile AğacıAşağıda aile ağacı için örnek verilmiştir. Burada bir baba kullanılır çünkü HTML dökümanında da yalnız bir baba vardır.
Bir aile ağacı tanımlandığına göre teknik ayrıntıları bir tarafa bırakıp DOM ile ağacı gezelim (Şu anda DOM denince W3C DOM önerilerinden söz edilir) Şu ana değin bildiğimize göre bir katmana kimliği bilinirse (id) document.getElementById() ile erişilebilir. Bir kez bu bilgi elinizde olursa, diğer katmanlara da erişme olanağı vardır. Şimid bazı kodları inceleyelim ve bunları aile ağacı açısında değerlendirelim. parentNode baba düğümüne erişir. Örneğin: childNodes çocukların düğüm listesini verir. Örneğin: firstChild bizim ilk çocuğun düğümüne erişir. Örneğin: lastChild bizim son çocuğun düğümüne erişir. Örneğin: previousSibling bundan önceki kardeşin düğümüne erişimi gösterir. Örneğin: "nextSlibling" bundan sonraki kardeşin düğümüne erişir. Örneğin: Aile öğelerine erişim
Öğrendiklerinizle yukarıdaki aile ağacını gezebilir ve aile öğelerine "Sen" öğesinden erişebildiğinizi gösterebilirsiniz. "Sen" öğesine:
Öğelere erişimde başka bir yöntem
Bir katmana, onun adıyla (kimliğiyle - ID)
document.getElementById(ID) kullanarak erişebiliriz.
Öğenin düğümüne biçim adı (tagName) kullanarak
document.getElementsByTagName(tagName) da erişebiliriz. Bu kullanımda dönen değer o biçim adının kullanıldığı öğelerden oluşan bir dizidir.
Örnek: document.getElementsByTagName("TD").item(0) Bu örnekte ilk tablo hücresinin <td> biçimine erişildi. Bir belgedeki tüm biçimlere ulaşmak için : document.getElementsByTagName("*") kullanılır. Öyleyse <body> biçimine erişmek için: document.getElementsByTagName("BODY").item(0) Bu bilgileri kullanmadan önce iki önemli başlıkta toplanan bilgileri incelemekte yarar vardır.
Burada söylenmek istenen bir öğeyi yakınındaki başka öğelerle tanımlamak pek gerçekçi olmaz. Ve son olarak bir <p> öğesi bir başkasının içinde olmamalıdır. Örneğe bakarakHer öğeye değişik açılardan bakan örnekten bu sayfa incelendiğinde: Buradaki ol1 biçimine sayıyla da erişebiliriz (unutmayın anlamsız düğümlerle sayıları değişebilir)
<body> biçimine çok erişeceğimizde yerine bir kısa tanım kullanabiliriz ( document.getElementsByTagName("BODY").item(0) kullanmak yerine) ya da ona bir kimlik tanımlayıp onu kullanabiliriz: Yukarıda kullanıldığı gibi "document.body." l2'ye erişmek için:
İçeriğinde "Buradaki Yazı 3." olan yazı düğümünü bulmaya çalışın Onu önce span3 kimlik adına erişip daha sonra onun firstChild (ilk çocuk) değerinden bulabiliriz. Örneğin:
document.getElementById("span3").firstChild
Düğüm özellikleri ve metodlarYukarıdaki örneği ele alarak başlayalım. "hasChildNodes()" mantıksal değer olan doğru yanlış değerlerini döndürür.
document.getElementById("span3").hasChildNodes()
dersek doğru değer döndürür ama:
document.getElementById("span3").firstChild.hasChildNodes()
dersek yanlış değeri döndürür. Çünkü çocukları yoktur (yazı düğümünün hiçbir zaman çocukları olmaz).nodeName düğümün "adını" döndürür:
document.getElementById("span3").nodeName
bize "SPAN" döndürür.tagName öğenin biçim adını döndürür.
document.getElementById("span3").tagName
"SPAN" döndürür.Dönen değer aynı olunca nodeName ve tagName arasındaki fark nedir diye sorabilirsiniz. Bir yazı düğümünün biçim adına erişmek isterseniz yooktur.Çünkü bir biçimi yoktur (biçim adı öğeler için geçerlidir) ama, yazı düğümüne düğüm adıyla erişmek isterseniz size "#text" dönecektir. Yani:
document.getElementById("span3").firstChild.nodeName
"#text" döndürür ama
document.getElementById("span3").firstChild.tagName
"undefined" döndürür."nodeType" düğümün nasıl bir düğüm olduğunu söyler. Dönene değer 1, 2 ya da 3'dür.
document.getElementById("span3").nodeType
1 döndürür halbuki:
document.getElementById("span3").firstChild.nodeType
3 döndürür."nodeValue" düğümün değerini döndürür. Bunu düğüme erişmek ya da içeriğini değiştirmek için kullanabilirisiniz. Eğer düğüm yazı tipiyse, yazıyı döndürür. Eğer nitelik türü düğümse niteliği döndürür. Eğer öğe ise dönen değer null'dur.
document.getElementById("span3").firstChild.nodeValue
"Buradaki Yazı 3" döndürür
document.getElementById("span3").nodeValue
null değerini döndürür.
Nitelik değerlerini al, ata ve sil
Daha önce söylendiği gibi bir sayfadaki her şey (nitelikler de dahil) düğümdür. Nitelikler uygunlandığı öğenin bir çocuğu olarak yorumlanamaz (zaten öyle de değildir). Burada niteliklere nasıl erişileceği, değiştirileceği ya da silineceği anlatılır. Aşağıdaki öğeyi ele alalım:
<iframe id="myIFrame" src="aDog.html" align="center"
width="400" height="200"></iframe>
Bu öğeye:
document.getElementById("myIFrame")
ile erişilebilir. Bu öğenin niteliklerine erişim nasıl olur?"getAttribute(attribute)" bir parametresi vardır. Erişilecek niteliğin adı verilir değeri döner. Örneğin:
document.getElementById("myIFrame").getAttribute("width")
Dönen değer "400"dür."setAttribute(attribute, newValue)" iki parametresi vardır. Değeri değiştirilecek niteliğin adı ve değeri bu parametreleri oluşturur. Örneğin:
document.getElementById("myIFrame").setAttribute("width","200")
Bu komutla myIFrame adlı öğenin eni 200 olur. Tamsayı kullansanız bile mutlaka tırnak içinde kullanılmalıdır (tarayıcılar böyle kullanılmasa bile sayıları kabul ederler).
<iframe> kaynak niteliğini değiştirmek için:
document.getElementById("myIFrame").setAttribute("src","someNewPage.html")
girebiliriz."removeAttribute(attribute)" bir parametre alır. Silinecek niteliğin adı burada belirtilir. Örneğin:
document.getElementById("myIFrame").removeAttribute("width")
Bu komut "en" niteliğini kaldırır ve tarayıcının enini iframe adılı öğeye atar.Yeni DüğümlerVar olan düğüm işlemlerinden başka yeni düğüm ekleme olanağı da vardır. "document.createElement(tagName)" ibelirtilen biçim adıyla yeni bir öğe düğümü yaratır. Bir parametresi olur. Yaratılacak biçim adıdır. Örneğin:
newSPAN = document.createElement("SPAN");
Unutmayın ki "createElement()" yalnız döküman içinden kullanılabilir ve yeni öğenin değeri bir değişkene atanmalıdır. Daha sonra bu değeri dökümana nasıl ekleyeceğimizi göreceğiz. "document.createTextNode(text)" yeni bir yazı düğümü yaratmak için kullanılır. Düğüm için bir parametre kullanır. Örnek:
newText = document.createTextNode("Buradaki yeni bir yazıdır");
Burada HTML kullanılmaz. Yalnız yazıya yer verilir (Diğer bir deyimle HTML biçimleri de yazı gibi değerlendirilir). Şimdi yaratılan yazı düğümü ve yeni öğeyi kullanalım. Düğümleri dökümanlara eklemek"appendChild(newNode)" yeni bir düğümü bulunduğu yerdeki çocukların listesinin sonuna ekler. inserts the new node to the end of the list of children of the node where this is run from. Aşağıdaki örnekte yer alan öğelerin düğümlerinden sonra eklenecek yeni düğümle ilgili bilgi vardır.
<body>
<div align="center" id="div1">
<span id="span1">Buradaki SPAN1 yazısıdır</span>
Buradaki yazı span biçim içinde değildir.
</div>
</body>
newSPAN.appendChild(newText);
document.getElementById("div1").appendChild(newSPAN);
alert(document.getElementById("div1").lastChild.nodeName);
Burada yaptığımız, yazı düğümünü newSPAN düğümünün son çocuğu olarak eklemektir. Sonra newSPAN düğümünü div1 düğümünün son çocuğu olarak ekledik. Yeni düğümü eklemeden önce "#text" alert mesajımız varken şimdi "SPAN" üretir. Yarattığımız yazı düğümünü <span> biçiminin sonuna eklemiş olduk. Eğer "div1" içine hem span hem de yazı düğümünü eklemek isteseydik:
document.getElementById("div1").appendChild(newSPAN);
document.getElementById("div1").lastChild.appendChild(newText);
alert(document.getElementById("div1").lastChild.nodeName);
"insertBefore(newNode, beforeNode)" aynı "appendChild()" gibidir yalnız düğümü son çocuk olarak eklemek yerine belirttiğiniz diğer düğümün önüne eklenmesi için kullanılır. Bu nedenle iki parametresi vardır.
Yani yukarıdaki örneğimizde yeni öğemiz SPAN2'yi SPAN!'in hemen önüne eklemek istiyor olsak:
SPAN2 = document.createElement("SPAN");
Şimdi "SPAN1" öğesine erişmemiz gerekir. Çünkü onun önüne yeni bir düğüm eklememiz söz konusudur.
SPAN1 = document.getElementById("div1").lastChild
Buradan insertBefore() metodunu kullanarak doğru yere ekleme yapabiliriz:
document.getElementById("div1").insertBefore(SPAN2,SPAN1);
ya da
document.getElementById("div1").insertBefore(SPAN2,
document.getElementById("div1").lastChild);
ya da
document.getElementById("div1").insertBefore(document.createElement("SPAN"),
document.getElementById("div1").lastChild);
Burada insertBefore() metodu baba düğümden çalıştırıldı. Çünkü bu düğümün çocuklarının listesi değişmektedir. Klonlama"cloneChild(node)" işlevi bir düğümü kopyalar ve değer olarak o düğümü döndürür. Bir parametresi vardır. O da kopyalanacak düğümün derin (deep) olup olmadığını belirtir. Örnek:
<body>
<div id="div1">
<span id="span1">This is the text of SPAN1</span>
<span id="span2">This is the text of SPAN2</span>
This text is not in a span tag.
</div>
</body>
div2=document.getElementById("div1").cloneNode(false)
Burada yalnız <div id="div1"></div> kopyalanır ve başka birşey kopyalamaz. Düğümün nitelikleri de kopyalanmaktadır. Şimdi bu düğüme yeni nitelikler ekleyebilir ya da düğümü istediğimiz yere taşıtabiliriz.
div2=document.getElementById("div1").cloneNode(true)
Kullanmış olsaydık "div1" altındaki çocuk düğümleri de kopyalardı:
<div id="div1">
<span id="span1">This is the text of SPAN1</span>
<span id="span2">This is the text of SPAN2</span>
This text is not in a span tag.
</div>
"derin" (deep) parametresini tanımlamazsak varsayılan değer "false" olur.
Kaybolma"removeChild(node)" parametresinde geçirilmiş olan düğümü siler. Unutmayın bu metod da baba düğümde çalıştırılmalıdır. Örnek:
<div id="div1">
<span id="span1">This is the text of SPAN1</span>
<span id="span2">This is the text of SPAN2</span>
This text is not in a span tag.
</div>
Eğer aşağıdaki satırı çalıştırırsak:
document.getElementById("div1").removeChild(document.getElementById("span2"))
"span2" düğümünü ve çocuklarını siler ve dökümanımızı:
<div id="div1">
<span id="span1">This is the text of SPAN1</span>
This text is not in a span tag.
</div>
görünümünde bırakırız.
"replaceChild(newChildNode, oldChildNode)" eski çocuğun dügümünü yeni çocuk düğümüyle değiştirir. Örnek:
<div id="div1">
<span id="span1">This is the text of SPAN1</span>
This text is not in a span tag.
</div>
Şimdi aşağıdaki komutları çalıştırırsak:
newSPAN = document.createElement("SPAN");
newSPAN.setAttribute("id","span2");
newSPAN.setAttribute("align","center");
newText = document.createTextNode("This is the text of SPAN2");
newSPAN.appendChild(newText);
div1 = document.getElementById("div1");
div1.replaceChild(newSPAN,div1.firstChild);
değiştirdiğimiz döküman şöyle gözükür:
<div id="div1">
<span id="span2" align="center" >This is the text of SPAN2</span>
This text is not in a span tag.
</div>
Bunlar W3C DOM Düzey 1 özellikleridir. Aynı biçimde Düzey 2 özelliklerine bakabiliriz.
Buradan Oraya
NS 6'da innerHTML kullanarak yazıyı değiştirmek istediğimizde çalışmıştı. Ama bu W3C'nin önerdiği biçimde değildi. Aslında NS 6 innerText, outerText ve outerHTML desteklemez, NS 6 yoğun istek karşısında yalnız innerHTML desteklemiştir.
İçeriği W3C önerilerine göre verimli bir biçimde değiştirmek için küçük öğeler yaratıl ardına yazı ekleyebiliriz. Örneğin aşağıdaki HTML kodunu başka bir öğeye yerleştirmek için çok iş yapmamız gerekir. Eklemek istediğimiz kod aşağıdadır:
Buradaki <b>Koyulaştırılmış</b> yazıdır.Ve bunu yaratmak için kullanmamız gereken aşağıdakidir:
text1 = document.createTextNode("This is ");
bTag = document.createElement("b");
textB = document.createTextNode("some bolded");
text2 = document.createTextNode(" text.");
bTag.appendChild(textB);
document.body.appendChild(text1);
document.body.appendChild(bTag);
document.body.appendChild(text2);
Bu kadar basit bir şey için gerçekten çok fazla bir iş. Halbuki biz:
document.body.innerHTML="This is some bolded text.";deyip işi bitirecektir. Görüldüğü gibi herbir öğeyi yaratmak çok zaman alıcı olacaktır. Sırf bu yüzden sınırlara gereksinim vardır. Sınır (range) bir HTML ya da XML içeriğinin belirli bir bölümüdür. Yazı düğümleri arasındaki birçok biçimi içerebilir. Bu ikinci düzeyin en önemli eklerindendir. NS 6'da düzgün çalışan ama IE 5'de çalışmayan sınır tanımını kullanan W3C DOM Standardıyla yazılmış kod aşağıdadır:
function writeLayerNSSix(node,txtHTML){
var newRange = document.createRange();
newRange.selectNodeContents(node);
newRange.deleteContents();
var newHTML = newRange.createContextualFragment(txtHTML);
node.appendChild(newHTML);
}
Şimdi bu işlevi "span1" içindeki yazıyı değiştirmekte kullanalım:
<div id="div1">
<span id="span1">Buradaki SPAN1 yazısıdır</span>
Buradaki span biçimi içinde olmayan yazıdır.
</div>
<script>
writeLayerNSSix(document.getElementById("span1"),
"Şimdi, buradaki <i>SPAN1</i><b>!</b> için <b>YENI</b> yazıdır");
</script>
Dökümanımız bu işlemden sonra aşağıdaki gibi olur:
<div id="div1">
<span id="span1">
Şimdi, buradaki <i>SPAN1</i><b>!</b> için <b>YENI</b> yazıdır
</span>
Buradaki span biçimi içinde olmayan yazıdır.
</div>
Soysal writeLayer() işlevini yeniden yazma.Katman içeriğini değiştirmek için daha önce yazdığımız işlev NS 6'da çalışıyor olsa bile W3C standartlarına uyumlu değildi. Şimdi kodumuz biraz daha uzun olacaktır. Başlamadan önce IE 5 ve NS 6 tarayıcılarını ayır edici bir yol bulmamız gerekecektir. "if(document.getElementById&&!document.all)" kullanabiliriz ve çalışır da... Ama IE 6' ya ne yapalım? IE 6 "document.all" desteklemektedir ve eski innerHTML metodunu kullanınca, NS 6 gibi W3C uyumlu çalışırken eski koda hata vermek durumunda kalacaktır. Böylece IE 5 ve IE 5.5 getAttributeNode() işlemini desteklemediğine göre "if(document.body.getAttributeNode)" kullanarak IE 6 ve NS 6 tarayıcılarını ayırmış oluruz. Şimdi katman içeriğini değiştirecek işlevi yazalım:
function writeLayer(layerID,txt){
if(document.body.getAttributeNode){
node = document.getElementById(layerID);
var newRange = document.createRange();
newRange.selectNodeContents(node);
newRange.deleteContents();
var newHTML = newRange.createContextualFragment(txtHTML);
node.appendChild(newHTML);
}else if(document.getElementById){
document.getElementById(layerID).innerHTML=txt;
}else if(document.all){
document.all[layerID].innerHTML=txt;
}else if(document.layers){
with(document.layers[layerID].document){
open();
write(txt);
close();
}
}
}
Burada düğüm geçirmek yerine parametrede katman kimliğini geçirdik. Bunu uyumluluk için yaptık ve aşağıdaki satırı yine uyumluluklar adına writeLayerNSSix() işlevine ekledik (eskiden bunlar yoktu):
node = document.getElementById(layerID);
Olaylar kullanıcıların yaptıklarına karşı çalışacak işlemlere denir. "olay yakalama" (Event handling) için aşağıdaki örnek çok kolay anlaşılacak türdendir:
<a href="javascript:void(0)" id="link1"
onMouseOver="alert('Hey, üzerimden çekil')">
Yanıma yaklaşma</a>
çalışan kod ise burada:
Bağın üzerine fareyle gelindiğinde "alert" (dikkat) mesajı veririz. Bu en temel/basit "olay yakalama" işlemidir. Önce IE 5'de olay nasıl yakalanıyor bakalım sonra DOM Düzey 2'ye geçeriz. Internet Explorer 5IE 5'de, olayları "attachEvent()" işlemiyle düğümlere atayabilirsiniz. Bu işlemin iki parametresi vardır. İşlenecek olay ve bu olayla çalışacak işlev. Örnek olması açısından aşağıdaki koda bakalım: Burada "onmouseover." kullanıldı. "onMouseOver," kullansam çalışmazdı. Hepsinin küçük harflerle olması gerekiyor. Bu örnekte "alerMessage()" işlemini çalıştırırken parantezleri kullanmadık. ![]() |
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||