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;
+}