diff --git a/index.html b/index.html index 9ca5820..2f8b4fe 100644 --- a/index.html +++ b/index.html @@ -39,10 +39,10 @@

Dictionary Name

-
+ diff --git a/package.json b/package.json index fbaced2..a1e790f 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "sass": "^1.19.0" }, "dependencies": { - "normalize.css": "^8.0.1" + "normalize.css": "^8.0.1", + "snarkdown": "^1.2.2" } } diff --git a/src/constants.js b/src/constants.js new file mode 100644 index 0000000..f352e20 --- /dev/null +++ b/src/constants.js @@ -0,0 +1,51 @@ +export const DEFAULT_DICTIONARY = { + name: 'New', + specification: 'Dictionary', + description: 'A new dictionary.', + partsOfSpeech: ['Noun', 'Adjective', 'Verb'], + alphabeticalOrder: [], + details: { + phonology: { + consonants: [], + vowels: [], + blends: [], + phonotactics: { + onset: [], + nucleus: [], + coda: [], + exceptions: '', + }, + }, + orthography: { + notes: '', + }, + grammar: { + notes: '', + }, + // custom: [ + // // { + // // name: 'Example Tab', + // // content: `This is an _example_ tab to show how **tabs** work with [Markdown](${ MARKDOWN_LINK })!`, + // // } + // ], + }, + words: [ + /* { + name: '', + pronunciation: '', + partOfSpeech: '', + simpleDefinition: '', + longDefinition: '', + wordId: 0 + }, */ + ], + settings: { + allowDuplicates: false, + caseSensitive: false, + sortByDefinition: false, + isComplete: false, + isPublic: false, + }, + lastUpdated: null, + createdOn: 0, +}; \ No newline at end of file diff --git a/src/index.js b/src/index.js index c14d3f3..ada9b3c 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,12 @@ import './main.scss'; +import { DEFAULT_DICTIONARY } from './constants'; +import setupListeners from './js/setupListeners'; + function initialize() { console.log('initializing'); + window.currentDictionary = JSON.parse(JSON.stringify(DEFAULT_DICTIONARY)); + setupListeners(); } window.onload = (function (oldLoad) { diff --git a/src/js/displayToggles.js b/src/js/displayToggles.js new file mode 100644 index 0000000..4e1f82d --- /dev/null +++ b/src/js/displayToggles.js @@ -0,0 +1,131 @@ +import md from 'snarkdown'; + +export function showSection(sectionName) { + switch (sectionName) { + case 'description': showDescription(); break; + case 'details': showDetails(); break; + case 'stats': showStats(); break; + } +} + +function showDescription() { + const detailsPanel = document.getElementById('detailsPanel'); + detailsPanel.style.display = 'block'; + const {description} = window.currentDictionary; + const descriptionHTML = md(description); + + detailsPanel.innerHTML = descriptionHTML; +} + +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 = `

Parts of Speech: ${partsOfSpeech.map(partOfSpeech => '' + partOfSpeech + '').join(' ')}

`; + const alphabeticalOrderHTML = `

Alphabetical Order: ${ + (alphabeticalOrder.length > 0 ? alphabeticalOrder : ['English Alphabet']).map(letter => `${letter}`).join(' ') + }

`; + + + detailsPanel.innerHTML = partsOfSpeechHTML + alphabeticalOrderHTML; +} + +function showStats() { + const detailsPanel = document.getElementById('detailsPanel'); + detailsPanel.style.display = 'block'; + const wordStats = getWordsStats(); + const numberOfWordsHTML = `

Number of Words
${wordStats.numberOfWords.map(stat => `${stat.name}${stat.value}`).join(' ')}

`; + + detailsPanel.innerHTML = numberOfWordsHTML; +} + +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 = totalLetters / words.length; + + 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; +} \ No newline at end of file diff --git a/src/js/setupListeners.js b/src/js/setupListeners.js new file mode 100644 index 0000000..ab25c97 --- /dev/null +++ b/src/js/setupListeners.js @@ -0,0 +1,22 @@ +import {showSection} from './displayToggles'; + +export default function setupListeners() { + setupDetailsTabs(); +} + +function setupDetailsTabs () { + let tabs = document.querySelectorAll('#detailsSection nav li'); + tabs.forEach(tab => { + tab.addEventListener('click', () => { + const section = tab.innerText.toLowerCase(); + const isActive = tab.classList.contains('active'); + tabs.forEach(t => t.classList.remove('active')); + if (isActive) { + document.getElementById('detailsPanel').style.display = 'none'; + } else { + tab.classList.add('active'); + showSection(section); + } + }); + }) +} \ No newline at end of file diff --git a/src/styles/_elements.scss b/src/styles/_elements.scss index 4135df4..a99ae4b 100644 --- a/src/styles/_elements.scss +++ b/src/styles/_elements.scss @@ -1,9 +1,26 @@ -.button { - cursor: pointer; +.tag { padding: 3px 9px; border: $border; border-radius: 3px; background-color: $light; + line-height: 30px; +} + +span .tag { + @extend .tag; + + border-radius: 3px 0 0 3px; + + &+.tag { + border-left: none; + border-radius: 0 3px 3px 0; + background-color: $white; + } +} + +.button { + @extend .tag; + cursor: pointer; } .modal { diff --git a/yarn.lock b/yarn.lock index 15da220..961a775 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4542,6 +4542,11 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" +snarkdown@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/snarkdown/-/snarkdown-1.2.2.tgz#0cfe2f3012b804de120fc0c9f7791e869c59cc74" + integrity sha1-DP4vMBK4BN4SD8DJ93kehpxZzHQ= + source-map-resolve@^0.5.0: version "0.5.2" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259"