我一直在思考这一段时间,但无法提出一个有效的解决方案。我甚至不能伪造它...
例如,假设您有一个页面,其标题结构如下:
<h1>Heading level 1</h1>
<h2>Sub heading #1</h2>
<h2>Sub heading #2</h2>
<h3>Sub Sub heading</h3>
<h2>Sub heading #3</h2>
<h3>Sub Sub heading #1</h3>
<h3>Sub Sub heading #2</h3>
<h4>Sub Sub Sub heading</h4>
<h2>Sub heading #4</h2>
<h3>Sub Sub heading</h3>
使用JavaScript(任何框架都没问题),您将如何生成这样的列表:(使用嵌套列表)
<ol>
<li>Heading level 1
<ol>
<li>Sub heading #1</li>
<li>Sub heading #2
<ol>
<li>Sub Sub heading</li>
</ol>
</li>
<li>Sub heading #3
<ol>
<li>Sub Sub heading #1</li>
<li>Sub Sub heading #2
<ol>
<li>Sub Sub Sub heading (h4)</li>
</ol>
</li>
</ol>
</li>
<li>Sub heading #4
<ol>
<li>Sub Sub heading</li>
</ol>
</li>
</ol>
</li>
</ol>
每当我尝试以某种方法开始时,它最终变得非常臃肿。
解决方案需要遍历每个标题并将其放入适当的嵌套列表中 - 我一直在重复这个问题,但我不能勾画出任何东西!
即使你有一种方法,但没有时间对其进行编码,我仍然想知道它! :)
谢谢!
答案 0 :(得分:3)
这里的问题是没有任何好的方法来检索文档顺序中的标题。例如,jQuery调用$('h1,h2,h3,h4,h5,h6')
将返回所有标题,但所有<h1>
将首先出现,然后是<h2>
,依此类推。当您使用逗号分隔的选择器时,没有主框架工作以文档顺序返回元素。
您可以通过向每个标题添加公共类来克服此问题。例如:
<h1 class="heading">Heading level 1</h1>
<h2 class="heading">Sub heading #1</h2>
<h2 class="heading">Sub heading #2</h2>
<h3 class="heading">Sub Sub heading</h3>
<h2 class="heading">Sub heading #3</h2>
...
现在,选择器$('.heading')
将按顺序完成它们。
以下是我将如何使用jQuery:
var $result = $('<div/>');
var curDepth = 0;
$('h1,h2,h3,h4,h5,h6').addClass('heading');
$('.heading').each(function() {
var $li = $('<li/>').text($(this).text());
var depth = parseInt(this.tagName.substring(1));
if(depth > curDepth) { // going deeper
$result.append($('<ol/>').append($li));
$result = $li;
} else if (depth < curDepth) { // going shallower
$result.parents('ol:eq(' + (curDepth - depth - 1) + ')').append($li);
$result = $li;
} else { // same level
$result.parent().append($li);
$result = $li;
}
curDepth = depth;
});
$result = $result.parents('ol:last');
// clean up
$('h1,h2,h3,h4,h5,h6').removeClass('heading');
$result
现在应该是您的<ol>
。
另请注意,这将处理<h4>
后跟<h1>
(一次向下移动多个级别),但它不会处理<h1>
后跟{ {1}}(一次超过一个级别)。
答案 1 :(得分:2)
首先,构建一棵树。伪代码(因为我不能流利使用Javascript):
var headings = array(...);
var treeLevels = array();
var treeRoots = array();
foreach(headings as heading) {
if(heading.level == treeLevels.length) {
/* Adjacent siblings. */
if(heading.level == 1) {
treeRoots[] = heading; // Append.
} else {
treeLevels[treeLevels.length - 2].children[] = heading; // Add child to parent element.
}
treeLevels[treeLevels.length - 1] = heading;
} else if(heading.level > treeLevels.length) {
/* Child. */
while(heading.level - 1 > treeLevels.length) {
/* Create dummy headings if needed. */
treeLevels[] = new Heading();
}
treeLevels[] = heading;
} else {
/* Child of ancestor. */
treeLevels.remove(heading.level, treeLevels.length - 1);
treeLevels[treeLevels.length - 1].children[] = heading;
treeLevels[] = heading;
}
}
接下来,我们横穿它,建立清单。
function buildList(root) {
var li = new LI(root.text);
if(root.children.length) {
var subUl = new UL();
li.children[] = subUl;
foreach(root.children as child) {
subUl.children[] = buildList(child);
}
}
return li;
}
最后,将LI
返回的buildList
插入每个UL
的{{1}}。
在jQuery中,您可以按顺序获取标题元素:
treeRoots
答案 2 :(得分:1)
我可以想象很多你可能会过度思考这种情况的情况。在许多情况下,您实际上只需要层次结构的外观,而不是实际重新生成的HTML层次结构本身,您可以为此执行以下简单操作:
#nav li.h1 { padding: 0 0 0 0px; } #nav li.h1:before { content: 'h1 '; }
#nav li.h2 { padding: 0 0 0 10px; } #nav li.h2:before { content: 'h2 '; }
#nav li.h3 { padding: 0 0 0 20px; } #nav li.h3:before { content: 'h3 '; }
#nav li.h4 { padding: 0 0 0 30px; } #nav li.h4:before { content: 'h4 '; }
#nav li.h5 { padding: 0 0 0 40px; } #nav li.h5:before { content: 'h5 '; }
#nav li.h6 { padding: 0 0 0 50px; } #nav li.h6:before { content: 'h6 '; }
for (i=1; i<=6; i++) {
var headers = document.getElementsByTagName('h'+i);
for (j=0; j<headers.length; j++) {
headers[j].className = 'h';
}
}
var headers = document.getElementsByClassName('h');
var h1 = document.getElementsByTagName('h1')[0];
h1.parentNode.insertBefore(document.createElement('ul'),h1.nextSibling);
h1.nextSibling.id = 'nav';
for (i=0; i<headers.length; i++) {
document.getElementById('nav').innerHTML += '<li class="'+headers[i].tagName.toLowerCase()+'">'+headers[i].innerHTML+'</li>';
}
答案 3 :(得分:0)
这将选择所有h1-h6标签到文档的docElTgt DOM部分,并且将遵守订单标题进入html文档
var hItemsList = docElTgt.querySelectorAll('h1, h2, h3, h4, h5, h6');
可以是docElTgt的值的示例:
docElTgt = document.body;
docElTgt = anyelement.id;
选择所有标题后,可以应用算法将层次结构作为其他用户显示的有序列表