jQueryで自動で見出しリストとアンカーリンクを作る

jQueryを使って、見出しタグから自動で見出しの一覧を作る
今回は、jQueryを使って記事内の見出しタグを自動で抽出して見出しタグのリストを作るコードを作ったので公開してみたいと思います。
作ってみたのがコレ
$(document).ready(function(){
var tags = $("#single h2,#single h3,#single h4");
var i=0;
if(tags.length > 2) {
$("#eye-catch").after("<div class='auto'><p>見出し</p><ul></ul></div>");
$(tags).each(function(){
$(this).attr("id","auto-h"+i);
auto($(this),"H2");
auto($(this),"H3");
auto($(this),"H4");
i++;
});
}
function auto(thiss,h) {
if( thiss.get(0).tagName == h ) {
$(".auto ul").append("<li class='auto-"+thiss.get(0).tagName+"'><a href='#auto-h"+i+"'>"+thiss.text());
}
}
});
#single 内のH2~H4タグまでを対象として、Hタグが3個以上存在するときだけ表示するようにもしました。出力するものはliでリスト化しているのですが階層化はしていません、ですが、Hタグの種類によってCSSを当てれるようにClass付しているので、見た目は階層化したリストの用に表現出来る。
実際使っているものは、そのようにしている。
実はもう一つ、リストで階層化するように作ったものもあります。まず、こっちを先に作ったんだけど、簡素化できると思って作りなおしたのが上で紹介しているものです。ulタグの階層化が閉じたりするのが処理的に条件が増えて煩雑になる
一応こんなコードです
$(document).ready(function(){
var i = 0;
var this_tagname;
var this_title;
var create_html_before = '<div class="auto-heading"><p>Auto Heading</p><ul>';
var create_html_after = '</ul></div>';
var tags = $("#single h2,#single h3,#single h4");
$(tags).each(function(index){
this_tagname = $(this).get(0).tagName;
if( this_tagname == "H2") {
if( index == tags.length - 1) {
if( tags.eq(i-1).get(0).tagName == "H3" ) {
$(this).attr("id","auto-heading-list-"+i);
create_html_before = create_html_before+"</ul><li><a href='#auto-heading-list-"+i+"'>"+$(this).text()+"</a>";
}
if( tags.eq(i-1).get(0).tagName == "H4" ) {
$(this).attr("id","auto-heading-list-"+i);
create_html_before = create_html_before+"</ul></ul><li><a href='#auto-heading-list-"+i+"'>"+$(this).text()+"</a>";
}
} else {
$(this).attr("id","auto-heading-list-"+i);
create_html_before = create_html_before+"<li><a href='#auto-heading-list-"+i+"'>"+$(this).text()+"</a>";
}
} else if( this_tagname == "H3") {
h(index,$(this),"H2","H3");
} else if( this_tagname == "H4") {
h(index,$(this),"H3","H4");
}
i++;
if( index == tags.length - 1) {
$("#eye-catch").after(create_html_before+create_html_after);
}
});
function h(index,this_this,before_h,h) {
if( index !== tags.length - 1) {
if( tags.eq(i-1).get(0).tagName == before_h ) {
//手前がH2の時にULを生成
this_this.attr("id","auto-heading-list-"+i);
create_html_before = create_html_before+"<ul><li><a href='#auto-heading-list-"+i+"'>"+this_this.text()+"</a>";
} else if( tags.eq(i+1).get(0).tagName !== h) {
//次のタグがH2の時 ULを閉じる
this_this.attr("id","auto-heading-list-"+i);
create_html_before = create_html_before+"<li><a href='#auto-heading-list-"+i+"'>"+this_this.text()+"</a></ul>";
} else {
this_this.attr("id","auto-heading-list-"+i);
create_html_before = create_html_before+"<li><a href='#auto-heading-list-"+i+"'>"+this_this.text()+"</a></li>";
}
} else {
if( tags.eq(i-1).get(0).tagName == before_h ) {
//手前がH2の時にULを生成
this_this.attr("id","auto-heading-list-"+i);
create_html_before = create_html_before+"<ul><li><a href='#auto-heading-list-"+i+"'>"+this_this.text()+"</a></ul>";
console.log(this_this.text());
} else {
this_this.attr("id","auto-heading-list-"+i);
create_html_before = create_html_before+"<li><a href='#auto-heading-list-"+i+"'>"+this_this.text()+"</a></ul>";
}
}
}
});
長いし見づらいしってことで、最初の方に簡素化したほうがスッキリして見やすいですよね、タグの構造は違うが見た目上は同一に出来る。また、検索エンジンに向けて階層化したほうがいいかな?というのがありますが。HTMLをjavascriptで後から生成しているので、そこんところは検索エンジンは生のHTMLを見てるので関係ないので、javascriptで出すHTMLは結構適当でもいいかなと思ってたりもします。機能と見た目ができてればよいかと。
今回作ってみて思ったポイントは
length
セレクタ.length でヒットした対象となるタグの数が取得出来るってことですね、lengthは総数を返しますので、eq()やindex()とのズレがあるって事がミソです。eq()やindex()は0からカウントが始まります。
.get(0).tagName
セレクタ.get(0).tagNameでそのタグの名称を取得すると言うこと。例えば<h2>だったら返りはH2です。タグは大文字で返されるって点を覚えておく必要がある。条件式を作るときに大文字と小文字は区別されるのでifがうまく動かなかったりする原因になる
その他は、function化したところは if else function化しなくてもかけるのですが。なんか、これのほうがコード見やすいかなと思ってあんな形にしました。each内にif else でやるのが普通かも


COMMENT