import { cloneObject, getIndicesOf } from "../helpers"; import removeDiacritics from "./StackOverflow/removeDiacritics"; import { renderWords } from "./render/words"; import { translateOrthography, parseReferences } from "./wordManagement"; export function showSearchModal() { document.getElementById('searchModal').style.display = 'block'; document.getElementById('searchBox').focus(); } export function clearSearchText() { document.getElementById('searchBox').value = ''; document.getElementById('openSearchModal').value = ''; renderWords(); } export function getSearchTerm() { return document.getElementById('searchBox').value; } export function getSearchFilters() { const filters = { caseSensitive: document.getElementById('searchCaseSensitive').checked, ignoreDiacritics: document.getElementById('searchIgnoreDiacritics').checked, exact: document.getElementById('searchExactWords').checked, orthography: document.getElementById('searchOrthography').checked, name: document.getElementById('searchIncludeName').checked, definition: document.getElementById('searchIncludeDefinition').checked, details: document.getElementById('searchIncludeDetails').checked, partsOfSpeech: {}, }; const partsOfSpeech = document.querySelectorAll('#searchPartsOfSpeech input[type="checkbox"]'); let checkedBoxes = 0; Array.from(partsOfSpeech).forEach(partOfSpeech => { const partOfSpeechLabel = partOfSpeech.parentElement.innerText.trim(); filters.partsOfSpeech[partOfSpeechLabel] = partOfSpeech.checked; if (partOfSpeech.checked) checkedBoxes++; }); filters.allPartsOfSpeechChecked = checkedBoxes === partsOfSpeech.length; return filters; } function wordMatchesPartsOfSpeechFilter(word, filters) { if (!filters.allPartsOfSpeechChecked) { const partOfSpeech = word.partOfSpeech === '' ? 'Unclassified' : word.partOfSpeech; return filters.partsOfSpeech.hasOwnProperty(partOfSpeech) && filters.partsOfSpeech[partOfSpeech]; } return true; } function wordMatchesSearchTermAndOptions(word, searchTerm, filters) { if (searchTerm === '') return true; // If searchTerm is blank, don't process word. searchTerm = filters.ignoreDiacritics ? removeDiacritics(searchTerm) : searchTerm; searchTerm = filters.caseSensitive ? searchTerm : searchTerm.toLowerCase(); let name = filters.orthography ? translateOrthography(word.name) : word.name; name = filters.ignoreDiacritics ? removeDiacritics(name) : name; name = filters.caseSensitive ? name : name.toLowerCase(); let definition = filters.ignoreDiacritics ? removeDiacritics(word.definition) : word.definition; definition = filters.caseSensitive ? definition : definition.toLowerCase(); let details = filters.orthography ? parseReferences(word.details) : word.details; details = filters.ignoreDiacritics ? removeDiacritics(details) : details; details = filters.caseSensitive ? details : details.toLowerCase(); let principalParts = typeof word.principalParts === 'undefined' ? [] : word.principalParts; principalParts = filters.orthography ? principalParts.map(part => translateOrthography(part)) : principalParts; principalParts = filters.ignoreDiacritics ? principalParts.map(part => removeDiacritics(part)) : principalParts; principalParts = filters.caseSensitive ? principalParts : principalParts.map(part => part.toLowerCase()); const isInName = filters.name && (filters.exact ? searchTerm == name : new RegExp(searchTerm, 'g').test(name) ); const isInDefinition = filters.definition && (filters.exact ? searchTerm == definition : new RegExp(searchTerm, 'g').test(definition) ); const isInDetails = filters.details && new RegExp(searchTerm, 'g').test(details); const isInPrincipalParts = filters.name && (filters.exact ? principalParts.includes(searchTerm) : principalParts.some(part => new RegExp(searchTerm, 'g').test(part)) ); return isInName || isInDefinition || isInDetails || isInPrincipalParts; } export function getMatchingSearchWords() { const searchTerm = getSearchTerm(); const filters = getSearchFilters(); if (searchTerm !== '' || !filters.allPartsOfSpeechChecked) { const matchingWords = window.currentDictionary.words.slice() .filter(word => wordMatchesPartsOfSpeechFilter(word, filters)) .filter(word => wordMatchesSearchTermAndOptions(word, searchTerm, filters)); return matchingWords; } return window.currentDictionary.words; } export function wordMatchesSearch(word) { const searchTerm = getSearchTerm(); const filters = getSearchFilters(); if (searchTerm !== '' || !filters.allPartsOfSpeechChecked) { if (searchTerm === '') { return wordMatchesPartsOfSpeechFilter(word, filters); } return wordMatchesPartsOfSpeechFilter(word, filters) && wordMatchesSearchTermAndOptions(word, searchTerm, filters); } return true; } export function highlightSearchTerm(word) { let searchTerm = getSearchTerm(); if (searchTerm) { const filters = getSearchFilters(); const markedUpWord = cloneObject(word); if (filters.orthography) { markedUpWord.name = translateOrthography(markedUpWord.name); markedUpWord.details = parseReferences(markedUpWord.details); } 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 += ''.length * i; markedUpWord.name = markedUpWord.name.substring(0, wordIndex) + '' + markedUpWord.name.substr(wordIndex, searchTermLength) + '' + markedUpWord.name.substr(wordIndex + searchTermLength); }); if (markedUpWord.principalParts !== null) { const part = getIndicesOf(searchTerm, removeDiacritics(markedUpWord.principalParts), filters.caseSensitive); part.forEach((wordIndex, i) => { wordIndex += ''.length * i; markedUpWord.principalParts = markedUpWord.principalParts.substring(0, wordIndex) + '' + markedUpWord.principalParts.substr(wordIndex, searchTermLength) + '' + markedUpWord.principalParts.substr(wordIndex + searchTermLength); }); } } if (filters.definition) { const definitionMatches = getIndicesOf(searchTerm, removeDiacritics(markedUpWord.definition), filters.caseSensitive); definitionMatches.forEach((wordIndex, i) => { wordIndex += ''.length * i; markedUpWord.definition = markedUpWord.definition.substring(0, wordIndex) + '' + markedUpWord.definition.substr(wordIndex, searchTermLength) + '' + markedUpWord.definition.substr(wordIndex + searchTermLength); }); } if (filters.details) { const detailsMatches = getIndicesOf(searchTerm, removeDiacritics(markedUpWord.details), filters.caseSensitive); detailsMatches.forEach((wordIndex, i) => { wordIndex += ''.length * i; markedUpWord.details = markedUpWord.details.substring(0, wordIndex) + '' + markedUpWord.details.substr(wordIndex, searchTermLength) + '' + markedUpWord.details.substr(wordIndex + searchTermLength); }); } } else { const regexMethod = 'g' + (filters.caseSensitive ? '' : 'i'); if (filters.name) { markedUpWord.name = markedUpWord.name.replace(new RegExp(`(${searchTerm})`, regexMethod), `$1`); if (markedUpWord.principalParts !== null) { markedUpWord.principalParts = markedUpWord.principalParts.replace(new RegExp(`(${searchTerm})`, regexMethod), `$1`); } } if (filters.definition) { markedUpWord.definition = markedUpWord.definition.replace(new RegExp(`(${searchTerm})`, regexMethod), `$1`); } if (filters.details) { markedUpWord.details = markedUpWord.details.replace(new RegExp(`(${searchTerm})`, regexMethod), `$1`); } } return markedUpWord; } return word; } export function checkAllPartsOfSpeechFilters() { const searchFilters = document.querySelectorAll('#searchPartsOfSpeech input[type="checkbox"]'); Array.from(searchFilters).forEach(filter => { filter.checked = true; }); renderWords(); } export function uncheckAllPartsOfSpeechFilters() { const searchFilters = document.querySelectorAll('#searchPartsOfSpeech input[type="checkbox"]'); Array.from(searchFilters).forEach(filter => { filter.checked = false; }); renderWords(); }