DOM là gì?

DOM (Document Object Model) là tiêu chuẩn được định nghĩa bởi W3C (World Wide Web Consortium) cho phép truy cập và thay đổi nội dung, cấu trúc, định dạng của các tài liệu.

W3C DOM gồm 3 phần:

  • Core DOM: tiêu chuẩn cho tất cả các dạng tài liệu
  • XML DOM: tiêu chuẩn cho tài liệu XML
  • HTML DOM: tiêu chuẩn cho tài liệu HTML

Thông tin về DOM có thể tham khảo tại https://www.w3.org/DOM/. Bài viết này chỉ đề cập đến HTML DOM.

Các mức DOM (DOM levels)

DOM mức 0 xuất hiện trước năm 1998, được hỗ trợ chủ yếu khi truy cập các phần tử trên form, các liên kết hay hình ảnh. Năm 1998, khi DOM mức 1 xuất hiện thì DOM mức 0 được biết như là legacy DOM và các đoạn mã dùng cho DOM mức 0 được biên tập lại cho phù hợp. Ngày nay, mọi trình duyệt lớn đều hỗ trợ DOM mức 0.

DOM mức 1 được hỗ trợ bởi hầu hết các trình duyệt lớn. DOM mức 2 xuất hiện năm 2000 và DOM mức 3 xuất hiện năm 2004. Các trình duyệt hỗ trợ rất khác nhau các mức DOM. Việc truy cập các phần tử theo các mức DOM trên các trình duyệt khác nhau làm tốn nhiều công sức của người lập trình JavaScript.

Thư viện jQuery ra đời đã giúp cho việc truy cập các phần tử DOM trở nên dễ dàng hơn.

Cây DOM

DOM thể hiện các tài liệu HTML dưới dạng cấu trúc cây.Ví dụ tài liệu HTML như sau:


<!doctype html>

<html>

  <head>

       <title>Hello World</title>

  </head>

  <body>

      <p>Here's some text.</p>

      <p>Here's more text.</p>

      <p>Link to the <a href="http://www.w3.org">W3</a></p>

  </body>

</html>

Cấu trúc DOM cho tài liệu này:

Các phần tử như html, head, body, v.v. cũng được gọi là các node (số nhiều là nodes). Các node mức thấp hơn một node đã cho gọi là các hậu duệ (descendant), các node mức kề dưới và có quan hệ với một node gọi là các node con và node đó được gọi là node cha (parent). Các node có cùng cha và cùng mức gọi là anh em (sibling).

Ví dụ từ cây DOM trên: các node head, body là con của html; head và body là anh em; title, p, v.v. là hậu duệ của html.

Để thao tác với các phần tử hay các node trên DOM, chúng ta dùng các phương thức JavaScript (hay jQuery).

Nhận các phần tử (retrieving elements)

Hai phương thức phổ biến nhất dùng để nhận các phần tử trong JavaScript là getElementById() and getElementsByTagName().

Nhận phần tử theo ID

Chúng ta có thể nhận một phần tử DOM xác định thông qua thuộc tính ID và trả về tham chiếu đến nó bằng phương thức getElementById(). Xét ví dụ sau:


<!doctype html>

<html>

    <head>

       <title>Hello World</title>

    <head>

    <body>

       <p>Here's some text.</p>

       <p>Here's more text.</p>

       <p>Link to the <a id="w3link" href="http://www.w3.org">W3</a></p>

    </body>

</html>

Giả sử chúng ta muốn nhận phần tử <a>id = w3link, đoạn mã như sau:


var a1 = document.getElementById("w3link");

tham chiếu cho phần tử a có id = w3link sẽ được đặt trong biến a1.

Sau khi nhận các phần tử thông qua id, chúng ta có thể truy cập đến các thuộc tính (khác id) của các phần tử này, ví dụ chúng ta truy cập đến thuộc tính href của phần tử <a> có id = w3link ở đoạn mã trên:

<!doctype html>

<html>

  <head>

     <title>Get By Id</title>

     <script type="text/javascript">

         function checkhref() {

            var a1 = document.getElementById("w3link");

            alert(a1.href);

        }

    </script>

  </head>

  <body onload="checkhref();">

  <p id="sometext">Here's some text.</p>

  <p id="moretext">Here's more text.</p>

  <p id="linkp">Link to the <a id="w3link" href="http://www.w3.org">W3</a></p>

  </body>

</html>

Kết quả:

Nhận phần tử theo tên thẻ (tag name)

Phương thức getElementById() làm việc tốt khi chúng ta chỉ nhận một hay một vài phần tử, nhưng khi cần nhận hơn một phần tử tại một thời điểm chúng ta có thể dùng phương thức getElementsByTagName().

Phương thức getElementsTagName() trả về tất cả các phần tử với tên thẻ nào nào đó trong một mảng hay danh sách, ví dụ đoạn mã sau nhận tất cả các phần tử <img>:


var images = document.getElementsByTagName("img");

Đoạn mã sau đây minh hoạ cách thay đổi màu nền của các ô (thẻ td) trong một bảng (table) khi nhấn chuột vào liên kết Click To Change Colors:


<!doctype html>

<html>

   <head>

       <title>Tag Name</title>

       <script type="text/javascript">

         function changecolors() {

           var a1 = document.getElementsByTagName("td");

           var a1Length = a1.length;

           for (var i = 0; i < a1Length; i++) {

             a1[i].style.background = "#aaabba";

           }

         }

      </script>

   </head>

   <body>

     <table id="mytable" border="1">

         <tr><td id="lefttd0">Left column</td><td id="righttd0">Right column</td></tr>

         <tr><td id="lefttd1">Left column</td><td id="righttd1">Right column</td></tr>

         <tr><td id="lefttd2">Left column</td><td id="righttd2">Right column</td></tr>

     </table>

     <a href="#" onclick="return changecolors();">Click to Change Colors</a>

   </body>

</html>

Khi chạy trình duyệt:

Khi nhấp chuột vào liên kết Click to Change Colors:

Đoạn mã trên nhận tất cả các phần tử <td> và lưu trong biến a1 dưới dạng một mảng:


var a1 = document.getElementsByTagName("td");

duyệt và a1 và thay đổi màu nền từng phần tử:


var a1Length = a1.length;

for (var i = 0; i < a1Length; i++) {

  a1[i].style.background = "#aaabba";

}

Làm việc với các quan hệ cha/con (parent/child), anh em (siblings)

JavaScript chứa các phương thức và thuộc tính để làm việc với các quan hệ trong một tài liệu HTML. Một số thuộc tính phổ biến:

– Thuộc tính childNodes chứa một nhóm (group) các node là con của một phần tử cho trước, ví dụ xác định số node con của phần tử div có id = “myDIV” như sau:


var c = document.getElementById("myDIV").childNodes.length;

thay đổi màu nền của node con thứ hai (index = 1) của phần tử div có id = “myDIV”:


var c = document.getElementById("myDIV").childNodes;

c[1].style.backgroundColor = "yellow";

(Tham khảo thêm tại https://www.w3schools.com/jsref/prop_node_childnodes.asp )

– Thuộc tính firstChildlastChild nhận phần tử con đầu tiên và phần tử con cuối cùng của một phần tử cho trước (nếu phần tử này không có phần tử con nào thì hai thuộc tính là null), ví dụ nhận phần tử con đầu tiên của phần tử ul có id là myList

Mã HTML


<ul id="myList"><li>Coffee</li><li>Tea</li></ul>

Mã JavaScript


var x = document.getElementById("myList").firstChild.innerHTML;//Coffee

Nhận phần tử con cuối cùng của phần tử ul có id là myList

Mã HTML


<ul id="myList"><li>Coffee</li><li>Tea</li></ul>

Mã JavaScript


var x = document.getElementById("myList").lastChild.innerHTML;//Tea

(Tham khảo thêm tại https://www.w3schools.com/jsref/prop_node_firstchild.asphttps://www.w3schools.com/jsref/prop_node_lastchild.asp )

– Thuộc tính parentNode nhận node cha của một phần tử cho trước, ví dụ:nhận phần tử cha của phần tử li có id là myLI:

Mã HTML


<ul>

  <li id="myLI">Coffee</li>

  <li>Tea</li>

</ul>

Mã JavaScript


var x = document.getElementById("myLI").parentNode.nodeName;

(Tham khảo thêm tại  https://www.w3schools.com/jsref/prop_node_parentnode.asp )

– Có thể lặp qua các phần tử con của một phần tử cho trước bằng các thuộc tính nextSiblingpreviousSibling. Nếu không có phần tử anh em thì hai thuộc tính trả về null, ví dụ previousSibling trả về null nếu dùng tại phần tử con đầu tiên, nextSibling trả về null nếu dùng tại phần tử con cuối cùng.

Làm việc với các thuộc tính (attributes)

Xem các thuộc tính (attributes)

Dùng phương thức getAttribute() để nhận các thuộc tính (attributes) của một phần tử đã cho. Phương thức tổng quát để xem tất cả các thuộc tính của một phần tử:


function showattribs(e) {

     var e = document.getElementById("braingialink");

     var elemList = "";

     for (var element in e) {

        var attrib = e.getAttribute(element);

        elemList = elemList + element + ": " + attrib + "\n";

     }

  alert(elemList);

}

Một ví dụ hoàn chỉnh về việc hiển thị các thuộc tính của một phần tử:


<!doctype html>

<html>

   <head>

       <title>Show Attribs</title>

       <script type="text/javascript">

          function showattribs(e) {

              var e = document.getElementById("braingialink");

              var elemList = "";

              for (var element in e) {

                  var attrib = e.getAttribute(element);

                  elemList = elemList + element + ": " + attrib + "\n";

              }

              alert(elemList);

          }

      </script>

      </head>

      <body>

         <a onclick="return showattribs();" href="http://www.braingia.org"

              id="braingialink">Ngoc Minh's Web Site</a>

         <script type="text/javascript">

         </script>

      </body>

</html>

Kết quả trên trình duyệt:

Khi nhấp chuột vào liên kết:

Thiết lập các thuộc tính (attributes)

Thiết lập giá trị cho các thuộc tính của một phần tử chúng ta dùng phương thức setAttribute(att_name, value) với att_name là tên thuộc tính và value là giá trị muốn thiết lập. Ví dụ sau thay đổi giá trị của thuộc tính href:


<!doctype html>

<html>

   <head>

      <title>Set Attrib</title>

   </head>

   <body>

      <a href="http://www.braingia.org" id="braingialink">Ngoc Minh's Web Site</a>
 
      <script type="text/javascript">

            var a1 = document.getElementById("braingialink");

            alert(a1.getAttribute("href"));

            a1.setAttribute("href","http://www.microsoft.com");

            alert(a1.getAttribute("href"));

       </script>

   </body>

</html>

Khi xem trên trình duyệt sẽ xuất hiện một hộp thông báo:

Nhấp OK, kết quả:

Tạo các phần tử

Thêm văn bản

Chúng ta có thể tạo hay thêm một phần tử đến đối tượng document theo các bước đơn giản sau:

Bước 1: dùng phương thức createElement() để tạo một tham chiếu đến phần tử mới, ví dụ:


var newelement = document.createElement("p");

Bước 2: Tạo phần tử mới với phương thức appendChild(), ví dụ:


document.body.appendChild(newelement);

Bước 3: thêm nội dung vào phần tử mới bằng cách dùng phương thức createTextNode(), ví dụ:


newelement.appendChild(document.createTextNode("Hello World"));

Ví dụ hoàn chỉnh về cách thêm phần tử mới p đến đối tượng document:


<!doctype html>

 <html>

    <head>

       <title>Create</title>

    </head>

    <body>

       <script type="text/javascript">

           var newelement = document.createElement("p");

           document.body.appendChild(newelement);

           newelement.appendChild(document.createTextNode("Hello World"));

       </script>

    </body>

</html>

Kết quả trên trình duyệt:

Thêm một phần tử và thiết lập một ID

Ở phần trên chúng ta đã biết cách thêm các phần tử, trong ví dụ dưới đây chúng ta sẽ kết hợp với phương thức setAttribute() để thêm thuộc tính đến phần tử:


<!doctype html>

<html>

  <head>

    <title>Create</title>

  </head>

  <body>

     <script type="text/javascript">

     var newelement = document.createElement("p");

     newelement.setAttribute("id","newelement");

     document.body.appendChild(newelement);

     newelement.appendChild(document.createTextNode("Hello World"));

     </script>

  </body>

</html>

Xoá các phần tử

Chúng ta có thể dùng phương thức removeChild() để xoá các phần tử. Giả sử chúng ta thêm 3 phần tử p như đoạn mã sau:


<!doctype html>

<html>

  <head>

      <title>Create</title>

  </head>

  <body>

     <script type="text/javascript">

        for (var i = 0; i < 3; i++) {

           var element = document.createElement("p");

           element.setAttribute("id","element" + i);

           document.body.appendChild(element);

           element.appendChild(document.createTextNode("Hello World, I'm Element " + i + "."));

       }

    </script>

  </body>

</html>

Kết quả trên trình duyệt:

Giả sử chúng ta muốn xoá Element 1, thêm đoạn mã sau:


var removeel = document.getElementById("element1");

document.body.removeChild(removeel);

Đoạn mã hoàn chỉnh:

<!doctype html>

<html>

   <head>

      <title>Del</title>

   </head>

   <body>

      <script type="text/javascript">

        for (var i = 0; i < 3; i++) {

           var element = document.createElement("p");

           element.setAttribute("id","element" + i);

           document.body.appendChild(element);

           element.appendChild(document.createTextNode("Hello World, I'm Element " + i + "."));

       }

       var removeel = document.getElementById("element1");

       document.body.removeChild(removeel);

    </script>

   </body>

</html>

Chạy lại với trình duyệt

< Cốt lõi JavaScript