dom التنقل بين عقد شجرة DOM


Bian Alabras

مقدمة

تعلمنا في المقال السابق طريقة الوصول إلى العناصر في DOM  عن كيفية استخدام التوابع الملحقة بالكائن document بهدف الوصول إلى عناصر html بإحدى الطرق التالية: معرف العنصر ID، صف العنصر class، اسم الوسم tag name، أو محددات الاستعلام query selectors.

كما شرحنا في مقال البنية الشجرية لـ DOM  عن العقدة الأب لـ DOM الممثلة بالكائن document، كما تطرقنا إلى شرح مفصل عن العقد الأبناء التي تبنى من خلالها الشجرة وعن أنواعها (العناصر، التعليقات، والنصوص).

ولكننا نحتاج غالبًا للانتقال بين عقد شجرة DOM بدون المرور على جميع العقد التي تسبق العقدة المطلوبة، لذلك سنتحدث في هذه المقالة عن كيفية التنقل في شجرة DOM من الأعلى إلى الأسفل وبالعكس، إضافة إلى التنقل بين أفرع الشجرة من خلال باستخدام تعليمات الجافا سكربت و html.

الإعداد:

لنبدأ أولًا بإنشاء ملف nodes.html والذي يحوي التعليمات التالية:

<!DOCTYPE html>
<html>

<head>
  <title>Learning About Nodes</title>

  <style>
    * { border: 2px solid #dedede; padding: 15px; margin: 15px; }
    html { margin: 0; padding: 0; }
    body { max-width: 600px; font-family: sans-serif; color: #333; }
  </style>
</head>

<body>
  <h1>Shark World</h1>
  <p>The world's leading source on <strong>shark</strong> related information.</p>
  <h2>Types of Sharks</h2>
  <ul>
    <li>Hammerhead</li>
    <li>Tiger</li>
    <li>Great White</li>
  </ul>
</body>

<script>
  const h1 = document.getElementsByTagName('h1')[0];
  const p = document.getElementsByTagName('p')[0];
  const ul = document.getElementsByTagName('ul')[0];
</script>

</html>

عند فتح هذا الملف من خلال متصفح الانترنت، سنشاهد الصفحة التالية:
01.png

في صفحة الويب هذه لدينا مستند html يحوي على عدد قليل من العناصر وأساسيات css مرفقة به من خلال الوسم style من أجل تحسين طريقة إظهار العناصر، كما قمنا ببناء عدد قليل من المتحولات باستخدام تعليمات الجافا سكربت والتي ذكرت ضمن الوسم script حيث ستساعدنا بالوصول إلى العناصر.

كما نلحظ وجود عنصر واحد من العناصر التالية h1، p، ul لذا يمكن الوصول إليها من خلال الدليل الأول index للتابع getElementsByTagName.

عقدة الجذر Root Node

يعتبر الكائن doucment العقدة الجذر root node لجميع العقد في DOM. ولكن في الحقيقة كائن document هو إحدى خصائص الكائن window والذي يمكن تعريفه بأنه كائن عام global وذو مستوى عالي top-level object حيث يمثل تبويب المتصفح الذي يظهر فيه صفحة الويب.

يمكننا من خلال كائن window أن نصل إلى معلومات عن شريط الأدوات، طول وارتفاع النافذة، الرسائل الظاهرة في المتصفح، والإنذارات، في حين أن كائن document يتضمن كل الأحداث والخصائص الأخرى الموجودة داخل window.

يتضمن الجدول المرفق عناصر الجذر التي يمتلكها كل document حتى لو كان ملف html المحمل إلى المتصفح فارغ وهي عبارة عن 3 عقد سيتم إضافتها وتفسيرها في DOM.

الخاصية العقدة نوع العقدة
document #document DOCUMENT_NODE
document.documentElement html Element_NODE
getElementsByTagName() head Element_NODE
querySelector() body Element_NODE

وبما أن عناصر html، head، body شائعة جدًا فإنها تمتلك الخصائص الخاصة بها في المستند.

سنقوم بفتح تبويب console ضمن أدوات المطورين DevTools حتى نختبر هذه الخصائص الأربع من خلال كتابتها في console ومشاهدة النتائج. كما يمكننا أيضًا اختبار العناصر h1، p، و ul.

عقد الآباء Parent Nodes

لدينا في DOM ثلاث أنواع من العقد معرفة حسب نوع العلاقة فيها بينها وهي الآباء parents، الأبناء children، والشقيقة siblings.

تعرف العقدة الأب parent بأنها أي عقدة تمتلك عقدًا أقل في مستوى level أقل منها في التدرّج الهرمي للـ DOM، أو يمكن تعريفها بأنها العقد الأقرب لعقدة الجذر document.

يمكن الوصول دومًا للعقدة الأب بواسطة إحدى الخاصيتين parentNode أو parentElement.

Gets Property
ParentNode parentNode
ParentElementNode parentElement

في مثالنا nodes.html نلاحظ أن:

  • html هي العقدة الأب لكل من عقد head، body، و script
  • العقدة body  هي العقدة الأب لكل من h1، h2، و ul ولكنها ليست العقدة الأب لـ li لأنها في المستوى الأقل منها بمستويين.

يمكننا اختبار طريقة الوصول إلى العقدة الأب التي ذكرناها سابقًا، حيث سنقوم بمعرفة أب العنصر p من خلال الخاصية parentNode، وكما نذكر أننا قمنا ببناء المتحول p في التعليمات السابقة وإسناد القيمة document.getElementsByTagName('p')[0] وللوصول للأب نكتب التعليمة التالية في تبويب console

> p.parentNode;

وسيكون الخرج:

Output
► <body>...</body>

ويمكن استعمال parentNode مرتين للوصول إلى جد p.

يمكن الاستعانة بالعديد من الخصائص التي تمكننا من الوصول إلى العقدة الأب ولكن يوجد فيما بينها القليل من الاختلافات كما سنبينها الآن

> // Assign html object to html variable
> const html = document.documentElement;
>
> console.log(html.parentNode); // > #document
> console.log(html.parentElement); // > null

إن الأب لأي عقدة هو من نوع عقدة العنصر element nodes بينما لايمكن للعقد من نوع نص أو تعليقات أن تكون أب لأي عقدة أخرى وبما أن العقدة الأب لـ html هي العقدة الجذر document node لذلك نلاحظ أن القيمة المرجعة هي Null في السطر الأخير من التعليمات.

بشكل عام إن استخدام الخاصية parentNode شائع أكثر في الانتقال ضمن DOM.

العقد الأبناء Children Nodes

إن أبناء أي عقدة هي جميع العقد الموجودة في المستوى الذي يليه مباشرة أما العقد الموجود في المستوى الذي يلي مستوى الأبناء تسمى العقد الأحفاد.

Gets Property
Child Nodes childNodes
First Child Node firstChild
Last Child Node lastChild
Element Child Nodes children
First Child Element Node firstElementChild
Last Child Element Node lastElementChild

إن خاصية ChildNode ستعيد قائمة بأبناء العقدة. على سبيل المثال في ملف nodes.html السابق نلاحظ أن عنصر ul لديه 3 عناصر أبناء من li وبالتالي عند إدخال التعليمة:

> ul.childNodes;

وسيكون الخرج:

Output
► (7) [text, li, text, li, text, li, text]

نلاحظ أننا حصلنا على قائمة بأبناء العنصر ul والتي تحوي العناصر li الثلاث التي ذكرناها بالإضافة إلى عُقد النصوص text nodes ويعود السبب في ذلك لأننا كتبنا ملف html بطريقة يدوية ولم يتم توليده بواسطة الجافا سكربت. مع العلم أن كل ما يوجد بين العناصر يعتبره DOM عقدة نص text node، ولكن يعمل تبويب Elements الموجودة في أدوات التطوير الخاصة بالمتصفح DevTools بحذف الفراغات البيضاء من النص وبالتالي لا يعتبرها عقد نصوص.

مثلًا إذا حاولنا تغيير لون الخلفية للابن الأول باستخدام خاصية firstChild سنفشل لأن أول عقدة هي نص.

> ul.firstChild.style.background = 'yellow';

وستكون رسالة الخطأ هي

Output

> Uncaught TypeError: Cannot set property 'background' of undefined

لذلك فإن الخصائص children، firstElementChild، و lastElementChild وجدت لكي نستطيع الحصول على العقدة من نوع عنصر element  node  فقط، أي في حال كتابة ul.children سنحصل على مصفوفة تحوي 3 عقد من نوع عنصر هي li.

باستخدام الخاصية firstElementChild سنقوم بتغيير لون الخلفية للعنصر الأول li التي هي ابن للعقدة ul

> ul.firstElementChild.style.background = 'yellow';

وعند تنفيذ هذه التعليمة سيتغير لون الخلفية
02.png

عند معالجة شجرة DOM تظهر بعض الخصائص المفيدة للعناصر element properties.

في تطبيقات الويب التي تم توليدها باستخدام الجافا سكربت الأكثر احتمالًا، هو استخدام الخصائص التي تختار جميع العقد، وفي هذه الحالة الخطوط والمساحات البيضاء لن تكون موجودة.

بالعودة للمثال السابق يمكن استخدام حلقة for ... of من أجل تطبيق اللون الأصفر في الخلف على جميع العناصر الأبناء children.

for (let element of ul.children) {
  element.style.background = 'yellow';
}

بتطبيق هذه التعليمات سيظهر اللون الأصفر في خلفية جميع الأبناء
03.png

وبما أن العنصر p يمتلك نوعي عقد من الأبناء وهي العناصر والنصوص في داخله، فإنه يمكن للخاصية childNodes أن تكون مفيدة في الوصول إلى لهذه المعلومات.

for (let element of p.childNodes) {
  console.log(element);
}

حيث سيكون الخرج عبارة عن ثلاثة أسطر كل سطر يمثل ابن للعقدة p

Output
"The world's leading source on "
<strong>shark</strong>
" related information."

إن خاصيتي children و childNode تعيد مصفوفة ولكنها لاتمتلك جميع خصائص وتوابع المصفوفات، ولكنها تظهر بشكل مشابه للمصفوفات في الجافا سكربت. ولكن يمكن الوصول إلى العقد من خلال رقم الدليل index أو من خلال خاصية طول المصفوفة length

document.body.children[3].lastElementChild.style.background = 'fuchsia';

التعليمة السابقة هي عبارة عن إضافة اللون الفوشي لخلفية العقدة الابن الأخيرة (li) التابعة للعنصر الابن رقم 3 (ul) والتي هي بدورها ابن للعقدة body.

04.pngإن استخدام خصائص الأب والابن تساعد في الوصول إلى أي عقدة ضمن شجرة DOM.

العقد الشقيقة Sibling Nodes

العقد الشقيقة sibling of nodes هي العقد الموجودة في نفس المستوى في شجرة DOM ويمكن أن تكون من أنواع مختلفة من العقد سواء عنصر، نص أو تعليق

Gets Property
Previous Sibling Node previousSibling
Next Sibling Node nextSibling
Previous Sibling Element Node previousElementSibling
Next Sibling Element Node nextElementSibling

إن خصائص العقد الشقيقة تعمل بنفس الطريقة التي تعمل فيها عند العقد الأبناء، حيث نجد مجموعة من الخصائص للتنقل بين العقد بكل أنواعها وهي previousSibling و nextSibling ومجموعة أخرى تساعد على التنقل بين العقد من نوع عناصر فقط وهي previousElementSibling و nextElementSibling.

في مثالنا nodes.html سنختار الابن الأوسط للعنصر ul

const tiger = ul.children[1];

وبما أننا بنينا DOM الخاص بنا من الصفر وليس بناء على تطبيق ويب باستخدام الجافا سكربت فإننا نحتاج لاستخدام خصائص العناصر الأشقاء للوصول إلى عقد العناصر السابقة واللاحقة مع العلم أن الفراغات البيضاء موجودة في DOM كعقد من نوع text

tiger.nextElementSibling.style.background = 'coral';

tiger.previousElementSibling.style.background = 'aquamarine';

وبتنفيذ التعليمات السابقة سنلاحظ أن لون الخلفية عند Hammerhead وGreat White قد تغير

05.pngملخص

تحدثنا في هذه المقالة عن كيفية الوصول إلى جميع عناصر مستند HTML وكيفية التحرك بين العقد في شجرة DOM من خلال خصائص العقد الأب، الابن، والشقيقة.

وبهذا ستكون قادرًا على الوصول إلى أي عقدة ضمن شجرة DOM في أي موقع ويب.

 

هذه المقالة ترجمة للمقالة How To Traverse the DOM  للكاتبة Tania Rascia





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن