لديك حساب بالفعل؟ دخول
دخول  سجل الأن 
جدول المحتويات
DOM
في هذا الفصل سندرس شيئا يسمى Document Object Model و يختصر بالـDOM و بالعربية يترجم ل"نموزج كائنات الوثيقة" ,و الوثيقة يقصد بها هنا محتوى صفحة الويب .و بفهم هذا الموضوع سيمكننا التحكم في محتويات صفحة الويب من خلال لغة الجافا سكريبت .
[تحسين] ما هو DOM؟
سميت هذا الفصل بالتحكم في html ,وربما كان العنوان الأنسب أن نسميه بالـ DOM إختصارا لـ Document Object Model ,لكني أحببت أن أضع له عنوانا يفهمه من لم يعرف بعد ما هو الـ DOM .فما هو الـ DOM ؟.
شاهدنا هذ الشكل في الفصل السابق :

ترى في الشكل أن هناك كائن يسمى بالـ Document ,هذا الكائن و ما يحتويه من كائنات و بيانات يسمى بالـDOM.و لكن ما الكائنات و البيانات التي يحتويها؟
للإجابة على هذا السؤال إفتح أي صفحة ويب بمتصفح الفاير فوكس و إضغط f12 لتظهر لك أدوات مطوري المواقع ثم أختار html كما بالصورة:


ستظهر لك قائمة بها محتويات الصفحة منسقة على شكل قوائم و ستجد علامات "+" عند بعض العناصر التي عندما تضغط عليها ستظهر لك قائمة أخرى من العناصر بحيث أنك ستجد كل تاج html (*) و كل نص و كل مكون من مكونات الصفحة ممثلا .
كل هذه المكونات و المعلومات تتيح لك الجافا سكريبت الوصول لها و التعامل معها من خلال الكائن Document .

(*):التاج tag يترجم بالعربية ل"وسم" و كأمثلة له <html> أو <p>, و احب إستخدام كلمة تاج لأن كلمة وسم غريبة ,فبدلا منها اكتب الكلمة الإنجليزية بالعربية .

و الآن عرفنا أن DOM هو الكائن Document بمحتوياته و عرفنا أن هذا الكائن يحتوى بداخله على محتويات صفحة الhtml .و لنقترب أكثر و نعرف كيف تمثل محتويات الصفحة في الكائن Document ,أنظر الشكل التالي:

على اليسار كود الhtml للصفحة و على اليمين شكل يوضح كيف تمثل في الجافا سكريبت.

يمثل التاج في الجافا سكريبت بكائن و ما يوجد داخله من تاجات و نصوص و( صفات Artibutes ) يمثل بخواص للكائن,و نعلم أنه يمكن أن يكون كائن خاصية في كائن آخر .و هناك مصطلح جديد يستخدم لوصف محتويات الـDom و هو الـ Node (النقطة ).
و ببساطة إذا نظرت للشكل بالأعلى فإن كل مستطيل من المستطيلات يسمى Node .تسمى النود الأعلى بالنقطة الأب parentNode و المتفرعات منها تسمى بالأبناء childNodes مثلا في الشكل تسمى body بالنقطة الأب ل p و تسمى p بالتالي بالنقطة الإبن لbody كذلك تسمى النقاط "this is the" و "paragrph"و em بالنقاط childNodes الأبناء لـ P.
الـDOM واسطة بين الهيتمل و الجافا سكريبت فهي تمكنك من معرفة قيم بيانات الهيتميل و أيضا التحكم فيها بالجافا سكريبت :
بالنسبة للهتميل الـ Nodes تكون إما عناصر html مثل <p> أو <body> أو نصوص مثل "this is the" أو أنواع أخرى سنذكرها في الدروس التالية .
أما أنوع البيانات في الـ Nodes عندما تتعامل معها داخل الجافا سكريبت يمكن أن تكون كائنات أو مصفوفات أو أوتار أو أرقام .

ما سبق هو مقدمة نظرية للDOM و إن لم تستوعبها جيداً لا تقلق في الدروس التالية بالأمثلة العملية ستتضح لك الأمور .و قبل أن ننتقل للتطبيق سأوضح لك الطريق الذي سنسير عليه في الفصل بالدروس التالية.
نعلم أن الهدف الأساسي من الجافا الإسكريبت جعل الويب متفاعل مع المستخدم .و فائدة الـ DOM هو أنه يمثل لنا مكونات صفحة الهيتميل بكائنات جافا سكريبت و بالتالي إذا كنت تريد أن تغير نص معين في صفحة الهيتميل مثل "this is the" فإنك لكي تفعل ذلك تحتاج أولا أن تصل له و تحدده و ثم بعد ذلك تجري ما تريد عليه من تعديلات من خلال الجافا سكريبت و ما تحدثه من تعديل في الجافا سكريبت على النص سيظهر أثره على صفحة الهيتميل و ما سندرسه في الدروس التالية هو:
  • كيفية الوصول للـNode التي نريدها.
  • كيفية معرفة خواص ومعلومات الـNode .
  • تغير محتويات هيتميل بالجافا سكريبت.
  • الصفات و تعديل إستايل العرض بالجافا سكريبت.


[تحسين] كيفية الوصول للنود التي نريدها
عرفنا أننا سنتحكم في هيتميل بالجافا سكريبت من خلال الكائن document و أن كل محتويات الهيتمل خواص بداخله و لذا للوصول للمحتوى الذي نريده فإننا في الأساس نستخدم النقطة "." و بعض الدوال و الخصائص التي سنشرحها في هذا الدرس .هناك طرق كثيرة و متعددة لفعل ذلك سنشرح منها الأكثر عملية و فاعلية .
سأقوم بالشرح على كود الهيتمل التالي في هذا الدرس و أيضا الدروس التالية قم بنسخه في برنامج مثل النوت باد و احفظه كملف html ثم إضغط f12 لفتح أدوات مطوري الويب و يفضل إستخدام متصفح الفاير فوكس المثبت به firebug لأن المتصفحات الأخرى ليس بها كل المميزات .
الكود:
<!DOCTYPE ...>
<html>
<head>
<title>DOM learning</title>
</head>
<body>
<div id="para">
	<p>This is a paragraph.</p>
</div>
<div id="list">
	<ul>
		<li class="first">first item</li>
		<li>second item </li>
		<li>third item </li>
	</ul>
	
</div>
</body>
</html>
في أداة مطوري المواقع إذا إخترت html و قمت بعرض كل العناصر الفرعية بالضغط على كل علامات ال"+" سيظهر لك الشكل التالي:

عناصر كل قائمة عبارة عن "أبناء" childs لرأس القائمة بمعنى مثلا أنه:

  • <head>و<body> أبناء لـ <html>.
  • <div id="para">و <div id="list">أبناء لـ<body>.
  • <ul> إبن لـ <div id="list">
  • <li class="first">first item</li> و <li>second item </li> و <li>third item </li> أبناء لـ<ul>.
أيضا يسمى أول عنصر في القائمة بالإبن الأول firstChild و الذي يليه يكون الثاني و هكذا حتى الأخير lastChild . الآن قم بفتح الـ console و قم بكتابة document فيه و اضغط Enter سيظهر لك مثل الموجود في الصورة التالية :

يظهر بالأزرق الأمر الذي كتبته

>>> document

و أسفله بالأخضر يوجد محتوى الكائن document إذا ضغط على document المكتوبة بالأخضر فإنها ستأخذك إلى قسم آخر من أدوات المطورين و هو DOM و ستجد أمامك كل ما يحتويه الكائن document من خواص و دوال كما بالصورة التالية:

لكل نقطة Node في الـ DOM عدد من الخصائص تساعدنا في الإنتقال منها إلى النقاط التي نريد,دائما نبدأ من الأعلى من document و أول خاصية سنتعرف عليها هي childNodes و ترجع مصفوفة بالأبناء للنقطة :

أكتب في الكنسول :
document.childNodes
سيرجع لك: [DocumentType { constructor=DocumentType, nodeName="...", nodeType=10, more...}, html]

و ستجد أن المصفوفة تتكون من عنصرين الأول نوع الوثيقة و الثاني html و هما إذا نظرت للشكل الثالث في الدرس الأول سيتضح لك أنهم الأبناء childs للنقطة document

. العنصر الثاني في المصفوفةhtml و لذا الوصول لها يكون كالتالي:
document.childNodes[1]
و ستجد أن الناتج <html> يمكنك أن تضع النقطة في متغير و يتم التعامل معه كأنه هي ,هكذا:
var htdoc=document.childNodes[1]
و لذا إذا كتبت إسم المتغير في الكنسول
htdoc

سيرجع <html>

للوصول إلى أبناء <html> نستخدم childNodes مرة أخرى :
htdoc.childNodes
سترجع لك المصفوفة :

[head, <TextNode textContent="\n">, body]

الأول head و الأخير body و هما الأبناء ل html أما العنصر الثاني في المصفوفة فهو عبارة عن \n و هي تعني سطر جديد و ذلك لأن الDOM يأخذ في الإعتبار المسافات الخالية . لكي تصل إلى الإبن الأول بطريقة أسهل تستخدم firstChild بدلا من childNodes[0]
htdoc.firstChild
يرجع <head> للوصول لآخر إبن مباشرة يمكن أن تستخدم lastChild.
htdoc.lastChild

يرجع <body>

أما إذا كنت تريد أن تصل من نقطة إبن للأب فتستخدم parentNode.

htdoc.parentNode

ترجع Document .

توجد خاصية تشبه childNodes لكنها مطورة أكثر بحيث أنها لا تعتبر المسافات البيضاء نقط و لكنها للأسف لا تعمل أيضا على إكبسلورر 6 و 7,و هذه الخاصية هي children.
document.getElementById("list").children[0].children
يرجع لك [li.first, li, li]

يمكننا الوصول مباشرة للعناصر من خلال عدد من الدوال أهمهم:

getElementById

و تمكنك للوصول للعنصر الذي تريده من خلال الـ id فللوصول إلى <div id="para"> تستخدمها هكذا.
document.getElementById("para")
و و كمثال آخر الوصول للعنصر <div id="list">
var list=document.getElementById('list')
و يمكن بعدها أن تأتي بالأبناء للعنصر <div id="list"> بإستخدام childNodes هكذا
list.childNodes
من الدوال المهمة دالة getElementsByTagName و تأتي بكل العناصر التي لها التاج الذي تحدده في مصفوفة
document.getElementsByTagName("div")

ترجع المصفوفة [div#para, div#list]

و أيضا للوصول للعنصر من خلال إسم الكلاس className توجد دالة هي getElementsByClassName و تأتي بمصفوفة فيها العناصر التي لها الكلاس الذي تحدده
document.getElementsByClassName("first")

ترجع [li.first]

لاحظ أن العناصر مكتوبة داخل المصفوفات بالطريقة التي تكتب بهاالـselectors (*) في الإستايل شيت.لكن هذا لا يفرق معنا في شيء .

(*)الـ selectors مفهوم يخص الcss ,وهو المحددات التي تحدد العناصر التي يتم تطبيق الإستايل عليها فمثلا لجعل كل القوائم تكتب باللون الأحمر تكتب ul{color:red} هنا ul تسمى بالـselector.

الآن لنأخذ بعض التطبيقات على ما سبق . للوصول إلى العنصر الثاني في القائمة second item يمكن ذلك بعدة طرق:
var ul=document.getElementById("list").childNodes[1]
ul.childNodes[3]
أو
document.getElementsByTagName('li')[1]
و يوجد طرق أخرى عديدة هناك دالتين جديدتين أكثر فاعلية لكنهم لا يعملو في إكسبلورر 6 و 7. querySelector و querySelectorAll و تستخدم css selectors للوصول مباشرة إلى التاج الذي تريده.

querySelector

ترجع عنصر واحد ,العنصر الأول مما ينطبق عليه الـselector . مثلا للوصول للعنصر الأول في القائمة first item نستخدم
document.querySelector("ul .first")
فترجع <li class="first"> أما

querySelectorAll

يرجع مصفوفة بكل العناصر التي ينطبق عليها الـselector مثلا
 document.querySelectorAll("ul li")

ترجع [li.first, li, li] وهما الثلاث عناصر الموجودين في القائمة.

[تحسين] معلومات النقط
سنكمل العمل على نفس المثال الموجود في أول الدرس السابق,عندما تريد أن تعرف نوع البيانات في الجافا سكريبت فأنك تستخدم typeof لاحظ الأمثلة التالية:
للوصول إلى أول عنصر في القائمة ثم إختبار نوع البيانات التي وصلنا لها
 var li=document.getElementsByTagName('li')
typeof li[0]

سيرجع لك الناتج "object"

و إذا وصلنا للنص الذي بداخله و الذي يكون هوا الإبن الأول له ثم أختبرنا النوع ايضا
var text=li[0].firstChild
typeof text

أيضا ستجد أنه نوعه "object".

كما ترى سواء كانت النقطة عبارة عن عنصر هيتميل "تاج" مثل li أو نص فإن نوعها كبيانات جافا سكريبت يكون object,لكن كيف نعرف من خلال الجافا سكريبت ماذا تمثل هذه البيانات في هيتيل كيف نعرف إن كانت النقطة نص أو عنصر هيتميل و كيف نعرف قيمة النقطة و إسمها .هذا ما سنعرفه من خلال هذا الدرس. هناك ثلاث خواص يزودونا بمعلومات أساسية عن النقاط و هم
  • nodeType و نعرف من خلالها نوع النقطة.
  • nodeName و نعرف من خلالها إسم النقطة.
  • nodeValue و نعرف من خلالها قيمة النقطة

nodeType

ترجع رقم يعبر عن نوع النقطة حسب الجدول التالي
المتغيرالوصف
1يعني أن النقطة عبارة عن تاج هيتميل
2النقطة عبارة عن صفة ATTRIBUTE
3النقطة عبارة عن نص
الجدول يحتوى على الأشياء الأساسية أما للوصول و لكن هناك أنواع أخرى من النقاط و للوصول لمعنى الأرقام فإن ذلك متوفر في كائن يسمى Node حيث توجد فيه قيم الأرقام مخزنه كثوابت و لتجدها اكتب في الكنسول
Node
سيرجع لك Node {ELEMENT_NODE=1, ATTRIBUTE_NODE=2, TEXT_NODE=3, more...} قم بالضغط عليها ستفتح لك صفحة فيها القيم الرقمية و مدلولها.

و الآن لنطبق على المثال الذي نعمل عليه.

li=document.getElementsByTagName('li')[0]
li.nodeType

سيرجع لك 1 حيث أن النقطة عبارة عن التاج li.

الآن فلندخل إلى النص الذي داخل li و نختبر نوعه
text=li.firstChild
text.nodeType
سيرجع لك 3 حيث أن النقطة عبارة عن نص .

nodeName

للنقاط التي تكون عبارة عن تاج <tag> في هيتميل ,يرجع لنا إسم التاج
document.getElementsByTagName('li')[0].nodeName

يرجع "LI"

أما إن كانت النقطة هي document رأس الـDOM
document.nodeName

يرجع "#document"

و في حالة كانت النقطة نص text
text=document.getElementsByTagName('li')[0].firstChild
text.nodeName
فإنه يرجع "#text"

nodeValue

هذه الخاصية مفيدة مع النصوص حيث من خلالها نصل للنص نفسه كـstring و ليس نقطته أنظر الأمثلة : للوصول إلى نقطة النص الموجود في أول عنصر في القائمة first item
textnode=document.querySelector('li.first').firstChild
سيرجع لك <TextNode textContent="first item"> لإختبار النوع
typeof textnode

يرجع "object"

إذا عرضنا textnode بإستخدام alert
alert(textnode )
ستجد أن الصندوق مكتوب فيه [object text] و ليس النص نفسه . للوصول للنص نفسه نستخدم nodeValue
text=textnode.nodeValue

يرجع لك "first item"

لإختبار النوع
typeof text
تجد أن النوع "string" لعرض المحتوى
alert(text)

ستجد أن الصندوق مكتوب فيه "first item"
مع النقاط التي تمثل تاج هيتميل خاصية nodeValue ترجع null ,فكما قلنا هي مفيدة مع نقط النصوص .

[تحسين] تغير محتويات هيتميل بالجافا سكريبت.
سنكمل العمل على نفس المثال الموجود في الدرس الثانيخلال هذا الدرس .أبسط مثال على تغير محتوى الصفحة بالجافا سكريبت من خلال الـ Dom هو تغير النصوص من بإستخدام nodeValue كالتالي :
سنغير النص first item الموجود كأول عنصر من عناصر القائمة
textnode=document.getElementsByTagName('li')[0].firstChild
textnode.nodeValue="changed"
عند كتابة هذا النص في الكنسول للمثال الذي نعمل عليه ستجد أن أول عنصر في القائمة تغير من first item لـ changed .و كما ذكرنا في الدرس السابق أن nodeValue تصلح فقط مع نقط النصوص فهي بتغير قيمتها أيضا لا تصلح إلا لتغير قيم النصوص أما إذا كنت تريد أن تغير محتوى الهيتمل كله لنقطة كأن تغير محتوى div مثلا فماذا تفعل؟.أبسط طريقة تكون بإستخدام أداة innerHTML

innerHTML

بإستخدام innerHTML مع أي نقطة تمثل تاج هيتمل فإنها ترجع لنا محتوى التاج كاملا فمثلا:
document.getElementById('list').innerHTML
ترجع

" <ul> <li class="first">first item</li> <li>second item </li> <li>third item </li> </ul> "

و أيضا
document.getElementById('para').innerHTML
ترجع

" <p>This is a paragraph.</p> "

و لتغير محتوى الهيتميل لأي نقطة فإننا نغير قيمة innerHTML لها كهذا المثال حيث سنضع القائمة مكان القطعة This is a paragraph ثم نضع إرتباط تشعبي link مكان القائمة
list=document.getElementById('list')
para=document.getElementById('para')
para.innerHTML=list.innerHTML
list.innerHTML="<a href='#'>link</a>"
عند تنفيذ هذا الكود ستجد أن القائمة أصبحت بالأعلى مكان النص و صار مكانها إرتباطا تشعبيا link الأمثلة السابقة عبارة عن إحداث تعديل في محتوى نقاط موجودة أصلا ,أما لكي تضيف نقطة جديدة فإنك تنشئها أولا من خلال دوال معينه ثم تضيفها بإستخدام دوال أخرى و هذا ما سنشرحه الآن.

أولا:لإنشاء نقطة جديدة .

لإنشاء نقطة تكون عبارة عن تاج هيتميل تستخدم الدالة
document.createElement("إسم التاج");
مثلا لإنشاء نقطة عبارة عن التاج <p>
var par=document.createElement('p')
فيتم وضع النقطة الجديدة في المتغير par و لذا إذا كتبت par في الكنسول سيرجع لك <p> . لإنشاء نقطة تكون عبارة عن نص نستخدم الدالة
document.createTextNode("النص ")
مثلا إنشاء نقطة نصية تحتوى على النص جملة "هذا نص جديد"
text=document.createTextNode("هذا نص جديد").
الدالتين السابقتين مثل دالة write()لا بد أن تسبق ب document و ليس يمكن إستخدامهم مع أي نقطه أخرى في الـDOM. أما لعمل نسخه من نقطة موجوده مسبقا نستخدم دالة ()cloneNode و تأخذ برامتر إما true لتنسخ كل محتويات النقطة أو false لتنسخ النقطة فقط بدون ما تحتويه من نقط و لنطبق ذلك على المثال الذي نعمل عليه منذ الدرس الثاني. لنسخ النقطة div التي لها ال id="para" بوضع البرامتر true
nodecopy=document.getElementById('para').cloneNode(true)
nodecopy.innerHTML
ستجد أن النقطة نسخت إلى المتغير nodecopy الذي عندما تستعرض محتوياته بإستخدام innerHTML ستجدها " <p>This is a paragraph.</p> " و هو كل ما تحتويه ال div أما بوضع البرمتر flase
document.getElementById('para').cloneNode(false)
nodecopy2.innerHTML
في هذه المرة ستجد أن محتوى nodecopy2 عبارة عن "" أي أنه خالي.

ثانيا:إضافة النقط الجديدة إلى هيتميل.

تعلمنا كيف ننشيء النقط الآن سنتعلم كيف نركب النقط التي أنشأناها بالجافا سكريبت في الهيتميل و ذلك يكون من خلال عدد من الدوال.

appendChild(النقطة)

تركب النقطه الجديدة كإبن أخير lastChild للنقطة التي تركبها فيها. و كمثال سننشئ تاج <p> ثم نضع فيه نقطة نصية فيها النص "this is text" ثم نركب النقطه الجديدة في الـdiv الأول الذي له ال id=para
el=document.createElement('p')
text=document.createTextNode('this is text')
el.appendChild(text)
div=document.getElementById('para')
div.appendChild(el)
عند تنفيذ هذا الكود ستجد أنه سيظهر نص جديد في الصفحة و هو this is text و ستجد أنه ظهر بعد This is a paragraph و ليس قبل و ذلك لأنه كما قلنا هذه الدالةappendChild تضع النقطة كآخر نقطة.

insertBefore(النقطة الجديدة, النقطة الموجودة)

دالة insertBefore تضع النقطة الجديدة التي تعطيها لها قبل نقطة موجودة تحددها لها فمثلا سنضيف في المثال التالي النص this is text قبل This is a paragraph
el=document.createElement('p')
text=document.createTextNode('this is text')
el.appendChild(text)
div=document.getElementById('para')
firstp=div.childNodes[1]
firstp.parentNode.insertBefore(el,firstp)
في الثلاث سطور الأولى قمنا بإنشاء النقطة p و النص الذي بداخلها ,و هي موضوعة في المتغير el.

في السطر الرابع و الخامس و صلنا للنقطة التي نريد أن نضع النقطة التي أنشأناها قبلها ووضعناها في المتغير firstp.

في السطر الأخير قمنا فيه بتركيب النقطة الجديدة في الصفحة
firstp.parentNode.insertBefore(el,firstp)
لاحظ أننا وضعنا insertBefore بعد النقطة الأب parentNode للنقطة التي نريد أن نضع النقطة الجديدة el قبلها و التي هي firstp.

createDocumentFragment()

هذه الدالة تنشيء شيئا يسمى بالـDocumentFragment و هو عبارة عن صندوق تضع فيه النقاط عندما تريد أن تنشئ نقاط عديده ثم تركبها في الصفحه.كما بالمثال
var fragment = document.createDocumentFragment();
// Create 100 new paragraphs with createElement()
for (var i = 0; i < 100; i++) {
var para = document.createElement("p");
para.appendChild(document.createTextNode("Paragraph " + i));
fragment.appendChild(para);
}
document.body.appendChild(fragment)
هذ المثال يضيف 100 فقرة <p> .و إذا قمنا بإضافتهم واحدة واحدة إلى المتصفح هذا سيسبب بطئ و ثقل في الأداء و لذا فإنه يتم إنشاء fragment كما في السطر الأول ثم نضع النقاط كلها فيها كما في السطر السادس ثم بعد ذلك نقوم بالتركيب ال fragment بإستخدام appendChild .و إذا وضعت هذا الكود في الكنسول في المثال الذي نعمل عليه ستجد أن مئة فقرة ستظهر في الصحفة .

ثالثا:حذف نقطة

لحذف نقطة تستخدم الدالة

removeChild(النقطة الإبن)

وهي تقوم بحذف النقطة التي تحددها لها و ذلك بأن تسبق الدالة بالأب للنقطة التي تريد حذفها ثم تضع بين القوسين النقطة التي تريد حذفها مثلا لنحذف أول عنصر من عناصر القائمة في المثال الذي نعمل عليه.
li1=document.getElementsByClassName('first')[0]
li1.parentNode.removeChild(li1)
عند تنفيذ هذا الكود ستجد أن العنصر الأول في القائمة اختفى من الصفحة.

تطبيق

في هذا المثال سنستخدم innerHTMLمع createElement لإضافة محتوى كبير نسبيا بطريقة سهلة قم بتجربته بنفسك.
تطبيق
<!DOCTYPE html>

<html>
<head>
    <title>Lesson 14 Example 1</title>
</head>
<body>
    <script type="text/javascript">
        var shoppingList = [
            "Eggs",
            "Milk",
            "Juice",
            "Diapers",
            "Bread"
        ];

        var ul = document.createElement("ul");
        
        for (var i = 0; i < shoppingList.length; i++) {
            ul.innerHTML = ul.innerHTML + "<li>" + shoppingList[i] + "</li>";
        }

        document.body.appendChild(ul);
    </script>
</body>
</html>

حاول بنفسك »اضغط على "حاول بنفسك" لكى ترى كيف تعمل فى الحقيقة


[تحسين] الصفات و تعديل إستايل العرض بالجافا سكريبت.
تعلمنا في الدروس السابقة كيف نصل إلى النقاط و كيف نغيرها و كيف نضيف نقاط جديدة إلى صفحة الهيتيمل .لكن لم نتعامل مع الـattributes و التي لها يتحدد من خلالها صفات عنصر الهيتميل فمثلا href في التاج a هي التي تحدد العنوان الذي ستنتقل له بالضغط على الإرتباط التشعبي .في هذا الدرس سنتعلم كيف نصل إلى الـattributes و كيف نغير قيمها بالجافا إسكريبت سنعمل خلال هذا الدرس على الكود التالي ,قم بنسخه و احفظه كملف html .
<!DOCTYPE ...>
<html>
<head>
<title>DOM learning 2</title>
<style>
.first{
	color: red;
}
.second{
	color: blue;
}	
</style>
</head>
<body>
	<h1>simple page</h1>
<div id="para">
	<p id="first" class="first">first paragraph.</p>
	<p id="second" class="second">second paragraph.</p>
	
</div>
<div id="frm">
	
		<a href="http://www.google.com">Search Engine</a><br/><br />
		<form>
input:<input type="text" name="name" id="name" value="" /><br /><br />
option1:<input type="radio" id="radio1" name="op"  value="x"/><br/><br />
option2:<input type="radio" id="radio2" name="op" value="y"/><br/><br />
agree?<input type="checkbox" />
</form>
</div>
</body>
</html>
عند فتح الملف سيكون شكل الصفحة كالتالي .

الطريقة الأبسط للوصول للصفات هو إستخدام الأداة "." بعد النقطة التي تمثل العنصر الذي تريد أن تصل لصفاته ثم بعد ذلك إسم الصفة . لاحظ المثال التالي للوصول إلى قيمة href في اللنك الموجود في الكود بالأعلى .
var link=document.getElementsByTagName('a')[0]
link.href
عند تنفيذ هذا الكود في الكنسول سيرجع لك. "http://www.google.com/" يمكنك أيضا تغير القيمة الموضوعه للصفة .فمثلا نغير العنوان من عنوان جوجل لعنوان الياهو كالتالي
link.href="http://www.yahoo.com/"
ستحد أن العنوان الذي يؤدي له اللنك Search Engine قد تغير من عنوان موقع جوجل لعنوان موقع الياهو . من صفات التاج <input/> الصفة value و التي تحدد النص المكتوب بداخله . أكتب في الصندوق input الكلمة awcore كما بالصورة.

عندما تصل لقيمة الخاصية value ستجد أنها النص المكتوب كالتالي:
document.getElementById('name').value
عند كتابة الأمر في الكنسول سيرجع "awcore" . يمكنك أيضا تغير القيمة المكتوبه في الصندوق من خلال الجافا سكريبت هكذا. فعند تنفيذ هذا الأمر في الكنسول
document.getElementById('name').value ="www.awcore.com"
ستجد أن النص في الصندوق تغير إلى www.awcore.com إستخدام هذه الطريقة التي إستخدمناها في الوصول لقيم الصفات ترجع لنا "قيمة محسوبة " و ليس القيم الموضوعه لها في هيتميل .فمثلا بالنسبة للتاج </input> من النوع type="radio" له صفة تسمى checked.مهمة هذه الصفة هي أنك عندما تريد أن يكون علامة الراديو معلم عليها بشكل إفتراضي فأنت تضع لها القيمة "checked" هكذا
:<input type="radio" id="radio2" name="op" checked="checked" value="y"/>
في الجافا سكريبت عندما تصل للصفة checked كما فعلنا بالأمثلة السابقة فإنه إن كان معلم عليها سيرجع لك true و ليس "checked" أما إن لم يكن معلم عليها فسترجع flase .في المثال الذي نعمل عليه علم على option1 و اكتب في الكنسول
document.getElementById('radio1').checked
سيرجع true إذا أزلت العلامة و أعدت تنفيذ الكود سيرجع false.و بالطبع القيم true و false تسهل التعامل أكثر في الجافا سكريبت . هناك صفتين في الهيتميل هما calss و for تتفق أساميهم مع كلمات خاصة بالجافا سكريبت و لذلك للوصول لهم بالجافا سكريبت نتسخدم className و htmlFor.
document.getElementById('first').className
ترجع "first"

الطريقة الأخرى للتعامل مع الصفات تكون من خلال عدد من الدوال الخاصة بتلك المهمة و هذه الدوال هي:

getAttribute(الصفة):تأتي لك بقيمة الصفة التي تحددها و ترجع القيمة الموجوده في هيتميل و ليس القيمة المحسوبه .

و كتطبيق على الكود الذي نعمل عليه
document.getElementById('first').getAttribute('class')
سترجع "first" و يتضح أنها ترجع القيم الموجودة في هيتميل و ليس المحسوبه من خلال هذا المثال
document.getElementById('radio1').getAttribute('checked')
سترجع null و ليس true أو false . ملحوظة :بالنسبة لمتصفح إنترنت أكسبلورر لتأتي بالقيمة الأصلية و ليس المحسوبه نستخدم getAttribute("الصفة", 2);

setAttribute("الصفة", "القيمة"):تستخدم لتغيير قيمة صفة كالتالي:

document.getElementById('name').setAttribute('value','awcore')
عند تنفيذ هذا الأمر ستجد أنه كتب في الصندوق الكلمة awcore.

removeAttribute("الصفة"):تحذف الصفة التي تحددها .مثلا الفقرة الأولى first paragraph. باللون الأحمر لأن لها الclass قيمته red .

و لذا إذا أزلت الصفة class سيرجع اللون إلى اللون الأسود كالتالي:
document.getElementById('first').removeAttribute('class')
ستجد أن الفقرة الأولى تغير لونها من الأحمر إلى الأسمر .

hasAttribute("الصفة"):تختبر إن كانت الصفة موجوده أم لا .

document.getElementById('first').hasAttribute('href')
سترجع flase لأن الصفة غير موجودة . الآن لنرى كيف يمكننا تعديل الإستايل css بإستخدام الجافا سكريبت. الطريقة الأول بتغيير ال class و بالطبع يمكنك من الإستايل شيت تحديدمواصفات كل كلاس .و لدينا في المثال الذي نعمل عليه كلاسين الأول .first و الثاني .second و مما يتضح من الإستايل شيت أن الأول محدد له أن يكون اللون أحمر أما الثاني فلون الكتابة يكون أزرق .إذ غيرنا الكلاس للفقرة الأولى من first ل second سيتغير اللون من الأحمر إلى الأزرق ونقوم بذلك كالتالي:
document.getElementById('first').className='second'
و بالطبع بما أنه بإستخدام الكلاس في الإستايل شيت يمكن تحديد عديد من المواصفات للكلاس كل هذه المواصفات ستتغير بتغير الكلاس .أما لتغير شيء واحد كاللون أو حجم الخط مثلا فذلك يتم من خلال الصفة style

الصفة style

و هي صفة ذات ميزات خاصة في الجافا سكريبت.و الميزة الخاصة في الصفة style أنها لها عدد من الخصائص تماثل خصائص الإستايل شيت مثلا في الإستايل شيت تستخدم الخاصية color لتغيير اللون أيضا الصفة style لها خاصية تسمى color يمكن من خلالها تغير اللون فلتغير لون الفقرة الأولى في مثالنا first paragraph يمكن عمل ذلك كالتالي:
document.getElementById('first').style.color='orange'
عند تنفيذ هذ الأمر في الكنسول سيتغير اللون إلى اللون البرتقالي.

ملحوظة:في الإستايل شيت خصائص تتكون من كلمتين مثل font-family ,في الجافا سكريبت تكون مكتوبة هكذا fontFamily حيث تبدأ الكلمة الثانية بحرف كبير بدلا من الشرطة '-'.

في هيتمل يمكنك إضافة الإستايل شيت بثلاث طرق :
  • من خلال الصفة style في التاج الذي تريد تحديد الإستايل له و تسمي هذه الطريقة بالسطرية (inline) و هذا مثال عليها:
  • <p style="font-family: monospace; background-color: #fcc;margin-bottom: 10px">Text</p>
  • أو من خلال التاج <style> كالمثال الذي ذكرناه في أول الدرس.
  • أو من خلال ملف خارجي .
و إستخدام style في الجافا سكريبت يغير الإستايل من خلال الطريقة السطرية .فمثلا الفقرة الثانية في المثال لونها أزرق second paragraph. لكن إذا نفذت هذا الكود :
document.getElementById('second').style.color
سيرجع لك "" نص خالي و ليس 'blue',و ذلك لأن اللون الأزرق محدد للفقرة بإستخدام الطريقة الثانية و ليس الأولى .حيث لا يوجد داخل التاج < p> الصفة style . لتغير اللون إلى اللون الأصفر:
document.getElementById('second').style.color='yellow'
ما حدث هو أن هذا الكود يضع داخل التاج الصفة ستايل و يحدد من خلالها اللون أي يجعله هكذا:
<p id="second" class="second" style="color: yellow;">second paragraph.</p>
يمكنك التأكد من هذا بنفسك إذا إنتقلت للقسم html في أداة مطوري المواقع كما بالصورة :

و لذا إذا إستخدمت hasAttribute لتعرف إن كان التاج فيه الصفة style أم لا هكذا:
document.getElementById('second').hasAttribute('style')
سيرجع لك true أي أنه الصفة موجودة ,حيث تم وضعها عندما قمت بتغير اللون .

و يأتي الآن سؤال آخر كيف يمكننا الوصول لخصائص للإستايل إن كان محدد بالطريقة الثانية أو الثالثة ؟

الإجابة أن هناك دوال مخصصة لعمل ذلك ,لكن يعيبها أن للإنترنت إكسبلورر دالة تختلف عن التي لبقية المتصفحات للقيام بهذه الوظيفة و هذا يضيف جهد إضافي في البرمجه ,كما أن هذه الدوال ترجع القيم محسوبة و ترجعها بشكل يحتاج بعض المعالجة بالجافا سكريبت لكي يمكن الإستفاده منها فمثلا ترجع اللون الأحمر بطريقة rgb هكذا "rgb(0, 0, 255)", و لذا عمليا يفضل إستخدام دوال الـ jquery ,أما الآن فسنذكر دوال الجافا سكريبت لمجرد العلم بها و في الدروس المتقدمه سنعود لنعرف كيف يمكننا في حالة إختلاف الدوال المستخدمه في المتصفحات المختلفة لنفسه المهمة أن نجعل الكود صالح للعمل على جميع المتصفحات و و أيضا قد نتعرض لأمثلة لكيفية معالجة البيانات بحيث تفهمها الجافا سكريبت للغرض الذي نريده. في الإكسبلورر تستخدم
العنصر .currentStyle("الخاصية");
أما في المتصفحات الأخرى:
document.defaultView.getComputedStyle(العنصر,null).getPropertyValue("الخاصية");