Compare commits
2 Commits
88c522ea1b
...
c5e3544570
Author | SHA1 | Date |
---|---|---|
Robbie Antenesse | c5e3544570 | |
Robbie Antenesse | a670abf24c |
82
index.html
82
index.html
|
@ -49,8 +49,8 @@
|
|||
|
||||
<main>
|
||||
<aside id="sideColumn">
|
||||
<form id="wordForm" onsubmit="function(e){e.preventDefault();return false;}">
|
||||
<label>Word<br>
|
||||
<form id="wordForm">
|
||||
<label>Word<span class="red">*</span><br>
|
||||
<input id="wordName">
|
||||
</label>
|
||||
<label>Pronunciation<a class="label-button">IPA Chart</a><br>
|
||||
|
@ -59,12 +59,14 @@
|
|||
<label>Part of Speech<br>
|
||||
<select id="wordPartOfSpeech" class="part-of-speech-select"></select>
|
||||
</label>
|
||||
<label>Definition<br>
|
||||
<label>Definition<span class="red">*</span><br>
|
||||
<input id="wordDefinition" placeholder="Equivalent words">
|
||||
</label>
|
||||
<label>Details<a class="label-button">Maximize</a><br>
|
||||
<label>Details<span class="red">*</span><a class="label-button">Maximize</a><br>
|
||||
<textarea id="wordDetails" placeholder="Markdown formatting allowed"></textarea>
|
||||
</label>
|
||||
<div id="wordErrorMessage"></div>
|
||||
<a class="button" id="addWordButton">Add Word</a>
|
||||
</form>
|
||||
</aside>
|
||||
|
||||
|
@ -73,7 +75,7 @@
|
|||
<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>
|
||||
<li>Description</li><li>Details</li><li>Stats</li><li id="editDictionaryButton">Edit</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<article id="detailsPanel" style="display:none;">
|
||||
|
@ -120,6 +122,76 @@
|
|||
<li class="active">Description</li><li>Details</li><li>Settings</li><li>Actions</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<section id="editDescriptionTab" style="display:none;">
|
||||
<label>Name<br>
|
||||
<input id="editName">
|
||||
</label>
|
||||
<label>Specification<br>
|
||||
<input id="editSpecification">
|
||||
</label>
|
||||
<label>Description<a class="label-button">Maximize</a><br>
|
||||
<textarea id="editDescription"></textarea>
|
||||
</label>
|
||||
</section>
|
||||
|
||||
<section id="editDetailsTab">
|
||||
<label>Parts of Speech <small>(Comma Separated List)</small><br>
|
||||
<input id="editPartsOfSpeech">
|
||||
</label>
|
||||
<label>Alphabetical Order <small>(Comma Separated List. Include every letter!)</small><br>
|
||||
<input id="editAlphabeticalOrder" disabled value="English Alphabet">
|
||||
</label>
|
||||
<h3>Phonology</h3>
|
||||
<div class="split three">
|
||||
<div>
|
||||
<label>Consonants<br>
|
||||
<input id="editConsonants">
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label>Vowels<br>
|
||||
<input id="editVowels">
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label>Polyphthongs / Blends<br>
|
||||
<input id="editBlends">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<h3>Phonotactics</h3>
|
||||
<div class="split three">
|
||||
<div>
|
||||
<label>Onset<br>
|
||||
<input id="editOnset">
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label>Nucleus<br>
|
||||
<input id="editNucleus">
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label>Coda<br>
|
||||
<input id="editCoda">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<h3>Orthography</h3>
|
||||
<label>Notes<a class="label-button">Maximize</a><br>
|
||||
<textarea id="editOrthography"></textarea>
|
||||
</label>
|
||||
<h3>Grammar</h3>
|
||||
<label>Notes<a class="label-button">Maximize</a><br>
|
||||
<textarea id="editGrammar"></textarea>
|
||||
</label>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<a class="button" id="editSave">Save</a>
|
||||
<a class="button" id="editSaveAndClose">Save & Close</a>
|
||||
<a class="red button" onclick="this.parentElement.parentElement.parentElement.style.display='none';">Close Without Saving</a>
|
||||
</footer>
|
||||
</div>
|
||||
</section>
|
||||
</body>
|
||||
|
|
|
@ -3,24 +3,26 @@ export function cloneObject(object) {
|
|||
}
|
||||
|
||||
export function removeTags(html) {
|
||||
var tagBody = '(?:[^"\'>]|"[^"]*"|\'[^\']*\')*';
|
||||
|
||||
var tagOrComment = new RegExp(
|
||||
'<(?:'
|
||||
// Comment body.
|
||||
+ '!--(?:(?:-*[^->])*--+|-?)'
|
||||
// Special "raw text" elements whose content should be elided.
|
||||
+ '|script\\b' + tagBody + '>[\\s\\S]*?</script\\s*'
|
||||
+ '|style\\b' + tagBody + '>[\\s\\S]*?</style\\s*'
|
||||
// Regular name
|
||||
+ '|/?[a-z]'
|
||||
+ tagBody
|
||||
+ ')>',
|
||||
'gi');
|
||||
var oldHtml;
|
||||
do {
|
||||
oldHtml = html;
|
||||
html = html.replace(tagOrComment, '');
|
||||
} while (html !== oldHtml);
|
||||
return html.replace(/</g, '<');
|
||||
if (html) {
|
||||
var tagBody = '(?:[^"\'>]|"[^"]*"|\'[^\']*\')*';
|
||||
var tagOrComment = new RegExp(
|
||||
'<(?:'
|
||||
// Comment body.
|
||||
+ '!--(?:(?:-*[^->])*--+|-?)'
|
||||
// Special "raw text" elements whose content should be elided.
|
||||
+ '|script\\b' + tagBody + '>[\\s\\S]*?</script\\s*'
|
||||
+ '|style\\b' + tagBody + '>[\\s\\S]*?</style\\s*'
|
||||
// Regular name
|
||||
+ '|/?[a-z]'
|
||||
+ tagBody
|
||||
+ ')>',
|
||||
'gi');
|
||||
var oldHtml;
|
||||
do {
|
||||
oldHtml = html;
|
||||
html = html.replace(tagOrComment, '');
|
||||
} while (html !== oldHtml);
|
||||
return html.replace(/</g, '<');
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import { renderDictionaryDetails } from "./render";
|
||||
|
||||
export function updateDictionary () {
|
||||
|
||||
renderDictionaryDetails();
|
||||
}
|
||||
|
||||
export function openEditModal() {
|
||||
document.getElementById('editModal').style.display = 'block';
|
||||
}
|
||||
|
||||
export function updateGeneralDetails() {
|
||||
|
||||
}
|
|
@ -1,9 +1,14 @@
|
|||
import {showSection} from './displayToggles';
|
||||
import { renderWords } from './render';
|
||||
import { validateWord, addWord } from './wordManagement';
|
||||
import { removeTags } from '../helpers';
|
||||
import { getNextId } from './utilities';
|
||||
import { openEditModal } from './dictionaryManagement';
|
||||
|
||||
export default function setupListeners() {
|
||||
setupDetailsTabs();
|
||||
setupSearchBar();
|
||||
setupWordForm();
|
||||
}
|
||||
|
||||
function setupDetailsTabs() {
|
||||
|
@ -11,16 +16,25 @@ function setupDetailsTabs() {
|
|||
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';
|
||||
if (section === 'edit') {
|
||||
openEditModal();
|
||||
} else {
|
||||
tab.classList.add('active');
|
||||
showSection(section);
|
||||
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);
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
});
|
||||
setupEditForm();
|
||||
}
|
||||
|
||||
function setupEditForm() {
|
||||
|
||||
}
|
||||
|
||||
function setupSearchBar() {
|
||||
|
@ -41,4 +55,34 @@ function setupSearchBar() {
|
|||
openSearchModal.addEventListener('click', () => {
|
||||
document.getElementById('searchModal').style.display = 'block';
|
||||
});
|
||||
}
|
||||
|
||||
function setupWordForm() {
|
||||
const wordForm = document.getElementById('wordForm'),
|
||||
addWordButton = document.getElementById('addWordButton');
|
||||
wordForm.addEventListener('submit', event => {
|
||||
// Allow semantic form and prevent it from getting submitted
|
||||
event.preventDefault();
|
||||
return false;
|
||||
});
|
||||
addWordButton.addEventListener('click', () => {
|
||||
const name = document.getElementById('wordName').value,
|
||||
pronunciation = document.getElementById('wordPronunciation').value,
|
||||
partOfSpeech = document.getElementById('wordPartOfSpeech').value,
|
||||
definition = document.getElementById('wordDefinition').value,
|
||||
details = document.getElementById('wordDetails').value;
|
||||
|
||||
const word = {
|
||||
name: removeTags(name).trim(),
|
||||
pronunciation: removeTags(pronunciation).trim(),
|
||||
partOfSpeech: removeTags(partOfSpeech).trim(),
|
||||
simpleDefinition: removeTags(definition).trim(),
|
||||
longDefinition: removeTags(details).trim(),
|
||||
wordId: getNextId(),
|
||||
};
|
||||
|
||||
if (validateWord(word)) {
|
||||
addWord(word);
|
||||
}
|
||||
});
|
||||
}
|
|
@ -1,5 +1,12 @@
|
|||
import { cloneObject } from '../helpers';
|
||||
|
||||
export function getNextId() {
|
||||
const lastId = window.currentDictionary.words.reduce((highestId, word) => {
|
||||
return (word.wordId && word.wordId) > highestId ? word.wordId : highestId;
|
||||
}, 0);
|
||||
return lastId + 1;
|
||||
}
|
||||
|
||||
export function getWordsStats() {
|
||||
const {words, partsOfSpeech} = window.currentDictionary;
|
||||
const {caseSensitive} = window.currentDictionary.settings;
|
||||
|
@ -69,7 +76,7 @@ export function getWordsStats() {
|
|||
});
|
||||
|
||||
wordStats.totalLetters = totalLetters;
|
||||
wordStats.wordLength.average = words.length > 0 ? totalLetters / words.length : 0;
|
||||
wordStats.wordLength.average = words.length > 0 ? Math.round(totalLetters / words.length) : 0;
|
||||
|
||||
for (const letter in numberOfLetters) {
|
||||
if (numberOfLetters.hasOwnProperty(letter)) {
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
import { renderWords } from "./render";
|
||||
import { wordExists } from "./utilities";
|
||||
|
||||
export function validateWord(word, wordId = false) {
|
||||
const errorElementId = wordId === false ? 'wordErrorMessage' : 'wordErrorMessage_' + wordId,
|
||||
errorElement = document.getElementById(errorElementId);
|
||||
let errorMessage = '';
|
||||
|
||||
if (word.name === '') {
|
||||
errorMessage += '<p class="bold red">Word field must not be blank.</p>';
|
||||
}
|
||||
if (word.simpleDefinition === '' && word.longDefinition === '') {
|
||||
errorMessage += '<p class="bold red">You must enter Definition or Details.</p>';
|
||||
}
|
||||
|
||||
const { allowDuplicates, caseSensitive } = window.currentDictionary.settings;
|
||||
if (!allowDuplicates) {
|
||||
const foundDuplicate = wordExists(word.name, true);
|
||||
if (foundDuplicate !== false) {
|
||||
errorMessage += `<p class="bold red">"<a href="#${foundDuplicate}">${word.name}</a>" already exists, and "Allow Duplicates" is turned off.${!caseSensitive ? ' <em>(Case sensitivity is turned also off)</em>' : ''}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
errorElement.innerHTML = errorMessage;
|
||||
return errorMessage === '';
|
||||
}
|
||||
|
||||
export function addWord(word) {
|
||||
const { sortByDefinition } = window.currentDictionary.settings;
|
||||
const sortBy = sortByDefinition ? 'simpleDefinition' : 'name';
|
||||
|
||||
window.currentDictionary.words.push(word);
|
||||
window.currentDictionary.words.sort((wordA, wordB) => {
|
||||
if (wordA[sortBy] === wordB[sortBy]) return 0;
|
||||
return wordA[sortBy] > wordB[sortBy] ? 1 : -1;
|
||||
});
|
||||
|
||||
renderWords();
|
||||
}
|
|
@ -1,3 +1,38 @@
|
|||
p, span {
|
||||
&.red {
|
||||
color: $red;
|
||||
}
|
||||
|
||||
&.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
small {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
input:not([type="checkbox"]):not([type="radio"]),
|
||||
select, textarea {
|
||||
font-weight: normal;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.label-button {
|
||||
font-size: 80%;
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.tag {
|
||||
padding: 3px 9px;
|
||||
border: $border;
|
||||
|
@ -67,6 +102,25 @@ span .tag {
|
|||
font-size: 200%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
section {
|
||||
padding: 20px;
|
||||
margin-bottom: 80px;
|
||||
overflow-y: auto;
|
||||
height: 78%;
|
||||
}
|
||||
|
||||
section~footer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: $white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,24 @@
|
|||
margin: 0 auto;
|
||||
width: 90%;
|
||||
padding: 20px;
|
||||
|
||||
label {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
section {
|
||||
padding: 0;
|
||||
overflow-y: unset;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
section+footer {
|
||||
position: relative;
|
||||
left: unset;
|
||||
bottom: unset;
|
||||
right: unset;
|
||||
background-color: $white;
|
||||
}
|
||||
}
|
||||
|
||||
#searchBox {
|
||||
|
@ -36,7 +54,7 @@
|
|||
}
|
||||
|
||||
.options {
|
||||
* {
|
||||
label {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
@ -51,26 +69,8 @@
|
|||
background-color: $light;
|
||||
border: $border;
|
||||
border-radius: 5px;
|
||||
|
||||
label {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
input, select, textarea {
|
||||
font-weight: normal;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.label-button {
|
||||
font-size: 80%;
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
max-height: 80%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#detailsSection {
|
||||
|
@ -130,3 +130,10 @@
|
|||
font-size: 70%;
|
||||
}
|
||||
}
|
||||
|
||||
#editModal {
|
||||
#editDescription {
|
||||
width: 100%;
|
||||
height: 350px;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue