المحتوى عن 'dom'.



مزيد من الخيارات

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المُحتوى


التصنيفات

  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • نصائح وإرشادات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • التجارة الإلكترونية
  • مقالات عامة

التصنيفات

  • PHP
    • Laravel
    • ووردبريس
  • جافاسكريبت
    • Node.js
    • jQuery
    • AngularJS
    • Cordova
  • HTML5
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • سي شارب #C
    • منصة Xamarin
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • برمجة أندرويد
  • لغة Swift
  • لغة R
  • سير العمل
    • Git
  • صناعة الألعاب
    • Unity3D
  • مقالات عامّة

التصنيفات

  • تجربة المستخدم
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
    • كوريل درو
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • مقالات عامّة

التصنيفات

  • خواديم
    • الويب HTTP
    • قواعد البيانات
    • البريد الإلكتروني
    • DNS
    • Samba
  • الحوسبة السّحابية
    • Docker
  • إدارة الإعدادات والنّشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • مقالات عامة

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • استسراع النمو
  • المبيعات

التصنيفات

  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • مقالات عامة

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
  • أندرويد
  • iOS
  • macOS
  • ويندوز

التصنيفات

  • شهادات سيسكو
    • CCNA
  • شهادات مايكروسوفت
  • شهادات Amazon Web Services
  • شهادات ريدهات
    • RHCSA
  • شهادات CompTIA
  • مقالات عامة

أسئلة وأجوبة

  • الأقسام
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة البرمجة
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات
    • أسئلة الشهادات المتخصصة

التصنيفات

  • ريادة الأعمال
  • العمل الحر
  • التسويق والمبيعات
  • البرمجة
  • التصميم
  • DevOps

تمّ العثور على 6 نتائج

  1. مقدمة تحدثنا في المقال السابق عن البنية الشجرية لـ DOM وعن العقد Nodes المكونة لها وهي عبارة عن كائنات objects من الممكن أن تكون نصوص أو تعليقات أو عناصر. في الغالب يمكن الوصول إلى محتوى DOM من خلال عقد عناصر html، ولمعرفة كيفية الوصول إلى عناصر DOM بشكل احترافي من الضروري امتلاك معلومات كافية عن قواعد وأساسيات css، لذلك سنقوم في هذه المقالة بتعلم كيفية الوصول إلى عناصر DOM من خلال ID والصف class والوسم tag، ومحددات الاستعلام query selectors. نظرة عامة سنستعرض في هذا المقال خمس توابع methods هي: الطرق محدد بناء الجملة يحصل على getElementById() #demo ID getElementsByClassName() .demo Class getElementsByTagName() demo Tag querySelector() Selector (single) querySelectorAll() Selector (all) من المهم عند دراستنا ل DOM أن تقوم بتطبيق الأمثلة على حاسبك للتأكد من فهم جميع المعلومات بشكل جيد. سنبدأ بإنشاء ملف access.html في مجلد المشروع والذي سنقوم بتطبيق جميع أمثلتنا عليه في هذه المقالة. <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Accessing Elements in the DOM</title> <style> html { font-family: sans-serif; color: #333; } body { max-width: 500px; margin: 0 auto; padding: 0 15px; } div, article { padding: 10px; margin: 5px; border: 1px solid #dedede; } </style> </head> <body> <h1>Accessing Elements in the DOM</h1> <h2>ID (#demo)</h2> <div id="demo">Access me by ID</div> <h2>Class (.demo)</h2> <div class="demo">Access me by class (1)</div> <div class="demo">Access me by class (2)</div> <h2>Tag (article)</h2> <article>Access me by tag (1)</article> <article>Access me by tag (2)</article> <h2>Query Selector</h2> <div id="demo-query">Access me by query</div> <h2>Query Selector All</h2> <div class="demo-query-all">Access me by query all (1)</div> <div class="demo-query-all">Access me by query all (2)</div> </body> </html> في ملف html هذا نلاحظ أن لدينا العديد من العناصر التي يمكن الوصول إليها من خلال توابع method الخاصة بـ document وعند فتح هذا الملف في المتصفح سيكون مشابه لهذه الصفحة: سنستخدم العديد من التوابع methods التي ذكرناها في المقال سابقًا للوصول إلى العناصر المتاحة في هذا الملف. الوصول للعناصر باستخدام ID أسهل طريقة للوصول إلى عنصر محدد في DOM هو المعرف الخاص بها ID(Identification). حيث يمكن الوصول إلى العنصر من خلال ID باستخدام التابع getElementById() مع العنصر document. document.getElementById(); ولكن للحصول على هذه الخاصية في الوصول إلى العنصر من خلال id يجب أولًا إضافة الصفة id للعنصر. مثلًا سنضيف المعرف demo للعنصر div <div id="demo">Access me by ID</div> الآن في تبويب console سنقوم بالوصول إلى العنصر واسناده للمتحول demoId > const demoId = document.getElementById('demo'); في حال تمرير المتحول demoId إلى تابع log سنحصل على عنصر html كاملًا. > console.log(demoId); سيكون الخرج عندها العنصر كاملًا <div id="demo">Access me by ID</div> للتأكد من وصولنا إلى العنصر الصحيح سنقوم بتغيير حدود العنصر border property إلى اللّون البنفسجي > demoId.style.border = '1px solid purple'; وعند تنفيذ هذه التعليمات سنلاحظ أن حدود العنصر قد تغيرت إلى اللّون البنفسجي: إن الوصول إلى أي عنصر من خلال ID الخاص به هي أكثر طريقة فعالة وسريعة للوصول إلى عنصر ضمن DOM، ومع ذلك هذه الطريقة لديها عدة عيوب وهي أن ID دائمًا يجب أن يكون متفردًا في الصفحة ولذلك لا يمكن الوصول إلا إلى عنصر واحد فقط من خلال التابع getElementById. ولذلك في حال الحاجة إلى إضافة تابع لأكثر من عنصر في الصفحة فإن إضافته باستخدام id سيؤدي إلى تكرار كتابة التابع لكل عنصر على حدى. الوصول للعناصر باستخدام class تستخدم خاصية class للوصول إلى عنصر أو أكثر في DOM وذلك من خلال التابع getElementByClassName() document.getElementsByClassName(); ونستطيع من خلال الخاصية class الوصول إلى أكثر من عنصر، كما في هذا المثال حيث سنعطي لعنصرين نفس اسم الصف demo <div class="demo">Access me by class (1)</div> <div class="demo">Access me by class (2)</div> الآن في تبويبة console سنبني متحول demoClass ونسند له العناصر التي استطعنا الوصول إليها من خلال اسم الصف demo > const demoClass = document.getElementsByClassName('demo'); والآن أصبح بالإمكان الوصول إلى العناصر وتعديلها باستخدام class كما فعلنا في المثال السابق باستخدم ID. سنقوم الآن بتغيير خاصية الحدود border من خلال المتحول demoClass، demoClass.style.border = '1px solid orange'; ولكن ستظهر لنا رسالة خطأ بأنه لا يمكن تحديد العنصر Output Uncaught TypeError: Cannot set property 'border' of undefined والسبب في هذا الخطأ أن المتحول demoClass لايحوي عنصرًا واحدًا فقط وإنما مصفوفة كائنات من هذه العناصر للتأكد من ذلك سنكتب التعليمة التالية لمعرفة عدد عناصر المصفوفة المُسند إلى deomClass console.log(demoClass); والخرج سيكون هو عدد العناصر في المصفوفة Output (2) [div.demo, div.demo] حتى نستطيع الوصول إلى العناصر بشكل صحيح يجب أن نتعامل مع المتحول demoClass على أنه مصفوفة جافا سكربت يتم الوصول إليها من خلال رقم دليل العنصر index number. الآن نستطيع تغيير حدود كل العنصر الأول في المصفوفة باستخدام رقم الدليل 0 demoClass[0].style.border = '1px solid orange'; بشكل عام للوصول إلى العناصر من خلال الصف calss سنقوم بتغيير جميع العناصر التي تمتلك نفس اسم الصف باستخدام حلقة for التي تقوم بالمرور على جميع العناصر التي تحويها المصفوفة for (i = 0; i < demoClass.length; i++) { demoClass[i].style.border = ‘lpx solid orange’; } وعند تنفيذ هذه التعليمات سيصبح شكل صفحة الويب إذًا استطعنا الوصول إلى جميع العناصر التي تمتلك الصف demo وتغيير خاصية حدودها border إلى اللّون البرتقالي. الوصول للعناصر باستخدام Tag طريقة الوصول للعنصر من خلال اسم الوسم html tag name هو أقل الطرق تخصيصًا حيث يمكننا الوصول إلى العديد من العناصر باستخدام تابع getElementsByTagName() document.getElementsByTagName(); سنستخدم كمثال هنا العنصر article للوصول إليه من خلال اسم الوسم، نلاحظ العنصرين الذين يحملان اسم الوسم article <article>Access me by tag (1)</article> <article>Access me by tag (2)</article> وبنفس الطريقة التي وصلنا للعناصر من خلال اسم الصف class فإن التابع getElementsByTagName تعيد لنا مصفوفة array من العناصر حيث يمكن تعديل كل tag في المستند من خلال حلقة for const demoTag = document.getElementsByTagName(‘article’); for (i = 0; i < demoTag.length; i++) { demoTag[i].style.border = ‘1px solid blue’; } وبمجرد تنفيذ هذه التعليمات سيصبح شكل صفحة الويب بالشكل وهكذا قمنا بتعديل خاصية الحدود border لجميع العناصر article إلى اللّون الأزرق. محددات الاستعلام Query Selector في حال كان لديك خبرة سابقة في jQuery API ربما ستكون لديك معرفة سابقة مع توابع jQuery التي تستطيع الوصول لعناصر DOM من خلال محددات css $('#demo'); // returns the demo ID element in jQuery يمكننا الحصول على نفس النتيجة في الجافا سكربت من خلال استخدام التوابع querySelector() و querySelectorAll() document.querySelector(); document.querySelectorAll(); للوصول إلى عنصر واحد نستخدم تابع querySelector. فمثلًا يمكننا الوصول إلى العنصر الذي لديه المعرف demo-query من خلال التابع querySelector() <div id="demo-query">Access me by query</div> حيث نمرر للتابع المعرف id مع إضافة الرمز #، وسنقوم بإسناد العنصر للثابت demoQuery const demoQuery = document.querySelector('#demo-query'); ولكن في حالة استخدمنا التابع السابق مع المحددات التي تعطينا أكثر من عنصر واحد مثل class أو tag فإن querySelector() سيعيد لنا العنصر الأول فقط الذي يتطابق مع الاستعلام، ولكن نستطيع استخدام التابع querySelectorAll() من أجل الحصول على جميع العناصر المتطابقة مع الاستعلام. في مثالنا نلاحظ أن لدينا عنصرين يملكان اسم الصف demo-query-all <div class="demo-query-all">Access me by query all (1)</div> <div class="demo-query-all">Access me by query all (2)</div> إن اسم المحدد للخاصية class يجب أن يسبق بنقطة عند تمريره للتابع querySelectorAll() أي سنمرر في هذا المثال .demo-query-all const demoQueryAll = document.querySelectorAll('.demo-query-all'); باستخدام التابع forEach() يمكننا تطبيق اللّون الأخضر على حدود هذه العناصر deomQueryAll.forEach(query => { query.style.border = ‘1px solid green’; }); تعتبر الفاصلة , في حال وضعناها بين القيم للتابع querySelector() كعملية OR مثلاً إذا قمنا بكتابة التابع بالشكل querySelector(‘div, article’) أي تعني أن يجد لنا العنصر div أو article بغض النظر عمن سيظهر أولًا في الملف. أما في حالة وجود الفاصلة بين القيم للتابع querySelectorAll فإنها تعني العملية AND أي في حال كتبنا التابع querySelectroAll(‘div, article’) فإنها تعني إعادة العناصر التي تحوي القيم articl و div الموجودة ضمن المستند. إن استخدام توابع محددات الاستعلامات يعطينا القدرة العالية في البرمجة للوصول إلى أي عنصر أو مجموعة عناصر ضمن DOM بنفس المحددات التي نستخدمها في ملف css. وفي هذه المقالة يوجد قائمة بجميع المحددات الخاصة بال css التي جمعت بواسطة شبكة مطوري Mozilla. تعليمات الجافا سكربت كاملة سأذكر هنا التعليمات التي كتبناها بلمف access.js بشكل كامل. حيث يمكن إضافة ملف js إلى ملف html قبل إغلاق body. // Assign all elements const demoId = document.getElementById('demo'); const demoClass = document.getElementsByClassName('demo'); const demoTag = document.getElementsByTagName('article'); const demoQuery = document.querySelector('#demo-query'); const demoQueryAll = document.querySelectorAll('.demo-query-all'); // Change border of ID demo to purple demoId.style.border = '1px solid purple'; // Change border of class demo to orange for (i = 0; i < demoClass.length; i++) { demoClass[i].style.border = '1px solid orange'; } // Change border of tag demo to blue for (i = 0; i < demoTag.length; i++) { demoTag[i].style.border = '1px solid blue'; } // Change border of ID demo-query to red demoQuery.style.border = '1px solid red'; // Change border of class query-all to green demoQueryAll.forEach(query => { query.style.border = '1px solid green'; }); وسيكون الشكل النهائي لملف html هو <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Accessing Elements in the DOM</title> <style> html { font-family: sans-serif; color: #333; } body { max-width: 500px; margin: 0 auto; padding: 0 15px; } div, article { padding: 10px; margin: 5px; border: 1px solid #dedede; } </style> </head> <body> <h1>Accessing Elements in the DOM</h1> <h2>ID (#demo)</h2> <div id="demo">Access me by ID</div> <h2>Class (.demo)</h2> <div class="demo">Access me by class (1)</div> <div class="demo">Access me by class (2)</div> <h2>Tag (article)</h2> <article>Access me by tag (1)</article> <article>Access me by tag (2)</article> <h2>Query Selector</h2> <div id="demo-query">Access me by query</div> <h2>Query Selector All</h2> <div class="demo-query-all">Access me by query all (1)</div> <div class="demo-query-all">Access me by query all (2)</div> <script src="access.js"></script> </body> </html> ملخص في هذه المقالة تعلمنا 5 طرق للوصول إلى عناصر html الموجودة في DOM وهي من خلال المعرف ID، الصف class، الوسم html tag name، ومن خلال المحددات selector. التوابع التي يمكن استخدامها للحصول على عنصر أو مجموعة عناصر تعتمد على مدى دعم المتصفح المستخدم لها وعدد العناصر التي تتم معالجتها. والآن يمكنك الوصول إل عناصر html الموجودة في المستند باستخدام الجافا سكربت و DOM. هذه المقالة هي ترجمة للمقالة How To Access Elements in the DOM وكاتبتها Tania Rascia. table { width: 100%; } td, th { border: 1px solid #dddddd; text-align: left; padding: 8px; } tr:nth-child(even) { background-color: #dddddd; }
  2. مقدمة تعلمنا في المقال السابق طريقة الوصول إلى العناصر في 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> عند فتح هذا الملف من خلال متصفح الانترنت، سنشاهد الصفحة التالية: في صفحة الويب هذه لدينا مستند 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. table { width: 100%; } td, th { border: 1px solid #dddddd; text-align: left; padding: 8px; } tr:nth-child(even) { background-color: #dddddd; } الخاصية العقدة نوع العقدة 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'; وعند تنفيذ هذه التعليمة سيتغير لون الخلفية عند معالجة شجرة DOM تظهر بعض الخصائص المفيدة للعناصر element properties. في تطبيقات الويب التي تم توليدها باستخدام الجافا سكربت الأكثر احتمالًا، هو استخدام الخصائص التي تختار جميع العقد، وفي هذه الحالة الخطوط والمساحات البيضاء لن تكون موجودة. بالعودة للمثال السابق يمكن استخدام حلقة for ... of من أجل تطبيق اللون الأصفر في الخلف على جميع العناصر الأبناء children. for (let element of ul.children) { element.style.background = 'yellow'; } بتطبيق هذه التعليمات سيظهر اللون الأصفر في خلفية جميع الأبناء وبما أن العنصر 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. إن استخدام خصائص الأب والابن تساعد في الوصول إلى أي عقدة ضمن شجرة 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 قد تغير ملخص تحدثنا في هذه المقالة عن كيفية الوصول إلى جميع عناصر مستند HTML وكيفية التحرك بين العقد في شجرة DOM من خلال خصائص العقد الأب، الابن، والشقيقة. وبهذا ستكون قادرًا على الوصول إلى أي عقدة ضمن شجرة DOM في أي موقع ويب. هذه المقالة ترجمة للمقالة How To Traverse the DOM للكاتبة Tania Rascia
  3. مقدمة عندما نتكلم عن DOM فإننا نتكلم عن بنية شجرية تحوي العديد من الكائنات objects التي تدعى العقد nodes. لقد تكلمنا في المقال السابق (مدخل إلى DOM) عن تعريف DOM وكيفية الوصول إلى الكائن document وطريقة تعديل خصائصه من خلال console بالإضافة إلى إيضاح الفرق بين ماهية HTML و DOM. في هذه المقالة فسنتحدث عن مصطلحات HTML التي تعتبر قواعد أساسية للتنسيق برمجة موقع الويب الذي يتضمن html، الجافا سكربت ومفاهيم DOM. حيث سنتعلم من خلال هذا المقال كيفية بناء شجرة DOM و كيفية إضافة العقد الخاصة بها Nodes حسب نوعها، أخيرًا سنقوم ببناء برنامج باستخدام الجافا سكربت بدلًا من استخدام console وذلك لتعديل DOM. مصطلحات HTML إن فهم مصطلحات Html و الجافا سكربت تعتبر أمرًا ضروريًا لفهم كيفية العمل مع DOM. ولذلك سنقوم بمراجعة بعض مصطلحات html سنبدأ أولًا بالنظر إلى عنصر html التالي <a href="index.html">Home</a> إن عنصر html السابق a هو عبارة عن عنصر يُضاف لربط صفحة الويب الخاصة بنا بصفحة أو محتوى آخر، في هذا المثال لتحقيق إمكانية الوصول إلى صفحة index.html a هو الوسم tag href هو الصفة attribute index.html هو قيمة الصف home هو النص الذي نضيفه للعنصر كل ماهو موجود بين علامتي <> هو عبارة عن عنصر html سنعمل على صفحة index.html التي بنيناها بالمقالة السابقة <!DOCTYPE html> <html lang="en"> <head> <title>Learning the DOM</title> </head> <body> <h1>Document Object Model</h1> </body> </html> إن الطريقة الأسهل للوصول إلى عنصر عبر الجافا سكربت هي استخدام الصفة id ويمكننا ربط أي عنصر في html بـ id خاص به، فمثلًا سنقوم بإضافة id خاص بالعنصر a في المثال السابق وقيمتها هي nav ... <body> <h1>Document Object Model</h1> <a id="nav" href="index.html">Home</a> </body> ... الآن سنقوم بتحميل إو إعادة تحميل صفحة index.html للتأكد بتعديل DOM الخاص بصفحتنا التي عدلناها. سنستخدم التابع getElementById() للوصول إلى العنصر كاملًا من خلال كتابة التعليمة التالية في تبويبة console document.getElementById('nav'); عندها سيكون الخرج في تبويبة console بالشكل <a id="nav" href="index.html">Home</a> حيث نلاحظ أننا حصلنا على العنصر كاملآ من خلال استخدام تابع getElementById() ، ولكن يمكننا إسناد عنصر html إلى متحول variable للوصول إليه بشكل أسرع من استخدام التابع السابق. let navLink = document.getElementById('nav'); وهكذا أصبح navLink هو عبارة عن متحول يحوي على عنصر a الخاص وبالتالي يمكننا تعديل الصفات attribute التي يحويها وقيمها بسهولة، فمثلًا يمكننا تعديل قيمة الصفة href بالشكل التالي navLink.href = 'https://www.wikipedia.org'; كما يمكننا تعديل المحتوى النصي للمتحول من خلال إعادة إسناد قيمة نصية جديدة للخاصية textContent navLink.textContent = 'Navigate to Wikipedia'; الآن عندما سنستعرض العنصر a إما من خلال console أو من خلال تمرير الفأة على الوسم a سنشاهد كيف تم تعديل العنصر navLink; وسيكون الخرج هو Output <a id="nav" href="https://www.wikipedia.org/">Navigate to Wikipedia</a> كما سنشاهد أن هذه سينعكس على شكل واجهة الموقع ولكن عند تحديث الصفحة سيتم التراجع عن كل التعديلات التي قمنا بها. وبنهاية هذه الفقرة يجب أن نكون قد تعلمنا كيفية التعامل مع توابع document وطريقة الوصول إليها وإسناد العنصر إلى متحول وتغيير الصفات الخاصة بالعنصر من خلال استخدام المتحول المُسند إليه. شجرة DOM والعقد المكونة لها تعرف جميع العناصر التي تنتمي لل DOM كعقد nodes ولها أنواع متعددة لكن يوجد 3 أنواع هي الأكثر استخداما عقد العنصر Element nodes عقد النص Text nodes عقد التعليقات Comment nodes عندما يتم تمثيل عنصر html كعنصر داخل DOM سنشير له بأنه عقدة العنصر element nodes، وأي نص خارج هذا العنصر سنشير له بأنه عقدة النص text node، وأخيرًا التعليقات التي نكتبها داخل html سنشي لها في DOM بأنها عقد التعليقات Comment node. بالإضافة إلى هذه الأنواع الثلاثة تعتبر document بأنها عقدة قائمة بذاتها تسمى document node والتي تعتبر بأنها جذر العقد الأخرى كافة التي يحتويها ملف DOM. إذًا يتضمن DOM بنية شجرية تحوي العديد من القعد المتداخلة والتي غالبًا ما يشار لها بشجرة DOM أو DOM tree وتشبه بنيتها إلى حد كبير بنية شجرة العائلة التي تضمن الآباء، الأبناء والأشقاء وتلك هي الحال أيضًا بالنسبة للعلاقة بين عقد شجرة DOM. لنرى هذه العلاقات بين عقد شجرة DOM بشكل عملي سنقوم ببناء ملف nodes.html والتي يحوي على أنواع العقد الثلات: عقد النص text، التعليقات comment والعناصر element <!DOCTYPE html> <html> <head> <title>Learning About Nodes</title> </head> <body> <h1>An element node</h1> <!-- a comment node --> A text node. </body> </html> عقدة العنصر html هي العقدة الأب parent node أما عقد العناصر head و body فهي عقد أشقاء وأبناء للقعدة html. أما عقدة body فهي تملك 3 عقد أبناء وهي جميعها عقد أخوة، مع العلم أن نوع العقدة لايؤثر على مستواها. ملاحظة: {.underline} عند العمل مع DOM المولد من قبل html فإن كثرة الفراغات المضافة إلى تعليمات html سيؤدي إلى خلق العديد من عقد النصوص text nodes الفارغة. والتي لاتظهر في تبويبة "Elements" الموجودة في DevTools في chrome. تمييز نوع العقدة كل العقد في المستند document تملك نوع مخصص والتي يمكن الحصول عليها من خلال الخاصية nodeType. قامت شبكة مطوري Mozilla بتحديث قائمتها لـ ثوابت نوع العقدة. وسنذكر هنا قائمة بأكثر أنواع العقد الشائعة وكيفية التعامل معها في هذه المقال نوع العقدة القيمة مثال عقدة العنصر ELEMENT_NODE 1 العنصر < body > عقدة النص TEXT_NODE 3 أي نص ليس جزء من العنصر عقدة التعليق COMMENT_NODE 8 < !--- html comment --- > في تبويبة "Elemnets" الموجودة في أدوات المطوريين قد تلاحظ أنه في حال قمت بالضغط على أي عنصر في DOM وتم تظليله فستلاحظ أنه سيظهر بجانبه القيمة ==$0 ولذلك فإن أحد الطرق السهلة للوصول إلى العنصر النشيط من خلال أدوات التطوير هو كتابة $0. في تبويبة "console" الخاصة بالصفحة nodes.html سنقوم بالضغط على أول عنصر موجود في body وهو h1 الآن سنحصل على نوع العقدة المفعلة حاليًا وذلك من خلال الوصول إليها عبر خاصية nodeType لذلك ندخل التعليمة التالية في console $0.nodeType; وسيكون عندها الخرج هو 1 بالشكل التالي Output 1 وجدنا أن الخرج هو 1 المرتبط بالعنصر المختار h1 والذي يشير إلى نوع ELEMENT_NODE. وبتجربة التعليمة السابقة على نص أو تعليق في ملف HTML فإننا سنحصل على الخرج 3 و 8 بالترتيب. كما يمكننا الحصول على نوع العقدة من دون الحاجة إلى تظليل العنصر في DOM قبل معرفته وذلك من خلال التعليمة document.body.nodeType; حيث سيكون الخرج هو 1 أيضًا. بالإضافة إلى الخاصية nodeType، يمكن استخدام الخاصية nodeValue للحصول على القيمة أو التعليق في عقد النص والتعليق، كما أن الخاصية nodeName تساعدنا في الحصول على اسم الوسم الخاص بالعنصر. تعديل DOM باستخدام الأحداث تعرفنا إلى الآن إلى كيفية تعديل DOM من خلال console ولكن هذا التعديل مؤقت فبمجرد تحديث صفحة الويب ستُلغى هذه التعديلات. في المقالة مدخل إلى DOM استخدمنا console من أجل تعديل لون خلفية الشاشة، الآن يمكن الجمع بين ما تعلمناه سابقًا مع المعلومات في هذه المقالة لبناء زر تفاعلي عندما يتم الضغط عليه. بالعودة إلى ملف index.html سنضيف زر من خلال العنصر button ونضيف له id كما أننا سنضيف رابط جديد لملف جافا سكربت موجود في المجلد js/scripts.js <!DOCTYPE html> <html lang="en"> <head> <title>Learning the DOM</title> </head> <body> <h1>Document Object Model</h1> <button id="changeBackground">Change Background Color</button> <script src="scripts.js"></script> </body> </html> يعرف الحدث event في الجافا سكربت بأنه الفعل الذي يقوم به المستخدم كمثال عندما يقوم المستخدم بتمرير الفأرة فوق عنصر، الضغط على عنصر، أو الضغط على زر معين في لوحة المفاتيح. في هذا المثال نريد للزر الذي بنيناه أن ينتظر ويكون مستعدًا لتلقي الفعل من قبل المستخدم من خلال استخدام event listener للزر. أولًا نقوم ببناء ملف scripts.js ونحفظه في مجلد js ثم سنضيف تعليمات الجافا سكربت التي تقوم بإيجاد العنصر وإسناده إلى متحول let button = document.getElementById('changeBackground'); ثم نضيف التابع addEventListener الذي يعمل على جعل الزر ينتظر حتى يتم الضغط عليه من أجل تنفيذ التابع function الذي يقوم بالفعل في هذا المثال الفعل هو تغيير لون الخلفية. ... button.addEventListener('click', () => { // action will go here }); حيث سنكتب داخل التابع function التعليمة الخاصة بتغيير لون الخلفية إلى لون fuchsia ... document.body.style.backgroundColor = 'fuchsia'; حيث ستكون التعليمات بالترتيب كما يلي let button = document.getElementById('changeBackground'); button.addEventListener('click', () => { document.body.style.backgroundColor = 'fuchsia'; }); وحالما نقوم بحفظ هذا الملف وإعادة تحديث ملف index.html ثم الضغط على زر الموجود في الشاشة فإن الحدث event الذي صممناه لتغير لون الخلفية سوف يعمل مباشرة. ملخص في هذه المقالة قمنا باستذكار المصطلحات التي تساعدنا على فهم وتعديل DOM كما تعرفنا على البنية الشجرية لل DOM وأنواع العقد المستخدمة في إنشائها مثل عناصر html، النصوص، والتعليقات. كما قمنا في النهاية بإنشاء سكربت يسمح للمستخدم بتعديل شكل الموقع من دون الحاجة إلى إدخال التعليمات يدويًا إلى تبويبة console. هذه المقالة هي ترجمة للمقالة Understanding the DOM Tree and Nodes وكاتبتها Tania Rascia
  4. dom

    مقدمة إن نموذج تمثيل المستند ك جسم أو كائن Document Object Model والذي يشار له اختصارا ب DOM يعتبر أحد الطرق الأساسية في بناء مواقع متفاعلة فيما بينها، حيث تُعتبر هذه الطريقة واجهة تسمح للغات البرمجة بمعالجة محتوى المواقع وهيكليتها. أحد اللغات المرتبطة بالـ DOM في المتصفحات هي الجافا سكربت وذلك لأنها لغة برمجة تعمل في مواقع الويب من جهة المستخدم client-side. حيث يمكن الاستفادة من مفاهيم DOM في بناء مواقع ويب متفاعلة مثل إضافة عرض صور للموقع من خلال شاشة عرض بطريقة تدوير الصور، أو إظهار لافتة تنبّه المستخدم إلى وقوعه في خطأ عند محاولته إدخال معلومات ناقصة ضمن الحقول المطلوبة، أو التبديل في قوائم التصفح الخاصة بالموقع ويتم تنفيذ هذه العمليات الثلاث من خلال لغة الجافاسكربت ولكن من خلال معالجة DOM. في هذا المقال سنتعلم ماهو DOM وكيفية التعامل معه من خلال تعريف كائن object هو document والتمييز بين أسطر التعليمات المكتوبة بلغة HTML وبين DOM. ملاحظة: لاتعتبر DOM لغة برمجة كما الحال في لغات البرمجة الاعتيادية كالجافا أو الجافا سكربت... حيث يتم تنفيذ وتطبيق مفاهيمها من خلال لغات برمجة أخرى وهنا سنستخدم لغة الجافا سكربت. المتطلبات الأساسية لفهم كيفية تطبيق مفاهم DOM بشكل فعال وتنفيذه في تطبيقات الويب من المهم أن تكون لديك معرفة سابقة بـ HTML و CSS بالإضافة إلى معرفة القواعد الأساسية حول طريقة كتابة تعليمات الجافا سكربت وهيكليتها. ما هي DOM للبدء ببناء أي موقع ويب مهما كان بسيط سنبدأ أولًا بإنشاء مستند HTML، حيث يقوم برنامج المتصفح الذي يستخدمه الزائر لمشاهدة الموقع بتفسير تعليمات html و CSS وتحويلهم إلى المحتوى، الهيكلية والتصميم الذي نشاهده أمامنا في الصفحة النهائية. بالإضافة لذلك يقوم المتصفح ببناء تمثيل للمستند يُعرف بأنه نموذج كائن المستند Document Object Model ويسمح هذا النموذج للجافا سكربت بالوصول إلى المحتوى المُعبّر عنه كنص text أو كعناصر element ضمن المستند ورؤيتها على شكل أغراض objects. ولسهولة فهم هذا المفهوم الجديد سنتعرف عليه من خلال مثال عملي يبدأ بتطوير موقع بسيط وذلك بإنشاء ملف جديد يسمى index.html ثم حفظه ضمن مجلد المشروع project directory <!DOCTYPE html> <html lang="en"> <head> <title>Learning the DOM</title> </head> <body> <h1>Document Object Model</h1> </body> </html> إن أسطر التعليمات السابقة هي أساسيات HTML لبناء موقع ويب. سنستخدم هنا متصفح Chrome ولكن يمكنك الوصول إلى نفس الخرج من خلال المتصفحات الحديثة الأخرى. أولًا سنقوم بفتح ملف index.html الذي قمنا ببنائه من خلال متصفح chrome عندها سيظهر أمامك صفحة ويب فارغة وتحوي فقط عنوان هو "Document Object Model" ومن خلال النقر بالزر اليميني في أي مكان بالصفحة ستظهر لدينا قائمة نختار منها "Inspect" والتي ستفتح لنا على جانب الصفحة أدوات التطوير، سيظهر لدينا DOM تحت تبويب "Elements" في هذه الحالة نلاحظ أن DOM الذي قمنا بإظهاره مطابق تمامًا لتعليمات html التي كتبناها سابقًا لبناء الموقع، وعند تمرير السهم فوق العنصر سنلاحظ أن مايقابله من صفحة الويب المفتوحة أمامنا ستُظلّل باللون الأزرق، كما أن السهم الموجود على جانب كل عنصر يسمح بتوسيع العناصر المكتوبة بالداخل. كائن المستند Document كائن المستند document هو عبارة عن كائن مُدمج يملك عدد من الخصائص properties والطرق methods التي يمكن استخدامها للوصول إلى الموقع وتعديله. لفهم كيفية عمل DOM يجب أولًا فهم كيف تعمل الكائنات objects في الجافا سكريبت، ويمكن ذلك من خلال الإطلاع على مقالة برمجة الكائنات Objects في جافاسكريبت في أدوات التطوير التي أظهرناها سابقًا بجانب ملف index.html ننتقل إلى التبويبة "Console" ونكتب document داخل console ثم نضغظ زر Enter حيث نلاحظ أن الخرج هو نفسه الخرج الموجود في تبويبة "Elements" document; Output #document <!DOCTYPE html> <html lang="en"> <head> <title>Learning the DOM</title> </head> <body> <h1>Document Object Model</h1> </body> إن كتابة المستند document أو العمل مباشرة في تبويب console ليست أمرًا شائعًا نقوم به خارج debugging ولكنه يساعد في ترسيخ مفهوم كائن المستند document وكيفية تعديله ومعرفه العناصر الأخرى المدرجة ضمنه. ماهو الفرق بين DOM وتعليمات HTML حاليًا في المثال السابق الذي طرحناه تبدو لنا DOM كما لو أنها تعليمات HTML نفسها ولكن يوجد أمثلة يقوم فيها المتصفح بتوليد DOM مختلف عن تعليمات HTML مثل: تعديل DOM من خلال تعليمات الجافا سكربت والتي يتم تنفيذها في جانب المستخدم. قيام المتصفح بتصحيح الأخطاء الموجودة في التعليمات HTML المكتوبة سابقًا بشكل تلقائي. سنقوم الآن باكتشاف آلية تعديل DOM من خلال استخدام الجافا سكربت التي تُطبق في جانب المستخدم. أولًا ندخل في console التعليمة document.body; عندها سيكون الخرج: Output <body> <h1>Document Object Model</h1> </body> سنلاحظ هنا أن document هو عبارة عن كائن أما body فهو خاصية property لهذا الكائن لذلك من للوصول إلى هذه الخاصية نكتب اسم الكائن ثم نقطة ثم الخاصية document.body عندها سيكون الخرج هو جميع عناصر body الموجودة في المستند document. نستطيع من خلال console تغيير بعض الصفات الظاهرة في الكائن body في هذا الموقع فمثلًا يمكن تغيير صفات style الخاصية بالـ body مثل تغيير لون الخلفية ويتم ذلك من خلال التعليمة document.body.style.backgroundColor = 'fuchsia'; بعد كتابة هذه التعليمة وإدخالها سنلحظ تغير لون خلفية الموقع للون الفوشيا: بالانتقال إلى تبويبة "Elements" أو من خلال كتابة تعليمة document.body في console مرة أخرى سنلاحظ أن DOM قد تغير Output <body style="background-color: fuchsia;"> <h1>Document Object Model</h1> </body> ملاحظة: رأينا في المثال السابق عند تغيير لون الخلفية أن خاصية لون الخلفية في CSS والذي يكتب بالشكل background-color تمت كتابته بالشكل backgroundColor في الجافا سكربت وبنفس هذا الترتيب فإن أي خاصية في CSS يمكن كتابتها في الجافا سكربت بطريقة camelCase والتي تعني أن الحرف الأول من الكلمة الأولى صغير بينما الحرف الأول من الكلمة الثانية كبير. عند الضغط بالزر اليميني على الصفحة واختيار "View Page Source" سنلاحظ أن التعليمات الظاهرة لاتحوي على الصفة attribute الجديدة للون الخلفية الذي أضفناه من خلال الجافا سكربت وذلك لأن التعليمات الأساسية الموجودة في جانب الخادم Server التي تم بناء الموقع من خلالها لاتتأثر بأي تعليمات كتبت في جانب المستخدم بلغة الجافا سكربت، ولذلك في حال قمنا بتحديث الصفحة فإن الخاصية التي أضفناها ستُلغى. بالنسبة للحالة الأخرى التي ذكرناها عن اختلاف DOM و تعليمات HTML وهي عندما يتم تصحيح الأخطاء المكتوبة في التعليمات source code آليًا من قبل المتصفح، كمثال شائع فإن الوسم tbody يجب أن يرافق الوسم table دائمًا ولكن غالبًا لايقوم المطورون بتضمين هذه الوسوم بالشكل الصحيح ضمن HTML وعندها يقوم المتصفح تلقائيًا بتصيح هذا الخطأ وإضافة الوسم tbody وبالتالي يتم تغيير DOM. بالإضافة إلى ذلك دائمًا يصحح DOM الوسوم التي لايتم إغلاقها. ملخص عرضنا في هذه المقالة تعريف للـ DOM واستطعنا الوصول إلى كائن المستند document باستخدام الجافا سكربت وconsole من أجل تغيير خصائص تابعة للكائن document، كما تعرفنا على الفرق بين HTML و DOM. أما في المقالة التالية سنقوم باستعراض معلومات مهمة عن HTML وشجرة DOM وكيفية التعامل مع عقدها Nodes وماهي الأنواع الشائعة منها. ترجمة بتصرف للمقال Introduction to DOM وكاتبتها Tania Rascia
  5. css 101

    يشرح هذا الجزء من سلسلة تعليم CSS كيف تعمل CSS في المتصفّحات وما الهدف من وجود DOM. سنتعلّم أيضًا كيف نُحلّل مستندًا بسيطًا. فهرس السلسلة: مدخل إلى أوراق الأنماط المتتالية (CSS). آلية عمل تعليمات CSS داخل المتصفحات. (هذا الدرس) المحددات (Selectors) في CSS. كيفية كتابة تعليمات CSS يسهل قراءتها. تنسيق نصوص صفحات الويب باستخدام CSS. التعامل مع الألوان في CSS. إضافة محتوى إلى صفحة ويب باستخدام CSS. تنسيق القوائم (Lists) في CSS. تعرف على الصناديق (Boxes) في CSS. رصف العناصر (Layout) في CSS. الجداول (Tables) في CSS. التعامل مع أجهزة العرض المختلفة والمطبوعات في CSS. كيفية عمل CSS عندما يعرض المتصفّح المستند، فإنّه يجمع محتواه مع معلومات التنسيق، ويُعالج المستند على مرحلتين: يحوّل المتصفّح لغة الرّماز وCSS إلى DOM (اختصارًا لـDocument Object Model). يُمثّل DOM المستند في ذاكرة الحاسوب، ويجمع محتوى المستند مع تنسيقه. يعرض المتصفّح محتويات DOM. تستخدم لغات الرّماز عناصر (elements) لتعريف هيكل المستند. يُحدّد العنصر بوسم (tag)، وهو نص يبدأ بالرّمز ‎<‎ وينتهي بالرّمز ‎>‎. معظم العناصر لها زوجان من الوسوم، وسم في البداية وآخر في النهاية. لكتابة وسم البداية أدرج اسم العنصر بين ‎<>‎، أما وسم النّهاية فيكتب بإضافة ‎/‎ بعد ‎<‎ وقبل اسم العنصر. قد يكون لبعض العناصر وسم بادئ فقط، أو وسم وحيد فيه تأتي ‎/‎ بعد اسم العنصر، وذلك تبعًا للغة الرّماز. قد يكون العنصر أيضًا حاويًا على عناصر آخرى ضمن وسْمَيه الأول والأخير. عليك التأكد من إغلاق الوسوم ضمن العنصر الحاوي. لـDOM بنية تشبه الشجرة، حيث يصبح كل عنصر أو خاصّة أو سلسلة من النصوص في لغة الرماز عقدة (node) في البنية الشجريّة. تُحدّد العُقد بعلاقتها بالعقد الأخرى، فبعض العناصر هي آباء (parent nodes) لعناصر آخرى (children nodes)، وقد يكون للأبناء إخوة (sibling nodes). يُعينك فهم DOM على تصميم وتنقيح وصيانة CSS، لأنّه يمثّل نقطة التقاء CSS مع محتوى المستند. مثال يُنشئ الوسم ‎<p>‎ ونظيره ‎</p>‎ عنصرًا حاويًا: <p> <strong>C</strong>ascading <strong>S</strong>tyle <strong>S</strong>heets </p> في هيكل DOM، تُعتير العقدة P أبًا، أبناؤه هي العقد STRONG والعقد النصيّة، وبالمثل فإنّ العقد STRONG آباء للعقد النّصيّة. ├─STRONG │ └─"C" ├─"ascading" ├─STRONG │ └─"S" ├─"tyle" ├─STRONG │ └─"S" └─"heets" تدريب: تحليل DOM باستخدام أداة فحص DOM لتحليل هيكل DOM، نحتاج إلى برنامج خاصّ، بإمكانك استخدام إضافة DOM Inspector من Mozilla لتحقيق ذلك. ما عليك إلا تثبيت الإضافة (المزيد من التفاصيل أدناه). استخدم متصفح Mozilla لفتح مستند HTML الذي أنشأته. من قائمة المتصفّح اختر: أدوات > DOM Inspector أو أدوات > تطوير الويب > DOM Inspector. تفاصيل أكثر إن لم يحوِ متصفح Mozilla عندك على أداة فحص DOM، فبإمكانك تثبيت الإضافة من موقع الإضافات وإعادة تشغيل المتصفح ثم العودة لهذا الدّرس. إن لم ترغب بتثبيت هذه الإضافة (أو لم تكن تستعمل متصفح من Mozilla)، بإمكانك استخدام Web X-Ray Goggles كما هو مشروح في القسم التالي. بإمكانك أيضًا تجاوز هذا القسم والمتابعة. في أداة فحص DOM، وسّع عقد المستند بالنقر على الأسهم. ملاحظة: قد تؤدي المسافات في ملف HTML إلى عرض عقد نصية فارغة، يمكنك تجاهلها. يبدو جزء من النتيجة مشابهًا لما يلي، تبعًا للعقد الّتي وسّعتها: │ ▼╴P │ │ │ ▼╴STRONG │ │ └#text │ ├╴#text │ ►╴STRONG │ │ عندما تختار أيّة عقدة، بإمكانك استخدام اللوحة على يمين DOM Inspector للاطّلاع على معلومات إضافية عنها، فمثلًا: يعرض DOM Inspector النص في اللوحة على اليمين عندما تحتار عقدة نصيّة. عندما تختار عقدة تمثّل عنصرًا، تُحلّل الأداة هذه العقدة وتقدّم معلومات كثيرة في اللّوحة على اليمين، يكون من ضمنها معلومات التنسيق. تمرين انقر على عقدة من نوع STRONG في أداة فحص DOM، ثم استخدم اللوحة على اليمين لإيجاد الموضع الّذي يُعيّن فيه لون العقدة إلى أحمر، والموضع الّذي يُجعل فيه خطّها أعرض من النصّ العاديّ. شاهد الحل في القائمة فوق اللوحة على اليمين، اختر CSS Rules، سترى عنصرين مُدرجين، أحدهما هو المصدر الداخلي الّذي ي يُعرّف font-width على أنّها bolder، والآخر آتٍ من ورقة الأنماط الّتي تُحرّرها والّذي يُعرّف color على أنّه red. استخدام Web X-Ray Goggles تعرض الأداة Web X-Ray Goggles معلومات أقل من DOM Inspector، ولكنّها أبسط في التثبيت والاستعمال: اذهب إلى الصّفحة الرئيسيّة للأداة. اسحب رابط العلامة المرجعيّة إلى شريط المتصفّح. افتح مستند HTML الّذي أنشأته. فعّل الأداة بالنقر على العلامة المرجعيّة في الشّريط. اسحب مؤشّر الفأرة فوق العناصر المختلفة في المستند. تتالي الأنماط ووراثتها سنتعلّم الآن كيف تتفاعل الأنماط المتتالية، وكيف ترث العناصر الأنماط عن آبائها، وكيف تضيف الأنماط إلى ورقة الأنماط مستفيدًا من فكرة الوراثة بحيث تغيّر تنسيق عدة أجزاء من المستند مرّة واحدة. قد يُحدّد النّمط النّهائي للعنصر في عدّة مواضع، تتفاعل فيما بينها بطريقة مُعقّدة، وهذا التّفاعل المعقّد يُعطي CSS قدراتها المُميّزة، ولكنّه قد يُعقّد الأمور ويجعل تتبّع الأخطاء عمليّة صعبة. تجتمع المصادر الثلاثة الأساسية لمعلومات التنسيق مشكّلة ما نسمّيه تعاقب الأنماط (cascade)، وهذه الأنماط هي: التنسيقات المبدئيّة الّتي يحدّدها المتصفّح للعناصر في لغة الرّماز. التنسيقات الّتي يحدّدها المستخدم الّذي يقرأ المستند. التنسيقات المرتبطة بالمستند الّتي يحدّدها مؤلّفه، والّتي قد تعيّن في ثلاثة مواضع: في ملفّ خارجيّ: وهذا الموضوع الأساسيّ لهذه الدّروس. في تعريف في بداية المستند: للتنسيقات الخاصّة بصفحة واحدة فقط. في عنصر معيّن ضمن متن المستند: وهي الطريقة الأقل سهولة في الصيانة، ويمكن استخدامها على سبيل التّجربة. تُغيّر أنماط المستخدم الأنماط الّتي يعيّنها المتصفّح، ثمّ تغيّر أنماط مؤلّف المستند تلك الّتي عيّنها المستخدم. في هذه السّلسلة أنت مؤلّف المستند، ولن نتعامل إلّا مع هذا النّوع من الأنماط. مثال عندما تقرأ هذا المستند في متصفّح، يأتي جزء من التنسيق الّذي تراه من الإعدادات المبدئيّة لـHTML في المتصفّح. وقد يأتي جزء آخر من الإعدادات المخصّصة للمتصفّح، إذ يمكن تخصيصها في مربع التفضيلات في Firefox مثلًا، أو يمكن تعيينها في ملف userContent.css في ملفّ المتصفّح الشّخصيّ. ويأتي الجزء الأخير من التنسيق من خادوم موقع الأكاديميّة. عندما تفتح المستند الّذي تتدرّب عليه في المتصفّح، تكون العناصر <strong> أعرض خطًّا من بقيّة النّصّ، هذا التنسيق يأتي من إعدادات المتصفّح المبدئيّة. كما أن العناصر نفسها ذات لون أحمر، وهذا التنسيق يأتي من ورقة الأنماط الّتي كتبناها بأنفسنا. ترث عناصر <strong> أيضًا معظم تنسيقها عن عناصر <p> لأنّها أبناؤها، وبالمثل ترث العناصر <p> معظم تنسيق عنصر <body>. يكون للتنسيقات الّتي يحدّدها مؤلّف المستند الأولويّة في تعاقب الأنماط على تلك الّتي يحدّدها القارئ، وتكون الأولويّة الأقل لتنسيقات المتصفّح المبدئيّة. بالنّسبة للتنسيقات الموروثة، يكون للتنسيقات المعرّفة على العقدة ذاتها الأولويّة على تلك الّتي ترثها عن آبائها. هناك قواعد أخرى لهذه الأولويّات، سنتعرّف عليها لاحقًا. تفاصيل أكثر توفّر CSS أيضًا طريقة للقارئ لحجب التنسيق الّذي يحدّده مؤلّف المستند باستخدام الكلمة !important. وهذا يعني أنّه لا يمكن توقّع الشّكل الّذي سيكون عليه المستند لكلّ قارئ. إذا أردت معرفة المزيد عن موضوع التعاقب والوراثة، انظر فقرة Assigning property values, Cascading and inheritance في تعريف CSS. تمرين: استخدام الوراثة حرّر ملفّ CSS الّذي تتدرّب عليه. أضف هذا السّطر بنسخه ولصقه. لا يهمّ إن كان فوق أو تحت السّطر الّذي أضفته من قبل. إلّا أن إضافته فوقه أكثر منطقيّة لأن العنصر <p> أب للعنصر <strong> في مستندك. p {color: blue; text-decoration: underline;} احفظ الملفّ وحدّث متصفّحك لتشاهد تأثير ذلك على المستند. يؤدّي ذلك إلى تسطير النّص في كامل الفقرة، بما في ذلك الحروف الأولى من كلّ كلمة، وهذا يعني أن العناصر <strong> ورثت عن أبيها نمط تسطير النّصّ. ولكّن هذه العناصر ما تزال حمراء اللّون، لأنّ اللون الأحمر هو نمطها الخاص، ولذا يكون له الأولويّة على اللّون الأزرق لأبيها العنصر <p>. قبل <p> <strong>C</strong>ascading <strong>S</strong>tyle <strong>S</strong>heets </p> strong {color:red} بعد <p> <strong>C</strong>ascading <strong>S</strong>tyle <strong>S</strong>heets </p> p {color:blue; text-decoration:underline} strong {color:red} تمرين عدّل ورقة الأنماط بحيث تكون الحروف الأولى فقط مُسطَّرة: شاهد الحل انقل التصريح الذي يُعنى بتسطير النّص من قاعدة <p> إلى <strong>، كما يلي: p {color: blue; } strong {color: orange; text-decoration: underline;} ما التالي؟ سنتعرّف في الدّرس التالي كيف نستهدف العناصر بطريقة أكثر انتقائيّة. ترجمة -وبتصرف- للمقال How CSS works من سلسلة Getting started with CSS على شبكة مطوّري Mozilla.
  6. توفّر jQuery أدوات قويّة لإيجاد العنصر أو العناصر التي تريدها في الصّفحة، ثمّ العمل بهذه العناصر للوصول إلى النّتيجة المرغوبة. تسهّل jQuery بأدواتها هذه عمليّات كانت لتكون أكثر تعقيدًا لو أردنا تنفيذها من خلال وظائف DOM الأصليّة. سنطّلع في هذا الجزء على بعض (لا كلّ) وظائف الانتقال عبر الصّفحة وتّعديل العناصر في jQuery. وقبل أن نبدأ، علينا فهم بعض المصطلحات الضّروريّة. لنفترض أنّ لدينا نصّ HTML التّالي: <ul> <li> <span> <i>Foo</i> </span> </li> <li>Bar</li> </ul>نقول عن عنصر القائمة الأوّل (<li>) أنّه ابن (child) القائمة غير المرتّبة (<ul>).نقول عن القائمة غير المرتّبة (<ul>) أنّها والد (parent) عنصري القائمة الاثنين.نقول عن العنصر <span> أنّه خَلَفُ (descendant) القائمة غير المرتّبة.نقول عن القائمة غير المرتّبة أنّها سَلَفٌ (ancestor) لكلّ ما داخلها.نقول عن عنصري القائمة أنّهما شقيقان (siblings).الانتقال عبر الصّفحة (Traversal)تسمح jQuery لنا بالانتقال عبر عناصر HTML الّتي تكوّن صفحتنا. إذ نُنشئ أوّلًا تحديدًا مبدئيًّا ثمّ ننتقل عبر DOM انطلاقًا منه. وخلال مسيرنا عبر DOM، فإنّنا نُغيّر من تحديدنا الأوّل فنضيف إليه أو نحذف منه بعض العناصر، أو نستبدل به تحديدًا آخر بالكامل في بعض الأحيان. تصفية التّحديداتبإمكانك تصفية تحديد موجودٍ بحيث يتضمّن فقط العناصر الّتي تطابق معاييرَ مُحدّدة. بإمكانك مثلًا إجراء التّصفية بإحدى الطّرق التّالية: var listItems = $( 'li' ); // صفِّ التّحديد ليحوي فقط العناصر ذات الصّنف 'special' var special = listItems.filter( '.special' ); // صفّ التّحديد ليحوي فقط العناصر من غير الصّنف 'special' var notSpecial = listItems.not( '.special' ); // صفّ التّحديد ليحوي فقط العناصر الّتي تتضمّن span var hasSpans = listItems.has( 'span' );من المهمّ أن تعرف أن الوظيفة ‎.not()‎ ليست عكس ‎.is()‎، لأنّ ‎.is()‎ تُعيد قيمة منطقيّة (true أو false)، بينما تُعيد ‎.not()‎ كائن jQuery جديدًا. إيجاد العناصر انطلاقًا من تحديديمكن الاستفادة من تحديد أوّليّ كأساس لإنشاء تحديدات إضافيّة؛ فإذا كان لديك تحديدٌ يحوي عنصر قائمة مُفردًا مثلًا، وأردت التّعامل مع "أشقّائه" أو مع القائمة غير المُرتّبة الّتي تحويه، فبإمكانك إنشاء تحديد جديد انطلاقًا من التّحديد الموجود بسهولة: // اختر أوّل عنصر قائمة في الصّفحة var listItem = $( 'li' ).first(); // أيضًا: .last() // اختر أشقّاء عنصر القائمة var siblings = listItem.siblings(); // اختر الشّقيق التّالي لعنصر القائمة var nextSibling = listItem.next(); // أيضًا: .prev() // اختر والد عنصر القائمة var list = listItem.parent(); // اختر عناصر القائمة الّتي تنحدر مباشرةً من القائمة var listItems = list.children(); // اختر كلّ عناصر القائمة ضمن القائمة، بما في ذلك العناصر الفرعيّة var allListItems = list.find( 'li' ); // اختر كل أسلاف عنصر القائمة ذوي الصّنف "module" var modules = listItem.parents( '.module' ); // اختر أقرب سلفٍ لعنصر القائمة له الصّنف "module" var module = listItem.closest( '.module' );بإمكانك كذلك الإضافة على التّحديد الحاليّ باستخدام الوظيفة ‎.add()‎، الّتي تقبل مُحدِّدًا أو مصفوفة عناصر أو نص HTML أو كائن jQuery. var list = $( '#my-unordered-list' ); // افعل شيئًا ما بالقائمة ثم ... var listAndListItems = list.add( '#my-unordered-list li' );العودة إلى التّحديد الأصليّتحتفظ jQuery بإشارة إلى تحديد الأصليّ عندما تستخدمه للانتقال إلى تحديدات أخرى انطلاقًا منه، في حال أردت العودة إلى التّحديد الأصليّ. افترض مثلًا أنّك حدّدت قائمة غير مرتّبه، ثمّ أردت التّعديل على عناصر القائمة، ثمّ العودة مجدّدًا للعمل على القائمة غير المرتّبة، عندها بإمكانك استخدام الوظيفة ‎.end()‎ للرّجوع إلى التّحديد الأصليّ: $( '#my-unordered-list' ) .find('li') // نحن الآن نعمل على عناصر القائمة .addClass('special') .end() // عدنا الآن للعمل على القائمة ذاتها .addClass('super-special');تُسهِّل الوظيفة ‎.end()‎ إجراء تعديلات كثيرة في جملة واحدة، إلّا أنّ هذا الأسلوب لا يُلقي بالًا لوضوح النّصّ البرمجيّ، فهو أشبه بأن تحكي قصّة دون أن تلتقط أنفاسك. لهذا السّبب لا أنصحك بالإكثار من استعماله، فهو يؤدّي في معظم الحالات إلى جعل قراءة النّصّ البرمجيّ وصيانته وتنقيحه أكثر صعوبة. فيما يلي حلّ أفضل للمشكلة ذاتها: var list = $( '#my-unordered-list' ); var listItems = list.find('li'); listItems.addClass( 'special' ); list.addClass( 'super-special' );توفّر jQuery أيضًا الوظيفة ‎.addBack()‎ إن أردت إضافة تحديدك الأصليّ إلى التّحديد الحاليّ. مثال: $( 'li.special' ) .siblings() // نحن نعمل الآن على أشقّاء التّحديد السّابقة .removeClass( 'important' ) .addBack() // الآن نعمل على عناصر القائمة الأصليّة وأشقائها **معًا** .addClass( 'urgent' );هل اختلط عليك الأمر؟ الوظيفة ‎.addBack()‎ تشبه الوظيفة ‎.end()‎ في عيوبها، فكلاهما (وإن كان لهما استخدامها) يزيدان تعقيد النّصّ البرمجيّة. الحلّ الأفضل هو استخدام الوظيفة ‎.add()‎ لدمج التّحديدين الأصليين معًا: var specialListItems = $( 'li.special' ); var otherListItems = specialListItems.siblings(); otherListItems.removeClass( 'important' ); specialListItems.add( otherListItems ).addClass( 'urgent' );هناك وظائف عديدة لم نتطرّق إليها هنا، يمكنك الاطّلاع عليها في وثائق الانتقال عبر الصّفحة. التّعامل مع العناصر (Manipulation)تسمح وظائف التّعامل مع العناصر في jQuery بتغيير DOM الصّفحة بصياغة أكثر بساطة من تلك الّتي توفّرها وظائف DOM الخام. تُعيد وظائف التّعامل مع العناصر في jQuery كائن jQuery الّتي استدعيت للعمل عليه، وهذا يعني إمكانيّة ربطها في سلسلة أو دمجها مع وظائف jQuery أخرى كالّتي ناقشناها في الفقرات السّابقة. تعديل العناصركثيرةٌ هي طرق تعديل العناصر في jQuery. سنطّلع فيما يلي على طرق إنجاز المهام الأكثر شيوعًا. إضافة أو حذف الأصناف (classes)يمكن الاستفادة من أصناف الكائنات في HTML بأن نستهدفها في CSS بغرض تنسيقها، كما يُستفاد منها في إنشاء تحديدات jQuery. فمثلًا يمكن لعنصر في الصّفحة أن يقع تحت الصّنف hidden، والّذي يُستخدم في CSS لجعل خاصّة display موافقة للقيمة none للعناصر من هذا الصّنف، ثمّ يمكن حذف هذا الصّنف أو إضافته لتغيير حالة ظهور العناصر الموافقة في jQuery: $( 'li' ).addClass( 'hidden' ); $( 'li' ).eq( 1 ).removeClass( 'hidden' );جرّب المثال في ساحة التّجربة (تأكد من ضغط زر Run with JS في هذا المثال وكلّ الأمثلة التالية) إن تطلّبت حالتك إضافة صنفٍ أو حذفه مرارًا، فبإمكانك استخدام الوظيفة ‎.toggleClass()‎ الّتي تُبدّل حالة الصّنف على العنصر، فتضيفه إن لم يكن موجودًا أو تحذفه إن وُجد: $( 'li' ).eq( 1 ).toggleClass( 'hidden' );جرّب المثال في ساحة التّجربة تغيير المظهرملاحظة: يُفضّل دومًا استخدام الأصناف واستهدافها بقواعد CSS لتغيير طريقة عرض العناصر، والاقتصار على استخدام jQuery في إضافة هذه الأصناف أو حذفها كما ورد للتوّ. في هذه الفقرة سنتعرّف كيف نُغيّر مظاهر العناصر مُباشرةً في jQuery، ولكننا نُفضِّل دومًا الأسلوب الأوّل إن كان يُحقِّق النّتائج ذاتها. عندما تعجز عن تحقيق هدفك بإضافة الأصناف أو حذفها، فإنّ jQuery تقدّم الوظيفة .css() الّتي تسمح بتعيين مظهر العناصر مباشرةً، ولعلّ هذا يكون ضروريًّا عادةً عندما تحتاج إلى إسناد قيم عدديّة لا يمكن حسابها إلّا أثناء عمل التّطبيق، كمعلومات توضّع العناصر في الصّفحة. لا يُفضَّل استخدام الوظيفة ‎.css()‎ لإجراء تنسيقات بسيطة مثل ‎display: none‎، بل يُفضَّل في معظم الحالات إنجاز الغاية ذاتها باستخدام الأصناف وCSS. افترض مثلًا أنّنا نريد تعيين مظهر العنصر بالاعتماد على عرض والده، وربّما يصعب أو يستحيل معرفة عرض الوالد مُسبقًا عند اعتماد تخطيط مرنٍ للصّفحة. في هذه الحالة قد نلجأ إلى الوظيفة ‎.css()‎ لتنسيق العنصر: var list = $( '#my-unordered-list' ); var width = Math.floor( list.width() * 0.1 ); list.find('li').each(function( index, elem ) { var padding = width * index; $( elem ).css( 'padding-right', padding + 'px' ); });جرّب المثال في ساحة التّجربة إن احتجت إلى تعيين أكثر من خاصّة في وقت واحدٍ، مرّر كائنًا إلى الوظيفة ‎.css()‎ بدلًا من اسم الخاصّة وقيمتها. لاحظ أنّ عليك إحاطة أيّة خاصّة تحوي الرّمز "-" بعلامتي اقتباس: $( 'li' ).eq( 1 ).css({ 'font-size': '20px', 'padding-right': '20px' });جرّب المثال في ساحة التّجربة تغيير قيم النّماذج (forms)تقدّم jQuery الوظيفة ‎.val()‎ لتعديل قيمة العناصر في النّماج مثل input وselect. بإمكانك تمرير سلسلة نصّيّة لتعيين محتوى حقول input النّصّيّة: $( 'input[type="text"]' ).val( 'new value' );جرّب المثال في ساحة التّجربة بالنّسبة للعناصر من نوع select، بإمكانك تعيين الخيار المُختار باستخدام ‎.val()‎ أيضًا: $( 'select' ).val( '2' );جرّب المثال في ساحة التّجربة أمّا لحقول input من نوع checkbox، فعليك تعيين الخاصّة checked على العنصر بالوظيفة ‎.prop()‎. $( 'input[type="checkbox"]' ).prop( 'checked', 'checked' );جرّب المثال في ساحة التّجربة ملاحظة: أُضيفت الوظيفة ‎.prop()‎ في الإصدارة 1.6 من jQuery؛ وقبل ذلك كانت تُستخدم الوظيفة ‎.attr()‎ للغرض ذاته، وهي ما تزال تعمل في الإصدارات الحديثة من jQuery، ولكنّها في حالة checked تكتفي باستدعاء ‎.prop()‎. إن كنت تستخدم إصدارةً أحدث من 1.6، فأنصحك باستخدام ‎.prop()‎ دومًا لتعيين الخاصّة checked وخصائص عناصر DOM الأخرى. اطّلع على الوثائق لتفاصيل أكثر. تغيير الصّفات (attributes) الأخرىبإمكانك استخدام وظيفة ‎.attr()‎ لتغيير صفات العناصر، فيمكنك مثلًا تغيير عنوان رابط (الخاصّة title لعنصر <a>): $( 'a' ).attr( 'href', 'new title');عند تعيين قيمة لصفة، بإمكانك تمرير دالّة في موضع المُعامل الثّاني للوظيفة، ومثلها مثل كلّ دوالّ الكتابة السّابقة، تتلقّى هذه الدّالّة مُعاملين اثنين: دليل العنصر الّذي تعمل عليه، والقيمة الحاليّة للصّفة. يجب أن تُعيد هذه الدّالة القيمة الجديدة للصّفة: $( 'a' ).attr( 'href', function(index, value) { return value + '?special=true'; });جرّب المثال في ساحة التّجربة بإمكانك حذف الصّفات أيضًا، وذلك باستخدام ‎.removeAttr()‎. الحصول على معلومات من العناصرناقشنا في الجزء السّابق (أساسيّات jQuery) فكرة وظائف القراءة والكتابة. كلّ الوظائف الّتي يمكن استخدامها لتغيير العناصر، يمكن أيضًا استخدامها لقراءة معلومات من تلك العناصر. فيمكن مثلًا استخدام الوظيفة ‎.val()‎ الّتي وصفناها أعلاه كوظيفة قراءة وكتابة معًا: var input = $( 'input[type="text"]' ); input.val( 'new value' ); input.val(); // returns 'new value'وكذلك الأمر بالنّسبة للوظيفة ‎.css()‎، إذ يمكن استخدامها لقراءة قيمة خصائص CSS مُفردة بإمرار اسم الخاصّة فقط دون قيمة: var listItemColor = $( 'li' ).css( 'color' );عندما تُستخدم وظائف التّعامل مع العناصر للقراءة، فإنّها تعمل فقط مع العنصر الأول في التّحديد، باستثناء الوظيفة ‎.text()‎ الّتي تقرأ المحتوى النّصيّ لكلّ العناصر المُحدّدة إن لم يُمرّر معامل إليها. إضافة العناصر إلى الصّفحةسواءٌ حدّدت عنصرًا أو أنشأت واحدًا جديدًا، فبإمكانك إضافة هذا العنصر إلى الصّفحة يمكن فعل ذلك بطريقتين: باستدعاء وظيفة تتبع للعنصر (أو العناصر) المطلوب إضافته، أو باستدعاء وظيفة تتبع لعنصر مرتبط بذلك الّذي تريد إضافته. افترض مثلًا أنّك تريد نقل عنصر في قائمة من رأسها إلى ذيلها، هناك عدّة طرق لفعل ذلك. بإمكانك مثلًا إضافة العنصر إلى القائمة باستدعاء الوظيفة ‎.appendTo()‎ على عنصر القائمة ذاته: var listItem = $( '#my-unordered-list li' ).first(); listItem.appendTo( '#my-unordered-list' );جرّب المثال في ساحة التّجربة وبإمكانك أيضًا إضافة العنصر باستدعاء ‎.append()‎ على القائمة: var listItem = $( '#my-unordered-list li' ).first(); $( '#my-unordered-list' ).append( listItem );أو إضافته باستدعاء ‎.insertAfter()‎ على العنصر المُراد نقله مُمرّرًا العنصر الأخير في القائمة إلى الوظيفة: var listItems = $( '#my-unordered-list li' ); listItems.first().insertAfter( listItems.last() );جرّب المثال في ساحة التّجربة أو إضافته باستدعاء ‎.after()‎ على العنصر الأخير في القائمة مُمرًّرا العنصر الأولى في القائمة إلى الوظيفة: var listItems = $( '#my-unordered-list li' ); listItems.last().after( listItems.first() );جرّب المثال في ساحة التّجربة هناك طرق آخرى كثير لإضافة العناصر، فبإمكانك إضافتها حول عناصر أخرى أو داخلها أو خارجها بحسب حاجتك. تعتمد أكثر الطّرق كفاءة في إضافة عنصر إلى الصّفحة على العناصر الّتي تتوفّر بين يديك بالفعل. فقد ترغب في إضافة العنصر إلى القائمة غير المُرتّبة في المثال السّابق إن كنت قد حدّدت القائمة غير المرتّبة من قبل لغرض آخر؛ أو إن كنت قد حدّدت عناصر القائجة جميعها، فقد يكون إضافة العنصر الأول بعد العنصر الأخير أمرًا أسهل. عندما تختار الطّريقة المناسبة لإضافة العنصر، فلا تكتفِ بالنّظر في سهولة الطّريقة، بل فكّر في إمكانيّة صيانتها لاحقًا. تجنّب الطّرق الّتي تعتمد على افتراض بنية مُحدِّدة بدقَّة لصفحتك، فقد تقرّر تغيير هذه البنية فيما بعد. نسخ العناصربإمكانك إنشاء نسخة من عنصر أو مجموعة عناصر باستخدام الوظيفة ‎.clone()‎ في jQuery، وستُنشئ النُّسخة في الذّاكرة دون أن تُدرج في الصّفحة، فعليك فعل ذلك بنفسك إن أردته. بإمكانك تعديل العناصر المنسوخة قبل إضافتها: var clones = $( 'li' ).clone(); clones.html(function( index, oldHtml ) { return oldHtml + '!!!'; }); $( '#my-unordered-list' ).append( clones );جرّب المثال في ساحة التّجربة ملاحظة*: لن تمنعك jQuery من نسخ عنصر ذي مُعرِّف (ID)، ولكن عليك التأكّد من حذف المُعرِّف أو تغييره في العنصر المنسوخ بتعديل الصّفة id قبل إدراجه في المستند، إذ لا ينبغي أ يوجد عنصران بمُعرِّف واحدٍ في الصّفحة. حذف العناصرهناك ثلاث طرق لحذف العناصر من الصّفحة: ‎.remove()‎‏ و‎.detach()‎‏ و‎.replaceWith()‎‏، ولكلّ منها غرضٌ مُختلف. يجب استخدام ‎.remove()‎‏ عند الحاجة لحذف العناصر بصورة دائمة، فهي ستحذف مع العنصر كلّ مُتوليّات الأحداث المُرتبطة به (event handlers). تُعيد الوظيفة ‎.remove()‎‏ إشارةً إلى العناصر المُحذوفة، ولكن عند إضافة هذه العناصر مرّة ثانيةً، فلن تكون أيّة أحداث مُرتبطةً بها. $( '#my-unordered-list li' ).click(function() { alert( $( this ).text() ); }); var removedListItem = $( '#my-unordered-list li' ).first().remove(); removedListItem.appendTo( '#my-unordered-list' ); removedListItem.trigger( 'click' ); // لا رسالة تنبيه!جرّب المثال في ساحة التّجربة تُفيد الوظيفة ‎.detach()‎‏ في حذف العناصر مؤقّتًا من الصّفحة، فمثلًا إن رغب في إجراء تعديلات كبيرة على بنية الصّفحة باستخدام jQuery، فقد يكون حذف العناصر مؤقّتًا من الصّفحة ثمّ إضافتها ثانيةً أفضل أداءً بمراحل. ستحتفظ العناصر المحذوفة بهذه الوظيفة بمُتولّيات الأحداث المُرتبطة بها، ويمكن بعد ذلك إضافتها إلى الصّفحة مُجدّدًا باستخدام ‎.appendTo()‎‏ أو غيرها من وظائف الإضافة. $( '#my-unordered-list li' ).click(function() { alert( $( this ).text() ); }); var detachedListItem = $( '#my-unordered-list li' ).first().detach(); // افعل شيئًا ما مُعقّدًا بعنصر القائمة detachedListItem.appendTo( '#my-unordered-list' ); detachedListItem.trigger( 'click' ); // alert!أخيرًا لدينا الوظيفة ‎.replaceWith()‎‏ الّتي تُحلِّ عنصرًا أو نصّ HTML محلّ عنصرٍ أو عناصر أخرى. تُعاد العناصر الّتي أُزيلت من الوظيفة، ولكنّ كلّ متولّيات الأحداث المرتبطة بها تُحذف، تمامًا كالوظيفة ‎.remove()‎‏. $( '#my-unordered-list li' ).click(function() { alert( $( this ).text() ); }); var replacedListItem = $( '#my-unordered-list li' ).first() .replaceWith( '<li>new!</li>' ); replacedListItem.appendTo( '#my-unordered-list' ); replacedListItem.trigger( 'click' ); // لا رسالة تنبيه!جرّب المثال في ساحة التّجربة خاتمةتعلّمنا في هذا الجزء الطّرق المختلفة للانتقال بين العناصر في الصّفحة، وكيفيّة نقلها وتغييرها وإضافة عناصر جديدة. سنتعلّم في الجزء القادم كيف نُنصِت لتفاعل المستخدم مع صفحتنا. ترجمة (بشيء من التصرف) للجزء الثالث من سلسلة  jQuery Fundamentals لمؤلّفتها Rebecca Murphey.