Compare commits
7 Commits
0673a2378e
...
88c522ea1b
Author | SHA1 | Date |
---|---|---|
Robbie Antenesse | 88c522ea1b | |
Robbie Antenesse | f3fd01f143 | |
Robbie Antenesse | dbff3a122e | |
Robbie Antenesse | 7011054487 | |
Robbie Antenesse | 060a78b3e4 | |
Robbie Antenesse | e4369f0ffd | |
Robbie Antenesse | 7b54e473e4 |
44
index.html
44
index.html
|
@ -10,7 +10,41 @@
|
|||
<body>
|
||||
<header id="top">
|
||||
<h1 id="title">Lexiconga</h1>
|
||||
<input id="searchButton" placeholder="🔍︎ Search">
|
||||
<input id="openSearchModal" placeholder="🔍︎ Search">
|
||||
<section id="searchModal" class="modal" style="display:none;">
|
||||
<div class="modal-background" onclick="this.parentElement.style.display='none';"></div>
|
||||
<div class="modal-content">
|
||||
<a class="close-button" onclick="this.parentElement.parentElement.style.display='none';">×︎</a>
|
||||
<section>
|
||||
<label><strong>Search Term</strong>
|
||||
<input id="searchBox" placeholder="Search term">
|
||||
</label>
|
||||
<a id="searchButton" class="small button">Search</a>
|
||||
<a id="clearSearchButton" class="small red button">Clear</a>
|
||||
<a class="small button" onclick="var options=document.getElementById('searchOptions').style;options.display=options.display=='block'?'none':'block';">
|
||||
Toggle Options
|
||||
</a>
|
||||
</section>
|
||||
<footer id="searchOptions" style="display:none;">
|
||||
<div class="split">
|
||||
<div class="quarter category">
|
||||
<h3>Include in Search</h3>
|
||||
</div>
|
||||
<div class="three-quarter options">
|
||||
<label><strong>Word Name</strong>
|
||||
<input type="checkbox" checked id="searchIncludeName">
|
||||
</label>
|
||||
<label><strong>Definition</strong>
|
||||
<input type="checkbox" checked id="searchIncludeDefinition">
|
||||
</label>
|
||||
<label><strong>Details</strong>
|
||||
<input type="checkbox" checked id="searchIncludeDetails">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</section>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
|
@ -23,20 +57,20 @@
|
|||
<input id="wordPronunciation">
|
||||
</label>
|
||||
<label>Part of Speech<br>
|
||||
<select id="wordPartOfSpeech"></select>
|
||||
<select id="wordPartOfSpeech" class="part-of-speech-select"></select>
|
||||
</label>
|
||||
<label>Definition<br>
|
||||
<input id="wordDefinition">
|
||||
<input id="wordDefinition" placeholder="Equivalent words">
|
||||
</label>
|
||||
<label>Details<a class="label-button">Maximize</a><br>
|
||||
<textarea id="wordDetails"></textarea>
|
||||
<textarea id="wordDetails" placeholder="Markdown formatting allowed"></textarea>
|
||||
</label>
|
||||
</form>
|
||||
</aside>
|
||||
|
||||
<section id="mainColumn">
|
||||
<section id="detailsSection">
|
||||
<h2>Dictionary Name</h2>
|
||||
<h2 id="dictionaryName">Dictionary Name</h2>
|
||||
<nav>
|
||||
<ul>
|
||||
<li>Description</li><li>Details</li><li>Stats</li><li onclick="document.getElementById('editModal').style.display='block'">Edit</li>
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
export function cloneObject(object) {
|
||||
return JSON.parse(JSON.stringify(object));
|
||||
}
|
||||
|
||||
export function removeTags(html) {
|
||||
var tagBody = '(?:[^"\'>]|"[^"]*"|\'[^\']*\')*';
|
||||
|
||||
|
@ -19,4 +23,4 @@ var tagOrComment = new RegExp(
|
|||
html = html.replace(tagOrComment, '');
|
||||
} while (html !== oldHtml);
|
||||
return html.replace(/</g, '<');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,14 @@ import './main.scss';
|
|||
|
||||
import { DEFAULT_DICTIONARY } from './constants';
|
||||
import setupListeners from './js/setupListeners';
|
||||
import { renderAll } from './js/render';
|
||||
import { cloneObject } from './helpers';
|
||||
|
||||
function initialize() {
|
||||
console.log('initializing');
|
||||
window.currentDictionary = JSON.parse(JSON.stringify(DEFAULT_DICTIONARY));
|
||||
window.currentDictionary = cloneObject(DEFAULT_DICTIONARY);
|
||||
setupListeners();
|
||||
renderAll();
|
||||
}
|
||||
|
||||
window.onload = (function (oldLoad) {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import md from 'snarkdown';
|
||||
import {removeTags} from '../helpers';
|
||||
import { renderDescription, renderDetails, renderStats } from './render';
|
||||
|
||||
export function showSection(sectionName) {
|
||||
switch (sectionName) {
|
||||
|
@ -12,153 +11,18 @@ export function showSection(sectionName) {
|
|||
function showDescription() {
|
||||
const detailsPanel = document.getElementById('detailsPanel');
|
||||
detailsPanel.style.display = 'block';
|
||||
const {description} = window.currentDictionary;
|
||||
const descriptionHTML = md(removeTags(description));
|
||||
|
||||
detailsPanel.innerHTML = descriptionHTML;
|
||||
renderDescription();
|
||||
}
|
||||
|
||||
function showDetails() {
|
||||
const detailsPanel = document.getElementById('detailsPanel');
|
||||
detailsPanel.style.display = 'block';
|
||||
const {partsOfSpeech, alphabeticalOrder} = window.currentDictionary;
|
||||
const {phonology, orthography, grammar} = window.currentDictionary.details;
|
||||
const partsOfSpeechHTML = `<p><strong>Parts of Speech:</strong> ${partsOfSpeech.map(partOfSpeech => '<span class="tag">' + partOfSpeech + '</span>').join(' ')}</p>`;
|
||||
const alphabeticalOrderHTML = `<p><strong>Alphabetical Order:</strong> ${
|
||||
(alphabeticalOrder.length > 0 ? alphabeticalOrder : ['English Alphabet']).map(letter => `<span class="tag">${letter}</span>`).join(' ')
|
||||
}</p>`;
|
||||
const generalHTML = `<h3>General</h3>${partsOfSpeechHTML}${alphabeticalOrderHTML}`;
|
||||
|
||||
const {consonants, vowels, blends, phonotactics} = phonology
|
||||
const consonantHTML = `<p><strong>Consonants:</strong> ${consonants.map(letter => `<span class="tag">${letter}</span>`).join(' ')}</p>`;
|
||||
const vowelHTML = `<p><strong>Vowels:</strong> ${vowels.map(letter => `<span class="tag">${letter}</span>`).join(' ')}</p>`;
|
||||
const blendHTML = blends.length > 0 ? `<p><strong>Polyphthongs / Blends:</strong> ${blends.map(letter => `<span class="tag">${letter}</span>`).join(' ')}</p>` : '';
|
||||
const phonologyHTML = `<h3>Phonology</h3>
|
||||
<div class="split two">
|
||||
<div>${consonantHTML}</div>
|
||||
<div>${vowelHTML}</div>
|
||||
</div>
|
||||
${blendHTML}`;
|
||||
|
||||
const {onset, nucleus, coda, exceptions} = phonotactics;
|
||||
const onsetHTML = `<p><strong>Onset:</strong> ${onset.map(letter => `<span class="tag">${letter}</span>`).join(' ')}</p>`;
|
||||
const nucleusHTML = `<p><strong>Nucleus:</strong> ${nucleus.map(letter => `<span class="tag">${letter}</span>`).join(' ')}</p>`;
|
||||
const codaHTML = `<p><strong>Coda:</strong> ${coda.map(letter => `<span class="tag">${letter}</span>`).join(' ')}</p>`;
|
||||
const exceptionsHTML = exceptions.trim().length > 0 ? '<p><strong>Exceptions:</strong></p><div>' + md(removeTags(exceptions)) + '</div>' : '';
|
||||
const phonotacticsHTML = `<h3>Phonotactics</h3>
|
||||
<div class="split three">
|
||||
<div>${onsetHTML}</div>
|
||||
<div>${nucleusHTML}</div>
|
||||
<div>${codaHTML}</div>
|
||||
</div>
|
||||
${exceptionsHTML}`;
|
||||
|
||||
const orthographyHTML = '<h3>Orthography</h3><p><strong>Notes:</strong></p><div>' + md(removeTags(orthography.notes)) + '</div>';
|
||||
const grammarHTML = '<h3>Grammar</h3><p><strong>Notes:</strong></p><div>' + md(removeTags(grammar.notes)) + '</div>';
|
||||
|
||||
detailsPanel.innerHTML = generalHTML + phonologyHTML + phonotacticsHTML + orthographyHTML + grammarHTML;
|
||||
renderDetails();
|
||||
}
|
||||
|
||||
function showStats() {
|
||||
const detailsPanel = document.getElementById('detailsPanel');
|
||||
detailsPanel.style.display = 'block';
|
||||
const wordStats = getWordsStats();
|
||||
const numberOfWordsHTML = `<p><strong>Number of Words</strong><br>${wordStats.numberOfWords.map(stat => `<span><span class="tag">${stat.name}</span><span class="tag">${stat.value}</span></span>`).join(' ')}</p>`;
|
||||
const wordLengthHTML = `<p><strong>Word Length</strong><br><span><span class="tag">Shortest</span><span class="tag">${wordStats.wordLength.shortest}</span></span>
|
||||
<span><span class="tag">Longest</span><span class="tag">${wordStats.wordLength.longest}</span></span>
|
||||
<span><span class="tag">Average</span><span class="tag">${wordStats.wordLength.average}</span></span></p>`;
|
||||
const letterDistributionHTML = `<p><strong>Letter Distribution</strong><br>${wordStats.letterDistribution.map(stat => `<span title="${stat.number} ${stat.letter}'s total"><span class="tag">${stat.letter}</span><span class="tag">${stat.percentage.toFixed(2)}</span></span>`).join(' ')}</p>`;
|
||||
const totalLettersHTML = `<p><strong>${wordStats.totalLetters} Total Letters</strong></p>`;
|
||||
|
||||
detailsPanel.innerHTML = numberOfWordsHTML + wordLengthHTML + letterDistributionHTML + totalLettersHTML;
|
||||
renderStats();
|
||||
}
|
||||
|
||||
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 ? 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;
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
import md from 'snarkdown';
|
||||
import { removeTags } from '../helpers';
|
||||
import { getWordsStats, wordExists } from './utilities';
|
||||
import { getMatchingSearchWords, highlightSearchTerm } from './search';
|
||||
import { showSection } from './displayToggles';
|
||||
|
||||
export function renderAll() {
|
||||
renderDictionaryDetails();
|
||||
renderPartsOfSpeechSelect();
|
||||
renderWords();
|
||||
}
|
||||
|
||||
export function renderDictionaryDetails() {
|
||||
renderName();
|
||||
|
||||
const tabs = document.querySelectorAll('#detailsSection nav li');
|
||||
const shownTab = Array.from(tabs).find(tab => tab.classList.contains('active'));
|
||||
if (shownTab) {
|
||||
const tabName = shownTab.innerText.toLowerCase();
|
||||
showSection(tabName);
|
||||
}
|
||||
}
|
||||
|
||||
export function renderName() {
|
||||
const dictionaryName = removeTags(window.currentDictionary.name) + ' ' + removeTags(window.currentDictionary.specification);
|
||||
document.getElementById('dictionaryName').innerHTML = dictionaryName;
|
||||
}
|
||||
|
||||
export function renderDescription() {
|
||||
const descriptionHTML = md(removeTags(window.currentDictionary.description));
|
||||
|
||||
detailsPanel.innerHTML = descriptionHTML;
|
||||
}
|
||||
|
||||
export function renderDetails() {
|
||||
const { partsOfSpeech, alphabeticalOrder } = window.currentDictionary;
|
||||
const { phonology, orthography, grammar } = window.currentDictionary.details;
|
||||
const partsOfSpeechHTML = `<p><strong>Parts of Speech:</strong> ${partsOfSpeech.map(partOfSpeech => '<span class="tag">' + partOfSpeech + '</span>').join(' ')}</p>`;
|
||||
const alphabeticalOrderHTML = `<p><strong>Alphabetical Order:</strong> ${
|
||||
(alphabeticalOrder.length > 0 ? alphabeticalOrder : ['English Alphabet']).map(letter => `<span class="tag">${letter}</span>`).join(' ')
|
||||
}</p>`;
|
||||
const generalHTML = `<h3>General</h3>${partsOfSpeechHTML}${alphabeticalOrderHTML}`;
|
||||
|
||||
const { consonants, vowels, blends, phonotactics } = phonology
|
||||
const consonantHTML = `<p><strong>Consonants:</strong> ${consonants.map(letter => `<span class="tag">${letter}</span>`).join(' ')}</p>`;
|
||||
const vowelHTML = `<p><strong>Vowels:</strong> ${vowels.map(letter => `<span class="tag">${letter}</span>`).join(' ')}</p>`;
|
||||
const blendHTML = blends.length > 0 ? `<p><strong>Polyphthongs / Blends:</strong> ${blends.map(letter => `<span class="tag">${letter}</span>`).join(' ')}</p>` : '';
|
||||
const phonologyHTML = `<h3>Phonology</h3>
|
||||
<div class="split two">
|
||||
<div>${consonantHTML}</div>
|
||||
<div>${vowelHTML}</div>
|
||||
</div>
|
||||
${blendHTML}`;
|
||||
|
||||
const { onset, nucleus, coda, exceptions } = phonotactics;
|
||||
const onsetHTML = `<p><strong>Onset:</strong> ${onset.map(letter => `<span class="tag">${letter}</span>`).join(' ')}</p>`;
|
||||
const nucleusHTML = `<p><strong>Nucleus:</strong> ${nucleus.map(letter => `<span class="tag">${letter}</span>`).join(' ')}</p>`;
|
||||
const codaHTML = `<p><strong>Coda:</strong> ${coda.map(letter => `<span class="tag">${letter}</span>`).join(' ')}</p>`;
|
||||
const exceptionsHTML = exceptions.trim().length > 0 ? '<p><strong>Exceptions:</strong></p><div>' + md(removeTags(exceptions)) + '</div>' : '';
|
||||
const phonotacticsHTML = `<h3>Phonotactics</h3>
|
||||
<div class="split three">
|
||||
<div>${onsetHTML}</div>
|
||||
<div>${nucleusHTML}</div>
|
||||
<div>${codaHTML}</div>
|
||||
</div>
|
||||
${exceptionsHTML}`;
|
||||
|
||||
const orthographyHTML = '<h3>Orthography</h3><p><strong>Notes:</strong></p><div>' + md(removeTags(orthography.notes)) + '</div>';
|
||||
const grammarHTML = '<h3>Grammar</h3><p><strong>Notes:</strong></p><div>' + md(removeTags(grammar.notes)) + '</div>';
|
||||
|
||||
detailsPanel.innerHTML = generalHTML + phonologyHTML + phonotacticsHTML + orthographyHTML + grammarHTML;
|
||||
}
|
||||
|
||||
export function renderStats() {
|
||||
const wordStats = getWordsStats();
|
||||
const numberOfWordsHTML = `<p><strong>Number of Words</strong><br>${wordStats.numberOfWords.map(stat => `<span><span class="tag">${stat.name}</span><span class="tag">${stat.value}</span></span>`).join(' ')}</p>`;
|
||||
const wordLengthHTML = `<p><strong>Word Length</strong><br><span><span class="tag">Shortest</span><span class="tag">${wordStats.wordLength.shortest}</span></span>
|
||||
<span><span class="tag">Longest</span><span class="tag">${wordStats.wordLength.longest}</span></span>
|
||||
<span><span class="tag">Average</span><span class="tag">${wordStats.wordLength.average}</span></span></p>`;
|
||||
const letterDistributionHTML = `<p><strong>Letter Distribution</strong><br>${wordStats.letterDistribution.map(stat => `<span title="${stat.number} ${stat.letter}'s total"><span class="tag">${stat.letter}</span><span class="tag">${stat.percentage.toFixed(2)}</span></span>`).join(' ')}</p>`;
|
||||
const totalLettersHTML = `<p><strong>${wordStats.totalLetters} Total Letters</strong></p>`;
|
||||
|
||||
detailsPanel.innerHTML = numberOfWordsHTML + wordLengthHTML + letterDistributionHTML + totalLettersHTML;
|
||||
}
|
||||
|
||||
export function renderPartsOfSpeechSelect() {
|
||||
let optionsHTML = '<option value=""></option>';
|
||||
window.currentDictionary.partsOfSpeech.forEach(partOfSpeech => {
|
||||
partOfSpeech = removeTags(partOfSpeech);
|
||||
optionsHTML += `<option value="${partOfSpeech}">${partOfSpeech}</option>`;
|
||||
});
|
||||
Array.from(document.getElementsByClassName('part-of-speech-select')).forEach(select => select.innerHTML = optionsHTML);
|
||||
}
|
||||
|
||||
export function renderWords() {
|
||||
const words = getMatchingSearchWords();
|
||||
let wordsHTML = '';
|
||||
words.forEach(originalWord => {
|
||||
let detailsMarkdown = removeTags(originalWord.longDefinition);
|
||||
const references = detailsMarkdown.match(/\{\{.+?\}\}/g);
|
||||
if (references && Array.isArray(references)) {
|
||||
new Set(references).forEach(reference => {
|
||||
const wordToFind = reference.replace(/\{\{|\}\}/g, '');
|
||||
const existingWordId = wordExists(wordToFind, true);
|
||||
if (existingWordId !== false) {
|
||||
const wordMarkdownLink = `[${wordToFind}](#${existingWordId})`;
|
||||
detailsMarkdown = detailsMarkdown.replace(new RegExp(reference, 'g'), wordMarkdownLink);
|
||||
}
|
||||
});
|
||||
}
|
||||
const word = highlightSearchTerm({
|
||||
name: removeTags(originalWord.name),
|
||||
pronunciation: removeTags(originalWord.pronunciation),
|
||||
partOfSpeech: removeTags(originalWord.partOfSpeech),
|
||||
simpleDefinition: removeTags(originalWord.simpleDefinition),
|
||||
longDefinition: detailsMarkdown,
|
||||
wordId: originalWord.wordId,
|
||||
});
|
||||
wordsHTML += `<article class="entry" id="${word.wordId}">
|
||||
<header>
|
||||
<h4 class="word">${word.name}</h4>
|
||||
<span class="pronunciation">${word.pronunciation}</span>
|
||||
<span class="part-of-speech">${word.partOfSpeech}</span>
|
||||
</header>
|
||||
<dl>
|
||||
<dt class="definition">${word.simpleDefinition}</dt>
|
||||
<dd class="details">
|
||||
${md(word.longDefinition)}
|
||||
</dd>
|
||||
</dl>
|
||||
</article>`;
|
||||
});
|
||||
|
||||
document.getElementById('entries').innerHTML = wordsHTML;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
import { cloneObject } from "../helpers";
|
||||
|
||||
export function getSearchTerm() {
|
||||
return document.getElementById('searchBox').value;
|
||||
}
|
||||
|
||||
export function getMatchingSearchWords() {
|
||||
const searchTerm = getSearchTerm();
|
||||
const matchingWords = window.currentDictionary.words.slice().filter(word => {
|
||||
const isInName = new RegExp(searchTerm, 'g').test(word.name);
|
||||
const isInDefinition = new RegExp(searchTerm, 'g').test(word.simpleDefinition);
|
||||
const isInDetails = new RegExp(searchTerm, 'g').test(word.longDefinition);
|
||||
return isInName || isInDefinition || isInDetails;
|
||||
});
|
||||
return matchingWords;
|
||||
}
|
||||
|
||||
export function highlightSearchTerm(word) {
|
||||
const searchTerm = getSearchTerm();
|
||||
const markedUpWord = cloneObject(word);
|
||||
if (searchTerm) {
|
||||
markedUpWord.name = markedUpWord.name.replace(new RegExp(searchTerm, 'g'), `<mark>${searchTerm}</mark>`);
|
||||
markedUpWord.simpleDefinition = markedUpWord.simpleDefinition.replace(new RegExp(searchTerm, 'g'), `<mark>${searchTerm}</mark>`);
|
||||
markedUpWord.longDefinition = markedUpWord.longDefinition.replace(new RegExp(searchTerm, 'g'), `<mark>${searchTerm}</mark>`);
|
||||
}
|
||||
return markedUpWord;
|
||||
}
|
|
@ -1,11 +1,13 @@
|
|||
import {showSection} from './displayToggles';
|
||||
import { renderWords } from './render';
|
||||
|
||||
export default function setupListeners() {
|
||||
setupDetailsTabs();
|
||||
setupSearchBar();
|
||||
}
|
||||
|
||||
function setupDetailsTabs () {
|
||||
let tabs = document.querySelectorAll('#detailsSection nav li');
|
||||
function setupDetailsTabs() {
|
||||
const tabs = document.querySelectorAll('#detailsSection nav li');
|
||||
tabs.forEach(tab => {
|
||||
tab.addEventListener('click', () => {
|
||||
const section = tab.innerText.toLowerCase();
|
||||
|
@ -19,4 +21,24 @@ function setupDetailsTabs () {
|
|||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
function setupSearchBar() {
|
||||
const searchBox = document.getElementById('searchBox'),
|
||||
clearSearchButton = document.getElementById('clearSearchButton'),
|
||||
openSearchModal = document.getElementById('openSearchModal');
|
||||
searchBox.addEventListener('change', () => {
|
||||
renderWords();
|
||||
});
|
||||
searchBox.addEventListener('input', event => {
|
||||
openSearchModal.value = event.target.value;
|
||||
});
|
||||
clearSearchButton.addEventListener('click', event => {
|
||||
searchBox.value = '';
|
||||
openSearchModal.value = '';
|
||||
renderWords();
|
||||
});
|
||||
openSearchModal.addEventListener('click', () => {
|
||||
document.getElementById('searchModal').style.display = 'block';
|
||||
});
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
import { cloneObject } from '../helpers';
|
||||
|
||||
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 ? 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 wordExists(word, returnId = false) {
|
||||
const { currentDictionary } = window;
|
||||
const { caseSensitive } = currentDictionary.settings;
|
||||
const foundWord = currentDictionary.words.find(existingWord => {
|
||||
return caseSensitive ? existingWord.name === word : existingWord.name.toLowerCase() === word.toLowerCase();
|
||||
});
|
||||
return foundWord ? (returnId ? foundWord.wordId : true) : false;
|
||||
}
|
|
@ -4,6 +4,16 @@
|
|||
border-radius: 3px;
|
||||
background-color: $light;
|
||||
line-height: 30px;
|
||||
|
||||
&.small {
|
||||
font-size: 80%;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
&.red {
|
||||
background-color: $red;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
|
||||
span .tag {
|
||||
|
@ -24,8 +34,14 @@ span .tag {
|
|||
}
|
||||
|
||||
.modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
|
||||
.modal-background {
|
||||
position: fixed;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
|
@ -35,7 +51,7 @@ span .tag {
|
|||
}
|
||||
|
||||
.modal-content {
|
||||
position: fixed;
|
||||
position: absolute;
|
||||
top: 10%;
|
||||
left: 20%;
|
||||
bottom: 10%;
|
||||
|
@ -45,9 +61,10 @@ span .tag {
|
|||
border-radius: 5px;
|
||||
|
||||
.close-button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 10px;
|
||||
font-size: 200%;
|
||||
float: right;
|
||||
margin: 10px 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +112,20 @@ span .tag {
|
|||
width: 46%;
|
||||
}
|
||||
|
||||
&.three div {
|
||||
&.three div,
|
||||
div.third {
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
div.two-third {
|
||||
width: 66%;
|
||||
}
|
||||
|
||||
div.quarter {
|
||||
width: 22%;
|
||||
}
|
||||
|
||||
div.three-quarter {
|
||||
width: 72%;
|
||||
}
|
||||
}
|
|
@ -4,14 +4,48 @@
|
|||
margin: 3px 20px 3px 0;
|
||||
}
|
||||
|
||||
#searchButton {
|
||||
#openSearchModal {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#searchModal {
|
||||
min-height: $header-height;
|
||||
bottom: unset;
|
||||
z-index: 10;
|
||||
|
||||
.modal-content {
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: 0 auto;
|
||||
width: 90%;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
#searchBox {
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
.category {
|
||||
text-align: right;
|
||||
* {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.options {
|
||||
* {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#wordForm {
|
||||
position: fixed;
|
||||
top: $header-height;
|
||||
top: auto;
|
||||
width: 24%;
|
||||
padding: 10px;
|
||||
background-color: $light;
|
||||
|
|
|
@ -7,4 +7,6 @@ $mid: #dedede;
|
|||
$light: #efefef;
|
||||
$white: #ffffff;
|
||||
|
||||
$red: #d42932;
|
||||
|
||||
$border: 1px solid $dark;
|
Loading…
Reference in New Issue