我想要一些我自己使用的东西,所以我不在乎它是否适用于所有浏览器。
我的方法是在包含详细信息元素的页面每个部分的每个标题中创建展开/关闭按钮。作为内联块的按钮位于每个部分标题的末尾,无需我手动添加它们。
代码遍历页面详细信息元素以找到最接近的父级,即部分、旁白、文章、主要或 div。然后使用这些父分组元素的唯一数组将按钮添加到它们各自的标题。这些标题是否为 h1 - h6 无关紧要,无论每个部分中的第一个标题是什么,都会使用“展开”按钮修改标题。
按钮本身会更新以在“展开”时显示“关闭”,反之亦然,因此其行为类似于切换。
因为我希望能够搜索页面上的内容,所以我还在主元素的第一个标题之后添加了一个“全部展开”按钮。这说明您需要“全部展开”才能在页面中搜索。
此“全部展开”会更新每个部分中的子“展开”按钮以显示“关闭”。它还会切换到“全部关闭”。
在我看来,只有当您处理使用语义元素并且页面上有大量内容的结构化内容时,才需要这种方法。
details 元素的一个失败之处在于它确实隐藏了页面搜索中的内容,这是我为解决可能被搜索的内容所做的最大努力,例如您可能想要隐藏代码 sn 的技术说明-ps 和设置软件的冗长说明,但仍想搜索给定的关键字。
document.addEventListener("DOMContentLoaded", function (t) {
var groups = ["section", "aside", "article", "main", "div"], headings = ["h1", "h2", "h3", "h4", "h5", "h6"],
parents = [],
details = document.querySelectorAll("details");
for (var detail of details) for (var group of groups) {
var parent = detail.closest(group);
if (parent) {
if (!parents.includes(parent)) for (var heading in parents.push(parent), headings) {
var location = parent.getElementsByTagName(headings[heading]);
if (location.length) {
var button = document.createElement("button");
button.classList.add("details-helper"),
button.setAttribute("type", "button"),
button.textContent = "Expand",
button.style.display = "inline-block",
location[0].appendChild(button),
button.addEventListener("click", expandGroup(parent));
}
}
break;
}
}
if (parents.length) {
var nav = document.createElement("nav");
nav.classList.add("text-search");
var button = document.createElement("button");
button.classList.add("search-helper"),
button.setAttribute("type", "button"),
button.textContent = "Expand All",
button.style.display = "inline-block",
nav.appendChild(button),
button.addEventListener("click", expandAll());
var p = document.createElement("p");
p.style.display = "inline-block";
var em = document.createElement("em");
em.textContent = "Press before searching this page with CTRL+F";
p.appendChild(em);
nav.appendChild(p);
for (heading of headings) {
if (location = document.querySelector("main " + heading)) {
location.parentNode.insertBefore(nav, location.nextSibling);
break;
}
}
}
function expandGroup(group) {
return function () {
this.classList.contains("close-details") ? (this.classList.remove("close-details"), this.textContent = "Expand", state = false) : (this.classList.add("close-details"), this.textContent = "Close", state = true);
var details = group.getElementsByTagName("details");
Array.from(details).forEach(function (detail) {
detail.open = state;
})
}
}
function expandAll() {
return function () {
this.classList.contains("close-all-details") ? (this.classList.remove("close-all-details"), this.textContent = "Expand All", state = false) : (this.classList.add("close-all-details"), this.textContent = "Close All", state = true);
var buttons = document.querySelectorAll('.details-helper');
Array.from(buttons).forEach(function (button) {
if(!state) {
button.classList.remove("close-details");
} else {
button.classList.add("close-details");
}
button.textContent = state ? "Close" : "Expand";
for (var group of groups) {
var parent = button.closest(group);
if (parent) {
var details = parent.querySelectorAll("details");
Array.from(details).forEach(function (detail) {
detail.open = state;
})
}
}
})
}
}
});
这可以包含在带有脚本标签的文档中 - 'details-helper.js' - 并且创建的按钮包括样式。
使按钮与细节元素的默认样式保持一致:
.search-helper,
.details-helper {
font-size: .66em;
margin: 0 1em;
outline: none;
padding: 0.25em;
text-transform: uppercase;
vertical-align: text-bottom;
width: 8em;
}
.search-helper {
width: 10em;
}
.search-helper::after,
.details-helper::after {
content: ' ▶';
}
.close-all-details::after,
.close-details::after {
content: ' ▼';
}
您的里程可能会因此解决方案而异,但希望您会发现其中的一些有用。假设您的页面具有内容的主要和逻辑结构。这还没有在每个元素都嵌套在许多 div 中并且没有文章或部分的页面上进行测试。