Hazirlayan: Bektur Karkakozhaev
JavaScript ne için kullanılır? JavaScript, bir web sitesinin içeriğini değiştirmek ve kullanıcı eylemlerine yanıt olarak farklı davranmasını sağlamak için kullanılabilen mantıksal bir programlama dilidir.
JavaScript çoğunlukla önceden var olan sayfa öğeleriyle çalışır. Ancak, bu öğelerin bir şekilde seçilmesi gerekir. Bu makalede açıklanan yöntemler bunu yapmanıza yardımcı olacaktır. Sayfa öğeleriyle çalışırken karşılanması gereken iki koşul vardır:
<script></script> etiketlerini, kodun manipüle etmesini istediğiniz html sayfası öğelerinden sonra ihtiyacınız olan kodla birlikte yerleştirin. İdeal olarak, kapanış </body> etiketinden önce, çünkü tüm biçimlendirmenin yerleştirildiği yer burasıdır. <script></script> etiketleri <head></head> bloğuna yerleştirilirse, window.onload = function(){} olay işleyicisine kod yazmanız gerekir veya
document.addEventListener("DOMContentLoaded",
function(event) { console.log("DOM yapısı yüklendi");
});
2. Çoğu durumda birden fazla öğeye sahip olacağınız için öğeleri doğru şekilde bulun ve üzerinden geçin.
3. Eleman koleksiyonlarının dizilerden farklı olduğunu anlama
Tek bir öğeyi bulma yöntemleri
Aşağıda tartışılan her iki yöntem de sorgunuzla eşleşen bir html öğesine bir bağlantı döndürür.
Yöntem document.getElementById()
document.getElementById('some_id') yöntemi, bir öğeyi parantez içinde dize parametresi olarak geçirilen kimliğine göre bulmayı sağlar. HTML spesifikasyonuna göre, bu id'ye sahip bir öğenin sayfada yalnızca bir örneği olmalıdır. Bu kuralı ihlal ederseniz, HTML-CSS bunu atlayacak ve birkaç öğeyi eşit şekilde biçimlendirecektir, ancak JavaScript yalnızca bu tür ilk öğeyi bulacak ve yalnızca onu biçimlendirecektir.
Örneğin, bu işaretlemeye ve css stillerine sahibiz:
<style>
#someWrapper {
display: flex;
justify-content: space-between;
text-align: center;
}
.some-block {
border: 2px dotted blue;
padding: 10px;
flex: 0 0 28%;
margin-bottom: 10px;
}
</style>
<div id="someWrapper">
<div class="some-block">
<h2>Block 1 in someWrapper 1</h2>
</div>
<div class="some-block">
<h2>Block 2 in someWrapper 2</h2>
</div>
<div class="some-block">
<h2>Block 3 in someWrapper 3</h2>
</div>
</div>
<div id="someWrapper">
<div class="some-block">
<h2>Block 1 in someWrapper 1</h2>
</div>
...
</div>
<div id="someWrapper">
<div class="some-block">
<h2>Block 1 in someWrapper 1</h2>
</div>
...
</div>
Örnekten de görebileceğiniz gibi, css-biçimlendirmesi id="someWrapper" ile 3 bloğa da uygulanmıştır, ancak bu durum semantikle çelişmektedir.
Örneğimiz için bazı JS kodları yazalım ve düğmeye tıklandığında uygulayalım.
const some=document.getElementById('someWrapper');
some.style.backgroundColor = '#cde';
//Sadece id kullanırsanız, bu da işe yarar
someWrapper.style.fontStyle = 'italic';
Yöntem document.querySelector()
document.querySelector('css-selector') yöntemi, sayfada parametre olarak aktarılan css-selector ile eşleşen ilk öğeyi bulur. Bu yöntemin adından ve açıklamasından, her türlü css-seçici arasında gezinmeniz gerektiği açıktır. Adil olmak gerekirse, bir öğeyi id veya sınıfa göre aramak için de kullanılabilir (bunlar herkesin bilmesi gereken basit seçicilerdir). İlk durumda document.getElementById() yerine geçecek, ikincisinde ise belirtilen sınıfa sahip ilk öğeyi bulacaktır.
<ol id="testOl">
<li class='li-item'>Liste öğesi <strong>1</strong></li>
<li class='li-item'>Liste öğesi <strong>2</strong></li>
<li class='li-item'>Liste öğesi <strong>3</strong></li>
<li class='li-item'>Liste öğesi <strong>4</strong></li>
<li class='li-item'>Liste öğesi <strong>5</strong></li>
<li class='li-item'>Liste öğesi <strong>6</strong></li>
<li class='li-item'>Liste öğesi <strong>7</strong></li>
</ol>
<script>
const liItem = document.querySelector('.li-item'),
liLast = document.querySelector('#testOl li:last-child'),
strongElem = document.querySelector('#testOl .li-item:nth-child(3) strong');
console.log(liLast);
liItem.style.cssText = 'line-height: 2; background-color:#8af2ce;'
liLast.style.cssText = 'list-style-type:upper-roman; font-weight: bold';
strongElem.style.color = 'red';
</script>
Sonuç olarak elde ettiğimiz şey bu:
Liste öğesi 1
Liste öğesi 2
Liste öğesi 3
Liste öğesi 4
Liste öğesi 5
Liste öğesi 6
VII. Liste öğesi 7
Yöntem element.closest()
element.closest() yöntemi, parantez içinde aktarılan seçiciyle eşleşen en yakın üst öğeyi veya verilen bir öğeyi bulmak için kullanılır. Böyle bir öğe bulunamazsa null döndürülür. Sözdizimi:
// wrap kimliğine sahip elemanın içinde bulunan satır sınıfına sahip eleman
let parent = element.closest('#wrap .row');
//veya data-description niteliğine sahip bir div
div = element.closest('div[data-description]') olsun;
Yani, parantez içinde css'de seçici yazma kurallarına uygun bir seçici geçirirsiniz.
Başka bir eşleşme bulunamazsa veya çok genel bir seçici belirttiyseniz, örneğin bir eleman seçici olarak (span, p, div, vb.), aradığımız elemana bir referansın da dönebileceğini unutmayın.
Çoğu zaman element.closest() yöntemi, iç içe geçmiş bir öğe üzerinde bir olay işlenirken üst öğeyi bulmak için kullanılır. Yaygın bir örnek, ödeme sırasında bir tablo satırının silinmesidir
Yöntem element.matches("selector")
element.matches("css-selector") yöntemi, öğenin belirtilen css-selector ile eşleşip eşleşmediğine bağlı olarak true veya false döndürür. Seçiciyi css kurallarına göre ayarlarsınız, yani id="my-test" ile seçmek için "#my-test", liste içinde bir sınıf aramak için "ul .my-class" querySelector() yönteminde yaptığınız gibi ayarlarsınız.
Belirli bir seçiciye işlevsellik eklemek için herhangi bir koşulu test etmek için bu yöntemi kullanmaya değer. Örneğin, listedeki 3. öğenin metnini kırmızı olarak seçmemiz gerekiyor. Bunu css'de yapmak daha kolaydır, ancak öğe numarasını kullanıcıdan dinamik olarak aldığımızı varsayalım.
Kod aşağıdaki gibi olacaktır:
<ul>
<li>Lorem ipsum dolor sit.</li>
<li>Quae quis, eveniet provident.</li>
<li>Possimus laudantium, soluta error?</li>
<li>Ea suscipit, provident quos!</li>
</ul>
<script>
let li = document.querySelectorAll('li');
for(item of li){
if(item.matches('li:nth-child(3)')) item.style.color = 'red';
}
</script>
Sonuç: Listedeki 3. madde gerçekten kırmızıya döndü:
Lorem ipsum dolor sit.
Quae quis, eveniet provident.
Possimus laudantium, soluta error?
Ea suscipit, provident quos!
contains() yöntemi
Node.contains(element) metodu, bir üst Node'un içinde bir element olup olmadığını kontrol eder. Bu yöntem, düğümün verilen düğümün soyundan gelip gelmediğini, yani düğümün kendisi, doğrudan soyundan gelenlerden biri (childNodes), çocuklarının çocuklarından biri vb. olup olmadığını gösteren bir boolean değeri true veya false olarak döndürür.
Pratik kullanım açısından, işte bir örnek: 2'si harici kaynağa referans içeren ve 2'si içermeyen 4 bloğumuz var. Bloğun görünümünü bozmamak için, içinde "descr" sınıfına sahip bir referans olup olmadığını kontrol ediyoruz ve ona mutlak konumlandırmayı belirten bir sınıf ekliyoruz.
Birden fazla eleman bulma yöntemleri
Tipik olarak, bir sayfada aynı sınıf adına, etiket adına (örneğin <p> paragrafları veya <nav>) veya her tablo satırındaki son hücreye sahip bir dizi öğe olacaktır. Bunların css özelliklerini tercihen stillerle değiştirin, ancak genellikle aynı türdeki tüm öğelere aynı anda dinamik olarak css veya olay işleyicileri atamak gerekir.
Yöntem document.querySelectorAll()
Kardeşi document.querySelector() yönteminin aksine, bu yöntem bir düğüm koleksiyonu olan bir öğe kümesi döndürür ve kodda bu dikkate alınmalıdır. Koleksiyon, her bir öğeye indeksle başvurmanıza olanak tanıyan ve length (koleksiyonun uzunluğu veya içindeki html öğelerinin sayısı) gibi bir özelliğe sahip olan, ancak yine de öğeleri için dizi yöntemlerini kullanmanıza izin vermeyen sözde bir dizidir.
document.querySelectorAll() yönteminin bir istisnası, koleksiyondaki öğeleri numaralandırmanıza ve istediğiniz özellikleri veya olay işleyicilerini atamanıza yardımcı olan forEach() yöntemidir. Birden fazla öğe aramaya yönelik diğer yöntemler, forEach() yöntemine sahip olmadıkları için bu özelliği sağlamaz. document.querySelectorAll() için de forEach() yönteminin nispeten yakın zamanda eklendiğini, bu nedenle çok yeni olmayan bazı tarayıcıların bu yöntemi kullanırken hata verebileceğini unutmayın.
Yöntem document.getElementsByClassName()
Adından da anlaşılacağı gibi, document.getElementsByClassName('className'), parantez içinde bir nitelik olarak geçirilen sınıfı içeren bir HTML öğe koleksiyonu döndürür. Dolayısıyla document.querySelectorAll() işlevinden daha dar bir örnekleme kapsamına sahiptir. Bununla birlikte, yalnızca bir sınıftan öğe seçmeniz gerekiyorsa kullanılabilir.
Aşağıdaki örnekte, "example-edit" sınıfına sahip tüm paragrafları seçmek için document.getElementsByClassName('className') kullanacağız ve contenteditable = "true" ekleyerek tıklama olayında düzenlenebilir hale getireceğiz. Ayrıca, her paragraftaki karakter sayısını saymamızı ve çıktısını almamızı sağlayacak olan oninput olayını da işleyeceğiz.
Yöntem document.getElementsByTagName()
document.getElementsByTagName('tagName') yöntemi, belirli bir etikete göre öğeleri seçmek için tasarlanmıştır. Yani, html sayfamızdaki tüm paragraflara, girdilere veya bölümlere erişmemizi sağlar.
Yöntem document.getElementsByName()
document.getElementsByName('name') yöntemi, sayfadaki öğelerin bir name niteliğine sahip olması gerektiğini varsayar. Form öğeleri bu niteliğe sahiptir. Bu yöntem, parantez içinde belirtilen ada sahip öğeleri bir koleksiyonda (sözde dizi) topladığından, bu yöntem genellikle aynı ada sahip olabilen radyo düğmeleri veya onay kutuları için kullanılır. Bunlar <input type="radio"> veya <input type="checkbox"> türündeki öğelerdir. Diğer tüm form öğeleri için bu yöntemin uygulanması pek olası değildir, çünkü muhtemelen benzersiz adlara sahip olacaklardır.
Dinamik ve statik koleksiyonlar
En son ele alınan document.getElementsByName(), document.getElementsByTagName() ve document.getElementsByClassName() yöntemleri, içlerinde html öğelerinin dinamik koleksiyonlarını saklar; bu da, örneğin öğeler klonlanarak elde edilirse içlerindeki öğe sayısının artabileceği veya remove() veya removeChild() ile kaldırılarak sayfadan kaybolursa ya da sınıf adı değişirse azalabileceği anlamına gelir. Bazı durumlarda, bu durum kafanızın karışmasına neden olabilir, çünkü öğeler beklediğiniz şekilde davranmayacaktır. Bu bazı dezavantajlar olarak adlandırılabilir. Öte yandan, bu davranış, örneğin görev listesinde kaç öğenin sürekli değiştiğini takip etmenizi sağlar. Bu da bir artıdır.
document.querySelectorAll() yöntemi, bu yöntemin çağrıldığı sırada sayfada bulunan DOM düğümlerinin sayısının bir seçimini saklar. Bu nedenle, bu yöntemde belirtilen seçiciyle eşleşen yeni oluşturulmuş öğeler bu koleksiyona dahil edilmeyecek ve silinen öğeler mevcut öğeler olarak listelenmeye devam edecektir. Bu nedenle bu seçim statik olarak kabul edilebilir. Çoğu durumda bu durumdan memnun olduğumuz için, çünkü sayfadaki öğeler çok sık eklenmez veya silinmez ve yöntemin kendisi istediğiniz seçiciyle eşleşen öğeleri seçmenize olanak tanır - sınıf, etiket adı, ad niteliği ve bir dizi başka seçeneğe göre - statik koleksiyonlar, örneğin olayları ele almak için harika bir yoldur.
Bağlantı, resim ve form koleksiyonları
Bağlantılar, resimler ve formlar için diğer yöntemlerle paralel olarak kullanılabilecek özel koleksiyonlar vardır, yani
document.links - sayfadaki tüm bağlantılar için
document.images - resimler için
document.forms - formlar için
Gerekirse bunlara bir dizi öğesi olarak başvurabilirsiniz, örneğin sayfadaki ilk bağlantıya erişmek document.links[0] ve ikinci resim document.images[1] gibi görünecektir. Bunlara ayrıca id veya name ile de erişilebilir, örneğin document.forms['myForm'].
Tüm bu koleksiyonların adının sonunda bir 's' harfi olduğuna dikkat edin, yani bir sayfada birden fazla bağlantı, resim ve form olabileceği anlamına gelir. Tek bir resim, bağlantı veya form olsa bile, html işaretlemesinde bir dize varsa, bunlara yalnızca sonunda 's' olan koleksiyon adı aracılığıyla erişilebilir, örneğin document.images['pic1']:
<img src="img/mypic.jpg" id="pic1" alt="Picture">
Kişi listesini sıralamak için document.links koleksiyonunu kullanma örneği için "Handling onkeyup events" makalesine bakın.
Html koleksiyonları için dizi yöntemlerini kullanma
Daha önce de belirtildiği gibi, html koleksiyonları, her eleman için numaralandırılmış indislere sahip olan, uzunluk özelliğinde sayılarını döndüren, ancak forEach(), map(), reduce(), filter() gibi yöntemlerle dizi numaralandırmaya izin vermeyen sözde dizilerdir.
Ancak, bir sözde diziyi bir diziye dönüştürerek durumu değiştirebiliriz.
Yöntem 1: call() yöntemini kullanma
call() yöntemi, dizi yöntemlerinden herhangi birini çağırmamıza ve koleksiyonumuzu ona bir argüman olarak geçirmemize olanak tanır. Bu yaklaşımı tablo satırları için zaten kullanmıştık.
let tr = testTable.getElementsByTagName('tr');
console.log(tr instanceof Array); //false
tr = [].slice.call(tr);
// veya biraz daha uzun
//tr = Array.prototype.slice.call(tr);
console.log(tr instanceof Array); //true
Tablonun tr satırındaki her bir td hücresinin numarasını (indeksini) almayı deneyebilirsiniz (bu kodu onclick işlevine kontrol etmek için koyun):
let indexTD = Array.prototype.indexOf.call(this.children, evt.target);
Yöntem 2: Array.from() yöntemini kullanma
Array.from() yöntemi call() yönteminden çok daha yenidir, yalnızca modern tarayıcılar tarafından desteklenir, ancak basit ve anlaşılır bir sözdizimine sahiptir. Bir sözde diziyi bu şekilde bir diziye dönüştürür:
let pars = document.getElementsByClassName('example-edit');
console.log(pars instanceof Array); //false
pars = Array.from(pars);
console.log(pars instanceof Array); //true
Yöntem 3: Bir genişletme operatörü kullanma
Genişletme operatörü veya yayma operatörü daha da basittir - istediğiniz sözde diziyi iki nokta üst üste ile köşeli parantez içine koyar ve böylece bir diziye dönüştürürsünüz:
let liElems = document.getElementsByTagName('li');
[...liItems].forEach(item => item.addEventListener('click', myFunc))
Bu dönüşümden sonra, html koleksiyonları için tüm dizi yöntemlerini kullanabilirsiniz.