Add Ignore Diacritics search option
This commit is contained in:
parent
a6727bd0e4
commit
29488f2ed5
|
@ -35,6 +35,9 @@
|
|||
<label>Case-Sensitive
|
||||
<input type="checkbox" id="searchCaseSensitive">
|
||||
</label>
|
||||
<label>Ignore Diacritics/Accents
|
||||
<input type="checkbox" id="searchIgnoreDiacritics">
|
||||
</label>
|
||||
<label>Exact Words
|
||||
<input type="checkbox" id="searchExactWords">
|
||||
</label>
|
||||
|
|
|
@ -32,3 +32,21 @@ export function removeTags(html) {
|
|||
export function slugify(string) {
|
||||
return removeDiacritics(string).replace(/[!a-zA-Z0-9-_]/g, '-');
|
||||
}
|
||||
|
||||
export function getIndicesOf(searchStr, findIn, caseSensitive) {
|
||||
// https://stackoverflow.com/a/3410557
|
||||
const searchStrLen = searchStr.length;
|
||||
if (searchStrLen == 0) {
|
||||
return [];
|
||||
}
|
||||
let startIndex = 0, index, indices = [];
|
||||
if (!caseSensitive) {
|
||||
findIn = findIn.toLowerCase();
|
||||
searchStr = searchStr.toLowerCase();
|
||||
}
|
||||
while ((index = findIn.indexOf(searchStr, startIndex)) > -1) {
|
||||
indices.push(index);
|
||||
startIndex = index + searchStrLen;
|
||||
}
|
||||
return indices;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { cloneObject } from "../helpers";
|
||||
import { cloneObject, getIndicesOf } from "../helpers";
|
||||
import removeDiacritics from "./StackOverflow/removeDiacritics";
|
||||
|
||||
export function getSearchTerm() {
|
||||
return document.getElementById('searchBox').value;
|
||||
|
@ -7,6 +8,7 @@ export function getSearchTerm() {
|
|||
export function getSearchFilters() {
|
||||
const filters = {
|
||||
caseSensitive: document.getElementById('searchCaseSensitive').checked,
|
||||
ignoreDiacritics: document.getElementById('searchIgnoreDiacritics').checked,
|
||||
exact: document.getElementById('searchExactWords').checked,
|
||||
name: document.getElementById('searchIncludeName').checked,
|
||||
definition: document.getElementById('searchIncludeDefinition').checked,
|
||||
|
@ -39,17 +41,19 @@ export function getMatchingSearchWords() {
|
|||
}
|
||||
return true;
|
||||
}).filter(word => {
|
||||
searchTerm = filters.ignoreDiacritics ? removeDiacritics(searchTerm) : searchTerm;
|
||||
searchTerm = filters.caseSensitive ? searchTerm : searchTerm.toLowerCase();
|
||||
const name = filters.caseSensitive ? word.name : word.name.toLowerCase();
|
||||
const simpleDefinition = filters.caseSensitive ? word.simpleDefinition : word.simpleDefinition.toLowerCase();
|
||||
const longDefinition = filters.caseSensitive ? word.longDefinition : word.longDefinition.toLowerCase();
|
||||
let name = filters.ignoreDiacritics ? removeDiacritics(word.name) : word.name;
|
||||
name = filters.caseSensitive ? name : name.toLowerCase();
|
||||
let simpleDefinition = filters.ignoreDiacritics ? removeDiacritics(word.simpleDefinition) : word.simpleDefinition;
|
||||
simpleDefinition = filters.caseSensitive ? simpleDefinition : simpleDefinition.toLowerCase();
|
||||
let longDefinition = filters.ignoreDiacritics ? removeDiacritics(word.longDefinition) : word.longDefinition;
|
||||
longDefinition = filters.caseSensitive ? longDefinition : longDefinition.toLowerCase();
|
||||
|
||||
const isInName = filters.name
|
||||
&& (filters.exact
|
||||
const isInName = filters.name && (filters.exact
|
||||
? searchTerm == name
|
||||
: new RegExp(searchTerm, 'g').test(name));
|
||||
const isInDefinition = filters.definition
|
||||
&& (filters.exact
|
||||
const isInDefinition = filters.definition && (filters.exact
|
||||
? searchTerm == simpleDefinition
|
||||
: new RegExp(searchTerm, 'g').test(simpleDefinition));
|
||||
const isInDetails = filters.details && new RegExp(searchTerm, 'g').test(longDefinition);
|
||||
|
@ -62,14 +66,52 @@ export function getMatchingSearchWords() {
|
|||
}
|
||||
|
||||
export function highlightSearchTerm(word) {
|
||||
const searchTerm = getSearchTerm();
|
||||
let searchTerm = getSearchTerm();
|
||||
if (searchTerm) {
|
||||
const filters = getSearchFilters();
|
||||
const regexMethod = 'g' + (filters.caseSensitive ? '' : 'i');
|
||||
const markedUpWord = cloneObject(word);
|
||||
if (filters.ignoreDiacritics) {
|
||||
const searchTermLength = searchTerm.length;
|
||||
searchTerm = removeDiacritics(searchTerm);
|
||||
if (filters.name) {
|
||||
const nameMatches = getIndicesOf(searchTerm, removeDiacritics(markedUpWord.name), filters.caseSensitive);
|
||||
nameMatches.forEach((wordIndex, i) => {
|
||||
wordIndex += '<mark></mark>'.length * i;
|
||||
markedUpWord.name = markedUpWord.name.substring(0, wordIndex)
|
||||
+ '<mark>' + markedUpWord.name.substr(wordIndex, searchTermLength) + '</mark>'
|
||||
+ markedUpWord.name.substr(wordIndex + searchTermLength);
|
||||
});
|
||||
}
|
||||
if (filters.definition) {
|
||||
const simpleDefinitionMatches = getIndicesOf(searchTerm, removeDiacritics(markedUpWord.simpleDefinition), filters.caseSensitive);
|
||||
simpleDefinitionMatches.forEach((wordIndex, i) => {
|
||||
wordIndex += '<mark></mark>'.length * i;
|
||||
markedUpWord.simpleDefinition = markedUpWord.simpleDefinition.substring(0, wordIndex)
|
||||
+ '<mark>' + markedUpWord.simpleDefinition.substr(wordIndex, searchTermLength) + '</mark>'
|
||||
+ markedUpWord.simpleDefinition.substr(wordIndex + searchTermLength);
|
||||
});
|
||||
}
|
||||
if (filters.details) {
|
||||
const longDefinitionMatches = getIndicesOf(searchTerm, removeDiacritics(markedUpWord.longDefinition), filters.caseSensitive);
|
||||
longDefinitionMatches.forEach((wordIndex, i) => {
|
||||
wordIndex += '<mark></mark>'.length * i;
|
||||
markedUpWord.longDefinition = markedUpWord.longDefinition.substring(0, wordIndex)
|
||||
+ '<mark>' + markedUpWord.longDefinition.substr(wordIndex, searchTermLength) + '</mark>'
|
||||
+ markedUpWord.longDefinition.substr(wordIndex + searchTermLength);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const regexMethod = 'g' + (filters.caseSensitive ? '' : 'i');
|
||||
if (filters.name) {
|
||||
markedUpWord.name = markedUpWord.name.replace(new RegExp(`(${searchTerm})`, regexMethod), `<mark>$1</mark>`);
|
||||
}
|
||||
if (filters.definition) {
|
||||
markedUpWord.simpleDefinition = markedUpWord.simpleDefinition.replace(new RegExp(`(${searchTerm})`, regexMethod), `<mark>$1</mark>`);
|
||||
}
|
||||
if (filters.details) {
|
||||
markedUpWord.longDefinition = markedUpWord.longDefinition.replace(new RegExp(`(${searchTerm})`, regexMethod), `<mark>$1</mark>`);
|
||||
}
|
||||
}
|
||||
return markedUpWord;
|
||||
}
|
||||
return word;
|
||||
|
|
|
@ -84,6 +84,7 @@ function setupSearchBar() {
|
|||
const searchBox = document.getElementById('searchBox'),
|
||||
clearSearchButton = document.getElementById('clearSearchButton'),
|
||||
openSearchModal = document.getElementById('openSearchModal'),
|
||||
searchIgnoreDiacritics = document.getElementById('searchIgnoreDiacritics'),
|
||||
searchExactWords = document.getElementById('searchExactWords'),
|
||||
searchIncludeDetails = document.getElementById('searchIncludeDetails');
|
||||
searchBox.addEventListener('change', () => {
|
||||
|
@ -102,7 +103,7 @@ function setupSearchBar() {
|
|||
searchBox.focus();
|
||||
});
|
||||
|
||||
searchExactWords.addEventListener('change', () => {
|
||||
const toggleDetailsCheck = function() {
|
||||
if (searchExactWords.checked) {
|
||||
searchIncludeDetails.checked = false;
|
||||
searchIncludeDetails.disabled = true;
|
||||
|
@ -110,7 +111,19 @@ function setupSearchBar() {
|
|||
searchIncludeDetails.disabled = false;
|
||||
searchIncludeDetails.checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
searchIgnoreDiacritics.addEventListener('change', () => {
|
||||
if (searchIgnoreDiacritics.checked) {
|
||||
searchExactWords.checked = false;
|
||||
searchExactWords.disabled = true;
|
||||
} else {
|
||||
searchExactWords.disabled = false;
|
||||
}
|
||||
toggleDetailsCheck();
|
||||
});
|
||||
|
||||
searchExactWords.addEventListener('change', () => toggleDetailsCheck());
|
||||
}
|
||||
|
||||
export function setupSearchFilters() {
|
||||
|
|
Loading…
Reference in New Issue