我<h1>通过<h6>标签有标题.有没有一种方法可以使用JavaScript来生成用作锚标签的内容的目录?
我希望输出类似于:
<ol>
<li>Header 1</li>
<li>Header 1</li>
<li>Header 2</li>
<li>Header 3</li>
</ol>
Run Code Online (Sandbox Code Playgroud)
我目前没有使用JavaScript框架,但我不明白为什么我不能使用它.
我也在寻找已经完成的事情,因为我猜这是一个常见的问题,但如果没有,那么我自己的起点就会很好.
Ate*_*ral 35
我无法抗拒快速实施.
在页面的任何位置添加以下脚本:
window.onload = function () {
var toc = "";
var level = 0;
document.getElementById("contents").innerHTML =
document.getElementById("contents").innerHTML.replace(
/<h([\d])>([^<]+)<\/h([\d])>/gi,
function (str, openLevel, titleText, closeLevel) {
if (openLevel != closeLevel) {
return str;
}
if (openLevel > level) {
toc += (new Array(openLevel - level + 1)).join("<ul>");
} else if (openLevel < level) {
toc += (new Array(level - openLevel + 1)).join("</ul>");
}
level = parseInt(openLevel);
var anchor = titleText.replace(/ /g, "_");
toc += "<li><a href=\"#" + anchor + "\">" + titleText
+ "</a></li>";
return "<h" + openLevel + "><a name=\"" + anchor + "\">"
+ titleText + "</a></h" + closeLevel + ">";
}
);
if (level) {
toc += (new Array(level + 1)).join("</ul>");
}
document.getElementById("toc").innerHTML += toc;
};
Run Code Online (Sandbox Code Playgroud)
您的页面应该是这样的结构:
<body>
<div id="toc">
<h3>Table of Contents</h3>
</div>
<hr/>
<div id="contents">
<h1>Fruits</h1>
<h2>Red Fruits</h2>
<h3>Apple</h3>
<h3>Raspberry</h3>
<h2>Orange Fruits</h2>
<h3>Orange</h3>
<h3>Tangerine</h3>
<h1>Vegetables</h1>
<h2>Vegetables Which Are Actually Fruits</h2>
<h3>Tomato</h3>
<h3>Eggplant</h3>
</div>
</body>
Run Code Online (Sandbox Code Playgroud)
您可以在http://magnetiq.com/exports/toc.htm上看到它的运行情况(在IE,FF,Safari,Opera中工作)
我已经修改了 AtesGoral 接受的答案中的函数,以输出正确的嵌套列表和有效的 HTML5。
只需将下面的代码添加到您的脚本中并TableOfContents(container, output);在加载时调用,其中容器是内容元素的类或 id,输出是 TOC 元素的类或 id。默认值分别是“#contents”和“#toc”。
请参阅http://codepen.io/aufmkolk/pen/RWKLzr了解工作演示。
function TableOfContents(container, output) {
var toc = "";
var level = 0;
var container = document.querySelector(container) || document.querySelector('#contents');
var output = output || '#toc';
container.innerHTML =
container.innerHTML.replace(
/<h([\d])>([^<]+)<\/h([\d])>/gi,
function (str, openLevel, titleText, closeLevel) {
if (openLevel != closeLevel) {
return str;
}
if (openLevel > level) {
toc += (new Array(openLevel - level + 1)).join('<ul>');
} else if (openLevel < level) {
toc += (new Array(level - openLevel + 1)).join('</li></ul>');
} else {
toc += (new Array(level+ 1)).join('</li>');
}
level = parseInt(openLevel);
var anchor = titleText.replace(/ /g, "_");
toc += '<li><a href="#' + anchor + '">' + titleText
+ '</a>';
return '<h' + openLevel + '><a href="#' + anchor + '" id="' + anchor + '">'
+ titleText + '</a></h' + closeLevel + '>';
}
);
if (level) {
toc += (new Array(level + 1)).join('</ul>');
}
document.querySelector(output).innerHTML += toc;
};
Run Code Online (Sandbox Code Playgroud)
这是一个很好的脚本来做到这一点:
https://github.com/matthewkastor/html-table-of-contents/wiki
要使用它:
添加这个标签:
<script src="./node_modules/html-table-of-contents/src/html-table-of-contents.js" type="text/javascript">
Run Code Online (Sandbox Code Playgroud)调用该函数,例如在您的 body 的 onload 属性中:
<body onload="htmlTableOfContents();">
Run Code Online (Sandbox Code Playgroud)以下是生成方法的定义:
/**
* Generates a table of contents for your document based on the headings
* present. Anchors are injected into the document and the
* entries in the table of contents are linked to them. The table of
* contents will be generated inside of the first element with the id `toc`.
* @param {HTMLDOMDocument} documentRef Optional A reference to the document
* object. Defaults to `document`.
* @author Matthew Christopher Kastor-Inare III
* @version 20130726
* @example
* // call this after the page has loaded
* htmlTableOfContents();
*/
function htmlTableOfContents (documentRef) {
var documentRef = documentRef || document;
var toc = documentRef.getElementById('toc');
var headings = [].slice.call(documentRef.body.querySelectorAll('h1, h2, h3, h4, h5, h6'));
headings.forEach(function (heading, index) {
var anchor = documentRef.createElement('a');
anchor.setAttribute('name', 'toc' + index);
anchor.setAttribute('id', 'toc' + index);
var link = documentRef.createElement('a');
link.setAttribute('href', '#toc' + index);
link.textContent = heading.textContent;
var div = documentRef.createElement('div');
div.setAttribute('class', heading.tagName.toLowerCase());
div.appendChild(link);
toc.appendChild(div);
heading.parentNode.insertBefore(anchor, heading);
});
}
try {
module.exports = htmlTableOfContents;
} catch (e) {
// module.exports is not defined
}
Run Code Online (Sandbox Code Playgroud)
我真的很喜欢d13 的答案,但想稍微改进它以使用 html5 符号并保留标头的现有 id:
document.addEventListener('DOMContentLoaded', function() {
htmlTableOfContents();
} );
function htmlTableOfContents( documentRef ) {
var documentRef = documentRef || document;
var toc = documentRef.getElementById("toc");
// Use headings inside <article> only:
// var headings = [].slice.call(documentRef.body.querySelectorAll('article h1, article h2, article h3, article h4, article h5, article h6'));
var headings = [].slice.call(documentRef.body.querySelectorAll('h1, h2, h3, h4, h5, h6'));
headings.forEach(function (heading, index) {
var ref = "toc" + index;
if ( heading.hasAttribute( "id" ) )
ref = heading.getAttribute( "id" );
else
heading.setAttribute( "id", ref );
var link = documentRef.createElement( "a" );
link.setAttribute( "href", "#"+ ref );
link.textContent = heading.textContent;
var div = documentRef.createElement( "div" );
div.setAttribute( "class", heading.tagName.toLowerCase() );
div.appendChild( link );
toc.appendChild( div );
});
}
try {
module.exports = htmlTableOfContents;
} catch (e) {
// module.exports is not defined
}
Run Code Online (Sandbox Code Playgroud)
您可以通过将脚本包含在标头中来使用它。
很棒的是,您可以在目录中使用样式表:
<style>
#toc div.h1 { margin-left: 0 }
#toc div.h2 { margin-left: 1em }
#toc div.h3 { margin-left: 2em }
#toc div.h4 { margin-left: 3em }
</style>
Run Code Online (Sandbox Code Playgroud)
在我的个人脚本中,我使用了略有不同的选择器:
var headings = [].slice.call(documentRef.body.querySelectorAll("article h1, article h2, article h3, article h4, article h5, h6"));
Run Code Online (Sandbox Code Playgroud)
主页保留在内部<article></article>,脚本将仅搜索主文章内的标题。我可以在目录中使用标题,例如<nav id="toc"><h3>Table of contents</h3></nav>在页脚/页眉中使用 或 在页脚/页眉中使用,而无需将其显示在目录中。
在下面的评论中,Gabriel Hautclocq对文章代码进行了优化。他还指出,这并不是严格意义上的列表,而是类似列表的 div 结构,它更简单并且生成的代码更短。
这是我为工作而想出的目录的普通 JavaScript 版本。
它查找指定内容容器中的所有标题并为它们创建 ID,然后生成目录链接。我让它添加样式类并使用嵌套列表来创建层次结构。
window.addEventListener('DOMContentLoaded', function (event) { // Let the DOM content load before running the script.
//Get all headings only from the actual contents.
var contentContainer = document.getElementById('content'); // Add this div to the html
var headings = contentContainer.querySelectorAll('h1,h2,h3,h4'); // You can do as many or as few headings as you need.
var tocContainer = document.getElementById('toc'); // Add this div to the HTML
// create ul element and set the attributes.
var ul = document.createElement('ul');
ul.setAttribute('id', 'tocList');
ul.setAttribute('class', 'sidenav')
// Loop through the headings NodeList
for (i = 0; i <= headings.length - 1; i++) {
var id = headings[i].innerHTML.toLowerCase().replace(/ /g, "-"); // Set the ID to the header text, all lower case with hyphens instead of spaces.
var level = headings[i].localName.replace("h", ""); // Getting the header a level for hierarchy
var title = headings[i].innerHTML; // Set the title to the text of the header
headings[i].setAttribute("id", id) // Set header ID to its text in lower case text with hyphens instead of spaces.
var li = document.createElement('li'); // create li element.
li.setAttribute('class', 'sidenav__item') // Assign a class to the li
var a = document.createElement('a'); // Create a link
a.setAttribute("href", "#" + id) // Set the href to the heading ID
a.innerHTML = title; // Set the link text to the heading text
// Create the hierarchy
if(level == 1) {
li.appendChild(a); // Append the link to the list item
ul.appendChild(li); // append li to ul.
} else if (level == 2) {
child = document.createElement('ul'); // Create a sub-list
child.setAttribute('class', 'sidenav__sublist')
li.appendChild(a);
child.appendChild(li);
ul.appendChild(child);
} else if (level == 3) {
grandchild = document.createElement('ul');
grandchild.setAttribute('class', 'sidenav__sublist')
li.appendChild(a);
grandchild.appendChild(li);
child.appendChild(grandchild);
} else if (level == 4) {
great_grandchild = document.createElement('ul');
great_grandchild.setAttribute('class', 'sidenav__sublist');
li.append(a);
great_grandchild.appendChild(li);
grandchild.appendChild(great_grandchild);
}
}
toc.appendChild(ul); // add list to the container
// Add a class to the first list item to allow for toggling active state.
var links = tocContainer.getElementsByClassName("sidenav__item");
links[0].classList.add('current');
// Loop through the links and add the active class to the current/clicked link
for (var i = 0; i < links.length; i++) {
links[i].addEventListener("click", function() {
var current = document.getElementsByClassName("current");
current[0].className = current[0].className.replace(" current", "");
this.className += " current";
});
}
});
Run Code Online (Sandbox Code Playgroud)
我在CodePen上有一个演示。