mirror of
https://github.com/codex-team/codex.docs.git
synced 2025-08-08 06:55:26 +02:00
comments added
This commit is contained in:
parent
0619af1bd0
commit
8fd0b7a820
1 changed files with 88 additions and 39 deletions
|
@ -41,8 +41,15 @@ export default class SidebarFilter {
|
||||||
this.selectedSearchResultIndex = null;
|
this.selectedSearchResultIndex = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
init(sections, sidebarContent, search)
|
/**
|
||||||
{
|
* Initialize sidebar filter.
|
||||||
|
*
|
||||||
|
* @param {HTMLElement[]} sections - Array of sections.
|
||||||
|
* @param {HTMLElement} sidebarContent - Sidebar content.
|
||||||
|
* @param {HTMLElement} search - Search input.
|
||||||
|
*/
|
||||||
|
init(sections, sidebarContent, search) {
|
||||||
|
// Store refs to HTML elements.
|
||||||
this.sections = sections;
|
this.sections = sections;
|
||||||
this.sidebarContent = sidebarContent;
|
this.sidebarContent = sidebarContent;
|
||||||
this.search = search;
|
this.search = search;
|
||||||
|
@ -54,25 +61,25 @@ export default class SidebarFilter {
|
||||||
}
|
}
|
||||||
this.search.parentElement.classList.add(className);
|
this.search.parentElement.classList.add(className);
|
||||||
|
|
||||||
|
// Initialize search input.
|
||||||
|
this.search.value = '';
|
||||||
|
// Initialize the search results.
|
||||||
|
this.filterSections('');
|
||||||
|
|
||||||
// Add event listener for search input.
|
// Add event listener for search input.
|
||||||
this.search.addEventListener('input', e => {
|
this.search.addEventListener('input', e => {
|
||||||
e.stopImmediatePropagation();
|
e.stopImmediatePropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.filterSections(e.target.value);
|
this.filterSections(e.target.value);
|
||||||
});
|
});
|
||||||
// Initialize the search results.
|
|
||||||
this.filterSections('');
|
|
||||||
|
|
||||||
// Add event listener for keyboard events.
|
// Add event listener for keyboard events.
|
||||||
this.search.addEventListener('keydown', e => this.handleKeyboardEvent(e));
|
this.search.addEventListener('keydown', e => this.handleKeyboardEvent(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle keyboard events when search input is focused.
|
* Handle keyboard events while search input is focused.
|
||||||
*
|
*
|
||||||
* @param {Event} e - Event Object.
|
* @param {Event} e - Event Object.
|
||||||
* @returns {void}
|
|
||||||
*/
|
*/
|
||||||
handleKeyboardEvent(e) {
|
handleKeyboardEvent(e) {
|
||||||
// Return if search is not focused.
|
// Return if search is not focused.
|
||||||
|
@ -80,9 +87,9 @@ export default class SidebarFilter {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if enter is pressed and item is focused, then click on focused item.
|
// handle enter key when item is focused.
|
||||||
if (e.code === 'Enter' && this.selectedSearchResultIndex !== null) {
|
if (e.code === 'Enter' && this.selectedSearchResultIndex !== null) {
|
||||||
// goto focused item.
|
// navigate to focused item.
|
||||||
this.searchResults[this.selectedSearchResultIndex].element.click();
|
this.searchResults[this.selectedSearchResultIndex].element.click();
|
||||||
// prevent default action.
|
// prevent default action.
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -90,21 +97,25 @@ export default class SidebarFilter {
|
||||||
e.stopImmediatePropagation();
|
e.stopImmediatePropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle up and down navigation.
|
||||||
if (e.code === 'ArrowUp' || e.code === 'ArrowDown') {
|
if (e.code === 'ArrowUp' || e.code === 'ArrowDown') {
|
||||||
// check for search results.
|
// check for search results.
|
||||||
if (this.searchResults.length === 0) {
|
if (this.searchResults.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get current focused item.
|
// get current focused item.
|
||||||
const prevSelectedSearchResultIndex = this.selectedSearchResultIndex;
|
const prevSelectedSearchResultIndex = this.selectedSearchResultIndex;
|
||||||
|
|
||||||
this.selectedSearchResultIndex = this.getNextSectionOrItemIndex(e.code,
|
// get next item to be focus.
|
||||||
|
this.selectedSearchResultIndex = this.getNextTitleOrItemIndex(e.code,
|
||||||
this.selectedSearchResultIndex,
|
this.selectedSearchResultIndex,
|
||||||
this.searchResults.length - 1);
|
this.searchResults.length - 1);
|
||||||
|
|
||||||
this.blurSectionOrItem(prevSelectedSearchResultIndex);
|
// blur previous focused item.
|
||||||
|
this.blurTitleOrItem(prevSelectedSearchResultIndex);
|
||||||
this.focusSectionOrItem(this.selectedSearchResultIndex);
|
// focus next item.
|
||||||
|
this.focusTitleOrItem(this.selectedSearchResultIndex);
|
||||||
|
|
||||||
// prevent default action.
|
// prevent default action.
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -113,68 +124,96 @@ export default class SidebarFilter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getNextSectionOrItemIndex(code, sectionOrItemIndex, maxNumberOfSectionsOrItems) {
|
/**
|
||||||
let nextSectionOrItemIndex = sectionOrItemIndex;
|
* Get next title or item index.
|
||||||
|
*
|
||||||
|
* @param {string} code - Key code for navigation.
|
||||||
|
* @param {number} titleOrItemIndex - Current title or item index.
|
||||||
|
* @param {number} maxNumberOfTitlesOrItems - Max number of titles or items.
|
||||||
|
* @returns {number} - Next section or item index.
|
||||||
|
*/
|
||||||
|
getNextTitleOrItemIndex(code, titleOrItemIndex, maxNumberOfTitlesOrItems) {
|
||||||
|
let nextTitleOrItemIndex = titleOrItemIndex;
|
||||||
|
|
||||||
if (code === 'ArrowUp') {
|
if (code === 'ArrowUp') {
|
||||||
if (sectionOrItemIndex === null) {
|
// if no item is focused, focus last item.
|
||||||
return maxNumberOfSectionsOrItems;
|
if (titleOrItemIndex === null) {
|
||||||
|
return maxNumberOfTitlesOrItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextSectionOrItemIndex--;
|
// focus previous item.
|
||||||
|
nextTitleOrItemIndex--;
|
||||||
|
|
||||||
if (nextSectionOrItemIndex < 0) {
|
// circular navigation.
|
||||||
nextSectionOrItemIndex = maxNumberOfSectionsOrItems;
|
if (nextTitleOrItemIndex < 0) {
|
||||||
|
nextTitleOrItemIndex = maxNumberOfTitlesOrItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nextSectionOrItemIndex;
|
return nextTitleOrItemIndex;
|
||||||
}
|
} else if (code === 'ArrowDown') {
|
||||||
else if (code === 'ArrowDown') {
|
// if no item is focused, focus first item.
|
||||||
if (sectionOrItemIndex === null) {
|
if (titleOrItemIndex === null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextSectionOrItemIndex++;
|
// focus next item.
|
||||||
|
nextTitleOrItemIndex++;
|
||||||
|
|
||||||
if (nextSectionOrItemIndex > maxNumberOfSectionsOrItems) {
|
// circular navigation.
|
||||||
nextSectionOrItemIndex = 0;
|
if (nextTitleOrItemIndex > maxNumberOfTitlesOrItems) {
|
||||||
|
nextTitleOrItemIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nextSectionOrItemIndex;
|
return nextTitleOrItemIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
focusSectionOrItem(sectionOrItemIndex) {
|
/**
|
||||||
if (sectionOrItemIndex === null) {
|
* Focus title or item at given index.
|
||||||
|
*
|
||||||
|
* @param {number} titleOrItemIndex - Title or item index.
|
||||||
|
*/
|
||||||
|
focusTitleOrItem(titleOrItemIndex) {
|
||||||
|
// check for valid index.
|
||||||
|
if (titleOrItemIndex === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { element, type } = this.searchResults[sectionOrItemIndex];
|
const { element, type } = this.searchResults[titleOrItemIndex];
|
||||||
|
|
||||||
if (!element || !type) {
|
if (!element || !type) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// focus title or item.
|
||||||
if (type === 'title') {
|
if (type === 'title') {
|
||||||
element.classList.add(SidebarFilter.CSS.sectionTitleSelected);
|
element.classList.add(SidebarFilter.CSS.sectionTitleSelected);
|
||||||
} else if (type === 'item') {
|
} else if (type === 'item') {
|
||||||
element.classList.add(SidebarFilter.CSS.sectionListItemSlelected);
|
element.classList.add(SidebarFilter.CSS.sectionListItemSlelected);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.scrollToSectionOrItem(element);
|
// scroll to focused title or item.
|
||||||
|
this.scrollToTitleOrItem(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
blurSectionOrItem(sectionOrItemIndex) {
|
/**
|
||||||
if (sectionOrItemIndex === null) {
|
* Blur title or item at given index.
|
||||||
|
*
|
||||||
|
* @param {number} titleOrItemIndex - Title or item index.
|
||||||
|
*/
|
||||||
|
blurTitleOrItem(titleOrItemIndex) {
|
||||||
|
// check for valid index.
|
||||||
|
if (titleOrItemIndex === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { element, type } = this.searchResults[sectionOrItemIndex];
|
const { element, type } = this.searchResults[titleOrItemIndex];
|
||||||
|
|
||||||
if (!element || !type) {
|
if (!element || !type) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// blur title or item.
|
||||||
if (type === 'title') {
|
if (type === 'title') {
|
||||||
element.classList.remove(SidebarFilter.CSS.sectionTitleSelected);
|
element.classList.remove(SidebarFilter.CSS.sectionTitleSelected);
|
||||||
} else if (type === 'item') {
|
} else if (type === 'item') {
|
||||||
|
@ -182,9 +221,14 @@ export default class SidebarFilter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scrollToSectionOrItem(sectionOrItem) {
|
/**
|
||||||
|
* Scroll to title or item.
|
||||||
|
*
|
||||||
|
* @param {HTMLElement} titleOrItem - Title or item element.
|
||||||
|
*/
|
||||||
|
scrollToTitleOrItem(titleOrItem) {
|
||||||
// check if it's visible.
|
// check if it's visible.
|
||||||
const rect = sectionOrItem.getBoundingClientRect();
|
const rect = titleOrItem.getBoundingClientRect();
|
||||||
let elemTop = rect.top;
|
let elemTop = rect.top;
|
||||||
let elemBottom = rect.bottom;
|
let elemBottom = rect.bottom;
|
||||||
const halfOfViewport = window.innerHeight / 2;
|
const halfOfViewport = window.innerHeight / 2;
|
||||||
|
@ -215,9 +259,14 @@ export default class SidebarFilter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter sidebar items.
|
||||||
|
*
|
||||||
|
* @param {string} searchValue - Search value.
|
||||||
|
*/
|
||||||
filterSections(searchValue) {
|
filterSections(searchValue) {
|
||||||
// remove selection from previous search results.
|
// remove selection from previous search results.
|
||||||
this.blurSectionOrItem(this.selectedSearchResultIndex);
|
this.blurTitleOrItem(this.selectedSearchResultIndex);
|
||||||
// empty selected index.
|
// empty selected index.
|
||||||
this.selectedSearchResultIndex = null;
|
this.selectedSearchResultIndex = null;
|
||||||
// empty search results.
|
// empty search results.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue