CMSの記事で、目次が有ると良いんだけど、毎回管理画面で入力するのかアホくさいので、
Jquryで目次のul>liを作ってくれるプログラムを作ってみた。
使い方?
- 一番下のソースで適当にjsファイルを作って読み込む。toc.jsとでも。
※読み込む方法とかは調べてください。 - 設定値を環境に合わせる
- 動くwww
気付いたと思うけど、CSSは無いのでご自由にwww
設定値
最低限、下の2個だけ環境に合わせれば、動く。
他の設定値はソースに書いてる
contentSelecter = jqueryのselecter文字列
reg = 目次に置き換える部分の正規表現オブジェクト
ソース
jQuery(function($){
var toc = {
//コンテンツ部分のセレクター
contentSelecter :'.column-detail_content',
//目次HTMLを配置する目印
reg:new RegExp("\\[@目次@\]"),
//H3H4の時に文字列の前に入れるスペーサー
//H3の時は1回、h4の時は2回
spacer:' ',
//目次htmlのclass名を付ける
class:{
ul:'toc_warp',
li:'toc_li',
a:'toc_ancker',
},
//アンカーへスライドする時のオフセット値
ofsetTop:-20,
//作成した目次html
html :'',
//目次を作るのに必要なデータを格納
rows : [],
numType :[],
ids:{
h2:[],
h3:[],
h4:[]
},
/**
* 全体処理
*/
make:function(){
if(toc.isMakeToc()){
toc.getHeadingNo();
toc.setHeadingId();
toc.makeHtml();
toc.replace();
}
},
/**
* 目次部分をhtmlに埋め込む
*/
replace:function(){
var contDom = $(toc.contentSelecter);
html = contDom.html().replace(toc.reg, toc.html);
contDom.html(html);
},
/**
* 目次部分のhtmlを作る
*/
makeHtml:function(){
var contDom = $(toc.contentSelecter);
html = '';
for(var i = 0; i < toc.numType.length;i++){
type = toc.numType[i];
html = html +'<li class="'+toc.class.li+' level_'+type.level+'">';
html = html +'<a class="'+toc.class.a+'" href="#'+type.id+'">';
for(var s = 2; s < type.level; s++ ){
html = html + toc.spacer;
}
html = html + contDom.find('#'+type.id).text();
html = html +'</a>';
html = html +"</li>\n";
}
toc.html = '<ul class="'+toc.class.ul+'">'+html+'</ul>';
},
/**
* h2~h4のタグにIDを作る
* @return {[type]} [description]
*/
setHeadingId:function(){
var contDom = $(toc.contentSelecter);
var h2s = contDom.find('h2');
for(var i = 0; i < h2s.length;i++){
var h2Dom = $(h2s[i]);
var id = toc.ids.h2[i];
h2Dom.attr('id',id);
}
var h3s = contDom.find('h3');
for(var i = 0; i < h3s.length;i++){
var h3Dom = $(h3s[i]);
var id = toc.ids.h3[i];
h3Dom.attr('id',id);
}
var h4s = contDom.find('h4');
for(var i = 0; i < h4s.length;i++){
var h4Dom = $(h4s[i]);
var id = toc.ids.h4[i];
h4Dom.attr('id',id);
}
},
/**
* h2~h4までのタグを調べて、それぞれのidを作っていく
* もっとかっこいい書き方が有ると思うけど、非同期処理対策の為にカッコ悪い方法をしてる。
*/
getHeadingNo:function(){
cntentHtml = $(toc.contentSelecter).html();
var h2ary = cntentHtml.split('<h2');
for(var i = 1; i < h2ary.length;i++){
idName =('00'+i).slice(-2);
toc.ids.h2.push(idName);
toc.numType.push({
level :2,
id:idName
});
h2row = {};
h2row['h2Str'] = h2ary[i];
//h3で分割
h2row = toc._splitH3(h2row,idName);
toc.rows.push(h2row);
}
//できた後のデータを確認する場合はtoc.rowsをconsole.log;
// console.log(toc.rows);
},
//h3タグで分割する
_splitH3:function(h2row,h2Name){
if(h2row['h2Str'].indexOf('<h3') >= 0){
h2row['h3'] = [];
var h3ary = h2row['h2Str'].split('<h3');
for(var i3 = 1; i3 < h3ary.length;i3++){
idName =h2Name +'-'+('00'+i3).slice(-2);
toc.ids.h3.push(idName);
toc.numType.push({
level :3,
id:idName
});
h3row = {};
h3row['h3str'] = h3ary[i3];
//h4で分割
h3row = toc._splitH4(h3row,idName);
h2row['h3'].push(h3row);
}
}
return h2row;
},
//h4タグで分割する
_splitH4 : function(h3row,h3Name){
if(h3row['h3str'].indexOf('<h4') >= 0){
h3row['h4'] = [];
var h4ary = h3row['h3str'].split('<h4');
for(var i4 = 1; i4 < h4ary.length;i4++){
idName =h3Name +'-'+('00'+i4).slice(-2);
toc.ids.h4.push(idName);
toc.numType.push({
level :4,
id:idName
});
h4row = {};
h4row['h4str'] = h4ary[i4];
h3row['h4'].push(h4row);
}
}
return h3row;
},
/**
* 目次を作るか確認する。
* toc.regに入ってる正規表現にマッチするものが有れば作る。
* @return bool 作る場合はTRUE
*/
isMakeToc : function(){
var contentHtml = $(toc.contentSelecter).html();
var reg = toc.reg;
var isCot = contentHtml.match(reg);
if(isCot !== null){
return true;
}
return false;
}
};
toc.make();
//目次をクリックしたら、アンカーまでスライドする。
$(document).on('click', '.toc_ancker', function(){
var dom = $(this);
var targSelecter = dom.attr('href');
var targPos = $(targSelecter).offset().top;
targPos = targPos + toc.ofsetTop;
$("html,body").animate({scrollTop:targPos});
return false;
});
});