main.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. (function () {
  2. var elements = document.getElementsByTagName("pre");
  3. for(var i=0; i<elements.length; ++i){
  4. elements[i].classList.add("language-none");
  5. elements[i].classList.add("line-numbers");
  6. }
  7. // $('pre').addClass("language-none");
  8. // $('pre').addClass("line-numbers").css("white-space", "pre-wrap");
  9. }());
  10. window.onload = function(){
  11. }
  12. var sleep = function(time) {
  13. var startTime = new Date().getTime() + parseInt(time, 10);
  14. while(new Date().getTime() < startTime) {}
  15. };
  16. $(document).ready(function(){
  17. $("#sidebar ul .show").slideDown(200);
  18. registerSidebarClick();
  19. addTOC();
  20. addSequence();
  21. var has_sidebar = document.getElementById("sidebar_wrapper");
  22. if(has_sidebar){
  23. addSplitter();
  24. focusSidebar();
  25. }
  26. addAnchor();
  27. registerOnWindowResize(has_sidebar);
  28. hello();
  29. imageViewer();
  30. if(false){
  31. addPrintPage();
  32. }
  33. addTocMobileListener();
  34. addTabsetListener();
  35. });
  36. var sidebar_width = "300px";
  37. var sidebar_width_is_percent = false;
  38. try{
  39. if(isNaN(sidebar_width)){
  40. if(sidebar_width.endsWith("px")){
  41. sidebar_width = parseInt(sidebar_width.substr(0, sidebar_width.length-2));
  42. }else if(sidebar_width.endsWith("%")){
  43. sidebar_width = parseInt(sidebar_width.substr(0, sidebar_width.length-1));
  44. sidebar_width_is_percent = true;
  45. }else{
  46. sidebar_width = parseInt(sidebar_width);
  47. }
  48. }
  49. }catch(err){
  50. alert('plugin theme env sidebar_width value error, e.g. 300 or "300px" or "30%", not ' + sidebar_width);
  51. }
  52. function menu_show(show)
  53. {
  54. if(show){
  55. $("#menu_wrapper").addClass("m_menu_fixed");
  56. $("#menu").addClass("close");
  57. $("#to_top").addClass("m_hide");
  58. $("#sidebar_wrapper").show(100);
  59. $(".gutter").css("display", "block");
  60. focusSidebar();
  61. }else{
  62. $("#menu_wrapper").removeClass("m_menu_fixed");
  63. $("#menu").removeClass("close");
  64. $("#to_top").removeClass("m_hide");
  65. $("#sidebar_wrapper").hide(100);
  66. $(".gutter").css("display", "none");
  67. $("#article").css("width", "100%"); // recover set by splitter
  68. }
  69. }
  70. function menu_toggle(){
  71. if(!$("#sidebar_wrapper").is(':visible')){ // show
  72. menu_show(true);
  73. }else{ // hide
  74. menu_show(false);
  75. }
  76. }
  77. function registerSidebarClick(){
  78. function show_collapse_item(a_obj){
  79. var o_ul = a_obj.next();
  80. var collapsed = !o_ul.hasClass("show");
  81. if(collapsed){
  82. o_ul.slideDown(200);
  83. o_ul.removeClass("collapsed");
  84. o_ul.addClass("show");
  85. a_obj.children(".sub_indicator").removeClass("sub_indicator_collapsed");
  86. }else {
  87. o_ul.slideUp(200);
  88. o_ul.removeClass("show");
  89. o_ul.addClass("collapsed");
  90. a_obj.children(".sub_indicator").addClass("sub_indicator_collapsed");
  91. }
  92. }
  93. $("#menu").bind("click", function(e){
  94. menu_toggle();
  95. });
  96. $("#navbar_menu_btn").bind("click", function(e){
  97. $("#navbar_items").toggle();
  98. });
  99. var theme = getTheme();
  100. setTheme(theme);
  101. $("#themes").bind("click", function(e){
  102. var theme = getTheme();
  103. if(theme == "light"){
  104. setTheme("dark");
  105. }else {
  106. setTheme("light");
  107. }
  108. });
  109. $("#to_top").bind("click", function(e){
  110. window.scrollTo({
  111. top: 0,
  112. behavior: "smooth"
  113. });
  114. return false;
  115. });
  116. $("#sidebar ul li > a").bind("click", function(e){
  117. var is_click_indicator = $(e.target).hasClass("sub_indicator");
  118. var a_obj = $(this);
  119. if(a_obj.attr("href") == window.location.pathname){
  120. show_collapse_item(a_obj);
  121. return false;
  122. }
  123. show_collapse_item(a_obj);
  124. if(is_click_indicator){ // click indicator, only collapse, not jump to link
  125. return false;
  126. }
  127. var screenW = $(window).width();
  128. if(screenW > 900){
  129. return;
  130. }
  131. link_href = $(this).attr("href").split(location.host);
  132. if(link_href.length > 1){
  133. link_href = link_href[1];
  134. }else{
  135. link_href = link_href[0];
  136. }
  137. url_href = location.href.split(location.host)[1]
  138. let link_url = link_href.split("#")[0];
  139. let sub = $(this).next();
  140. var haveSub = false;
  141. if(sub && sub.prop("nodeName")){
  142. haveSub = sub.prop("nodeName").toLowerCase() == "ul";
  143. }
  144. if((link_href != decodeURIComponent(url_href) || !haveSub) && location.pathname == link_url){ // current page, and jump to header, close sidebar
  145. location.href = link_href;
  146. menu_toggle();
  147. }
  148. });
  149. }
  150. function hello(){
  151. console.log('\n\n\
  152. _ _ \n\
  153. | | | | \n\
  154. | |_ ___ ___ __| | ___ ___ \n\
  155. | __/ _ \\/ _ \\/ _` |/ _ \\ / __|\n\
  156. | || __/ __/ (_| | (_) | (__ \n\
  157. \\__\\___|\\___|\\__,_|\\___/ \\___|\n\
  158. \n\
  159. generated by teedoc: \n\
  160. \n\
  161. https://github.com/teedoc/teedoc\n\
  162. \n\n\n\
  163. ');
  164. }
  165. function addTOC(){
  166. if(!document.getElementById("toc_content"))
  167. return;
  168. tocbot.init({
  169. // Where to render the table of contents.
  170. tocSelector: '#toc_content',
  171. // Where to grab the headings to build the table of contents.
  172. contentSelector: '#article_content',
  173. // Which headings to grab inside of the contentSelector element.
  174. headingSelector: 'h1, h2, h3, h4',
  175. // For headings inside relative or absolute positioned containers within content.
  176. hasInnerContainers: true,
  177. });
  178. }
  179. function toChineseNumber(n) {
  180. if (!Number.isInteger(n) && n < 0) {
  181. throw Error('请输入自然数');
  182. }
  183. const digits = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
  184. const positions = ['', '十', '百', '千', '万', '十万', '百万', '千万', '亿', '十亿', '百亿', '千亿'];
  185. const charArray = String(n).split('');
  186. let result = '';
  187. let prevIsZero = false;
  188. //处理0 deal zero
  189. for (let i = 0; i < charArray.length; i++) {
  190. const ch = charArray[i];
  191. if (ch !== '0' && !prevIsZero) {
  192. result += digits[parseInt(ch)] + positions[charArray.length - i - 1];
  193. } else if (ch === '0') {
  194. prevIsZero = true;
  195. } else if (ch !== '0' && prevIsZero) {
  196. result += '零' + digits[parseInt(ch)] + positions[charArray.length - i - 1];
  197. }
  198. }
  199. //处理十 deal ten
  200. if (n < 100) {
  201. result = result.replace('一十', '十');
  202. }
  203. return result;
  204. }
  205. function addSequence(){
  206. if(!tocbot._parseContent){
  207. return;
  208. }
  209. var headings = tocbot._parseContent.selectHeadings(document.getElementById("article_content"), tocbot.options.headingSelector);
  210. var counth2=0, counth3=0, counth4=0;
  211. var html = document.getElementsByTagName("html")[0];
  212. var isZh = html.lang.substring(0, 2).toLowerCase() == "zh";
  213. for(var i=0; i<html.classList.length; ++i){
  214. if(html.classList[i] == "heading_no_counter"){
  215. return;
  216. }
  217. }
  218. var headerJoiner = ".";
  219. for(var i=0; i<headings.length; ++i){
  220. var headerEnd = ". ";
  221. if(headings[i].tagName == "H1"){
  222. counth2 = 0;
  223. continue;
  224. }
  225. if(headings[i].tagName == "H2"){
  226. counth2 += 1;
  227. counth3 = 0;
  228. var counts = [counth2];
  229. if (isZh){
  230. var counts = counts.map(toChineseNumber);
  231. headerEnd = "、";
  232. }
  233. } else if(headings[i].tagName == "H3"){
  234. counth3 += 1;
  235. counth4 = 0;
  236. var counts = [counth2, counth3];
  237. } else if(headings[i].tagName == "H4"){
  238. counth4 += 1;
  239. var counts = [counth2, counth3, counth4];
  240. }
  241. var seq = counts.join(headerJoiner) + headerEnd
  242. headings[i].insertAdjacentHTML('afterbegin', '<span class="sequence">' + seq + '</span>');
  243. }
  244. }
  245. function getSplitter(){
  246. var sizes = localStorage.getItem("splitter_w");
  247. if(sizes){
  248. try
  249. {
  250. sizes = JSON.parse(sizes);
  251. }
  252. catch(err)
  253. {
  254. sizes = false;
  255. }
  256. }
  257. if(!sizes){
  258. var screenW = $(window).width();
  259. var split_w = 0;
  260. if(!sidebar_width_is_percent){
  261. split_w = parseInt(sidebar_width/screenW*100);
  262. }else{
  263. split_w = sidebar_width;
  264. }
  265. sizes = [split_w, 100-split_w];
  266. setSplitter(sizes);
  267. }
  268. return sizes;
  269. }
  270. function setSplitter(sizes){
  271. localStorage.setItem("splitter_w", JSON.stringify(sizes));
  272. }
  273. var hasSplitter = false;
  274. function createSplitter(){
  275. var split = Split(["#sidebar_wrapper", "#article"],{
  276. gutterSize: 3,
  277. gutterAlign: 'start',
  278. minSize: 200,
  279. elementStyle: function (dimension, size, gutterSize) {
  280. return {
  281. 'width': 'calc(' + size + '% - ' + gutterSize + 'px)',
  282. }
  283. },
  284. onDragEnd: function (sizes) {
  285. setSplitter(sizes)
  286. },
  287. });
  288. hasSplitter = true;
  289. var screenW = $(window).width();
  290. var sizes = getSplitter();
  291. split_w = parseInt(sizes[0]);
  292. if(isNaN(split_w) || (split_w + 20) >= screenW){
  293. if(!sidebar_width_is_percent){
  294. split_w = parseInt(sidebar_width/screenW*100);
  295. }else{
  296. split_w = sidebar_width;
  297. }
  298. }
  299. split.setSizes([split_w, 100 - split_w]);
  300. $(".gutter").append('<div class="gutter_icon"></div>');
  301. $(".gutter").hover(function(){
  302. $(".gutter").css("width", "10px");
  303. $(".gutter_icon").css("width", "10px");
  304. },function(){
  305. $(".gutter").css("width", "3px");
  306. $(".gutter_icon").css("width", "3px");
  307. });
  308. }
  309. function addSplitter(){
  310. var screenW = $(window).width();
  311. if(screenW > 900)
  312. {
  313. createSplitter();
  314. }
  315. }
  316. function registerOnWindowResize(has_sidebar){
  317. window.onresize = function(){
  318. var screenW = $(window).width();
  319. if(!has_sidebar){
  320. return;
  321. }
  322. if(screenW < 900){
  323. $("#sidebar_wrapper").removeAttr("style");
  324. if($("#menu").hasClass("close")){
  325. $("#sidebar_wrapper").css("display", "block");
  326. }
  327. $(".gutter").css("display", "none");
  328. $("#article").css("width", "100%");
  329. }else{
  330. if(!hasSplitter){
  331. createSplitter();
  332. }
  333. if($("#sidebar_wrapper").css("display") != "none"){
  334. $(".gutter").css("display", "block");
  335. }
  336. }
  337. }
  338. }
  339. function focusSidebar(){
  340. var windowH = window.innerHeight;
  341. var active = $("#sidebar .active")[0];
  342. if(!active)
  343. return;
  344. var offset = active.offsetTop;
  345. if(offset > windowH/2){
  346. $("#sidebar .show").scrollTop(offset);
  347. }
  348. }
  349. function imageViewer(){
  350. var content_e = document.getElementById("content_body");
  351. if(!content_e){
  352. content_e = document.getElementById("page_wrapper");
  353. }
  354. const gallery = new Viewer(content_e);
  355. }
  356. function addAnchor(){
  357. $("#content_body h2, #content_body h3, #content_body h4, #content_body h5").each(function(){
  358. if($(this).attr("id")){
  359. $(this).append('<a class="anchor" href="#'+ $(this).attr("id") +'">#</a>');
  360. }
  361. });
  362. }
  363. function rerender(){
  364. Prism.highlightAll();
  365. }
  366. function addPrintPage(){
  367. if(!$("#article_info_right")){
  368. return;
  369. }
  370. $("#article_info_right").append('<div id="print_page"></div>');
  371. var beforePrint = function(){
  372. // update style changed by js:
  373. $("#article").css("width", "100%");
  374. // rerender for proper output
  375. rerender();
  376. }
  377. var afterPrint = function() {
  378. // location.reload();
  379. }
  380. if (window.matchMedia) {
  381. var mediaQueryList = window.matchMedia('print');
  382. mediaQueryList.addListener(function(mql) {
  383. if (mql.matches) {
  384. beforePrint();
  385. } else {
  386. afterPrint();
  387. }
  388. });
  389. }
  390. window.onbeforeprint = beforePrint;
  391. window.onafterprint = afterPrint;
  392. $("#print_page").click(function(){
  393. window.print();
  394. });
  395. }
  396. function addTocMobileListener(){
  397. $("#toc_btn").click(function(){
  398. if($("#toc_wrapper").hasClass("show")){
  399. $("#toc_wrapper").removeClass("show");
  400. }else{
  401. $("#toc_wrapper").addClass("show");
  402. }
  403. });
  404. $("#toc_wrapper").click(function(){
  405. if($("#toc_btn").is(":visible")){
  406. $("#toc_wrapper").removeClass("show");
  407. }
  408. });
  409. }
  410. function addTabsetListener(){
  411. $(".tabset-tab-label").on("click", function(){
  412. let this_obj = $(this);
  413. // already active, do nothing
  414. if(this_obj.hasClass("tabset-tab-active")){
  415. return;
  416. }
  417. // remove all active tabset-tab-active and tabset-text-active class from all have class that startswith tabset-id-,
  418. // then add active class to the same idx tab-label and tab-text
  419. let tabset_id = null;
  420. let same_id_tabsets = [];
  421. let old_idx = this_obj.parent().find(".tabset-tab-active").attr("idx");
  422. let new_idx = this_obj.attr("idx");
  423. let tabset_obj = this_obj.parent().parent().parent();
  424. tabset_obj.attr("class").split(' ').forEach(function(item){
  425. if(item.startsWith("tabset-id-")){
  426. tabset_id = item;
  427. }
  428. });
  429. if(!tabset_id){
  430. same_id_tabsets = [tabset_obj[0]]; // to DOM element
  431. }else{
  432. same_id_tabsets = document.getElementsByClassName(tabset_id);
  433. }
  434. for (let tabset of same_id_tabsets) {
  435. console.log(tabset);
  436. let tab_labels = tabset.getElementsByClassName("tabset-tab-label");
  437. tab_labels[old_idx].classList.remove("tabset-tab-active");
  438. tab_labels[new_idx].classList.add("tabset-tab-active");
  439. let tab_texts = tabset.getElementsByClassName("tabset-text");
  440. tab_texts[old_idx].classList.remove("tabset-text-active");
  441. tab_texts[new_idx].classList.add("tabset-text-active");
  442. }
  443. });
  444. }