اذهب إلى المحتوى

التعرف على شجرة DOM لتعديلها عبر جافاسكربت


محمد أمين بوقرة

تعدّ الوسوم (tags) أساس مستندات HTML. ويُمثَّل كلُّ وسمٍ منها في نموذج كائن المستند (DOM) بكائن. كما يُمثَّل النصّ الذي بداخل الوسم بكائن أيضا. وتعدّ الوسوم المتشعبة عن وسم آخر "أبناءً" لذلك الوسم.

يمكننا الوصول لكلّ هذه الكائنات من خلال جافاسكربت، ونستطيع بواسطتها التعديل على الصفحة. فعلى سبيل المثال، يمثّل الكائن document.body وسم <body>، وبتنفيذ الشفرة التالية يصير لون <body> أحمر لمدّة 3 ثوانٍ:

document.body.style.background = 'red'; // جعل الخلفية حمراء اللون

setTimeout(() => document.body.style.background = '', 3000); // ارجاعها كما كانت

استعملنا هنا خاصّيّة style.background لتغيير لون خلفيّة document.body، وهناك العديد من الخاصّيّات اﻷخرى مثل:

  • innerHTML -- محتوى HTML الذي بداخل العقدة.
  • offsetWidth -- مقدار عرض العقدة (بالبكسل).
  • … إلى غير ذلك.

سنتعلم قريبا المزيد من الطرق لمعالجة DOM، لكن نحتاج أوّلا إلى التعرّف على بنيته.

مثال عن DOM

لنبدأ بالمستند البسيط التالي:

<!DOCTYPE HTML>
<html>
<head>
  <title>About elk</title>
</head>
<body>
  The truth about elk.
</body>
</html>

يمثِّل DOM مستند HTML بواسطة بنية شجريّة من الوسوم، كما في الصورة التالية:

001.png

كل عقدة من هذه الشجرة هي كائن.

تُمثَّل الوسوم بعقدٍ عنصريّة element nodes (أو عناصر elements باختصار) وتشكّل بنية الشّجرة. فعند الجذر توجد<html> ، و<head> و <body> هما أبناؤها، إلى آخر ذلك.

يُمثَّل النّص الذي بداخل العناصر بعقدٍ نصّيّة وهي معلّمة في الصّورة بـ text#. لا تحتوي العقد النّصية إلا على سلاسل نصيّة (string)، ولا يمكن أن يكون لها أبناء، وتكون دائما بمثابة ورقةٍ للشجرة.

على سبيل المثال، يحوي وسم <title> على النصّ "About elk".

لاحظ وجود هذه المحارف الخاصّة (special characters) في العقد النصّيّة:

  • السطر الجديد: (يُعرف في جافاسكربت بـ n\).
  • الفراغ: .

يعدّ السطر الجديد والفراغ محارف صحيحة، تماما كالحروف واﻷرقام، وتُكوّن بدورها عقدا نصّيّة وتصير جزءًا من DOM. ففي المثال أعلاه، يحوي وسم <head> بعض الفراغات قبل <title>، ويكوّن ذلك النّص عقدة نصّيّة (تحوي سطرا جديدا وبعض الفراغات فقط).

يُستثنى من ذلك شيئان:

  • تُهمل الفراغات واﻷسطر الجديدة التي قبل <head> لأسباب تاريخيّة.
  • إذا وضعنا شيئا ما بعد <body/>، فإنه يُنقل تلقائيّا إلى آخر body، ﻷنّ مواصفة HTML تشترط أن يكون جميع المحتوى موجودا داخل <body>. لذا فلا يمكن أن تكون هناك أيّة فراغات بعد <body/>.

في غير ذلك من الحالات، فاﻷمر واضح؛ إذا كانت هناك فراغات في المستند فإنّها تصير عقدا نصّيّة (كغيرها من المحرّفات) في DOM، وإن أزلناها فلن تكون هناك أيّ منها.

هذا مثال لعقد نصيّة لا تحوي أيّة فراغات:

<!DOCTYPE HTML>
<html><head><title>About elk</title></head><body>The truth about elk.</body></html>

002.png

لا تُظهر أدوات المتصفّح (التي سنتطرق لها لاحقا) عند تعاملها مع DOM عادةً الفراغات التي في أوّل النّصّ وآخره، ولا العقد النصّيّة الفارغة (كالتي تنجم عن إنهاء السطر) بين الوسوم. توفّر أدوات المتصفّح بذلك المساحة على الشاشة. قد نحذفها أيضا في ما يأتي صورٍ لـ DOM إذا لم يكن في إظهارها فائدة. لا تؤثر هذه الفراغات عادة على كيفيّة عرض المستند.

التصحيح التلقائي

إذا صادف المتصفّح مستند HTML خاطئ التنسيق، فإنّه يصحّحه تلقائيّا عند بناء DOM.

على سبيل المثال، يكون <html> دائما هو الوسم اﻷعلى. حتى وإن لم يوجد في المستند، فإنّه سُيوجد في DOM، لأن المتصفّح سيُنشئه. وكذلك الشأن مع <body>.

فإذا كان ملف HTML عبارةً عن كلمة واحدة "Hello"، فإنّ المتصفّح سيلفُّه وسط <html> و <body> ويضيف لهما <head> كما يلزم، ويصير بذلك DOM:

003.png

عند توليد DOM، تعالج المتصفّحات تلقائيّا الأخطاء التي في المستند، كعدم إغلاق الوسوم وغير ذلك.

فإذا كان في المستند وسوم لم تُغلق:

<p>Hello
<li>Mom
<li>and
<li>Dad

فإنّ المتصفّح يستعيد الأجزاء المفقودة عندما يطّلع على الوسوم:

004.png


للجداول دائما <tbody>

تعدّ الجداول "حالة خاصّة" مثيرة للاهتمام. فوفقًا لمواصفة DOM يجب أن يكون للجداول العنصر <tbody>، لكن يُسمح (رسميًّا) لنصوص HTML أن تسقطه. فينشئ المتصفح حينها <tbody> في DOM تلقائيّا.

فتؤدّي مثلا شفرة HTML هذه:

<table id="table"><tr><td>1</td></tr></table>

إلى بنية DOM التالية:

005.png

أرأيت؟ ظهر <tbody> من لاشيء. ينبغي الانتباه لهذا عند التعامل مع الجداول لتفادي المفاجآت.


أنواع أخرى من العقد

هناك أنواع أخرى من العقد ما عدا العقد العنصريّة والنصيّة.

فهناك مثلا التعليقات.

<!DOCTYPE HTML>
<html>
<body>
  The truth about elk.
  <ol>
    <li>An elk is a smart</li>
    <!-- comment -->
    <li>...and cunning animal!</li>
  </ol>
</body>
</html>

06.png

يمكننا في الصورة أعلاه ملاحظة نوع جديد من العقد -- العقد التعليقيّة ، معلّمة بـ comment# ، بين عقدتين نصّيّتين.

لكن قد نتساءل -- لماذا تضاف التعليقات إلى DOM؟ فلا تأثير لها على التمثيل البصريّ بأيّ شكل من اﻷشكال. هذا صحيح، لكن هناك قاعدة تقول: كلُّ ما وُجد في HTML، فلا بدّ أن يوجد أيضا في شجرة DOM.

كلّ ما يحويه HTML، حتّى التعليقات، يصير جزءًا من DOM.

حتّى تعليمة <...DOCTYPE!> التي في أوّل HTML هي أيضا عقدة من DOM. هي موجودة في شجرة DOM قبل <html> مباشرة. لن نمسّ تلك العقدة، ولن نرسمها حتى في المخططات، لكنّها موجودة.

بل إنّ كائن document الذي يمثل المستند بأكمله هو، اصطلاحًا، عقدة من DOM أيضا.

هناك 12 نوعا من العقد، لكن نتعامل عادةً مع أربعة منها فقط:

  1. document -- "نقطة الدخول" إلى DOM.
  2. العقد العنصريّة -- وسوم HTML التي تمثل لبِنات الشجرة اﻷساسيّة.
  3. العقد النصّيّة -- تحتوي على نصّ فقط.
  4. التعليقات -- نضع فيها بعض المعلومات أحيانا. هي لا تُعرض، ولكن يستطيع جافاسكربت قراءتها من خلال DOM.

عاينه بنفسك

لمعاينة البنية الآنيّة لـ DOM، جرّب Live DOM Viewer. عليك فقط أن تدخل المستند، وسيظهر لك على شكل DOM حالًا.

يمكن أيضا تفحّص DOM باستخدام أدوات المطوّر (developer tools) في المتصفّح، وهي في الحقيقة ما نستعمله عند التطوير.

للقيام بذلك، افتح صفحة elk.html، ثمّ فعّل أدوات المطوّر في المتصفّح بالضغط على F12، وانتقل إلى لسان Elements (بمعنى عناصر).

يُفترض أن تبدو كما في الصورة:

elk.png

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

يُرجى التنبّه إلى أن بنية DOM مبسّطة في أدوات المطوّر. فتظهر العقد النصّيّة كمجرّد نصّ، وليست هناك عقد نصّيّة فارغة (أي تتكوّن من فراغات فقط) إطلاقًا. لكن لا بأس بذلك، إذ ما نهتمّ به في الغالب هي العقد العنصريّة.

بالنقر على الزرالذي على شكل مؤشر في أقصى الزاوية اليسرى من اﻷعلى يمكننا اختيار عقدة من الصفحة باستخدام الفأرة (أو أيٍّ من أجهزة التأشير اﻷخرى) و "فحصها" (بالانتقال إلى موضعها في لسان العناصر). يفيد هذا كثيرا عندما تكون صفحة HTML (وما يقابلها من DOM) التي لدينا كبيرة جدا، ونود أن نرى مكان عنصر معيّن منها.

كما يمكن أيضا فعل ذلك عن طريق النقر بالزر اﻷيمن على صفحة الويب ومن ثمّ اختيار "Inspect" (أي تفحّص) من القائمة المنبثقة.

inspect.png

توجد في الجزء اﻷيمن من اﻷدوات اﻷلسنة الفرعية التالية:

  • Styles (بمعنى الأنماط) -- تمكّننا من رؤية قواعد CSS المطبّقة على العنصر الحاليّ قاعدةً بقاعدة، بما في ذلك القواعد المضمّنة (باللون الرمادي). يمكن تقريبًا تعديل كلّ شيء من مكانه، بما في ذلك أبعاد (dimensions) وهوامش (margins) وحشوات (paddings) الصندوق (box) من أسفل اللسان.
  • Computed (بمعنى المحسوبة) -- لرؤية تنسيقات CSS المطبّقة على العنصر مرتّبةً حسب الخاصّيّة (property): كلّ خاصّيّة تقابلها القاعدة التي منحتها (بما في ذلك التنسيقات المورّثة وما إلى ذلك).
  • Event Listeners (بمعنى مستمعي اﻷحداث) -- لرؤية مستمعي اﻷحداث المرفقة مع عناصر DOM (سنتناول ذلك في مقالات لاحقة).

أفضل طريقة لدراسة كلّ هذه اﻷقسام هي بالنقر هنا وهناك. معظم القيم قابلة للتعديل من مكانها.

التعامل مع الطرفية (console)

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

بدايةً:

  1. حدّد أوّل <li> في لسان العناصر.
  2. اضغط زر Esc -- سيفتح ذلك الطرفيّة تحت لسان العناصر مباشرة.

يكون آخر العناصر التي حدّدناها محفوظا في المتغيّر 0$ ، والذي حدّدناه قبل ذلك في 1$ وهكذا.

يمكننا تنفيذ أوامر عليها. فمثلا، يغيّر اﻷمر ‎‎$0.style.background = 'red'‎ لون عنصر القائمة المحدَّد إلى اﻷحمر كما في الصّورة:

domconsole0 .png

بهذه الطريقة تُنقل العقد من لسان العناصر إلى الطرفية.

يمكن أيضا فعل العكس. فإذا كان لدينا متغيّر يشير إلى عقدة ما، يمكننا استخدام اﻷمر (inspect(node (حيث node هو اسم المتغيّر) في الطرفيّة لرؤيتها في لسان العناصر.

أو يمكننا فقط طباعة عقدة DOM في الطرفية وتفحصّها "من مكانها"، كما هو الحال مع document.body في اﻷسفل:

domconsole1.png

لا تُستخدم هذه الطرق إلا عند تنقيح اﻷخطاء بالطبع. ابتداءً من المقال الموالي، سنستخدم جافاسكربت للوصول إلى DOM والتعديل عليه.

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

خلاصة

يُمثًّل مستند HTML/XML في المتصفّح بواسطة شجرة DOM.

  • تصير الوسوم عقدًا عنصريّة وتشكّل بنية الشجرة.
  • تصير النصوص عقدًا نصّيّة.
  • … إلى غير ذلك، فلِكلّ ما يوجد في HTML مكانه في DOM، حتّى التعليقات.

يمكننا استخدام أدوات المطوّر لتفحّص DOM وتعديله يدويّا.

اقتصرنا هنا كبدايةٍ على اﻷساسيّات من أهمّ العمليّات وأكثرها استخداما. هناك توثيق شامل ﻷدوات المطوّر في متصفّح Chrome على https://developers.google.com/web/tools/chrome-devtools. أفضل طريقة لتعلم هذه اﻷدوات هو النقر هنا وهناك، وقراءة ما في القوائم، فمعظم الخيارات واضحة. لاحقا، عندما تتقن استخدامها عموما، طالع التوثيق والتقط الباقي.

لعُقد DOM خاصّيّات وتوابع تمكنّنا من التنقّل بينها والتعديل عليها والتجوّل في الصفحة وغير ذلك. هذا ما سنتناوله في المقال التالي.

ترجمة وبتصرف لمقال DOM tree من كتاب The Modern JavaScript Tutorial


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

أفضل التعليقات

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



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...