Tạo Auto-generated Mục lục với HTML Slots

Mục lục có thể cải thiện đáng kể trải nghiệm người dùng của nhiều trang web, ví dụ như các trang tài liệu hoặc các bách khoa toàn thư trực tuyến như Wikipedia.Mục lục được thiết kế tốt cung cấp tổng quan về trang và giúp người dùng nhanh chóng điều hướng tới phần mà họ quan tâm. Theo truyền thống, bạn có thể tạo bảng nội dung trong HTML hoặc JavaScript, tuy nhiên các HTML slot được chuẩn hóa gần đây cung cấp một khoảng giữa giữa hai thành phần. HTML Slot là một tiêu chuẩn web cho phép bạn thêm các trình giữ chỗ vào một trang web và sau đó điền nó với nội dung động.

Khi sử dụng thẻ <slot>

Bạn có thể đặt các thẻ <slot> vào trong mục lục bên trong tệp tin HTML, do đó các slot có thể được điền vào các tiêu đề và phân nhóm có liên quan. Khi tiêu đề được thay đổi, slot được cập nhật tự động. Với kỹ thuật này, bạn cần tạo mã nguồn HTML của mục lục theo cách thủ công. JavaScript chỉ tự động tạo ra nội dung văn bản của bảng mục lục, dựa trên tiêu đề hoặc phân nhóm trên trang. Nếu bạn không muốn mục lục có mặt trong HTML, bạn cần phải tạo ra cả bố cục và nội dung bằng JavaScript.

1. Create the HTML

Mã nguồn HTML của TOC (mục lục) sẽ nằm trong thẻ <template>. Mã bên trong <template> không được hiển thị cho đến khi nó được thêm vào tài liệu bằng JavaScript. TOC của chúng ta sẽ có các trình giữ chỗ, được giữ trong các thẻ <slot>, cho tất cả các đề mục và phân nhóm được tìm thấy trong tài liệu. Thuộc tính name của mỗi <slot> sẽ có cùng giá trị với thuộc tính slot trong các tiêu đề và phân nhóm tương ứng trong tài liệu. Dưới đây, bạn có thể xem một mẫu HTML <article> với một số tiêu đề và phân nhóm.

ngay từ đầu là nơi chúng ta sẽ chèn TOC tự động.

<div id='toc'></div>
<article>
<p>Velociraptor (/vᵻˈlɒsᵻræptər/; meaning "swift seizer" in Latin) is a …</p>
 
<h2 slot='h-1'>Description</h2>
<p>Velociraptor was a mid-sized dromaeosaurid, with adults …</p>
 
  <h3 slot='sh-1-1'>Feathers</h3>
  <p>Fossils of dromaeosaurids more primitive than …</p >
 
<h2 slot='h-2'>History of discovery</h2>
<p>During an American Museum of Natural History expedition …</p>
 
<h2 slot='h-3'>Classification</h2>
<p>Velociraptor is a member of the group Eudromaeosauria, a derived sub-group of …</p>
 
<h2 slot='h-4'>Paleobiology</h2>
<p>The "Fighting Dinosaurs" specimen, found in 1971, preserves a …</p>
 
  <h3 slot='sh-4-1'>Scavenging behavior</h3>
  <p>In 2010, Hone and colleagues published a paper on …</p>
 
  <h3 slot='sh-4-2'>Metabolism</h3>
  <p>Velociraptor was warm-blooded to some degree, as it required a …</p>
 
  <h3 slot='sh-4-3'>Pathology</h3>
  <p>One Velociratoptor mongoliensis skull bears two parallel …</p>
</article>

Như bạn thấy, mỗi tiêu đề được cho một giá trị slot duy nhất.

Và đây là mã HTML của TOC, bên trong thẻ <template>.

<template>
<ul>
  <li>
    <slot name='h-1'></slot>
    <ul>
      <li><slot name='sh-1-1'></slot></li>
    </ul>
  </li>
  <li><slot name='h-2'></slot></li>
  <li><slot name='h-3'></slot></li>
  <li>
    <slot name='h-4'></slot>
    <ul>
      <li><slot name='sh-4-1'></slot></li>
      <li><slot name='sh-4-2'></slot></li>
      <li><slot name='sh-4-3'></slot></li>
    </ul>
  </li>
</ul>
<style>
  ul {
    list-style: none;
  }
/* … */
</style>
</template>

Trong hai đoạn mã ở trên, hãy chú ý đến các thuộc tính slotname trong các tiêu đề và thẻ slot

2. Number the headings

Trước khi tìm kiếm mã JavaScript để thêm TOC từ <template> vào tài liệu, hãy thêm số serial cho các tiêu đề, sử dụng các bộ đếm CSS.

templateContent = document.querySelector('template').content;
article = document.querySelector('article').cloneNode(true);
article.attachShadow({  mode: 'closed' }).appendChild(templateContent.cloneNode(true));
document.querySelector('#toc').appendChild(article);

Đoạn mã trên tạo ra một bản sao của <article> và gắn một DOM Tree vào nó. Chúng ta cũng thêm một bản sao của nội dung <template> vào cây DOM Shadow này. Sau đó, <article> nhân bản được chèn vào phần tử <div id = 'toc'>. Phần tử <article> cũng hiện diện trong TOC, tuy nhiên chỉ có các tiêu đề và phân nhóm của nó mới có thể thấy được vị trí bên trong TOC. Nếu chúng ta đặt lại bộ đếm CSS ở phần thân hoặc phần tử html thay vì bài viết, bộ đếm sẽ đếm danh sách các tiêu đề bên trong TOC.

4. Thêm các siêu liên kết

Nếu bạn muốn liên kết các tiêu đề TOC với các tiêu đề và phân nhóm tương ứng bằng cách thêm id vào các tiêu đề và anchoring văn bản TOC tương ứng, bạn sẽ phải loại bỏ các giá trị id lặp lại khỏi bài viết nhân bản.

<div id='toc'></div>
<article>
<p>Velociraptor (/vᵻˈlɒsᵻræptər/; meaning "swift seizer" in Latin) is a …</p>
 
<h2 id='h-1' slot='h-1'>Description</h2>
<p>Velociraptor was a mid-sized dromaeosaurid, with adults …</p>
 
<h3 id='sh-1-1' slot='sh-1-1'>Feathers</h3>
<p>Fossils of dromaeosaurids more primitive than …</p >
<!-- ... -->
</article>

Như bạn thấy ở trên, thuộc tính id được thêm vào mỗi tiêu đề và phân mục trong bài viết.

Và, các tiêu đề bên trong bảng nội dung được neo:

<template>
<ul>
<li>
    <a href='#h-1'><slot name='h-1'></slot></a>
    <ul>
      <a href='#sh-1-1'><li><slot name='sh-1-1'></slot></li></a>
    </ul>
</li>
<!-- ... -->
</ul>
</template>
In the extra line above, al

Trong dòng thêm ở trên, tất cả các thuộc tính id được xóa khỏi bài viết nhân bản trước khi gắn DOM Shadow vào nó.

templateContent = document.querySelector('template').content;
article = document.querySelector('article').cloneNode(true);
article.querySelectorAll('*[id]').forEach((ele)=>{ele.removeAttribute('id')})
article.attachShadow({  mode: 'closed' }).appendChild(templateContent.cloneNode(true));
document.querySelector('#toc').appendChild(article);