Start working on details panel
This commit is contained in:
		
							parent
							
								
									c4b7fa4257
								
							
						
					
					
						commit
						5311aeea9d
					
				
					 8 changed files with 237 additions and 5 deletions
				
			
		| 
						 | 
				
			
			@ -39,10 +39,10 @@
 | 
			
		|||
        <h2>Dictionary Name</h2>
 | 
			
		||||
        <nav>
 | 
			
		||||
          <ul>
 | 
			
		||||
            <li id="toggleDescription">Description</li><li id="toggleDetails">Details</li><li id="toggleStats" class="active">Stats</li><li id="showEdit" onclick="document.getElementById('editModal').style.display='block'">Edit</li>
 | 
			
		||||
            <li>Description</li><li>Details</li><li>Stats</li><li onclick="document.getElementById('editModal').style.display='block'">Edit</li>
 | 
			
		||||
          </ul>
 | 
			
		||||
        </nav>
 | 
			
		||||
        <article id="detailsPanel">
 | 
			
		||||
        <article id="detailsPanel" style="display:none;">
 | 
			
		||||
          <p>The dictionary details</p>
 | 
			
		||||
        </article>
 | 
			
		||||
      </section>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,7 @@
 | 
			
		|||
    "sass": "^1.19.0"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "normalize.css": "^8.0.1"
 | 
			
		||||
    "normalize.css": "^8.0.1",
 | 
			
		||||
    "snarkdown": "^1.2.2"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										51
									
								
								src/constants.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/constants.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										131
									
								
								src/js/displayToggles.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								src/js/displayToggles.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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 = `<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>`;
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  detailsPanel.innerHTML = partsOfSpeechHTML + alphabeticalOrderHTML;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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>`;
 | 
			
		||||
 | 
			
		||||
  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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								src/js/setupListeners.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/js/setupListeners.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue