diff --git a/blocks/header/header.js b/blocks/header/header.js
index cea1276..204fd90 100644
--- a/blocks/header/header.js
+++ b/blocks/header/header.js
@@ -1,202 +1,12 @@
-import { getMetadata } from '../../scripts/aem.js';
+import { debounce, getMetadata } from '../../scripts/aem.js';
+import {
+ input, div, ul, li, span, a,
+} from '../../scripts/dom-builder.js';
+import { getCookie } from '../../scripts/scripts.js';
const windowWidth = document.body.offsetWidth;
-function createGcseTools() {
- const gcseTools = document.createElement('div');
- gcseTools.id = 'mmg-gcse-tools';
- const gcseOuter = document.createElement('div');
- gcseOuter.className = 'mmg-gcse-outer';
- const closeButton = document.createElement('span');
- closeButton.className = 'close-btn';
- closeButton.innerText = '×';
-
- // Add click event to close the search and remove the element from the DOM
- closeButton.addEventListener('click', () => {
- const searchResultsBlock = document.getElementById('mmg-gcse');
- if (searchResultsBlock) {
- searchResultsBlock.remove();
- }
- });
-
- gcseOuter.appendChild(closeButton);
- gcseTools.appendChild(gcseOuter);
- return gcseTools;
-}
-
-function truncateText(text, maxLength) {
- if (text.length <= maxLength) {
- return text;
- }
- return `${text.slice(0, maxLength)}...`;
-}
-
-function createGcseBox() {
- const gcseBox = document.createElement('div');
- gcseBox.id = 'mmg-gcse-box';
- const outer = document.createElement('div');
- outer.className = 'mmg-gcse-outer';
- outer.style.opacity = 1;
- gcseBox.appendChild(outer);
- return gcseBox;
-}
-
-function createHeadingElement(input) {
- const heading = document.createElement('h2');
- heading.innerText = `Search for: ${input}`;
- heading.classList.add('search-title');
- return heading;
-}
-
-function createUnifiedElement(input) {
- const unified = document.createElement('span');
- unified.innerHTML = `Want to Search across all Life Sciences Companies of Danaher? Explore Danaher Unified Search`;
- unified.classList.add('search-unified');
- return unified;
-}
-
-function createCountElement(resultsLength, total) {
- const count = document.createElement('p');
- count.className = 'search-info';
- count.innerText = `Results ${resultsLength} out of ${total} items`;
- return count;
-}
-
-function createResultLink(result) {
- const link = document.createElement('a');
- link.classList.add('item');
-
- const spanTitle = document.createElement('span');
- spanTitle.classList.add('title');
- spanTitle.textContent = truncateText(result.title, 70);
- const date = new Date(Number(result.date) * 1000).toLocaleDateString('en-US', { year: 'numeric', month: 'long' }).toLowerCase();
- const description = truncateText(result.description, 150);
- link.appendChild(spanTitle);
- const dateNode = document.createTextNode(date);
- const descriptionNode = document.createTextNode(description);
- link.appendChild(dateNode);
- link.appendChild(descriptionNode);
- link.href = result.path;
-
- return link;
-}
-
-function removeSearchResult() {
- const searchResultsBlock1 = document.getElementById('mmg-gcse');
- if (searchResultsBlock1) {
- searchResultsBlock1.remove();
- }
-}
-
-function updateDisplayedItems(currentPage, itemsPerPage, container) {
- const anchorTags = container.querySelectorAll('a');
- const startIndex = (currentPage - 1) * itemsPerPage;
- const endIndex = startIndex + itemsPerPage;
- anchorTags.forEach((element, index) => {
- element.style.display = (index >= startIndex && index < endIndex) ? '' : 'none';
- });
-}
-
-function clearExistingPagination(container) {
- const existingPagination = container.querySelector('.pagination');
- if (existingPagination) {
- container.removeChild(existingPagination);
- }
-}
-
-function createPaginationDiv() {
- const paginationDiv = document.createElement('div');
- paginationDiv.className = 'pagination';
- return paginationDiv;
-}
-
-function updatePagination(currentPage, totalPages, elementsContainer) {
- const itemsPerPage = 10;
- updateDisplayedItems(currentPage, itemsPerPage, elementsContainer);
-
- // Clear existing pagination before appending new one
- clearExistingPagination(elementsContainer);
-
- function createNavigationButton(label, isEnabled, targetPage) {
- const button = document.createElement('span');
- button.className = `nav-button ${label.toLowerCase()} ${isEnabled ? '' : 'disabled'}`;
- button.textContent = label;
- if (isEnabled) {
- button.addEventListener('click', () => updatePagination(targetPage, totalPages, elementsContainer));
- }
- return button;
- }
-
- function createPageButton(pageNumber, currentPageValue, totalPagesValue, container) {
- const pageButton = document.createElement('span');
- pageButton.className = `page ${pageNumber === currentPageValue ? 'active' : ''}`;
- pageButton.textContent = pageNumber;
- pageButton.addEventListener('click', () => {
- if (pageNumber !== currentPageValue) {
- updatePagination(pageNumber, totalPagesValue, container);
- }
- });
- return pageButton;
- }
-
- const pagination = createPaginationDiv();
- pagination.appendChild(createNavigationButton('Prev', currentPage > 1, currentPage - 1));
- for (let i = 1; i <= totalPages; i += 1) {
- pagination.appendChild(createPageButton(i, currentPage, totalPages, elementsContainer));
- }
- pagination.appendChild(createNavigationButton('Next', currentPage < totalPages, currentPage + 1));
-
- elementsContainer.appendChild(pagination);
-}
-
-function roundToNextTenth(value) {
- return Math.ceil(value / 10) * 10;
-}
-
-function createSearchResultsBlock(results, input, total) {
- // Remove the main search results container if any
- removeSearchResult();
- // Create the main search results container
- const searchResultsBlock = document.createElement('div');
- searchResultsBlock.id = 'mmg-gcse';
- searchResultsBlock.className = 'active';
- const bodyHeight = document.body.clientHeight;
- const header = document.getElementById('header');
- const headerHeight = header.clientHeight;
- searchResultsBlock.style.height = `${bodyHeight - headerHeight}px`;
-
- // Create GCSE tools container
- const gcseTools = createGcseTools();
-
- // Create GCSE box container
- const gcseBox = createGcseBox();
-
- // Create Unified Search element
- const unified = createUnifiedElement(input);
-
- // Create heading element
- const heading = createHeadingElement(input);
-
- // Create count element
- const count = createCountElement(results.length, total);
-
- // Append elements to the searchResultsBlock
- const outer = gcseBox.querySelector('.mmg-gcse-outer');
- outer.appendChild(heading);
- outer.appendChild(unified);
- outer.appendChild(count);
-
- // Create individual result elements
- results.forEach((result) => {
- const link = createResultLink(result);
- outer.appendChild(link);
- });
- updatePagination(1, roundToNextTenth(results.length) / 10, outer);
- searchResultsBlock.appendChild(gcseTools);
- searchResultsBlock.appendChild(gcseBox);
-
- return searchResultsBlock;
-}
+let coveoSearchValue = '';
function addClassesToMenuItems(element, depth) {
const childItems = element.children;
@@ -216,11 +26,13 @@ function addClassesToMenuItems(element, depth) {
if (childElement?.children?.length > 0) {
if (windowWidth < 961) {
- const spanElement = document.createElement('span');
- spanElement.className = 'arrow';
+ const spanElement = span({ class: 'arrow' });
childElement.style.display = 'none';
spanElement.addEventListener('click', () => {
- if (childElement.style.display === 'block' || childElement.style.display === '') {
+ if (
+ childElement.style.display === 'block'
+ || childElement.style.display === ''
+ ) {
childElement.style.display = 'none';
item.classList.remove('open');
} else {
@@ -238,39 +50,206 @@ function addClassesToMenuItems(element, depth) {
}
}
-function handleSearchFormSubmit(formElement) {
- function searchFormHandler(e) {
- e.preventDefault();
- const inputValue = formElement.querySelector('input').value;
- fetch('/query-index.json')
- .then((response) => response.json())
- .then((jsonData) => {
- // Perform a search based on the fetched JSON data
- const results = jsonData.data.filter((item) => {
- // Customize this condition to match your search criteria
- const it = (item.title.toLowerCase()
- + item['sub-title'].toLowerCase()
- + item.description.toLowerCase()).includes(inputValue);
- return it;
- });
- const resultBlock = document.querySelector('.search-results');
- if (resultBlock) {
- resultBlock.remove();
- }
- if (inputValue !== '') {
- // Create a block based on the search results
- const searchResultsBlock = createSearchResultsBlock(
- results,
- inputValue,
- jsonData.total,
- );
- document.body.appendChild(searchResultsBlock);
- } else {
- removeSearchResult();
- }
+function getRecentSearches() {
+ const recentSearchesString = localStorage.getItem('coveo-recent-queries');
+ const recentSearches = recentSearchesString ? JSON.parse(recentSearchesString) : [];
+ return recentSearches.slice(0, 3);
+}
+
+function setRecentSearches(value) {
+ const recentSearches = getRecentSearches();
+ const searchValueIndex = recentSearches.findIndex((search) => (
+ search.toLowerCase() === value.toLowerCase()
+ ));
+ if (searchValueIndex > -1) recentSearches.splice(searchValueIndex, 1);
+ recentSearches.unshift(value);
+ localStorage.setItem('coveo-recent-queries', JSON.stringify(recentSearches.slice(0, 3)));
+}
+
+function submitSearchPage() {
+ const inputValue = document.querySelector('.mobile-search .coveo-search')?.value?.trim();
+ if (inputValue && inputValue !== '') {
+ document.querySelectorAll('.coveo-search').forEach((searchInputEl) => {
+ searchInputEl.blur();
+ });
+ window.location = `${window.location.origin}/search#q=${inputValue}`;
+ }
+}
+
+function onClickOfitems(value) {
+ setRecentSearches(value);
+ document.querySelectorAll('.coveo-search').forEach((inpEl) => {
+ inpEl.value = value;
+ inpEl.focus();
+ inpEl.click();
+ submitSearchPage();
+ });
+}
+
+function toggleSearchDropdown(event, mode) {
+ if (mode === 'focus') {
+ event.target.parentElement.nextSibling.classList.add('show');
+ } else if (mode === 'blur') {
+ setTimeout(() => {
+ event.target.parentElement.nextSibling.classList.remove('show');
+ }, 500);
+ }
+}
+
+async function addRecentSearch() {
+ let recentSearches = getRecentSearches();
+ if (recentSearches.length > 0) {
+ recentSearches = recentSearches.reverse();
+ const parentEls = document.querySelectorAll('div.coveo-search-dropdown-menu .all-recent-searches ul');
+ parentEls.forEach((parentEl) => {
+ parentEl.innerHTML = '';
+ recentSearches.forEach((el) => {
+ const item = li({ class: 'recent-search-item', onclick: () => onClickOfitems(el) });
+ item.innerHTML = ` ${el}`;
+ parentEl.prepend(item);
});
+ });
+ }
+}
+
+async function buildSearchSuggestions(response) {
+ const parentEls = document.querySelectorAll('div.coveo-search-dropdown-menu ul.suggestions');
+ if (parentEls.length > 0) {
+ parentEls.forEach((parentEl) => {
+ parentEl.innerHTML = '';
+ if (response && response.completions && response.completions.length > 0) {
+ response?.completions?.forEach((el) => {
+ if (el && el.expression) {
+ const item = li({ onclick: () => onClickOfitems(el.expression) });
+ item.innerHTML = ` ${el.expression}`;
+ parentEl.append(item);
+ }
+ });
+ }
+ });
}
- return searchFormHandler;
+}
+
+function getCoveoPayload(values) {
+ const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
+ const userTimestamp = new Date().toISOString();
+ const clientId = getCookie('coveo_visitorId');
+ const searchHistoryString = localStorage.getItem('__coveo.analytics.history');
+ const searchHistory = searchHistoryString ? JSON.parse(searchHistoryString) : [];
+ const payload = {
+ analytics: {
+ clientId,
+ clientTimestamp: userTimestamp,
+ documentLocation: window.location.href,
+ documentReferrer: document.referrer,
+ originContext: 'Search',
+ },
+ locale: 'en',
+ pipeline: 'Aldevron Marketplace',
+ searchHub: 'AldevronMainSearch',
+ actionsHistory: searchHistory.map(({ time, value, name }) => ({ time, value, name })),
+ timezone: userTimeZone,
+ q: values,
+ count: 8,
+ referrer: document.referrer,
+ visitorId: clientId,
+ };
+ return payload;
+}
+
+async function fetchSuggestions(value) {
+ try {
+ const payload = getCoveoPayload(value);
+ const organizationId = window.aldevronConfig?.searchOrg;
+ const accessToken = window.aldevronConfig?.searchKey;
+ const domain = window.aldevronConfig?.origin;
+ const path = window.aldevronConfig?.path;
+ const apiURL = `https://${organizationId}${domain}${path}`;
+ const resp = await fetch(
+ apiURL,
+ {
+ method: 'POST',
+ headers: {
+ authorization: `Bearer ${accessToken}`,
+ 'content-type': 'application/json',
+ },
+ body: JSON.stringify(payload),
+ },
+ );
+ const response = await resp.json();
+ buildSearchSuggestions(response);
+ coveoSearchValue = value;
+ } catch (error) {
+ /* eslint-disable no-console */
+ console.log('Error', error);
+ }
+}
+
+function customCoveoSearch() {
+ const searchIcon = div({
+ onclick: () => {
+ const mobileValue = document.querySelector('.mobile-search .coveo-search')?.value;
+ if (mobileValue && mobileValue !== '') {
+ setRecentSearches(mobileValue);
+ submitSearchPage();
+ }
+ },
+ });
+ searchIcon.innerHTML = '