diff --git a/docs/conf.py b/docs/conf.py index 5cebae49..128c1777 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -56,7 +56,7 @@ "first_notebook_cell": ("%matplotlib inline"), } -# pytorch_project = "tutorials" +pytorch_project = "docs" # torch_version = str(torch.__version__) # Temporarily commented out for testing torch_version = "2.0.0" # Hardcoded for testing version = "main (" + torch_version + " )" @@ -269,7 +269,7 @@ # "llm_description": "PyTorch is an optimized tensor library for deep learning", # "llm_important_pages": "index, notes/cuda", # "enable_navbar_dropdowns": False, - # "pytorch_project": "tutorials", + "pytorch_project": "docs", # "show_lf_header": False, # "show_lf_footer": False, # RunLLM Widget Configuration (uncomment and set assistant_id to enable) diff --git a/pytorch_sphinx_theme2/static/css/theme.css b/pytorch_sphinx_theme2/static/css/theme.css index 8aacb74d..8710f618 100644 --- a/pytorch_sphinx_theme2/static/css/theme.css +++ b/pytorch_sphinx_theme2/static/css/theme.css @@ -1542,11 +1542,11 @@ input:checked + .slider:before { #gsc-i-id1 { height: 1.5rem; - text-indent: 12px !important; + text-indent: 0 !important; font-size: 1rem !important; font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; - background-position: 5px 0px !important; - padding-left: 20px !important; + background-image: none !important; + padding-left: 8px !important; color: var(--pst-color-text-base) !important; position: relative; z-index: 10; @@ -1583,24 +1583,19 @@ table.gsc-search-box td { } .gsc-search-button { - margin-left: 0 !important; + display: none !important; + width: 0 !important; + overflow: hidden !important; + padding: 0 !important; } .gsc-search-button-v2 { - padding: 9px 16px !important; - border-radius: 0 0.25rem 0.25rem 0 !important; - background-color: var(--pst-color-primary) !important; - border-color: var(--pst-color-primary) !important; - margin-left: -1px !important; - height: 38px !important; -} -.gsc-search-button-v2 svg { - fill: white !important; - width: 13px !important; - height: 13px !important; + display: none !important; } -.gsc-search-button-v2 { +td.gsc-search-button { display: none !important; + width: 0 !important; + padding: 0 !important; } .gcs-branding { @@ -1679,6 +1674,23 @@ table.gsc-search-box td { font-weight: bold !important; } +.gs-image-box, +.gs-image, +.gsc-table-result .gs-image-box, +.gsc-url-top .gs-image { + display: none !important; +} + +.gs-image-box a img { + display: none !important; +} + +.gsc-table-result td.gsc-table-cell-thumbnail { + display: none !important; + width: 0 !important; + padding: 0 !important; +} + .gsc-table-result { font-family: var(--pst-font-family-base) !important; } @@ -1722,6 +1734,50 @@ table.gsc-search-box td { fill: var(--pst-color-primary) !important; } +.google-search-suggestions { + display: none; + position: absolute; + top: 38px; + left: 0; + right: 0; + background-color: var(--pst-color-background); + border: 1px solid var(--pst-color-border); + border-top: none; + border-radius: 0 0 0.5rem 0.5rem; + z-index: 10001; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + max-height: 320px; + overflow-y: auto; + padding: 0.25rem 0; +} + +.google-suggest-item { + padding: 0.5rem 0.75rem; + cursor: pointer; + font-size: 0.9rem; + color: var(--pst-color-text-base); + font-family: var(--pst-font-family-base); + display: flex; + align-items: center; + gap: 0.6rem; + transition: background-color 0.1s ease; +} +.google-suggest-item::before { + content: "\f002"; + font-family: "Font Awesome 6 Free"; + font-weight: 900; + font-size: 0.75rem; + color: var(--pst-color-text-muted); + flex-shrink: 0; +} +.google-suggest-item:hover, .google-suggest-item.active { + background-color: var(--pst-color-primary); + color: white; +} +.google-suggest-item:hover::before, .google-suggest-item.active::before { + color: white; +} + .gssb_c { box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1) !important; border: 1px solid var(--pst-color-border) !important; @@ -1758,13 +1814,57 @@ body.gsc-overflow-hidden.search-page .footer-article-item .feedback-send { display: none !important; } -body.gsc-overflow-hidden .gsc-results-wrapper-overlay  { +body.gsc-overflow-hidden .gsc-results-wrapper-overlay { position: fixed !important; - z-index: 10000  !important; - max-width: 1000px; - left: 50%; + z-index: 10000 !important; + max-width: 900px !important; + width: 90vw !important; + left: 50% !important; right: auto !important; - transform: translate(-50%); + top: 70px !important; + transform: translateX(-50%) !important; + background-color: var(--pst-color-background) !important; + border: 1px solid var(--pst-color-border) !important; + border-radius: 0.5rem !important; + box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2) !important; + max-height: calc(100vh - 100px) !important; + overflow-y: auto !important; + padding: 0.5rem 0.75rem !important; +} + +.gsc-results-close-btn { + position: absolute !important; + top: 8px !important; + right: 8px !important; + width: 30px !important; + height: 30px !important; + cursor: pointer !important; + border: 1px solid var(--pst-color-border) !important; + border-radius: 50% !important; + z-index: 10001 !important; + background: var(--pst-color-background) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z' fill='%23666'/%3E%3C/svg%3E") center/16px no-repeat !important; +} + +.gsc-results-close-btn:hover { + background-color: var(--pst-color-on-surface) !important; +} + +.gsc-webResult.gsc-result { + padding: 0.5rem 0 !important; + border-bottom: 1px solid var(--pst-color-border) !important; +} + +.gsc-wrapper { + padding: 0 !important; +} + +.gsc-expansionArea { + padding: 0 !important; +} + +.gsc-positioningWrapper { + margin: 0 !important; + padding: 0 !important; } .version-switcher__menu { @@ -1904,12 +2004,11 @@ body.gsc-overflow-hidden:not(.search-page) .bd-main, body.gsc-overflow-hidden:no #gsc-i-id1 { height: 1.5rem; - text-indent: 12px !important; + text-indent: 0 !important; font-size: 1rem !important; font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; - background-size: 18px 18px !important; - background-position: 5px 0px !important; - padding-left: 20px !important; + background-image: none !important; + padding-left: 8px !important; color: var(--pst-color-text-base) !important; position: relative; z-index: 10; @@ -1964,6 +2063,17 @@ body.search-page.gsc-overflow-hidden .footer-article-item .feedback-send { top: 0.5em !important; } +@media (max-width: 991.98px) { + .sidebar-header-items__end .navbar-item .search-container-wrapper .search-toggle-container { + display: none !important; + } + .sidebar-header-items__end .navbar-item .search-container-wrapper #google-search { + display: none !important; + } + .sidebar-header-items__end .navbar-item .search-container-wrapper #sphinx-search { + display: block !important; + } +} @media (max-width: 991.98px) { .bd-sidebar-primary .sidebar-header-items .sidebar-header-items__end { align-items: flex-start !important; @@ -2570,12 +2680,128 @@ a.btn { margin-right: 0.5rem; } +.announcement-banner { + background-color: #CC2FAA; + color: #ffffff; + padding: 0.25rem 1rem; + position: relative; + width: 100%; + text-align: center; +} +.announcement-banner.is-visible { + animation: announcementSlideDown 0.3s ease-out; +} +.announcement-banner.is-hiding { + animation: announcementSlideUp 0.3s ease-out; +} +.announcement-banner .announcement-banner-container { + display: flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + max-width: 100%; + margin: 0 auto; + flex-wrap: wrap; +} +.announcement-banner .announcement-banner-icon { + flex-shrink: 0; +} +.announcement-banner .announcement-banner-icon i { + font-size: 0.8rem; +} +.announcement-banner .announcement-banner-text { + font-size: 0.8rem; + font-weight: 500; + line-height: 1.3; +} +.announcement-banner .announcement-banner-link { + flex-shrink: 0; + color: #ffffff; + text-decoration: underline; + font-weight: 600; + font-size: 0.8rem; + transition: opacity 0.2s ease; +} +.announcement-banner .announcement-banner-link:hover { + opacity: 0.85; + text-decoration: underline; + color: #ffffff; +} +.announcement-banner .announcement-banner-close { + flex-shrink: 0; + background: transparent; + border: none; + color: #ffffff; + cursor: pointer; + padding: 0.15rem 0.35rem; + margin-left: 0.5rem; + opacity: 0.8; + transition: opacity 0.2s ease; + border-radius: 3px; +} +.announcement-banner .announcement-banner-close:hover { + opacity: 1; +} +.announcement-banner .announcement-banner-close:focus { + outline: 2px solid rgba(255, 255, 255, 0.5); + outline-offset: 2px; +} +.announcement-banner .announcement-banner-close i { + font-size: 0.75rem; +} +.announcement-banner.no-dismiss .announcement-banner-container { + padding-right: 0; +} +html[data-theme=dark] .announcement-banner { + background-color: #a8258c; +} +@media (max-width: 768px) { + .announcement-banner { + padding: 0.3rem 0.5rem; + } + .announcement-banner .announcement-banner-container { + gap: 0.35rem; + } + .announcement-banner .announcement-banner-text { + font-size: 0.75rem; + } + .announcement-banner .announcement-banner-link { + font-size: 0.75rem; + } + .announcement-banner .announcement-banner-close { + position: absolute; + top: 50%; + right: 0.3rem; + transform: translateY(-50%); + } +} + +@keyframes announcementSlideDown { + from { + opacity: 0; + transform: translateY(-10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} +@keyframes announcementSlideUp { + from { + opacity: 1; + transform: translateY(0); + } + to { + opacity: 0; + transform: translateY(-10px); + } +} @media screen and (min-width: 1200px) { .header-holder { height: var(--header-height-desktop); } .header-container-wrapper { - max-width: 100%; + max-width: 1140px; } .gcse-search-wrapper .fa-magnifying-glass { top: 0.7em; @@ -2697,12 +2923,6 @@ a.btn { width: 50%; } } -@media (min-width: 1800px) { - .bd-main .bd-content .bd-article-container .bd-article { - max-width: 1200px; - margin: 0 auto; - } -} html { scroll-behavior: auto !important; } @@ -3131,15 +3351,6 @@ h1[id], h2[id], h3[id], h4[id], h5[id], h6[id] { margin-top: 1rem; margin-bottom: 1rem; } -#tutorial-cards-container .card.tutorials-card { - border-radius: 0; - border-color: var(--bs-border-color-translucent); - height: 98px; - margin-bottom: 1.875rem; - overflow: scroll; - background-color: var(--sg-background-color); - cursor: pointer; -} #tutorial-cards-container .card.tutorials-card a { text-decoration: none; } @@ -3161,6 +3372,15 @@ h1[id], h2[id], h3[id], h4[id], h5[id], h6[id] { #tutorial-cards-container .card.tutorials-card a p.card-summary:hover, #tutorial-cards-container .card.tutorials-card a p.tags:hover { text-decoration: none; } +#tutorial-cards-container .card.tutorials-card { + border-radius: 0; + border-color: var(--bs-border-color-translucent); + height: 98px; + margin-bottom: 1.875rem; + overflow: scroll; + background-color: var(--sg-background-color); + cursor: pointer; +} @media screen and (min-width: 1240px) { #tutorial-cards-container .card.tutorials-card { height: 200px; @@ -12150,8 +12370,8 @@ readers do not read off random characters that represent icons */ * Copyright 2024 Fonticons, Inc. */ :root, :host { - --fa-style-family-classic: "Font Awesome 6 Free"; - --fa-font-solid: normal 900 1em/1 "Font Awesome 6 Free"; + --fa-style-family-classic: 'Font Awesome 6 Free'; + --fa-font-solid: normal 900 1em/1 'Font Awesome 6 Free'; } @font-face { @@ -12172,8 +12392,8 @@ readers do not read off random characters that represent icons */ * Copyright 2024 Fonticons, Inc. */ :root, :host { - --fa-style-family-classic: "Font Awesome 6 Free"; - --fa-font-regular: normal 400 1em/1 "Font Awesome 6 Free"; + --fa-style-family-classic: 'Font Awesome 6 Free'; + --fa-font-regular: normal 400 1em/1 'Font Awesome 6 Free'; } @font-face { @@ -12194,8 +12414,8 @@ readers do not read off random characters that represent icons */ * Copyright 2024 Fonticons, Inc. */ :root, :host { - --fa-style-family-brands: "Font Awesome 6 Brands"; - --fa-font-brands: normal 400 1em/1 "Font Awesome 6 Brands"; + --fa-style-family-brands: 'Font Awesome 6 Brands'; + --fa-font-brands: normal 400 1em/1 'Font Awesome 6 Brands'; } @font-face { diff --git a/pytorch_sphinx_theme2/static/scss/_google_search.scss b/pytorch_sphinx_theme2/static/scss/_google_search.scss index c1c2ae55..d3e3885d 100644 --- a/pytorch_sphinx_theme2/static/scss/_google_search.scss +++ b/pytorch_sphinx_theme2/static/scss/_google_search.scss @@ -247,11 +247,11 @@ input:checked + .slider { // Google search input field #gsc-i-id1 { height: 1.5rem; - text-indent: 12px !important; + text-indent: 0 !important; font-size: 1rem !important; font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; - background-position: 5px 0px !important; - padding-left: 20px !important; + background-image: none !important; + padding-left: 8px !important; color: var(--pst-color-text-base) !important; position: relative; z-index: 10; @@ -289,26 +289,20 @@ table.gsc-search-box td { } .gsc-search-button { - margin-left: 0 !important; + display: none !important; + width: 0 !important; + overflow: hidden !important; + padding: 0 !important; &-v2 { - padding: 9px 16px !important; - border-radius: 0 0.25rem 0.25rem 0 !important; - background-color: var(--pst-color-primary) !important; - border-color: var(--pst-color-primary) !important; - margin-left: -1px !important; - height: 38px !important; - - svg { - fill: white !important; - width: 13px !important; - height: 13px !important; - } + display: none !important; } } -.gsc-search-button-v2 { +td.gsc-search-button { display: none !important; + width: 0 !important; + padding: 0 !important; } // Hide Google branding @@ -397,6 +391,25 @@ table.gsc-search-box td { } +// Hide broken images in search results (shows red X when image not found) +.gs-image-box, +.gs-image, +.gsc-table-result .gs-image-box, +.gsc-url-top .gs-image { + display: none !important; +} + +.gs-image-box a img { + display: none !important; +} + +// Hide the image column in result tables +.gsc-table-result td.gsc-table-cell-thumbnail { + display: none !important; + width: 0 !important; + padding: 0 !important; +} + .gsc-table-result { font-family: var(--pst-font-family-base) !important; } @@ -444,6 +457,55 @@ table.gsc-search-box td { fill: var(--pst-color-primary) !important; } +// Google search autocompletion styling - custom dropdown for searchresults-only mode +.google-search-suggestions { + display: none; + position: absolute; + top: 38px; + left: 0; + right: 0; + background-color: var(--pst-color-background); + border: 1px solid var(--pst-color-border); + border-top: none; + border-radius: 0 0 0.5rem 0.5rem; + z-index: 10001; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + max-height: 320px; + overflow-y: auto; + padding: 0.25rem 0; +} + +.google-suggest-item { + padding: 0.5rem 0.75rem; + cursor: pointer; + font-size: 0.9rem; + color: var(--pst-color-text-base); + font-family: var(--pst-font-family-base); + display: flex; + align-items: center; + gap: 0.6rem; + transition: background-color 0.1s ease; + + &::before { + content: "\f002"; + font-family: "Font Awesome 6 Free"; + font-weight: 900; + font-size: 0.75rem; + color: var(--pst-color-text-muted); + flex-shrink: 0; + } + + &:hover, + &.active { + background-color: var(--pst-color-primary); + color: white; + + &::before { + color: white; + } + } +} + // Google search autocompletion styling .gssb_c { box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1) !important; @@ -491,13 +553,57 @@ body.gsc-overflow-hidden { } } -body.gsc-overflow-hidden .gsc-results-wrapper-overlay { +body.gsc-overflow-hidden .gsc-results-wrapper-overlay { position: fixed !important; - z-index: 10000 !important; - max-width: 1000px; - left: 50%; + z-index: 10000 !important; + max-width: 900px !important; + width: 90vw !important; + left: 50% !important; right: auto !important; - transform: translate(-50%); + top: 70px !important; + transform: translateX(-50%) !important; + background-color: var(--pst-color-background) !important; + border: 1px solid var(--pst-color-border) !important; + border-radius: 0.5rem !important; + box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2) !important; + max-height: calc(100vh - 100px) !important; + overflow-y: auto !important; + padding: 0.5rem 0.75rem !important; +} + +.gsc-results-close-btn { + position: absolute !important; + top: 8px !important; + right: 8px !important; + width: 30px !important; + height: 30px !important; + cursor: pointer !important; + border: 1px solid var(--pst-color-border) !important; + border-radius: 50% !important; + z-index: 10001 !important; + background: var(--pst-color-background) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z' fill='%23666'/%3E%3C/svg%3E") center/16px no-repeat !important; +} + +.gsc-results-close-btn:hover { + background-color: var(--pst-color-on-surface) !important; +} + +.gsc-webResult.gsc-result { + padding: 0.5rem 0 !important; + border-bottom: 1px solid var(--pst-color-border) !important; +} + +.gsc-wrapper { + padding: 0 !important; +} + +.gsc-expansionArea { + padding: 0 !important; +} + +.gsc-positioningWrapper { + margin: 0 !important; + padding: 0 !important; } // Version switcher @@ -676,12 +782,11 @@ body.gsc-overflow-hidden { // Fix for Google search input field #gsc-i-id1 { height: 1.5rem; - text-indent: 12px !important; + text-indent: 0 !important; font-size: 1rem !important; font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; - background-size: 18px 18px !important; - background-position: 5px 0px !important; - padding-left: 20px !important; + background-image: none !important; + padding-left: 8px !important; color: var(--pst-color-text-base) !important; position: relative; z-index: 10; @@ -747,6 +852,25 @@ body.search-page.gsc-overflow-hidden .footer-article-item .feedback-send { } } + +// Hide Google search toggle on mobile - Google CSE results-only mode +// doesn't work properly when cloned into the mobile sidebar +@media (max-width: 991.98px) { + .sidebar-header-items__end .navbar-item .search-container-wrapper { + .search-toggle-container { + display: none !important; + } + + #google-search { + display: none !important; + } + + #sphinx-search { + display: block !important; + } + } +} + // Mobile menu layout improvements @media (max-width: 991.98px) { .bd-sidebar-primary .sidebar-header-items .sidebar-header-items__end { diff --git a/pytorch_sphinx_theme2/static/scss/_responsive.scss b/pytorch_sphinx_theme2/static/scss/_responsive.scss index fbd8e970..aff577f8 100644 --- a/pytorch_sphinx_theme2/static/scss/_responsive.scss +++ b/pytorch_sphinx_theme2/static/scss/_responsive.scss @@ -8,7 +8,7 @@ } .header-container-wrapper { - max-width: 100%; + max-width: 1140px; } .gcse-search-wrapper .fa-magnifying-glass { @@ -158,11 +158,3 @@ width: 50%; } } - -// Wide screen styles - limit main content width for readability -@media (min-width: 1800px) { - .bd-main .bd-content .bd-article-container .bd-article { - max-width: 1200px; - margin: 0 auto; - } -} diff --git a/pytorch_sphinx_theme2/templates/search-field-custom.html b/pytorch_sphinx_theme2/templates/search-field-custom.html index 2115e5a6..f3778399 100644 --- a/pytorch_sphinx_theme2/templates/search-field-custom.html +++ b/pytorch_sphinx_theme2/templates/search-field-custom.html @@ -1,14 +1,24 @@ -{% if pytorch_project in ['docs', 'tutorials'] %} +{% if theme_pytorch_project in ['docs', 'tutorials'] %}
@@ -54,12 +64,198 @@ } } + // Execute Google CSE search programmatically from our custom input + function executeGoogleSearch(query) { + if (!query) return; + + // Close mobile sidebar if open, so results overlay is visible + var sidebar = document.querySelector('.bd-sidebar-primary'); + if (sidebar && sidebar.classList.contains('show')) { + var closeBtn = sidebar.querySelector('[data-bs-dismiss="offcanvas"]'); + if (closeBtn) closeBtn.click(); + // Also try Bootstrap's offcanvas API + try { + var offcanvas = bootstrap.Offcanvas.getInstance(sidebar); + if (offcanvas) offcanvas.hide(); + } catch(e) {} + } + + var element = google.search.cse.element.getElement('searchresults-only0'); + if (element) { + element.execute(query); + } + } + + // Wire up our custom Google search input + var googleSearchForm = document.getElementById('google-search-form'); + var googleSearchInput = document.getElementById('google-search-input'); + + if (googleSearchForm) { + googleSearchForm.addEventListener('submit', function(e) { + e.preventDefault(); + var query = googleSearchInput ? googleSearchInput.value : ''; + executeGoogleSearch(query); + }); + } + + var suggestDebounce; + var activeSuggestionIndex = -1; + + if (googleSearchInput) { + // Trigger search on Enter key + googleSearchInput.addEventListener('keydown', function(e) { + if (e.key === 'Enter') { + e.preventDefault(); + hideSuggestions(); + executeGoogleSearch(this.value); + } else if (e.key === 'ArrowDown' || e.key === 'ArrowUp') { + e.preventDefault(); + navigateSuggestions(e.key === 'ArrowDown' ? 1 : -1); + } else if (e.key === 'Escape') { + hideSuggestions(); + } + }); + + googleSearchInput.addEventListener('input', function() { + clearTimeout(suggestDebounce); + var query = this.value.trim(); + activeSuggestionIndex = -1; + if (query.length < 2) { + hideSuggestions(); + return; + } + suggestDebounce = setTimeout(function() { + fetchGoogleSuggestions(query); + }, 200); + }); + + // Hide suggestions when clicking outside + document.addEventListener('click', function(e) { + if (!e.target.closest('#google-search')) { + hideSuggestions(); + } + }); + } + + // Filter and clean suggestions: keep only PyTorch-related, strip prefix + function cleanSuggestions(rawList) { + return rawList.map(function(s) { + var text = typeof s === 'string' ? s : s[0]; + return text; + }).filter(function(text) { + return /pytorch/i.test(text); + }).map(function(text) { + return text.replace(/^pytorch\s*/i, ''); + }).filter(function(s) { + return s.length > 0; + }); + } + + // Fetch suggestions from Google suggest API, scoped to PyTorch + function fetchGoogleSuggestions(query) { + var scopedQuery = 'pytorch ' + query; + fetch('https://suggestqueries.google.com/complete/search?client=firefox&q=' + encodeURIComponent(scopedQuery)) + .then(function(r) { return r.json(); }) + .then(function(data) { + if (data && data[1] && data[1].length) { + var cleaned = cleanSuggestions(data[1]); + cleaned.length ? showSuggestions(cleaned) : hideSuggestions(); + } else { + hideSuggestions(); + } + }) + .catch(function() { + fetchGoogleSuggestionsJSONP(scopedQuery); + }); + } + + function fetchGoogleSuggestionsJSONP(scopedQuery) { + var script = document.getElementById('gcse-suggest-script'); + if (script) script.remove(); + + window.__gcseSuggestCallback = function(data) { + if (data && data[1] && data[1].length) { + var cleaned = cleanSuggestions(data[1]); + cleaned.length ? showSuggestions(cleaned) : hideSuggestions(); + } else { + hideSuggestions(); + } + }; + + script = document.createElement('script'); + script.id = 'gcse-suggest-script'; + script.src = 'https://clients1.google.com/complete/search?client=hp&q=' + encodeURIComponent(scopedQuery) + '&callback=__gcseSuggestCallback'; + script.onerror = function() { hideSuggestions(); }; + document.head.appendChild(script); + } + + function stripHtml(str) { + var tmp = document.createElement('div'); + tmp.innerHTML = str; + return tmp.textContent || tmp.innerText || ''; + } + + function showSuggestions(suggestions) { + var container = document.getElementById('google-search-suggestions'); + if (!container || !suggestions.length) { hideSuggestions(); return; } + + container.innerHTML = ''; + suggestions.forEach(function(rawText, index) { + var text = stripHtml(rawText); + var item = document.createElement('div'); + item.className = 'google-suggest-item'; + item.textContent = text; + item.setAttribute('data-index', index); + item.addEventListener('click', function() { + googleSearchInput.value = text; + hideSuggestions(); + executeGoogleSearch(text); + }); + item.addEventListener('mouseenter', function() { + activeSuggestionIndex = index; + highlightSuggestion(); + }); + container.appendChild(item); + }); + container.style.display = 'block'; + activeSuggestionIndex = -1; + } + + function hideSuggestions() { + var container = document.getElementById('google-search-suggestions'); + if (container) { + container.style.display = 'none'; + container.innerHTML = ''; + } + activeSuggestionIndex = -1; + // Clean up JSONP script + var script = document.getElementById('gcse-suggest-script'); + if (script) script.remove(); + } + + function navigateSuggestions(direction) { + var items = document.querySelectorAll('#google-search-suggestions .google-suggest-item'); + if (!items.length) return; + + activeSuggestionIndex += direction; + if (activeSuggestionIndex >= items.length) activeSuggestionIndex = 0; + if (activeSuggestionIndex < 0) activeSuggestionIndex = items.length - 1; + + highlightSuggestion(); + googleSearchInput.value = items[activeSuggestionIndex].textContent; + } + + function highlightSuggestion() { + var items = document.querySelectorAll('#google-search-suggestions .google-suggest-item'); + items.forEach(function(item, i) { + item.classList.toggle('active', i === activeSuggestionIndex); + }); + } + // Function to handle search toggle function handleSearchToggle(toggle, sphinxSearch, googleSearch) { if (!toggle || !sphinxSearch || !googleSearch) return; - // Check if the URL contains /stable/ or /tutorials/ - const currentUrl = window.location.href; // TODO: We've had reports that the google programmable search is returning stale documentation, // Simple reproduction is to turn google search on and search for multinomial which will // result in returning 1.8.1 documentation. @@ -96,6 +292,8 @@ localStorage.setItem('searchPreference', 'google'); reinitializeGoogleSearch(); trackSearchEngineSwitch('Google'); + // Focus our custom input when switching to Google + if (googleSearchInput) googleSearchInput.focus(); } else { sphinxSearch.style.display = 'block'; googleSearch.style.display = 'none'; @@ -161,18 +359,6 @@ const googleSearch = document.getElementById('google-search'); handleSearchToggle(toggle, sphinxSearch, googleSearch); - // Set placeholder text for Google search input - const observer = new MutationObserver(function() { - document.querySelectorAll('.gsc-input input').forEach(input => { - if (input && !input.hasAttribute('data-placeholder-set')) { - input.setAttribute('placeholder', 'Search the docs ...'); - input.setAttribute('data-placeholder-set', 'true'); - } - }); - }); - - observer.observe(document.body, { childList: true, subtree: true }); - // Fix for scroll jump issue - improved approach function setupSearchInputHandlers(input) { if (input.hasAttribute('data-scroll-fixed')) return; @@ -182,19 +368,13 @@ let isTyping = false; let scrollTimeout; - // Save position before typing starts input.addEventListener('keydown', () => { lastScrollPosition = window.scrollY; isTyping = true; - - // Reset typing state after a short delay clearTimeout(scrollTimeout); - scrollTimeout = setTimeout(() => { - isTyping = false; - }, 100); + scrollTimeout = setTimeout(() => { isTyping = false; }, 100); }); - // Only maintain scroll position during typing function maintainScroll() { if (document.activeElement === input && isTyping) { window.scrollTo(0, lastScrollPosition); @@ -203,27 +383,20 @@ } input.addEventListener('focus', () => { - // Just store initial position but don't force it lastScrollPosition = window.scrollY; }); input.addEventListener('input', () => { isTyping = true; window.scrollTo(0, lastScrollPosition); - - // Reset typing state after a short delay clearTimeout(scrollTimeout); - scrollTimeout = setTimeout(() => { - isTyping = false; - }, 100); - + scrollTimeout = setTimeout(() => { isTyping = false; }, 100); requestAnimationFrame(maintainScroll); }); } - // Apply to all search inputs and observe for new ones function applyToSearchInputs() { - document.querySelectorAll('.search-container input, .gsc-input input').forEach(setupSearchInputHandlers); + document.querySelectorAll('.search-container input').forEach(setupSearchInputHandlers); } applyToSearchInputs(); @@ -236,35 +409,54 @@ for (const mutation of mutations) { if (!mutation.addedNodes.length) continue; - // Style mobile search inputs - document.querySelectorAll('.sidebar-header-items__end .navbar-item .search-container-wrapper .gsc-input input').forEach(input => { - if (input) { - input.setAttribute('placeholder', 'Search the docs ...'); - input.style.paddingLeft = '36px'; - } - }); - - // Check for mobile search container const mobileSearchContainer = document.querySelector('.sidebar-header-items__end .navbar-item .search-container-wrapper'); if (!mobileSearchContainer) continue; const mobileToggle = mobileSearchContainer.querySelector('#search-toggle'); if (mobileToggle && toggle) { - // Sync mobile toggle with desktop toggle mobileToggle.checked = toggle.checked; updateMobileSearch(); - // Add event listener to mobile toggle if not already added if (!mobileToggle.hasAttribute('data-initialized')) { mobileToggle.setAttribute('data-initialized', 'true'); mobileToggle.addEventListener('change', function() { - // Sync desktop toggle with mobile toggle toggle.checked = this.checked; - // Trigger change event on desktop toggle to update both toggle.dispatchEvent(new Event('change')); }); } } + + // Wire up mobile Google search input + var mobileGoogleInput = mobileSearchContainer.querySelector('#google-search-input'); + if (mobileGoogleInput && !mobileGoogleInput.hasAttribute('data-mobile-wired')) { + mobileGoogleInput.setAttribute('data-mobile-wired', 'true'); + + var mobileForm = mobileSearchContainer.querySelector('#google-search-form'); + if (mobileForm) { + mobileForm.addEventListener('submit', function(e) { + e.preventDefault(); + executeGoogleSearch(mobileGoogleInput.value); + }); + } + + mobileGoogleInput.addEventListener('keydown', function(e) { + if (e.key === 'Enter') { + e.preventDefault(); + executeGoogleSearch(this.value); + } + }); + + mobileGoogleInput.addEventListener('input', function() { + clearTimeout(suggestDebounce); + var query = this.value.trim(); + activeSuggestionIndex = -1; + if (query.length < 2) return; + suggestDebounce = setTimeout(function() { + // Mobile uses the same search execution but no suggestions dropdown + // (suggestions dropdown is complex on mobile; just support Enter to search) + }, 200); + }); + } } }); @@ -273,7 +465,6 @@ // Ensure Google CSE is properly loaded if (window.__gcse) { window.__gcse.callback = function() { - // This will run after Google CSE is fully loaded if (toggle && toggle.checked) { reinitializeGoogleSearch(); }