theme-default.js 5.4 KB

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