Dom در جاوا اسکریپت
در این فصل به بررسی DOM یکی دیگر از اجزای مهم تشکیل دهنده جاوا اسکریپت می پردازیم. این DOM است که امکان دسترسی و دستکاری عناصر موجود در صفحه و قابلیت اضافه، حذف و جابجایی آن ها در جای جای صفحه را فراهم می آورد. در سرآغاز این فصل ابتدا به بررسی و تشریح DOM پرداخته و سپس روش هایی که برای دستکاری عناصر موجود در صفحه را فراهم کرده توضیح خواهیم داد.
Dom در جاوا اسکریپت چیست؟
DOM در جاوا اسکریپت به توسعه دهندگان وب امکان دسترسی و دستکاری عناصر یک صفحه HTML را می دهد. این مدل عناصر موجود در یک صفحه HTML را به صورت درختی از گره ها ترسیم می کند. به تکه کد زیر دقت کنید:
<html> <head> <title>DOMinating JavaScript</title> </head> <body> <h1>DOMinating JavaScript</h1> <p> If you need some help with your JavaScript, you might like to read articles from <a href=http://www.danwebb.net/ rel="external">DanWebb</a> <a href="http://www.quirksmode.org/" rel="external">PPK</a> and <a href="http://adactio.com/" rel="external">Jeremy Keith</a> </p> </body> </html>
این کد را می توان در قالب درخت زیر نمایش داد :
همانطور که می بینید می توان هر یک از عناصر موجود در صفحه را در قالب یک گره نمایش داده می شود. اما همیشه در DOM گرهی ویژه به نام document وجود دارد که در بالاترین سطح درخت قرار گرفته و سایر گره ها را شامل می شود. با این فرض درخت فوق به شکل زیر تبدیل خواهد شد:
در درخت بالا هر مستطیل به عنوان یک گره محسوب می شود. گره ها انواع مختلفی دارند که بعضی از آن ها به شرح زیر است:
document : بالاترین گرهی که همه گره های دیگر به آن متصل هستند(فرزند آن هستند). به این نوع گره ، گره سند گفته می شود.
element : گره ی که شامل یک عنصر از صفحه باشد. این گره شامل یک تگ آغازی و یک تگ پایانی مانند <tag></tag> یا </ tag> است. این نوع گره تنها نوعی است که می تواند شامل فرزندان از انواع دیگر باشد. به این گره ها ، گره عنصری گفته می شود.
text : این نوع گره ها به متن موجود در داخل یک تگ آغازی و تگ پایانی اشاره دارند. این نوع گره ها هم نمی توانند فرزند داشته باشند. به این نوع گره ها ، گره متنی ۳ می گویند. اگر گره های متنی را هم به مثالی که بررسی کردیم اضافه کنیم درخت ما به شکل زیر تبدیل خواهد شد:
attr : گره ای که به یک صفت از یک عنصر اشاره می کند و فاقد فرزند می باشد. به این نوع گره ها ، گره صفتی گفته می شود. در درخت DOM معمولا این گره ها را به صورت دایره ای و متصل به گره های عنصری نمایش می دهند. به عنوان مثال هر یک از عناصر لینکی که در مثال بالا مشاهده می شود دارای صفت های href و rel هستند که می توان آن ها را به صورت زیر نمایش داد:
comment : به گره های توضیحی اشاره می کند و فاقد فرزند است. (در واقع به تگ comment صفحه اشاره می کند.)
غالبا گرهی اصلی به عنوان راس این درخت وجود دارد که همان document است.
گره ها از نظر جاوا اسکریپت به عنوان یک شی در نظر گرفته می شوند که این اشیا می توانند خاصیت ها و متدهایی داشته باشند. بعضی از آن ها به شرح زیر هستند:
استفاده از Dom در جاوا اسکریپت
دسترسی به گره ها
تکه کد زیر را در نظر بگیرید:
<html> <head> <title>DOM Example</title> </head> <body> <p>Hello World!</p> <p>Isn’t this exciting?</p> <p>You’re learning to use the DOM!</p> </body> </html>
اولا برای دسترسی به عنصر HTML می توان از documentElement که یکی از خاصیت های شی document است استفاده کنیم. به صورت زیر:
var oHtml = document.documentElement;
حال می توانیم با استفاده از این متغیر به عناصر head و body به صورت زیر دسترسی داشته باشیم:
var oHead = oHtml.firstChild; var oBody = oHtml.lastChild;
راه دیگر به صورت زیر است:
var oHead = oHtml.childNodes[0]; var oBody = oHtml.childNodes[1];
برای بدست آوردن تعداد فرزندان یک گره:
alert(oHtml.childNodes.length); //outputs “۲”
می توانیم از متدی موسوم به ()item برای دسترسی نیز استفاده کنیم:
var oHead = oHtml.childNodes.item(0); var oBody = oHtml.childNodes.item(1);
DOM همچنین از دستور document.body را برای دسترسی به عنصر body صفحه استفاده می کند.
var oBody = document.body;
می توانیم صحت رابطه های سه متغیر oHead ، oBody و oHtml را به صورت زیر نشان دهیم:
alert(oHead.parentNode == oHtml); //outputs “true” alert(oBody.parentNode == oHtml); //outputs “true” alert(oBody.previousSibling == oHead); //outputs “true” alert(oHead.nextSibling == oBody); //outputs “true” alert(oHead.ownerDocument == document); //outputs “true”
دسترسی به صفات عناصر
DOM برای دسترسی و دستکاری صفات یک عنصر سه متد تعریف کرده است:
- getAttribute(name) : مقدار صفتی به نام name را از عنصری خاص برمی گرداند.
- setAttribute(name,new Value) : مقدار صفتی به نام name را برابر new Value قرار می دهد.
- removeAttribute(name) : صفتی به نام name را از عنصری مشخص حذف می کند.
این متدها برای دسترسی و دستکاری مستقیم صفت های یک عنصر بسیار مناسب اند. بنابراین برای به دست آوردن مقدار صفت ID تگی مشخص می توان به صورت زیر عمل کرد:
var sId = oP.getAttribute(“id”);
و برای تغییر مقدار صفت ID به صورت زیر عمل می کنیم:
oP.setAttribute(“id”, “newId”);
دسترسی به گره های خاص
تا به اینجا با دسترسی به گره های فرزند و پدری آشنا شدیم. اما اگر بخواهیم به یک گره خاص، آن هم در عمق یک درخت دسترسی داشته باشیم چه؟ برای سهولت این کار ، DOM چندین متد برای دسترسی مستقیم به گره ها فراهم آورده است.
getElementsByTagName()
از این متد برای دسترسی به لیستی(آرایه) از عناصر خاص استفاده می شود.
var oImgs = document.getElementsByTagName(“img”);
دستور فوق لیستی از تمام عناصر img صفحه را در oImgs ذخیره می کند.
فرض کنید می خواهیم به اولین عنصر عکس اولین پاراگراف صفحه دسترسی داشته باشیم:
var oPs = document.getElementsByTagname(“p”); var oImgsInP = oPs[0].getElementsByTagName(“img”);
می توانیم از دستور زیر برای دسترسی به تمام عناصر صفحه استفاده کنیم:
var oAllElements = document.getElementsByTagName(“*”); getElementsByName()
DOM برای دسترسی به عناصری که صفت name آنها برابر با مقدار خاص است از این متد استفاده می کند. به مثال زیر توجه کنید:
<html> <head> <title>DOM Example</title> </head> <body> <form method=”post” action=”dosomething.php”> <fieldset> <legend>What color do you like?</legend> <input type=”radio” name=”radColor” value=”red” /> Red<br /> <input type=”radio” name=”radColor” value=”green” /> Green<br /> <input type=”radio” name=”radColor” value=”blue” /> Blue<br /> </fieldset> <input type=”submit” value=”Submit” /> </form> </body> </html>
این صفحه رنگ مورد علاقه کاربر را سوال می کند. radiobutton ها اسم یکسانی دارند. اما می خواهیم فقط مقدار radiobutton ی که انتخاب شده است را پیدا کنیم. برای ایجاد ارجاع به عناصر radiobutton می توان از کد زیر استفاده نمود.
var oRadios = document.getElementsByName(“radColor”);
حال می توانید از همان روش قبلی برای به دست آوردن مقدار هر از radiobutton ها به روش زیر عمل کنید:
alert(oRadios[0].getAttribute(“value”)); //outputs “red” getElementById()
از این متد برای دسترسی به عناصر به وسیله خاصیت ID آنها استفاده می شود. می دانیم که خاصیت ID باید یکتا باشد به این معنی که هیچ دو عنصری نمی توانند داخل یک صفحه ، ID یکسانی داشته باشند. این سریعترین و رایجترین راه برای دسترسی به عنصری خاص از صفحه است. به کد زیر نگاه کنید:
<html> <head> <title>DOM Example</title> </head> <body> <p>Hello World!</p> <div id=”div1”>This is my first layer</div> </body> </html>
چنانچه بخواهیم از متد ()getElementsByTagName برای دسترسی به عنصر div این صفحه با شناسه div1 استفاده کنیم باید به صورت زیر عمل کنیم:
var oDivs = document.getElementsByTagName(“div”); var oDiv1 = null; for (var i=0; i < oDivs.length; i++){ if (oDivs[i].getAttribute(“id”) == “div1”) { oDiv1 = oDivs[i]; break; } }
اما می توانیم همین کار را به صورت زیر و با استفاده از متد ()getElementById انجام دهیم:
var oDiv1 = document.getElementById(“div1”);
می بینید که استفاده از حالت دوم بسیار ساده تر ، کوتاه تر و بهینه تر است.
ایجاد و دستکاری گره ها
می توانیم از DOM برای اضافه کردن، حذف کردن و جابجایی و دیگر دستکاریها استفاده کنیم.
ایجاد گره های جدید
برای ایجاد گره های جدید(از انواع مختلف) از متدهای زیر استفاده می شود:
- createAttribute(name) : برای ایجاد یک صفت جدید با name گرفته شده به کار می رود
- createComment(text) : برای ایجاد یک توضیح
- createElement(tagname) : برای ایجاد یک عنصر جدید استفاده می شود.
- createTextNode(text) : ایجاد یک متن ساده با عنوان text
createTextNode() ،appendChild و ()createElement()
فرض کنید تکه کد زیر را داریم:
<html> <head> <title>createElement() Example</title> </head> <body> </body> </html>
حال می خواهیم عبارت زیر را در این صفحه چاپ کنیم:
<p>Hello World !</p>
اولین کار ایجاد یک عنصر <p> است.
var oP = document.createElement(“p”);
حال یک متن ساده ایجاد می کنیم:
var oText = document.createTextNode(“Hello World!”);
حال باید متن را به عنصر <p> ، الحاق کنیم. برای این کار از متد ()appendchild استفاده می کنیم. از این متد برای اضافه کردن یک فرزند به انتهای لیست فرزندان یک گره استفاده می شود.
oP.appendChild(oText);
پاراگرافی که را ایجاد کرده ایم باید به صفحه و قسمت body و یا یکی از زیر مجموعه های آن الحاق کنیم. به این شکل:
oP.appendChild(oText);
نکته : گره های عنصری از خاصیتی خواندنی/نوشتنی به نام innerHTML برای بازیابی و تغییر محتوای یک عنصر پشتیبانی می کنند. این خاصیت جز استانداردهای W3C نمی باشد اما تمامی مرورگرها از آن پشتیبانی می کنند. فرض کنید تگ زیر را در صفحه داریم:
<p id=”intro”>Hello World!</p>
اجرای دستور زیر موجب نمایش پیغام !Hello World یعنی همان محتوای تگ <p> خواهد شد:
txt=document.getElementById(‘intro’).innerHTML; alert(txt);// Hello World!
با نسبت دادن مقداری جدید به این خاصیت با استفاده از علامت انتساب می توانیم محتوای یک تگ را تغییر دهیم:
Var myPara=document.getElementById(‘intro’); myPara.innerHTML=”Click <a href=’#’>Here</a>”;
تگ <p> به صورت زیر درخواهد آمد. زیرا خاصیت innerHTML محتوای تگ را به صورت کامل با مقدار جدید جایگرین می کند.
<p id=”intro”>Click <a href=’#’>Here</a></p> replaceChild() ،removeChild و ()insertBefore()
طبیعتا وقتی می توانیم گرهی را اضافه کنیم امکان حذف آن ها نیز وجود خواهد داشت. برای حذف گره ها ازمتد ()removeChild استفاده می کنیم. این متد یک آرگومان می گیرد که در واقع گرهی است که باید حذف شود. به شکل زیر:
var oP = document.body.getElementsByTagName(“p”)[۰]; document.body.removeChild(oP);
برای جابجایی گره ها از متد ()replaceChild استفاده می شود. از این تابع به صورت زیر استفاده می شود:
var oNewP = document.createElement(“p”); var oText = document.createTextNode(“Hello Universe! “); oNewP.appendChild(oText); var oOldP = document.body.getElementsByTagName(“p”)[۰]; oOldP.parentNode.replaceChild(oNewP, oOldP);
برای اضافه کردن یک عنصر به قبل از عنصر دیگری از ()insertBefore استفاده می شود. این متد دو آرگومان می پذیرد و آرگومان اول را قبل از آرگومان دوم قرار می دهد.
createDocumentFragment()
به محض اینکه تعدادی گره جدید به سند اضافه می کنیم صفحه برای نمایش تغییرات، به روزرسانی می شود. این رفتار برای تعداد تغییرات کم مناسب است. اما هنگامی که تغییرات زیاد باشد و صفحه بخواهد این رفتار را برای تک تک تغییرات تکرار کند ممکن است موجب کندی در عملکرد مرورگر شود.
برای رفع این مشکل می توانید از یک تکه برنامه استفاده کنید. می توانید تمام گره های جدید را به تکه برنامه اضافه کرده و سپس آن را در صفحه اصلی قرار دهید. فرض کنید می خواهیم چندین پاراگراف را در صفحه ایجاد کنیم. در صورت استفاده از روش های قبلی این امر موجب رفرش هر باره صفحه خواهد شد.
اما بهتر است به روش زیر عمل کنیم:
var arrText = [“first”, “second”, “third”, “fourth”, “fifth”, “sixth”]; var oFragment = document.createDocumentFragment(); for (var i=0; i < arrText.length; i++) { var oP = document.createElement(“p”); var oText = document.createTextNode(arrText[i]); oP.appendChild(oText); oFragment.appendChild(oP); } document.body.appendChild(oFragment);
ویژگی های منحصر به فرد DOM برای HTML
یکی از ویژگی های DOM در جاوا اسکریپت این است که امکان تنظیم و دستکاری صفات مربوط به عناصر HTML را فراهم میآورد. از جمله این ویژگی ها می توان به در نظر گرفتن صفات عناصر به عنوان خاصیت های هر شی اشاره کرد که برای این کار متدها و خاصیت هایی ارائه شده است.
می توانیم به صفات عناصر به عنوان خاصیت های آن دسترسی داشته باشیم. فرض کنید عنصر زیر را داریم:
<img src=”mypicture.jpg” border=”۰” />
برای دسترسی و تنظیم src و border می توانیم از متدهای ()getAttribute و یا ()setAttribute استفاده کنیم:
alert(oImg.getAttribute(“src”)); alert(oImg.getAttribute(“border”)); oImg.setAttribute(“src”, “mypicture2.jpg”); oImg.setAttribute(“border”, “۱”);
می توانیم از نام صفات هم به عنوان خاصیت هر یک از اشیاء، برای بازیابی و تغییر مقدار صفات استفاده کنیم:
alert(oImg.src); alert(oImg.border); oImg.src = “mypicture2.jpg”; oImg.border = “۱”;
نکته : بر خلاف بسیاری از صفات تگ ها، نمی توانیم از خود صفت class به عنوان یک خاصیت استفاده کنیم. چون این کلمه جز کلمات رزرو شده است و باید به جای آن از کلمه className استفاده کنیم.
دستکاری قواعد سبک عناصر
گره های عنصری از شی ای به نام style برای دسترسی به قواعد سبک تعریف شده برای تگ ها پشتیبانی می کنند.
سینتکس کلی استفاده از این شی به صورت زیر است:
document.getElementById(‘id’).style.property=”newValue”;
به عنوان مثال فراخوانی دستور زیر موجب تغییر رنگ متن عنصری با id برابر intro به رنگ قرمز خواهد شد:
document.getElementById(‘intro’).style.color=”red”;
در جاوا اسکریپت به منظور دسترسی به آن دسته از قواعدی که شامل کاراکتر – هستند می بایست ابتدا کاراکتر – را حذف کرده و اولین حرف کلمه های بعد از آن را به صورت بزرگ بنویسیم. به عنوان مثال، کد زیر موجب تغییر رنگ پس زمینه عنصر به آبی خواهد شد:
document.getElementById(‘intro’).style.backgroundColor=”blue”;
به عنوان مثالی دیگر برای دسترسی به قواعدی همچون border-top-width و padding-bottom می بایست به ترتیب از نام های borderTopWidth و paddingBottom استفاده نمود.
متدهای مربوطه به جداول
فرض کنید که می خواهیم جدول زیر را به صورت پویا و با استفاده از جاوا اسکریپت ایجاد کنیم:
<table border=”۱” width=”۱۰۰%”> <tbody> <tr> <td>Cell 1,1</td> <td>Cell 2,1</td> </tr> <tr> <td>Cell 1,2</td> <td>Cell 2,2</td> </tr> </tbody> </table>
اگر برای ایجاد این جدول بخواهیم از متد های رایج DOM استفاده کنیم کد ما به صورت ذیل بسیار طولانی و گاهی اوقات سردرگم کننده خواهد شد:
//create the table var oTable = document.createElement(“table”); oTable.setAttribute(“border”, “۱”); oTable.setAttribute(“width”, “۱۰۰%”); //create the tbody var oTBody = document.createElement(“tbody”); oTable.appendChild(oTBody); //create the first row var oTR1 = document.createElement(“tr”); oTBody.appendChild(oTR1); var oTD11 = document.createElement(“td”); oTD11.appendChild(document.createTextNode(“Cell 1,1”)); oTR1.appendChild(oTD11); var oTD21 = document.createElement(“td”); oTD21.appendChild(document.createTextNode(“Cell 2,1”)); oTR1.appendChild(oTD21); //create the second row var oTR2 = document.createElement(“tr”); oTBody.appendChild(oTR2); var oTD12 = document.createElement(“td”); oTD12.appendChild(document.createTextNode(“Cell 1,2”)); oTR2.appendChild(oTD12); var oTD22 = document.createElement(“td”); oTD22.appendChild(document.createTextNode(“Cell 2,2”)); oTR2.appendChild(oTD22); //add the table to the document body document.body.appendChild(oTable);
برای آسانی اینکار DOM یکسری خاصیت ها و متد های منحصر به فردی برای عناصر اصلی جداول همچون tody ، table ، tr ایجاد کرده است.
متد ها و خاصیت های منحصر به فرد جدول به شرح زیر می باشد:
- caption : اشاره به عنصر caption جدول دارد. (البته اگر وجود داشته باشد.)
- tBodies : مجموعه (آرایه) ای از عناصر tbody
- tFoot : اشاره به عنصر tfoot جدول
- tHead : اشاره به عنصر thead جدول
- Rows : مجموعه ای از تمام ردیف های جدول
- ()createThead : ایجاد و قرار دادن یک عنصر جدید thead در جدول
- ()createTfoot : ایجاد و قرار دادن یک عنصر جدید tfoot در جدول
- ()createCaption : ایجاد و قرار دادن یک عنصر جدید caption در جدول
- ()deleteThead : حذف عنصر thead از جدول
- ()deleteTfoot : حذف عنصر tfoot از جدول
- ()deleteCaption : حذف عنصر Caption از جدول
- deleteRow(position) : حذف ردیفی از جدول که در موقعیت position قرار دارد
- (insertRow(positio : قرار دادن ردیفی در موقعیت position
متد ها و خاصیت های tbody
- Rows : مجموعه از ردیف ها در عنصر tbody
- deleteRow(position) : حذف ردیفی در موقعیت position
- insertRow(position) : قراردادن ردیفی در موقعیت position مجموعه ای از ردیف ها
متد ها و خاصیت های tr
- Cells : مجموعه ای از سلو ل ها در یک ردیف
- deleteCell(position) : حذف سلولی در موقعیت position
- insertCell(position) : قرار دادن سلولی در موقعیت position مجموعه ای از سلول ها.
برای ایجاد جدول قبلی کد ما به صورت زیر خواهد بود :
//create the table var oTable = document.createElement(“table”); oTable.setAttribute(“border”, “۱”); oTable.setAttribute(“width”, “۱۰۰%”); //create the tbody var oTBody = document.createElement(“tbody”); oTable.appendChild(oTBody); //create the first row oTBody.insertRow(0); oTBody.rows[0].insertCell(0); oTBody.rows[0].cells[0].appendChild(document.createTextNode(“Cell ۱,۱”)); oTBody.rows[0].insertCell(1); oTBody.rows[0].cells[1].appendChild(document.createTextNode(“Cell ۲,۱”)); //create the second row oTBody.insertRow(1); oTBody.rows[1].insertCell(0); oTBody.rows[1].cells[0].appendChild(document.createTextNode(“Cell ۱,۲”)); oTBody.rows[1].insertCell(1); oTBody.rows[1].cells[1].appendChild(document.createTextNode(“Cell ۲,۲”)); //add the table to the document body document.body.appendChild(oTable);
به پایان آموزش Dom در جاوا اسکریپت رسیدیم ، امیدوارم که این آموزش برای شما مفید واقع قرار گرفته شده باشد. در صورتی که سوالی در رابطه با Dom در جاوا اسکریپت دارید ، از بخش نظرات زیر با ما در میان بگذارید.
دیدگاه ها