├── .gitignore ├── demo.gif ├── bookmarklet.gif ├── package.json ├── src ├── gentoc.js ├── bookmark.js ├── loader.js └── awesome-toc.js ├── Gruntfile.js ├── test ├── test01.html ├── test06.html ├── test05.html ├── test02.html ├── test04.html ├── test07.html └── test03.html └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letiantian/awesome-toc/HEAD/demo.gif -------------------------------------------------------------------------------- /bookmarklet.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/letiantian/awesome-toc/HEAD/bookmarklet.gif -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "awesome-toc", 3 | "version": "0.1.0", 4 | "devDependencies": { 5 | "grunt": "~0.4.5", 6 | "grunt-contrib-uglify": "~0.5.0" 7 | } 8 | } -------------------------------------------------------------------------------- /src/gentoc.js: -------------------------------------------------------------------------------- 1 | $.awesome_toc({ 2 | autoDetectHeadings: true, 3 | enableToTopButton: true, 4 | displayNow: true, 5 | overlay: true, 6 | css: { 7 | fontSize: "14px", 8 | largeFontSize: "18px", 9 | lineHeight: "1.8", 10 | }, 11 | }); -------------------------------------------------------------------------------- /src/bookmark.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var addScript = function(src) { 3 | var s = document.createElement( 'script' ); 4 | s.setAttribute( 'src', src+'?'+'time='+Date.parse(new Date())); 5 | document.body.appendChild( s ); 6 | }; 7 | addScript('http://127.0.0.1:8000/build/loader.min.js'); 8 | })(); 9 | 10 | // javascript:(function(){var a=function(a){var b=document.createElement("script");b.setAttribute("src",a+"?time="+Date.parse(new Date)),document.body.appendChild(b)};a("http://127.0.0.1:8000/build/loader.min.js")})(); 11 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | uglify: { 6 | options: { 7 | banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' 8 | }, 9 | build: { 10 | files: [{ 11 | expand: true, 12 | cwd: 'src/', 13 | src: ['**/*.js'], 14 | dest: 'build/', 15 | ext: '.min.js' 16 | }] 17 | } 18 | } 19 | }); 20 | 21 | grunt.loadNpmTasks('grunt-contrib-uglify'); 22 | grunt.registerTask('default', ['uglify']); 23 | 24 | }; -------------------------------------------------------------------------------- /src/loader.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 4 | Loader = (function() { 5 | 6 | var load_cursor = 0; 7 | var load_queue; 8 | 9 | var loadFinished = function() { 10 | load_cursor ++; 11 | if (load_cursor < load_queue.length) { 12 | loadScript(); 13 | } 14 | } 15 | 16 | function loadError (oError) { 17 | console.error("The script " + oError.target.src + " is not accessible."); 18 | } 19 | 20 | 21 | var loadScript = function() { 22 | var url = load_queue[load_cursor]; 23 | var script = document.createElement('script'); 24 | script.type = "text/javascript"; 25 | 26 | if (script.readyState){ //IE 27 | script.onreadystatechange = function(){ 28 | if (script.readyState == "loaded" || 29 | script.readyState == "complete"){ 30 | script.onreadystatechange = null; 31 | loadFinished(); 32 | } 33 | }; 34 | } else { //Others 35 | script.onload = function(){ 36 | loadFinished(); 37 | }; 38 | } 39 | 40 | script.onerror = loadError; 41 | 42 | // script.src = url+'?'+'time='+Date.parse(new Date()); 43 | script.src = url; 44 | document.body.appendChild(script); 45 | }; 46 | 47 | var loadMultiScript = function(url_array) { 48 | load_cursor = 0; 49 | load_queue = url_array; 50 | loadScript(); 51 | } 52 | 53 | return { 54 | load: loadMultiScript, 55 | }; 56 | 57 | })(); 58 | 59 | jqueryUrl = 'http://127.0.0.1:8000/build/jquery-1.11.3.min.js'; 60 | tocUrl = 'http://127.0.0.1:8000/build/awesome-toc.min.js'; 61 | gentocUrl = 'http://127.0.0.1:8000/build/gentoc.min.js'; 62 | 63 | if (typeof(jQuery) == 'undefined' || typeof($) == 'undefined') { 64 | Loader.load([jqueryUrl, tocUrl, gentocUrl]); 65 | } else { 66 | Loader.load([tocUrl, gentocUrl]); 67 | } 68 | 69 | })(); 70 | -------------------------------------------------------------------------------- /test/test01.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | awesome toc - Hi, 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 62 | 63 | 64 | 65 | 66 |
67 |
Hi, awesome toc
68 |

What's it?

69 |

Go to https://github.com/someus/awesome-toc for more info.

70 |

Heading 1

71 |

Sub 1

72 |

Heading 2

73 |

Sub 1

74 |

Sub 2

75 |

Heading 3

76 |

Heading 4

77 |

Heading 5

78 |
79 | 80 | 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # awesome-toc 2 | 3 | awesome-toc是一个为网页生成目录的小工具,也支持回到顶部的功能。 4 | 5 | ![](./demo.gif) 6 | 7 | ## 用法 8 | 9 | ```js 10 | 11 | 22 | ``` 23 | 24 | 25 | ## 依赖 26 | jQuery。 27 | 28 | 在jquery 1.11和jquery 2.0中测试通过。 29 | 30 | ## 配置项 31 | 32 | | 属性 | 类型 | 说明 | 33 | | ------------- |-------------|--------| 34 | | css.fontSize | string | 目录项字体大小,"90%"、"16px" | 35 | | css.largeFontSize | string | 标题字体大小 | 36 | | css.fontColor | string | 基本的字体颜色,"#999"、"red" | 37 | | css.activeFontColor|string| 标题和当前active的目录项的字体颜色 | 38 | | css.lineHeight | string| 目录项的行高| 39 | | css.backgroundColor | string | 目录的背景颜色 | 40 | | css.zIndex | int | 目录的z-index | 41 | | title | string | 标题 | 42 | | windowMinWidth | int | 单位px。当窗口宽度低于此值时,不显示目录 | 43 | | sideBarId | string | 目录的id,最好带随机字符,以防和网页中id冲突/混淆 | 44 | | sideBarWidth | string | 目录的宽度 | 45 | | sideBarPrefix | string | 目录中生成的元素的class的前缀,
最好带随机字符,以防和网页中id冲突/混淆| 46 | | headingList | array of string | 识别哪些h*标签 | 47 | | enableToTopButton | bool |是否显示“返回顶部”的按钮| 48 | | enableToc | bool | 是否生成目录 | 49 | | overlay | bool | 是否以遮盖方式显示目录 | 50 | | autoDetectHeadings | bool | 是否自动探测使用哪些h*标签生成目录 | 51 | | contentId | string | 若不为空,则根据这个id对应的元素的内容生成目录 | 52 | | contentClass | string | 若不为空,则根据这个class对应
的第一个元素的内容生成目录 | 53 | | displayNow | bool| 是否立即显示目录| 54 | | topOffset | int | 单位px。有些网页的菜单是固定在顶部的,
占有一定空间,该属性值和菜单的高度应该一致。
如果设置的合理,点击目录项时,
页面滚动后,标题不会被覆盖 | 55 | | itemPrefix | string | 每个菜单项目的前缀,例如"- " | 56 | 57 | 58 | 59 | ## 小书签 60 | 61 | 首先开启本地的服务: 62 | ```plain 63 | $ cd awesome-toc 64 | $ python -m SimpleHTTPServer 65 | ``` 66 | 67 | 在浏览器中创建书签,url使用下面的内容: 68 | 69 | ```js 70 | javascript:(function(){var a=function(a){var b=document.createElement("script");b.setAttribute("src",a+"?time="+Date.parse(new Date)),document.body.appendChild(b)};a("http://127.0.0.1:8000/build/loader.min.js")})(); 71 | ``` 72 | 73 | 示例: 74 | 75 | ![](./bookmarklet.gif) 76 | 77 | 78 | ## 其他 79 | 80 | 界面设计上参考了[hexo-theme-next](https://github.com/iissnan/hexo-theme-next)。 81 | 82 | ## License 83 | 84 | MIT -------------------------------------------------------------------------------- /test/test06.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | awesome toc - Hi, 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 62 | 63 | 64 | 65 | 66 |
67 |
Hi, awesome toc
68 |

What's it?

69 |

Go to https://github.com/someus/awesome-toc for more info.

70 |

Heading 1

71 |

Sub 1

72 |

Heading 2

73 |

Sub 1

74 |

Sub 2

75 |

Heading 3

76 |

Heading 4

77 |

Heading 5

78 |
79 | 80 | 81 | 82 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /test/test05.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | awesome toc - Hi, 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 62 | 63 | 64 | 65 | 66 |
67 |
Hi, awesome toc
68 |

What's it?

69 |

Go to https://github.com/someus/awesome-toc for more info.

70 |

Heading 1

71 |

Sub 1

72 |

Heading 2

73 |

Sub 1

74 |

Sub 2

75 |

Heading 3

76 |

Heading 4

77 |

Heading 5

78 |
79 | 80 | 81 | 82 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /test/test02.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | awesome toc - Hi, 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 62 | 63 | 64 | 65 | 66 |
67 |
Hi, awesome toc
68 |

What's it?

69 |

Go to https://github.com/someus/awesome-toc for more info.

70 |

Heading 1

71 |

Sub 1

72 |

Heading 2

73 |

Sub 1

74 |

Sub 2

75 |

Heading 3

76 |

Heading 4

77 |

Heading 5

78 |
79 | 80 | 81 | 82 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /test/test04.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | awesome toc - Hi, 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 62 | 63 | 64 | 65 | 66 |
67 |
Hi, awesome toc
68 |

I am not a title in content

69 |
70 |

What's it?

71 |

Go to https://github.com/someus/awesome-toc for more info.

72 |

Heading 1

73 |

Sub 1

74 |

Heading 2

75 |

Sub 1

76 |

Sub 2

77 |

Heading 3

78 |

Heading 4

79 |

Heading 5

80 |
81 |
82 | 83 | 84 | 85 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /test/test07.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | awesome toc - Hi, 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 62 | 63 | 64 | 65 | 66 |
67 |
Hi, awesome toc
68 |

I am not a title in content

69 |
70 |

What's it?

71 |

Go to https://github.com/someus/awesome-toc for more info.

72 |

Heading 1

73 |

Sub 1

74 |

Heading 2

75 |

Sub 1

76 |

Sub 2

77 |

Heading 3

78 |

Heading 4

79 |

Heading 5

80 |
81 |
82 | 83 | 84 | 85 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /test/test03.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | awesome toc - Hi, 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 62 | 63 | 64 | 65 | 66 |
67 |
Hi, awesome toc
68 |

I am not a title in content

69 |
70 |

What's it?

71 |

Go to https://github.com/someus/awesome-toc for more info.

72 |

Heading 1

73 |

Sub 1

74 |

Heading 2

75 |

Sub 1

76 |

Sub 2

77 |

Heading 3

78 |

Heading 4

79 |

Heading 5

80 |
81 |
82 | 83 | 84 | 85 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /src/awesome-toc.js: -------------------------------------------------------------------------------- 1 | (function ($) { 2 | 3 | var DEBUG = false; 4 | 5 | var log = function(msg) { 6 | if (DEBUG) { 7 | console.log(msg); 8 | } 9 | }; 10 | 11 | var scrollVar = {}; 12 | 13 | var baseConfig = { 14 | css: { 15 | fontSize: "90%", 16 | largeFontSize: "120%", 17 | fontColor: "#999", // similar to grey 18 | activeFontColor: "#87daff", // similar to cyan 19 | lineHeight: "1.8", 20 | backgroundColor: "rgba(0,0,0,0.7)", 21 | zIndex: 999999, 22 | }, 23 | title: "文章目录", 24 | windowMinWidth: 100, // 单位px,窗口宽度小于该值时,不显示目录 25 | sideBarId: "sidebar-toc-Ik4D", 26 | sideBarWidth: "16em", 27 | sideBarPrefix: "sidebar-toc-Ik4D-", 28 | itemPrefix: "- ", 29 | headingList: ["h1", "h2", "h3", "h4", "h5", "h6"], 30 | enableToTopButton: true, 31 | enableToc: true, 32 | overlay: false, 33 | autoDetectHeadings: true, 34 | contentId: '', // 如果有定义,则从这里把h*提取出来 35 | contentClass: '', // 如果有定义,则从这里把h*提取出来。优先级低于contetnId 36 | displayNow: false, // 马上显示目录 37 | topOffset: 0, // px 38 | }; 39 | 40 | 41 | var addToggleSidebar = function() { 42 | var toggleDiv = document.createElement("div"); 43 | toggleDiv.setAttribute("id", baseConfig.sideBarId); 44 | toggleDiv.setAttribute("class", baseConfig.sideBarId); 45 | $("body").append(toggleDiv); 46 | $(toggleDiv).css({ 47 | "background": baseConfig.css.backgroundColor+" none repeat scroll 0 0", // similar to black 48 | "bottom": "0", 49 | "box-shadow": "0 2px 4px #000 inset", 50 | "position": "fixed", 51 | "right": "0", 52 | "top": "0", 53 | "width": "0", 54 | "z-index": ""+baseConfig.css.zIndex, 55 | "color": baseConfig.css.fontColor, 56 | "overflow": "auto", 57 | "font-size": baseConfig.css.fontSize, 58 | "text-align": "left", 59 | }); 60 | generateTableOfContents(); 61 | enableMenuScrollEvent(); 62 | }; 63 | 64 | 65 | var generateTableOfContents = function(documentRef) { 66 | var documentRef = documentRef || document; 67 | 68 | contentRef = documentRef.body; 69 | if (baseConfig.contentClass.length > 0) { 70 | contentRef = document.getElementsByClassName(baseConfig.contentClass)[0]; 71 | } 72 | if (baseConfig.contentId.length > 0) { 73 | contentRef = document.getElementById(baseConfig.contentId); 74 | } 75 | 76 | log(contentRef); 77 | 78 | var toc = documentRef.getElementById(baseConfig.sideBarId); 79 | 80 | var title = documentRef.createElement("div"); 81 | $(title).css({ 82 | "text-align": "center", 83 | "border-bottom-color": baseConfig.css.activeFontColor, 84 | "color": baseConfig.css.activeFontColor, 85 | "border-width": "0 0 1.5px 0", 86 | "border-style": "solid", 87 | "font-size": baseConfig.css.largeFontSize, 88 | "padding": "8px 0", 89 | }); 90 | 91 | title.textContent=baseConfig.title; 92 | toc.appendChild(title); 93 | 94 | var headingList = baseConfig.headingList; // 若为空,[].slice.call会报错 95 | if (headingList.length > 0) { 96 | var headings = [].slice.call(contentRef.querySelectorAll(headingList.join(", "))); 97 | headings.forEach(function (heading, index) { 98 | var anchor = documentRef.createElement("a"); 99 | anchor.setAttribute("name", "" + baseConfig.sideBarPrefix + index); 100 | anchor.setAttribute("id", "" + baseConfig.sideBarPrefix + index); 101 | heading.parentNode.insertBefore(anchor, heading); 102 | 103 | var link = documentRef.createElement("a"); 104 | link.setAttribute("href", "#"+ baseConfig.sideBarPrefix + index); 105 | link.textContent = baseConfig.itemPrefix + heading.textContent; // html标签会被去掉 106 | 107 | $(link).click(function(e){ 108 | $(this).parent().parent().find("a").css({"color": baseConfig.css.fontColor}); 109 | $(this).css({"color": baseConfig.css.activeFontColor}); 110 | var offsetTop = $($(this).attr("href")).offset().top - baseConfig.topOffset; 111 | disableMenuScrollEvent(); 112 | $('html, body').stop().animate( 113 | { 114 | scrollTop: offsetTop 115 | }, 116 | { 117 | duration: 300, 118 | complete: enableMenuScrollEvent, 119 | } 120 | ); 121 | e.preventDefault(); 122 | }); 123 | 124 | var div = documentRef.createElement("div"); 125 | $(div).css({ 126 | "padding-left": getIndent(heading.tagName.toLowerCase(), headingList, 20), 127 | "text-align": "left", 128 | }); 129 | 130 | div.appendChild(link); 131 | toc.appendChild(div); 132 | 133 | }); 134 | } 135 | 136 | 137 | $("#"+baseConfig.sideBarId+" div").css({ 138 | "margin": "0 12px", 139 | }); 140 | 141 | var linkSelector = "#"+baseConfig.sideBarId+" a, "; 142 | linkSelector += "#"+baseConfig.sideBarId+" a:hover, "; 143 | linkSelector += "#"+baseConfig.sideBarId+" a:visited"; 144 | // console.log(linkSelector); 145 | $(linkSelector).css({ 146 | "color": baseConfig.css.fontColor, 147 | "word-wrap": "break-word", 148 | "text-decoration": "none", 149 | "line-height": baseConfig.css.lineHeight, 150 | }); 151 | }; 152 | 153 | 154 | var getIndent = function(currentHeading, headingList, baseIndent) { 155 | var position = 0; 156 | for (; position < headingList.length; position++) { 157 | if (currentHeading !== headingList[position]) 158 | continue; 159 | else 160 | break; 161 | } 162 | if (position >= headingList.length) { 163 | position = 0; 164 | } 165 | 166 | return "" + (position*baseIndent) + "px"; 167 | }; 168 | 169 | 170 | var addToggleButton = function() { 171 | var toggleBtn = document.createElement("div"); 172 | toggleBtn.setAttribute('id', baseConfig.sideBarPrefix+'toggleBtn'); 173 | $(toggleBtn).css({ 174 | "background": "#222 none repeat scroll 0 0", 175 | "bottom": "55px", 176 | "cursor": "pointer", 177 | "height": "15px", 178 | "line-height": "0", 179 | "padding": "5px", 180 | "position": "fixed", 181 | "right": "50px", 182 | "width": "15px", 183 | "z-index": ""+(baseConfig.css.zIndex+1), 184 | 185 | }); 186 | 187 | for (var i=0; i<3; i++) { 188 | var line = document.createElement("span"); 189 | $(line).css({ 190 | "background": "#87daff none repeat scroll 0 0", 191 | "display": "inline-block", 192 | "height": "2px", 193 | "margin-top": "2px", 194 | "position": "relative", 195 | "vertical-align": "top", 196 | "width": "100%", 197 | }).appendTo(toggleBtn); 198 | } 199 | 200 | $("body").append(toggleBtn); 201 | 202 | toggleBtn.onclick = toggleButtonClickListener; 203 | }; 204 | 205 | 206 | var toggleButtonClickListener = function() { 207 | log("in toggleButtonClickListener: overlay " + baseConfig.overlay); 208 | if ($(window).width() < baseConfig.windowMinWidth) { 209 | return; 210 | } 211 | var sideBar = $("#"+baseConfig.sideBarId); 212 | // console.log(sideBar); 213 | 214 | if (sideBar.hasClass(baseConfig.sideBarPrefix+"active")) { // 隐藏 215 | sideBar.removeClass(baseConfig.sideBarPrefix+"active"); 216 | $(sideBar).animate({ 217 | "width": "0", 218 | }); 219 | if(!baseConfig.overlay) { 220 | $("body").animate({ 221 | "margin-right":"0", 222 | }); 223 | } 224 | 225 | } else { // 显示 226 | sideBar.addClass(baseConfig.sideBarPrefix+"active"); 227 | $(sideBar).animate({ 228 | "width": baseConfig.sideBarWidth, 229 | }); 230 | if(!baseConfig.overlay) { 231 | $("body").animate({ 232 | "margin-right":baseConfig.sideBarWidth, 233 | }); 234 | } 235 | 236 | } 237 | }; 238 | 239 | 240 | var addToTopButton = function() { 241 | var toTopBtn = document.createElement("div"); 242 | toTopBtn.setAttribute('id', baseConfig.sideBarPrefix+'toTopBtn'); 243 | $(toTopBtn).css({ 244 | "background": "#222 none repeat scroll 0 0", 245 | "bottom": "25px", 246 | "cursor": "pointer", 247 | "height": "15px", 248 | "line-height": "15px", 249 | "padding": "5px", 250 | "position": "fixed", 251 | "right": "50px", 252 | "width": "15px", 253 | "z-index": ""+(baseConfig.css.zIndex+1), 254 | "color": "#fff", 255 | "font-size": "16px", 256 | "text-align": "center", 257 | }).html(""); 258 | 259 | toTopBtn.onclick = function() { 260 | $("html, body").animate({scrollTop: 0}, 600); 261 | }; 262 | 263 | $("body").append(toTopBtn); 264 | }; 265 | 266 | var scrollHandler = function() { 267 | // log("scroll"); 268 | var fromTop = $(this).scrollTop()+10; 269 | 270 | var cur = scrollVar.scrollItems.map(function(){ 271 | if ($(this).offset().top < fromTop) 272 | return this; 273 | }); 274 | 275 | // Get the id of the current element 276 | cur = cur[cur.length-1]; 277 | var id = cur && cur.length ? cur[0].id : ""; 278 | 279 | if (scrollVar.lastId !== id) { 280 | scrollVar.lastId = id; 281 | scrollVar.menuItems.css({"color": baseConfig.css.fontColor}); 282 | scrollVar.menuItems.filter("[href=#"+id+"]").css({"color": baseConfig.css.activeFontColor}); 283 | } 284 | }; 285 | 286 | var disableMenuScrollEvent = function() { 287 | $(window).off( "scroll", scrollHandler ); 288 | }; 289 | 290 | var enableMenuScrollEvent = function() { 291 | $(window).scroll( scrollHandler ); 292 | }; 293 | 294 | var getScope = function() { 295 | var _scope = 'body'; 296 | if (baseConfig.contentClass.length > 0) { 297 | _scope = '.' + baseConfig.contentClass; 298 | } 299 | if (baseConfig.contentId.length > 0) { 300 | _scope = '#' + baseConfig.contentId; 301 | } 302 | return $(_scope); 303 | }; 304 | 305 | 306 | // 把第一个出现次数大于等于threshold的h*放入数组的第一个元素, 307 | // 之后的就看存不存在,存在就放进去最多放level个 308 | var getNiceHeadingTags = function(firstThreshold, level) { 309 | firstThreshold = firstThreshold || 1; 310 | level = level || 6; 311 | var allHeadingTags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']; 312 | scope = getScope(); 313 | var result = []; 314 | for (var idx=0; idx < allHeadingTags.length; idx++) { 315 | heading = allHeadingTags[idx]; 316 | if (result.length == 0){ 317 | if (scope.find(heading).length >= firstThreshold) { 318 | result.push(heading); 319 | } 320 | } else { 321 | if ($(heading).length >= 1) { 322 | result.push(heading); 323 | } 324 | } 325 | 326 | if (result.length >= level) break; 327 | } 328 | return result; 329 | }; 330 | 331 | var compactHeadingTags = function(headingList) { 332 | scope = getScope(); 333 | 334 | var result = []; 335 | for (var idx=0; idx < headingList.length; idx++) { 336 | heading = headingList[idx]; 337 | if (scope.find(heading).length > 0) { 338 | result.push(heading.toLowerCase()); 339 | } 340 | } 341 | return result; 342 | }; 343 | 344 | var isToggleBtnExist = function() { 345 | if ($('#'+baseConfig.sideBarPrefix+'toggleBtn').length == 0) 346 | return false; 347 | else 348 | return true; 349 | }; 350 | 351 | var isToTopBtnExist = function () { 352 | if ($('#'+baseConfig.sideBarPrefix+'toTopBtn').length == 0) 353 | return false; 354 | else 355 | return true; 356 | }; 357 | 358 | // 插件 359 | $.extend({ 360 | awesome_toc: function(config) { 361 | $.extend(true, baseConfig, config); 362 | 363 | baseConfig.contentId = baseConfig.contentId.trim(); 364 | baseConfig.contentClass = baseConfig.contentClass.trim(); 365 | 366 | if (baseConfig.autoDetectHeadings) { 367 | baseConfig.headingList = getNiceHeadingTags(); 368 | } 369 | 370 | baseConfig.headingList = compactHeadingTags(baseConfig.headingList); 371 | 372 | 373 | if (baseConfig.enableToc && !isToggleBtnExist()) { 374 | addToggleSidebar(); 375 | addToggleButton(); 376 | 377 | scrollVar.lastId = ''; 378 | scrollVar.sideBar = $("#"+baseConfig.sideBarId), 379 | scrollVar.menuItems = scrollVar.sideBar.find("a"), 380 | scrollVar.scrollItems = scrollVar.menuItems.map(function(){ 381 | var item = $($(this).attr("href")); 382 | if (item.length) { return item; } 383 | }); 384 | 385 | log(scrollVar); 386 | 387 | } 388 | 389 | if (baseConfig.enableToTopButton && !isToTopBtnExist()) { 390 | addToTopButton(); 391 | } 392 | 393 | if (baseConfig.displayNow) { 394 | toggleButtonClickListener(); 395 | } 396 | } 397 | }); 398 | 399 | 400 | })(jQuery); 401 | --------------------------------------------------------------------------------