diff --git a/assets/js/search-google.js b/assets/js/search-google.js new file mode 100644 index 0000000000000..2589c46b8f93b --- /dev/null +++ b/assets/js/search-google.js @@ -0,0 +1,45 @@ +/* +Copyright 2018 Google LLC +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + https://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +(function ($) { + "use strict"; + + var Search = { + init: function () { + $(document).ready(function () { + // Fill the search input form with the current search keywords + const searchKeywords = new URLSearchParams(location.search).get('q'); + if (searchKeywords !== null && searchKeywords !== '') { + const searchInput = document.querySelector('.td-search-input'); + searchInput.focus(); + searchInput.value = searchKeywords; + } + + // Set a keydown event + $(document).on("keypress", ".td-search-input", function (e) { + if (e.keyCode !== 13) { + return; + } + + var query = $(this).val(); + var searchPage = $(this).closest('form').data('search-page') + "?q=" + query; + document.location = searchPage; + + return false; + }); + }); + }, + }; + + Search.init(); +})(jQuery); diff --git a/assets/js/search.js b/assets/js/search.js index d786cef0f0ddb..e3780991739d4 100644 --- a/assets/js/search.js +++ b/assets/js/search.js @@ -1,45 +1,108 @@ -/* -Copyright 2018 Google LLC -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - https://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -(function ($) { - "use strict"; - - var Search = { - init: function () { - $(document).ready(function () { - // Fill the search input form with the current search keywords - const searchKeywords = new URLSearchParams(location.search).get('q'); - if (searchKeywords !== null && searchKeywords !== '') { - const searchInput = document.querySelector('.td-search-input'); - searchInput.focus(); - searchInput.value = searchKeywords; - } + document.querySelector('html').classList.add('search'); + + document.addEventListener('DOMContentLoaded', function() { + let searchTerm = new URLSearchParams(window.location.search).get('q'); + let fetchingElem = document.getElementById('bing-results-container'); - // Set a keydown event - $(document).on("keypress", ".td-search-input", function (e) { - if (e.keyCode !== 13) { - return; - } + if (!searchTerm) { + if (fetchingElem) fetchingElem.style.display = 'none'; + } + }); - var query = $(this).val(); - var searchPage = $(this).data('search-page') + "?q=" + query; - document.location = searchPage; + window.renderGoogleSearchResults = () => { + var cx = '013288817511911618469:elfqqbqldzg'; + var gcse = document.createElement('script'); + gcse.type = 'text/javascript'; + gcse.async = true; + gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//cse.google.com/cse.js?cx=' + cx; + var s = document.getElementsByTagName('script')[0]; + s.parentNode.insertBefore(gcse, s); + } + + window.renderPageFindSearchResults = () => { + let urlParams = new URLSearchParams(window.location.search); + let searchTerm = urlParams.get("q") || ""; + let sidebarSearch = document.querySelector('.td-sidebar__search'); + if (sidebarSearch) { + sidebarSearch.remove(); + } + document.getElementById('search').style.display = 'block'; + pagefind = new PagefindUI({ element: "#search", showImages: false }); + if (searchTerm) { + pagefind.triggerSearch(searchTerm); + } - return false; + document.querySelector("#search input").addEventListener("input", function() { + var inputValue = this.value; + var queryStringVar = "q"; + updateQueryString(queryStringVar, inputValue); }); - }); - }, - }; + } + + function updateQueryString(key, value) { + var baseUrl = window.location.href.split("?")[0]; + var queryString = window.location.search.slice(1); + var urlParams = new URLSearchParams(queryString); + + if (urlParams.has(key)) { + urlParams.set(key, value); + } else { + urlParams.append(key, value); + } + + var newUrl = baseUrl + "?" + urlParams.toString(); + // Update the browser history (optional) + history.replaceState(null, '', newUrl); + } + + // China Verification. + var path = "path=/;" + d = new Date() + d.setTime(d.getTime() + (7 * 24 * 60 * 60 * 1000)) + expires = "expires=" + d.toUTCString() + + function getCookie(name) { + var value = "; " + document.cookie; + var parts = value.split("; " + name + "="); + if (parts.length == 2) return parts.pop().split(";").shift(); + else return ""; + } + + async function checkBlockedSite(url) { + const controller = new AbortController(); + const timeout = setTimeout(() => { + controller.abort(); + }, 5000); // Timeout set to 5000ms (5 seconds) + + try { + const response = await fetch(url, { method: 'HEAD', mode: 'no-cors', signal: controller.signal }); + // If we reach this point, the site is accessible (since mode: 'no-cors' doesn't allow us to check response.ok) + clearTimeout(timeout); + return false; + } catch (error) { + // If an error occurs, it's likely the site is blocked + return true; + } + } + + async function loadSearch() { + if (getCookie("can_google") === "") { + const isGoogleBlocked = await checkBlockedSite("https://www.google.com/favicon.ico"); + if ( isGoogleBlocked ) { + // Google is blocked. + document.cookie = "can_google=false;" + path + expires + window.renderPageFindSearchResults() + } else { + // Google is not blocked. + document.cookie = "can_google=true;" + path + expires + window.renderGoogleSearchResults() + } + } else if (getCookie("can_google") == "false") { + window.renderPageFindSearchResults() + } else { + window.renderGoogleSearchResults() + } + } + + window.onload = loadSearch; - Search.init(); -})(jQuery); diff --git a/assets/scss/_custom.scss b/assets/scss/_custom.scss index ac7737dfd481b..73d6fd6827a73 100644 --- a/assets/scss/_custom.scss +++ b/assets/scss/_custom.scss @@ -115,6 +115,23 @@ body.td-home main[role="main"] > section:first-of-type .content p:first-child { margin-bottom: 1.5em; } +// Style search on main (landing) page +body.td-home section.k8s-search { + margin-left: 0; + margin-right: 0; + padding: 3rem; + padding-left: calc(max(2rem, (100vw - 44rem) / 2)); + padding-right: calc(max(2rem, (100vw - 44rem) / 2)); + + .search-bar { + // center align, allocate space + + form input.search-input.td-search-input { + max-width: initial; + } + } +} + #desktopShowVideoButton { border: none } @@ -289,11 +306,41 @@ body.td-404 main .error-details { } } -input[type="search"]{ +input[type="search"] { -moz-box-sizing: border-box; width: 100%; } +nav .search-bar { + &:has(input:focus) { + outline: 0.05rem solid $primary; + } + min-height: calc(max(2em, 2rem)); + > form { + vertical-align: middle; + + } +} +.search-bar { + padding-left: 0.75em; + + input.search-input:focus { + outline: none; + } +} + +// suppress search / magnifying glass icon on main page +.k8s-search .search-bar i.fa { + display: none; +} + +.search-bar form input.search-input.td-search-input { + max-width: 90%; + background: transparent; + display: inline-block; + padding: 1px; +} + .flip-nav .search-item { .td-search-input, .search-bar { background-color: $medium-grey; @@ -306,9 +353,9 @@ input[type="search"]{ } } -@media only screen and (max-width: 1500px) { +@media only screen and (max-width: 1400px) { header nav .search-item { - display: none; + display: none !important; } } @@ -1475,7 +1522,7 @@ body.cid-code-of-conduct main { } .td-sidebar__inner { - form.td-sidebar__search { + div.td-sidebar__search { .td-sidebar__toggle { &:hover { @@ -1485,6 +1532,10 @@ body.cid-code-of-conduct main { color: $primary; margin: 1rem; } + + .search-bar form > input { + padding-left: 1.5em; + } } } @@ -1848,16 +1899,11 @@ div.alert > em.javascript-required { } -// Adjust Search-bar search-icon .search-bar { - display: flex; - align-items: center; background-color: #fff; border: 1px solid #4c4c4c; border-radius: 20px; vertical-align: middle; - flex-grow: 1; - overflow-x: hidden; width: auto; &:focus-within { @@ -1866,16 +1912,10 @@ div.alert > em.javascript-required { } } -.search-bar i.search-icon { - padding: .5em .5em .5em .75em; - opacity: .75; -} - -.search-input { +input.search-input { flex: 1; border: none; outline: none; - padding: .5em 0 .5em 0; } // PageFind Styles @@ -1932,9 +1972,14 @@ div.alert > em.javascript-required { font-size: 1.15rem; } -body.td-search #search { - margin-top: 1rem; - margin-bottom: 3rem; +body.td-search { + section.td-search-query { + padding: 3rem; + } + #search { + margin-top: 1rem; + margin-bottom: 3rem; + } } /* CSS for 'figure' full-screen display */ @@ -2025,4 +2070,4 @@ section.k8s-birthday-override:has(div.k8s-birthday-override.revert-to-previous i @extend .table; } } -} \ No newline at end of file +} diff --git a/hugo.toml b/hugo.toml index e95a6b2fce854..dcb3f8ada5b1d 100644 --- a/hugo.toml +++ b/hugo.toml @@ -150,9 +150,6 @@ githubWebsiteRaw = "raw.githubusercontent.com/kubernetes/website" # GitHub repository link for editing a page and opening issues. github_repo = "https://github.com/kubernetes/website" -# Searching -k8s_search = true - # The following search parameters are specific to Docsy's implementation. Kubernetes implementes its own search-related partials and scripts. # Google Custom Search Engine ID. Remove or comment out to disable search. @@ -208,6 +205,8 @@ url = "https://v1-28.docs.kubernetes.io" # User interface configuration [params.ui] +# Searching (eg via Google / Bing). Customized from Docsy's usual search. +search = true # Enable to show the side bar menu in its compact state. sidebar_menu_compact = false # Show this many levels in compact mode @@ -224,6 +223,8 @@ sidebar_search_disable = false navbar_logo = true # Set to true to disable the About link in the site footer footer_about_disable = false +# Enable searching from the top nav bar +top_nav_bar_search = true # Adds a H2 section titled "Feedback" to the bottom of each doc. The responses are sent to Google Analytics as events. # This feature depends on [services.googleAnalytics] and will be disabled if "services.googleAnalytics.id" is not set. diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html index 4a82539d1074e..fd7203117b4d6 100644 --- a/layouts/_default/baseof.html +++ b/layouts/_default/baseof.html @@ -38,6 +38,6 @@