0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

jqueryで目次を作るプログラム

Posted at

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;
	});
});
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?