diff --git a/assets/js/components/sidebar-search.js b/assets/js/components/sidebar-search.js
new file mode 100644
index 000000000..1e5023050
--- /dev/null
+++ b/assets/js/components/sidebar-search.js
@@ -0,0 +1,6 @@
+import SearchInteractions from '../utils/search-interactions';
+
+export default function SidebarSearch({ component }) {
+ const searchInput = component.querySelector('.sidebar--search-field');
+ SearchInteractions({ searchInput });
+}
\ No newline at end of file
diff --git a/assets/js/feature-callouts.js b/assets/js/feature-callouts.js
index 253b09b13..a77015e6e 100644
--- a/assets/js/feature-callouts.js
+++ b/assets/js/feature-callouts.js
@@ -6,33 +6,29 @@
assets/js/cookies.js.
*/
+import $ from 'jquery';
+import * as LocalStorageAPI from './local-storage.js';
+
// Get notification ID
-function getCalloutID (el) {
+function getCalloutID(el) {
return $(el).attr('id');
}
// Hide a callout and update the cookie with the viewed callout
-function hideCallout (calloutID) {
- if (!window.LocalStorageAPI.notificationIsRead(calloutID)) {
- window.LocalStorageAPI.setNotificationAsRead(calloutID, 'callout');
+function hideCallout(calloutID) {
+ if (!LocalStorageAPI.notificationIsRead(calloutID)) {
+ LocalStorageAPI.setNotificationAsRead(calloutID, 'callout');
$(`#${calloutID}`).fadeOut(200);
}
}
// Show the url feature callouts on page load
-$(document).ready(function () {
- $('.feature-callout').each(function () {
- const calloutID = getCalloutID($(this));
+export default function FeatureCallout({ component }) {
+ const calloutID = getCalloutID($(component));
- if (!window.LocalStorageAPI.notificationIsRead(calloutID, 'callout')) {
- $(`#${calloutID}.feature-callout`)
- .fadeIn(300)
- .removeClass('start-position');
- }
- });
-});
-
-// Hide the InfluxDB URL selector callout
-// $('button.url-trigger, #influxdb-url-selector .close').click(function () {
-// hideCallout('influxdb-url-selector');
-// });
+ if (LocalStorageAPI.notificationIsRead(calloutID, 'callout')) {
+ $(`#${calloutID}.feature-callout`)
+ .fadeIn(300)
+ .removeClass('start-position');
+ }
+}
diff --git a/assets/js/keybindings.js b/assets/js/keybindings.js
index 6c8f2fcbe..6048e899c 100644
--- a/assets/js/keybindings.js
+++ b/assets/js/keybindings.js
@@ -11,17 +11,14 @@ function getPlatform() {
}
}
-const platform = getPlatform()
-
-function addOSClass(osClass) {
- $('.keybinding').addClass(osClass)
+function addOSClass(osClass, { $component }) {
+ $component.addClass(osClass)
}
-function updateKeyBindings() {
- $('.keybinding').each(function() {
- var osx = $(this).data("osx")
- var linux = $(this).data("linux")
- var win = $(this).data("win")
+function updateKeyBindings({ $component }) {
+ var osx = $component.data("osx")
+ var linux = $component.data("linux")
+ var win = $component.data("win")
if (platform === "other") {
if (win != linux) {
@@ -30,12 +27,16 @@ function updateKeyBindings() {
var keybind = '' + linux + '
for Linux and Windows and ' + osx + '
for macOS';
}
} else {
- var keybind = '' + $(this).data(platform) + '
'
+ var keybind = '' + $component.data(platform) + '
'
}
- $(this).html(keybind)
- })
+ $component.html(keybind)
}
-addOSClass(platform)
-updateKeyBindings()
+export default function KeyBinding({ component }) {
+ // Initialize keybindings
+ const platform = getPlatform();
+ const $component = $(component);
+ addOSClass(platform, { $component });
+ updateKeyBindings({ $component });
+}
diff --git a/assets/js/list-filters.js b/assets/js/list-filters.js
index 7b008dcb6..b541161ec 100644
--- a/assets/js/list-filters.js
+++ b/assets/js/list-filters.js
@@ -3,8 +3,8 @@ function countTag(tag) {
return $(".visible[data-tags*='" + tag + "']").length
}
-function getFilterCounts() {
- $('#list-filters label').each(function() {
+function getFilterCounts($labels) {
+ $labels.each(function() {
var tagName = $('input', this).attr('name').replace(/[\W/]+/, "-");
var tagCount = countTag(tagName);
$(this).attr('data-count', '(' + tagCount + ')');
@@ -16,35 +16,39 @@ function getFilterCounts() {
})
}
-// Get initial filter count on page load
-getFilterCounts()
+export default function ListFilters({ component }) {
+ const $labels = $(component).find('label');
+ const $inputs = $(component).find('input');
-$("#list-filters input").click(function() {
+ getFilterCounts($labels);
- // List of tags to hide
- var tagArray = $("#list-filters input:checkbox:checked").map(function(){
- return $(this).attr('name').replace(/[\W]+/, "-");
- }).get();
+ $inputs.click(function() {
- // List of tags to restore
- var restoreArray = $("#list-filters input:checkbox:not(:checked)").map(function(){
- return $(this).attr('name').replace(/[\W]+/, "-");
- }).get();
+ // List of tags to hide
+ var tagArray = $(component).find("input:checkbox:checked").map(function(){
+ return $(this).attr('name').replace(/[\W]+/, "-");
+ }).get();
- // Actions for filter select
- if ( $(this).is(':checked') ) {
- $.each( tagArray, function( index, value ) {
- $(".filter-item.visible:not([data-tags~='" + value + "'])").removeClass('visible').fadeOut()
- })
- } else {
- $.each( restoreArray, function( index, value ) {
- $(".filter-item:not(.visible)[data-tags~='" + value + "']").addClass('visible').fadeIn()
- })
- $.each( tagArray, function( index, value ) {
- $(".filter-item.visible:not([data-tags~='" + value + "'])").removeClass('visible').hide()
- })
- }
+ // List of tags to restore
+ var restoreArray = $(component).find("input:checkbox:not(:checked)").map(function(){
+ return $(this).attr('name').replace(/[\W]+/, "-");
+ }).get();
- // Refresh filter count
- getFilterCounts()
-});
+ // Actions for filter select
+ if ( $(this).is(':checked') ) {
+ $.each( tagArray, function( index, value ) {
+ $(".filter-item.visible:not([data-tags~='" + value + "'])").removeClass('visible').fadeOut()
+ })
+ } else {
+ $.each( restoreArray, function( index, value ) {
+ $(".filter-item:not(.visible)[data-tags~='" + value + "']").addClass('visible').fadeIn()
+ })
+ $.each( tagArray, function( index, value ) {
+ $(".filter-item.visible:not([data-tags~='" + value + "'])").removeClass('visible').hide()
+ })
+ }
+
+ // Refresh filter count
+ getFilterCounts($labels);
+ });
+}
diff --git a/assets/js/main.js b/assets/js/main.js
index 5c2289720..72838978b 100644
--- a/assets/js/main.js
+++ b/assets/js/main.js
@@ -3,6 +3,9 @@
// If you need to pass parameters from the calling Hugo page, you can import them here like so:
// import * as pageParams from '@params';
+// Import dependencies that we still need to load in the global scope
+import $ from 'jquery';
+
/** Import modules that are not components.
* TODO: Refactor these into single-purpose component modules.
*/
@@ -11,7 +14,7 @@ import * as codeControls from './code-controls.js';
import * as contentInteractions from './content-interactions.js';
import { delay } from './helpers.js';
import { InfluxDBUrl } from './influxdb-url.js';
-import * as localStorage from './local-storage.js';
+import * as localStorage from './local-storage.js';
import * as modals from './modals.js';
import * as notifications from './notifications.js';
import * as pageContext from './page-context.js';
@@ -29,8 +32,13 @@ import * as v3Wayfinding from './v3-wayfinding.js';
import AskAITrigger from './ask-ai-trigger.js';
import CodePlaceholder from './code-placeholders.js';
import { CustomTimeTrigger } from './custom-timestamps.js';
+import FeatureCallout from './feature-callouts.js';
import FluxInfluxDBVersionsTrigger from './flux-influxdb-versions.js';
+import KeyBinding from './keybindings.js';
+import ListFilters from './list-filters.js';
+import ProductSelector from './version-selector.js';
import { SearchButton } from './search-button.js';
+import SidebarSearch from './components/sidebar-search.js';
import { SidebarToggle } from './sidebar-toggle.js';
import Theme from './theme.js';
import ThemeSwitch from './theme-switch.js';
@@ -49,8 +57,13 @@ const componentRegistry = {
'ask-ai-trigger': AskAITrigger,
'code-placeholder': CodePlaceholder,
'custom-time-trigger': CustomTimeTrigger,
+ 'feature-callout': FeatureCallout,
'flux-influxdb-versions-trigger': FluxInfluxDBVersionsTrigger,
+ 'keybinding': KeyBinding,
+ 'list-filters': ListFilters,
+ 'product-selector': ProductSelector,
'search-button': SearchButton,
+ 'sidebar-search': SidebarSearch,
'sidebar-toggle': SidebarToggle,
'theme': Theme,
'theme-switch': ThemeSwitch
@@ -72,6 +85,11 @@ function initGlobals() {
window.influxdatadocs.toggleModal = modals.toggleModal;
window.influxdatadocs.componentRegistry = componentRegistry;
+ // Re-export jQuery to global namespace for legacy scripts
+ if (typeof window.jQuery === 'undefined') {
+ window.jQuery = window.$ = $;
+ }
+
return window.influxdatadocs;
}
diff --git a/assets/js/search-interactions.js b/assets/js/search-interactions.js
deleted file mode 100644
index 4f8fdd8ac..000000000
--- a/assets/js/search-interactions.js
+++ /dev/null
@@ -1,10 +0,0 @@
-// Fade content wrapper when focusing on search input
-$('#algolia-search-input').focus(function() {
- $('.content-wrapper').fadeTo(300, .35);
-})
-
-// Hide search dropdown when leaving search input
-$('#algolia-search-input').blur(function() {
- $('.content-wrapper').fadeTo(200, 1);
- $('.ds-dropdown-menu').hide();
-})
diff --git a/assets/js/utils/search-interactions.js b/assets/js/utils/search-interactions.js
new file mode 100644
index 000000000..83d217382
--- /dev/null
+++ b/assets/js/utils/search-interactions.js
@@ -0,0 +1,22 @@
+export default function SearchInteractions({ searchInput }) {
+ const contentWrapper = document.querySelector('.content-wrapper');
+ const dropdownMenu = document.querySelector('.ds-dropdown-menu');
+
+ // Fade content wrapper when focusing on search input
+ searchInput.addEventListener('focus', () => {
+ // Using CSS transitions instead of jQuery's fadeTo for better performance
+ contentWrapper.style.opacity = '0.35';
+ contentWrapper.style.transition = 'opacity 300ms';
+ });
+
+ // Hide search dropdown when leaving search input
+ searchInput.addEventListener('blur', () => {
+ contentWrapper.style.opacity = '1';
+ contentWrapper.style.transition = 'opacity 200ms';
+
+ // Hide dropdown menu
+ if (dropdownMenu) {
+ dropdownMenu.style.display = 'none';
+ }
+ });
+}
\ No newline at end of file
diff --git a/assets/js/version-selector.js b/assets/js/version-selector.js
index 51fa52c53..253365a23 100644
--- a/assets/js/version-selector.js
+++ b/assets/js/version-selector.js
@@ -1,19 +1,21 @@
-// Select the product dropdown and dropdown items
-const productDropdown = document.querySelector("#product-dropdown");
-const dropdownItems = document.querySelector("#dropdown-items");
+export default function ProductSelector({ component }) {
+ // Select the product dropdown and dropdown items
+ const productDropdown = component.querySelector("#product-dropdown");
+ const dropdownItems = component.querySelector("#dropdown-items");
-// Expand the menu on click
-if (productDropdown) {
- productDropdown.addEventListener("click", function() {
- productDropdown.classList.toggle("open");
- dropdownItems.classList.toggle("open");
+ // Expand the menu on click
+ if (productDropdown) {
+ productDropdown.addEventListener("click", function() {
+ productDropdown.classList.toggle("open");
+ dropdownItems.classList.toggle("open");
+ });
+ }
+
+ // Close the dropdown by clicking anywhere else
+ document.addEventListener("click", function(e) {
+ // Check if the click was outside of the '.product-list' container
+ if (!e.target.closest('.product-list')) {
+ dropdownItems.classList.remove("open");
+ }
});
}
-
-// Close the dropdown by clicking anywhere else
-document.addEventListener("click", function(e) {
- // Check if the click was outside of the '.product-list' container
- if (!e.target.closest('.product-list')) {
- dropdownItems.classList.remove("open");
- }
-});
diff --git a/layouts/index.html b/layouts/index.html
index b04b66e5c..6bbd51ab6 100644
--- a/layouts/index.html
+++ b/layouts/index.html
@@ -19,7 +19,7 @@