main.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /**
  2. * Utils
  3. */
  4. // Load and run script via AJAX
  5. //
  6. const loadScript = (source, beforeEl, async = true, defer = true) => {
  7. return new Promise((resolve, reject) => {
  8. let script = document.createElement('script');
  9. const prior = beforeEl || document.getElementsByTagName('script')[0];
  10. script.async = async;
  11. script.defer = defer;
  12. function onloadHander(_, isAbort) {
  13. if (isAbort || !script.readyState || /loaded|complete/.test(script.readyState)) {
  14. script.onload = null;
  15. script.onreadystatechange = null;
  16. script = undefined;
  17. if (isAbort) {
  18. reject();
  19. } else {
  20. resolve();
  21. }
  22. }
  23. }
  24. script.onload = onloadHander;
  25. script.onreadystatechange = onloadHander;
  26. script.src = source;
  27. prior.parentNode.insertBefore(script, prior);
  28. });
  29. }
  30. // Throttle
  31. //
  32. const throttle = (callback, limit) => {
  33. let timeoutHandler = null;
  34. return () => {
  35. if (timeoutHandler == null) {
  36. timeoutHandler = setTimeout(() => {
  37. callback();
  38. timeoutHandler = null;
  39. }, limit);
  40. }
  41. }
  42. }
  43. // addEventListener Helper
  44. //
  45. const listen = (ele, e, callback) => {
  46. if (document.querySelector(ele) !== null) {
  47. document.querySelector(ele).addEventListener(e, callback);
  48. }
  49. }
  50. /**
  51. * Functions
  52. */
  53. // Set inner width into CSS variable
  54. //
  55. function setVw() {
  56. let vw = document.documentElement.clientWidth / 100;
  57. document.documentElement.style.setProperty('--vw', `${vw}px`);
  58. }
  59. setVw();
  60. window.addEventListener('resize', setVw);
  61. // ToC toggle
  62. //
  63. function toggleToc() {
  64. const toc = document.getElementById('toc');
  65. if (toc.style.display === 'block') {
  66. toc.style.display = 'none';
  67. } else {
  68. toc.style.display = 'block';
  69. }
  70. }
  71. listen ("#toc-btn", "click", toggleToc);
  72. // Scroll to Top
  73. //
  74. const scrollBtn = document.getElementById('scroll-top-btn');
  75. const btnVisibility = () => {
  76. if ((window.scrollY > 400) && (window.innerWidth >= 1590)) {
  77. scrollBtn.style.display = "block";
  78. } else {
  79. scrollBtn.style.display = "none";
  80. }
  81. };
  82. scrollBtn.addEventListener("click", () => {
  83. window.scrollTo(0,0);
  84. });
  85. // Anchor points for list page
  86. //
  87. document.querySelectorAll('.post-year').forEach((ele)=> {
  88. ele.addEventListener('click', () => {
  89. window.location.hash = '#' + ele.id;
  90. });
  91. });
  92. // Load Comments
  93. //
  94. let commentsLoaded = false;
  95. let comments = document.getElementById('comments');
  96. let commentsLoader = document.getElementById('comments-loader');
  97. const valineJsUrl = 'https://cdn.jsdelivr.net/npm/valine@1.4.18/dist/Valine.min.js';
  98. const loadComments = () => {
  99. loadScript(valineJsUrl).then(() => {
  100. new Valine({
  101. el: '#comments',
  102. appId: 'QfBLso0johYg7AXtV9ODU6FC-gzGzoHsz',
  103. appKey: 'J1tpEEsENa48aLVsPdvwMP14',
  104. placeholder: '说点什么吧'
  105. });
  106. commentsLoader.style.display = 'none';
  107. }, () => {
  108. console.log('Failed to Load Valine.min.js');
  109. });
  110. }
  111. // Load comments if the window is not scrollable
  112. if ((comments !== null) && (comments.offsetTop < window.innerHeight)) {
  113. commentsLoader.style.display = 'block';
  114. loadComments();
  115. commentsLoaded = true;
  116. }
  117. window.addEventListener('scroll', throttle(() => {
  118. if ((comments !== null) && (commentsLoaded == false)) {
  119. if (window.pageYOffset + window.innerHeight > comments.offsetTop) {
  120. commentsLoader.style.display = 'block';
  121. loadComments();
  122. commentsLoaded = true;
  123. }
  124. }
  125. if (scrollBtn !== null) {
  126. btnVisibility();
  127. }
  128. }, 150));