theme-default.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. document.addEventListener('DOMContentLoaded', function() {
  2. const updateHash = function (id) {
  3. window.location.hash = `#${id}`;
  4. };
  5. const throttledUpdateHash = _.throttle(updateHash, 200);
  6. const observer = new IntersectionObserver((entries) => {
  7. // If intersectionRatio is 0, the target is out of view
  8. // and we do not need to do anything.
  9. if (entries[0].intersectionRatio <= 0) {
  10. return;
  11. }
  12. throttledUpdateHash(entries[0].target.id);
  13. }, {
  14. rootMargin: '0px 0px -12% 0px', // shrink the intersection viewport
  15. threshold: 1.0, // trigger at 100% visibility
  16. });
  17. function makeObserver(elem) {
  18. return observer.observe(elem);
  19. }
  20. // find all links in the menu
  21. const menuItems = document.querySelectorAll('#toc a[href]');
  22. // make observers for those links
  23. Array.from(menuItems).forEach((aTag) => {
  24. const title = document.querySelector(aTag.getAttribute('href'));
  25. makeObserver(title);
  26. });
  27. const navButton = document.getElementById('nav-button');
  28. const menuWrapper = document.querySelector('.tocify-wrapper');
  29. function toggleSidebar() {
  30. if (menuWrapper) {
  31. menuWrapper.classList.toggle('open');
  32. navButton.classList.toggle('open');
  33. }
  34. }
  35. function closeSidebar() {
  36. if (menuWrapper) {
  37. menuWrapper.classList.remove('open');
  38. navButton.classList.remove('open');
  39. }
  40. }
  41. navButton.addEventListener('click', toggleSidebar);
  42. window.hljs.highlightAll();
  43. const wrapper = document.getElementById('toc');
  44. // https://jets.js.org/
  45. window.jets = new window.Jets({
  46. // *OR - Selects elements whose values contains at least one part of search substring
  47. searchSelector: '*OR',
  48. searchTag: '#input-search',
  49. contentTag: '#toc li',
  50. didSearch: function(term) {
  51. wrapper.classList.toggle('jets-searching', String(term).length > 0)
  52. },
  53. // map these accent keys to plain values
  54. diacriticsMap: {
  55. a: 'ÀÁÂÃÄÅàáâãäåĀāąĄ',
  56. c: 'ÇçćĆčČ',
  57. d: 'đĐďĎ',
  58. e: 'ÈÉÊËèéêëěĚĒēęĘ',
  59. i: 'ÌÍÎÏìíîïĪī',
  60. l: 'łŁ',
  61. n: 'ÑñňŇńŃ',
  62. o: 'ÒÓÔÕÕÖØòóôõöøŌō',
  63. r: 'řŘ',
  64. s: 'ŠšśŚ',
  65. t: 'ťŤ',
  66. u: 'ÙÚÛÜùúûüůŮŪū',
  67. y: 'ŸÿýÝ',
  68. z: 'ŽžżŻźŹ'
  69. }
  70. });
  71. function hashChange() {
  72. const currentItems = document.querySelectorAll('.tocify-subheader.visible, .tocify-item.tocify-focus');
  73. Array.from(currentItems).forEach((elem) => {
  74. elem.classList.remove('visible', 'tocify-focus');
  75. });
  76. const currentTag = document.querySelector(`a[href="${window.location.hash}"]`);
  77. if (currentTag) {
  78. const parent = currentTag.closest('.tocify-subheader');
  79. if (parent) {
  80. parent.classList.add('visible');
  81. }
  82. const siblings = currentTag.closest('.tocify-header');
  83. if (siblings) {
  84. Array.from(siblings.querySelectorAll('.tocify-subheader')).forEach((elem) => {
  85. elem.classList.add('visible');
  86. });
  87. }
  88. currentTag.parentElement.classList.add('tocify-focus');
  89. // wait for dom changes to be done
  90. setTimeout(() => {
  91. currentTag.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' });
  92. // only close the sidebar on level-2 events
  93. if (currentTag.parentElement.classList.contains('level-2')) {
  94. closeSidebar();
  95. }
  96. }, 1500);
  97. }
  98. }
  99. const languages = JSON.parse(document.body.getAttribute('data-languages'));
  100. // if there is no language use the first one
  101. const currentLanguage = window.localStorage.getItem('language') || languages[0];
  102. const languageStyle = document.getElementById('language-style');
  103. const langSelector = document.querySelectorAll('.lang-selector button.lang-button');
  104. function setActiveLanguage(newLanguage) {
  105. window.localStorage.setItem('language', newLanguage);
  106. if (!languageStyle) {
  107. return;
  108. }
  109. const newStyle = languages.map((language) => {
  110. return language === newLanguage
  111. // the current one should be visible
  112. ? `body .content .${language}-example code { display: block; }`
  113. // the inactive one should be hidden
  114. : `body .content .${language}-example code { display: none; }`;
  115. }).join(`\n`);
  116. Array.from(langSelector).forEach((elem) => {
  117. elem.classList.toggle('active', elem.getAttribute('data-language-name') === newLanguage);
  118. });
  119. const activeHash = window.location.hash.slice(1);
  120. languageStyle.innerHTML = newStyle;
  121. setTimeout(() => {
  122. updateHash(activeHash);
  123. }, 200);
  124. }
  125. setActiveLanguage(currentLanguage);
  126. Array.from(langSelector).forEach((elem) => {
  127. elem.addEventListener('click', () => {
  128. const newLanguage = elem.getAttribute('data-language-name');
  129. setActiveLanguage(newLanguage);
  130. });
  131. });
  132. window.addEventListener('hashchange', hashChange, false);
  133. hashChange();
  134. });