Skip to content

Commit

Permalink
IBX-4064: Search page (#322)
Browse files Browse the repository at this point in the history
(cherry picked from commit 03e568e)
  • Loading branch information
adriendupuis committed Dec 6, 2024
1 parent 9a8fba5 commit e0ab748
Show file tree
Hide file tree
Showing 12 changed files with 751 additions and 30 deletions.
150 changes: 150 additions & 0 deletions docs/css/instantsearch.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
.md-content {
margin: 0 auto;
}

footer.md-footer {
left: 0;
}

.md-content .ais-InstantSearch {
letter-spacing: 0.12px;
}

.md-content .ais-InstantSearch h1 {
font-size: 32px;
line-height: 36px;
letter-spacing: 0.17px;
margin: 8px 0 40px;
}

.md-content .ais-InstantSearch .ais-SearchBox .ais-SearchBox-submit {
left: 16px;
}

.md-content .ais-InstantSearch .ais-SearchBox .ais-SearchBox-submitIcon {
width: 16px;
}

.md-content .ais-InstantSearch .ais-SearchBox .ais-SearchBox-input {
font-size: 14px;
line-height: 21px;
height: 48px;
padding-left: 48px;
border-color: #A0A4A8;
}

.md-content .ais-InstantSearch .ais-Hits-list {
margin-left: 0;
}

.md-content .ais-InstantSearch .ais-Hits-item {
padding: 0px;
width: initial;
margin: 0;
border: 0;
box-shadow: none;
}

.md-content .ais-InstantSearch .ais-Hits-item + .ais-Hits-item {
border-top: 1px solid #E0E0E8;
margin-top: 16px;
padding-top: 16px;
}

.md-content .ais-InstantSearch .ais-Highlight-highlighted {
background-color: #ECF4FF;
color: #4191FF;
font-size: inherit;
line-height: inherit;
}

.md-content .ais-InstantSearch .instantsearch__entry {
display: block;
color: var(--ibexa-dusk-black);
}

.md-content .ais-InstantSearch .instantsearch__entry:hover,
.md-content .ais-InstantSearch .instantsearch__entry:hover .instantsearch__entry-header,
.md-content .ais-InstantSearch .instantsearch__entry:hover .instantsearch__entry-content {
color: var(--ibexa-jazzberry)
}

.md-content .ais-InstantSearch .instantsearch__entry:hover mark,
.md-content .ais-InstantSearch .instantsearch__entry:hover .instantsearch__entry-header mark,
.md-content .ais-InstantSearch .instantsearch__entry:hover .instantsearch__entry-content mark {
color: var(--ibexa-jazzberry)
}

.md-content .ais-InstantSearch .instantsearch__entry-header {
font-size: 18px;
line-height: 20px;
letter-spacing: 0.12px;
margin: 4px 0;
}

.md-content .ais-InstantSearch .instantsearch__entry-header .ais-Highlight-highlighted {
font-size: 18px;
line-height: 20px;
}

.md-content .ais-InstantSearch .instantsearch__entry-content {
color: #3B424A;
font-size: 14px;
line-height: 21px;
letter-spacing: 0.12px;
margin-top: 10px;
padding-left: 10px;
border-left: 2px solid var(--mid-grey);
}

.md-content .ais-InstantSearch .instantsearch__entry-content .ais-Highlight-highlighted {
font-size: 14px;
line-height: 21px;
}

.md-content .ais-InstantSearch .instantsearch__entry-breadcrumbs {
font-size: 12px;
line-height: 21px;
letter-spacing: 0.12px;
}

.md-content .ais-InstantSearch .instantsearch__entry-breadcrumbs-item:after {
content: '›';
display: inline-block;
padding: 0 5px;
}

.md-content .ais-InstantSearch .ais-Pagination .ais-Pagination-list:not([hidden]) {
display: flex;
list-style: none;
margin: 15px 0 0;
display: flex;
justify-content: flex-end;
}

.md-content .ais-InstantSearch .ais-Pagination .ais-Pagination-list .ais-Pagination-item {
margin: 0;
}

.md-content .ais-InstantSearch .ais-Pagination .ais-Pagination-link {
border: none;
font-size: 14px;
line-height: 21px;
letter-spacing: 0.12px;
color: var(--ibexa-dusk-black);
height: 40px;
min-width: 40px;
display: flex;
justify-content: center;
align-items: center;
}

.md-content .ais-InstantSearch .ais-Pagination .ais-Pagination-item--selected .ais-Pagination-link,
.md-content .ais-InstantSearch .ais-Pagination .ais-Pagination-link:hover {
background-color: #F3F3F6;
border-radius: 5px;
}

#version {
display: none;
}
166 changes: 166 additions & 0 deletions docs/css/instantsearch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
(function(global, doc) {
let match;
const search_query = (match = doc.location.search.match(/sq=(.*?)(&|$)/)) ? match[1] : '';
const parsed_search_query = decodeURI(search_query.replaceAll('+', ' '));
const search_page = (match = doc.location.search.match(/p=(\d*?)(&|$)/)) ? match[1] : 1;
const parsed_search_page = parseInt(search_page);
let version = doc.location.pathname.split('/')[2];
if (!/^\d+\.\d+$/.test(version) && version !== 'latest') {
version = 'master';
}
const hitsContainer = '#hits';
const statsContainer = '#stats';
const paginationContainer = '#pagination';
const search = instantsearch({
indexName: 'ezplatform',
searchClient: algoliasearch('2DNYOU6YJZ', '21ce3e522455e18e7ee16cf7d66edb4b'),
initialUiState: {
ezplatform: {
query: parsed_search_query,
refinementList: { version: [version] },
page: parsed_search_page,
},
},
searchFunction(helper) {
if (helper.state.query) {
helper.search();
$(statsContainer).css('visibility', 'visible');
$(paginationContainer).show();
} else {
$(hitsContainer).empty();
$(statsContainer).css('visibility', 'hidden');
$(paginationContainer).hide();
}
},
});

getNextSearchURL = () => {
const searchInputElements = document.getElementsByClassName('ais-SearchBox-input');
const text = searchInputElements[0].value.trim();
const selectedPaginationItemElements = doc.getElementsByClassName('ais-Pagination-item--selected');
const page = selectedPaginationItemElements.length ? parseInt(selectedPaginationItemElements[0].innerText) : 1;
const url = new URL(window.location);
url.searchParams.set('sq', text);
url.searchParams.set('p', page);
return url;
};

let idleTimer;
const startIdleTimer = (url) => {
stopIdleTimer();
idleTimer = window.setTimeout(() => {
window.history.pushState({}, '', url);
}, 1500);
};
const stopIdleTimer = () => {
window.clearTimeout(idleTimer);
};

doc.getElementById('searchbox').addEventListener('keyup', function(event) {
const url = getNextSearchURL();
if (url.searchParams.get('sq') != (new URL(window.location)).searchParams.get('sq')) {
url.searchParams.set('p', 1);
startIdleTimer(url);
}
});

doc.getElementById('pagination').addEventListener('click', function(event) {
stopIdleTimer();
const url = getNextSearchURL();
window.history.pushState({}, '', url);
});

window.onpopstate = (event) => {
window.location.reload();
};

search.addWidgets([
instantsearch.widgets.configure({
hitsPerPage: 10,
}),
instantsearch.widgets.stats({
container: statsContainer,
templates: {
text: `<h1>
Search results ({{#helpers.formatNumber}}{{nbHits}}{{/helpers.formatNumber}})
</h1>`,
},
}),
instantsearch.widgets.searchBox({
container: '#searchbox',
}),
instantsearch.widgets.hits({
container: hitsContainer,
templates: {
item: (hit) => {
const hierarchy = Object.entries(hit.hierarchy).filter(([, value]) => value);
const breadcrumbsKeys = hierarchy.map(([key]) => key);
const entryNameKey = breadcrumbsKeys.pop();

const headerHTML = `<h3 class="instantsearch__entry-header">
${instantsearch.highlight({
attribute: `hierarchy.${entryNameKey}`,
highlightedTagName: 'mark',
hit: hit,
})}
</h3>`;

let breadcrumbsHTML = '';
let contentHTML = '';

if (hit.content && hit._highlightResult.content.matchedWords.length && (!hit._highlightResult.content.fullyHighlighted || 1 < hit._highlightResult.content.matchedWords.length)) {
contentHTML = `<div class="instantsearch__entry-content">
${instantsearch.highlight({
attribute: `content`,
highlightedTagName: 'mark',
hit: hit,
}).replaceAll('&amp;', '&')}
</div>`;
}

breadcrumbsKeys?.forEach((breadcrumbKey) => {
breadcrumbsHTML += `<span class="instantsearch__entry-breadcrumbs-item">
${instantsearch.highlight({
attribute: `hierarchy.${breadcrumbKey}`,
highlightedTagName: 'mark',
hit: hit,
})}
</span>`;
});

return resultHTML = `<a class="instantsearch__entry" href="${hit.url}">
<div class="instantsearch__entry-breadcrumbs">
${breadcrumbsHTML}
</div>
${headerHTML}
${contentHTML}
</a>`;
},
},
}),
instantsearch.widgets.pagination({
container: paginationContainer,
padding: 2,
templates: {
first: `<svg class="tile-icon" width="16" height="16">
<use fill="var(--ibexa-dusk-black)" xlink:href="../images/ez-icons.svg#caret-double-back"></use>
</svg>`,
previous: `<svg class="tile-icon" width="20" height="20">
<use fill="var(--ibexa-dusk-black)" xlink:href="../images/ez-icons.svg#caret-back"></use>
</svg>`,
next: `<svg class="tile-icon" width="20" height="20">
<use fill="var(--ibexa-dusk-black)" xlink:href="../images/ez-icons.svg#caret-next"></use>
</svg>`,
last: `<svg class="tile-icon" width="16" height="16">
<use fill="var(--ibexa-dusk-black)" xlink:href="../images/ez-icons.svg#caret-double-next"></use>
</svg>`,
},
}),
instantsearch.widgets.refinementList({
container: document.querySelector('#version'),
attribute: 'version',
}),
]);

search.start();
})(window, window.document);
Loading

0 comments on commit e0ab748

Please sign in to comment.