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