記事内目次を自動で無料ブログに追加するJavaScript

勘違いしながらどハマりしながら作り上げる爺の『JavaScript奮闘記』。今回は、無料ブログに自動で記事内目次を生成する機能を作ります。

ポク太郎です。

WordPressではほぼ標準装備される記事内目次

はてなブログLivedoorブログSeesaaBlogger等の無料ブログでもそれ相当となるJavaScriptを作ってみます。

ブログ運営者それぞれで数値の調整が必要なので多少プログラムを触れる方向け。


まず知るべきHTMLタグの常識~下準備

ホームページの正体はHTML。HTMLタグがズラズラ並んだもの。

はてなブログLivedoorブログSeesaaBloggerにはHTMLで編集するモードが実装されており、そこにHTMLタグを並べられます。

記事内目次を無料ブログに自動で追加するJavaScript

で、下のようなHTMLがあった場合、

<h2>これがH2タグ</h2>
<h3>これがH3タグ</h3>
<style>.moku {
text-align:center;
width:100%;
max-width:500px;
margin:30px auto;
}</style>
<script type="text/javascript">
var i,j;</script>

<style></style>で囲まれた部分がcss<script type=”text/javascript”></script>で囲まれた部分がJavaScriptとして働きます。

所定の場所に書く場合はこれら<style><script type=”text/javascript”>タグは削除して記述し、HTMLを書くべき場所の場合はそれらタグで挟んで記述しないと認識されません。

これがまず知るべき常識。

記事内目次の仕様とJavaScriptの仕事~下準備

見出し作成にJavaScriptが行うこと

前の記事内目次 次の記事内目次 

JavaScriptが行う仕事は、

この記事内目次生成するJavaScriptの仕事
仕事内容
1 ページ内のH2H3タグを全部調べ仮のid名を割り振る。オフセット値で除外された分除く。
2 H2タグとH3タグの階層を考慮し、JavaScriptid名を付け直す。例:H2id名はan、H3id名はbnm。n、mは整数。

//こんな付け方
<h2 id="a1">H2タグ1番目</h2>
 <h3 id="b11">H3タグ11番目</h3>
 <h3 id="b12">H3タグ12番目</h3>
 <h3 id="b13">H3タグ13番目</h3>
<h2 id="a2">H2タグ2番目</h2>
 <h3 id="b21">H3タグ21番目</h3>
 <h3 id="b22">H3タグ22番目</h3>
<h2 id="a3">H2タグ3番目</h2>
<h2 id="a4">H2タグ4番目</h2>
 <h3 id="b41">H3タグ41番目</h3>
 <h3 id="b42">H3タグ42番目</h3>
3 H2H3タグのid名と文言を抜き出してリンクを作成し、調べた階層通りに<ol><li>タグで並べ記事内目次のHTMLを作成。

//作る記事内目次のHTML
<ol>
<li><a href="#a1"></a>H2タグ1番目</li>
<ol>
<li><a href="#b11"></a>H3タグ11番目</li>
<li><a href="#b12"></a>H3タグ12番目</li>
<li><a href="#b13"></a>H3タグ13番目</li>
</ol>
<li><a href="#a2"></a>H2タグ2番目</li>
<ol>
<li><a href="#b21"></a>H3タグ21番目</li>
<li><a href="#b22"></a>H3タグ22番目</li>
</ol>
<li><a href="#a3"></a>H2タグ3番目</li>
<li><a href="#a4"></a>H2タグ4番目</li>
<ol>
<li><a href="#b41"></a>H3タグ41番目</li>
<li><a href="#b42"></a>H3タグ42番目</li>
</ol>
</ol>
4 出来上がったHTMLを設置された<div id=”kiji_moku” class=”moku”></div>内に書き込み完成。

この記事内目次の仕様と制限

前の記事内目次 次の記事内目次 

ここで作る記事内目次はphpにより作られるWordPressのものとは異なり、JavaScriptで作るものなので、記事作成時には以下タグを最初のH2タグ直上に手動で追加しないといけません。

<div id="kiji_moku" class="moku"></div>

JavaScriptがページ内の全H2H3タグを調べ、上記id名kiji_mokudivタグ内に見出しのリンク集=記事内目次を作り出して表示します。

また、無料ブログでは記事内だけでなく投稿タイトルや時刻、サイドバー内の項目にH2H3タグが使われる場合が。←各ブログ運営者で異なる数。

なので、その分を対象外とするため先頭以前と末尾以降の数をソース内のオフセット値に設定。つまり、ブログのデザインを変更する度に値を修正する必要が出てきます。

オフセット値を代入する4変数ofsp_h2ofsa_h2ofsp_h3ofsa_h3。詳細は下の実践部分で説明。

その他、PC向け画面とモバイル向け画面でそのオフセット値が異なるデザインの場合はそれを考慮してプログラムを改良する必要があります。

まとめると、

記事内目次の劣る点
劣る点 修正要する時 説明と必要作業
1 対応するタグ H2H3タグのみ対応。H4以降は未対応。
2 専用タグの設置 毎記事要 先頭のH2タグ直上に、<div id=”kiji_moku” class=”moku”></div>と毎記事書く必要あり。
3 オフセット値設定 ブログデザイン変更時 H2H3タグが増減するデザイン変更時には、JavaScriptソース内のオフセット値修正要。

PCとモバイルでオフセット値が異なるデザインの場合はJavaScriptソースを改良する必要あり。現時点では未対応。

Bloggerで自動記事内目次~実践1

BloggerでのHTML、css、JavaScript

前のBlogger 次のBlogger 

css、JavaScriptも全部HTMLで表示すると、

冒頭文<br />
<br />
<br />
<!--more-->
<div id="kiji_moku" class="moku"></div>

<h2>H2タグ1番目</h2>
<h3>H3タグ11番目</h3>
<h3>H3タグ12番目</h3>
<h3>H3タグ13番目</h3>
<h2>H2タグ2番目</h2>
<h3>H3タグ21番目</h3>
<h3>H3タグ22番目</h3>
<h2>H2タグ3番目</h2>
<h2>H2タグ4番目</h2>
<h3>H3タグ41番目</h3>
<h3>H3タグ42番目</h3>

<div id="debug"></div>

<style>
.moku {
text-align:center;
width:100%;
max-width:500px;
margin:30px auto;
}
.moku a {
text-decoration:none;
color:#444;
}
.moku ol {
background-color:rgba(150,180,200,0.2);
padding-left:0px;
list-style:none;
padding:10px;
}
.moku li {
padding-left:20px;
}
</style>

<script async="async" type="text/javascript">
				var i,j;
				var ofsp_h2 = 1;//ブログテーマ・サイドバー状況による
				var ofsa_h2 = 2;//ブログテーマ・サイドバー状況による
				var ofsp_h3 = 1;//ブログテーマ・サイドバー状況による
				var ofsa_h3 = 0;//ブログテーマ・サイドバー状況による

				var h_tag = document.querySelectorAll('h2,h3');
				var h2_tag = document.querySelectorAll('h2');
				var h3_tag = document.querySelectorAll('h3');

				var k1='0';
				var k2=0;
				var jd = '';

	for(i=ofsp_h2; i<h2_tag.length-ofsa_h2; i++) {
				h2_tag[i].setAttribute('id','a'+i);
	}
	for(i=ofsp_h3; i<h3_tag.length-ofsa_h3; i++) {
				//仮id付加
				h3_tag[i].setAttribute('id','btmp'+i);
	}
	document.getElementById('debug').innerHTML += 'STEP1<br />';
	for(i=0; i<h3_tag.length; i++) {
		for(j=ofsp_h2+ofsp_h3; j<h_tag.length-ofsa_h2-ofsa_h3; j++) {
				jd = h_tag[j].id.substr(0,1);
			if (jd == 'a'){
				k1 = h_tag[j].id.replace('a','');
				k2 = 0;
			}
			else {
				k2 = k2 + 1;
			if (h3_tag[i] == h_tag[j]){
				h3_tag[i].setAttribute('id','b'+k1+k2.toString());
				break;
			}
			}
		}
	}
	document.getElementById('debug').innerHTML += 'STEP2<br />';

	for(i=ofsp_h2+ofsp_h3; i<h_tag.length-ofsa_h2-ofsa_h3; i++) {
	document.getElementById('debug').innerHTML += h_tag[i].id+'<br />';
	}

				var h2t = [];
				h2t.length = h_tag.length;
				var h2s = [];
				h2s.length = h_tag.length;
				var h3_before = false;

				var tmp = '';
				var tmp2 = '<ol>';

				var m = -1;
				var jd = '';
	//<h2>はa
	for(i=ofsp_h2+ofsp_h3; i<h_tag.length-ofsa_h2-ofsa_h3; i++) {

				jd = h_tag[i].id.substr(0,1);
		if (jd == 'a' || jd == 'b'){
				m = m + 1;
				h2t[m] = h_tag[i].childNodes[0].textContent;
				h2s[m] = h_tag[i].id;

				tmp = '<li><a href="#' + h2s[m] + '">' + h2t[m] + '</a></li>';
			if (jd == 'a' || jd == 'z'){
				if (h3_before == true){
					tmp = '</ol>' + tmp;
					h3_before = false;
				}
			}
			else {
				if (h3_before == false){
					tmp = '<ol>' + tmp;
				}
				h3_before = true;
			}
				tmp2 = tmp2 + tmp;
		}
	}
				if (h3_before == true){
					tmp2 = '</ol>' + tmp2 + '</ol>';
				}
				else {
					tmp2 = tmp2 + '</ol>';
				}

	document.getElementById('kiji_moku').innerHTML += '記事内目次'+'<br />';
	document.getElementById('kiji_moku').innerHTML += tmp2;
	document.getElementById('debug').innerHTML += '<br />'+'JS終了到達';
</script>

Bloggerでのオフセット値

上記全部を投稿編集の画面に貼り付けると一応動くはず。実際に作成したBloggerページはこちら。記事内目次の文言をクリックすると目的のタグへジャンプします。

使用したテーマは「シンプル」。ダサい見た目はcss部分を修正して下さい。

上述のオフセット値は以下表の通り。

JavaScript内のオフセット値
変数名 意味 Bloggerの場合
変数ofsp_h2 先頭より前にあるH2タグの数を設定。 1
変数ofsa_h2 末尾より後にあるH2タグの数を設定。 2
変数ofsp_h3 先頭より前にあるH3タグの数を設定。 1
変数ofsa_h3 末尾より後にあるH3タグの数を設定。 0

Bloggerでの共通化

テストは投稿編集画面に貼り付け。が、全ページ共通なので最終的にはcssJavaScriptをウィジェットに移動させます。(“ガジェット”と表示されてますが。)

記事内目次を無料ブログに自動で追加するJavaScript~Blogger

→レイアウト-Footer-1部分に「ガジェットを追加」で「HTML/JavaScript」を2つ追加。
→片方に<style></style>部分をタグを付けたまま貼り付け。
→もう一方に<script type=”text/javascript”></script>部分をタグを付けたまま貼り付け。
→保存。
→全記事共通となるガジェット内にcssJavaScriptを移動させたので、投稿編集内からはそれらを削除。

Bloggerでのモバイル対応

前のBlogger 次のBlogger 

当然、モバイルページにも上記ウィジェットを表示する設定をしないといけません。

テーマ-「カスタマイズ」ボタン横の矢印-「html編集」でHTMLを開き、追加した2ウィジェットを探して以下のように修正。

<b:widget id='HTML1' locked='false' title='' type='HTML'>
↓修正
<b:widget id='HTML1' locked='false' mobile='yes' title='' type='HTML'>

Bloggerの場合、モバイルページURLは末尾にURLパラメータ?m=1付加したもの。モバイルでも同様に記事内目次を生成したBloggerページがこちら

Seesaaで自動記事内目次~実践2

SeesaaでのHTML、css、JavaScript

前のSeesaa 次のSeesaa 

css、JavaScriptも全部HTMLで表示すると、

冒頭文<br />
<br />
<br />
<!--Seesaaの場合、↑まで「本文」タブに記入-->
<!--more-->
<!--Seesaaの場合、↓から「追記」タブに記入-->
<div id="kiji_moku" class="moku"></div>
<h2>H2タグ1番目</h2>
<h3>H3タグ11番目</h3>
<h3>H3タグ12番目</h3>
<h3>H3タグ13番目</h3>
<h2>H2タグ2番目</h2>
<h3>H3タグ21番目</h3>
<h3>H3タグ22番目</h3>
<h2>H2タグ3番目</h2>
<h2>H2タグ4番目</h2>
<h3>H3タグ41番目</h3>
<h3>H3タグ42番目</h3>

<div id="debug"></div>

<style>
.moku {
border-color:#ccc;
border:2px solid;
padding:5px;
margin:0 auto;
width:100%;
max-width:500px;
}
.moku a {
text-decoration:none;
color:#444;
}
.moku ol {
background-color:rgba(150,180,200,0.2);
padding-left:0px;
padding:10px;
list-style:none;
}
.moku li {
padding-left:20px;
list-style:none;
}
</style>

<script async="async" type="text/javascript">
				var i,j;
				var ofsp_h2 = 1;//ブログテーマ・サイドバー状況による
				var ofsa_h2 = 0;//ブログテーマ・サイドバー状況による
				var ofsp_h3 = 0;//ブログテーマ・サイドバー状況による
				var ofsa_h3 = 7;//ブログテーマ・サイドバー状況による

				var h_tag = document.querySelectorAll('h2,h3');
				var h2_tag = document.querySelectorAll('h2');
				var h3_tag = document.querySelectorAll('h3');

				var k1='0';
				var k2=0;
				var jd = '';

	for(i=ofsp_h2; i<h2_tag.length-ofsa_h2; i++) {
				h2_tag[i].setAttribute('id','a'+i);
	}
	for(i=ofsp_h3; i<h3_tag.length-ofsa_h3; i++) {
				//仮id付加
				h3_tag[i].setAttribute('id','btmp'+i);
	}
	document.getElementById('debug').innerHTML += 'STEP1<br />';
	for(i=0; i<h3_tag.length; i++) {
		for(j=ofsp_h2+ofsp_h3; j<h_tag.length-ofsa_h2-ofsa_h3; j++) {
				jd = h_tag[j].id.substr(0,1);
			if (jd == 'a'){
				k1 = h_tag[j].id.replace('a','');
				k2 = 0;
			}
			else {
				k2 = k2 + 1;
			if (h3_tag[i] == h_tag[j]){
				h3_tag[i].setAttribute('id','b'+k1+k2.toString());
				break;
			}
			}
		}
	}
	document.getElementById('debug').innerHTML += 'STEP2<br />';

	for(i=ofsp_h2+ofsp_h3; i<h_tag.length-ofsa_h2-ofsa_h3; i++) {
	document.getElementById('debug').innerHTML += h_tag[i].id+'<br />';
	}

				var h2t = [];
				h2t.length = h_tag.length;
				var h2s = [];
				h2s.length = h_tag.length;
				var h3_before = false;

				var tmp = '';
				var tmp2 = '<ol>';

				var m = -1;
				var jd = '';
	//<h2>はa
	for(i=ofsp_h2+ofsp_h3; i<h_tag.length-ofsa_h2-ofsa_h3; i++) {

				jd = h_tag[i].id.substr(0,1);
		if (jd == 'a' || jd == 'b'){
				m = m + 1;
				h2t[m] = h_tag[i].childNodes[0].textContent;
				h2s[m] = h_tag[i].id;

				tmp = '<li><a href="#' + h2s[m] + '">' + h2t[m] + '</a></li>';
			if (jd == 'a' || jd == 'z'){
				if (h3_before == true){
					tmp = '</ol>' + tmp;
					h3_before = false;
				}
			}
			else {
				if (h3_before == false){
					tmp = '<ol>' + tmp;
				}
				h3_before = true;
			}
				tmp2 = tmp2 + tmp;
		}
	}
				if (h3_before == true){
					tmp2 = '</ol>' + tmp2 + '</ol>';
				}
				else {
					tmp2 = tmp2 + '</ol>';
				}

	document.getElementById('kiji_moku').innerHTML += '記事内目次'+'<br />';
	document.getElementById('kiji_moku').innerHTML += tmp2;
	document.getElementById('debug').innerHTML += '<br />'+'JS終了到達';
</script>

Seesaaでのオフセット値

上記全部を投稿編集の画面に貼り付けると一応動くはず。実際に作成したSeesaaのページはこちら。記事内目次の文言をクリックすると目的のタグへジャンプします。

使用したデザインは「Standard_2018_PC」。ダサい見た目はcss部分を修正して下さい。

Seesaaの場合、<!–more–>タグが認識せず、冒頭文章を「本文」タブに、以降を「追記」タブに記述すると、TOPページに冒頭文だけ並ぶようです。

上述のオフセット値は以下表の通り。サイドバー内の項目が全部H3扱いになるようです。

JavaScript内のオフセット値
変数名 意味 Seesaaの場合
変数ofsp_h2 先頭より前にあるH2タグの数を設定。 1
変数ofsa_h2 末尾より後にあるH2タグの数を設定。 0
変数ofsp_h3 先頭より前にあるH3タグの数を設定。 0
変数ofsa_h3 末尾より後にあるH3タグの数を設定。 7

Seesaaでの共通化

前のSeesaa 次のSeesaa 

テストは投稿編集画面に全部貼り付け。が、全ページ共通なので最終的にはcssJavaScript専用の場所に移動させます。

ブログ一覧-デザイン-「css/HTML編集」ボタン。

記事内目次を無料ブログに自動で追加するJavaScript~Seesaa

→「スタイルシート編集」中に<style></style>部分をタグを取り除いて貼り付け。

貼り付ける場所は@media screen and (max-width: …px) {が始まる直前。これは表示幅の条件に合う場合に適用される部分なので。探すの面倒なら一番上でもいいけど。

→保存。
→「HTML編集」一番下の</body>直前に<script type=”text/javascript”></script>部分をタグを付けたまま貼り付け。
→保存。
→全記事共通となる部分にcssJavaScriptを移動させたので、投稿編集内からはそれらを削除。

Livedoorブログで自動記事内目次~実践3

LivedoorブログでのHTML、css、JavaScript

前のLiveDoorブログ 次のLiveDoorブログ 

css、JavaScriptも全部HTMLで表示すると、

冒頭文<br /><br /><br />
<!--LiveDoorの場合、↑まで「記事を書く」タブに記入-->
<!--more-->
<!--LiveDoorの場合、↓から「続きを書く」タブに記入-->
<article>
<div id="kiji_moku" class="moku"></div>
<h2>H2タグ1番目</h2>
<h3>H3タグ11番目</h3>
<h3>H3タグ12番目</h3>
<h3>H3タグ13番目</h3>
<h2>H2タグ2番目</h2>
<h3>H3タグ21番目</h3>
<h3>H3タグ22番目</h3>
<h2>H2タグ3番目</h2>
<h2>H2タグ4番目</h2>
<h3>H3タグ41番目</h3>
<h3>H3タグ42番目</h3>
<br />
<div id="debug"></div>

<style>
.moku {
text-align:center;
width:100%;
max-width:500px;
margin:30px auto;
}
.moku a {
text-decoration:none;
color:#444;
}
.moku ol {
background-color:rgba(150,180,200,0.2);
padding-left:0px;
list-style:none;
padding:10px;
}
.moku li {
padding-left:20px;
}
</style>

<script async="async" type="text/javascript">
                var i,j;
                var ofsp_h2 = 0;//ブログテーマ・サイドバー状況による
                var ofsa_h2 = 0;//ブログテーマ・サイドバー状況による
                var ofsp_h3 = 0;//ブログテーマ・サイドバー状況による
                var ofsa_h3 = 1;//ブログテーマ・サイドバー状況による

                var h_tag = document.querySelectorAll('h2,h3');
                var h2_tag = document.querySelectorAll('h2');
                var h3_tag = document.querySelectorAll('h3');

                var k1='0';
                var k2=0;
                var jd = '';

    for(i=ofsp_h2; i<h2_tag.length-ofsa_h2; i++) {
                h2_tag[i].setAttribute('id','a'+i);
    }
    for(i=ofsp_h3; i<h3_tag.length-ofsa_h3; i++) {
                //仮id付加
                h3_tag[i].setAttribute('id','btmp'+i);
    }
    document.getElementById('debug').innerHTML += 'STEP1<br />';
    for(i=0; i<h3_tag.length; i++) {
        for(j=ofsp_h2+ofsp_h3; j<h_tag.length-ofsa_h2-ofsa_h3; j++) {
                jd = h_tag[j].id.substr(0,1);
            if (jd == 'a'){
                k1 = h_tag[j].id.replace('a','');
                k2 = 0;
            }
            else {
                k2 = k2 + 1;
            if (h3_tag[i] == h_tag[j]){
                h3_tag[i].setAttribute('id','b'+k1+k2.toString());
                break;
            }
            }
        }
    }
    document.getElementById('debug').innerHTML += 'STEP2<br />';

    for(i=ofsp_h2+ofsp_h3; i<h_tag.length-ofsa_h2-ofsa_h3; i++) {
    document.getElementById('debug').innerHTML += h_tag[i].id+'<br />';
    }

                var h2t = [];
                h2t.length = h_tag.length;
                var h2s = [];
                h2s.length = h_tag.length;
                var h3_before = false;

                var tmp = '';
                var tmp2 = '<ol>';

                var m = -1;
                var jd = '';
    //<h2>はa
    for(i=ofsp_h2+ofsp_h3; i<h_tag.length-ofsa_h2-ofsa_h3; i++) {

                jd = h_tag[i].id.substr(0,1);
        if (jd == 'a' || jd == 'b'){
                m = m + 1;
                h2t[m] = h_tag[i].childNodes[0].textContent;
                h2s[m] = h_tag[i].id;

                tmp = '<li><a href="#' + h2s[m] + '">' + h2t[m] + '</a></li>';
            if (jd == 'a' || jd == 'z'){
                if (h3_before == true){
                    tmp = '</ol>' + tmp;
                    h3_before = false;
                }
            }
            else {
                if (h3_before == false){
                    tmp = '<ol>' + tmp;
                }
                h3_before = true;
            }
                tmp2 = tmp2 + tmp;
        }
    }
                if (h3_before == true){
                    tmp2 = '</ol>' + tmp2 + '</ol>';
                }
                else {
                    tmp2 = tmp2 + '</ol>';
                }

    document.getElementById('kiji_moku').innerHTML += '記事内目次'+'<br />';
    document.getElementById('kiji_moku').innerHTML += tmp2;
    document.getElementById('debug').innerHTML += '<br />'+'JS終了到達';
</script>

LiveDoorブログでのオフセット値

上記全部を投稿編集の画面に貼り付けると一応動くはず。実際に作成したLiveDoorのページはこちら。記事内目次の文言をクリックすると目的のタグへジャンプします。

使用したデザインはデフォルトのヤツ。ダサい見た目はcss部分を修正して下さい。

Livedoorブログの場合、<!–more–>タグが認識せず、冒頭文章を「記事を書く」タブに、以降を「続きを書く」タブに記述すると、TOPページに冒頭文だけ並ぶようです。

上述のオフセット値は以下表の通り。

JavaScript内のオフセット値
変数名 意味 Livedoorの場合
変数ofsp_h2 先頭より前にあるH2タグの数を設定。 0
変数ofsa_h2 末尾より後にあるH2タグの数を設定。 0
変数ofsp_h3 先頭より前にあるH3タグの数を設定。 0
変数ofsa_h3 末尾より後にあるH3タグの数を設定。 1

Livedoorブログでの共通化

前のLiveDoorブログ 次のLiveDoorブログ 

テストは投稿編集画面に貼り付け。が、全ページ共通なので最終的にはcssJavaScriptをデザイン設定に移動させます。

ブログ設定-「カスタマイズ」タブ中。

記事内目次を無料ブログに自動で追加するJavaScript~Livedoor

→「css」タブに<style></style>部分をタグを取り除いて貼り付け。

貼り付ける場所は@media screen and (max-width: …px) {が始まる直前。これは表示幅の条件に合う場合に適用される部分なので。探すの面倒なら一番上でもいいけど。

→保存。
→「個別記事ページ」タブ内一番下の</body>直前に<script type=”text/javascript”></script>部分をタグを付けたまま貼り付け。
→保存。
→全記事共通となる部分にcssJavaScriptを移動させたので、投稿編集内からはそれらを削除。

はてなブログで自動記事内目次~実践4

はてなブログでのHTML、css、JavaScript

前のはてなブログ 次のはてなブログ 

css、JavaScriptも全部HTMLで表示すると、

<article>冒頭文<br /><br /><br /><!--more-->

<div id="kiji_moku" class="moku"></div>
<h2>H2タグ1番目</h2>
<h3>H3タグ11番目</h3>
<h3>H3タグ12番目</h3>
<h3>H3タグ13番目</h3>
<h2>H2タグ2番目</h2>
<h3>H3タグ21番目</h3>
<h3>H3タグ22番目</h3>
<h2>H2タグ3番目</h2>
<h2>H2タグ4番目</h2>
<h3>H3タグ41番目</h3>
<h3>H3タグ42番目</h3>
<br /><br />
<div id="debug"></div>
</article>
<style>
.moku {
text-align:center;
width:100%;
max-width:500px;
margin:30px auto;
}
.moku a {
text-decoration:none;
color:#444;
}
.moku ol {
background-color:rgba(150,180,200,0.2);
padding-left:0px;
list-style:none;
padding:10px;
}
.moku li {
padding-left:20px;
}
</style>

<script async="async" type="text/javascript">
                var i,j;
                var ofsp_h2 = 1;//ブログテーマ・サイドバー状況による
                var ofsa_h2 = 0;//ブログテーマ・サイドバー状況による
                var ofsp_h3 = 0;//ブログテーマ・サイドバー状況による
                var ofsa_h3 = 0;//ブログテーマ・サイドバー状況による

                var h_tag = document.querySelectorAll('h2,h3');
                var h2_tag = document.querySelectorAll('h2');
                var h3_tag = document.querySelectorAll('h3');

                var k1='0';
                var k2=0;
                var jd = '';

    for(i=ofsp_h2; i<h2_tag.length-ofsa_h2; i++) {
                h2_tag[i].setAttribute('id','a'+i);
    }
    for(i=ofsp_h3; i<h3_tag.length-ofsa_h3; i++) {
                //仮id付加
                h3_tag[i].setAttribute('id','btmp'+i);
    }
    document.getElementById('debug').innerHTML += 'STEP1<br />';
    for(i=0; i<h3_tag.length; i++) {
        for(j=ofsp_h2+ofsp_h3; j<h_tag.length-ofsa_h2-ofsa_h3; j++) {
                jd = h_tag[j].id.substr(0,1);
            if (jd == 'a'){
                k1 = h_tag[j].id.replace('a','');
                k2 = 0;
            }
            else {
                k2 = k2 + 1;
            if (h3_tag[i] == h_tag[j]){
                h3_tag[i].setAttribute('id','b'+k1+k2.toString());
                break;
            }
            }
        }
    }
    document.getElementById('debug').innerHTML += 'STEP2<br />';

    for(i=ofsp_h2+ofsp_h3; i<h_tag.length-ofsa_h2-ofsa_h3; i++) {
    document.getElementById('debug').innerHTML += h_tag[i].id+'<br />';
    }

                var h2t = [];
                h2t.length = h_tag.length;
                var h2s = [];
                h2s.length = h_tag.length;
                var h3_before = false;

                var tmp = '';
                var tmp2 = '<ol>';

                var m = -1;
                var jd = '';
    //<h2>はa
    for(i=ofsp_h2+ofsp_h3; i<h_tag.length-ofsa_h2-ofsa_h3; i++) {

                jd = h_tag[i].id.substr(0,1);
        if (jd == 'a' || jd == 'b'){
                m = m + 1;
                h2t[m] = h_tag[i].childNodes[0].textContent;
                h2s[m] = h_tag[i].id;

                tmp = '<li><a href="#' + h2s[m] + '">' + h2t[m] + '</a></li>';
            if (jd == 'a' || jd == 'z'){
                if (h3_before == true){
                    tmp = '</ol>' + tmp;
                    h3_before = false;
                }
            }
            else {
                if (h3_before == false){
                    tmp = '<ol>' + tmp;
                }
                h3_before = true;
            }
                tmp2 = tmp2 + tmp;
        }
    }
                if (h3_before == true){
                    tmp2 = '</ol>' + tmp2 + '</ol>';
                }
                else {
                    tmp2 = tmp2 + '</ol>';
                }

    document.getElementById('kiji_moku').innerHTML += '記事内目次'+'<br />';
    document.getElementById('kiji_moku').innerHTML += tmp2;
    document.getElementById('debug').innerHTML += '<br />'+'JS終了到達';
</script>

はてなブログでのオフセット値

上記全部を投稿編集の画面に貼り付けると一応動くはず。実際に作成したはてなブログはこちら。記事内目次の文言をクリックすると目的のタグへジャンプします。

使用したデザインは不明、忘れた、覚えてない。ダサい見た目はcss部分を修正して下さい。

上述のオフセット値は以下表の通り。

JavaScript内のオフセット値
変数名 意味 はてなの場合
変数ofsp_h2 先頭より前にあるH2タグの数を設定。 1
変数ofsa_h2 末尾より後にあるH2タグの数を設定。 0
変数ofsp_h3 先頭より前にあるH3タグの数を設定。 0
変数ofsa_h3 末尾より後にあるH3タグの数を設定。 0

はてなブログでの共通化

前のはてなブログ 次のはてなブログ 

テストは投稿編集画面に貼り付け。が、全ページ共通なので最終的にはcssJavaScriptをフッタに移動させます。

デザイン-レンチのアイコン-「フッタ」ボタン。

記事内目次を無料ブログに自動で追加するJavaScript~はてなブログ

→フッタ部分に<style></style><script type=”text/javascript”></script>部分を両方ともタグを付けたまま貼り付け。
→保存。
→全記事共通となるフッタ部分にcssJavaScriptを移動させたので、投稿編集内からはそれらを削除。

ちょと心配なのは各無料ブログのモバイルの扱い。設定画面にPC用とあったり、扱いが変わってくるんでなかろうなて点。

どちらが来ても読み込まれる場所に<style><script type=”text/javascript”>があれば同じように動くはずなんだけど。

その辺は無料ブログで実際に運営されてる方には釈迦に説法なので、適当にいじり倒して下さい。

また、本サイトの記事内目次には「閉じる」ボタンがあり非表示に切り替え可。これはcss修正だけで可能です。

美的センスも釈迦に説法なのでソース内<style></style>部分のcssを適当に修正して下さい。

コメント

タイトルとURLをコピーしました