From c0909343f61be4a8d6ea457734b3ae7dcf32e89a Mon Sep 17 00:00:00 2001 From: Robbie Antenesse Date: Thu, 6 Jun 2019 11:03:00 -0600 Subject: [PATCH] Shrink view js by splitting out only what is needed --- src/js/view/dictionaryManagement.js | 12 --- src/js/view/index.js | 12 +-- src/js/view/render.js | 14 ++- src/js/view/search.js | 145 ++++++++++++++++++++++++++++ src/js/view/setupListeners.js | 2 +- src/js/view/utilities.js | 102 +++++++++++++++++++ src/js/view/wordManagement.js | 44 +++++++++ 7 files changed, 303 insertions(+), 28 deletions(-) delete mode 100644 src/js/view/dictionaryManagement.js create mode 100644 src/js/view/search.js create mode 100644 src/js/view/utilities.js create mode 100644 src/js/view/wordManagement.js diff --git a/src/js/view/dictionaryManagement.js b/src/js/view/dictionaryManagement.js deleted file mode 100644 index eb5f3fb..0000000 --- a/src/js/view/dictionaryManagement.js +++ /dev/null @@ -1,12 +0,0 @@ -export function getDictionary() { - const url = window.location.href.replace(/\#.*$/gi, ''); - console.log(url); - let dict = url.substr(url.lastIndexOf('?')); - console.log(dict); - if (dict === url) { - dict = dict.substr(dict.lastIndexOf('/')); - console.log(dict); - } - dict = dict.replace(/[\?\/]/g, ''); - console.log(dict); -} \ No newline at end of file diff --git a/src/js/view/index.js b/src/js/view/index.js index 4cacb87..b588b6f 100644 --- a/src/js/view/index.js +++ b/src/js/view/index.js @@ -2,20 +2,12 @@ import { renderAll } from './render'; import setupListeners from './setupListeners'; import { setupAds } from '../ads'; -// import setupListeners, { setupSearchFilters } from './js/setupListeners'; -// import { renderAll } from './js/render'; -// import { hasToken } from './js/utilities'; -// import { loadDictionary } from './js/dictionaryManagement'; -// import { loadSettings } from './js/settings'; - function initialize() { setupAds().then(() => renderAll()); setupListeners(); } window.onload = (function (oldLoad) { - return function () { - oldLoad && oldLoad(); - initialize(); - } + oldLoad && oldLoad(); + initialize(); })(window.onload); \ No newline at end of file diff --git a/src/js/view/render.js b/src/js/view/render.js index 3dcbabc..8e5cb46 100644 --- a/src/js/view/render.js +++ b/src/js/view/render.js @@ -1,11 +1,10 @@ import md from 'marked'; import { removeTags, slugify } from '../../helpers'; -import { getWordsStats, wordExists } from '../utilities'; -import { getMatchingSearchWords, highlightSearchTerm, getSearchFilters, getSearchTerm } from '../search'; -import { showSection } from '../displayToggles'; +import { getWordsStats } from './utilities'; +import { getMatchingSearchWords, highlightSearchTerm, getSearchFilters, getSearchTerm } from './search'; +import { showSection } from './displayToggles'; import { setupSearchFilters, setupInfoModal } from './setupListeners'; -import { parseReferences } from '../wordManagement'; -import { renderTheme } from '../render'; +import { parseReferences } from './wordManagement'; import { renderAd } from '../ads'; export function renderAll() { @@ -15,6 +14,11 @@ export function renderAll() { renderWords(); } +export function renderTheme() { + const { theme } = window.currentDictionary.settings; + document.body.id = theme + 'Theme'; +} + export function renderDictionaryDetails() { renderName(); diff --git a/src/js/view/search.js b/src/js/view/search.js new file mode 100644 index 0000000..42f76b8 --- /dev/null +++ b/src/js/view/search.js @@ -0,0 +1,145 @@ +import { cloneObject, getIndicesOf } from "../../helpers"; +import removeDiacritics from "../StackOverflow/removeDiacritics"; +import { renderWords } from "./render"; + +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, + 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 => { + // console.log('partOfSpeech Inner Text:', partOfSpeech.parentElement.innerText); + const partOfSpeechLabel = partOfSpeech.parentElement.innerText.trim(); + filters.partsOfSpeech[partOfSpeechLabel] = partOfSpeech.checked; + if (partOfSpeech.checked) checkedBoxes++; + }); + + filters.allPartsOfSpeechChecked = checkedBoxes === partsOfSpeech.length; + + return filters; +} + +export function getMatchingSearchWords() { + let searchTerm = getSearchTerm(); + const filters = getSearchFilters(); + if (searchTerm !== '' || !filters.allPartsOfSpeechChecked) { + const matchingWords = window.currentDictionary.words.slice().filter(word => { + if (!filters.allPartsOfSpeechChecked) { + const partOfSpeech = word.partOfSpeech === '' ? 'Unclassified' : word.partOfSpeech; + return filters.partsOfSpeech.hasOwnProperty(partOfSpeech) && filters.partsOfSpeech[partOfSpeech]; + } + return true; + }).filter(word => { + searchTerm = filters.ignoreDiacritics ? removeDiacritics(searchTerm) : searchTerm; + searchTerm = filters.caseSensitive ? searchTerm : searchTerm.toLowerCase(); + let name = filters.ignoreDiacritics ? removeDiacritics(word.name) : word.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.ignoreDiacritics ? removeDiacritics(word.details) : word.details; + details = filters.caseSensitive ? details : details.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); + return searchTerm === '' || isInName || isInDefinition || isInDetails; + }); + return matchingWords; + } + + return window.currentDictionary.words +} + +export function highlightSearchTerm(word) { + let searchTerm = getSearchTerm(); + if (searchTerm) { + const filters = getSearchFilters(); + 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 += ''.length * i; + markedUpWord.name = markedUpWord.name.substring(0, wordIndex) + + '' + markedUpWord.name.substr(wordIndex, searchTermLength) + '' + + markedUpWord.name.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 (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(); +} \ No newline at end of file diff --git a/src/js/view/setupListeners.js b/src/js/view/setupListeners.js index 82e8b47..8ba46bb 100644 --- a/src/js/view/setupListeners.js +++ b/src/js/view/setupListeners.js @@ -1,5 +1,5 @@ import {showSection, hideDetailsPanel} from './displayToggles'; -import { showSearchModal, clearSearchText, checkAllPartsOfSpeechFilters, uncheckAllPartsOfSpeechFilters } from '../search'; +import { showSearchModal, clearSearchText, checkAllPartsOfSpeechFilters, uncheckAllPartsOfSpeechFilters } from './search'; import { renderWords, renderInfoModal } from './render'; export default function setupListeners() { diff --git a/src/js/view/utilities.js b/src/js/view/utilities.js new file mode 100644 index 0000000..3753346 --- /dev/null +++ b/src/js/view/utilities.js @@ -0,0 +1,102 @@ +export function getWordsStats() { + const {words, partsOfSpeech} = window.currentDictionary; + const {caseSensitive} = window.currentDictionary.settings; + + const wordStats = { + numberOfWords: [ + { + name: 'Total', + value: words.length, + }, + ], + wordLength: { + shortest: 0, + longest: 0, + average: 0, + }, + letterDistribution: [ + /* { + letter: '', + number: 0, + percentage: 0.00, + } */ + ], + totalLetters: 0, + }; + + partsOfSpeech.forEach(partOfSpeech => { + const wordsWithPartOfSpeech = words.filter(word => word.partOfSpeech === partOfSpeech); + wordStats.numberOfWords.push({ + name: partOfSpeech, + value: wordsWithPartOfSpeech.length, + }); + }); + + wordStats.numberOfWords.push({ + name: 'Unclassified', + value: words.filter(word => !partsOfSpeech.includes(word.partOfSpeech)).length, + }); + + let totalLetters = 0; + const numberOfLetters = {}; + + words.forEach(word => { + const shortestWord = wordStats.wordLength.shortest; + const longestWord = wordStats.wordLength.longest; + const wordLetters = word.name.split(''); + const lettersInWord = wordLetters.length; + + totalLetters += lettersInWord; + + if (shortestWord === 0 || lettersInWord < shortestWord) { + wordStats.wordLength.shortest = lettersInWord; + } + + if (longestWord === 0 || lettersInWord > longestWord) { + wordStats.wordLength.longest = lettersInWord; + } + + wordLetters.forEach(letter => { + const letterToUse = caseSensitive ? letter : letter.toLowerCase(); + if (!numberOfLetters.hasOwnProperty(letterToUse)) { + numberOfLetters[letterToUse] = 1; + } else { + numberOfLetters[letterToUse]++; + } + }); + }); + + wordStats.totalLetters = totalLetters; + wordStats.wordLength.average = words.length > 0 ? Math.round(totalLetters / words.length) : 0; + + for (const letter in numberOfLetters) { + if (numberOfLetters.hasOwnProperty(letter)) { + const number = numberOfLetters[letter]; + wordStats.letterDistribution.push({ + letter, + number, + percentage: number / totalLetters, + }); + } + } + + wordStats.letterDistribution.sort((a, b) => { + if (a.percentage === b.percentage) return 0; + return (a.percentage > b.percentage) ? -1 : 1; + }); + + return wordStats; +} + +export function getHomonymnIndexes(word) { + const { currentDictionary } = window; + const { caseSensitive } = currentDictionary.settings; + const foundIndexes = []; + currentDictionary.words.forEach((existingWord, index) => { + if (existingWord.wordId !== word.wordId + && (caseSensitive ? existingWord.name === word.name : existingWord.name.toLowerCase() === word.name.toLowerCase())) { + foundIndexes.push(index); + } + }); + return foundIndexes; +} diff --git a/src/js/view/wordManagement.js b/src/js/view/wordManagement.js new file mode 100644 index 0000000..ff1fe64 --- /dev/null +++ b/src/js/view/wordManagement.js @@ -0,0 +1,44 @@ +import { wordExists, getHomonymnIndexes } from "./utilities"; + +export function parseReferences(detailsMarkdown) { + const references = detailsMarkdown.match(/\{\{.+?\}\}/g); + if (references && Array.isArray(references)) { + new Set(references).forEach(reference => { + let wordToFind = reference.replace(/\{\{|\}\}/g, ''); + let homonymn = 0; + + if (wordToFind.includes(':')) { + const separator = wordToFind.indexOf(':'); + homonymn = wordToFind.substr(separator + 1); + wordToFind = wordToFind.substring(0, separator); + if (homonymn && homonymn.trim() + && !isNaN(parseInt(homonymn.trim())) && parseInt(homonymn.trim()) > 0) { + homonymn = parseInt(homonymn.trim()); + } else { + homonymn = false; + } + } + + let existingWordId = false; + const homonymnIndexes = getHomonymnIndexes({ name: wordToFind, wordId: -1 }); + + if (homonymn !== false && homonymn > 0) { + if (typeof homonymnIndexes[homonymn - 1] !== 'undefined') { + existingWordId = window.currentDictionary.words[homonymnIndexes[homonymn - 1]].wordId; + } + } else if (homonymn !== false) { + existingWordId = wordExists(wordToFind, true); + } + + if (existingWordId !== false) { + if (homonymn < 1 && homonymnIndexes.length > 0) { + homonymn = 1; + } + const homonymnSubHTML = homonymn > 0 ? '' + homonymn.toString() + '' : ''; + const wordMarkdownLink = `[${wordToFind}${homonymnSubHTML}](#${existingWordId})`; + detailsMarkdown = detailsMarkdown.replace(new RegExp(reference, 'g'), wordMarkdownLink); + } + }); + } + return detailsMarkdown; +}