ioerror

티스토리 목차(TOC) 만들기 - 3 본문

JavaScript

티스토리 목차(TOC) 만들기 - 3...

반응형

목록 페이지에서도 목차를 만들어보자

티스토리 목차(TOC) 만들기 - 2 에서는 entry 그러니까 글 내용만 목차를 만들었는데, 이 스킨의 왼쪽 공백이 좀 허전한 거 같아서 목차를 표시되게 하기로 했다.

글 내용의 목차처럼 해당 위치로 이동되게 할려다가, 그냥 글 보기로 이동되게 했다.

코드 마지막의 코드블록 관련된 것은 무슨 언어인지 코드 블록(code highlight)에 표시하기 위한 코드다.

 

코드

$(function() {
    let chapters = [];
    if ($('.chapters, .area_view h2, .area_view h3, .area_view h4, .list_content .tit_post').length > 0) {
        $('.chapters, .area_view h2, .area_view h3, .area_view h4, .list_content .tit_post').each(function(k, o) {
            $this = $(this);
            let text = $this.text();
            let link_url = '';
            let depth = $this.data('chapters_depth');
            depth = typeof(depth) == 'undefined' ? 0 : depth;
            if (depth == 0) {
                if ($(this).prop('tagName').toLowerCase() == 'h3' ||
                $(this).prop('tagName').toLowerCase() == 'strong'    
                ) {
                    link_url = $(this).parent().prop("href");
                    depth = 1;
                }
                if ($(this).prop('tagName').toLowerCase() == 'h4') {
                    depth = 2;
                }
            }
            let padding_left = depth * 8;
            padding_left = padding_left == 0 ? 3 : padding_left;
            let css_indent = '';
            css_indent = " style='padding-left:" + padding_left + "px' ";
            let regExp = /[\{\}\[\]\/?.,;:|\)*~`!^\+<>@\#$%&\\\=\(\'\"]/gi;
            let text_esc = text.replace(/\&lt\;/g, '<').replace(/(\&gt\;)/g, '>');
            text_esc = text_esc.replace(/<[^>]+>/gm, '');
            text_esc = text_esc.replace(/\&nbsp\;/g, '_').replace(regExp, '').replace(/ /g, '_');
            text_esc = text_esc + '_' + k;
            $this.data('chapter-key', k);
            $target_anchor = $('<a name="' + text_esc + '" class="chapters-target"></a>');
            $this.prepend($target_anchor);
            depth = depth > 3 ? 3 : depth;
            // 목록 페이지이면 TOC에서 바로 링크로 이동
            if ($(this).prop('tagName').toLowerCase() == 'strong' && link_url != '') {
                $('#chapters_lists > dl').append("<dd ><a href='" + link_url + "' class='chapters-item chapters-item-depth-" 
                                                + depth + "' tco_target='"+text_esc+"'" 
                                                + css_indent + ">" + text + "</a></dl>");
            }else{
                $('#chapters_lists > dl').append("<dd ><a href='#" + text_esc + "' "
                                                + "class='chapters-item chapters-item-depth-"+ depth + "' " 
                                                + css_indent + ">" + text + "</a></dl>");
            }
            chapters.push($target_anchor);
        });
        $('#chapters_lists').addClass("chapters_lists_on");
        if ($('.area_title').length > 0) {
            $('.area_title').after("<div class='area_chapters'>" + $('#chapters_lists').html() + "</div>");
        }
        if ($('.list_title').length > 0) {
            $('.list_title').after("<div class='area_chapters'>" + $('#chapters_lists').html() + "</div>");
        }
        
        let st_by_click = 0;    // 목차에서 클릭시 스크롤 이벤트로 인한 스타일 변경 방지
        $(document).on("click", ".chapters-item", function() {
            $("#chapters_lists > dl > dd").removeClass('chapter-on-scroll');
            $(this).parent().addClass('chapter-on-scroll');
            let chapter_anchor = $(this).prop("href").replace('#', '');
            st_by_click = 1;
        });

        $(window).scroll(function(event) {
            let scroll_y = $(this).scrollTop();
            let chapter_anchor;
            if (chapters.length == 0 || st_by_click == 1) {
                st_by_click = 0;
                return;
            }
            is_bottom_no_margin = 0;
            for (k in chapters) {
                let chpt = $(chapters[k]);
                try {
                    if (scroll_y >= chpt.offset().top) {
                        chapter_anchor = chpt.prop("name");
                    }
                } catch (e) {
                    break;
                }
            }
            if ($(".list_content .tit_post").length == 0) {
                $("#chapters_lists a[href='#" + chapter_anchor + "']").parent().addClass('chapter-on-scroll');
                $("#chapters_lists a").not("a[href='#" + chapter_anchor + "']").parent().removeClass('chapter-on-scroll');
            }else{
                $("#chapters_lists a[tco_target='" + chapter_anchor + "']").parent().addClass('chapter-on-scroll');
                $("#chapters_lists a").not("a[tco_target='" + chapter_anchor + "']").parent().removeClass('chapter-on-scroll');
            }
        });
    }
    // 코드 블록의 제목으로 코드의 언어를 표시하기, SCALA는 shell 스크립트로 표시
    if ($("pre[data-ke-type='codeblock']").length > 0) {
        $("pre[data-ke-type='codeblock']").each(function() {
            let pre_lang = $(this).data('ke-language').toUpperCase();
            pre_lang = pre_lang == 'SCALA' ? 'SHELL' : pre_lang;
            $(this).prepend("<span class='codeblock-lang'>" + pre_lang + "</span>");
        })
    }
});
반응형
Comments