895 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			HTML
		
	
	
	
			
		
		
	
	
			895 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			HTML
		
	
	
	
| {{ if .Site.Params.custom_js }}
 | |
| {{ range .Site.Params.custom_js }}
 | |
|   {{ $custom_template := resources.Get . }}
 | |
|   {{ if $custom_template }}
 | |
|     {{ $custom_js := $custom_template | resources.Minify | resources.Fingerprint }}
 | |
|     <script defer src="{{ $custom_js.RelPermalink }}"></script>
 | |
|   {{ end }}
 | |
| {{ end }}
 | |
| {{ end }}
 | |
| 
 | |
| {{ $fuse := resources.Get "js/fuse.min.js" | resources.Fingerprint }}
 | |
| <script defer src="{{ $fuse.RelPermalink }}"></script>
 | |
| {{ $getParents := resources.Get "js/helper/getParents.js" | resources.Minify | resources.Fingerprint }}
 | |
| <script defer src="{{ $getParents.RelPermalink }}"></script>
 | |
| {{ $fadeinout := resources.Get "js/helper/fadeinout.js" | resources.Minify | resources.Fingerprint }}
 | |
| <script defer src="{{ $fadeinout.RelPermalink }}"></script>
 | |
| {{ $closest := resources.Get "js/helper/closest.js" | resources.Minify }}
 | |
| <script defer src="{{ $closest.RelPermalink }}"></script>
 | |
|   
 | |
| <script>
 | |
|   "use strict";
 | |
| 
 | |
|   // ========================== poiyfill ==========================
 | |
|   // forEach
 | |
|   if (window.NodeList && !NodeList.prototype.forEach) {
 | |
|     NodeList.prototype.forEach = Array.prototype.forEach;
 | |
|   }
 | |
| 
 | |
|   // includes
 | |
|   if (!String.prototype.includes) {
 | |
|     String.prototype.includes = function (search, start) {
 | |
|       'use strict';
 | |
| 
 | |
|       if (search instanceof RegExp) {
 | |
|         throw TypeError('first argument must not be a RegExp');
 | |
|       }
 | |
|       if (start === undefined) { start = 0; }
 | |
|       return this.indexOf(search, start) !== -1;
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   // append
 | |
|   Document.prototype.append = Element.prototype.append = function append() {
 | |
|     this.appendChild(_mutation(arguments));
 | |
|   };
 | |
|   function _mutation(nodes) {
 | |
|     if (!nodes.length) {
 | |
|       throw new Error('DOM Exception 8');
 | |
|     } else if (nodes.length === 1) {
 | |
|       return typeof nodes[0] === 'string' ? document.createTextNode(nodes[0]) : nodes[0];
 | |
|     } else {
 | |
|       var
 | |
|       fragment = document.createDocumentFragment(),
 | |
|       length = nodes.length,
 | |
|       index = -1,
 | |
|       node;
 | |
| 
 | |
|       while (++index < length) {
 | |
|         node = nodes[index];
 | |
| 
 | |
|         fragment.appendChild(typeof node === 'string' ? document.createTextNode(node) : node);
 | |
|       }
 | |
| 
 | |
|       return fragment;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // startsWith
 | |
|   if (!String.prototype.startsWith) {
 | |
|     String.prototype.startsWith = function (searchString, position) {
 | |
|       position = position || 0;
 | |
|       return this.indexOf(searchString, position) === position;
 | |
|     };
 | |
|   }
 | |
|   // ===============================================================
 | |
| 
 | |
| 
 | |
|   document.addEventListener('DOMContentLoaded', function () {
 | |
|     // ============================ tab ============================
 | |
|     document.querySelectorAll('.tab') ? 
 | |
|     document.querySelectorAll('.tab').forEach(function(elem, idx) {
 | |
|       var containerId = elem.getAttribute('id');
 | |
|       var containerElem = elem;
 | |
|       var tabLinks = elem.querySelectorAll('.tab__link');
 | |
|       var tabContents = elem.querySelectorAll('.tab__content');
 | |
|       var ids = [];
 | |
| 
 | |
|       tabLinks && tabLinks.length > 0 ?
 | |
|       tabLinks.forEach(function(link, index, self) {
 | |
|         link.onclick = function(e) {
 | |
|           for (var i = 0; i < self.length; i++) {
 | |
|             if (index === parseInt(i, 10)) {
 | |
|               if (!self[i].classList.contains('active')) {
 | |
|                 self[i].classList.add('active');
 | |
|                 tabContents[i].style.display = 'block';
 | |
|               }
 | |
|             } else {
 | |
|               self[i].classList.remove('active');
 | |
|               tabContents[i].style.display = 'none';
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }) : null;
 | |
|     }) : null;
 | |
|     // =============================================================
 | |
| 
 | |
| 
 | |
|     // ========================== codetab ==========================
 | |
|     document.querySelectorAll('.codetab') ? 
 | |
|     document.querySelectorAll('.codetab').forEach(function(elem, idx) {
 | |
|       var containerId = elem.getAttribute('id');
 | |
|       var containerElem = elem;
 | |
|       var codetabLinks = elem.querySelectorAll('.codetab__link');
 | |
|       var codetabContents = elem.querySelectorAll('.codetab__content');
 | |
|       var ids = [];
 | |
| 
 | |
|       codetabLinks && codetabLinks.length > 0 ?
 | |
|       codetabLinks.forEach(function(link, index, self) {
 | |
|         link.onclick = function(e) {
 | |
|           for (var i = 0; i < self.length; i++) {
 | |
|             if (index === parseInt(i, 10)) {
 | |
|               if (!self[i].classList.contains('active')) {
 | |
|                 self[i].classList.add('active');
 | |
|                 codetabContents[i].style.display = 'block';
 | |
|               }
 | |
|             } else {
 | |
|               self[i].classList.remove('active');
 | |
|               codetabContents[i].style.display = 'none';
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }) : null;
 | |
|     }) : null;
 | |
|     // =============================================================
 | |
| 
 | |
| 
 | |
|     // ========================= go to top =========================
 | |
|     var gttBtn = document.getElementById("gtt");
 | |
|     gttBtn.style.display = "none";
 | |
|     gttBtn.addEventListener('click', function () {
 | |
|       if (window.document.documentMode) {
 | |
|         document.documentElement.scrollTop = 0;
 | |
|       } else {
 | |
|         scrollToTop(250);
 | |
|       }
 | |
|     });
 | |
| 
 | |
|     function scrollToTop(scrollDuration) {
 | |
|       var scrollStep = -window.scrollY / (scrollDuration / 15);
 | |
|       var scrollInterval = setInterval(function () {
 | |
|         if (window.scrollY != 0) {
 | |
|           window.scrollBy(0, scrollStep);
 | |
|         }
 | |
|         else clearInterval(scrollInterval);
 | |
|       }, 15);
 | |
|     }
 | |
| 
 | |
|     var scrollFunction = function () {
 | |
|       if (document.body.scrollTop > 250 || document.documentElement.scrollTop > 250) {
 | |
|         gttBtn.style.display = "block";
 | |
|       } else {
 | |
|         gttBtn.style.display = "none";
 | |
|       }
 | |
|     }
 | |
|     // ============================================================
 | |
| 
 | |
| 
 | |
|     // ========================== expand ==========================
 | |
|     var expandBtn = document.querySelectorAll('.expand__button');
 | |
| 
 | |
|     for (let i = 0; i < expandBtn.length; i++) {
 | |
|       expandBtn[i].addEventListener("click", function () {
 | |
|         var content = this.nextElementSibling;
 | |
|         if (content.style.maxHeight) {
 | |
|           content.style.maxHeight = null;
 | |
|           this.querySelector('svg').classList.add('expand-icon__right');
 | |
|           this.querySelector('svg').classList.remove('expand-icon__down');
 | |
|         } else {
 | |
|           content.style.maxHeight = content.scrollHeight + "px";
 | |
|           this.querySelector('svg').classList.remove('expand-icon__right');
 | |
|           this.querySelector('svg').classList.add('expand-icon__down');
 | |
|         }
 | |
|       });
 | |
|     }
 | |
|     // ============================================================
 | |
| 
 | |
| 
 | |
|     // ========================== scroll ==========================
 | |
|     var lastScrollTop = window.pageYOffset || document.documentElement.scrollTop;
 | |
|     var tocElem = document.querySelector('.toc');
 | |
|     var tableOfContentsElem = tocElem ? tocElem.querySelector('#TableOfContents') : null;
 | |
|     var toggleTocElem = document.getElementById('toggle-toc');
 | |
|     var singleContentsElem = document.querySelector('.single__contents');
 | |
|     var navbar = document.querySelector('.navbar');
 | |
|     var tocFlexbox = document.querySelector('.toc__flexbox');
 | |
|     var tocFlexboxOuter = document.querySelector('.toc__flexbox--outer');
 | |
|     var expandContents = document.querySelectorAll('.expand__content');
 | |
|     var boxContents = document.querySelectorAll('.box');
 | |
|     var notAllowedTitleIds = null;
 | |
| 
 | |
|     // tab
 | |
|     singleContentsElem && singleContentsElem.querySelectorAll(".tab") ?
 | |
|     singleContentsElem.querySelectorAll(".tab").forEach(function (elem) {
 | |
|       elem.querySelectorAll("h1, h2, h3, h4, h5, h6").forEach(function (element) {
 | |
|         notAllowedTitleIds = Array.isArray(notAllowedTitleIds) ?
 | |
|           notAllowedTitleIds.concat(element.getAttribute('id')) :
 | |
|           [element.getAttribute('id')];
 | |
|       });
 | |
|     }) : null;
 | |
| 
 | |
|     // expand
 | |
|     expandContents ? expandContents.forEach(function(elem) {
 | |
|       elem.querySelectorAll("h1, h2, h3, h4, h5, h6").forEach(function (element) {
 | |
|         notAllowedTitleIds = Array.isArray(notAllowedTitleIds) ?
 | |
|           notAllowedTitleIds.concat(element.getAttribute('id')) :
 | |
|           [element.getAttribute('id')];
 | |
|       });
 | |
|     }) : null;
 | |
| 
 | |
|     // box
 | |
|     boxContents ? boxContents.forEach(function(elem) {
 | |
|       elem.querySelectorAll("h1, h2, h3, h4, h5, h6").forEach(function (element) {
 | |
|         notAllowedTitleIds = Array.isArray(notAllowedTitleIds) ?
 | |
|           notAllowedTitleIds.concat(element.getAttribute('id')) :
 | |
|           [element.getAttribute('id')];
 | |
|       });
 | |
|     }) : null;
 | |
| 
 | |
|     
 | |
|     window.onscroll = function () {
 | |
|       scrollFunction();
 | |
|       
 | |
|       var st = window.pageYOffset || document.documentElement.scrollTop;
 | |
|       if (st > lastScrollTop) { // scroll down
 | |
|         if (st < 250) {
 | |
|           gttBtn.style.display = "none";
 | |
|         } else {
 | |
|           gttBtn.style.display = "block";
 | |
|         }
 | |
| 
 | |
|         if (st < 45) {
 | |
|           return null;
 | |
|         }
 | |
|         
 | |
|         if (!navbar.classList.contains('navbar--hide')) {
 | |
|           navbar.classList.add('navbar--hide');
 | |
|         } else if (navbar.classList.contains('navbar--show')) {
 | |
|           navbar.classList.remove('navbar--show');
 | |
|         }
 | |
| 
 | |
|         if (singleContentsElem) {
 | |
|           if (singleContentsElem.querySelectorAll("h1, h2, h3, h4, h5, h6").length > 0) {
 | |
|             singleContentsElem.querySelectorAll("h1, h2, h3, h4, h5, h6").forEach(function (elem) {
 | |
|               if (toggleTocElem && !toggleTocElem.checked) {
 | |
|                 return null;
 | |
|               }
 | |
| 
 | |
|               if (notAllowedTitleIds && notAllowedTitleIds.includes(elem.getAttribute('id'))) {
 | |
|                 return null;
 | |
|               }
 | |
|               
 | |
|               if (document.documentElement.scrollTop >= elem.offsetTop) {
 | |
|                 if (tableOfContentsElem) {
 | |
|                   var id = elem.getAttribute('id');
 | |
|                   tocElem.querySelectorAll('a').forEach(function (elem) {
 | |
|                     elem.classList.remove('active');
 | |
|                   });
 | |
|                   tocElem.querySelector('a[href="#' + id + '"]') ?
 | |
|                     tocElem.querySelector('a[href="#' + id + '"]').classList.add('active') : null;
 | |
| 
 | |
|                   tableOfContentsElem.querySelector('ul') ?
 | |
|                     tableOfContentsElem.querySelector('ul').querySelectorAll('li').forEach(function (liElem) {
 | |
|                       liElem.querySelectorAll('ul').forEach(function (ulElem) {
 | |
|                         ulElem.style.display = 'none';
 | |
|                       });
 | |
|                     }) : null;
 | |
| 
 | |
|                   var curElem = tableOfContentsElem.querySelector("[href='#" + id + "']");
 | |
|                   if (curElem && curElem.nextElementSibling) {
 | |
|                     curElem.nextElementSibling.style.display = 'block';
 | |
|                   }
 | |
|                   getParents(curElem, 'ul') ?
 | |
|                     getParents(curElem, 'ul').forEach(function (elem) {
 | |
|                       elem.style.display = 'block';
 | |
|                     }) : null;
 | |
|                 }
 | |
|               }
 | |
|             });
 | |
|           } else {
 | |
|             if (tocFlexbox) {
 | |
|               tocFlexbox.setAttribute('data-position', '');
 | |
|               if (!tocFlexbox.classList.contains('hide')) {
 | |
|                 tocFlexbox.classList.add('hide');
 | |
|               }
 | |
|             }
 | |
|             if (tocFlexboxOuter) {
 | |
|               tocFlexboxOuter.setAttribute('data-position', '');
 | |
|               if (!tocFlexboxOuter.classList.contains('hide')) {
 | |
|                 tocFlexboxOuter.classList.add('hide');
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       } else { // scroll up
 | |
|         if (st < 250) {
 | |
|           gttBtn.style.display = "none";
 | |
|         }
 | |
| 
 | |
|         if (navbar.classList.contains('navbar--hide')) {
 | |
|           navbar.classList.remove('navbar--hide');
 | |
|         } else if (!navbar.classList.contains('navbar--show')) {
 | |
|           navbar.classList.add('navbar--show');
 | |
|         }
 | |
| 
 | |
|         if (singleContentsElem) {
 | |
|           if (singleContentsElem.querySelectorAll("h1, h2, h3, h4, h5, h6").length > 0) {
 | |
|             singleContentsElem.querySelectorAll("h1, h2, h3, h4, h5, h6").forEach(function (elem) {
 | |
|               if (toggleTocElem && !toggleTocElem.checked) {
 | |
|                 return null;
 | |
|               }
 | |
|               
 | |
|               if (notAllowedTitleIds && notAllowedTitleIds.includes(elem.getAttribute('id'))) {
 | |
|                 return null;
 | |
|               }
 | |
| 
 | |
|               if (document.documentElement.scrollTop >= elem.offsetTop) {
 | |
|                 if (tableOfContentsElem) {
 | |
|                   var id = elem.getAttribute('id');
 | |
|                   tocElem.querySelectorAll('a').forEach(function (elem) {
 | |
|                     elem.classList.remove('active');
 | |
|                   });
 | |
|                   tocElem.querySelector('a[href="#' + id + '"]') ?
 | |
|                     tocElem.querySelector('a[href="#' + id + '"]').classList.add('active') : null;
 | |
| 
 | |
|                   tableOfContentsElem.querySelectorAll('ul').forEach(function (rootUl) {
 | |
|                     rootUl.querySelectorAll('li').forEach(function (liElem) {
 | |
|                       liElem.querySelectorAll('ul').forEach(function (ulElem) {
 | |
|                         ulElem.style.display = 'none';
 | |
|                       });
 | |
|                     });
 | |
|                   });
 | |
| 
 | |
|                   var curElem = tableOfContentsElem.querySelector("[href='#" + id + "']");
 | |
|                   if (curElem && curElem.nextElementSibling) {
 | |
|                     curElem.nextElementSibling.style.display = 'block';
 | |
|                   }
 | |
|                   getParents(curElem, 'ul') ?
 | |
|                     getParents(curElem, 'ul').forEach(function (elem) {
 | |
|                       elem.style.display = 'block';
 | |
|                     }) : null;
 | |
|                 }
 | |
|               }
 | |
|             });
 | |
|           } else {
 | |
|             if (tocFlexbox && !tocFlexbox.classList.contains('hide')) {
 | |
|               tocFlexbox.classList.add('hide');
 | |
|             }
 | |
|             if (tocFlexboxOuter && !tocFlexboxOuter.classList.contains('hide')) {
 | |
|               tocFlexboxOuter.classList.add('hide');
 | |
|             }
 | |
|           }
 | |
|           
 | |
|         }
 | |
| 
 | |
|         if (tableOfContentsElem && document.documentElement.scrollTop < 250) {
 | |
|           tableOfContentsElem.querySelector('ul') ?
 | |
|           tableOfContentsElem.querySelector('ul').querySelectorAll('li').forEach(function (liElem) {
 | |
|             liElem.querySelectorAll('ul').forEach(function (ulElem) {
 | |
|               ulElem.style.display = 'none';
 | |
|             });
 | |
|           }) : null;
 | |
|         }
 | |
|       }
 | |
|       lastScrollTop = st <= 0 ? 0 : st;
 | |
|     };
 | |
|   // ============================================================
 | |
| 
 | |
| 
 | |
|   // ========================== navbar ==========================
 | |
|     var navbarBurgerElem = document.querySelector('.navbar__burger');
 | |
|     var navbarMenuElem = document.querySelector('.navbar__menu');
 | |
|     navbarBurgerElem ?
 | |
|     navbarBurgerElem.addEventListener('click', function () {
 | |
|       if (navbarBurgerElem.classList.contains('is-active')) {
 | |
|         navbarBurgerElem.classList.remove('is-active');
 | |
|         navbarMenuElem.classList.remove('is-active');
 | |
|       } else {
 | |
|         navbarBurgerElem.classList.add('is-active');
 | |
|         navbarMenuElem.classList.add('is-active');
 | |
|       }
 | |
|     }) : null;
 | |
|   // ============================================================
 | |
| 
 | |
| 
 | |
|   // ====================== mobile search =======================
 | |
|     var mobileSearchInputElem = document.querySelector('#search-mobile');
 | |
|     var mobileSearchClassElem = document.querySelector('.mobile-search');
 | |
|     var mobileSearchBtnElem = document.querySelector('#mobileSearchBtn');
 | |
|     var mobileSearchCloseBtnElem = document.querySelector('#search-mobile-close');
 | |
|     var mobileSearchContainer = document.querySelector('#search-mobile-container');
 | |
|     var mobileSearchResultsElem = document.querySelector('#search-mobile-results');
 | |
|     var htmlElem = document.querySelector('html');
 | |
| 
 | |
|     if (mobileSearchClassElem) {
 | |
|       mobileSearchClassElem.style.display = 'none';
 | |
|     }
 | |
| 
 | |
|     mobileSearchBtnElem ? 
 | |
|     mobileSearchBtnElem.addEventListener('click', function () {
 | |
|       if (mobileSearchContainer) {
 | |
|         mobileSearchContainer.style.display = 'block';
 | |
|       }
 | |
| 
 | |
|       if (mobileSearchInputElem) {
 | |
|         mobileSearchInputElem.focus();
 | |
|       }
 | |
| 
 | |
|       if (htmlElem) {
 | |
|         htmlElem.style.overflowY = 'hidden';
 | |
|       }
 | |
|     }) : null;
 | |
| 
 | |
|     mobileSearchCloseBtnElem ? 
 | |
|     mobileSearchCloseBtnElem.addEventListener('click', function() {
 | |
|       if (mobileSearchContainer) {
 | |
|         mobileSearchContainer.style.display = 'none';
 | |
|       }
 | |
| 
 | |
|       if (mobileSearchInputElem) {
 | |
|         mobileSearchInputElem.value = '';
 | |
|       }
 | |
|       
 | |
|       if (mobileSearchResultsElem) {
 | |
|         while (mobileSearchResultsElem.firstChild) {
 | |
|           mobileSearchResultsElem.removeChild(mobileSearchResultsElem.firstChild);
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if (htmlElem) {
 | |
|         htmlElem.style.overflowY = 'visible';
 | |
|       }
 | |
|     }) : null;
 | |
| 
 | |
|     mobileSearchInputElem ? 
 | |
|     mobileSearchInputElem.addEventListener('keydown', function(e) {
 | |
|       var keyCode = e.which || e.keyCode;
 | |
|       if (e.key === 'Escape' || keyCode === 27) {
 | |
|         if (mobileSearchContainer) {
 | |
|           mobileSearchContainer.style.display = 'none';
 | |
|         }
 | |
|         
 | |
|         if (mobileSearchInputElem) {
 | |
|           mobileSearchInputElem.value = '';
 | |
|         }
 | |
| 
 | |
|         if (mobileSearchResultsElem) {
 | |
|           while (mobileSearchResultsElem.firstChild) {
 | |
|             mobileSearchResultsElem.removeChild(mobileSearchResultsElem.firstChild);
 | |
|           }
 | |
|         }
 | |
|         if (htmlElem) {
 | |
|           htmlElem.style.overflowY = 'visible';
 | |
|         }
 | |
|       }
 | |
|     }) : null;
 | |
|   // ============================================================
 | |
| 
 | |
| 
 | |
|   // ======================= theme change =======================
 | |
|     var localTheme = localStorage.getItem('theme');
 | |
|     var rootEleme = document.getElementById('root');
 | |
|     var selectThemeElem = document.querySelectorAll('.select-theme');
 | |
|     var selectThemeItemElem = document.querySelectorAll('.select-theme__item');
 | |
|     
 | |
|     if (localTheme) {
 | |
|       selectThemeItemElem ? 
 | |
|       selectThemeItemElem.forEach(function (elem) {
 | |
|         if (elem.text.trim() === localTheme) {
 | |
|           elem.classList.add('is-active');
 | |
|         } else {
 | |
|           elem.classList.remove('is-active');
 | |
|         }
 | |
|       }) : null;
 | |
|     }
 | |
| 
 | |
|     selectThemeItemElem ? 
 | |
|     selectThemeItemElem.forEach(function (v, i) {
 | |
|       v.addEventListener('click', function (e) {
 | |
|         var selectedThemeVariant = e.target.text.trim();
 | |
|         localStorage.setItem('theme', selectedThemeVariant);
 | |
| 
 | |
|         rootEleme.removeAttribute('class');
 | |
|         rootEleme.classList.add('theme__' + selectedThemeVariant);
 | |
|         selectThemeElem.forEach(function(rootElem) {
 | |
|           rootElem.querySelectorAll('a').forEach(function (elem) {
 | |
|             if (elem.classList) {
 | |
|               if (elem.text.trim() === selectedThemeVariant) {
 | |
|                 if (!elem.classList.contains('is-active')) {
 | |
|                   elem.classList.add('is-active');
 | |
|                 }
 | |
|               } else {
 | |
|                 if (elem.classList.contains('is-active')) {
 | |
|                   elem.classList.remove('is-active');
 | |
|                 }
 | |
|               }
 | |
|             }
 | |
|           });
 | |
|         });
 | |
| 
 | |
|         if (window.mermaid) {
 | |
|           if (selectedThemeVariant === "dark" || selectedThemeVariant === "hacker") {
 | |
|             mermaid.initialize({ theme: 'dark' });
 | |
|             location.reload();
 | |
|           } else {
 | |
|             mermaid.initialize({ theme: 'default' });
 | |
|             location.reload();
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         var utterances = document.querySelector('iframe');
 | |
|         if (utterances) {
 | |
|           utterances.contentWindow.postMessage({
 | |
|             type: 'set-theme',
 | |
|             theme: selectedThemeVariant === "dark" || selectedThemeVariant === "hacker" ? 'photon-dark' : selectedThemeVariant === 'kimbie' ? 'github-dark-orange' : 'github-light',
 | |
|           }, 'https://utteranc.es');
 | |
|         }
 | |
|       });
 | |
|     }) : null;
 | |
|   // ============================================================  
 | |
| 
 | |
| 
 | |
|   // ========================== search ==========================
 | |
|     var baseurl = null;
 | |
|     {{ $siteBaseURL:= .Site.BaseURL }}
 | |
|     var siteBaseURL = JSON.parse({{ $siteBaseURL | jsonify }});
 | |
|     var siteBaseChecker = /\/\w+\//i;
 | |
|     var isSlug = siteBaseChecker.test(siteBaseURL);
 | |
|     var isThemeSite = location.origin.includes('themes.gohugo.io');
 | |
| 
 | |
|     {{ if .Site.IsMultiLingual }}
 | |
|         if (isThemeSite) {
 | |
|           baseurl = "{{.Site.BaseURL}}{{.Site.LanguagePrefix}}";
 | |
|         } else {
 | |
|           var hasLangPostfix = location.pathname.includes("/{{.Site.Language.Lang}}");
 | |
|           if (hasLangPostfix) {
 | |
|             if (isSlug) {
 | |
|               baseurl = location.origin + siteBaseURL.match(siteBaseChecker)[0] + "{{.Site.Language.Lang}}";
 | |
|             } else {
 | |
|               baseurl = location.origin + "/{{.Site.Language.Lang}}";
 | |
|             }
 | |
|           } else {
 | |
|             if (isSlug) {
 | |
|               baseurl = location.origin + siteBaseURL.match(siteBaseChecker)[0];
 | |
|             } else {
 | |
|               baseurl = location.origin;
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|     {{ else }}
 | |
|         if (isThemeSite) {
 | |
|           baseurl = "{{.Site.BaseURL}}";
 | |
|         } else {
 | |
|           if (isSlug) {
 | |
|             baseurl = location.origin + siteBaseURL.match(siteBaseChecker)[0];
 | |
|           } else {
 | |
|             baseurl = location.origin;
 | |
|           } 
 | |
|         }
 | |
|     {{ end }}
 | |
| 
 | |
|     var searchResults = null;
 | |
|     var searchMenu = null;
 | |
|     var searchText = null;
 | |
|     
 | |
|     {{ $enableSearchHighlight := ($.Param "enableSearchHighlight") }}
 | |
|     var enableSearchHighlight = JSON.parse({{ $enableSearchHighlight | jsonify }});
 | |
| 
 | |
|     var fuse = null;
 | |
| 
 | |
|     function endsWith(str, suffix) {
 | |
|       return str.indexOf(suffix, str.length - suffix.length) !== -1;
 | |
|     }
 | |
| 
 | |
|     function initFuse() {
 | |
|       if (!endsWith(baseurl, "/")) {
 | |
|         baseurl = baseurl + '/';
 | |
|       };
 | |
| 
 | |
|       var xhr = new XMLHttpRequest();
 | |
|       xhr.open('GET', baseurl + "index.json");
 | |
|       xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
 | |
|       xhr.onload = function () {
 | |
|         if (xhr.status === 200) {
 | |
|           fuse = new Fuse(JSON.parse(xhr.response.toString('utf-8')), {
 | |
|             keys: ['title', 'description', 'content'],
 | |
|             includeMatches: enableSearchHighlight,
 | |
|             shouldSort: true,
 | |
|             threshold: 0.4,
 | |
|             location: 0,
 | |
|             distance: 100,
 | |
|             maxPatternLength: 32,
 | |
|             minMatchCharLength: 2,
 | |
|           });
 | |
|         }
 | |
|         else {
 | |
|           console.error('[' + xhr.status + ']Error:', xhr.statusText);
 | |
|         }
 | |
|       };
 | |
|       xhr.send();
 | |
|     }
 | |
| 
 | |
|     function renderSearchResults(results) { // [{}, {}, ...] or [{item: {}, matches: []}, ...]
 | |
|       searchResults = document.getElementById('search-results');
 | |
|       searchMenu = document.getElementById('search-menu');
 | |
|       searchResults.setAttribute('class', 'dropdown is-active');
 | |
| 
 | |
|       var content = document.createElement('div');
 | |
|       content.setAttribute('class', 'dropdown-content search-content');
 | |
| 
 | |
|       if (results.length > 0) {
 | |
|         results.forEach(function (result) {
 | |
|           var item = document.createElement('a');
 | |
|           item.setAttribute('href', result.uri);
 | |
|           item.setAttribute('class', 'dropdown-item');
 | |
|           item.innerHTML = '<div class="menu-item"><div class="menu-item__title">📄 ' + result.title + '</div><div class="menu-item__desc">' + (result.description ? result.description : result.content) + '</div></div>';
 | |
|           content.appendChild(item);
 | |
|         });
 | |
|       } else {
 | |
|         var item = document.createElement('span');
 | |
|         item.setAttribute('class', 'dropdown-item');
 | |
|         item.innerText = 'No results found';
 | |
|         content.appendChild(item);
 | |
|       }
 | |
| 
 | |
|       while (searchMenu.hasChildNodes()) {
 | |
|         searchMenu.removeChild(
 | |
|           searchMenu.lastChild
 | |
|         );
 | |
|       }
 | |
|       searchMenu.appendChild(content);
 | |
|     }
 | |
| 
 | |
|     function renderSearchHighlightResults(results) {      
 | |
|       searchResults = document.getElementById('search-results');
 | |
|       searchMenu = document.getElementById('search-menu');
 | |
|       searchResults.setAttribute('class', 'dropdown is-active');
 | |
| 
 | |
|       var content = document.createElement('div');
 | |
|       content.setAttribute('class', 'dropdown-content search-content');
 | |
| 
 | |
|       if (results.length > 0) {
 | |
|         results.forEach(function (result) {
 | |
|           var item = document.createElement('a');
 | |
|           item.setAttribute('href', result.item.uri);
 | |
|           item.setAttribute('class', 'dropdown-item');
 | |
|           item.innerHTML = '<div class="menu-item"><div class="menu-item__title">📄 ' + generateHighlightedText(result.item.title, result.matches[0].indices) + '</div><div class="menu-item__desc">' + (result.matches[1] ? generateHighlightedText(result.item.description, result.matches[1].indices) : result.matches[2] ? generateHighlightedText(result.item.content, result.matches[2].indices) : '') + '</div></div>';
 | |
|           content.appendChild(item);
 | |
|         });
 | |
|       } else {
 | |
|         var item = document.createElement('span');
 | |
|         item.setAttribute('class', 'dropdown-item');
 | |
|         item.innerText = 'No results found';
 | |
|         content.appendChild(item);
 | |
|       }
 | |
| 
 | |
|       while (searchMenu.hasChildNodes()) {
 | |
|         searchMenu.removeChild(
 | |
|           searchMenu.lastChild
 | |
|         );
 | |
|       }
 | |
|       searchMenu.appendChild(content);
 | |
|     }
 | |
| 
 | |
|     function renderSearchResultsMobile(results) {
 | |
|       searchResults = document.getElementById('search-mobile-results');
 | |
| 
 | |
|       var content = document.createElement('div');
 | |
|       content.setAttribute('class', 'mobile-search__content');
 | |
| 
 | |
|       if (results.length > 0) {
 | |
|         results.forEach(function (result) {
 | |
|           var item = document.createElement('a');
 | |
|           item.setAttribute('href', result.uri);
 | |
|           item.innerHTML = '<div class="mobile-search__item"><div class="mobile-search__item--title">📄 ' + result.title + '</div><div class="mobile-search__item--desc">' + (result.description ? result.description : result.content) + '</div></div>';
 | |
|           content.appendChild(item);
 | |
|         });
 | |
|       } else {
 | |
|         var item = document.createElement('span');
 | |
|         content.appendChild(item);
 | |
|       }
 | |
| 
 | |
|       let wrap = document.getElementById('search-mobile-results');
 | |
|       while (wrap.firstChild) {
 | |
|         wrap.removeChild(wrap.firstChild)
 | |
|       }
 | |
|       searchResults.appendChild(content);      
 | |
|     }
 | |
| 
 | |
|     function renderSearchHighlightResultsMobile(results) {
 | |
|       searchResults = document.getElementById('search-mobile-results');
 | |
| 
 | |
|       var content = document.createElement('div');
 | |
|       content.setAttribute('class', 'mobile-search__content');
 | |
| 
 | |
|       if (results.length > 0) {
 | |
|         results.forEach(function (result) {
 | |
|           var item = document.createElement('a');
 | |
|           item.setAttribute('href', result.item.uri);
 | |
|           item.innerHTML = '<div class="mobile-search__item"><div class="mobile-search__item--title">📄 ' + generateHighlightedText(result.item.title, result.matches[0].indices) + '</div><div class="mobile-search__item--desc">' + (result.matches[1] ? generateHighlightedText(result.item.description, result.matches[1].indices) : result.matches[2] ? generateHighlightedText(result.item.content, result.matches[2].indices) : '') + '</div></div>';
 | |
|           content.appendChild(item);
 | |
|         });
 | |
|       } else {
 | |
|         var item = document.createElement('span');
 | |
|         content.appendChild(item);
 | |
|       }
 | |
| 
 | |
|       let wrap = document.getElementById('search-mobile-results');
 | |
|       while (wrap.firstChild) {
 | |
|         wrap.removeChild(wrap.firstChild)
 | |
|       }
 | |
|       searchResults.appendChild(content);
 | |
|     }
 | |
| 
 | |
|     function generateHighlightedText(text, regions) {
 | |
|       if (!regions) {
 | |
|         return text;
 | |
|       }
 | |
| 
 | |
|       var content = '', nextUnhighlightedRegionStartingIndex = 0;
 | |
| 
 | |
|       regions.forEach(function(region) {
 | |
|         if (region[0] === region[1]) {
 | |
|           return null;
 | |
|         }
 | |
|         
 | |
|         content += '' +
 | |
|           text.substring(nextUnhighlightedRegionStartingIndex, region[0]) +
 | |
|           '<span class="search__highlight">' +
 | |
|             text.substring(region[0], region[1] + 1) +
 | |
|           '</span>' +
 | |
|         '';
 | |
|         nextUnhighlightedRegionStartingIndex = region[1] + 1;
 | |
|       });
 | |
| 
 | |
|       content += text.substring(nextUnhighlightedRegionStartingIndex);
 | |
| 
 | |
|       return content;
 | |
|     };
 | |
| 
 | |
|     initFuse();
 | |
| 
 | |
|     var searchElem = document.getElementById('search');
 | |
|     var searchMobile = document.getElementById('search-mobile');
 | |
| 
 | |
|     searchElem ? 
 | |
|     searchElem.addEventListener('input', function(e) {
 | |
|       if (!e.target.value) {
 | |
|         document.getElementById('search-results').setAttribute('class', 'dropdown');
 | |
|         return null;
 | |
|       }
 | |
| 
 | |
|       if (window.innerWidth < 770) {
 | |
|         return null;
 | |
|       }
 | |
| 
 | |
|       searchText = e.target.value;
 | |
|       var results = fuse.search(e.target.value);
 | |
|       if (enableSearchHighlight) {
 | |
|         renderSearchHighlightResults(results);
 | |
|       } else {
 | |
|         renderSearchResults(results);
 | |
|       }
 | |
|     }) : null;
 | |
| 
 | |
|     searchElem ? 
 | |
|     searchElem.addEventListener('blur', function() {
 | |
|       if (window.innerWidth < 770) {
 | |
|         return null;
 | |
|       }
 | |
|       setTimeout(function () {
 | |
|         document.getElementById('search-results').setAttribute('class', 'dropdown');
 | |
|       }, 100);
 | |
|     }) : null;
 | |
| 
 | |
|     searchElem ? 
 | |
|     searchElem.addEventListener('click', function(e) {
 | |
|       if (window.innerWidth < 770) {
 | |
|         return null;
 | |
|       }
 | |
|       if (!e.target.value) {
 | |
|         document.getElementById('search-results').setAttribute('class', 'dropdown');
 | |
|         return null;
 | |
|       }
 | |
| 
 | |
|       searchText = e.target.value;
 | |
|       var results = fuse.search(e.target.value);
 | |
|       if (enableSearchHighlight) {
 | |
|         renderSearchHighlightResults(results);
 | |
|       } else {
 | |
|         renderSearchResults(results);
 | |
|       }
 | |
|     }) : null;
 | |
|     
 | |
|     function indexInParent(node) {
 | |
|       var children = node.parentNode.childNodes;
 | |
|       var num = 0;
 | |
|       for (var i = 0; i < children.length; i++) {
 | |
|         if (children[i] == node) return num;
 | |
|         if (children[i].nodeType == 1) num++;
 | |
|       }
 | |
|       return -1;
 | |
|     }
 | |
| 
 | |
|     var searchMenuElem = document.getElementById("search-menu");
 | |
|     var activeItem = document.querySelector('#search-menu .dropdown-item.is-active');
 | |
|     var activeIndex = null;
 | |
|     var items = null;
 | |
|     var searchContainerMaxHeight = 350;
 | |
| 
 | |
|     searchElem ? 
 | |
|     searchElem.addEventListener('keydown', function(e) {
 | |
|       if (window.innerWidth < 770) {
 | |
|         return null;
 | |
|       }
 | |
| 
 | |
|       var items = document.querySelectorAll('#search-menu .dropdown-item');
 | |
|       var keyCode = e.which || e.keyCode;
 | |
|       
 | |
|       if (e.key === 'ArrowDown' || keyCode === 40) {
 | |
|         if (activeIndex === null) {
 | |
|           activeIndex = 0;
 | |
|           items[activeIndex].classList.remove('is-active');
 | |
|         } else {
 | |
|           items[activeIndex].classList.remove('is-active');
 | |
|           activeIndex = activeIndex === items.length - 1 ? 0 : activeIndex + 1;
 | |
|         }
 | |
|         items[activeIndex].classList.add('is-active');
 | |
| 
 | |
|         let overflowedPixel = items[activeIndex].offsetTop + items[activeIndex].clientHeight - searchContainerMaxHeight;
 | |
|         if (overflowedPixel > 0) {
 | |
|           document.querySelector(".search-content").scrollTop += items[activeIndex].getBoundingClientRect().height;
 | |
|         } else if (activeIndex === 0) {
 | |
|           document.querySelector(".search-content").scrollTop = 0;
 | |
|         }
 | |
|       } else if (e.key === 'ArrowUp' || keyCode === 38) {
 | |
|         if (activeIndex === null) {
 | |
|           activeIndex = items.length - 1;
 | |
|           items[activeIndex].classList.remove('is-active');
 | |
|         } else {
 | |
|           items[activeIndex].classList.remove('is-active');
 | |
|           activeIndex = activeIndex === 0 ? items.length - 1 : activeIndex - 1;
 | |
|         }
 | |
|         items[activeIndex].classList.add('is-active');
 | |
|         
 | |
|         let overflowedPixel = items[activeIndex].offsetTop + items[activeIndex].clientHeight - searchContainerMaxHeight;
 | |
|         if (overflowedPixel < 0) {
 | |
|           document.querySelector(".search-content").scrollTop -= items[activeIndex].getBoundingClientRect().height;
 | |
|         } else {
 | |
|           document.querySelector(".search-content").scrollTop = overflowedPixel + items[activeIndex].getBoundingClientRect().height;
 | |
|         }
 | |
|       } else if (e.key === 'Enter' || keyCode === 13) {
 | |
|         var currentItemLink = items[activeIndex].getAttribute('href');
 | |
|         if (currentItemLink) {
 | |
|           location.href = currentItemLink;
 | |
|         }
 | |
|       } else if (e.key === 'Escape' || keyCode === 27) {
 | |
|         e.target.value = null;
 | |
|         if (searchResults) {
 | |
|           searchResults.classList.remove('is-active');
 | |
|         }
 | |
|       }
 | |
|     }) : null;
 | |
| 
 | |
|     searchMobile ? 
 | |
|     searchMobile.addEventListener('input', function(e) {
 | |
|       if (!e.target.value) {
 | |
|         let wrap = document.getElementById('search-mobile-results');
 | |
|         while (wrap.firstChild) {
 | |
|           wrap.removeChild(wrap.firstChild);
 | |
|         }
 | |
|         return null;
 | |
|       }
 | |
| 
 | |
|       searchText = e.target.value;
 | |
|       var results = fuse.search(e.target.value);
 | |
|       renderSearchResultsMobile(results);
 | |
|       if (enableSearchHighlight) {
 | |
|         renderSearchHighlightResultsMobile(results);
 | |
|       } else {
 | |
|         renderSearchResultsMobile(results);
 | |
|       }
 | |
|     }) : null;
 | |
|   // ============================================================
 | |
|   });
 | |
| </script> |