Javascript 递归JS函数列出Hx HTML标记?
我有一些代码:Javascript 递归JS函数列出Hx HTML标记?,javascript,jquery,html,recursion,Javascript,Jquery,Html,Recursion,我有一些代码: $('section').each(function() { var the_id; var list_item; $(this).find('h2').each(function() { the_id = $(this).attr('id'); $('nav > ol').append('<li><a href="#' + the_id + '">' + $(this).text() + '&
$('section').each(function() {
var the_id;
var list_item;
$(this).find('h2').each(function() {
the_id = $(this).attr('id');
$('nav > ol').append('<li><a href="#' + the_id + '">' + $(this).text() + '</a></li>');
$(this).siblings('h3').each(function(i) {
the_id = $(this).attr('id');
if (i == 0) {
$('nav > ol > li:last').append('<ol></ol>');
}
$('nav > ol > li:last > ol').append('<li><a href="#' + the_id + '">' + $(this).text() + '</a></li>');
});
});
});
$('section')。每个(函数(){
var_id;
风险值清单项目;
$(this).find('h2').each(function(){
_id=$(this.attr('id');
$('nav>ol')。追加('li>');
$(this).同级('h3')。每个(函数(i){
_id=$(this.attr('id');
如果(i==0){
$('nav>ol>li:last')。附加('');
}
$('nav>ol>li:last>ol')。追加('');
});
});
});
它会生成一些HTML,如:
<li>
<a href="#example-1">Example 1</a>
<ol>
<li>
<a href="#example-1a">Example 1a</a>
</li>
<li>
<a href="#example-1b">Example 1b</a>
</li>
</ol>
</li>
<li>
<a href="#another-example">Another Example</a>
</li>
<li>
<a href="#last-one">Last One</a>
</li>
<li>
<a href="#just-kidding--another">Just kidding, another</a>
<ol>
<li>
<a href="#this-is-a-sub-header">This is a sub header</a>
</li>
</ol>
</li>
我的问题是,我的JS只在我写的时候起作用(h2,然后寻找H3,我必须为h4编写另一个回调,然后为h5和h6编写另一个回调。我如何才能编写一个递归函数来实现这一点?稍微看一下这个,我想我明白了你的目的。每个级别实际上并没有什么不同,你只是解释了最低级别来实现它。就像Matt一样的评论说,您需要单独声明回调。但您还需要将当前级别的列表传递到其中,以便可以附加到正确的位置。我们可以尝试一种使用方法构造回调的方法,如下所示:
function Generator(e, level) {
var list = e; // I think you need this for the closure to work, but my js is rusty so I may be wrong.
return function() {
var new_list = $('<ol></ol>');
list.append(new_list); // you might want to make sure there's more than 0 siblings?
$(this).siblings('h' + level).each(function(i) {
the_id = $(this).attr('id');
new_list.append('<li><a href="#' + the_id + '">' + $(this).text() + '</a></li>');
if (level < 6) { // your max h tag level
Generator(new_list, level + 1)();
}
});
}
}
显然,您的代码一开始使用的是$(this.find('h2')
,而不是$(this.this.)。兄弟姐妹('h2')
,因此需要在这方面进行一些调整。但我相信这不是什么大问题
我没有测试这个,所以我可能在某个地方至少犯了一个错误。一个搜索结果显示:它是纯“ole javascript”,但您应该能够根据自己的需要调整它(或者,借用这个想法,编写自己的代码)
在讨论了一些之后,我认为Juan是对的:迭代方法似乎更容易。我制作了一个使用类似方法的快速jQuery插件:
(function($) {
$.fn.buildTOC = function(options) {
var opts = $.extend({
scan: $(document) // By default, search the entire page for headings
}, options),
$toc = $(this), // This is where we'll place our TOC links
/*
* Get the current level from the Heading tag.
*/
getLevel = function(h) {
return parseInt(h.substring(1));
},
/*
* Creates a new sublist and returns it.
* The randomly-generated ID just makes it easier to find the new list.
*/
pushLevel = function(toc) {
var id = 'node' + Math.round(Math.random() * 50000 + 1);
toc.append($('<ol id="' + id + '"></ol>'));
return $('#' + id, toc);
},
/*
* Returns the last sublist containing an element at the current level;
* otherwise, returns the parent list (for top-level items).
*/
popLevel = function(toc, level) {
var sub = $('.toc-level-' + level + ':last', toc);
if (sub.length) {
return sub.parent();
} else {
return $toc.children('ol');
}
},
/*
* Appends a link for the current tag to the current list.
* Also adds a class for the current level (handy for styling), so it's easy
* to find items at this level.
*/
appendLink = function(toc, tag, level) {
toc.append($('<li class="toc-level-' + level + '"><a href="#' + tag.id + '">' + tag.innerHTML + '</a></li>'))
},
buildTOC = function(toc) {
var headings = $('h1,h2,h3,h4,h5,h6', opts.scan),
lastLevel = 0;
for (var i=0, len=headings.length; i<len; i++) {
var currTag = headings[i],
currLevel = getLevel(currTag.tagName);
if (lastLevel == currLevel) {
// Siblings: just add a link for this item
appendLink(toc, currTag, currLevel);
} else if (lastLevel < currLevel) {
// Child: create a new list and append to that
toc = pushLevel(toc);
appendLink(toc, currTag, currLevel);
} else {
// Parent: move back out to the appropriate list
toc = popLevel(toc, currLevel);
appendLink(toc, currTag, currLevel);
}
lastLevel = currLevel;
}
};
buildTOC($toc);
};
})(jQuery);
其中
toc
是链接应该放在哪里的容器ID。另一种构建列表HTML的方法如何?我在编写/理解递归代码方面真的很差劲。迭代通常对我来说更容易
function buildToc(container) {
var html = "", lastLevel = -1;
container.find('h1, h2, h3, h4, h5, h6, h7, h8, h9').each(function() {
var $this = $(this);
var level = this.tagName.match(/H(\d)/)[1];
if (lastLevel < level) {
html += "<ol>";
}
if (lastLevel > level) {
html += "</ol>";
}
html += "<li><a href='"+ this.id + "' >" + $this.text() + "</a></li>";
lastLevel = level;
});
return html;
}
$('nav').append( buildToc( $('article section') ) );
函数buildToc(容器){
var html=”“,lastLevel=-1;
container.find('h1,h2,h3,h4,h5,h6,h7,h8,h9')。每个(函数(){
var$this=$(this);
变量级别=此.tagName.match(/H(\d)/)[1];
如果(最后级别<级别){
html+=“”;
}
如果(lastLevel>level){
html+=“”;
}
html+=“”;
lastLevel=level;
});
返回html;
}
$('nav').append(buildToc($('article section'));
我在你的页面上运行了它,它复制了你现有的TOC。你不需要为每一个级别编写自定义代码;快速而肮脏。如果你单独声明回调函数,而不是匿名声明回调函数,那么用JavaScript编写递归函数就很容易了。但是,我看不出递归在这里有什么帮助,因为它看起来逻辑不同对于每个标题级别都是t。对于“s”之后的所有内容都是相同的。它始终是同级的,但是ol>li x,不管你在什么位置。为什么是递归的?也许你的问题是为什么不
$(“h*”)
工作,我怎样才能得到相同的效果,一组所有的h1,h2,h3,…?你说的最后一位是什么意思,ol>li x
?我知道这是一个选择器,但我知道你不仅仅是指H4的ol>li 4
。它需要以的方式嵌套所有内容。也就是说,将所有内容都放在一个div中,然后通过该d进行下去iv对于所有sub在抓取所有sub之后,返回到s并进入div抓取所有sub hx,等等。这是一个ToC:你不应该有一个只包含链接的答案。你应该在这里简单地解释一下。代码看起来很棒,它会工作,但这是很多代码。这应该是一个简单的递归函数,比如Tesserexp,我还在测试。@Juan,@Oscar:很对,伙计们……我正在研究:)顺便说一句,我认为Tesserex的功能也很好。更接近,我认为,--除了“示例1”、“另一个示例”、“最后一个”和“开玩笑”看起来不太正确之外都是兄弟姐妹,而不是示例1的后代。递归函数让我的大脑爆炸;)也请看我对JS模板的评论!
$(function() {
$('#toc').buildTOC();
})
function buildToc(container) {
var html = "", lastLevel = -1;
container.find('h1, h2, h3, h4, h5, h6, h7, h8, h9').each(function() {
var $this = $(this);
var level = this.tagName.match(/H(\d)/)[1];
if (lastLevel < level) {
html += "<ol>";
}
if (lastLevel > level) {
html += "</ol>";
}
html += "<li><a href='"+ this.id + "' >" + $this.text() + "</a></li>";
lastLevel = level;
});
return html;
}
$('nav').append( buildToc( $('article section') ) );