Hujjat (DOM)

Atributlar va xossalar

Brauzer HTML sahifasini yuklaganda, teglarni "o'qib" (parse qilib), DOM obyektlarini yaratadi. Element tugunlari uchun standart HTML atributlari mos DOM xossalariga aylanadi. Masalan, <body id="page"> uchun DOM obyektida body.id === "page" bo'ladi. Ammo bu "atribut โ†’ xossa" moslashuvi 1-ga-1 emas! Ushbu darsda atribut va xossalar orasidagi nozik, ammo muhim farqlarni chuqur o'rganamiz.

DOM xossalari

Biz DOM tugunlari standart JavaScript obyektlari ekanligini ko'rdik. Ular xossalar to'plamiga ega. Va biz ularga o'z xossalarimizni ham qo'shishimiz mumkin โ€” huddi oddiy obyektlarga o'xshab:

document.body.myData = {
  name: 'Sezar',
  title: 'Imperator'
};

alert(document.body.myData.title); // Imperator

// hatto metod ham qo'shsak bo'ladi
document.body.sayTagName = function() {
  alert(this.tagName);
};

document.body.sayTagName(); // BODY (this qiymati document.body)

Prototipni ham o'zgartirishimiz mumkin, masalan barcha elementlarga yangi metod qo'shish uchun:

Element.prototype.sayHi = function() {
  alert(`Salom, men ${this.tagName}`);
};

document.documentElement.sayHi(); // Salom, men HTML
document.body.sayHi(); // Salom, men BODY

Demak, DOM xossalari va metodlari oddiy JavaScript obyektlarinikidek ishlaydi: istalgan qiymat qabul qiladi, katta-kichik harfga sezgir (elem.nodeType, elem.NodeType emas).

HTML atributlari

HTML'da teglar atributlarga ega bo'lishi mumkin. Brauzer HTML'ni o'qiganda standart atributlarni tanib, ulardan DOM xossalarini yaratadi.

Ammo elementda nostandart (standartda bo'lmagan) atribut bo'lsa, u mos DOM xossasiga aylanmaydi. Masalan:

<body id="test" something="nostandart">
  <script>
    // standart atribut xossaga aylandi
    alert(document.body.id); // test

    // nostandart atribut โ€” yo'q
    alert(document.body.something); // undefined
  </script>
</body>

E'tibor bering: bir element uchun standart atribut boshqa element uchun noma'lum bo'lishi mumkin. Masalan, type atributi <input> uchun standart (HTMLInputElement), ammo <body> uchun emas. Standart atributlar aniq element sinfida tasvirlanadi.

Shunda ham, barcha atributlarga (standart va nostandart) DOM metodlari orqali kirishimiz mumkin:

<body something="nostandart">
  <script>
    let body = document.body;

    alert( body.getAttribute('something') ); // nostandart
    body.setAttribute('test', 123);
    alert( body.outerHTML ); // <body something="nostandart" test="123">

    // barcha atributlarni aylanamiz
    for (let attr of body.attributes) {
      alert( `${attr.name} = ${attr.value}` );
    }
  </script>
</body>

HTML atributlarining ikkita muhim xususiyati bor:

  1. Nomi katta-kichik harfga sezgir emas: id va ID bir xil (chunki atributlar HTML'ga tegishli, HTML esa katta-kichik harfga befarq);
  2. Qiymatlari doim satr (string): getAttribute har doim satr qaytaradi, hatto biz son o'rnatgan bo'lsak ham.
<div id="elem" about="Elephant"></div>

<script>
  alert( elem.getAttribute('About') ); // Elephant (katta-kichik befarq)

  elem.setAttribute('Test', 123); // son berdik...

  alert( elem.outerHTML ); // <div id="elem" about="Elephant" test="123">
  // ...ammo satr sifatida saqlandi
</script>

Xossa-atribut sinxronizatsiyasi

Standart atribut o'zgarsa, mos xossa avtomatik yangilanadi โ€” va (aksariyat hollarda) teskarisi ham. Ular sinxronlashadi:

<input>

<script>
  let input = document.querySelector('input');

  // atribut => xossa
  input.setAttribute('id', 'id');
  alert(input.id); // id (yangilandi)

  // xossa => atribut
  input.id = 'newId';
  alert(input.getAttribute('id')); // newId (yangilandi)
</script>

Ammo bu sinxronizatsiyaning istisnolari bor. Masalan, input.value faqat atributdan xossaga sinxronlashadi, ammo teskarisiga EMAS:

<input>

<script>
  let input = document.querySelector('input');

  // atribut => xossa (ishlaydi)
  input.setAttribute('value', 'matn');
  alert(input.value); // matn

  // xossa => atribut (ISHLAMAYDI)
  input.value = 'yangi';
  alert(input.getAttribute('value')); // matn (o'zgarmadi!)
</script>
Yuqoridagi "xususiyat" aslida foydali: foydalanuvchi <input> qiymatini o'zgartirsa (yozsa), value xossasi yangilanadi, ammo value atributi HTML'dagi ASL (dastlabki, default) qiymatni saqlab qoladi. Bu esa "formani asl holatiga qaytarish" (reset) kabi vazifalarda qo'l keladi.

DOM xossalari tur (type) bo'yicha farqlanadi

DOM xossalari har doim satr emas! Ular turli tiplarda bo'lishi mumkin, atributlar esa har doim satr. Bir necha misol:

1. input.checked โ€” checkbox uchun โ€” mantiqiy (boolean) qiymat:

<input id="input" type="checkbox" checked>

<script>
  alert(input.getAttribute('checked')); // atribut: '' (bo'sh satr)
  alert(input.checked); // xossa: true (boolean)
</script>

2. style atributi satr, ammo style xossasi โ€” obyekt:

<div id="div" style="color:red;font-size:120%">Salom</div>

<script>
  // atribut โ€” satr
  alert(div.getAttribute('style')); // color:red;font-size:120%

  // xossa โ€” obyekt
  alert(div.style); // [object CSSStyleDeclaration]
  alert(div.style.color); // red
</script>

3. Ba'zi hollarda atribut va xossa qiymatlari farq qiladi. Masalan, href atributi HTML'da yozilgan qiymatni saqlaydi, href xossasi esa har doim TO'LIQ URL manzilini qaytaradi:

<a id="a" href="#salom">havola</a>

<script>
  // atribut: HTML'da yozilgani
  alert(a.getAttribute('href')); // #salom

  // xossa: to'liq URL
  alert(a.href); // http://site.com/page#salom (to'liq)
</script>
Agar atributdagi AYNAN yozilgan qiymat kerak bo'lsa โ€” getAttribute ishlating. Agar odatiy, qulay talqin (masalan to'liq URL yoki boolean) kerak bo'lsa โ€” DOM xossasidan foydalaning.

Nostandart atributlar va dataset

Ba'zan JavaScript'dan HTML'ga ma'lumot uzatish yoki elementlarni "belgilash" uchun nostandart atributlar ishlatiladi. Masalan:

<div show-info="name"></div>
<div show-info="age"></div>

<script>
  // show-info atributi bo'yicha elementlarni topib,
  // ularga ma'lumot joylaymiz
  for (let div of document.querySelectorAll('[show-info]')) {
    let field = div.getAttribute('show-info');
    div.innerHTML = field; // name yoki age
  }
</script>
Nostandart atributlarni ishlatish xavfli: bugun ular standart emas, ammo ertaga HTML standartiga qo'shilishi mumkin. Shunda bizning nostandart atributimiz standart atribut bilan to'qnashib, kutilmagan xatti-harakat keltirib chiqaradi. Bunday to'qnashuvlarning oldini olish uchun maxsus yechim bor: data-* atributlar.

data-* atributlar va dataset

data- bilan boshlanadigan barcha atributlar dasturchilar foydalanishi uchun ZAXIRALANGAN. Ular elem.dataset obyekti orqali qulay o'qiladi:

<body data-about="Fillar">
  <script>
    // data-about => dataset.about
    alert(document.body.dataset.about); // Fillar
  </script>
</body>

Bir nechta so'zdan iborat data-order-state kabi atributlar camelCase shaklga aylanadi: dataset.orderState:

<style>
  .order[data-order-state="new"] { color: green; }
  .order[data-order-state="pending"] { color: blue; }
</style>

<div id="order" class="order" data-order-state="new">
  Yangi buyurtma
</div>

<script>
  // o'qish
  alert(order.dataset.orderState); // new

  // yozish (CSS ham avtomatik yangilanadi!)
  order.dataset.orderState = 'pending'; // rang ko'kga o'zgaradi
</script>
data-* atributlaridan foydalanish HTML'da maxsus ma'lumot saqlashning to'g'ri va xavfsiz usuli. Ular hech qachon standart HTML atributi bilan to'qnashmaydi (standart hech qachon data- bilan boshlanmaydi). Bundan tashqari, dataset ularni o'qish va yozishni juda qulay qiladi, hamda CSS ham [data-...] selektorlar orqali ular bilan ishlay oladi.

Xulosa

Atributlar va xossalar โ€” ikki xil narsa, ularni ajratish muhim: