JavaScript and DOM Interaction

TRƯỜNG ĐẠI HỌC CẦN THƠ TRƯỜNG CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG

  • Nhập môn Lập trình Đa phương tiện
  • Nhóm tác giả: Khoa Truyền thông Đa Phương tiện
  • BÀI GIẢNG CT089

JavaScript (JS)

JavaScript DOM Overview

  • DOM: Document Object Model
  • Các lớp thuộc tính và phương thức để tương tác với DOM.

Document Object Model (DOM)

Khái niệm

  • Mỗi phần tử (element) trong trang HTML được xem là một object
  • Cấu trúc DOM tạo thành một cây phân cấp, có nút gốc là window
  • Một số đối tượng trong DOM:
    • Element nodes
    • Text nodes
    • Document nodes
    • Comment nodes
    • Tag nodes

Ví dụ về cấu trúc DOM

  • Ví dụ cấu trúc DOM của trang HTML:
   <html>
       <head>
           <title>Sample Document</title>
       </head>
       <body>
           <h1>An HTML Document</h1>
           <p>This is a <i>simple</i> document</p>
       </body>
   </html>

Tính năng của JS trong DOM

  • Cung cấp các phương thức để thao tác trên DOM:
    • Duyệt DOM
    • Thay đổi thuộc tính, giá trị, định dạng của các element
    • Tạo mới phần tử
    • Chèn thêm phần tử vào các node trên trang HTML
    • Loại bỏ phần tử từ trang HTML
    • Tìm kiếm các phần tử với nhiều tiêu chí khác nhau

Các thuộc tính truy xuất DOM

PropertyDescription
document.baseURITrả về URL của trang HTML
document.bodyTrả về phần tử <body>
document.cookieTrả về cookie
document.doctypeTrả về phần tử doctype
document.documentElementTrả về phần tử <html> của trang
document.domainTrả về tên miền (example: yoursite.com)
document.formsTrả về tất cả phần tử form
document.headTrả về phần tử <head>
document.imagesTrả về tất cả phần tử <img>
document.inputEncodingTrả về mã hóa của trang
document.linksTrả về tất cả phần tử <area><a> có thuộc tính href
document.readyStateTrả về trạng thái loading của trang
document.scriptsTrả về tất cả phần tử <script>
document.titleTrả về phần tử <title>

Chọn phần tử DOM

Cách chọn phần tử

  1. document.getElementById(“e_id”)
    • Chọn phần tử có thuộc tính id=“e_id”
  2. document.getElementsByName(“str”)
    • Chọn tất cả phần tử có thuộc tính name=“str”
  3. document.getElementsByTagName(“tag”)
    • Chọn tất cả phần tử theo loại (VD: <input>, <form>, <span> …)
  4. document.getElementsByClassName(“cls”)
    • Chọn phần tử với thuộc tính class=“cls”
  5. document.querySelectorAll(CSS_selectors)
    • Chọn các phần tử khớp với bộ chọn CSS

Lưu ý

  • Các phương thức từ 2 đến 5 trả về danh sách các node thỏa mãn điều kiện.

Ví dụ:

  • Chọn và thay đổi thuộc tính của phần tử.
   <html>
       <head>
           <title>DOM</title>
           <script>
               function checkall() {
                   var x = document.getElementsByName("course");
                   for (let i = 0; i < x.length; i++) {
                       if (x[i].type == "checkbox") {
                           x[i].checked = true;
                       }
                   }
               }
           </script>
       </head>
       <body>
           JavaScript <input name="course" type="checkbox" value="js">
           Python <input name="course" type="checkbox" value="py">
           C++ <input name="course" type="checkbox" value="cpp">
           <br />
           <button onclick="checkall()">Select all</button>
       </body>
   </html>

Duyệt phần tử DOM

Các thuộc tính và phương thức

  • node.childNodes: Trả về danh sách các node con, bao gồm text node và element node.
  • node.children: Trả về danh sách chỉ các element nodes con.
  • node.firstChild: Trả về node con đầu tiên, trả về null nếu không có.
  • node.firstElementChild: Trả về element node con đầu tiên.
  • node.lastChild: Trả về node con cuối cùng.
  • node.lastElementChild: Trả về element node cuối cùng.
  • node.parentNode: Trả về node cha.
  • node.parentElement: Trả về element node cha.
  • node.closest(ancestor): Tìm phần tử tổ tiên.
  • node.nextSibling: Trả về node anh em bên phải.
  • node.nextElementSibling: Trả về element node bên phải.
  • node.previousSibling: Trả về node anh em bên trái.
  • node.previousElementSibling: Trả về element node bên trái.

Ví dụ:

  • Lấy tất cả element nodes con từ parent node.
   <div id="main">
       <p>This is an element node</p>
       This is a text node
       <h3>This is heading element</h3>
   </div>
   <script>
       var root = document.getElementById("main");
       var elements = root.children;
       for (let i = 0; i < elements.length; i++) {
           console.log(elements[i].textContent);
       }
   </script>

Ví dụ:

  • Lấy tất cả nodes huyền từ parent node.
   <div id="main">
       <p>This is an element node</p>
       This is a text node
       <h3>This is heading element</h3>
   </div>
   <script>
       var root = document.getElementById("main");
       var elements = root.childNodes;
       for (let i = 0; i < elements.length; i++) {
           console.log(elements[i].textContent);
       }
   </script>

Các phương thức và thuộc tính

Cách sử dụng

  • document.write(data): Ghi giá trị trực tiếp lên trang HTML.
  • node.getAttribute(attrib): Nhận giá trị của thuộc tính attrib.
  • node.setAttribute(attrib, val): Gán giá trị val cho thuộc tính attrib.
  • node.style.property: Nhận/ thay đổi giá trị định dạng của node.

Nội dung node

  • node.innerText: Trả về nội dung của node mà không bao gồm mã HTML.
  • node.textContent: Tương tự innerText, nhưng bao gồm cả khoảng trắng và nội dung ẩn.
  • node.innerHTML: Trả về toàn bộ mã HTML trong node.

Ví dụ: Sự khác biệt

  • ```html

This element has extra spacing and contains a span element.

var x = document.getElementById("demo");
alert(x.innerText); // "This element has extra spacing and contains a span element."
alert(x.textContent); // " This element has extra spacing and contains a span element."
alert(x.innerHTML); // " This element has extra spacing and contains a span element."

---

# Thêm, sửa, xóa node
## Tạo document fragment
- `document.createDocumentFragment()`: Tạo tài liệu rỗng để thêm các node con vào trước khi chèn vào trang HTML.  
### Ví dụ:  
- Chèn phần tử `<li>` vào `<ul>`.

html

    ## Tạo mới các phần tử  
    - `node.createElement(name)`: Tạo mới một element (VD: `span`, `div`, `h1`, `table`, `td`).
    - `node.createTextNode(string)`: Tạo mới một text node.
    - `document.createAttribute(name)`: Tạo mới attribute cho element.
    - `node.setAttributeNode(attrOjb)`: Gán attribute cho node với `attrObj` tạo ra bởi `createAttribute()`.  
    - `node.cloneNode(bool)`: Nhân bản node (true: nhân bản và tất cả node con, false: chỉ nhân bản node). 
    
    ### Ví dụ: Tạo liên kết và chèn vào tài liệu  
    - ```html
       <body>
           <div id="main"></div>
           <script>
               var main = document.getElementById("main");
               var a = document.createElement("a");
               var href = document.createAttribute("href");
               href.value = "http://www.ctu.edu.vn";
               a.setAttributeNode(href);
               a.innerText = "Can Tho University Website";
               a.style.textDecoration = "none";
               a.style.color = "blue";
               main.appendChild(a);
           </script>
       </body>
    

    JavaScript Events

    Các loại sự kiện

    • Mouse events: Liên quan đến tương tác chuột.
    • Keyboard events: Liên quan đến nhập liệu trên bàn phím.
    • Event handler: Mã xử lý sự kiện.
    • Form Validation: Kiểm tra và xác thực thông tin biểu mẫu.

    Tương tác với người dùng

    • JavaScript sử dụng sự kiện để tương tác với người dùng.
    • Ví dụ: nhấn chuột, gõ phím, thay đổi kích thước màn hình, v.v.
    • Khi sự kiện phát sinh, mã lệnh đã định nghĩa trước sẽ được thực thi (event handler).
    • Các trình duyệt có cách phản ứng khác nhau với một số sự kiện.

    Dòng sự kiện (Event Flow)

    • Khi có sự kiện, sự kiện sẽ lan truyền từ đối tượng này sang đối tượng khác.
    • Có hai dòng sự kiện: capturing (từ trên xuống dưới) và bubbling (từ dưới lên trên).

    Ví dụ:

    • Khi người dùng nhấn chuột lên thẻ div, sự kiện click sẽ lan truyền:
      • Capturing:
      1. đối tượng document
      2. phần tử html
      3. phần tử body
      4. phần tử div
      • Bubbling:
      1. phần tử div
      2. phần tử body
      3. phần tử html
      4. đối tượng document

    Các loại sự kiện

    Các loại sự kiện chính

    • UI Events: Liên quan đến giao diện (VD: load, resize, scroll, abort, error, select).
    • Focus Events: Xảy ra khi các control nhận được hoặc mất tiêu điểm.
    • Mouse & Wheel Events: Liên quan đến các nút nhấn và cuộn chuột.
    • Keyboard Events: Sự kiện xảy ra khi nhấn phím.
    • Mutation Events: Xảy ra khi một node được chèn vào hoặc xóa bỏ khỏi DOM Tree.
    • Device Events: Xảy ra khi thiết bị cầm tay di chuyển, xoay hướng.
    • Touch Events: Khi người dùng chạm vào màn hình cảm ứng.

    UI Events chi tiết

    • load:
      • Xảy ra trên window khi nội dung trang đã load hoàn toàn.
      • Xảy ra trên frameset khi tất cả các frame đã tải xong.
      • Xảy ra trên hình ảnh khi nội dung đã tải hoàn toàn.
      • Xảy ra trên object khi đã được load hoàn toàn.
    • unload: Xảy ra trên đối tượng window khi người dùng đóng cửa sổ.
    • abort: Xảy ra trên object khi người dùng bỏ qua quá trình tải.
    • error: Xảy ra khi có lỗi JS trong window hay không thể load hình ảnh, object hay frame.
    • resize: Xảy ra trên window khi thay đổi kích thước.
    • scroll: Xảy ra trên các đối tượng có scrollbar khi người dùng cuộn màn hình.

    Focus Events

    • blur: Xảy ra trên phần tử mất focus.
    • focusout: Xảy ra trên phần tử và tất cả con bên trong khi mất focus (bubbling).
    • focus: Xảy ra khi phần tử nhận được tiêu điểm.
    • focusin: Xảy ra trên phần tử và tất cả con bên trong khi nhận được tiêu điểm.

    Mouse Events

    • click: Khi nhấn chuột trái và thả ra.
    • dblclick: Khi nhấn chuột trái hai lần liên tiếp.
    • mousedown: Khi nhấn chuột trái.
    • mouseup: Khi nhả chuột trái.
    • mouseenter: Khi rê chuột vào phần tử.
    • mouseover: Khi rê chuột vào phần tử và các phần tử con.
    • mouseleave: Khi con trỏ rời khỏi phần tử.
    • mouseout: Khi con trỏ rời khỏi phần tử và các con bên trong.
    • mousemove: Khi con trỏ rê trên phần tử và các phần tử bên trong.

    Keyboard Events

    • keydown: Khi nhấn phím, sự kiện lặp lại nếu giữ phím.
    • keypress: Khi nhấn phím không báo cáo với phím đặc biệt.
    • keyup: Khi nhả phím.

    Event Handlers

    Bắt sự kiện

    • Có hai cách để bắt sự kiện:

      1. Sử dụng thuộc tính của phần tử
      2. Sử dụng phương thức addEventListener()
    • **Cú pháp: **

      • Sử dụng thuộc tính:
       <button onclick="alert('Hi!')">Click me</button>
      
      • Sử dụng addEventListener():
       var btn = document.getElementById('test');
       btn.addEventListener('click', function() { alert('Hi!'); });
      

    Event Object

    Thông tin sự kiện

    • Khi sự kiện xảy ra, JS sẽ truyền một object vào trong callback function.
    • Đặc tính của event object:
      • key: Phím được nhấn trên keyboard event.
      • keyCode: Mã phím được nhấn.
      • target: Đối tượng đang bắt sự kiện.
      • currentTarget: Đối tượng lắng nghe sự kiện.

    Ví dụ: Nhấn phím

    • ```html

    Key:

    Code:

    ### Ví dụ: Đổi màu nền ô textbox khi có sự kiện focus  
    - ```html
       <form id="regForm" action="#" method="POST">
           <label for="fName">First name: </label>
           <input type="text" name="fName" id="fName" />
           <br/>
           <label for="lName">Last name: </label>
           <input type="text" name="lName" id="lName" />
           <br/>
           <button type="submit">Submit</button>
       </form>
       <script>
           var form = document.getElementById('regForm');
           form.addEventListener('focusin' , function(e) {
               if (e.target.tagName == 'INPUT') {
                   e.target.style.backgroundColor = 'yellow';
               }
           });
           // loại bỏ màu nền khi mất focus
           form.addEventListener('focusout' , function(e) {
               if (e.target.tagName == 'INPUT') {
                   e.target.style.backgroundColor = null;
               }
           });
       </script>
    

    Form Validation

    Kiểm tra ràng buộc form

    • Dữ liệu trước khi lưu trữ cần được kiểm tra các điều kiện như kiểu dữ liệu, miền giá trị, yêu cầu bắt buộc.
    • Các điều kiện kiểm tra ràng buộc phải dựa trên thuộc tính của dữ liệu.
    • Kiểm tra ràng buộc thường thực hiện ở cả phía client và server.
    • Nếu dữ liệu không thỏa mãn, quá trình submit sẽ bị hủy và thông báo lỗi sẽ hiển thị.

    Required Fields

    • Tối thiểu một số trường dữ liệu không được phép trống trong CSDL.
    • Trên form, cần các phần tử bắt buộc nhập (ô textbox, textarea) hoặc các lựa chọn bắt buộc (checkbox, radio, select).
    • Một ví dụ kiểm tra ô nhập không được rỗng:
       <form action="register.php" onsubmit="return formValidate()" name="regForm" method="post">
           <label for="fname">First name: </label>
           <input type="text" name="fname" />
           <label for="lname">Last name: </label>
           <input type="text" name="lname" />
           <button type="submit">Submit</button>
       </form>
       <script>
           function formValidate() {
               var frm = document.forms['regForm'];
               if (frm.fname.value.length == 0) {
                   alert("Please enter First name.");
                   frm.fname.focus();
                   return false;
               }
               if (frm.lname.value.length == 0) {
                   alert("Please enter Last name.");
                   frm.lname.focus();
                   return false;
               }
               return true;
           }
       </script>
    

    Kiểm tra ràng buộc kiểu

    • Chỉ cho phép nhập số vào ô textbox.
       <form name="frm" action="" method="post">
           <label for="age">Age: </label>
           <input type="text" name="age" onkeypress="return isNumber(event)" />
           <button type="button" onclick="formValidate()">Submit</button>
       </form>
       <script>
           function formValidate() {
               var frm = document.forms['frm'];
               var age = parseInt(frm.age.value);
               if (age == NaN || age < 10 || age > 50) {
                   alert('Only 10 to 50 allowed.');
                   return false;
               }
               if (frm.age.value.length == 0) {
                   alert("Please enter your age.");
                   return false;
               }
               alert("That's OK.");
               frm.submit();
           }
           function isNumber(event) {
               var key = event.which || event.keyCode;
               if (key < 48 || key > 57) {
                   return false;
               }
               return true;
           }
       </script>
    

    Pattern Matching in Validation

    Diễn giải

    • Pattern matching là cách kiểm tra dữ liệu nhập có khớp với mẫu đã cho.
    • Các pattern là biểu thức chính quy (regular expressions) cho phép kiểm tra dữ liệu một cách đơn giản.
      • Ví dụ:
      • /(a|b)/: Kiểm tra dữ liệu có chứa a hoặc b.
      • /[a-zA-Z]/: Kiểm tra dữ liệu có chứa ký tự HOA hoặc thường.
      • /[0-9]/: Kiểm tra dữ liệu có chứa chữ số.
      • /[^a-z]/: Kiểm tra dữ liệu KHÔNG chứa ký tự thường.

    Ví dụ

    • Một số cách xác thực đơn giản với regex về địa chỉ email, mật khẩu:
      • Kiểm tra địa chỉ email:
       var emailReg = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
    
    • Kiểm tra độ dài mật khẩu ít nhất 8 ký tự:
       var passReg = /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$/g;