From 244d34427d10a35a07ad4e330ec25bd6b5e8f9e6 Mon Sep 17 00:00:00 2001 From: Karthik Ganeshram Date: Mon, 23 Feb 2026 09:59:38 +0100 Subject: [PATCH] fix overlapping search button on medium sized screens Signed-off-by: Karthik Ganeshram --- static/css/styles.css | 108 +- static/js/main.js | 1610 ++++++++++++++++++++- static/js/src/modules/search.js | 4 +- static/sass/developer-include-search.scss | 81 +- static/sass/developer-include-topbar.scss | 5 +- templates/content_navbar.hbs | 4 +- 6 files changed, 1639 insertions(+), 173 deletions(-) diff --git a/static/css/styles.css b/static/css/styles.css index 8b642e981..119522ae6 100644 --- a/static/css/styles.css +++ b/static/css/styles.css @@ -577,7 +577,6 @@ footer { position: relative; z-index: 1400; /* top row of links */ - /* bottom row of smaller links */ } footer ul, footer p { @@ -611,6 +610,9 @@ footer.is-shallow { footer.is-shallow img { max-height: 2.5rem; } +footer { + /* bottom row of smaller links */ +} footer .footer-nav { border-top: 1px solid #D9DBE8; } @@ -761,10 +763,6 @@ body { color: #0D203F; } -.content { - /* Code Styling */ - /* highlight.js css */ -} .content h1, .content h2, .content h3 { font-weight: bold; display: block; @@ -1007,6 +1005,9 @@ body { margin: 0 0 -0.333rem; letter-spacing: -0.02em; } +.content { + /* Code Styling */ +} .content h1 code, .content h2 code, .content h3 code, @@ -1060,6 +1061,9 @@ body { .content .hljs { background-color: transparent !important; } +.content { + /* highlight.js css */ +} .content pre code.hljs { display: block; overflow-x: auto; @@ -1169,16 +1173,16 @@ html.dark-theme > body .content .pagination-link, html.dark-theme > body .conten Responsive Media Queries */ @media screen and (max-width: 1023px) { + #topbar.navbar .logo svg, + #topbar.navbar .logo span { + display: none !important; + } #topbar.navbar .logo { width: 3rem; height: 3rem; background: url(../image/avatar.png) no-repeat 0 0; background-size: contain; } - #topbar.navbar .logo svg, - #topbar.navbar .logo span { - display: none !important; - } #topbar.navbar .logo-project { margin-left: 0.5rem; } @@ -2189,7 +2193,6 @@ html.dark-theme .external { #topbar.navbar { display: flex; align-items: center; - /* Show the dropdown menu on hover */ } #topbar.navbar.is-wide { padding-left: 0 !important; @@ -2420,6 +2423,9 @@ html.dark-theme .external { #topbar.navbar .dropdown-content :first-child { display: none; } +#topbar.navbar { + /* Show the dropdown menu on hover */ +} #topbar.navbar .dropdown:hover .dropdown-content { display: block; } @@ -2431,8 +2437,11 @@ html.dark-theme .external { .navbar-menu { position: relative; z-index: 1020; + display: flex; } .navbar-menu .navbar-start { + display: flex; + flex: 1; z-index: 1023; align-items: center; } @@ -2557,10 +2566,10 @@ html.dark-theme .external { } .search-button-container { - display: inline-block; - position: absolute; + display: flex; + flex: 1; + justify-content: flex-end; width: 100%; - display: block; top: 0; left: 2px; bottom: 0; @@ -2581,11 +2590,9 @@ html.dark-theme .external { .search-button { border: none !important; - padding: 0.8rem 25rem 0.8rem 0.8rem; z-index: 19; cursor: text; display: block; - width: 100%; height: 4.333rem; background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 100%); text-align: right; @@ -2607,21 +2614,10 @@ html.dark-theme .external { .search-button.mobile::before { right: 0rem; } -.search-button:before { - height: 2rem; - width: 1px; - background: #E6D2F1; - right: 30.5rem; - top: 1rem; - display: block; - content: " "; - position: absolute; -} .search-button:after { background: url("/static/image/search.svg") no-repeat 0 0; background-size: cover; display: inline-block; - position: absolute; z-index: -1; height: 1.35rem; width: 1.35rem; @@ -2629,57 +2625,10 @@ html.dark-theme .external { top: 1.33rem; right: 31.35rem; } -.search-button .search-command { - opacity: 0; - position: absolute; - top: 2.35rem; - right: 34rem; - transition: all 0.3s ease-in-out; -} -.search-button .search-placeholder { - font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace; - font-size: 1rem; - opacity: 0; - color: rgb(160.9210526316, 127.6315789474, 217.3684210526); - font-weight: normal; - min-width: 6.5vw; - display: inline-block; - transition: all 0.3s ease-in-out; - position: absolute; - right: 43.33rem; - top: 1.5rem; - text-align: left; -} .search-button:hover { background: rgb(255, 255, 255); background: linear-gradient(0deg, rgba(255, 255, 255, 0.5) 0%, rgba(255, 255, 255, 0) 100%); } -.search-button:hover .search-placeholder, -.search-button:hover .search-command { - opacity: 1; -} -@media screen and (min-width: 1024px) and (max-width: 1214px) { - .search-button .search-placeholder, - .search-button .search-command { - display: none; - } -} - -.search-placeholder { - padding: 0 1rem 0 1rem; - font-weight: 600; - font-size: 0.8rem; -} - -.search-command { - background-color: white; - color: #345995; - padding: 0.333em 0.5em 0.333em; - display: inline-block; - margin-top: -1rem; - font-size: 0.7rem; - border-radius: 0.667rem; -} .modal-wrapper { width: 100%; @@ -2962,9 +2911,6 @@ html.dark-theme #topbar.navbar .search-button:hover { html.dark-theme .search-button-container:after { background: url("../image/search-white.svg") no-repeat 0 0 !important; } -html.dark-theme .search-button .search-placeholder { - color: #ECE5EE; -} html.dark-theme .search-button { color: white; border: none !important; @@ -2972,10 +2918,6 @@ html.dark-theme .search-button { html.dark-theme .search-button::before { background: rgba(231, 211, 242, 0.2) !important; } -html.dark-theme .search-command { - background-color: rgba(33, 55, 98, 0.5); - color: #ECE5EE; -} html.dark-theme .search-modal-container .modal-wrapper { background-color: rgba(0, 0, 0, 0.2509803922); } @@ -4429,13 +4371,13 @@ html.dark-theme .changelog-item-tags span { font-size: 1.25rem; padding: 0 !important; } - .documentation .changelog-header { - padding-bottom: 2rem; - } .documentation .changelog-header h1 { margin: 0 0 1.5rem !important; padding-bottom: 0.5rem !important; } + .documentation .changelog-header { + padding-bottom: 2rem; + } .documentation .changelog-content { padding-left: 3rem !important; } diff --git a/static/js/main.js b/static/js/main.js index 4ea7fedbf..8f7cd0e31 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -1,10 +1,1292 @@ -(()=>{let t,e,{el:i,mount:s,text:n,list:a,setChildren:o,setStyle:l,setAttr:c}=redom,r=["Spin"];async function h(){try{let t=await fetch("/static/data.json");return await t.json()}catch(t){console.log("cannot load search module")}}async function d(){e=await h();let i=window.location.pathname.match(/^\/(v\d+)\//),s=i?i[1]:"v3";e=e.filter(t=>!!t.url&&t.url.split("/")[1]===s),t=lunr(function(){this.field("title"),this.field("subheading"),this.field("content"),this.field("keywords",{boost:100}),this.field("subsectionKeywords",{boost:100}),this.ref("url"),e.forEach(function(t){this.add(t)},this)})}class u{constructor(){this.itemIcon=i("span.result-item-icon","#"),this.link=i("span"),this.el=i("a.result-subitem",{onclick:function(t){k.close()}},[this.itemIcon,this.link])}update(t){this.link.textContent=t.subheading,this.el.href=t.url,""==t.subheading?l(this.el,{display:"none"}):l(this.el,{display:"flex"})}}class p{constructor(){this.subheading=a("div.result-subheading-container",u),this.projectName=i("code.project-name"),this.pageTitle=i("span"),this.title=i("a",this.pageTitle,this.projectName),this.el=i("div.result-block",[this.title,this.subheading])}update(t){this.pageTitle.textContent=t.title,this.projectName.textContent=t.project,this.title.href=t.url,this.subheading.update(t.data)}}class m{constructor(){this.index,this.active=!0,this.parentCallback,this.el=i("code.active",{onclick:(function(t){this.toggle()}).bind(this)})}update(t,e,i,s){this.parentCallback=s.callback,this.index=e,s.reset&&(this.active=!0),this.active&&this.el.classList.add("active"),this.el.textContent=t}toggle(){this.active=!this.active,this.active?this.el.classList.add("active"):this.el.classList.remove("active"),this.parentCallback(this.index,this.active)}}class b{constructor(t,e){this.categories=t,this.parentCallback=e,this.active=[!0,!0,!0],this.activefilter=t.map(t=>t.toLowerCase()),this.filters=a("div.filter-categories",m),this.filters.update(this.categories,{callback:this.updateFilterSearch.bind(this)}),this.resetFilter=i("span.reset-filter",{onclick:(function(t){this.resetFilters()}).bind(this)},"Clear filters"),this.el=i("div.result-filters",this.filters,this.resetFilter)}updateFilterSearch(t,e){console.log(this.active,this.active[t]),this.active[t]=e,this.activefilter=this.categories.filter((t,e)=>this.active[e]).map(t=>t.toLowerCase()),this.parentCallback(this.activefilter)}resetFilters(){this.activefilter=this.categories.map(t=>t.toLowerCase()),this.parentCallback(this.activefilter),this.filters.update(this.categories,{callback:this.updateFilterSearch.bind(this),reset:!0})}}class g{constructor(){this.data,this.projects=r,this.resultItems=a("div.result-section",p),this.resultFilters=new b(this.projects,this.filter.bind(this)),this.el=i("div.result-section-container",this.resultFilters,this.resultItems)}update(t){this.data=t,this.resultItems.update(this.data)}filter(t){this.resultItems.update(this.data.filter(e=>t.includes(e.project)))}}class f{constructor(){this.link1=i("a.suggested-project-link"),this.link2=i("a.suggested-project-link"),this.link3=i("a.suggested-project-link"),this.link4=i("a.suggested-project-link"),this.projectLinks=i("div.recommended-navs",this.link1,this.link2,this.link3,this.link4),this.projectTitle=i("div.project-title"),this.el=i("div.suggested-project",this.projectTitle,this.projectLinks)}update(t){this.projectTitle.textContent=t.project,this.link1.textContent=t.link1[0],this.link1.href=t.link1[1],this.link2.textContent=t.link2[0],this.link2.href=t.link2[1],this.link3.textContent=t.link3[0],this.link3.href=t.link3[1],this.link4.textContent=t.link4[0],this.link4.href=t.link4[1]}}class v{constructor(){this.projectData=[{project:"Spin",link1:["Install","/install"],link2:["Quickstart","/quickstart"],link3:["Develop","/writing-apps"],link4:["Deploy","/deploying"]}],this.projectRecommendations=a("div.result-section",f),this.projectRecommendations.update(this.projectData),this.el=i("div.result-section-container",this.projectRecommendations)}}let k=new class{constructor(){this.container=document.getElementById("search-modal-container"),this.modalSearchBar=i("input.modal-search-bar",{type:"text",spellcheck:!1,placeholder:"Search Spin Docs",oninput:(function(t){this.updateSearch()}).bind(this)}),this.searchResults=new g,this.modalSuggest=new v,this.modal=i("div.modal-box",{onclick:function(t){t.stopPropagation()}}),this.el=i("div.modal-wrapper",{onclick:(function(t){this.close()}).bind(this),onkeydown:function(t){"Escape"!=t.key&&t.stopPropagation()}},this.modal)}open(){l(this.container,{display:"block"}),l(document.body,{overflow:"hidden",height:"100%"}),this.modalSearchBar.value="",o(this.modal,[this.modalSearchBar,this.modalSuggest]),this.modalSearchBar.focus()}close(){l(this.container,{display:"none"}),l(document.body,{"overflow-y":"auto",height:"auto"}),o(this.modal,[])}updateSearch(){let i,s=this.modalSearchBar.value;if(""==s)return void o(this.modal,[this.modalSearchBar,this.modalSuggest]);let n=s.split(" ").map(t=>t+"^2 "+t+"* "+t+"~2").join(" "),a=t.search(n),l={};a.map(t=>{if(t.score<.5)return;let s=(i=e.find(e=>t.ref===e.url)).title.replaceAll(" ","");l[s]||(l[s]={},l[s].data=[]),""==i.subheading?l[s].url=i.url:l[s].url=i.url.slice(0,i.url.indexOf("#")),l[s].data.push({subheading:i.subheading,url:i.url}),l[s].title=i.title,l[s].project=i.project,l[s].score=l[s].score&&l[s].score>t.score?l[s].score:t.score}),l=Object.keys(l).map(t=>l[t]).sort(function(t,e){return e.score-t.score}).filter(t=>void 0!=t.title),this.searchResults.update(l),o(this.modal,[this.modalSearchBar,this.searchResults])}},w=new class{constructor(t){this.modal=t,this.searchPlaceholder=i("span.search-placeholder","Search"),this.searchCommand=i("span.search-command","⌘/ctrl + K"),this.el=i("button.search-button",{onclick:(function(t){this.modal.open()}).bind(this)},[this.searchPlaceholder,this.searchCommand]);let e=document.getElementById("mobile-search");e&&(e.classList.add("enable"),e.addEventListener("click",()=>{this.modal.open()}))}}(k);var y=new Headroom(document.querySelector("#topbar"),{tolerance:5,offset:80}),C=new Headroom(document.querySelector("#blogSlogan"),{tolerance:5,offset:300});let S='\x3c!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --\x3e',L=t=>{document.querySelectorAll("pre > code").forEach(e=>{let i=e.innerText.trim(),s=e.parentNode.previousSibling.previousSibling;if(s&&"#comment"==s.nodeName)switch(s.textContent.trim()){case"@nocpy":return;case"@selectiveCpy":{let t=!1;i=i.split("\n").map(e=>{let i=(e=e.trim()).startsWith("$");return i||!0==t?(t=!!e.endsWith("\\"),i?e.substring(1).trim():e):void 0}).filter(t=>void 0!=t).join("\n")}}let n=document.createElement("button");n.className="copy-code-button",n.type="button",n.ariaLabel="Copy code",n.innerHTML=S,n.addEventListener("click",()=>{t.writeText(i).then(()=>{n.classList.add("is-success"),n.innerHTML='',setTimeout(()=>{n.innerHTML=S,n.classList.remove("is-success")},2e3)},t=>n.innerHTML="Error")}),e.parentNode.appendChild(n)})},x=()=>{document.querySelectorAll(".content h1, .content h2, .content h3, .content h4, .content tr").forEach(t=>{let e;if("tr"===t.tagName.toLowerCase()){let i=t.closest("table").previousElementSibling;for(;i&&!i.matches("h1, h2, h3, h4");)i=i.previousElementSibling;let s=t.cells[0].textContent.trim().toLowerCase().replace(/[^\w\s-]/g,"").replace(/\s+/g,"-");if(i){let t=i.getAttribute("id");e=`${t}-${s}`}else e=s}else e=t.textContent.trim().toLowerCase().replace(/[^\w\s-]/g,"").replace(/\s+/g,"-");t.classList.add("heading-anchor"),t.setAttribute("id",e);let i=document.createElement("a");i.className="anchor-link",i.href="#"+e,i.innerHTML='\x3c!--! Font Awesome Pro 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --\x3e',t.append(i),i.addEventListener("click",t=>{t.preventDefault(),window.location=i.href;let e=i.getAttribute("href").substring(1),s=document.getElementById(e);s&&s.scrollIntoView({behavior:"smooth",block:"start"})})})},{el:T,mount:E,text:j,list:H,setChildren:A,setStyle:B,setAttr:F}=redom;class I{constructor(t){this.index,this.parentCallback=t,this.lang=T("a"),this.el=T("li",{onclick:(function(e){t(this.index,e.target)}).bind(this)},this.lang)}update(t,e,i,s){this.index=e,this.lang.textContent=t,s.active==this.index?this.lang.classList.add("is-active"):this.lang.classList.remove("is-active")}}class V{constructor(t,e,i,s){this.tabClass=e,this.parentCallback=s,this.nodes=Array.from(t),this.langs=this.nodes.map(t=>t.dataset.title),this.active=this.langs.indexOf(i),"spin-version"!=e?this.active=this.active>0?this.active:0:this.active=this.active>0?this.active:this.nodes.length-1,this.tabs=H("ul",I,null,this.ChildEventHandler.bind(this)),this.el=T("div.tabs.is-boxed",this.tabs),"spin-version"===e&&B(this.tabs,{display:"flex","flex-direction":"row-reverse"}),this.tabs.update(this.langs,{active:this.active}),this.updateTabContent(this.active)}ChildEventHandler(t,e){this.tabs.update(this.langs,{active:t}),this.updateTabContent(t),this.parentCallback(this.tabClass,this.langs[t],!0,!0,e)}updateTabContent(t){for(let e=0;e0==t.indexOf("multitab_")).reduce((e,i)=>(e[i.replace("multitab_","")]=t[i],e),{})}();Object.keys(t).map(e=>{this.selectedTab[e]=t[e]}),null==this.selectedTab.os&&(this.selectedTab.os=function(){let t=null,e=navigator.userAgent.toLowerCase();switch(!0){case -1!=e.indexOf("win"):t="Windows";break;case -1!=e.indexOf("mac"):t="macOS";break;case -1!=e.indexOf("linux"):t="Linux"}return t}()),this.handler=[],document.querySelectorAll("div.multitab-content-wrapper").forEach((t,e)=>{let i=t.querySelectorAll("div.multitab-content");this.handler[e]={},this.handler[e].class=t.dataset.class.toLowerCase(),this.handler[e].tabBlock=new V(i,this.handler[e].class,this.selectedTab[this.handler[e].class],this.updateTabs.bind(this)),t.insertBefore(this.handler[e].tabBlock.el,t.firstChild)}),Object.keys(this.selectedTab).map(t=>{this.selectedTab[t]&&this.updateTabs(t,this.selectedTab[t],!1)}),window.addEventListener("storage",t=>{"toggleTabSelections"==t.key&&Object.keys(this.selectedTab).map(t=>{this.selectedTab=JSON.parse(localStorage.getItem("toggleTabSelections"))||this.selectedTab,this.selectedTab[t]&&this.updateTabs(t,this.selectedTab[t],!1)})})}updateTabs(t,e,i,s,n){let a,o;"soloblock"!=t&&(this.selectedTab[t]=e,s&&(a=n.getBoundingClientRect().top),this.handler.map(i=>{i.class==t&&i.tabBlock.globalTabUpdate(e)}),s&&(o=n.getBoundingClientRect().top+document.documentElement.scrollTop,window.scroll(0,o-a)),i&&localStorage.setItem("toggleTabSelections",JSON.stringify(this.selectedTab)))}}let{el:M,mount:q,textContent:N,list:D,setChildren:P,setStyle:R,setAttr:z}=redom;class K{constructor(){this.pageTitle=document.querySelector(".blog-post-title").innerText,this.promptDelay=5e3,this.prompt=M("div.statement","Did you find the answers you were looking for?"),this.close=M("div.close",{onclick:(function(t){R(this.el,{display:"none"})}).bind(this)}),this.thumbsUp=M("button.feedback-button",{onclick:(function(t){this.submitSatisfactionForm("satisfied"),this.closeFeedback()}).bind(this)}),this.thumbsUp.innerHTML=` - - - `,this.thumbsDown=M("button.feedback-button",{onclick:(function(t){this.submitSatisfactionForm("not satisfied"),this.notFindingFeedback()}).bind(this)}),this.thumbsDown.innerHTML=` - - - `,this.buttonContainer=M("div.feedback-response-container",this.thumbsUp,this.thumbsDown),this.feedback=M("textarea"),this.actionLink=M("button.button.is-primary",{onclick:(function(t){this.submitFeedbackForm()}).bind(this)},"submit"),this.el=M("div.feedback-modal",this.close,this.prompt,this.buttonContainer);let t=setInterval(()=>{this.checkForScroll()&&clearInterval(t)},250);new IntersectionObserver(t=>{t[0].isIntersecting?this.el.parentNode.classList.add("end-of-page"):this.el.parentNode.classList.remove("end-of-page")},{rootMargin:"0px 0px 100px 0px",threshold:[.5]}).observe(document.querySelector("#end-of-content"))}async submitSatisfactionForm(t){let e={page:this.pageTitle,satisfaction:t};await fetch("https://submit-form.com/KjF5CuTg",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(e)})}async submitFeedbackForm(){let t=this.feedback.value;if(t){let e={page:this.pageTitle,url:window.location.pathname,config:localStorage.getItem("toggleTabSelections"),feedback:t};await fetch("https://submit-form.com/c3jrxv8A",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(e)}),this.prompt.textContent="Thanks for submitting the feedback",P(this.el,[this.close,this.prompt]),setTimeout(()=>{this.closeFeedback()},1e4)}}closeFeedback(){this.parent=this.el.parentNode.parentNode,console.log(this.parent),R(this.el,{opacity:0}),R(this.parent,{opacity:0,transition:"opacity 1s ease-in-out"})}notFindingFeedback(){this.prompt.textContent="Let us know what you are looking for!",P(this.el,[this.close,this.prompt,this.feedback,this.actionLink])}checkForScroll(){return(window.scrollY/(document.body.offsetHeight-window.innerHeight)>.5||document.body.offsetHeight-window.innerHeight<500)&&(R(this.el,{opacity:1,"z-index":998}),!0)}}let{mount:U}=redom;document.querySelectorAll(".modal-button").forEach(function(t){t.addEventListener("click",function(){var e=document.querySelector(t.getAttribute("data-target"));e.classList.add("is-active"),e.querySelector(".modal-close").addEventListener("click",function(){e.classList.remove("is-active")}),e.querySelector(".modal-background").addEventListener("click",function(){e.classList.remove("is-active")})})}),document.body.contains(document.getElementById("blogSlogan"))&&C.init(),document.addEventListener("DOMContentLoaded",function(){var t,e;let i,s;t=document.querySelector(".burger"),e=document.querySelector("#"+t.dataset.target),t.addEventListener("click",function(){t.classList.toggle("is-active"),e.classList.toggle("is-active")}),y.init(),hljs.highlightAll(),navigator&&navigator.clipboard&&L(navigator.clipboard),(s=(i=document.querySelectorAll(".community-highlight .carousel-cell")).length)&&(i.forEach(t=>{t.dataset.expirydate&&new Date(t.dataset.expirydate) numeric require +// +// anything defined in a previous bundle is accessed via the +// orig method which is the require for previous bundles + +(function ( + modules, + entry, + mainEntry, + parcelRequireName, + externals, + distDir, + publicUrl, + devServer +) { + /* eslint-disable no-undef */ + var globalObject = + typeof globalThis !== 'undefined' + ? globalThis + : typeof self !== 'undefined' + ? self + : typeof window !== 'undefined' + ? window + : typeof global !== 'undefined' + ? global + : {}; + /* eslint-enable no-undef */ + + // Save the require from previous bundle to this closure if any + var previousRequire = + typeof globalObject[parcelRequireName] === 'function' && + globalObject[parcelRequireName]; + + var importMap = previousRequire.i || {}; + var cache = previousRequire.cache || {}; + // Do not use `require` to prevent Webpack from trying to bundle this call + var nodeRequire = + typeof module !== 'undefined' && + typeof module.require === 'function' && + module.require.bind(module); + + function newRequire(name, jumped) { + if (!cache[name]) { + if (!modules[name]) { + if (externals[name]) { + return externals[name]; + } + // if we cannot find the module within our internal map or + // cache jump to the current global require ie. the last bundle + // that was added to the page. + var currentRequire = + typeof globalObject[parcelRequireName] === 'function' && + globalObject[parcelRequireName]; + if (!jumped && currentRequire) { + return currentRequire(name, true); + } + + // If there are other bundles on this page the require from the + // previous one is saved to 'previousRequire'. Repeat this as + // many times as there are bundles until the module is found or + // we exhaust the require chain. + if (previousRequire) { + return previousRequire(name, true); + } + + // Try the node require function if it exists. + if (nodeRequire && typeof name === 'string') { + return nodeRequire(name); + } + + var err = new Error("Cannot find module '" + name + "'"); + err.code = 'MODULE_NOT_FOUND'; + throw err; + } + + localRequire.resolve = resolve; + localRequire.cache = {}; + + var module = (cache[name] = new newRequire.Module(name)); + + modules[name][0].call( + module.exports, + localRequire, + module, + module.exports, + globalObject + ); + } + + return cache[name].exports; + + function localRequire(x) { + var res = localRequire.resolve(x); + if (res === false) { + return {}; + } + // Synthesize a module to follow re-exports. + if (Array.isArray(res)) { + var m = {__esModule: true}; + res.forEach(function (v) { + var key = v[0]; + var id = v[1]; + var exp = v[2] || v[0]; + var x = newRequire(id); + if (key === '*') { + Object.keys(x).forEach(function (key) { + if ( + key === 'default' || + key === '__esModule' || + Object.prototype.hasOwnProperty.call(m, key) + ) { + return; + } + + Object.defineProperty(m, key, { + enumerable: true, + get: function () { + return x[key]; + }, + }); + }); + } else if (exp === '*') { + Object.defineProperty(m, key, { + enumerable: true, + value: x, + }); + } else { + Object.defineProperty(m, key, { + enumerable: true, + get: function () { + if (exp === 'default') { + return x.__esModule ? x.default : x; + } + return x[exp]; + }, + }); + } + }); + return m; + } + return newRequire(res); + } + + function resolve(x) { + var id = modules[name][1][x]; + return id != null ? id : x; + } + } + + function Module(moduleName) { + this.id = moduleName; + this.bundle = newRequire; + this.require = nodeRequire; + this.exports = {}; + } + + newRequire.isParcelRequire = true; + newRequire.Module = Module; + newRequire.modules = modules; + newRequire.cache = cache; + newRequire.parent = previousRequire; + newRequire.distDir = distDir; + newRequire.publicUrl = publicUrl; + newRequire.devServer = devServer; + newRequire.i = importMap; + newRequire.register = function (id, exports) { + modules[id] = [ + function (require, module) { + module.exports = exports; + }, + {}, + ]; + }; + + // Only insert newRequire.load when it is actually used. + // The code in this file is linted against ES5, so dynamic import is not allowed. + // INSERT_LOAD_HERE + + Object.defineProperty(newRequire, 'root', { + get: function () { + return globalObject[parcelRequireName]; + }, + }); + + globalObject[parcelRequireName] = newRequire; + + for (var i = 0; i < entry.length; i++) { + newRequire(entry[i]); + } + + if (mainEntry) { + // Expose entry point to Node, AMD or browser globals + // Based on https://github.com/ForbesLindesay/umd/blob/master/template.js + var mainExports = newRequire(mainEntry); + + // CommonJS + if (typeof exports === 'object' && typeof module !== 'undefined') { + module.exports = mainExports; + + // RequireJS + } else if (typeof define === 'function' && define.amd) { + define(function () { + return mainExports; + }); + } + } +})({"jdgog":[function(require,module,exports,__globalThis) { +var global = arguments[3]; +var HMR_HOST = null; +var HMR_PORT = 1234; +var HMR_SERVER_PORT = 1234; +var HMR_SECURE = false; +var HMR_ENV_HASH = "42036d7a98ade5a7"; +var HMR_USE_SSE = false; +module.bundle.HMR_BUNDLE_ID = "2a29ff2311f401cb"; +"use strict"; +/* global HMR_HOST, HMR_PORT, HMR_SERVER_PORT, HMR_ENV_HASH, HMR_SECURE, HMR_USE_SSE, chrome, browser, __parcel__import__, __parcel__importScripts__, ServiceWorkerGlobalScope */ /*:: +import type { + HMRAsset, + HMRMessage, +} from '@parcel/reporter-dev-server/src/HMRServer.js'; +interface ParcelRequire { + (string): mixed; + cache: {|[string]: ParcelModule|}; + hotData: {|[string]: mixed|}; + Module: any; + parent: ?ParcelRequire; + isParcelRequire: true; + modules: {|[string]: [Function, {|[string]: string|}]|}; + HMR_BUNDLE_ID: string; + root: ParcelRequire; +} +interface ParcelModule { + hot: {| + data: mixed, + accept(cb: (Function) => void): void, + dispose(cb: (mixed) => void): void, + // accept(deps: Array | string, cb: (Function) => void): void, + // decline(): void, + _acceptCallbacks: Array<(Function) => void>, + _disposeCallbacks: Array<(mixed) => void>, + |}; +} +interface ExtensionContext { + runtime: {| + reload(): void, + getURL(url: string): string; + getManifest(): {manifest_version: number, ...}; + |}; +} +declare var module: {bundle: ParcelRequire, ...}; +declare var HMR_HOST: string; +declare var HMR_PORT: string; +declare var HMR_SERVER_PORT: string; +declare var HMR_ENV_HASH: string; +declare var HMR_SECURE: boolean; +declare var HMR_USE_SSE: boolean; +declare var chrome: ExtensionContext; +declare var browser: ExtensionContext; +declare var __parcel__import__: (string) => Promise; +declare var __parcel__importScripts__: (string) => Promise; +declare var globalThis: typeof self; +declare var ServiceWorkerGlobalScope: Object; +*/ var OVERLAY_ID = '__parcel__error__overlay__'; +var OldModule = module.bundle.Module; +function Module(moduleName) { + OldModule.call(this, moduleName); + this.hot = { + data: module.bundle.hotData[moduleName], + _acceptCallbacks: [], + _disposeCallbacks: [], + accept: function(fn) { + this._acceptCallbacks.push(fn || function() {}); + }, + dispose: function(fn) { + this._disposeCallbacks.push(fn); + } + }; + module.bundle.hotData[moduleName] = undefined; +} +module.bundle.Module = Module; +module.bundle.hotData = {}; +var checkedAssets /*: {|[string]: boolean|} */ , disposedAssets /*: {|[string]: boolean|} */ , assetsToDispose /*: Array<[ParcelRequire, string]> */ , assetsToAccept /*: Array<[ParcelRequire, string]> */ , bundleNotFound = false; +function getHostname() { + return HMR_HOST || (typeof location !== 'undefined' && location.protocol.indexOf('http') === 0 ? location.hostname : 'localhost'); +} +function getPort() { + return HMR_PORT || (typeof location !== 'undefined' ? location.port : HMR_SERVER_PORT); +} +// eslint-disable-next-line no-redeclare +let WebSocket = globalThis.WebSocket; +if (!WebSocket && typeof module.bundle.root === 'function') try { + // eslint-disable-next-line no-global-assign + WebSocket = module.bundle.root('ws'); +} catch { +// ignore. +} +var hostname = getHostname(); +var port = getPort(); +var protocol = HMR_SECURE || typeof location !== 'undefined' && location.protocol === 'https:' && ![ + 'localhost', + '127.0.0.1', + '0.0.0.0' +].includes(hostname) ? 'wss' : 'ws'; +// eslint-disable-next-line no-redeclare +var parent = module.bundle.parent; +if (!parent || !parent.isParcelRequire) { + // Web extension context + var extCtx = typeof browser === 'undefined' ? typeof chrome === 'undefined' ? null : chrome : browser; + // Safari doesn't support sourceURL in error stacks. + // eval may also be disabled via CSP, so do a quick check. + var supportsSourceURL = false; + try { + (0, eval)('throw new Error("test"); //# sourceURL=test.js'); + } catch (err) { + supportsSourceURL = err.stack.includes('test.js'); + } + var ws; + if (HMR_USE_SSE) ws = new EventSource('/__parcel_hmr'); + else try { + // If we're running in the dev server's node runner, listen for messages on the parent port. + let { workerData, parentPort } = module.bundle.root('node:worker_threads') /*: any*/ ; + if (workerData !== null && workerData !== void 0 && workerData.__parcel) { + parentPort.on('message', async (message)=>{ + try { + await handleMessage(message); + parentPort.postMessage('updated'); + } catch { + parentPort.postMessage('restart'); + } + }); + // After the bundle has finished running, notify the dev server that the HMR update is complete. + queueMicrotask(()=>parentPort.postMessage('ready')); + } + } catch { + if (typeof WebSocket !== 'undefined') try { + ws = new WebSocket(protocol + '://' + hostname + (port ? ':' + port : '') + '/'); + } catch (err) { + // Ignore cloudflare workers error. + if (err.message && !err.message.includes('Disallowed operation called within global scope')) console.error(err.message); + } + } + if (ws) { + // $FlowFixMe + ws.onmessage = async function(event /*: {data: string, ...} */ ) { + var data /*: HMRMessage */ = JSON.parse(event.data); + await handleMessage(data); + }; + if (ws instanceof WebSocket) { + ws.onerror = function(e) { + if (e.message) console.error(e.message); + }; + ws.onclose = function() { + console.warn("[parcel] \uD83D\uDEA8 Connection to the HMR server was lost"); + }; + } + } +} +async function handleMessage(data /*: HMRMessage */ ) { + checkedAssets = {} /*: {|[string]: boolean|} */ ; + disposedAssets = {} /*: {|[string]: boolean|} */ ; + assetsToAccept = []; + assetsToDispose = []; + bundleNotFound = false; + if (data.type === 'reload') fullReload(); + else if (data.type === 'update') { + // Remove error overlay if there is one + if (typeof document !== 'undefined') removeErrorOverlay(); + let assets = data.assets; + // Handle HMR Update + let handled = assets.every((asset)=>{ + return asset.type === 'css' || asset.type === 'js' && hmrAcceptCheck(module.bundle.root, asset.id, asset.depsByBundle); + }); + // Dispatch a custom event in case a bundle was not found. This might mean + // an asset on the server changed and we should reload the page. This event + // gives the client an opportunity to refresh without losing state + // (e.g. via React Server Components). If e.preventDefault() is not called, + // we will trigger a full page reload. + if (handled && bundleNotFound && assets.some((a)=>a.envHash !== HMR_ENV_HASH) && typeof window !== 'undefined' && typeof CustomEvent !== 'undefined') handled = !window.dispatchEvent(new CustomEvent('parcelhmrreload', { + cancelable: true + })); + if (handled) { + console.clear(); + // Dispatch custom event so other runtimes (e.g React Refresh) are aware. + if (typeof window !== 'undefined' && typeof CustomEvent !== 'undefined') window.dispatchEvent(new CustomEvent('parcelhmraccept')); + await hmrApplyUpdates(assets); + hmrDisposeQueue(); + // Run accept callbacks. This will also re-execute other disposed assets in topological order. + let processedAssets = {}; + for(let i = 0; i < assetsToAccept.length; i++){ + let id = assetsToAccept[i][1]; + if (!processedAssets[id]) { + hmrAccept(assetsToAccept[i][0], id); + processedAssets[id] = true; + } + } + } else fullReload(); + } + if (data.type === 'error') { + // Log parcel errors to console + for (let ansiDiagnostic of data.diagnostics.ansi){ + let stack = ansiDiagnostic.codeframe ? ansiDiagnostic.codeframe : ansiDiagnostic.stack; + console.error("\uD83D\uDEA8 [parcel]: " + ansiDiagnostic.message + '\n' + stack + '\n\n' + ansiDiagnostic.hints.join('\n')); + } + if (typeof document !== 'undefined') { + // Render the fancy html overlay + removeErrorOverlay(); + var overlay = createErrorOverlay(data.diagnostics.html); + // $FlowFixMe + document.body.appendChild(overlay); + } + } +} +function removeErrorOverlay() { + var overlay = document.getElementById(OVERLAY_ID); + if (overlay) { + overlay.remove(); + console.log("[parcel] \u2728 Error resolved"); + } +} +function createErrorOverlay(diagnostics) { + var overlay = document.createElement('div'); + overlay.id = OVERLAY_ID; + let errorHTML = '
'; + for (let diagnostic of diagnostics){ + let stack = diagnostic.frames.length ? diagnostic.frames.reduce((p, frame)=>{ + return `${p} +${frame.location} +${frame.code}`; + }, '') : diagnostic.stack; + errorHTML += ` +
+
+ \u{1F6A8} ${diagnostic.message} +
+
${stack}
+
+ ${diagnostic.hints.map((hint)=>"
\uD83D\uDCA1 " + hint + '
').join('')} +
+ ${diagnostic.documentation ? `
\u{1F4DD} Learn more
` : ''} +
+ `; + } + errorHTML += '
'; + overlay.innerHTML = errorHTML; + return overlay; +} +function fullReload() { + if (typeof location !== 'undefined' && 'reload' in location) location.reload(); + else if (typeof extCtx !== 'undefined' && extCtx && extCtx.runtime && extCtx.runtime.reload) extCtx.runtime.reload(); + else try { + let { workerData, parentPort } = module.bundle.root('node:worker_threads') /*: any*/ ; + if (workerData !== null && workerData !== void 0 && workerData.__parcel) parentPort.postMessage('restart'); + } catch (err) { + console.error("[parcel] \u26A0\uFE0F An HMR update was not accepted. Please restart the process."); + } +} +function getParents(bundle, id) /*: Array<[ParcelRequire, string]> */ { + var modules = bundle.modules; + if (!modules) return []; + var parents = []; + var k, d, dep; + for(k in modules)for(d in modules[k][1]){ + dep = modules[k][1][d]; + if (dep === id || Array.isArray(dep) && dep[dep.length - 1] === id) parents.push([ + bundle, + k + ]); + } + if (bundle.parent) parents = parents.concat(getParents(bundle.parent, id)); + return parents; +} +function updateLink(link) { + var href = link.getAttribute('href'); + if (!href) return; + var newLink = link.cloneNode(); + newLink.onload = function() { + if (link.parentNode !== null) // $FlowFixMe + link.parentNode.removeChild(link); + }; + newLink.setAttribute('href', // $FlowFixMe + href.split('?')[0] + '?' + Date.now()); + // $FlowFixMe + link.parentNode.insertBefore(newLink, link.nextSibling); +} +var cssTimeout = null; +function reloadCSS() { + if (cssTimeout || typeof document === 'undefined') return; + cssTimeout = setTimeout(function() { + var links = document.querySelectorAll('link[rel="stylesheet"]'); + for(var i = 0; i < links.length; i++){ + // $FlowFixMe[incompatible-type] + var href /*: string */ = links[i].getAttribute('href'); + var hostname = getHostname(); + var servedFromHMRServer = hostname === 'localhost' ? new RegExp('^(https?:\\/\\/(0.0.0.0|127.0.0.1)|localhost):' + getPort()).test(href) : href.indexOf(hostname + ':' + getPort()); + var absolute = /^https?:\/\//i.test(href) && href.indexOf(location.origin) !== 0 && !servedFromHMRServer; + if (!absolute) updateLink(links[i]); + } + cssTimeout = null; + }, 50); +} +function hmrDownload(asset) { + if (asset.type === 'js') { + if (typeof document !== 'undefined') { + let script = document.createElement('script'); + script.src = asset.url + '?t=' + Date.now(); + if (asset.outputFormat === 'esmodule') script.type = 'module'; + return new Promise((resolve, reject)=>{ + var _document$head; + script.onload = ()=>resolve(script); + script.onerror = reject; + (_document$head = document.head) === null || _document$head === void 0 || _document$head.appendChild(script); + }); + } else if (typeof importScripts === 'function') { + // Worker scripts + if (asset.outputFormat === 'esmodule') return import(asset.url + '?t=' + Date.now()); + else return new Promise((resolve, reject)=>{ + try { + importScripts(asset.url + '?t=' + Date.now()); + resolve(); + } catch (err) { + reject(err); + } + }); + } + } +} +async function hmrApplyUpdates(assets) { + global.parcelHotUpdate = Object.create(null); + let scriptsToRemove; + try { + // If sourceURL comments aren't supported in eval, we need to load + // the update from the dev server over HTTP so that stack traces + // are correct in errors/logs. This is much slower than eval, so + // we only do it if needed (currently just Safari). + // https://bugs.webkit.org/show_bug.cgi?id=137297 + // This path is also taken if a CSP disallows eval. + if (!supportsSourceURL) { + let promises = assets.map((asset)=>{ + var _hmrDownload; + return (_hmrDownload = hmrDownload(asset)) === null || _hmrDownload === void 0 ? void 0 : _hmrDownload.catch((err)=>{ + // Web extension fix + if (extCtx && extCtx.runtime && extCtx.runtime.getManifest().manifest_version == 3 && typeof ServiceWorkerGlobalScope != 'undefined' && global instanceof ServiceWorkerGlobalScope) { + extCtx.runtime.reload(); + return; + } + throw err; + }); + }); + scriptsToRemove = await Promise.all(promises); + } + assets.forEach(function(asset) { + hmrApply(module.bundle.root, asset); + }); + } finally{ + delete global.parcelHotUpdate; + if (scriptsToRemove) scriptsToRemove.forEach((script)=>{ + if (script) { + var _document$head2; + (_document$head2 = document.head) === null || _document$head2 === void 0 || _document$head2.removeChild(script); + } + }); + } +} +function hmrApply(bundle /*: ParcelRequire */ , asset /*: HMRAsset */ ) { + var modules = bundle.modules; + if (!modules) return; + if (asset.type === 'css') reloadCSS(); + else if (asset.type === 'js') { + let deps = asset.depsByBundle[bundle.HMR_BUNDLE_ID]; + if (deps) { + if (modules[asset.id]) { + // Remove dependencies that are removed and will become orphaned. + // This is necessary so that if the asset is added back again, the cache is gone, and we prevent a full page reload. + let oldDeps = modules[asset.id][1]; + for(let dep in oldDeps)if (!deps[dep] || deps[dep] !== oldDeps[dep]) { + let id = oldDeps[dep]; + let parents = getParents(module.bundle.root, id); + if (parents.length === 1) hmrDelete(module.bundle.root, id); + } + } + if (supportsSourceURL) // Global eval. We would use `new Function` here but browser + // support for source maps is better with eval. + (0, eval)(asset.output); + // $FlowFixMe + let fn = global.parcelHotUpdate[asset.id]; + modules[asset.id] = [ + fn, + deps + ]; + } + // Always traverse to the parent bundle, even if we already replaced the asset in this bundle. + // This is required in case modules are duplicated. We need to ensure all instances have the updated code. + if (bundle.parent) hmrApply(bundle.parent, asset); + } +} +function hmrDelete(bundle, id) { + let modules = bundle.modules; + if (!modules) return; + if (modules[id]) { + // Collect dependencies that will become orphaned when this module is deleted. + let deps = modules[id][1]; + let orphans = []; + for(let dep in deps){ + let parents = getParents(module.bundle.root, deps[dep]); + if (parents.length === 1) orphans.push(deps[dep]); + } + // Delete the module. This must be done before deleting dependencies in case of circular dependencies. + delete modules[id]; + delete bundle.cache[id]; + // Now delete the orphans. + orphans.forEach((id)=>{ + hmrDelete(module.bundle.root, id); + }); + } else if (bundle.parent) hmrDelete(bundle.parent, id); +} +function hmrAcceptCheck(bundle /*: ParcelRequire */ , id /*: string */ , depsByBundle /*: ?{ [string]: { [string]: string } }*/ ) { + checkedAssets = {}; + if (hmrAcceptCheckOne(bundle, id, depsByBundle)) return true; + // Traverse parents breadth first. All possible ancestries must accept the HMR update, or we'll reload. + let parents = getParents(module.bundle.root, id); + let accepted = false; + while(parents.length > 0){ + let v = parents.shift(); + let a = hmrAcceptCheckOne(v[0], v[1], null); + if (a) // If this parent accepts, stop traversing upward, but still consider siblings. + accepted = true; + else if (a !== null) { + // Otherwise, queue the parents in the next level upward. + let p = getParents(module.bundle.root, v[1]); + if (p.length === 0) { + // If there are no parents, then we've reached an entry without accepting. Reload. + accepted = false; + break; + } + parents.push(...p); + } + } + return accepted; +} +function hmrAcceptCheckOne(bundle /*: ParcelRequire */ , id /*: string */ , depsByBundle /*: ?{ [string]: { [string]: string } }*/ ) { + var modules = bundle.modules; + if (!modules) return; + if (depsByBundle && !depsByBundle[bundle.HMR_BUNDLE_ID]) { + // If we reached the root bundle without finding where the asset should go, + // there's nothing to do. Mark as "accepted" so we don't reload the page. + if (!bundle.parent) { + bundleNotFound = true; + return true; + } + return hmrAcceptCheckOne(bundle.parent, id, depsByBundle); + } + if (checkedAssets[id]) return null; + checkedAssets[id] = true; + var cached = bundle.cache[id]; + if (!cached) return true; + assetsToDispose.push([ + bundle, + id + ]); + if (cached && cached.hot && cached.hot._acceptCallbacks.length) { + assetsToAccept.push([ + bundle, + id + ]); + return true; + } + return false; +} +function hmrDisposeQueue() { + // Dispose all old assets. + for(let i = 0; i < assetsToDispose.length; i++){ + let id = assetsToDispose[i][1]; + if (!disposedAssets[id]) { + hmrDispose(assetsToDispose[i][0], id); + disposedAssets[id] = true; + } + } + assetsToDispose = []; +} +function hmrDispose(bundle /*: ParcelRequire */ , id /*: string */ ) { + var cached = bundle.cache[id]; + bundle.hotData[id] = {}; + if (cached && cached.hot) cached.hot.data = bundle.hotData[id]; + if (cached && cached.hot && cached.hot._disposeCallbacks.length) cached.hot._disposeCallbacks.forEach(function(cb) { + cb(bundle.hotData[id]); + }); + delete bundle.cache[id]; +} +function hmrAccept(bundle /*: ParcelRequire */ , id /*: string */ ) { + // Execute the module. + bundle(id); + // Run the accept callbacks in the new version of the module. + var cached = bundle.cache[id]; + if (cached && cached.hot && cached.hot._acceptCallbacks.length) { + let assetsToAlsoAccept = []; + cached.hot._acceptCallbacks.forEach(function(cb) { + let additionalAssets = cb(function() { + return getParents(module.bundle.root, id); + }); + if (Array.isArray(additionalAssets) && additionalAssets.length) assetsToAlsoAccept.push(...additionalAssets); + }); + if (assetsToAlsoAccept.length) { + let handled = assetsToAlsoAccept.every(function(a) { + return hmrAcceptCheck(a[0], a[1]); + }); + if (!handled) return fullReload(); + hmrDisposeQueue(); + } + } +} + +},{}],"e9rxa":[function(require,module,exports,__globalThis) { +var _search = require("./modules/search"); +var _utils = require("./modules/utils"); +var _multiTab = require("./modules/multiTab"); +var _feedback = require("./modules/feedback"); +const { mount } = redom; +document.querySelectorAll('.modal-button').forEach(function(el) { + el.addEventListener('click', function() { + var target = document.querySelector(el.getAttribute('data-target')); + target.classList.add('is-active'); + target.querySelector('.modal-close').addEventListener('click', function() { + target.classList.remove('is-active'); + }); + target.querySelector('.modal-background').addEventListener('click', function() { + target.classList.remove('is-active'); + }); + }); +}); +if (document.body.contains(document.getElementById('blogSlogan'))) (0, _utils.blogAd).init(); +document.addEventListener("DOMContentLoaded", function() { + // Initialize after the DOM. + (function() { + var burger = document.querySelector('.burger'); + var menu = document.querySelector('#' + burger.dataset.target); + burger.addEventListener('click', function() { + burger.classList.toggle('is-active'); + menu.classList.toggle('is-active'); + }); + })(); + (0, _utils.header).init(); + hljs.highlightAll(); + if (navigator && navigator.clipboard) (0, _utils.addCopyButtons)(navigator.clipboard); + (0, _utils.removeExpiredEvents)(); + (0, _utils.addAnchorLinks)(); + (0, _utils.scrollSideMenu)(); + // changelogFilter() + new (0, _multiTab.multiTabContentHandler)(); + if (window.location.hash.length > 0) { + setTimeout(function() { + document.querySelector('a[href="' + window.location.hash + '"]').click(); + }, 150); + (0, _utils.header).unpin(); + } + (async function() { + try { + await (0, _search.setupSearch)(); + mount(document.getElementById("search-button-container"), (0, _search.searchButton)); + mount(document.getElementById("search-modal-container"), (0, _search.searchModal)); + document.onkeydown = function(e) { + if (e.key == "Escape") (0, _search.searchModal).close(); + if ((e.key == "k" || e.key == "K") && (e.metaKey || e.ctrlKey)) { + e.preventDefault(); + e.stopPropagation(); + (0, _search.searchModal).open(); + } + if (e.key == "s" || e.key == "S") { + let searchBar = document.getElementById("hub-search-input"); + if (searchBar && document.activeElement != searchBar) { + e.preventDefault(); + searchBar.focus(); + } + } + }; + } catch (err) { + console.error("Could not setup search"); + } + })(); + // Init feedback on docs pages + let feedback = document.getElementById("feedback-wrapper"); + if (feedback) (0, _feedback.createFeedbackElement)(feedback); +}); +//added for the hub +window.addAnchorLinks = (0, _utils.addAnchorLinks); +window.addCopyButtons = (0, _utils.addCopyButtons); + +},{"./modules/search":"kiRSd","./modules/utils":"hWZf7","./modules/multiTab":"1bdXi","./modules/feedback":"c5ZDr"}],"kiRSd":[function(require,module,exports,__globalThis) { +var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js"); +parcelHelpers.defineInteropFlag(exports); +parcelHelpers.export(exports, "setupSearch", ()=>setupSearch); +parcelHelpers.export(exports, "searchButton", ()=>searchButton); +parcelHelpers.export(exports, "searchModal", ()=>searchModal); +const { el, mount, text, list, setChildren, setStyle, setAttr } = redom; +const projectList = [ + "Spin" +]; +const versionPattern = /^v\d+$/; +let idx; +let documents; +async function getSearchIndex() { + try { + let res = await fetch("/static/data.json"); + return await res.json(); + } catch (err) { + console.log("cannot load search module"); + } +} +// +// This function filters and builds the search index, based on which project is selected (Spin v1, V2, V3, Cloud, Etc.), +// +async function setupSearch() { + documents = await getSearchIndex(); + const match = window.location.pathname.match(/^\/(v\d+)\//); + const version = match ? match[1] : "v3"; + documents = documents.filter((doc)=>{ + if (!doc.url) return false; + const urlVersion = doc.url.split("/")[1]; + return urlVersion === version; + }); + idx = lunr(function() { + this.field("title"); + this.field("subheading"); + this.field("content"); + this.field("keywords", { + boost: 100 + }); + this.field("subsectionKeywords", { + boost: 100 + }); + this.ref("url"); + documents.forEach(function(doc) { + this.add(doc); + }, this); + }); +} +class SearchButton { + constructor(modal){ + this.modal = modal; + this.el = el("button.search-button", { + onclick: (function(e) { + this.modal.open(); + }).bind(this) + }, []); + let mobileSearch = document.getElementById("mobile-search"); + if (mobileSearch) { + mobileSearch.classList.add("enable"); + mobileSearch.addEventListener("click", ()=>{ + this.modal.open(); + }); + } + } +} +class SearchResultSubHeading { + constructor(){ + this.itemIcon = el("span.result-item-icon", "#"); + this.link = el("span"); + this.el = el("a.result-subitem", { + onclick: function(e) { + searchModal.close(); + } + }, [ + this.itemIcon, + this.link + ]); + } + update(data) { + this.link.textContent = data.subheading; + this.el.href = data.url; + // Hide listing where the subheading is empty + if (data.subheading == "") setStyle(this.el, { + display: "none" + }); + else setStyle(this.el, { + display: "flex" + }); + } +} +class SearchResultItem { + constructor(){ + this.subheading = list("div.result-subheading-container", SearchResultSubHeading); + this.projectName = el("code.project-name"); + this.pageTitle = el("span"); + this.title = el("a", this.pageTitle, this.projectName); + this.el = el("div.result-block", [ + this.title, + this.subheading + ]); + } + update(data) { + this.pageTitle.textContent = data.title; + this.projectName.textContent = data.project; + this.title.href = data.url; + this.subheading.update(data.data); + } +} +class ResultFilterItem { + constructor(){ + this.index; + this.active = true; + this.parentCallback; + this.el = el("code.active", { + onclick: (function(e) { + this.toggle(); + }).bind(this) + }); + } + update(data, index, item, context) { + this.parentCallback = context.callback; + this.index = index; + context.reset && (this.active = true); + if (this.active) this.el.classList.add("active"); + this.el.textContent = data; + } + toggle() { + this.active = !this.active; + if (this.active) this.el.classList.add("active"); + else this.el.classList.remove("active"); + this.parentCallback(this.index, this.active); + } +} +class SearchResultFilter { + constructor(categories, callback){ + this.categories = categories; + this.parentCallback = callback; + this.active = [ + true, + true, + true + ]; + this.activefilter = categories.map((k)=>k.toLowerCase()); + this.filters = list("div.filter-categories", ResultFilterItem); + this.filters.update(this.categories, { + callback: this.updateFilterSearch.bind(this) + }); + this.resetFilter = el("span.reset-filter", { + onclick: (function(e) { + this.resetFilters(); + }).bind(this) + }, "Clear filters"); + this.el = el("div.result-filters", this.filters, this.resetFilter); + } + updateFilterSearch(index, status) { + console.log(this.active, this.active[index]); + this.active[index] = status; + this.activefilter = this.categories.filter((k, i)=>{ + return this.active[i]; + }).map((k)=>{ + return k.toLowerCase(); + }); + this.parentCallback(this.activefilter); + } + resetFilters() { + this.activefilter = this.categories.map((k)=>k.toLowerCase()); + this.parentCallback(this.activefilter); + this.filters.update(this.categories, { + callback: this.updateFilterSearch.bind(this), + reset: true + }); + } +} +class SearchResult { + constructor(){ + this.data; + this.projects = projectList; + this.resultItems = list("div.result-section", SearchResultItem); + this.resultFilters = new SearchResultFilter(this.projects, this.filter.bind(this)); + this.el = el("div.result-section-container", this.resultFilters, this.resultItems); + } + update(data) { + this.data = data; + this.resultItems.update(this.data); + } + filter(filters) { + this.resultItems.update(this.data.filter((k)=>{ + return filters.includes(k.project); + })); + } +} +class ProjectRecommendations { + constructor(){ + this.link1 = el("a.suggested-project-link"); + this.link2 = el("a.suggested-project-link"); + this.link3 = el("a.suggested-project-link"); + this.link4 = el("a.suggested-project-link"); + this.projectLinks = el("div.recommended-navs", this.link1, this.link2, this.link3, this.link4); + this.projectTitle = el("div.project-title"); + this.el = el("div.suggested-project", this.projectTitle, this.projectLinks); + } + update(data) { + this.projectTitle.textContent = data.project; + this.link1.textContent = data.link1[0]; + this.link1.href = data.link1[1]; + this.link2.textContent = data.link2[0]; + this.link2.href = data.link2[1]; + this.link3.textContent = data.link3[0]; + this.link3.href = data.link3[1]; + this.link4.textContent = data.link4[0]; + this.link4.href = data.link4[1]; + } +} +// this content shouldn't live in the theme javascript, ideally be managed via the config/site.toml and shortcodes in the template html +class ModalSuggest { + constructor(){ + this.projectData = [ + { + project: "Spin", + link1: [ + "Install", + "/install" + ], + link2: [ + "Quickstart", + "/quickstart" + ], + link3: [ + "Develop", + "/writing-apps" + ], + link4: [ + "Deploy", + "/deploying" + ] + } + ]; + this.projectRecommendations = list("div.result-section", ProjectRecommendations); + this.projectRecommendations.update(this.projectData); + this.el = el("div.result-section-container", this.projectRecommendations); + } +} +class SearchModal { + constructor(){ + this.container = document.getElementById("search-modal-container"); + this.modalSearchBar = el("input.modal-search-bar", { + type: "text", + spellcheck: false, + placeholder: "Search Spin Docs", + oninput: (function(e) { + this.updateSearch(); + }).bind(this) + }); + this.searchResults = new SearchResult(); + this.modalSuggest = new ModalSuggest(); + this.modal = el("div.modal-box", { + onclick: function(e) { + e.stopPropagation(); + } + }); + this.el = el("div.modal-wrapper", { + onclick: (function(e) { + this.close(); + }).bind(this), + onkeydown: function(e) { + if (e.key != "Escape") e.stopPropagation(); + } + }, this.modal); + } + open() { + setStyle(this.container, { + display: "block" + }); + setStyle(document.body, { + overflow: "hidden", + height: "100%" + }); + this.modalSearchBar.value = ""; + setChildren(this.modal, [ + this.modalSearchBar, + this.modalSuggest + ]); + this.modalSearchBar.focus(); + } + close() { + setStyle(this.container, { + display: "none" + }); + setStyle(document.body, { + "overflow-y": "auto", + height: "auto" + }); + setChildren(this.modal, []); + } + updateSearch() { + let query = this.modalSearchBar.value; + if (query == "") { + setChildren(this.modal, [ + this.modalSearchBar, + this.modalSuggest + ]); + return; + } + let updatedQuery = query.split(" ").map((word)=>word + "^2 " + word + "* " + word + "~2").join(" "); + let result = idx.search(updatedQuery); + let matches = {}; + let data; + result.map((k)=>{ + if (k.score < 0.5) return; + data = documents.find((post)=>k.ref === post.url); + let key = data.title.replaceAll(" ", ""); + if (!matches[key]) { + matches[key] = {}; + matches[key].data = []; + } + if (data.subheading == "") matches[key].url = data.url; + else matches[key].url = data.url.slice(0, data.url.indexOf("#")); + matches[key].data.push({ + subheading: data.subheading, + url: data.url + }); + matches[key].title = data.title; + matches[key].project = data.project; + matches[key].score = matches[key].score ? matches[key].score > k.score ? matches[key].score : k.score : k.score; + }); + matches = Object.keys(matches).map((k)=>{ + return matches[k]; + }).sort(function(a, b) { + return b.score - a.score; + }).filter((k)=>{ + return k.title != undefined; + }); + this.searchResults.update(matches); + setChildren(this.modal, [ + this.modalSearchBar, + this.searchResults + ]); + } +} +let searchModal = new SearchModal(); +let searchButton = new SearchButton(searchModal); + +},{"@parcel/transformer-js/src/esmodule-helpers.js":"j7FRh"}],"j7FRh":[function(require,module,exports,__globalThis) { +exports.interopDefault = function(a) { + return a && a.__esModule ? a : { + default: a + }; +}; +exports.defineInteropFlag = function(a) { + Object.defineProperty(a, '__esModule', { + value: true + }); +}; +exports.exportAll = function(source, dest) { + Object.keys(source).forEach(function(key) { + if (key === 'default' || key === '__esModule' || Object.prototype.hasOwnProperty.call(dest, key)) return; + Object.defineProperty(dest, key, { + enumerable: true, + get: function() { + return source[key]; + } + }); + }); + return dest; +}; +exports.export = function(dest, destName, get) { + Object.defineProperty(dest, destName, { + enumerable: true, + get: get + }); +}; + +},{}],"hWZf7":[function(require,module,exports,__globalThis) { +var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js"); +parcelHelpers.defineInteropFlag(exports); +parcelHelpers.export(exports, "scrollSideMenu", ()=>scrollSideMenu); +parcelHelpers.export(exports, "addCopyButtons", ()=>addCopyButtons); +parcelHelpers.export(exports, "addAnchorLinks", ()=>addAnchorLinks); +parcelHelpers.export(exports, "changelogFilter", ()=>changelogFilter); +parcelHelpers.export(exports, "removeExpiredEvents", ()=>removeExpiredEvents); +parcelHelpers.export(exports, "header", ()=>header); +parcelHelpers.export(exports, "blogAd", ()=>blogAd); +var header = new Headroom(document.querySelector("#topbar"), { + tolerance: 5, + offset: 80 +}); +var blogAd = new Headroom(document.querySelector("#blogSlogan"), { + tolerance: 5, + offset: 300 +}); +function scrollSideMenu() { + let sidemenu = document.querySelector("aside.menu"); + if (sidemenu) { + let active = sidemenu.querySelector(".active"); + if (active) { + active.parentElement.parentElement.parentElement.firstElementChild.checked = true; + active.parentElement.parentElement.classList.add("stay-open"); + active.parentElement.parentElement.previousElementSibling.classList.add("stay-open"); + active.scrollIntoView({ + behavior: 'auto', + block: 'center', + inline: 'center', + behavior: 'smooth' + }); + } + } +} +const svgCopy = ''; +const svgCheck = ''; +const addCopyButtons = (clipboard)=>{ + document.querySelectorAll("pre > code").forEach((codeBlock)=>{ + let content = codeBlock.innerText.trim(); + let isComment = codeBlock.parentNode.previousSibling.previousSibling; + if (isComment && isComment.nodeName == "#comment") switch(isComment.textContent.trim()){ + case "@nocpy": + return; + case "@selectiveCpy": + { + let previousSlashEnding = false; + content = content.split("\n").map((k)=>{ + k = k.trim(); + let isCommand = k.startsWith("$"); + if (isCommand || previousSlashEnding == true) { + if (!k.endsWith("\\")) previousSlashEnding = false; + else previousSlashEnding = true; + return isCommand ? k.substring(1).trim() : k; + } else return undefined; + }).filter((k)=>k != undefined).join("\n"); + } + } + let button = document.createElement("button"); + button.className = "copy-code-button"; + button.type = "button"; + button.ariaLabel = "Copy code"; + button.innerHTML = svgCopy; + button.addEventListener("click", ()=>{ + clipboard.writeText(content).then(()=>{ + button.classList.add("is-success"); + button.innerHTML = svgCheck; + setTimeout(()=>{ + button.innerHTML = svgCopy; + button.classList.remove("is-success"); + }, 2000); + }, (error)=>button.innerHTML = "Error"); + }); + let pre = codeBlock.parentNode; + pre.appendChild(button); + }); +}; +const addAnchorLinks = ()=>{ + const elementsToProcess = document.querySelectorAll(".content h1, .content h2, .content h3, .content h4, .content tr"); + elementsToProcess.forEach((element)=>{ + let uniqueId; + if (element.tagName.toLowerCase() === 'tr') { + let closestHeading = element.closest('table').previousElementSibling; + while(closestHeading && !closestHeading.matches('h1, h2, h3, h4'))closestHeading = closestHeading.previousElementSibling; + const firstColumnName = element.cells[0].textContent.trim().toLowerCase().replace(/[^\w\s-]/g, '').replace(/\s+/g, '-'); + if (closestHeading) { + const headingId = closestHeading.getAttribute('id'); + uniqueId = `${headingId}-${firstColumnName}`; + } else uniqueId = firstColumnName; + } else uniqueId = element.textContent.trim().toLowerCase().replace(/[^\w\s-]/g, '').replace(/\s+/g, '-'); + element.classList.add("heading-anchor"); + element.setAttribute('id', uniqueId); + let anchor = document.createElement('a'); + anchor.className = 'anchor-link'; + anchor.href = '#' + uniqueId; + anchor.innerHTML = ''; + element.append(anchor); + anchor.addEventListener("click", (e)=>{ + e.preventDefault(); + window.location = anchor.href; + let targetId = anchor.getAttribute('href').substring(1); + let targetElement = document.getElementById(targetId); + if (targetElement) targetElement.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); + }); + }); +}; +function removeExpiredEvents() { + let events = document.querySelectorAll(".community-highlight .carousel-cell"); + let eventsNumber = events.length; + if (eventsNumber) events.forEach((k)=>{ + if (k.dataset.expirydate) { + let eventExpiryDate = new Date(k.dataset.expirydate); + if (eventExpiryDate < Date.now()) { + k.remove(); + eventsNumber--; + } + } + }); + else return; + if (eventsNumber) ; + else { + let eventsCarousel = document.querySelector(".community-highlight"); + eventsCarousel.innerHTML = ` - `)),x();let n=document.querySelector("aside.menu");if(n){let t=n.querySelector(".active");t&&(t.parentElement.parentElement.parentElement.firstElementChild.checked=!0,t.parentElement.parentElement.classList.add("stay-open"),t.parentElement.parentElement.previousElementSibling.classList.add("stay-open"),t.scrollIntoView({behavior:"auto",block:"center",inline:"center",behavior:"smooth"}))}new O,window.location.hash.length>0&&(setTimeout(function(){document.querySelector('a[href="'+window.location.hash+'"]').click()},150),y.unpin()),async function(){try{await d(),U(document.getElementById("search-button-container"),w),U(document.getElementById("search-modal-container"),k),document.onkeydown=function(t){if("Escape"==t.key&&k.close(),("k"==t.key||"K"==t.key)&&(t.metaKey||t.ctrlKey)&&(t.preventDefault(),t.stopPropagation(),k.open()),"s"==t.key||"S"==t.key){let e=document.getElementById("hub-search-input");e&&document.activeElement!=e&&(t.preventDefault(),e.focus())}}}catch(t){console.error("Could not setup search")}}();let a=document.getElementById("feedback-wrapper");a&&q(a,new K)}),window.addAnchorLinks=x,window.addCopyButtons=L})(); \ No newline at end of file + `; + } +} +function changelogFilter() { + let changelogItems = Array.from(document.querySelectorAll(".changelog-item-title")); + if (changelogItems.length) { + let changelogTags = new Set([ + "all_features" + ]); + changelogItems.map((k)=>{ + JSON.parse(k.dataset.tags).forEach((item)=>changelogTags.add(item)); + }); + changelogTags = Array.from(changelogTags); + let changelogSelect = document.getElementById("changelog-select"); + changelogTags.map((k)=>{ + let opt = document.createElement('option'); + opt.value = k; + opt.innerHTML = k; + changelogSelect.appendChild(opt); + }); + changelogSelect.addEventListener("change", ()=>{ + let selected = changelogSelect.value; + changelogItems.map((k)=>{ + if (selected != "all_features" && !k.dataset.tags.includes(selected)) { + console.log(k.parentElement); + k.parentElement.style.display = "none"; + } else k.parentElement.style.display = "flex"; + }); + }); + } +} + +},{"@parcel/transformer-js/src/esmodule-helpers.js":"j7FRh"}],"1bdXi":[function(require,module,exports,__globalThis) { +var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js"); +parcelHelpers.defineInteropFlag(exports); +parcelHelpers.export(exports, "multiTabContentHandler", ()=>multiTabContentHandler); +const { el, mount, text, list, setChildren, setStyle, setAttr } = redom; +class codeblockLanguageTab { + constructor(parentCallback){ + this.index; + this.parentCallback = parentCallback; + this.lang = el("a"); + this.el = el("li", { + onclick: (function(e) { + parentCallback(this.index, e.target); + }).bind(this) + }, this.lang); + } + update(data, index, items, context) { + this.index = index; + this.lang.textContent = data; + if (context.active == this.index) this.lang.classList.add("is-active"); + else this.lang.classList.remove("is-active"); + } +} +class multiTabBlockHandler { + constructor(nodes, tabClass, activeValue, parentCallback){ + this.tabClass = tabClass; + this.parentCallback = parentCallback; + this.nodes = Array.from(nodes); + this.langs = this.nodes.map((k)=>{ + return k.dataset.title; + }); + this.active = this.langs.indexOf(activeValue); + if (tabClass != "spin-version") this.active = this.active > 0 ? this.active : 0; + else this.active = this.active > 0 ? this.active : this.nodes.length - 1; + this.tabs = list("ul", codeblockLanguageTab, null, this.ChildEventHandler.bind(this)); + this.el = el("div.tabs.is-boxed", this.tabs); + // If the tabClass is `spin-version` reverse the order of the list + if (tabClass === "spin-version") setStyle(this.tabs, { + display: "flex", + "flex-direction": "row-reverse" + }); + this.tabs.update(this.langs, { + active: this.active + }); + this.updateTabContent(this.active); + } + ChildEventHandler(data, element) { + this.tabs.update(this.langs, { + active: data + }); + this.updateTabContent(data); + this.parentCallback(this.tabClass, this.langs[data], true, true, element); + } + updateTabContent(data) { + for(let i = 0; i < this.nodes.length; i++)setStyle(this.nodes[i], { + display: i == data ? "block" : "none" + }); + } + globalTabUpdate(data) { + let activeIndex = this.langs.indexOf(data); + if (activeIndex < 0) return; + this.tabs.update(this.langs, { + active: activeIndex + }); + this.updateTabContent(activeIndex); + } +} +class multiTabContentHandler { + constructor(){ + this.selectedTab = JSON.parse(localStorage.getItem("toggleTabSelections")) || { + os: null + }; + // Set defaults specified in the query parameter + let queryParamSelectors = filterMultitabQuery(); + Object.keys(queryParamSelectors).map((k)=>{ + this.selectedTab[k] = queryParamSelectors[k]; + }); + // If no OS preference set, try detect the user OS + if (this.selectedTab.os == null) this.selectedTab.os = detectOS(); + this.handler = []; + let multiTabBlocks = document.querySelectorAll("div.multitab-content-wrapper"); + multiTabBlocks.forEach((multiTabBlock, index)=>{ + let tabs = multiTabBlock.querySelectorAll("div.multitab-content"); + this.handler[index] = {}; + this.handler[index].class = multiTabBlock.dataset.class.toLowerCase(); + this.handler[index].tabBlock = new multiTabBlockHandler(tabs, this.handler[index].class, this.selectedTab[this.handler[index].class], this.updateTabs.bind(this)); + multiTabBlock.insertBefore(this.handler[index].tabBlock.el, multiTabBlock.firstChild); + }); + Object.keys(this.selectedTab).map((k)=>{ + if (this.selectedTab[k]) this.updateTabs(k, this.selectedTab[k], false); + }); + window.addEventListener('storage', (e)=>{ + if (e.key == "toggleTabSelections") Object.keys(this.selectedTab).map((k)=>{ + this.selectedTab = JSON.parse(localStorage.getItem("toggleTabSelections")) || this.selectedTab; + if (this.selectedTab[k]) this.updateTabs(k, this.selectedTab[k], false); + }); + }); + } + updateTabs(tabClass, value, updateLocalStorage, isUserEvent, element) { + if (tabClass == "soloblock") return; + this.selectedTab[tabClass] = value; + let originalOffset, newOffset; + if (isUserEvent) originalOffset = element.getBoundingClientRect().top; + this.handler.map((k)=>{ + if (k.class == tabClass) k.tabBlock.globalTabUpdate(value); + }); + if (isUserEvent) { + newOffset = element.getBoundingClientRect().top + document.documentElement.scrollTop; + window.scroll(0, newOffset - originalOffset); + } + if (updateLocalStorage) localStorage.setItem("toggleTabSelections", JSON.stringify(this.selectedTab)); + } +} +function detectOS() { + let OS = null; + let userAgent = navigator.userAgent.toLowerCase(); + switch(true){ + case userAgent.indexOf("win") != -1: + OS = "Windows"; + break; + case userAgent.indexOf("mac") != -1: + OS = "macOS"; + break; + case userAgent.indexOf("linux") != -1: + OS = "Linux"; + break; + } + return OS; +} +function filterMultitabQuery() { + let queryString = window.location.search; + let urlParams = new URLSearchParams(queryString); + let query = Object.fromEntries(urlParams.entries()); + let multitabQuery = Object.keys(query).filter((k)=>{ + return k.indexOf("multitab_") == 0; + }).reduce((obj, key)=>{ + obj[key.replace("multitab_", "")] = query[key]; + return obj; + }, {}); + return multitabQuery; +} + +},{"@parcel/transformer-js/src/esmodule-helpers.js":"j7FRh"}],"c5ZDr":[function(require,module,exports,__globalThis) { +var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js"); +parcelHelpers.defineInteropFlag(exports); +parcelHelpers.export(exports, "createFeedbackElement", ()=>createFeedbackElement); +const { el, mount, textContent, list, setChildren, setStyle, setAttr } = redom; +class FeedBack { + constructor(){ + this.pageTitle = document.querySelector(".blog-post-title").innerText; + this.promptDelay = 5000; + this.prompt = el("div.statement", "Did you find the answers you were looking for?"); + this.close = el("div.close", { + onclick: (function(e) { + setStyle(this.el, { + display: "none" + }); + }).bind(this) + }); + this.thumbsUp = el("button.feedback-button", { + onclick: (function(e) { + this.submitSatisfactionForm("satisfied"); + this.closeFeedback(); + }).bind(this) + }); + this.thumbsUp.innerHTML = ` + + + `; + this.thumbsDown = el("button.feedback-button", { + onclick: (function(e) { + this.submitSatisfactionForm("not satisfied"); + this.notFindingFeedback(); + }).bind(this) + }); + this.thumbsDown.innerHTML = ` + + + `; + this.buttonContainer = el("div.feedback-response-container", this.thumbsUp, this.thumbsDown); + this.feedback = el("textarea"); + this.actionLink = el("button.button.is-primary", { + onclick: (function(e) { + this.submitFeedbackForm(); + }).bind(this) + }, "submit"); + this.el = el("div.feedback-modal", this.close, this.prompt, this.buttonContainer); + let a = setInterval(()=>{ + if (this.checkForScroll()) clearInterval(a); + }, 250); + let observer = new IntersectionObserver((entries)=>{ + if (entries[0].isIntersecting) this.el.parentNode.classList.add("end-of-page"); + else this.el.parentNode.classList.remove("end-of-page"); + }, { + rootMargin: "0px 0px 100px 0px", + threshold: [ + 0.5 + ] + }); + observer.observe(document.querySelector("#end-of-content")); + } + async submitSatisfactionForm(satisfaction) { + let data = { + page: this.pageTitle, + satisfaction: satisfaction + }; + await fetch("https://submit-form.com/KjF5CuTg", { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json" + }, + body: JSON.stringify(data) + }); + } + async submitFeedbackForm() { + let content = this.feedback.value; + if (content) { + let data = { + page: this.pageTitle, + url: window.location.pathname, + config: localStorage.getItem("toggleTabSelections"), + feedback: content + }; + await fetch("https://submit-form.com/c3jrxv8A", { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json" + }, + body: JSON.stringify(data) + }); + this.prompt.textContent = "Thanks for submitting the feedback"; + setChildren(this.el, [ + this.close, + this.prompt + ]); + setTimeout(()=>{ + this.closeFeedback(); + }, 10000); + } + } + closeFeedback() { + this.parent = this.el.parentNode.parentNode; + console.log(this.parent); + setStyle(this.el, { + opacity: 0 + }); + setStyle(this.parent, { + opacity: 0, + transition: "opacity 1s ease-in-out" + }); + } + notFindingFeedback() { + this.prompt.textContent = "Let us know what you are looking for!"; + setChildren(this.el, [ + this.close, + this.prompt, + this.feedback, + this.actionLink + ]); + } + checkForScroll() { + let percentage = window.scrollY / (document.body.offsetHeight - window.innerHeight); + if (percentage > 0.5 || document.body.offsetHeight - window.innerHeight < 500) { + setStyle(this.el, { + opacity: 1, + "z-index": 998 + }); + return true; + } + return false; + } +} +function createFeedbackElement(handle) { + const feedback = new FeedBack(); + mount(handle, feedback); +} + +},{"@parcel/transformer-js/src/esmodule-helpers.js":"j7FRh"}]},["jdgog","e9rxa"], "e9rxa", "parcelRequire8afe", {}) + diff --git a/static/js/src/modules/search.js b/static/js/src/modules/search.js index 9c5ee06c2..0764f0a07 100644 --- a/static/js/src/modules/search.js +++ b/static/js/src/modules/search.js @@ -45,8 +45,6 @@ async function setupSearch() { class SearchButton { constructor(modal) { this.modal = modal; - this.searchPlaceholder = el("span.search-placeholder", "Search"); - this.searchCommand = el("span.search-command", "⌘/ctrl + K"); this.el = el( "button.search-button", { @@ -54,7 +52,7 @@ class SearchButton { this.modal.open(); }.bind(this), }, - [this.searchPlaceholder, this.searchCommand], + [], ); let mobileSearch = document.getElementById("mobile-search"); diff --git a/static/sass/developer-include-search.scss b/static/sass/developer-include-search.scss index c625c00cc..c6497e930 100644 --- a/static/sass/developer-include-search.scss +++ b/static/sass/developer-include-search.scss @@ -12,10 +12,10 @@ } .search-button-container { - display: inline-block; - position: absolute; + display: flex; + flex: 1; + justify-content: flex-end; width: 100%; - display: block; top: 0; left: 2px; bottom: 0; @@ -35,11 +35,9 @@ .search-button { border: none !important; - padding: 0.8rem 25rem 0.8rem 0.8rem; z-index: 19; cursor: text; display: block; - width: 100%; height: 4.333rem; background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 100%); text-align: right; @@ -65,22 +63,10 @@ } } - &:before { - height: 2rem; - width: 1px; - background: $lavendermid; - right: 30.5rem; - top: 1rem; - display: block; - content: " "; - position: absolute; - } - &:after { background: url('/static/image/search.svg') no-repeat 0 0; background-size: cover; display: inline-block; - position: absolute; z-index: -1; height: 1.35rem; width: 1.35rem; @@ -89,63 +75,15 @@ right: 31.35rem; } - .search-command { - opacity: 0; - position: absolute; - top: 2.35rem; - right: 34rem; - @include transition; - } - - .search-placeholder { - font-family: $mono; - font-size: 1rem; - opacity: 0; - color: darken($lavender, 10%); - font-weight: normal; - min-width: 6.5vw; - display: inline-block; - @include transition; - position: absolute; - right: 43.33rem; - top: 1.5rem; - text-align: left; - } + &:hover { background: rgb(255, 255, 255); background: linear-gradient(0deg, rgba(255, 255, 255, 0.5) 0%, rgba(255, 255, 255, 0) 100%); - .search-placeholder, - .search-command { - opacity: 1; - } - } - - @media screen and (min-width: 1024px) and (max-width: 1214px) { - - .search-placeholder, - .search-command { - display: none; - } + } -} - -.search-placeholder { - padding: 0 1rem 0 1rem; - font-weight: 600; - font-size: 0.8rem; -} - -.search-command { - background-color: white; - color: #345995; - padding: 0.333em 0.5em 0.333em; - display: inline-block; - margin-top: -1rem; - font-size: 0.7rem; - border-radius: 0.667rem; } .modal-wrapper { @@ -462,10 +400,6 @@ html.dark-theme { } } - .search-button .search-placeholder { - color: $lightlavender; - } - .search-button { color: white; border: none !important; @@ -475,11 +409,6 @@ html.dark-theme { } } - .search-command { - background-color: rgba($darkspace, 0.5); - color: $lightlavender; - } - // results .search-modal-container { diff --git a/static/sass/developer-include-topbar.scss b/static/sass/developer-include-topbar.scss index 822a50a6a..26a69360c 100644 --- a/static/sass/developer-include-topbar.scss +++ b/static/sass/developer-include-topbar.scss @@ -290,8 +290,11 @@ .navbar-menu { position: relative; z-index: 1020; - + display: flex; + .navbar-start { + display: flex; + flex: 1; z-index: 1023; align-items: center; diff --git a/templates/content_navbar.hbs b/templates/content_navbar.hbs index 622c188fe..fafdb3e1d 100644 --- a/templates/content_navbar.hbs +++ b/templates/content_navbar.hbs @@ -40,6 +40,8 @@ Tutorials Starter guides for Spin's features --}} +
+ - -
\ No newline at end of file