/Hàm after trong JQuery API

Hàm after trong JQuery API

Hàm after là một trong các hàm hỗ trợ sẵn (built-in fuctions) JQuery API của thư viện jQuery được sử dụng với mục đích chèn nội dung (được chỉ định bởi tham số) sau mỗi phần tử trong tập hợp các phần tử đã được chọn.

1. Cú pháp hàm after

1.1. Các cú pháp

Chèn nội dung sau mỗi phần tử trong tập hợp các phần tử đã chọn.

Cú pháp:

  • .after(content [, content ])
  • .after(function)
  • .after(function-html)

Tham số:

  • content: Một chuỗi HTML, phần tử DOM, node văn bản, một mảng các phần tử và node văn bản hoặc đối tượng jQuery để chèn sau mỗi phần tử trong tập hợp các phần tử đã chọn.
  • function: Một hàm trả về một chuỗi HTML, một hoặc nhiều phần tử DOM, node văn bản hoặc đối tượng jQuery để chèn sau mỗi phần tử trong tập hợp đã chọn. Hàm nhận tham số là vị trí index của phần tử trong tập hợp.
  • function-html: Một hàm trả về một chuỗi HTML, một hoặc nhiều phần tử DOM, node văn bản hoặc đối tượng jQuery để chèn sau mỗi phần tử trong tập hợp đã chọn. Hàm nhận tham số là vị trí index của phần tử trong tập hợp và giá trị HTML ban đầu của phần tử.

Kết quả trả về:

  • Không có giá trị trả về (undefined).

Phiên bản hỗ trợ:

  • Phiên bản 1.0: .after(content [, content ])
  • Phiên bản 1.4: .after(function)
  • Phiên bản 1.10/2.0: .after(function-html)

1.2. Một số chú ý

Các hàm after() và hàm insertAfter() thực hiện cùng một nhiệm vụ. Sự khác biệt chính nằm ở cú pháp, cụ thể là vị trí đặt nội dung và mục tiêu. Với hàm after(), nội dung được chèn dựa trên đối số của phương thức: $(target).after(contentToBeInserted).

Ngược lại, với hàm.insertAfter(), nội dung xuất hiện trước phương thức và được chèn sau mục tiêu, mục tiêu này lại được truyền làm đối số cho phương thức .insertAfter(): $(contentToBeInserted).insertAfter(target).

Hàm after trong JQuery API

Trước phiên bản jQuery 1.9, .after() sẽ cố gắng thêm hoặc thay đổi các nút trong tập hợp jQuery hiện tại nếu nút đầu tiên trong tập hợp không kết nối với tài liệu, và trong những trường hợp đó, nó sẽ trả về một tập hợp jQuery mới thay vì tập hợp ban đầu.

Phương thức này có thể đã trả về kết quả mới hoặc không, phụ thuộc vào số lượng hoặc tính kết nối của đối số!

Từ phiên bản jQuery 1.9, .after(), .before(), và .replaceWith() luôn trả về tập hợp ban đầu chưa được sửa đổi.

Cố gắng sử dụng các phương thức này trên một nút không có phần tử cha không có tác dụng – nghĩa là, tập hợp cũng như các nút mà nó chứa không thay đổi.

Theo thiết kế, bất kỳ constructor hoặc phương thức jQuery nào chấp nhận một chuỗi HTML – jQuery(), .append(), .after(), v.v. – đều có thể thực thi mã. Điều này có thể xảy ra thông qua chèn thẻ script hoặc sử dụng các thuộc tính HTML thực thi mã (ví dụ: <img onload=””>).

Không sử dụng các phương thức này để chèn chuỗi được lấy từ nguồn không đáng tin cậy như tham số truy vấn URL, cookie hoặc đầu vào biểu mẫu. Làm như vậy có thể giới thiệu lỗ hổng cross-site-scripting (XSS). Hãy loại bỏ hoặc tránh mọi đầu vào người dùng trước khi thêm nội dung vào tài liệu.

2. Một số ví dụ

2.1. Sử dụng hàm after(content [, content ])

Ví dụ dưới đây sử dụng thư viện jQuery phiên bản 1.3, trong đó sử dụng hàm after(content [, content ]) với HTML string, Element, Text, Array và jQuery như sau:

HTML Code:

<!DOCTYPE html>
<html>
<head>
  <title>Example: .after() with jQuery 1.3</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
  <script>
    $(document).ready(function() {
      // HTML string
      $('#target').after('<p>This is HTML content.</p>');

      // DOM element
      var newElement = document.createElement('p');
      newElement.textContent = 'This is a new element.';
      $('#target').after(newElement);

      // Text
      $('#target').after(document.createTextNode('This is some text.'));

      // Array
      var elementsArray = [document.createElement('p'), document.createElement('p')];
      $(elementsArray).text('These are elements in an array.');
      $('#target').after(elementsArray);

      // jQuery object
      var jQueryObject = $('<p>This is a jQuery object.</p>');
      $('#target').after(jQueryObject);
    });
  </script>
</head>
<body>
  <div id="target">This is a target element.</div>
</body>
</html>

Trong ví dụ này, hàm after() được để chèn nội dung bằng HTML string, Element, Text, Array và jQuery trong phiên bản jQuery 1.3.

2.2. Sử dụng hàm after( function )

Bắt đầu từ thư viện jQuery phiên bản 1.4, bạn có thể sử dụng hàm after(function) với một hàm callback để chèn nội dung động vào các phần tử.

Dưới đây là một ví dụ hoạt động trên jQuery 1.4.4:

<!DOCTYPE html>
<html>
<head>
  <title>jQuery .after() Function Example</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
  <script>
    $(document).ready(function() {
      $('button').click(function() {
        // Function to determine the content to be inserted after each element
        function determineContent(index) {
          // Returning different types of content based on the index
          if (index % 4 === 0) {
            return $("<div>").text("jQuery Object");
          } else if (index % 4 === 1) {
            return "<p>HTML String</p>";
          } else if (index % 4 === 2) {
            return document.createTextNode("Text Node");
          } else {
            return $("<span>").text("DOM Element");
          }
        }

        // Insert content after each element using the determineContent function
        $('p').after(function(index) {
          return determineContent(index);
        });
      });
    });
  </script>
</head>
<body>
  <button>Add Content</button>
  <p>Content 1</p>
  <p>Content 2</p>
  <p>Content 3</p>
  <p>Content 4</p>
</body>
</html>
=

Ở đây, hàm after(function) sẽ gọi hàm callback và chèn nội dung được xác định bởi determineContent(index) sau mỗi phần tử <p>. Các loại nội dung khác nhau (HTML string, DOM element, text node) được chèn dựa trên chỉ mục của phần tử.

2.3. Sử dụng hàm after(function-html)

Dưới đây là một ví dụ sử dụng hàm after(function-html) để chèn các loại nội dung khác nhau:

HTML Code:

<!DOCTYPE html>
<html>
<head>
  <title>jQuery .after() Function Example</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script>
    $(document).ready(function() {
      $('button').click(function() {
        // Function to determine the content to be inserted after each element
        function determineContent(index, oldHTML) {
          // Returning different types of content based on the index and oldHTML
          if (index % 4 === 0) {
            return $("<div>").text("jQuery Object "+ oldHTML);
          } else if (index % 4 === 1) {
            return "<p>HTML String " + oldHTML+ " </p>";
          } else if (index % 4 === 2) {
            return document.createTextNode("Text Node " + oldHTML);
          } else {
            return $("<span>").text("DOM Element. Previous HTML: " + oldHTML);
          }
        }

        // Insert content after each element using the determineContent function
        $('.content').after(function(index, oldHTML) {
          return determineContent(index, oldHTML);
        });
      });
    });
  </script>
</head>
<body>
  <button>Add Content</button>
  <p class="content">Content 1</p>
  <p class="content">Content 2</p>
  <p class="content">Content 3</p>
  <p class="content">Content 4</p>
</body>
</html>

Trong ví dụ này, hàm determineContent sẽ nhận thêm tham số oldHTML để thể hiện nội dung trước đó của phần tử. Hàm này sẽ chèn các loại nội dung khác nhau dựa trên chỉ mục và nội dung trước đó.

2.4. Hàm after và insertAfter

Hai hàm after() và insertAfter() thực hiện cùng một nhiệm vụ là chèn nội dung vào sau một phần tử. Sự khác biệt chính giữa chúng nằm ở cú pháp và vị trí của nội dung và đối tượng mục tiêu.

Hãy xem ví dụ:

<!DOCTYPE html>
<html>
<head>
  <title>jQuery .after() vs .insertAfter() Example</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script>
    $(document).ready(function() {
      $('#afterButton').click(function() {
        // Inserting content using .after()
        $('#target').after("<p>Content inserted using .after()</p>");
      });

      $('#insertAfterButton').click(function() {
        // Inserting content using .insertAfter()
        $("<p>Content inserted using .insertAfter()</p>").insertAfter('#target');
      });
    });
  </script>
</head>
<body>
  <button id="afterButton">Insert Content using .after()</button>
  <button id="insertAfterButton">Insert Content using .insertAfter()</button>
  
  <div id="target">Target Element</div>
</body>
</html>

Trong ví dụ này, có hai nút: “Insert Content using .after()” và “Insert Content using .insertAfter()”. Khi bạn nhấp vào mỗi nút, một đoạn văn bản mới sẽ được chèn sau phần tử có id là “target”. Cả hai phương thức đều có hiệu quả tương tự.

Giống nhau: Cả hai đều chèn nội dung vào sau một phần tử.

Khác nhau:

  • Hàm .after() chèn nội dung từ đối số của phương thức: $(target).after(contentToBeInserted).
  • Hàm .insertAfter() chèn nội dung trước phương thức và chuyển đối tượng mục tiêu làm đối số: $(contentToBeInserted).insertAfter(target).

2.5. Sự khác biệt kết quả trả về after() trước và sau bản 1.9

Trước jQuery 1.9, các hàm .after(), .before(), và .replaceWith() luôn trả về tập hợp ban đầu chưa được sửa đổi. Ví dụ

HTML Code:

<!DOCTYPE html>
<html>
<head>
  <title>jQuery .after() Before 1.9 Example</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
  <script>
    $(document).ready(function() {
      // Create a detached DOM element
      var detached = $("<p>This is a detached paragraph.</p>");

      // Try to use .after() on the detached element
      var result = detached.after("<p>This is added after.</p>");

      // Show the modified set
      alert(result.length);

      // Show the original detached element
      alert(detached.length);
    });
  </script>
</head>
<body>
</body>
</html>

Trong ví dụ trên, tập hợp ban đầu detached và tập hợp results sau after đều trả về số phần tử đã sửa đổi với số phần tử là 2

Tuy nhiên, trong phiên bản jQuery 1.9 trở lên, .after(), .before(), và .replaceWith() luôn trả về tập hợp ban đầu chưa được sửa đổi.

Nếu vẫn ví dụ trên nhưng thay đổi phiên bản jQuery 1.9 trở nên thì số phần tử nhận được là 1 là số phần tử ban đầu thay cho 2.

2.6. Hàm after có thể thực thi mã

Theo thiết kế, bất kỳ constructor hoặc phương thức jQuery nào chấp nhận một chuỗi HTML – jQuery(), .append(), .after(), v.v. – đều có thể thực thi mã. Điều này có thể xảy ra thông qua chèn thẻ script hoặc sử dụng các thuộc tính HTML thực thi mã (ví dụ: <img onload=””>).

Đặc điểm này cảnh báo rằng khi chúng ta sử dụng các phương thức jQuery như .after() để chèn nội dung từ chuỗi HTML, cẩn thận cần được thực hiện để tránh lỗ hổng bảo mật XSS. Đây là một ví dụ minh họa việc lợi dụng lỗ hổng này:

<!DOCTYPE html>
<html>
<head>
  <title>jQuery HTML Injection Example</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script>
    $(document).ready(function() {
      // Assume this HTML string comes from an untrusted source
      var maliciousHTML = '<img src="invalid-image" onerror="alert(\'XSS Attack!\');">';

      // Insert the HTML string into the document using .after()
      $('p').after(maliciousHTML);
    });
  </script>
</head>
<body>
  <p>This is a paragraph.</p>
</body>
</html>

Trong ví dụ này, chúng ta chèn một chuỗi HTML (maliciousHTML) chứa một thẻ <img> với sự kiện onerror để gọi hàm alert. Nếu chúng ta không kiểm soát và làm sạch chuỗi HTML này, nó có thể chứa mã độc hoặc mã tấn công khác. Khi chúng ta chèn chuỗi này vào tài liệu bằng .after(), mã độc sẽ được thực thi khi <img> tải thất bại (onerror được gọi).

Để tránh lỗ hổng bảo mật XSS, chúng ta cần luôn kiểm soát và làm sạch chuỗi HTML trước khi chèn nó vào tài liệu.