JavaScript İle Temel DOM İşlemleri
DOM (Belge Nesne Modeli) ile ilgili detaylar değindiğim yazının ardından, konuyu JavaScript ile DOM işlemleri ile sürdürmek istiyorum.
Benzer bir konuya jQuery bağlamında jQuery Traversing / DOM Insertion, Around başlığı altında değinmiştim. Ancak, örnekler *wrap
metotları ile sınırlı kalmıştı. Bu yazıdaki örnekleri de temel teşkil etmesi açısından mümkün olduğu kadar farklılaştırmaya çalışacağım.
DOM (Belge Nesne Modeli)
DOM (Belge Nesne Modeli) Nedir? yazısında da bahsi geçtiği üzere; DOM, HTML, XHTML, XML gibi belgelerin script dilleriyle iletişim kurabilmesini sağlamak için geliştirilmiş bir arabirimdir ve bir W3C standardıdır. W3C tarafından; DOM, programların ve komut dosyalarının bir belgenin içeriğine, yapısına ve stiline dinamik olarak erişmesini ve güncellemesini sağlayan bir platform ve dilden bağımsız bir arayüz şeklinde ifade edilmektedir1 2.
Bir HTML dosyasında yer alan bütün elemanlar DOM nesnesi (object) olarak nitelendirilir. JavaScript temelinde bir global nesneden (window
) bahsetmiştim. Özetlemek gerekirse, window
tarayıcı penceresini ifade eden bir global nesnedir ve tarayıcı penceresindeki tüm nesneleri kapsar. document
nesnesi ise DOM yapısını içerir3 4 5. window.document
ile document
aynı tanımlardır6. document
içerisinde yer alan bir iframe
eleman olarak tanımlanabilir, ancak içeriği ayrı bir window
nesnesi, iframe
içerisinde render edilen HTML elemanları ise bu iframe
'e ait document
(window.document
) ile ilişkilenir. Bu konu ile ilgili olarak Web API window.postMessage İle Pencereler Arası İletişim başlıklı yazıma göz atabilirsiniz.
Doküman İçeriği
Tekrar DOM ve dolayısıyla document
nesnesine dönelim. Aşağıdaki yapı bize temel bir HTML dokümanını verecektir. Eklenecek diğer elemanlar (link, div, vb.) DOM ağacını daha da detaylandırabiliriz. Bu DOM yapısı içerisindeki her elemana konumu, sırası, tanımı (tag), class ve id gibi seçiciler sayesinde erişebilir ve JavaScript kullanarak manipüle edebiliriz.
<html>
<head>
...
</head>
<body>
...
</body>
</html>
Modern bir internet tarayıcısının console alanına document
yazdığınızda DOM ile ilişkili tüm detaylara ulaşabilirsiniz.
Listelenen bu bilgiler arasında, ilk node (düğüm) firstChild
ile erişilebilir7 8. firstElementChild
ve documentElement
html
etiketine ulaşabilmemizi sağlar. Elbette DOM yapsına göre içerikler farklılık arz edebilir. Aynı şekilde, son node da erişilebilir durumdadır ve lastChild
, lastElementChild
ile bu işlem gerçekleştirilebilir. İlgili node'ların her birinin html
etiketiyle ilişkili olduğunu görebilirsiniz. Bunun nedeni html
elemanın bir DOM içerisinde kullanılan en üst kapsayıcı node olmasıdır. Bu nedenle root element olarak nitelendirilmektedir.
html
sonrasında, bir alt seviyede head
, body
elemanları yer alır. Bu nedenle, body
, head
, documentElement
, title
tek bir nesneyi döndürürken, diğer elemanlar dizi (array) döndürebilir. Bu duruma örnek olarak aşağıdaki yapılar incelenebilir.
Az önce de bahsi geçtiği üzere; document.head
, head
etiketini, document.body
ise body
etiketini getirir. document.title
ile sayfa başlığına ulaşabiliriz. document.documentElement
bize root element olan HTML ile birlikte tüm dokümana ulaşma imkanı verir.
Doküman içerisinde bulunan tüm bağlandılara document.links
(<a href="...">...</a>
) ile ulaşabiliriz. Eğer gömülü elemanlar (<object>
) var ise document.embeds
, formlar document.forms
, görseller document.images
ve script dosyaları document.scripts
ile listelenebilir. Bunların yanı sıra fontlar, eklentiler, stil dosyaları ve çerezler gibi daha pek çok bilgiye ulaşmak mümkün4.
// <head></head>
document.head
// <body></body>
document.body
Bir örnek bir HTML dosyası oluşturalım. Bu HTML dosyasını yazının kalan bölümünde de kullanacağım. Tarayıcının console alanına document
yazdığınızda bu HTML dosyası içeriğine dair bilgiler listelenecektir.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Hello World!</title>
</head>
<body id="page" class="single-page">
<div id="main" class="container">
<div class="row">
<div class="col">
<h1>Lorem Ipsum</h1>
</div>
<div class="col">
<p><strong id="status">Dolor Sit Amet</strong></p>
</div>
<div class="col">
<ul class="list">
<li class="even">List item <span>(1)</span></li>
<li class="odd">List item <span>(2)</span></li>
<li class="even">List item <span>(3)</span></li>
<li class="odd">List item <span>(4)</span></li>
</ul>
</div>
<div class="col">
<div id="even">
<strong>Even</strong>
<ul>
<li>List item 5</li>
</ul>
</div>
<div id="odd">
<strong>Odd</strong>
<ul>
<li>List item 6</li>
</ul>
</div>
</div>
</div>
</div>
</body>
</html>
JavaScript ile ilgili elementlere getElementsByClassName()
, getElementsByTagName()
, getElementById()
başta olmak üzere pek çok metot vasıtasıyla erişebilmekteyiz. Dikkat çekmek istediği bir konu ilgili metot tanımındaki getElements*
ve getElement*
ayrımı. Çoğul kullanımda bir dizi dönüş yapacaktır. ID ise class ve tag'lerden farklı olarak benzersiz bir tanımlayıcıdır9.
const el = document.getElementById('status');
console.log(el.innerHTML); // Dolor Sit Amet
const el = document.getElementsByTagName('strong');
[...el].forEach(e => console.log(e.innerHTML)); // el.status.innerHTML
Element ilişkili metotların yanı sıra, DOM içerisinde sorgu (query) temelli seçimler de yapabilmekteyiz. Sorgu bir tag olabileceği gibi, class, id veya bir öznitelik (attribute) değer(ler)i ile ilgili de gerçekleştirilebilir.
document
.querySelector('p');
document
.body
.querySelector("style[type='text/css'], style:not([type])");
document
.querySelectorAll('[data-name*="funnel-chart-percent"]');
document
.querySelectorAll('iframe[data-src]');
querySelector()
belirtilen seçici grubuyla eşleşen ilk elemanı döndürürken10, querySelectorAll()
belirtilen seçici grubuyla eşleşen öğelerin bir statik listesini (NodeList) döndürür11.
Tekrar örneğimize dönelim ve col
class'ına sahip ilk elemanı seçelim.
document
.getElementsByClassName('col')[0];
Şimdi bu örneği biraz daha detaylandıralım ve col
class'ına sahip 3. eleman içerisindeki 3. li
etiket içeriğine ulaşalım.
document
.getElementsByClassName('col')[2]
.getElementsByTagName('li')[2]
.innerHTML;
// ya da
document
.querySelector('.col>ul>li:nth-child(3)')
.innerHTML;
Yukarıdaki örnek HTML içerisinde, liste elemanları even
ve odd
class'larına sahipler. Yeni örneğimizde, even ve odd olarak 2 section oluşturup liste elemanlarının değerlerini ilgili section içerisine alalım12 13.
[...document.querySelectorAll('.list li')]
.forEach(e => document
.getElementById(e.className)
.querySelector('ul')
.innerHTML += e.outerHTML);
Element İşlemleri
Artık, doküman içerisinde sırasına, diğer node ile ilişkisine, class, id veya tag tanımına ve hata özniteliklerine göre DOM içi elemanlara nasıl ulaşabileceğimizi biliyoruz. O halde, şimdi ulaştığımız bu elemanlarla ilgili detaylara nasıl ulaşabileceğimize bakalım14.
Yukarıda da bahsi geçtiği üzere; innerHML
ve outerHTML
birer Element propety. innerHML
, öğenin içerdiği HTML veya XML biçimlendirmesini string olarak verir veya ayarlarken15, outerHTML
ilgili Element'in kendisini de dahil ederek alt elemanlarla beraber string olarak verir veya ayarlar16.
document.getElementById('status').innerHTML; // "Dolor Sit Amet"
document.getElementById('status').outerHTML; // "<strong id=\"status\">Dolor Sit Amet</strong>"
innerHML
ve outerHTML
dışında, attributes
, classList
, className
, id
ve tagName
gibi tanımları kullanarak seçme ve getAttribute()
, hasAttribute()
, getAttributeNames()
, hasAttributes()
, matches()
gibi metotlarla da listeleme ve düzenleme işlemleri gerçekleştirilebilmekte9.
document.getElementsByTagName("strong")[0].attributes // [id="status"]
document.getElementsByTagName("body")[0].attributes // [id="page", class="single-page"]
for (let name of document.querySelector('ul').getAttributeNames()) {
let
value = document
.querySelector('li')
.getAttribute(name);
console.log(`name: ${name}, value: ${value}`); // name: class, value: even
value
.setAttribute("class", "odd");
}
Yeni elementler oluşturmak ve/veya var olan elementleri silmek istediğimizde ise createElement()
, removeChild()
, appendChild()
, replaceChild()
metotlarından document
düzeyinde faydalanabilmekteyiz4 17 18.
let
newItem = document
.createElement('li'),
updatedItem = document
.getElementById('even')
.getElementsByTagName('ul')[0];
newItem
.textContent = 'List item 7';
updatedItem
.appendChild(newItem)
.setAttribute('class', 'new');
Son olarak, farklı iç içe node'ların sahip olduğu değerleri alabileceğimiz bir örnek ile yazısı sonlandıralım. Yukarıdaki HTML içeriği içerisinde yer alan listeleri tıklayarak console alanından iletilen değerleri takip edebilirsiniz.
[...document.querySelectorAll('ul')].forEach(item => {
item.addEventListener('click', el => {
let value = el.target.firstChild.nodeValue.trim().replace(/[()]/g,'');
(value === '') ? console.log('Empty area!') : console.log(value);
});
});
Yukarıdaki örnek kod parçacığı even
id'li liste içerisine yeni bir item eklemekte ve bu item için new
class'ı atamakta. DOM manipülasyonu ile ilgili başlangıç yazısının devamı olarak ilgili bir sonraki yazıda bir to-do list uygulaması hazırlayacağım19 14 20. Ardından, ilgili metotları kullanarak21 22 23 veri listeleme ve görselleştirme konularını detaylandıracağım.
- DOM. Living Standard ↩
- Document Object Model. Wikipedia ↩
- Window. MDN web docs ↩
- Document Object Model (DOM). MDN web docs ↩ ↩ ↩
- JavaScript HTML DOM Examples. w3schools ↩
- What is the difference between window, screen, and document in Javascript? StackOverflow ↩
- HTML DOM firstChild Property ↩
- Node.firstChild. MDN web docs ↩
- Element. MDN web docs ↩ ↩
- Element.querySelector. MDN web docs ↩
- Element.querySelectorAll. MDN web docs ↩
- Get first element of array in JavaScript ↩
- Array.prototype.find. MDN web docs ↩
- JavaScript DOM. javascripttutorial ↩ ↩
- Element.innerHTML. MDN web docs ↩
- Element.outerHTML. MDN web docs ↩
- Manipulating documents. MDN web docs ↩
- Manipulating DOM Elements. plainjs ↩
- Preethi Ranjit. (2017). 15 JavaScript Methods For DOM Manipulation for Web Developers ↩
- Sebastian Eschweiler. (2020). Building A Vanilla JavaScript Todo App From Start To Finish | EP 1: Introduction & Project Setup ↩
- JavaScript DOM Manipulation. tutorialrepublic ↩
- George Ilias. (2020). Manipulating DOM in JavaScript for beginners ↩
- Krasimir Tsonev. (2014). A DOM Manipulation Class in 100 Lines of JavaScript ↩