Started on the path to node compatibility, but it's not usable yet.

Need to figure out how to require() defiant.js...
This commit is contained in:
Robbie Antenesse 2016-09-20 15:59:59 -06:00
parent d6e9741736
commit d914d8f133
13 changed files with 2984 additions and 0 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
php/google/
ipa_character_picker/
node_modules/

24
package.json Normal file
View File

@ -0,0 +1,24 @@
{
"name": "lexiconga",
"title": "Lexiconga",
"version": "1.0.0",
"description": "A tool to build simple dictionaries using JSON.",
"main": "src/app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://Alamantus@github.com/Alamantus/Lexiconga.git"
},
"author": "Robbie Antenesse <gamedev@alamantus.com>",
"license": "ISC",
"bugs": {
"url": "https://github.com/Alamantus/Lexiconga/issues"
},
"homepage": "https://github.com/Alamantus/Lexiconga#readme",
"dependencies": {
"marked": "^0.3.6",
"papaparse": "^4.1.2"
}
}

36
src/components/login.js Normal file
View File

@ -0,0 +1,36 @@
<div class="settingsCol"><form id="loginForm" method="post" action="?login">
<h2>Log In</h2>
<label><span>Email</span>
<input type="email" id="loginEmailField" name="email" />
</label>
<label><span>Password</span>
<input type="password" id="loginPasswordField" name="password" />
</label>
<div id="loginError" style="font-weight:bold;color:red;"></div>
<button type="submit" id="loginSubmitButton" onclick="ValidateLogin(); return false;">Log In</button>
<div id="dictionaryWarn" style="margin-bottom: 5px;"></div>
<span id="forgotPassword" class="clickable" onclick="ShowInfo('forgotForm')" style="margin-top:20px;">Forgot Password?</span>
</form></div>
<div class="settingsCol"><form id="createAccountForm" method="post" action="?createaccount">
<h2>Create a New Account</h2>
<p style="font-size: 12px;">Creating an account allows you to save and switch between as many dictionaries as you need and access them from any device for free! If you have a dictionary you've been working on loaded already, it will automatically be uploaded to your account when you log in for the first time.</p>
<p style="font-size: 12px;">Plus if you allow us to send you emails, we'll make sure that you're the first to hear about any new features that get added or if any of our policies change for any reason. We'll never spam you or sell your information.</p>
<p style="font-size: 12px;">By creating an account, you are indicating that you agree to the <span class="clickable inline-button" onclick="ShowInfo('termsText')">Terms of Service</span> and that you understand Lexiconga's <span class="clickable inline-button" onclick="ShowInfo('privacyText')">Privacy Policy</span>.</p>
<label><span>Email</span>
<input type="email" id="createAccountEmailField" name="email" />
</label>
<label><span>Password</span>
<input type="password" id="createAccountPasswordField" name="password" />
</label>
<label><span>Confirm Password</span>
<input type="password" id="createAccountPasswordConfirmField" name="confirmpassword" />
</label>
<label><span>Public Name <span class="clickable inline-button" onclick="ExplainPublicName()">?</span></span>
<input type="text" id="createAccountPublicNameField" name="publicname" />
</label>
<label style="display:inline;"><b>Allow Emails</b>
<input type="checkbox" id="createAccountAllowEmailsField" name="allowemails" checked="checked" />
</label> <span class="clickable inline-button" onclick="ExplainAllowEmails()">?</span>
<div id="createAccountError" style="font-weight:bold;color:red;"></div>
<button type="submit" id="createAccountSubmitButton" onclick="ValidateCreateAccount(); return false;">Create Account</button>
</form></div>

19
src/index.html Normal file
View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Lexiconga Dictionary Builder</title>
<meta property="og:url" content="http://lexicon.ga" />
<meta property="og:type" content="website" />
<meta property="og:title" content="Lexiconga Dictionary Builder" />
<meta property="og:description" content="Build lexicons for contructed languages or anything that you can think of!" />
<meta property="og:image" content="http://lexicon.ga/images/logo.svg" />
<link href="/css/styles.css" rel="stylesheet" />
</head>
<body>
<site></site>
<script src="dictionaryBuilder.js"></script>
</body>
</html>

877
src/js/app.js Normal file
View File

@ -0,0 +1,877 @@
var publicName = "Someone";
var currentDictionary = {
name: "New",
description: "A new dictionary.",
createdBy: publicName,
words: [],
nextWordId: 1,
settings: {
allowDuplicates: false,
caseSensitive: false,
partsOfSpeech: "Noun,Adjective,Verb,Adverb,Preposition,Pronoun,Conjunction",
sortByEquivalent: false,
isComplete: false,
isPublic: false
},
externalID: 0
}
var defaultDictionaryJSON = JSON.stringify(currentDictionary); //Saves a stringifyed default dictionary.
var previousDictionary = {};
var savedScroll = {
x: 0,
y: 0
}
function AddWord() {
var word = htmlEntities(document.getElementById("word").value).trim();
var pronunciation = htmlEntities(document.getElementById("pronunciation").value).trim();
var partOfSpeech = htmlEntities(document.getElementById("partOfSpeech").value).trim();
var simpleDefinition = htmlEntities(document.getElementById("simpleDefinition").value).trim();
var longDefinition = htmlEntities(document.getElementById("longDefinition").value);
// var editIndex = htmlEntities(document.getElementById("editIndex").value);
var errorMessageArea = document.getElementById("errorMessage");
var errorMessage = "";
var updateConflictArea = document.getElementById("updateConflict");
if (word != "" && (simpleDefinition != "" || longDefinition != "")) {
var wordIndex = (!currentDictionary.settings.allowDuplicates) ? WordIndex(word) : -1;
if (wordIndex >= 0) {
if (WordAtIndexWasChanged(wordIndex, word, pronunciation, partOfSpeech, simpleDefinition, longDefinition)) {
document.getElementById("newWordButtonArea").style.display = "none";
DisableForm('');
updateConflictArea.style.display = "block";
var updateConflictText = "<span id='updateConflictMessage'>\"" + word + "\" is already in the dictionary";
if (currentDictionary.words[wordIndex].name != word) {
updateConflictText += " as \"" + currentDictionary.words[wordIndex].name + "\", and your dictionary is set to ignore case.";
} else {
updateConflictText += "."
}
updateConflictText += "<br>Do you want to update it to what you have set above?</span>";
updateConflictText += '<button type="button" id="updateConfirmButton" \
onclick="UpdateWord(' + wordIndex + ', \'' + htmlEntities(word) + '\', \'' + htmlEntities(pronunciation) + '\', \'' + htmlEntities(partOfSpeech) + '\', \'' + htmlEntities(simpleDefinition) + '\', \'' + htmlEntities(longDefinition) + '\'); \
return false;">Yes, Update it</button>';
updateConflictText += ' <button type="button" id="updateCancelButton" onclick="CloseUpdateConflictArea(\'\'); return false;">No, Leave it</button>';
updateConflictArea.innerHTML = updateConflictText;
} else {
errorMessage = "\"" + word + "\" is already in the dictionary exactly as it is written above";
if (currentDictionary.words[wordIndex].name != word) {
errorMessage += ". (Your dictionary is currently set to ignore case.)"
}
}
} else {
currentDictionary.words.push({name: word, pronunciation: pronunciation, partOfSpeech: ((partOfSpeech.length > 0) ? partOfSpeech : " "), simpleDefinition: simpleDefinition, longDefinition: longDefinition, wordId: currentDictionary.nextWordId++});
SaveAndUpdateWords("new");
FocusAfterAddingNewWord();
NewWordNotification(word);
}
errorMessageArea.innerHTML = "";
} else {
if (word == "") {
errorMessage += "Word cannot be blank";
if (simpleDefinition == "" && longDefinition == "") {
errorMessage += " and you need at least one definition.";
} else {
errorMessage += ".";
}
} else if (simpleDefinition == "" && longDefinition == "") {
errorMessage += "You need at least one definition."
}
}
errorMessageArea.innerHTML = errorMessage;
}
function ShowWordEditForm(index) {
var indexString = index.toString(); // Variable for reduced processing
var word = currentDictionary.words[index]; // Reference for easier reading
var editForm = '<form id="editForm' + indexString + '">\
<h2>Editing ' + word.name + '</h2>\
<label><span>Word</span>\
<input type="text" id="word' + indexString + '" value="' + htmlEntitiesParse(word.name) + '" onkeydown="SubmitWordOnCtrlEnter(this)" />\
</label>\
<label><span>Pronunciation <a class="clickable inline-button" href="http://r12a.github.io/pickers/ipa/" target="_blank" title="IPA Character Picker located at http://r12a.github.io/pickers/ipa/">IPA Characters</a></span>\
<input type="text" id="pronunciation' + indexString + '" value="' + htmlEntitiesParse(word.pronunciation) + '" onkeydown="SubmitWordOnCtrlEnter(this)" />\
</label>\
<label><span>Part of Speech</span>\
<select id="partOfSpeech' + indexString + '" onkeydown="SubmitWordOnCtrlEnter(this)"></select>\
</label>\
<label><span>Definition/Equivalent Word(s)</span>\
<input type="text" id="simpleDefinition' + indexString + '" value="' + htmlEntitiesParse(word.simpleDefinition) + '" onkeydown="SubmitWordOnCtrlEnter(this)" />\
</label>\
<label><span>Explanation/Long Definition <span id="showFullScreenTextbox" class="clickable inline-button" onclick="ShowFullScreenTextbox(\'longDefinition' + indexString + '\', \'Explanation/Long Definition\')">Maximize</span></span>\
<textarea id="longDefinition' + indexString + '" class="longDefinition" onkeydown="SubmitWordOnCtrlEnter(this)">' + htmlEntitiesParse(word.longDefinition) + '</textarea>\
</label>\
<span id="errorMessage' + indexString + '"></span>\
<div id="editWordButtonArea' + indexString + '" style="display: block;">\
<button type="button" onclick="EditWord(\'' + indexString + '\'); return false;">Edit Word</button> <button type="button" onclick="CancelEditForm(' + indexString + '); return false;">Cancel</button>\
</div>\
<div id="updateConflict' + indexString + '" style="display: none;"></div>\
</form>';
document.getElementById("entry" + indexString).innerHTML = editForm;
SetPartsOfSpeech("partOfSpeech" + indexString);
document.getElementById("partOfSpeech" + indexString).value = htmlEntitiesParse(word.partOfSpeech);
document.getElementById("word" + indexString).focus();
}
function CancelEditForm(index) {
document.getElementById("entry" + index.toString()).innerHTML = DictionaryEntry(index).replace("<entry id='entry" + index.toString() + "'>", "").replace("</entry>", "");
}
function EditWord(indexString) {
var word = htmlEntities(document.getElementById("word" + indexString).value).trim();
var pronunciation = htmlEntities(document.getElementById("pronunciation" + indexString).value).trim();
var partOfSpeech = htmlEntities(document.getElementById("partOfSpeech" + indexString).value).trim();
var simpleDefinition = htmlEntities(document.getElementById("simpleDefinition" + indexString).value).trim();
var longDefinition = htmlEntities(document.getElementById("longDefinition" + indexString).value);
var errorMessageArea = document.getElementById("errorMessage" + indexString);
var errorMessage = "";
var updateConflictArea = document.getElementById("updateConflict" + indexString);
if (WordAtIndexWasChanged(indexString, word, pronunciation, partOfSpeech, simpleDefinition, longDefinition)) {
document.getElementById("editWordButtonArea" + indexString).style.display = "none";
DisableForm(indexString);
updateConflictArea.style.display = "block";
updateConflictArea.innerHTML = "<span id='updateConflictMessage" + indexString + "'>Do you really want to change the word \"" + currentDictionary.words[parseInt(indexString)].name + "\" to what you have set above?</span><br>";
updateConflictArea.innerHTML += '<button type="button" id="updateConfirmButton' + indexString + '" \
onclick="UpdateWord(' + indexString + ', \'' + htmlEntities(word) + '\', \'' + htmlEntities(pronunciation) + '\', \'' + htmlEntities(partOfSpeech) + '\', \'' + htmlEntities(simpleDefinition) + '\', \'' + htmlEntities(longDefinition) + '\'); \
return false;">Yes, Update it</button>';
updateConflictArea.innerHTML += '<button type="button" id="updateCancelButton' + indexString + '" onclick="CloseUpdateConflictArea(\'' + indexString + '\'); return false;">No, Leave it</button>';
} else {
errorMessage = "No change has been made to \"" + word + "\"";
if (currentDictionary.words[parseInt(indexString)].name != word) {
errorMessage += ". (Your dictionary is currently set to ignore case.)";
}
}
errorMessageArea.innerHTML = errorMessage;
if (document.getElementById("updateConfirmButton" + indexString)) {
document.getElementById("updateConfirmButton" + indexString).focus();
}
}
function UpdateWord(wordIndex, word, pronunciation, partOfSpeech, simpleDefinition, longDefinition) {
SaveScroll();
currentDictionary.words[wordIndex].name = word;
currentDictionary.words[wordIndex].pronunciation = pronunciation;
currentDictionary.words[wordIndex].partOfSpeech = ((partOfSpeech.length > 0) ? partOfSpeech : " ");
currentDictionary.words[wordIndex].simpleDefinition = simpleDefinition;
currentDictionary.words[wordIndex].longDefinition = longDefinition;
SaveAndUpdateWords("update", wordIndex);
window.scroll(savedScroll.x, savedScroll.y);
if (!wordFormIsLocked()) {
FocusAfterAddingNewWord();
}
}
function DeleteWord(index) {
var deleteWord = new XMLHttpRequest();
deleteWord.open('POST', "/php/ajax_dictionarymanagement.php?action=worddelete");
deleteWord.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
deleteWord.onreadystatechange = function() {
if (deleteWord.readyState == 4 && deleteWord.status == 200) {
if (deleteWord.responseText == "deleted successfully" || deleteWord.responseText == "not signed in") {
currentDictionary.words.splice(index, 1);
SaveWords(false);
}
console.log(deleteWord.responseText);
return true;
} else {
return false;
}
}
deleteWord.send("dict=" + currentDictionary.externalID.toString() + "&word=" + currentDictionary.words[index].wordId.toString());
}
function ShowDictionary() {
var filters = GetSelectedFilters();
var searchResults = [];
var search = htmlEntitiesParseForSearchEntry(document.getElementById("searchBox").value);
var searchByWord = document.getElementById("searchOptionWord").checked;
var searchBySimple = document.getElementById("searchOptionSimple").checked;
var searchByLong = document.getElementById("searchOptionLong").checked;
var searchIgnoreCase = !document.getElementById("searchCaseSensitive").checked; //It's easier to negate case here instead of negating it every use since ignore case is default.
var searchIgnoreDiacritics = document.getElementById("searchIgnoreDiacritics").checked;
if (search != "" && (searchByWord || searchBySimple || searchByLong)) {
var xpath = [];
var searchDictionaryJSON = htmlEntitiesParseForSearch(JSON.stringify(currentDictionary));
if (searchIgnoreCase) {
search = search.toLowerCase();
}
if (searchIgnoreDiacritics) {
search = removeDiacritics(search);
searchDictionaryJSON = removeDiacritics(searchDictionaryJSON);
}
if (searchByWord) {
xpath.push('contains('+ ((searchIgnoreCase) ? 'name' : 'translate(name, "", "")') +', "'+ search +'")');
}
if (searchBySimple) {
xpath.push('contains('+ ((searchIgnoreCase) ? 'simpleDefinition' : 'translate(simpleDefinition, "", "")') +', "'+ search +'")');
}
if (searchByLong) {
xpath.push('contains('+ ((searchIgnoreCase) ? 'longDefinition' : 'translate(longDefinition, "", "")') +', "'+ search +'")');
}
var searchDictionary = JSON.parse(searchDictionaryJSON);
searchResults = JSON.search(searchDictionary, '//words['+ xpath.join(' or ') +']/wordId');
}
var dictionaryNameArea = document.getElementById("dictionaryName");
dictionaryNameArea.innerHTML = currentDictionary.name + " Dictionary";
if (loggedIn && currentDictionary.settings.isPublic) {
dictionaryNameArea.innerHTML += "<a href='/" + currentDictionary.externalID + "' target='_blank' id='dictionaryShareLink' class='clickable' title='Share Dictionary'>&#10150;</a>";
}
var dictionaryDescriptionArea = document.getElementById("dictionaryDescription");
dictionaryDescriptionArea.innerHTML = marked(htmlEntitiesParseForMarkdown(currentDictionary.description));
var dictionaryArea = document.getElementById("theDictionary");
var dictionaryText = "";
var numberOfWordsDisplayed = 0;
if (currentDictionary.words.length > 0) {
for (var i = 0; i < currentDictionary.words.length; i++) {
if (filters.length == 0 || (filters.length > 0 && filters.indexOf(currentDictionary.words[i].partOfSpeech) > -1)) {
if (search == "" || (search != "" && (searchByWord || searchBySimple || searchByLong) && searchResults.indexOf(currentDictionary.words[i].wordId) >= 0)) {
if (!currentDictionary.words[i].hasOwnProperty("pronunciation")) {
currentDictionary.words[i].pronunciation = ""; //Account for new property
}
if (!currentDictionary.words[i].hasOwnProperty("wordId")) {
currentDictionary.words[i].wordId = i + 1; //Account for new property
}
dictionaryText += DictionaryEntry(i);
numberOfWordsDisplayed++;
}
}
}
} else {
dictionaryText = "There are no entries in the dictionary.";
}
dictionaryArea.innerHTML = dictionaryText;
ShowFilterWordCount(numberOfWordsDisplayed);
}
function DictionaryEntry(itemIndex) {
var searchTerm = regexParseForSearch(document.getElementById("searchBox").value);
var searchByWord = document.getElementById("searchOptionWord").checked;
var searchBySimple = document.getElementById("searchOptionSimple").checked;
var searchByLong = document.getElementById("searchOptionLong").checked;
var searchIgnoreCase = !document.getElementById("searchCaseSensitive").checked; //It's easier to negate case here instead of negating it every use since ignore case is default.
var searchIgnoreDiacritics = document.getElementById("searchIgnoreDiacritics").checked;
var searchRegEx = new RegExp("(" + ((searchIgnoreDiacritics) ? removeDiacritics(searchTerm) + "|" + searchTerm : searchTerm) + ")", "g" + ((searchIgnoreCase) ? "i" : ""));
var wordName = wordPronunciation = wordPartOfSpeech = wordSimpleDefinition = wordLongDefinition = "";
if (searchTerm != "" && searchByWord) {
// Parse HTML Entities while searching so the regex can search actual characters instead of HTML.
wordName += htmlEntities(htmlEntitiesParse(currentDictionary.words[itemIndex].name).replace(searchRegEx, "<searchterm>$1</searchterm>")).replace(/&lt;(\/?)searchterm&gt;/g, '<$1searchterm>');
} else {
// Don't need to parse if not searching because HTML displays correctly anyway!
wordName += currentDictionary.words[itemIndex].name.toString(); // Use toString() to prevent using a reference instead of the value.
}
if (currentDictionary.words[itemIndex].pronunciation != "") {
wordPronunciation += marked(htmlEntitiesParseForMarkdown(currentDictionary.words[itemIndex].pronunciation)).replace(/<\/?p>/g,"");
}
if (currentDictionary.words[itemIndex].partOfSpeech != " " && currentDictionary.words[itemIndex].partOfSpeech != "") {
wordPartOfSpeech += currentDictionary.words[itemIndex].partOfSpeech.toString();
}
if (currentDictionary.words[itemIndex].simpleDefinition != "") {
if (searchTerm != "" && searchBySimple) {
wordSimpleDefinition += htmlEntities(htmlEntitiesParse(currentDictionary.words[itemIndex].simpleDefinition).replace(searchRegEx, "<searchterm>$1</searchterm>")).replace(/&lt;(\/?)searchterm&gt;/g, '<$1searchterm>');
} else {
wordSimpleDefinition += currentDictionary.words[itemIndex].simpleDefinition.toString();
}
}
if (currentDictionary.words[itemIndex].longDefinition != "") {
if (searchTerm != "" && searchByLong) {
wordLongDefinition += marked(htmlEntitiesParseForMarkdown(htmlEntities(htmlEntitiesParse(currentDictionary.words[itemIndex].longDefinition).replace(searchRegEx, "<searchterm>$1</searchterm>")))).replace(/&lt;(\/?)searchterm&gt\;/g, '<$1searchterm>');
} else {
wordLongDefinition += marked(htmlEntitiesParseForMarkdown(currentDictionary.words[itemIndex].longDefinition));
}
}
return DictionaryEntryTemplate({
name : wordName,
pronunciation : wordPronunciation,
partOfSpeech : wordPartOfSpeech,
simpleDefinition : wordSimpleDefinition,
longDefinition : wordLongDefinition,
wordId : currentDictionary.words[itemIndex].wordId.toString()
}, (!currentDictionary.settings.isComplete) ? itemIndex : false);
}
function ManagementArea(itemIndex) {
var managementHTML = "<div class='management'>";
managementHTML += "<span class='clickable editButton' onclick='ShowWordEditForm(" + itemIndex + ")'>Edit</span>";
managementHTML += "<span class='clickable deleteButton' onclick='document.getElementById(\"delete" + itemIndex + "Confirm\").style.display = \"block\";'>Delete</span>";
managementHTML += "<div class='deleteConfirm' id='delete" + itemIndex + "Confirm' style='display:none;'>Are you sure you want to delete this entry?<br><br>";
managementHTML += "<span class='clickable deleteCancelButton' onclick='document.getElementById(\"delete" + itemIndex + "Confirm\").style.display = \"none\";'>No</span>";
managementHTML += "<span class='clickable deleteConfirmButton' onclick='DeleteWord(" + itemIndex + ")'>Yes</span>";
managementHTML += "</div>";
managementHTML += "</div>";
return managementHTML;
}
function DictionaryEntryTemplate(wordObject, managementIndex) {
managementIndex = (typeof managementIndex !== 'undefined') ? managementIndex : false;
var entryText = "<entry id='entry";
if (managementIndex !== false) {
// If there's a managementIndex, append index number to the element id.
entryText += managementIndex.toString();
}
entryText += "'><a name='" + wordObject.wordId + "'></a>";
if (loggedIn && currentDictionary.settings.isPublic) {
entryText += "<a href='/" + currentDictionary.externalID + "/" + wordObject.wordId + "' target='_blank' class='wordLink clickable' title='Share Word' style='margin-left:5px;'>&#10150;</a>";
}
entryText += "<a href='#" + wordObject.wordId + "' class='wordLink clickable' title='Link Within Page'>&#x1f517;</a>";
entryText += "<word>" + wordObject.name + "</word>";
if (wordObject.pronunciation != "") {
entryText += "<pronunciation>" + wordObject.pronunciation + "</pronunciation>";
}
if (wordObject.partOfSpeech != "") {
entryText += "<partofspeech>" + wordObject.partOfSpeech + "</partofspeech>";
}
entryText += "<br>";
if (wordObject.simpleDefinition != "") {
entryText += "<simpledefinition>" + wordObject.simpleDefinition + "</simpledefinition>";
}
if (wordObject.longDefinition != "") {
entryText += "<longdefinition>" + wordObject.longDefinition + "</longdefinition>";
}
if (managementIndex !== false) {
entryText += ManagementArea(managementIndex);
}
entryText += "</entry>";
return entryText;
}
function SaveSettings() {
if (htmlEntities(document.getElementById("dictionaryNameEdit").value) != "") {
currentDictionary.name = htmlEntities(document.getElementById("dictionaryNameEdit").value);
}
currentDictionary.description = htmlEntities(document.getElementById("dictionaryDescriptionEdit").value);
CheckForPartsOfSpeechChange();
currentDictionary.settings.allowDuplicates = document.getElementById("dictionaryAllowDuplicates").checked;
currentDictionary.settings.caseSensitive = document.getElementById("dictionaryCaseSensitive").checked;
currentDictionary.settings.sortByEquivalent = document.getElementById("dictionarySortByEquivalent").checked;
currentDictionary.settings.isComplete = document.getElementById("dictionaryIsComplete").checked;
if (document.getElementById("dictionaryIsPublic")) {
currentDictionary.settings.isPublic = document.getElementById("dictionaryIsPublic").checked;
}
HideSettingsWhenComplete();
SaveAndUpdateDictionary(true);
LoadUserDictionaries();
}
function EmptyWholeDictionary() {
if (confirm("This will delete the entire current dictionary. If you do not have a backed up export, you will lose it forever!\n\nDo you still want to delete?")) {
CreateNewDictionary();
}
}
function CreateNewDictionary() {
ResetDictionaryToDefault();
SaveAndUpdateDictionary(false);
SetPartsOfSpeech();
HideSettings();
ShowSettings();
document.getElementById("dictionaryNameEdit").focus();
}
function DeleteCurrentDictionary() {
if (confirm("This will delete the current dictionary from the database. If you do not have a backed up export, you will lose it forever!\n\nDo you still want to delete?")) {
ResetDictionaryToDefault();
var deleteDictionary = new XMLHttpRequest();
deleteDictionary.open('POST', "/php/ajax_dictionarymanagement.php?action=delete");
deleteDictionary.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
deleteDictionary.onreadystatechange = function() {
if (deleteDictionary.readyState == 4 && deleteDictionary.status == 200) {
if (deleteDictionary.responseText.length < 31) {
console.log(deleteDictionary.responseText);
CreateNewDictionary();
} else {
HideSettings();
ShowDictionaryDeleteMenu(deleteDictionary.responseText);
if (document.getElementById("loadAfterDelete").options.length == 0) {
document.getElementById('loadAfterDeleteScreen').style.display = 'none';
CreateNewDictionary();
}
}
return true;
} else {
return false;
}
}
deleteDictionary.send();
}
}
function ResetDictionaryToDefault() {
currentDictionary = JSON.parse(defaultDictionaryJSON);
}
function SaveAndUpdateWords(action, wordIndex) {
var dataToSend = "";
if (action == "all") {
// For dictionaries not already in the db. Send all the words to database.
dataToSend = JSON.stringify(currentDictionary.words);
} else if (action == "update") {
// Only send the specified word to update.
dataToSend = JSON.stringify(currentDictionary.words[wordIndex]);
} else if (action == "new") {
// Send the last word pushed to the words array before it's sorted.
dataToSend = JSON.stringify(currentDictionary.words[currentDictionary.words.length - 1]);
}
var sendWords = new XMLHttpRequest();
sendWords.open('POST', "/php/ajax_dictionarymanagement.php?action=word" + action + "&dict=" + currentDictionary.externalID.toString() + "&nextwordid=" + currentDictionary.nextWordId.toString());
sendWords.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
sendWords.onreadystatechange = function() {
if (sendWords.readyState == 4 && sendWords.status == 200) {
SaveWords();
ClearForm();
console.log(sendWords.responseText);
return true;
} else {
return false;
}
}
sendWords.send(dataToSend);
}
function SaveWords() {
if (!currentDictionary.settings.sortByEquivalent) {
currentDictionary.words.sort(dynamicSort(['name', 'partOfSpeech']));
} else {
currentDictionary.words.sort(dynamicSort(['simpleDefinition', 'partOfSpeech']));
}
SaveDictionary(false);
ProcessLoad();
}
function SaveAndUpdateDictionary(keepFormContents) {
SaveDictionary(true);
ShowDictionary();
if (!keepFormContents) {
ClearForm();
}
CloseUpdateConflictArea('');
}
function SaveDictionary(sendToDatabase) {
//Always save local copy of current dictionary, but if logged in also send to database.
if (sendToDatabase) {
SendDictionary();
}
localStorage.setItem('dictionary', JSON.stringify(currentDictionary));
SavePreviousDictionary();
}
function SendDictionary() {
var action = "";
var postString = "";
if (currentDictionary.externalID > 0) {
action = "update";
postString = DataToSend(false);
} else {
action = "new";
postString = DataToSend(true);
}
var sendDictionary = new XMLHttpRequest();
sendDictionary.open('POST', "/php/ajax_dictionarymanagement.php?action=" + action);
sendDictionary.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
sendDictionary.onreadystatechange = function() {
if (sendDictionary.readyState == 4 && sendDictionary.status == 200) {
if (sendDictionary.responseText == "updated successfully") {
console.log(sendDictionary.responseText);
LoadUserDictionaries();
ProcessLoad();
} else if (isNaN(parseInt(sendDictionary.responseText))) {
console.log(sendDictionary.responseText);
} else { // It will only be a number if it is a new dictionary.
currentDictionary.externalID = parseInt(sendDictionary.responseText);
if (currentDictionary.words.length > 0) {
SaveAndUpdateWords("all");
}
LoadUserDictionaries();
ProcessLoad();
console.log("saved " + parseInt(sendDictionary.responseText).toString() + " successfully");
}
return true;
} else {
return false;
}
}
sendDictionary.send(postString);
}
function DataToSend(sendAll) {
sendAll = (typeof sendAll !== 'undefined' && sendAll != null) ? sendAll : false;
var data = "";
if (currentDictionary.externalID == 0) {
data = "name=" + encodeURIComponent(currentDictionary.name) + "&description=" + encodeURIComponent(currentDictionary.description) + "&words=" + encodeURIComponent(JSON.stringify(currentDictionary.words));
data += "&nextwordid=" + currentDictionary.nextWordId + "&allowduplicates=" + ((currentDictionary.settings.allowDuplicates) ? "1" : "0") + "&casesensitive=" + ((currentDictionary.settings.caseSensitive) ? "1" : "0");
data += "&partsofspeech=" + encodeURIComponent(currentDictionary.settings.partsOfSpeech) + "&sortbyequivalent=" + ((currentDictionary.settings.sortByEquivalent) ? "1" : "0") + "&iscomplete=" + ((currentDictionary.settings.isComplete) ? "1" : "0") + "&ispublic=" + ((currentDictionary.settings.isPublic) ? "1" : "0") + "";
} else {
if (sendAll || currentDictionary.name != previousDictionary.name) {
data += "name=" + encodeURIComponent(currentDictionary.name);
}
if (sendAll || currentDictionary.description != previousDictionary.description) {
data += ((data=="") ? "" : "&") + "description=" + encodeURIComponent(currentDictionary.description);
}
if (sendAll || currentDictionary.nextWordId != previousDictionary.nextWordId) {
data += ((data=="") ? "" : "&") + "nextwordid=" + currentDictionary.nextWordId;
}
if (sendAll || currentDictionary.settings.allowDuplicates != previousDictionary.allowDuplicates) {
data += ((data=="") ? "" : "&") + "allowduplicates=" + ((currentDictionary.settings.allowDuplicates) ? "1" : "0");
}
if (sendAll || currentDictionary.settings.caseSensitive != previousDictionary.caseSensitive) {
data += ((data=="") ? "" : "&") + "casesensitive=" + ((currentDictionary.settings.caseSensitive) ? "1" : "0");
}
if (sendAll || currentDictionary.settings.partsOfSpeech != previousDictionary.partsOfSpeech) {
data += ((data=="") ? "" : "&") + "partsofspeech=" + encodeURIComponent(currentDictionary.settings.partsOfSpeech);
}
if (sendAll || currentDictionary.settings.sortByEquivalent != previousDictionary.sortByEquivalent) {
data += ((data=="") ? "" : "&") + "sortbyequivalent=" + ((currentDictionary.settings.sortByEquivalent) ? "1" : "0");
}
if (sendAll || currentDictionary.settings.isComplete != previousDictionary.isComplete) {
data += ((data=="") ? "" : "&") + "iscomplete=" + ((currentDictionary.settings.isComplete) ? "1" : "0");
}
if (sendAll || currentDictionary.settings.isPublic != previousDictionary.isPublic) {
data += ((data=="") ? "" : "&") + "ispublic=" + ((currentDictionary.settings.isPublic) ? "1" : "0");
}
}
return data;
}
function LoadDictionary() {
LoadLocalDictionary();
var loadDictionary = new XMLHttpRequest();
loadDictionary.open('GET', "/php/ajax_dictionarymanagement.php?action=load");
loadDictionary.onreadystatechange = function() {
if (loadDictionary.readyState == 4 && loadDictionary.status == 200) {
if (loadDictionary.responseText == "no dictionaries") {
// If there are no dictionaries in the database and there's one in memory, remove the id & public setting and send it as a new one.
currentDictionary.externalID = 0;
currentDictionary.settings.isPublic = false;
SendDictionary(true);
} else if (loadDictionary.responseText.length < 60) {
console.log(loadDictionary.responseText);
} else {
currentDictionary = JSON.parse(loadDictionary.responseText);
SaveDictionary(false);
}
}
ProcessLoad();
}
loadDictionary.send();
}
function ChangeDictionary(userDictionariesSelect) {
userDictionariesSelect = (typeof userDictionariesSelect !== 'undefined' && userDictionariesSelect != null) ? userDictionariesSelect : document.getElementById("userDictionaries");
if (currentDictionary.externalID != userDictionariesSelect.value && userDictionariesSelect.options.length > 0) {
// Show the info page with loading screen and hide settings and stuff.
ShowInfoWithText("<h1>Loading " + userDictionariesSelect.options[userDictionariesSelect.selectedIndex].text + "...</h1>");
HideSettings();
ChangeDictionaryToId(userDictionariesSelect.value, function(response) {
if (response == "no dictionaries") {
console.log(response);
SendDictionary(false);
} else if (response.length < 60) {
console.log(response);
} else {
currentDictionary = JSON.parse(response);
SaveDictionary(false);
ProcessLoad();
LoadUserDictionaries();
HideInfo(); // Hide the loading screen.
}
});
}
}
function ChangeDictionaryToId(dictionaryId, callbackFunction) {
var changeDictionaryRequest = new XMLHttpRequest();
changeDictionaryRequest.open('POST', "/php/ajax_dictionarymanagement.php?action=switch");
changeDictionaryRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
var postString = "newdictionaryid=" + dictionaryId.toString();
changeDictionaryRequest.onreadystatechange = function() {
if (changeDictionaryRequest.readyState == 4 && changeDictionaryRequest.status == 200) {
callbackFunction(changeDictionaryRequest.responseText);
}
}
changeDictionaryRequest.send(postString);
}
function LoadLocalDictionary() {
if (localStorage.getItem('dictionary')) {
var tmpDictionary = JSON.parse(localStorage.getItem('dictionary'));
if (tmpDictionary.words.length > 0 || tmpDictionary.description != "A new dictionary." || tmpDictionary.name != "New") {
currentDictionary = JSON.parse(localStorage.getItem('dictionary'));
}
tmpDictionary = null;
}
}
function ProcessLoad() {
if (!currentDictionary.hasOwnProperty("nextWordId")) {
currentDictionary.nextWordId = currentDictionary.words.length + 1;
}
HideSettingsWhenComplete();
ShowDictionary();
SetPartsOfSpeech();
if (currentDictionary.settings.isComplete) {
document.getElementById("wordEntryForm").style.display = "none";
}
SavePreviousDictionary();
}
function SavePreviousDictionary () {
// Save non-word data to check if anything has changed (words can identify themselves if changed).
// Used to minimize data pushed to database.
previousDictionary = {
name: currentDictionary.name,
description: currentDictionary.description,
nextWordId: currentDictionary.nextWordId,
allowDuplicates: currentDictionary.settings.allowDuplicates,
caseSensitive: currentDictionary.settings.caseSensitive,
partsOfSpeech: currentDictionary.settings.partsOfSpeech,
sortByEquivalent: currentDictionary.settings.sortByEquivalent,
isComplete: currentDictionary.settings.isComplete,
isPublic: currentDictionary.settings.isPublic
};
}
function ExportDictionary() {
var downloadName = removeDiacritics(stripHtmlEntities(currentDictionary.name)).replace(/\W/g, '');
if (downloadName == "") {
downloadName = "export";
}
download(downloadName + ".dict", localStorage.getItem('dictionary'));
}
function ExportWords() {
if (currentDictionary.words.length > 0) {
var downloadName = removeDiacritics(stripHtmlEntities(currentDictionary.name)).replace(/\W/g, '');
if (downloadName == "") {
downloadName = "export";
}
downloadName += "_words";
var wordsCSV = "word,pronunciation,part of speech,definition,explanation\n";
for (var i = 0; i < currentDictionary.words.length; i++) {
var word = "\"" + htmlEntitiesParse(currentDictionary.words[i].name).trim().replace(/\"/g, "\"\"") + "\"";
var pronunciation = "\"" + htmlEntitiesParse(currentDictionary.words[i].pronunciation).trim().replace(/\"/g, "\"\"") + "\"";
var partOfSpeech = "\"" + htmlEntitiesParse(currentDictionary.words[i].partOfSpeech).trim().replace(/\"/g, "\"\"") + "\"";
var simpleDefinition = "\"" + htmlEntitiesParse(currentDictionary.words[i].simpleDefinition).trim().replace(/\"/g, "\"\"") + "\"";
var longDefinition = "\"" + htmlEntitiesParse(currentDictionary.words[i].longDefinition).replace(/\"/g, "\"\"") + "\"";
wordsCSV += word + "," + pronunciation + "," + partOfSpeech + "," + simpleDefinition + "," + longDefinition + "\n";
}
download(downloadName + ".csv", wordsCSV);
} else {
alert("Dictionary must have at least 1 word to export.");
}
}
function ImportDictionary() {
if (currentDictionary.externalID > 0 || confirm("Importing this dictionary will overwrite your current one, making it impossible to retrieve if you have not already exported it! Do you still want to import?")) {
if (!window.FileReader) {
alert('Your browser is not supported');
return false;
}
var reader = new FileReader();
if (document.getElementById("importFile").files.length > 0) {
var file = document.getElementById("importFile").files[0];
// Read the file
reader.readAsText(file);
// When it's loaded, process it
reader.onloadend = function () {
if (reader.result && reader.result.length) {
var tmpDicitonary = JSON.parse(reader.result);
if (tmpDicitonary.hasOwnProperty("name") && tmpDicitonary.hasOwnProperty("description") &&
tmpDicitonary.hasOwnProperty("words") && tmpDicitonary.hasOwnProperty("settings"))
{
currentDictionary = JSON.parse(reader.result);
currentDictionary.externalID = 0; // Reset external id for imported dictionary.
currentDictionary.settings.isPublic = false; // Reset public setting for imported dictionary.
SaveDictionary(true);
ProcessLoad();
HideInfo();
HideSettings();
document.getElementById("importFile").value = "";
NewNotification("Successfully Imported the \"" + currentDictionary.name + "\" Dictionary.");
} else {
var errorString = "File is missing:";
if (!tmpDicitonary.hasOwnProperty("name"))
errorString += " name";
if (!tmpDicitonary.hasOwnProperty("description"))
errorString += " description";
if (!tmpDicitonary.hasOwnProperty("words"))
errorString += " words";
if (!tmpDicitonary.hasOwnProperty("settings"))
errorString += " settings";
alert("Uploaded file is not compatible.\n\n" + errorString);
}
tmpDicitonary = null;
} else {
alert("Upload Failed");
}
reader = null;
}
} else {
alert("You must add a file to import.");
}
}
}
function ImportWords() {
if (currentDictionary.externalID > 0 || confirm("This will add words in a correctly formatted CSV file to your currently loaded dictionary. Do you still want to import?")) {
if (!window.FileReader) {
alert('Your browser is not supported');
return false;
}
if (document.getElementById("importWordsCSV").files.length > 0) {
var file = document.getElementById("importWordsCSV").files[0];
var resultsArea = document.getElementById("importOptions");
resultsArea.innerHTML = "<h3>Importing Words...</h3>";
var currentRow = 0; // Because of the header, the first row of data is always on line 2.
var rowsImported = 0;
Papa.parse(file, {
header: true,
step: function(row, parser) {
currentRow++;
// If there are no errors OR the word and either definition or explanation contain data, then import it.
if ((row.data[0].word.trim().length > 0 && (row.data[0].definition.trim().length > 0 || row.data[0].explanation.trim().length > 0)) || row.errors.length == 0) {
var wordName = htmlEntities(row.data[0]["word"]).trim(),
wordPronunciation = htmlEntities(row.data[0]["pronunciation"]).trim(),
wordPartOfSpeech = ((htmlEntities(row.data[0]["part of speech"]).trim().length > 0) ? htmlEntities(row.data[0]["part of speech"]).trim() : " "),
wordSimpleDefinition = htmlEntities(row.data[0]["definition"]).trim(),
wordLongDefinition = htmlEntities(row.data[0]["explanation"]).trim(),
wordId = currentDictionary.nextWordId++;
currentDictionary.words.push({name: wordName, pronunciation: wordPronunciation, partOfSpeech: wordPartOfSpeech, simpleDefinition: wordSimpleDefinition, longDefinition: wordLongDefinition, wordId: wordId});
var wordEntry = DictionaryEntryTemplate(currentDictionary.words[currentDictionary.words.length - 1]);
resultsArea.innerHTML += wordEntry;
rowsImported++;
} else {
// If it's not just an empty line, give an error.
if (row.data[0].word.trim().length > 0) {
for (var i = 0; i < row.errors.length; i++) {
resultsArea.innerHTML += "<p>Error on record #" + currentRow.toString() + ": " + row.errors[i].message + "</p>";
}
}
}
// Scroll to the bottom.
document.getElementById("infoPage").scrollTop = document.getElementById("infoPage").scrollHeight;
},
complete: function(results) {
SaveAndUpdateWords("all");
resultsArea.innerHTML += "<p>The file has finished importing " + rowsImported.toString() + " words.</p>";
NewNotification("Imported " + rowsImported.toString() + " words.");
// Scroll to the bottom.
document.getElementById("importOptions").scrollTop = document.getElementById("importOptions").scrollHeight;
document.getElementById("numberOfWordsInDictionary").innerHTML = currentDictionary.words.length.toString();
}
});
} else {
alert("You must add a file to import.");
}
}
}
function WordIndex(word, byId) {
// Use byId = true to enter word id number instead of string.
for (var i = 0; i < currentDictionary.words.length; i++)
{
if ((!byId && (!currentDictionary.settings.caseSensitive && currentDictionary.words[i].name.toLowerCase() == word.toLowerCase()) ||
(currentDictionary.settings.caseSensitive && currentDictionary.words[i].name == word)) ||
(byId && currentDictionary.words[i].wordId == word)) {
return i;
}
}
return -1;
}
function WordAtIndexWasChanged(indexString, word, pronunciation, partOfSpeech, simpleDefinition, longDefinition) {
return (!currentDictionary.settings.caseSensitive && currentDictionary.words[parseInt(indexString)].name.toLowerCase() != word.toLowerCase()) ||
(currentDictionary.settings.caseSensitive && currentDictionary.words[parseInt(indexString)].name != word) ||
currentDictionary.words[parseInt(indexString)].pronunciation != pronunciation ||
currentDictionary.words[parseInt(indexString)].partOfSpeech.trim() != partOfSpeech ||
currentDictionary.words[parseInt(indexString)].simpleDefinition != simpleDefinition ||
currentDictionary.words[parseInt(indexString)].longDefinition != longDefinition;
}
function CheckForPartsOfSpeechChange() {
if (htmlEntities(document.getElementById("dictionaryPartsOfSpeechEdit").value) != currentDictionary.settings.partsOfSpeech) {
if (htmlEntities(document.getElementById("dictionaryPartsOfSpeechEdit").value) != "") {
currentDictionary.settings.partsOfSpeech = htmlEntities(document.getElementById("dictionaryPartsOfSpeechEdit").value);
SetPartsOfSpeech();
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,120 @@
/*
Retrieved from http://stackoverflow.com/a/18391901/3508346
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// "what?" version ... http://jsperf.com/diacritics/12
function removeDiacritics(str) {
var defaultDiacriticsRemovalap = [
{'base':'A', 'letters':'\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F'},
{'base':'AA','letters':'\uA732'},
{'base':'AE','letters':'\u00C6\u01FC\u01E2'},
{'base':'AO','letters':'\uA734'},
{'base':'AU','letters':'\uA736'},
{'base':'AV','letters':'\uA738\uA73A'},
{'base':'AY','letters':'\uA73C'},
{'base':'B', 'letters':'\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181'},
{'base':'C', 'letters':'\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E'},
{'base':'D', 'letters':'\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779'},
{'base':'DZ','letters':'\u01F1\u01C4'},
{'base':'Dz','letters':'\u01F2\u01C5'},
{'base':'E', 'letters':'\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E'},
{'base':'F', 'letters':'\u0046\u24BB\uFF26\u1E1E\u0191\uA77B'},
{'base':'G', 'letters':'\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E'},
{'base':'H', 'letters':'\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D'},
{'base':'I', 'letters':'\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197'},
{'base':'J', 'letters':'\u004A\u24BF\uFF2A\u0134\u0248'},
{'base':'K', 'letters':'\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2'},
{'base':'L', 'letters':'\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780'},
{'base':'LJ','letters':'\u01C7'},
{'base':'Lj','letters':'\u01C8'},
{'base':'M', 'letters':'\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C'},
{'base':'N', 'letters':'\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4'},
{'base':'NJ','letters':'\u01CA'},
{'base':'Nj','letters':'\u01CB'},
{'base':'O', 'letters':'\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C'},
{'base':'OI','letters':'\u01A2'},
{'base':'OO','letters':'\uA74E'},
{'base':'OU','letters':'\u0222'},
{'base':'OE','letters':'\u008C\u0152'},
{'base':'oe','letters':'\u009C\u0153'},
{'base':'P', 'letters':'\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754'},
{'base':'Q', 'letters':'\u0051\u24C6\uFF31\uA756\uA758\u024A'},
{'base':'R', 'letters':'\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782'},
{'base':'S', 'letters':'\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784'},
{'base':'T', 'letters':'\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786'},
{'base':'TZ','letters':'\uA728'},
{'base':'U', 'letters':'\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244'},
{'base':'V', 'letters':'\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245'},
{'base':'VY','letters':'\uA760'},
{'base':'W', 'letters':'\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72'},
{'base':'X', 'letters':'\u0058\u24CD\uFF38\u1E8A\u1E8C'},
{'base':'Y', 'letters':'\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE'},
{'base':'Z', 'letters':'\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762'},
{'base':'a', 'letters':'\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250'},
{'base':'aa','letters':'\uA733'},
{'base':'ae','letters':'\u00E6\u01FD\u01E3'},
{'base':'ao','letters':'\uA735'},
{'base':'au','letters':'\uA737'},
{'base':'av','letters':'\uA739\uA73B'},
{'base':'ay','letters':'\uA73D'},
{'base':'b', 'letters':'\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253'},
{'base':'c', 'letters':'\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184'},
{'base':'d', 'letters':'\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A'},
{'base':'dz','letters':'\u01F3\u01C6'},
{'base':'e', 'letters':'\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD'},
{'base':'f', 'letters':'\u0066\u24D5\uFF46\u1E1F\u0192\uA77C'},
{'base':'g', 'letters':'\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F'},
{'base':'h', 'letters':'\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265'},
{'base':'hv','letters':'\u0195'},
{'base':'i', 'letters':'\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131'},
{'base':'j', 'letters':'\u006A\u24D9\uFF4A\u0135\u01F0\u0249'},
{'base':'k', 'letters':'\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3'},
{'base':'l', 'letters':'\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747'},
{'base':'lj','letters':'\u01C9'},
{'base':'m', 'letters':'\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F'},
{'base':'n', 'letters':'\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5'},
{'base':'nj','letters':'\u01CC'},
{'base':'o', 'letters':'\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275'},
{'base':'oi','letters':'\u01A3'},
{'base':'ou','letters':'\u0223'},
{'base':'oo','letters':'\uA74F'},
{'base':'p','letters':'\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755'},
{'base':'q','letters':'\u0071\u24E0\uFF51\u024B\uA757\uA759'},
{'base':'r','letters':'\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783'},
{'base':'s','letters':'\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B'},
{'base':'t','letters':'\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787'},
{'base':'tz','letters':'\uA729'},
{'base':'u','letters': '\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289'},
{'base':'v','letters':'\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C'},
{'base':'vy','letters':'\uA761'},
{'base':'w','letters':'\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73'},
{'base':'x','letters':'\u0078\u24E7\uFF58\u1E8B\u1E8D'},
{'base':'y','letters':'\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF'},
{'base':'z','letters':'\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763'}
];
var diacriticsMap = {};
for (var i=0; i < defaultDiacriticsRemovalap.length; i++){
var letters = defaultDiacriticsRemovalap[i].letters;
for (var j=0; j < letters.length ; j++){
diacriticsMap[letters[j]] = defaultDiacriticsRemovalap[i].base;
}
}
return str.replace(/[^\u0000-\u007E]/g, function(a){
return diacriticsMap[a] || a;
});
}
modules.export = removeDiacritics;

256
src/js/helpers.js Normal file
View File

@ -0,0 +1,256 @@
function ready(fn) {
if (document.readyState != 'loading'){
fn();
} else {
document.addEventListener('DOMContentLoaded', fn);
}
}
// Set Marked.js settings
marked.setOptions({
gfm: true,
tables: true,
breaks: true,
sanitize: true
});
// Get Keycode based on key name
function keyCodeFor(keyName) {
if (keyName == "backspace") return 8;
else if (keyName == "tab") return 9;
else if (keyName == "ctrlEnter") return 10;
else if (keyName == "enter") return 13;
else if (keyName == "shift") return 16;
else if (keyName == "ctrl") return 17;
else if (keyName == "alt") return 18;
else if (keyName == "pausebreak") return 19;
else if (keyName == "capslock") return 20;
else if (keyName == "escape") return 27;
else if (keyName == "space") return 32;
else if (keyName == "pageup") return 33;
else if (keyName == "pagedown") return 34;
else if (keyName == "end") return 35;
else if (keyName == "home") return 36;
else if (keyName == "left") return 37;
else if (keyName == "up") return 38;
else if (keyName == "right") return 39;
else if (keyName == "down") return 40;
else if (keyName == "insert") return 45;
else if (keyName == "del") return 46;
else if (keyName == "zero") return 48;
else if (keyName == "one") return 49;
else if (keyName == "two") return 50;
else if (keyName == "three") return 51;
else if (keyName == "four") return 52;
else if (keyName == "five") return 53;
else if (keyName == "six") return 54;
else if (keyName == "seven") return 55;
else if (keyName == "eight") return 56;
else if (keyName == "nine") return 57;
else if (keyName == "a") return 65;
else if (keyName == "b") return 66;
else if (keyName == "c") return 67;
else if (keyName == "d") return 68;
else if (keyName == "e") return 69;
else if (keyName == "f") return 70;
else if (keyName == "g") return 71;
else if (keyName == "h") return 72;
else if (keyName == "i") return 73;
else if (keyName == "j") return 74;
else if (keyName == "k") return 75;
else if (keyName == "l") return 76;
else if (keyName == "m") return 77;
else if (keyName == "n") return 78;
else if (keyName == "o") return 79;
else if (keyName == "p") return 80;
else if (keyName == "q") return 81;
else if (keyName == "r") return 82;
else if (keyName == "s") return 83;
else if (keyName == "t") return 84;
else if (keyName == "u") return 85;
else if (keyName == "v") return 86;
else if (keyName == "w") return 87;
else if (keyName == "x") return 88;
else if (keyName == "y") return 89;
else if (keyName == "z") return 90;
else if (keyName == "leftwinkey") return 91;
else if (keyName == "rightwinkey") return 92;
else if (keyName == "selectkey") return 93;
else if (keyName == "numpad_0") return 96;
else if (keyName == "numpad_1") return 97;
else if (keyName == "numpad_2") return 98;
else if (keyName == "numpad_3") return 99;
else if (keyName == "numpad_4") return 100;
else if (keyName == "numpad_5") return 101;
else if (keyName == "numpad_6") return 102;
else if (keyName == "numpad_7") return 103;
else if (keyName == "numpad_8") return 104;
else if (keyName == "numpad_9") return 105;
else if (keyName == "numpad_asterisk") return 106;
else if (keyName == "numpad_plus") return 107;
else if (keyName == "numpad_dash") return 109;
else if (keyName == "numpad_period") return 110;
else if (keyName == "numpad_slash") return 111;
else if (keyName == "f1") return 112;
else if (keyName == "f2") return 113;
else if (keyName == "f3") return 114;
else if (keyName == "f4") return 115;
else if (keyName == "f5") return 116;
else if (keyName == "f6") return 117;
else if (keyName == "f7") return 118;
else if (keyName == "f8") return 119;
else if (keyName == "f9") return 120;
else if (keyName == "f10") return 121;
else if (keyName == "f11") return 122;
else if (keyName == "f12") return 123;
else if (keyName == "numlock") return 144;
else if (keyName == "scrolllock") return 145;
else if (keyName == "semicolon") return 186;
else if (keyName == "equal") return 187;
else if (keyName == "comma") return 188;
else if (keyName == "dash") return 189;
else if (keyName == "period") return 190;
else if (keyName == "slash") return 191;
else if (keyName == "grave") return 192;
else if (keyName == "openbracket") return 219;
else if (keyName == "backslash") return 220;
else if (keyName == "closebraket") return 221;
else if (keyName == "quote") return 222;
else return false;
}
function getInputSelection(el) {
// Retrieved from http://stackoverflow.com/a/4207763
var start = 0, end = 0, normalizedValue, range,
textInputRange, len, endRange;
el.focus();
if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
start = el.selectionStart;
end = el.selectionEnd;
} else {
range = document.selection.createRange();
if (range && range.parentElement() == el) {
len = el.value.length;
normalizedValue = el.value.replace(/\r\n/g, "\n");
// Create a working TextRange that lives only in the input
textInputRange = el.createTextRange();
textInputRange.moveToBookmark(range.getBookmark());
// Check if the start and end of the selection are at the very end
// of the input, since moveStart/moveEnd doesn't return what we want
// in those cases
endRange = el.createTextRange();
endRange.collapse(false);
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
start = end = len;
} else {
start = -textInputRange.moveStart("character", -len);
start += normalizedValue.slice(0, start).split("\n").length - 1;
if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
end = len;
} else {
end = -textInputRange.moveEnd("character", -len);
end += normalizedValue.slice(0, end).split("\n").length - 1;
}
}
}
}
return {
start: start,
end: end
};
}
function setSelectionRange(input, selectionStart, selectionEnd) {
// Retrieved from http://stackoverflow.com/a/17858641/3508346
if (input.setSelectionRange) {
input.focus();
input.setSelectionRange(selectionStart, selectionEnd);
}
else if (input.createTextRange) {
var range = input.createTextRange();
range.collapse(true);
range.moveEnd('character', selectionEnd);
range.moveStart('character', selectionStart);
range.select();
}
}
function SaveScroll() {
var doc = document.documentElement;
var left = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0);
var top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
savedScroll.x = left;
savedScroll.y = top;
}
function htmlEntities(string) {
return String(string).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&apos;').replace(/\\/g, '&#92;').replace(/\n/g, '<br>');
}
function htmlEntitiesParse(string) {
return String(string).replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&#92;/g, '\\').replace(/<br>/g, '\n');
}
function htmlEntitiesParseForMarkdown(string) {
return String(string).replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&#92;/g, '\\').replace(/<br>/g, '\n');
}
function stripHtmlEntities(string) {
// This is for the export name.
return String(string).replace(/&amp;/g, '').replace(/&lt;/g, '').replace(/&gt;/g, '').replace(/&quot;/g, '').replace(/&apos;/g, "").replace(/&#92;/g, '').replace(/<br>/g, '');
}
function htmlEntitiesParseForSearchEntry(string) {
return String(string).replace(/"/g, '%%%%').replace(/'/g, "````");
}
function htmlEntitiesParseForSearch(string) {
return String(string).replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '%%%%').replace(/&apos;/g, "````");
}
function regexParseForSearch(string) {
return String(string).replace(/([\[\\\^\$\.\|\?\*\+\(\)\{\}\]])/g, "\\$1");
}
function dynamicSort(propertiesArray) {
/* Retrieved from http://stackoverflow.com/a/30446887/3508346
Usage: theArray.sort(dynamicSort(['propertyAscending', '-propertyDescending']));*/
return function (a, b) {
return propertiesArray
.map(function (o) {
var dir = 1;
if (o[0] === '-') {
dir = -1;
o=o.substring(1);
}
if (removeDiacritics(a[o]).toLowerCase() > removeDiacritics(b[o]).toLowerCase()) return dir;
if (removeDiacritics(a[o]).toLowerCase() < removeDiacritics(b[o]).toLowerCase()) return -(dir);
return 0;
})
.reduce(function firstNonZeroValue (p,n) {
return p ? p : n;
}, 0);
};
}
function download(filename, text) {
/* Retrieved from http://stackoverflow.com/a/18197341/3508346
Usage: download('test.txt', 'Hello world!');*/
var element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}

194
src/js/publicView.js Normal file
View File

@ -0,0 +1,194 @@
function IsValidPublicDicitonary() {
return typeof publicDictionary !== 'string';
}
function ShowPublicDictionary(ignoreFilters) {
ignoreFilters = (typeof ignoreFilters !== 'undefined') ? ignoreFilters : false;
if (IsValidPublicDicitonary()) {
var filters = (ignoreFilters) ? [] : GetSelectedFilters();
var searchResults = [];
var search = (ignoreFilters) ? "" : htmlEntitiesParseForSearchEntry(document.getElementById("searchBox").value);
var searchByWord = (ignoreFilters) ? null : document.getElementById("searchOptionWord").checked;
var searchBySimple = (ignoreFilters) ? null : document.getElementById("searchOptionSimple").checked;
var searchByLong = (ignoreFilters) ? null : document.getElementById("searchOptionLong").checked;
var searchIgnoreCase = (ignoreFilters) ? null : !document.getElementById("searchCaseSensitive").checked; //It's easier to negate case here instead of negating it every use since ignore case is default.
var searchIgnoreDiacritics = (ignoreFilters) ? null : document.getElementById("searchIgnoreDiacritics").checked;
if (!ignoreFilters && search != "" && (searchByWord || searchBySimple || searchByLong)) {
var xpath = [];
var searchDictionaryJSON = htmlEntitiesParseForSearch(JSON.stringify(publicDictionary));
if (searchIgnoreCase) {
search = search.toLowerCase();
//searchDictionaryJSON = searchDictionaryJSON.toLowerCase();
}
if (searchIgnoreDiacritics) {
search = removeDiacritics(search);
searchDictionaryJSON = removeDiacritics(searchDictionaryJSON);
}
if (searchByWord) {
xpath.push('contains('+ ((searchIgnoreCase) ? 'name' : 'translate(name, "", "")') +', "'+ search +'")');
}
if (searchBySimple) {
xpath.push('contains('+ ((searchIgnoreCase) ? 'simpleDefinition' : 'translate(simpleDefinition, "", "")') +', "'+ search +'")');
}
if (searchByLong) {
xpath.push('contains('+ ((searchIgnoreCase) ? 'longDefinition' : 'translate(longDefinition, "", "")') +', "'+ search +'")');
}
var searchDictionary = JSON.parse(searchDictionaryJSON);
searchResults = JSON.search(searchDictionary, '//words['+ xpath.join(' or ') +']/wordId');
}
var dictionaryNameArea = document.getElementById("dictionaryName");
dictionaryNameArea.innerHTML = publicDictionary.name + " Dictionary";
var dictionaryByArea = document.getElementById("dictionaryBy");
dictionaryByArea.innerHTML = "created by " + publicDictionary.createdBy;
var dictionaryIncompleteArea = document.getElementById("incompleteNotice");
if (!publicDictionary.settings.isComplete) {
dictionaryIncompleteArea.innerHTML = "<em>Note: This dictionary is not yet complete and is likely to change.</em>";
}
var dictionaryDescriptionArea = document.getElementById("dictionaryDescription");
dictionaryDescriptionArea.innerHTML = marked(htmlEntitiesParseForMarkdown(publicDictionary.description));
var dictionaryArea = document.getElementById("theDictionary");
var dictionaryText = "";
var numberOfWordsDisplayed = 0;
if (publicDictionary.words.length > 0) {
for (var i = 0; i < publicDictionary.words.length; i++) {
if (filters.length == 0 || (filters.length > 0 && filters.indexOf(publicDictionary.words[i].partOfSpeech) > -1)) {
if (search == "" || (search != "" && (searchByWord || searchBySimple || searchByLong) && searchResults.indexOf(publicDictionary.words[i].wordId) >= 0)) {
if (!publicDictionary.words[i].hasOwnProperty("pronunciation")) {
publicDictionary.words[i].pronunciation = ""; //Account for new property
}
if (!publicDictionary.words[i].hasOwnProperty("wordId")) {
publicDictionary.words[i].wordId = i + 1; //Account for new property
}
dictionaryText += PublicDictionaryEntry(i, ignoreFilters);
numberOfWordsDisplayed++;
}
}
}
} else {
dictionaryText = "There are no entries in the dictionary."
}
dictionaryArea.innerHTML = dictionaryText;
if (!ignoreFilters) {
ShowFilterWordCount(numberOfWordsDisplayed);
}
} else {
document.getElementById("dictionaryContent").innerHTML = publicDictionary;
}
}
function PublicDictionaryEntry(itemIndex, ignoreFilters) {
var searchTerm = (ignoreFilters) ? "" : regexParseForSearch(document.getElementById("searchBox").value);
var searchByWord = (ignoreFilters) ? false : document.getElementById("searchOptionWord").checked;
var searchBySimple = (ignoreFilters) ? false : document.getElementById("searchOptionSimple").checked;
var searchByLong = (ignoreFilters) ? false : document.getElementById("searchOptionLong").checked;
var searchIgnoreCase = (ignoreFilters) ? false : !document.getElementById("searchCaseSensitive").checked; //It's easier to negate case here instead of negating it every use since ignore case is default.
var searchIgnoreDiacritics = (ignoreFilters) ? false : document.getElementById("searchIgnoreDiacritics").checked;
var searchRegEx = new RegExp("(" + ((searchIgnoreDiacritics) ? removeDiacritics(searchTerm) + "|" + searchTerm : searchTerm) + ")", "g" + ((searchIgnoreCase) ? "i" : ""));
var wordName = wordPronunciation = wordPartOfSpeech = wordSimpleDefinition = wordLongDefinition = "";
if (searchTerm != "" && searchByWord) {
wordName += htmlEntities(htmlEntitiesParse(publicDictionary.words[itemIndex].name).replace(searchRegEx, "<searchterm>$1</searchterm>")).replace(/&lt;(\/?)searchterm&gt;/g, '<$1searchterm>');
} else {
wordName += publicDictionary.words[itemIndex].name.toString(); // Use toString() to prevent using a reference instead of the value.
}
if (publicDictionary.words[itemIndex].pronunciation != "") {
wordPronunciation += marked(htmlEntitiesParseForMarkdown(publicDictionary.words[itemIndex].pronunciation)).replace(/<\/?p>/g,"");
}
if (publicDictionary.words[itemIndex].partOfSpeech != " " && publicDictionary.words[itemIndex].partOfSpeech != "") {
wordPartOfSpeech += publicDictionary.words[itemIndex].partOfSpeech.toString();
}
if (publicDictionary.words[itemIndex].simpleDefinition != "") {
if (searchTerm != "" && searchBySimple) {
wordSimpleDefinition += htmlEntities(htmlEntitiesParse(publicDictionary.words[itemIndex].simpleDefinition).replace(searchRegEx, "<searchterm>$1</searchterm>")).replace(/&lt;(\/?)searchterm&gt;/g, '<$1searchterm>');
} else {
wordSimpleDefinition += publicDictionary.words[itemIndex].simpleDefinition.toString();
}
}
if (publicDictionary.words[itemIndex].longDefinition != "") {
if (searchTerm != "" && searchByLong) {
wordLongDefinition += marked(htmlEntitiesParseForMarkdown(htmlEntities(htmlEntitiesParse(publicDictionary.words[itemIndex].longDefinition).replace(searchRegEx, "<searchterm>$1</searchterm>")))).replace(/&lt;(\/?)searchterm&gt\;/g, '<$1searchterm>');
} else {
wordLongDefinition += marked(htmlEntitiesParseForMarkdown(publicDictionary.words[itemIndex].longDefinition));
}
}
return PublicDictionaryEntryTemplate({
name : wordName,
pronunciation : wordPronunciation,
partOfSpeech : wordPartOfSpeech,
simpleDefinition : wordSimpleDefinition,
longDefinition : wordLongDefinition,
wordId : publicDictionary.words[itemIndex].wordId.toString()
}, false);
}
function PublicDictionaryEntryTemplate(wordObject, managementIndex) {
managementIndex = (typeof managementIndex !== 'undefined') ? managementIndex : false;
var entryText = "<entry id='entry";
if (managementIndex !== false) {
// If there's a managementIndex, append index number to the element id.
entryText += managementIndex.toString();
}
entryText += "'><a href='/" + publicDictionary.id + "/" + wordObject.wordId + "' class='wordLink clickable' title='Share Word'>&#10150;</a>";
entryText += "<word>" + wordObject.name + "</word>";
if (wordObject.pronunciation != "") {
entryText += "<pronunciation>" + wordObject.pronunciation + "</pronunciation>";
}
if (wordObject.partOfSpeech != "") {
entryText += "<partofspeech>" + wordObject.partOfSpeech + "</partofspeech>";
}
entryText += "<br>";
if (wordObject.simpleDefinition != "") {
entryText += "<simpledefinition>" + wordObject.simpleDefinition + "</simpledefinition>";
}
if (wordObject.longDefinition != "") {
entryText += "<longdefinition>" + wordObject.longDefinition + "</longdefinition>";
}
if (managementIndex !== false) {
entryText += ManagementArea(managementIndex);
}
entryText += "</entry>";
return entryText;
}
function SetPublicPartsOfSpeech () {
var wordFilterOptions = document.getElementById("filterOptions");
var newPartsOfSpeech = htmlEntitiesParse(publicDictionary.settings.partsOfSpeech).trim().split(",");
for (var j = 0; j < newPartsOfSpeech.length; j++) {
var thePartOfSpeech = newPartsOfSpeech[j].trim();
var wordFilterLabel = document.createElement('label');
wordFilterLabel.appendChild(document.createTextNode(thePartOfSpeech + " "));
wordFilterLabel['part-of-speech'] = thePartOfSpeech;
wordFilterLabel.className = 'filterOption';
var wordFilterCheckbox = document.createElement('input');
wordFilterCheckbox.type = 'checkbox';
wordFilterCheckbox.onchange = function(){ShowPublicDictionary()};
wordFilterLabel.appendChild(wordFilterCheckbox);
wordFilterOptions.appendChild(wordFilterLabel);
}
}

714
src/js/ui.js Normal file
View File

@ -0,0 +1,714 @@
function Initialize() {
LoadDictionary();
ClearForm();
LoadUserDictionaries();
GetTextFile("/README.md", "aboutText", true);
GetTextFile("/TERMS.md", "termsText", true);
GetTextFile("/PRIVACY.md", "privacyText", true);
GetTextFile("/LOGIN.form", "loginForm", false);
GetTextFile("/FORGOT.form", "forgotForm", false);
GetTextFile("/EXPORT.form", "exportForm", false);
GetTextFile("/IMPORT.form", "importForm", false);
SetKeyboardShortcuts();
SetWindowListeners();
}
function SetKeyboardShortcuts() {
document.addEventListener("keydown", function(e) {
var keyCode = (e.which ? e.which : e.keyCode);
if (keyCode == keyCodeFor("escape")) {
if (document.getElementById("infoScreen").style.display == "block") {
HideInfo();
}
else if (document.getElementById("fullScreenTextboxScreen").style.display == "block") {
HideFullScreenTextbox();
}
else if (document.getElementById("settingsScreen").style.display == "block") {
HideSettings();
}
else if (document.getElementById("accountSettingsScreen") && document.getElementById("accountSettingsScreen").style.display == "block") {
HideAccountSettings();
}
}
else if (e.ctrlKey) {
// Only allow shortcuts if not currently using fullscreen textbox
if (document.getElementById("fullScreenTextboxScreen").style.display == "none") {
if (keyCode == keyCodeFor("m")) {
if (document.activeElement.id.indexOf("longDefinition") >= 0) {
e.preventDefault();
ShowFullScreenTextbox(document.activeElement.id, 'Explanation/Long Definition');
}
else if (document.activeElement.id == "dictionaryDescriptionEdit") {
e.preventDefault();
ShowFullScreenTextbox('dictionaryDescriptionEdit', 'Dictionary Details');
}
else if (document.activeElement.id == "fullScreenTextbox") {
e.preventDefault();
HideFullScreenTextbox();
}
}
else if (keyCode == keyCodeFor("u")) {
e.preventDefault();
ToggleWordFormLock();
}
else if (keyCode == keyCodeFor("d")) {
e.preventDefault();
ToggleDescription();
}
else if (keyCode == keyCodeFor("s")) {
e.preventDefault();
//ToggleSearchFilter();
var searchFilterToggle = document.getElementById("searchFilterToggle");
var searchFilterArea = document.getElementById("searchFilterArea");
if (searchFilterArea.style.display == "none") {
searchFilterArea.style.display = "block";
searchFilterToggle.innerHTML = "Hide Search/Filter Options";
}
document.getElementById("searchBox").focus();
}
else if (keyCode == keyCodeFor("h")) {
e.preventDefault();
ShowInfo('aboutText');
}
}
else { //If the fullscreen editor *is* open, just prevent the others for consistent behavior.
if (keyCode == keyCodeFor("m")) {
e.preventDefault();
HideFullScreenTextbox();
}
else if (keyCode == keyCodeFor("u")) {
e.preventDefault();
}
else if (keyCode == keyCodeFor("d")) {
e.preventDefault();
}
else if (keyCode == keyCodeFor("s")) {
e.preventDefault();
}
else if (keyCode == keyCodeFor("h")) {
e.preventDefault();
}
}
}
else if (e.altKey) {
// Only toggle screens if not currently using fullscreen textbox
if (document.getElementById("fullScreenTextboxScreen").style.display == "none") {
if (keyCode == keyCodeFor("s")) {
e.preventDefault();
ToggleSettingsScreen(true);
}
else if (keyCode == keyCodeFor("a")) {
e.preventDefault();
ToggleAccountSettings();
}
}
}
}, false);
}
function SetWindowListeners() {
window.addEventListener("scroll", function() {
var doc = document.documentElement;
var top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
var dictionaryColumn = document.getElementById("dictionaryColumn");
var wordPullout = document.getElementById("mobileWordFormPullout");
if (top > dictionaryColumn.offsetTop) {
wordPullout.style.display = "block";
} else {
wordPullout.style.display = "none";
if (wordPullout.innerHTML != "+") {
LockWordForm();
wordPullout.innerHTML = "+";
}
}
});
}
function SubmitWordOnCtrlEnter(keypress) {
var keyCode = (event.which ? event.which : event.keyCode);
if (keyCode === keyCodeFor("ctrlEnter") || (keyCode == keyCodeFor("enter") && event.ctrlKey)) { //Windows and Linux Chrome accept ctrl+enter as keyCode 10.
event.preventDefault();
if (/\d/.test(document.activeElement.id)) { // If there IS a number in the ID, then it is a word being edited.
EditWord(document.activeElement.id.match(/\d+/)[0]); // .match(/\d+/) returns an array of digits in a string.
} else { // Otherwise, it's a new word.
AddWord();
}
}
}
function LoadUserDictionaries() {
var getDictionariesRequest = new XMLHttpRequest();
var userDictionariesSelect = document.getElementById("userDictionaries");
if (userDictionariesSelect != null) {
getDictionariesRequest.open('GET', "/php/ajax_dictionarymanagement.php?action=getall");
getDictionariesRequest.onreadystatechange = function() {
if (getDictionariesRequest.readyState == 4 && getDictionariesRequest.status == 200) {
ParseUserDictionariesIntoSelect(userDictionariesSelect, getDictionariesRequest.responseText);
}
}
getDictionariesRequest.send();
}
}
function ParseUserDictionariesIntoSelect(selectToPopulate, dicitonaryList) {
if (selectToPopulate.options.length > 0) {
for (var i = selectToPopulate.options.length - 1; i >= 0; i--) {
selectToPopulate.removeChild(selectToPopulate.options[i]);
}
}
var dictionaries = dicitonaryList.split("_DICTIONARYSEPARATOR_");
for (var j = 0; j < dictionaries.length - 1; j++) {
var dictionaryOption = document.createElement('option');
var dictionaryValues = dictionaries[j].split("_IDNAMESEPARATOR_");
dictionaryOption.appendChild(document.createTextNode(htmlEntitiesParse(dictionaryValues[1])));
dictionaryOption.value = dictionaryValues[0];
selectToPopulate.appendChild(dictionaryOption);
}
selectToPopulate.value = (currentDictionary.externalID > 0) ? currentDictionary.externalID : "";
}
function GetTextFile(filename, variableName, parseMarkdown) {
parseMarkdown = (typeof parseMarkdown !== 'undefined') ? parseMarkdown : false;
var readmeFileRequest = new XMLHttpRequest();
readmeFileRequest.open('GET', filename);
readmeFileRequest.onreadystatechange = function() {
if (readmeFileRequest.readyState == 4 && readmeFileRequest.status == 200) {
window[variableName] = (parseMarkdown) ? marked(readmeFileRequest.responseText, {sanitize: false}) : readmeFileRequest.responseText;
}
}
readmeFileRequest.send();
}
function ValidateLogin() {
var errorMessage = document.getElementById("loginError");
var emailValue = document.getElementById("loginEmailField").value;
var passwordValue = document.getElementById("loginPasswordField").value;
if (emailValue == "") {
errorMessage.innerHTML = "Email cannot be blank!";
return false;
} else if (!(/[^\s@]+@[^\s@]+\.[^\s@]+/.test(emailValue))) {
errorMessage.innerHTML = "Your email address looks fake. Email addresses look like this: name@email.com."
return false;
} else if (passwordValue == "") {
errorMessage.innerHTML = "Password cannot be blank!";
return false;
} else {
document.getElementById("loginForm").submit();
}
}
function ValidateCreateAccount() {
var errorMessage = document.getElementById("createAccountError");
var emailValue = document.getElementById("createAccountEmailField").value;
var passwordValue = document.getElementById("createAccountPasswordField").value;
var passwordConfirmValue = document.getElementById("createAccountPasswordConfirmField").value;
var publicNameValue = document.getElementById("createAccountPublicNameField").value;
if (emailValue == "") {
errorMessage.innerHTML = "Email cannot be blank!";
return false;
} else if (!(/[^\s@]+@[^\s@]+\.[^\s@]+/.test(emailValue))) {
errorMessage.innerHTML = "Your email address looks fake. Email addresses look like this: name@email.com."
return false;
} else if (passwordValue == "") {
errorMessage.innerHTML = "Password cannot be blank!";
return false;
} else if (passwordValue != passwordConfirmValue) {
errorMessage.innerHTML = "Passwords do not match!";
return false;
} else if (publicNameValue == "") {
errorMessage.innerHTML = "Public Name cannot be blank!";
return false;
} else {
var emailCheck = new XMLHttpRequest();
emailCheck.open('GET', "/php/ajax_createaccountemailcheck.php?email=" + emailValue);
emailCheck.onreadystatechange = function() {
if (emailCheck.readyState == 4 && emailCheck.status == 200) {
if (emailCheck.responseText != "ok") {
errorMessage.innerHTML = "The email address entered is already being used. Try logging in or using a different email address instead.";
return false;
} else {
document.getElementById("createAccountForm").submit();
}
}
}
emailCheck.send();
}
}
function ValidateAccountSettings() {
var errorMessage = document.getElementById("accountSettingsError");
var emailValue = document.getElementById("accountSettingsEmailField").value;
var publicNameValue = document.getElementById("accountSettingsPublicNameField").value;
if (emailValue == "") {
errorMessage.innerHTML = "Email cannot be blank!";
return false;
} else if (!(/[^\s@]+@[^\s@]+\.[^\s@]+/.test(emailValue))) {
errorMessage.innerHTML = "Your email address looks fake. Email addresses look like this: name@email.com."
return false;
} else if (publicNameValue == "") {
errorMessage.innerHTML = "Public Name cannot be blank!";
return false;
} else {
document.getElementById("createAccountForm").submit();
}
}
function ValidateForgotPassword() {
var errorMessage = document.getElementById("forgotError");
var emailValue = document.getElementById("forgotEmailField").value;
if (emailValue == "") {
errorMessage.innerHTML = "Email cannot be blank!";
return false;
} else if (!(/[^\s@]+@[^\s@]+\.[^\s@]+/.test(emailValue))) {
errorMessage.innerHTML = "Your email address looks fake. Email addresses look like this: name@email.com."
return false;
} else {
var emailCheck = new XMLHttpRequest();
emailCheck.open('GET', "/php/ajax_passwordresetemailcheck.php?email=" + emailValue);
emailCheck.onreadystatechange = function() {
if (emailCheck.readyState == 4 && emailCheck.status == 200) {
if (emailCheck.responseText != "email exists") {
errorMessage.innerHTML = "The email address entered is not in use and therefore can't have its password reset. Try <span class='clickable' onclick='ShowInfo(\"loginForm\")'>creating an account</span> instead!";
return false;
} else {
document.getElementById("forgotForm").submit();
}
}
}
emailCheck.send();
}
}
function ValidateResetPassword() {
var errorMessage = document.getElementById("resetPasswordError");
var passwordValue = document.getElementById("newPasswordField").value;
var passwordConfirmValue = document.getElementById("newPasswordConfirmField").value;
if (passwordValue == "") {
errorMessage.innerHTML = "Password cannot be blank!";
return false;
} else if (passwordValue != passwordConfirmValue) {
errorMessage.innerHTML = "Passwords do not match!";
return false;
} else {
document.getElementById("resetPasswordForm").submit();
}
}
function WarnEmailChange() {
var emailChangeWarning = document.getElementById("accountSettingsEmailChangeWarning");
var emailValue = document.getElementById("accountSettingsEmailField").value;
var originalEmailValue = document.getElementById("accountSettingsPreviousEmailField").value;
if (emailValue != originalEmailValue) {
emailChangeWarning.style.display = "block";
} else {
emailChangeWarning.style.display = "none";
}
}
function LoggedInResetPassword() {
var resetPasswordRequest = new XMLHttpRequest();
resetPasswordRequest.open('GET', "/php/ajax_setnewpassword.php");
resetPasswordRequest.onreadystatechange = function() {
if (resetPasswordRequest.readyState == 4 && resetPasswordRequest.status == 200) {
if (resetPasswordRequest.responseText != "done") {
console.log(resetPasswordRequest.responseText);
alert("Error resetting password.\n\nTry again later.");
return false;
} else {
window.location = "./";
}
}
}
resetPasswordRequest.send();
}
function ExplainPublicName() {
alert("This is the name we greet you with. It's also the name displayed if you ever decide to share any of your dictionaries.\n\nNote: this is not a username, and as such is not guaranteed to be unique. Use something people will recognize you as to differentiate from other people who might use the same name!");
}
function ExplainAllowEmails() {
alert("We'll make sure that you're the first to hear about any new features that get added or if any of our policies change for any reason. We'll never spam you or sell your information, but you may need to mark emails from lexicon.ga as not spam to receive them.\nNOTE: Password reset emails will be sent regardless of your choice.");
}
function wordFormIsLocked() {
return document.getElementById("formLockButton").innerHTML == "\uD83D\uDD12";
}
function MobileToggleWordForm() {
var pullout = document.getElementById("mobileWordFormPullout");
ToggleWordFormLock("7%");
if (pullout.innerHTML == "+") {
pullout.innerHTML = "✕";
} else {
pullout.innerHTML = "+";
}
}
function ToggleWordFormLock(topValue) {
if (wordFormIsLocked()) { //If it is already locked, change it to Unlocked and get everything working as it needs to.
UnlockWordForm(topValue);
} else {
LockWordForm();
}
}
function UnlockWordForm(topValue) {
var lockButton = document.getElementById("formLockButton");
var leftColumn = document.getElementById("leftColumn");
var wordForm = document.getElementById("wordEntryForm");
var wordFormWidth = wordForm.offsetWidth;
var leftColumnWidth = leftColumn.offsetWidth;
var leftColumnHeight = leftColumn.offsetHeight;
lockButton.innerHTML = "&#128275;"; // Change to the "Unlocked lock" icon.
wordForm.style.position = "fixed";
wordForm.style.top = (typeof topValue !== 'undefined') ? topValue : document.getElementById("dictionaryColumn").offsetTop.toString() + "px";
wordForm.style.width = wordFormWidth.toString() + "px";
leftColumn.style.width = leftColumnWidth.toString() + "px";
leftColumn.style.height = leftColumnHeight.toString() + "px";
}
function LockWordForm() {
var lockButton = document.getElementById("formLockButton");
var leftColumn = document.getElementById("leftColumn");
var wordForm = document.getElementById("wordEntryForm");
lockButton.innerHTML = "&#128274;"; // Change to the "locked" icon.
leftColumn.removeAttribute('style');
wordForm.removeAttribute('style');
}
function CloseUpdateConflictArea(wordIndexString) {// displayId, hideId) {
// displayId = (typeof displayId !== 'undefined' && displayId != null) ? displayId : false;
// if (displayId != false) {
if (wordIndexString == "") {
document.getElementById("newWordButtonArea").style.display = "block";
} else {
document.getElementById("editWordButtonArea" + wordIndexString).style.display = "block";
}
// }
document.getElementById("updateConflict" + wordIndexString).style.display = "none";
EnableForm(wordIndexString);
}
function DisableForm(wordIndexString) {
document.getElementById("word" + wordIndexString).disabled = true;
document.getElementById("pronunciation" + wordIndexString).disabled = true;
document.getElementById("partOfSpeech" + wordIndexString).disabled = true;
document.getElementById("simpleDefinition" + wordIndexString).disabled = true;
document.getElementById("longDefinition" + wordIndexString).disabled = true;
}
function EnableForm(wordIndexString) {
document.getElementById("word" + wordIndexString).disabled = false;
document.getElementById("pronunciation" + wordIndexString).disabled = false;
document.getElementById("partOfSpeech" + wordIndexString).disabled = false;
document.getElementById("simpleDefinition" + wordIndexString).disabled = false;
document.getElementById("longDefinition" + wordIndexString).disabled = false;
// document.getElementById("editIndex").disabled = false;
}
function ClearForm() {
if (document.getElementById("wordEntryForm")) {
document.getElementById("word").value = "";
document.getElementById("pronunciation").value = "";
document.getElementById("partOfSpeech").value = "";
document.getElementById("simpleDefinition").value = "";
document.getElementById("longDefinition").value = "";
document.getElementById("editIndex").value = "";
document.getElementById("newWordButtonArea").style.display = "block";
document.getElementById("editWordButtonArea").style.display = "none";
document.getElementById("errorMessage").innerHTML = "";
document.getElementById("updateConflict").style.display = "none";
EnableForm("");
}
}
function ToggleDescription() {
var descriptionToggle = document.getElementById("descriptionToggle");
var descriptionArea = document.getElementById("dictionaryDescription");
if (descriptionArea.style.display == "none") {
descriptionArea.style.display = "block";
descriptionToggle.innerHTML = "Hide Description";
} else {
descriptionArea.style.display = "none";
descriptionToggle.innerHTML = "Show Description";
}
}
function ToggleSearchFilter() {
var searchFilterToggle = document.getElementById("searchFilterToggle");
var searchFilterArea = document.getElementById("searchFilterArea");
if (searchFilterArea.style.display == "none") {
searchFilterArea.style.display = "block";
searchFilterToggle.innerHTML = "Hide Search/Filter Options";
} else {
searchFilterArea.style.display = "none";
searchFilterToggle.innerHTML = "Search/Filter Options";
}
}
function ShowInfo(variableName) {
ShowInfoWithText(window[variableName]);
if (variableName == "loginForm") {
// document.getElementById("infoText").innerHTML = loginForm;
if (currentDictionary.words.length > 0 || currentDictionary.name != "New" || currentDictionary.description != "A new dictionary.") {
document.getElementById("dictionaryWarn").innerHTML = "If your current dictionary is not already saved to your account, be sure to <span class='exportWarnText' onclick='ExportDictionary()'>export it before logging in</span> so you don't lose anything!";
}
}
}
function ShowInfoWithText(text) {
document.getElementById("infoText").innerHTML = text;
document.getElementById("infoScreen").style.display = "block";
document.getElementById("infoPage").scrollTop = 0;
HideAccountSettings();
}
function HideInfo() {
document.getElementById("infoScreen").style.display = "none";
}
function ToggleAccountSettings() {
if (document.getElementById("accountSettingsScreen")) {
var accountScreen = document.getElementById("accountSettingsScreen");
if (accountScreen.style.display == "block") {
HideAccountSettings();
} else {
ShowAccountSettings();
}
}
}
function ShowAccountSettings(variableName) {
if (document.getElementById("accountSettingsScreen"))
document.getElementById("accountSettingsScreen").style.display = "block";
HideInfo();
}
function HideAccountSettings() {
if (document.getElementById("accountSettingsScreen"))
document.getElementById("accountSettingsScreen").style.display = "none";
}
function ToggleSettingsScreen(doSave) {
var settingsScreen = document.getElementById("settingsScreen");
if (settingsScreen.style.display == "block") {
if (doSave) {
SaveSettings();
}
HideSettings();
} else {
ShowSettings();
}
}
function ShowSettings() {
document.getElementById("settingsScreen").style.display = "block";
document.getElementById("dictionaryNameEdit").value = htmlEntitiesParse(currentDictionary.name);
document.getElementById("dictionaryDescriptionEdit").value = htmlEntitiesParse(currentDictionary.description);
document.getElementById("dictionaryPartsOfSpeechEdit").value = htmlEntitiesParse(currentDictionary.settings.partsOfSpeech);
document.getElementById("dictionaryAllowDuplicates").checked = currentDictionary.settings.allowDuplicates;
document.getElementById("dictionaryCaseSensitive").checked = currentDictionary.settings.caseSensitive;
document.getElementById("dictionarySortByEquivalent").checked = currentDictionary.settings.sortByEquivalent;
document.getElementById("dictionaryIsComplete").checked = currentDictionary.settings.isComplete;
if (document.getElementById("dictionaryIsPublic")) {
document.getElementById("dictionaryIsPublic").checked = currentDictionary.settings.isPublic;
TogglePublicLink();
}
document.getElementById("numberOfWordsInDictionary").innerHTML = currentDictionary.words.length.toString();
}
function HideSettings() {
document.getElementById("settingsScreen").style.display = "none";
if (currentDictionary.settings.isComplete) {
LockWordForm();
document.getElementById("wordEntryForm").style.display = "none";
} else {
document.getElementById("wordEntryForm").style.display = "block";
}
}
function HideSettingsWhenComplete() {
if (document.getElementById("settingsScreen")) {
if (currentDictionary.settings.isComplete) {
document.getElementById("hideIfComplete").style.display = "none";
} else {
document.getElementById("hideIfComplete").style.display = "block";
}
}
}
function ShowFullScreenTextbox(textboxToExpandId, labelText) {
var sourceTextboxElement = document.getElementById(textboxToExpandId);
var targetTextboxElement = document.getElementById("fullScreenTextbox");
document.getElementById("fullScreenTextboxLabel").innerHTML = labelText;
var selection = getInputSelection(sourceTextboxElement);
document.getElementById("expandedTextboxId").innerHTML = textboxToExpandId;
targetTextboxElement.value = sourceTextboxElement.value;
document.getElementById("fullScreenTextboxScreen").style.display = "block";
setSelectionRange(targetTextboxElement, selection.start, selection.end);
}
function HideFullScreenTextbox() {
var expandedTextboxId = document.getElementById("expandedTextboxId").innerHTML;
var sourceTextboxElement = document.getElementById("fullScreenTextbox");
var targetTextboxElement = document.getElementById(expandedTextboxId);
var selection = getInputSelection(sourceTextboxElement);
targetTextboxElement.value = sourceTextboxElement.value;
document.getElementById("fullScreenTextboxScreen").style.display = "none";
setSelectionRange(targetTextboxElement, selection.start, selection.end);
}
function ShowDictionaryDeleteMenu(dictionaryList) {
document.getElementById('loadAfterDeleteScreen').style.display = 'block';
//Parse response into the list that forces you to load one and reload select in settings.
ParseUserDictionariesIntoSelect(document.getElementById("loadAfterDelete"), dictionaryList);
ParseUserDictionariesIntoSelect(document.getElementById("userDictionaries"), dictionaryList);
}
function ToggleCaseSensitiveOption() {
if (document.getElementById("dictionaryAllowDuplicates").checked) {
document.getElementById("dictionaryCaseSensitive").disabled = true;
} else {
document.getElementById("dictionaryCaseSensitive").disabled = false;
}
}
function TogglePublicLink() {
if (document.getElementById("dictionaryIsPublic").checked) {
var publicLink = "http://lexicon.ga/" + currentDictionary.externalID;
document.getElementById("publicLink").innerHTML = "<strong>Public Link:</strong><br>" + publicLink;
} else {
document.getElementById("publicLink").innerHTML = "";
}
}
function SetPartsOfSpeech (selectId) {
selectId = (typeof selectId !== 'undefined') ? selectId : "partOfSpeech";
var partsOfSpeechSelect = document.getElementById(selectId);
var wordFilterOptions = document.getElementById("filterOptions");
var wordFiltersSelected = GetSelectedFilters();
// Clear parts of speech.
partsOfSpeechSelect.innerHTML = "";
wordFilterOptions.innerHTML = "";
// Insert blank part of speech as first dropdown option.
var blankpartOfSpeechOption = document.createElement('option');
blankpartOfSpeechOption.appendChild(document.createTextNode(""));
blankpartOfSpeechOption.value = " ";
partsOfSpeechSelect.appendChild(blankpartOfSpeechOption);
// Rebuild parts of speech
var newPartsOfSpeech = htmlEntitiesParse(currentDictionary.settings.partsOfSpeech).trim().split(",");
for (var j = 0; j < newPartsOfSpeech.length; j++) {
var thePartOfSpeech = newPartsOfSpeech[j].trim();
var partOfSpeechOption = document.createElement('option');
partOfSpeechOption.appendChild(document.createTextNode(thePartOfSpeech));
partOfSpeechOption.value = thePartOfSpeech;
partsOfSpeechSelect.appendChild(partOfSpeechOption);
var wordFilterLabel = document.createElement('label');
wordFilterLabel.appendChild(document.createTextNode(thePartOfSpeech + " "));
wordFilterLabel['part-of-speech'] = thePartOfSpeech;
wordFilterLabel.className = 'filterOption';
var wordFilterCheckbox = document.createElement('input');
wordFilterCheckbox.type = 'checkbox';
wordFilterCheckbox.onchange = function(){ShowDictionary()};
if (wordFiltersSelected.indexOf(thePartOfSpeech) > -1) wordFilterCheckbox.checked = true;
wordFilterLabel.appendChild(wordFilterCheckbox);
wordFilterOptions.appendChild(wordFilterLabel);
}
// Insert blank part of speech as last filter option
var blankwordFilterLabel = document.createElement('label');
blankwordFilterLabel.appendChild(document.createTextNode("Blanks "));
blankwordFilterLabel['part-of-speech'] = " ";
blankwordFilterLabel.className = 'filterOption';
var blankwordFilterCheckbox = document.createElement('input');
blankwordFilterCheckbox.type = 'checkbox';
blankwordFilterCheckbox.onchange = function(){ShowDictionary()};
if (wordFiltersSelected.indexOf(" ") > -1) blankwordFilterCheckbox.checked = true;
blankwordFilterLabel.appendChild(blankwordFilterCheckbox);
wordFilterOptions.appendChild(blankwordFilterLabel);
}
function GetSelectedFilters() {
var wordFilterOptions = document.getElementById("filterOptions");
var wordFiltersSelected = [];
for (var i = 0; i < wordFilterOptions.children.length; i++) {
var filterOption = wordFilterOptions.children[i];
if (filterOption.children[0].checked) {
wordFiltersSelected.push(filterOption['part-of-speech']);
}
}
return wordFiltersSelected;
}
function ToggleAllFilters(doCheck) {
var wordFilterOptions = document.getElementById("filterOptions");
for (var i = 0; i < wordFilterOptions.children.length; i++) {
wordFilterOptions.children[i].children[0].checked = doCheck;
}
}
function ShowFilterWordCount(numberOfWords) {
var filters = GetSelectedFilters();
var search = htmlEntitiesParseForSearchEntry(document.getElementById("searchBox").value);
var wordCounter = document.getElementById("filterWordCount");
if (filters.length > 0 || search != "") {
wordCounter.innerHTML = "Showing " + numberOfWords.toString() + " result" + ((numberOfWords != 1) ? "s" : "");
} else {
wordCounter.innerHTML = "";
}
}
function NewWordNotification(word) {
var wordId = currentDictionary.nextWordId - 1;
NewNotification("New Word Added: <a href='#" + wordId.toString() + "'>" + word + "</a>");
}
function NewNotification(message) {
var notificationArea = document.getElementById("notificationArea");
var notificationMessage = document.getElementById("notificationMessage");
notificationArea.style.display = "block";
notificationMessage.innerHTML = message;
}
function FocusAfterAddingNewWord() {
document.getElementById("word").focus();
}

149
src/sass/lexiconga.scss Normal file
View File

@ -0,0 +1,149 @@
body {
background: #e6cfaa;
}
header {
background: #eacc9d;
}
tr, thead {
border-bottom: 1px solid #af8050;
}
td, th {
border-right: 1px solid #af8050;
}
a {
text-decoration: underline;
color: #a01000;
}
#siteLogo {
display: block;
text-indent: -9999px;
width: 242px;
height: 48px;
background: url(../images/logo.svg);
background-size: 242px 48px;
float: left;
}
#aboutButton {
}
#loginoutArea {
float: right;
}
#loginoutArea a {
color: #000000;
text-decoration: none;
font-size: 13px;
}
@media screen
and (min-device-width : 481px) {
#headerPadder {
padding: 1px;
}
#loginoutArea {
margin: 16px;
}
}
/* Smartphones (portrait and landscape) ----------- */
@media only screen
and (max-device-width : 480px) {
#siteLogo {
display: block;
text-indent: -9999px;
width: 150px;
height: 30px;
background: url(../images/logo.svg);
background-size: 150px 30px;
float: left;
}
#loginoutArea {
margin: 16px 8px;
}
}
#wordEntryForm {
background: #ba5536;
-webkit-box-shadow: 5px 5px 7px 0px rgba(0,0,0,0.75);
-moz-box-shadow: 5px 5px 7px 0px rgba(0,0,0,0.75);
box-shadow: 5px 5px 7px 0px rgba(0,0,0,0.75);
border: none;
}
input, textarea, select, option {
background: #efdfc0;
}
#announcementArea {
background: #a0c066;
}
#notificationArea {
background: #c0c088;
}
#dictionaryColumn {
background: #bd7251;
border: none;
-webkit-box-shadow: 5px 5px 7px 0px rgba(0,0,0,0.75);
-moz-box-shadow: 5px 5px 7px 0px rgba(0,0,0,0.75);
box-shadow: 5px 5px 7px 0px rgba(0,0,0,0.75);
}
#settingsOptions, #infoPage, #loadAfterDeletePage, #accountSettingsPage, #fullScreenTextboxPage {
background: #f2d5b2;
}
.management {
border-width: 2px;
border: none;
}
#dictionaryName {
text-shadow: 2px 2px 2px #915337;
}
#dictionaryShareLink {
text-shadow: none;
}
#dictionaryDescription {
width: 90%;
background: #f2d5b2;
}
#loginLink, #logoutLink, #descriptionToggle, #searchFilterToggle, #settingsButton, .deleteCancelButton, .deleteConfirmButton, #settingsScreenCloseButton, #infoScreenCloseButton, .clickable, button {
background: #dcb078;
}
entry {
background: #d7ad7d;
border: none;
-webkit-box-shadow: 3px 3px 10px -1px rgba(0,0,0,0.75);
-moz-box-shadow: 3px 3px 10px -1px rgba(0,0,0,0.75);
box-shadow: 3px 3px 10px -1px rgba(0,0,0,0.75);
}
.editButton {
background: #86ac41;
}
.deleteButton {
background: #ba5536;
}
footer {
background: #cb6318;
border: none;
-webkit-box-shadow: 0px -3px 7px -1px rgba(0,0,0,0.75);
-moz-box-shadow: 0px -3px 7px -1px rgba(0,0,0,0.75);
box-shadow: 0px -3px 7px -1px rgba(0,0,0,0.75);
}

134
src/sass/mobile.scss Normal file
View File

@ -0,0 +1,134 @@
/* Smartphones (portrait and landscape) ----------- */
@media screen
and (max-width : 910px) {
body {
font-size: 11pt;
}
header {
height: 70px;
}
footer {
position: relative;
clear: both;
max-height: 100%;
}
#announcementArea, #notificationArea {
width: 80%;
}
#leftColumn {
width: 100%;
margin: 0;
}
#wordEntryForm {
padding: 8px 0;
width: 100%;
max-width: 450px;
margin: 10px auto;
}
#wordEntryForm label {
overflow: hidden;
display: flex;
justify-content: center;
font-size: 10pt;
}
#wordEntryForm label span {
float: left;
width: 30%;
text-align: right;
margin-right: 8px;
}
#wordEntryForm input, #wordEntryForm select, #wordEntryForm textarea {
float: right;
width: 60%;
margin-right: 8px;
align-self: center;
}
.longDefinition {
min-width: 200px;
height: 80px;
}
#wordEntryForm button {
display: block;
width: 50%;
height: 30px;
margin: 0px auto;
}
#mobileWordFormPullout {
position: fixed;
top: 7%;
left: 0;
width: 32px;
height: 32px;
font-size: 20px;
font-weight: bold;
text-align: center;
padding: 6px;
background: #86ac41;
-webkit-box-shadow: 5px 5px 7px 0px rgba(0,0,0,0.75);
-moz-box-shadow: 5px 5px 7px 0px rgba(0,0,0,0.75);
box-shadow: 5px 5px 7px 0px rgba(0,0,0,0.75);
border: none;
cursor: pointer;
}
#dictionaryColumn {
width: 100%;
margin: 0;
padding: 0;
}
#dictionaryContent {
margin: 0 auto;
padding: 15px;
}
#dictionaryDescription {
margin: 0 auto;
}
#searchFilterArea {
width: 90%;
min-width: 200px;
padding: 10px 10px 3px;
margin: 0 auto;
}
.fixedFade {
z-index: 5;
}
.fixedPage {
z-index: 10;
}
entry {
margin: 0 auto 5px;
}
#formLockButton {
display: none;
}
#showFullScreenTextbox {
display: none;
}
#settingsSaveButtons {
position: relative;
right: 0;
bottom: 0;
clear: both;
width: 100%;
}
}

453
src/sass/styles.scss Normal file
View File

@ -0,0 +1,453 @@
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
html {
width: 100%;
}
body {
width: 100%;
padding: 0;
margin: 0;
border: none;
font-family: "Helvetica", Arial, sans-serif;
}
contents {
display: block;
width: 100%;
}
header {
height: 50px;
width: 100%;
margin: 0 0 10px;
position: relative;
top: 0px;
left: 0px;
right: 0px;
border: none;
padding: 0;
-webkit-box-shadow: 0px 3px 10px -1px rgba(0,0,0,0.75);
-moz-box-shadow: 0px 3px 10px -1px rgba(0,0,0,0.75);
box-shadow: 0px 3px 10px -1px rgba(0,0,0,0.75);
}
footer {
width: 100%;
text-align: center;
vertical-align: middle;
position:fixed;
bottom: 0px;
left: 0px;
background: #aaaaaa;
padding: 0;
max-height: 32px; /* Update Dictionary Container's bottom margin to account for footer */
}
#footer-content {
padding: 8px;
}
table {
border-collapse: collapse;
width: 100%;
}
tr, thead {
border-bottom: 1px solid #afafaf;
}
tr:last-child {
border-bottom: none;
}
td, th {
border-right: 1px solid #afafaf;
padding: 3px 10px;
}
td:last-child, th:last-child {
border-right: none;
}
.inline {
display: inline !important;
}
#leftColumn {
float: left;
width: 25%;
margin: 15px 0 15px 15px;
}
form {
padding: 15px;
}
#wordEntryForm {
max-width: 400px;
min-width: 260px;
}
.wbr:after {
content: "\00200B";
}
label {
display: block;
margin-bottom: 10px;
}
label span {
display: block;
font-weight: bold;
}
label label {
margin-left: 20px;
}
label span.checkboxlabel {
display: inline;
margin-left: 10px;
}
input, textarea {
display: block;
padding: 2px 0 2px 5px;
border: none;
margin: 2px 0;
}
input[type=checkbox] {
display: inline;
margin: 5px;
}
.longDefinition {
width: 100%;
min-width: 230px;
height: 150px;
}
#updateConflict {
width: 260px;
}
#errorMessage, #updateConflictMessage, #settingsErrorMessage {
display: block;
color: maroon;
font-weight: bold;
}
#dictionaryWarn {
margin-top: 10px;
font-size: 12px;
font-weight: bold;
font-style: italic;
}
.exportWarnText {
display: inline;
color: red;
cursor: pointer;
text-decoration: underline;
}
#formLockButton {
float: right;
}
#createAccountSubmitButton, #accountSettingsSubmitButton {
margin-top: 10px;
}
#aboutButton {
display: inline;
margin: 0 10px 0 0;
}
#announcementArea, #notificationArea {
text-align:center;
padding:10px;
margin: 0 auto 5px;
width:50%;
min-width:200px;
-webkit-box-shadow: 5px 5px 7px 0px rgba(0,0,0,0.75);
-moz-box-shadow: 5px 5px 7px 0px rgba(0,0,0,0.75);
box-shadow: 5px 5px 7px 0px rgba(0,0,0,0.75);
}
#dictionaryColumn {
width: 50%;
margin: 15px 0 36px 15px; /* bottom margin must clear footer */
padding: 0;
float: left;
}
#dictionaryContent {
width: 100%;
min-width: 260px;
max-width: 800px;
padding: 15px;
}
#dictionaryName {
margin: 0 0 5px;
}
#dictionaryShareLink {
margin-left: 10px;
vertical-align: middle;
text-decoration: none;
}
#dictionaryDescription {
width: 100%;
max-height: 400px;
overflow-y: auto;
padding: 15px;
border: none;
margin: 10px;
}
.clickable, button {
display: inline;
font-weight: bold;
font-size: 13px;
padding: 5px;
border: none;
background: #dddddd;
}
.clickable, button {
cursor: pointer;
}
.inline-button {
font-size: 11px;
padding: 2px 4px;
}
.toggleButton {
display: inline-block;
margin: 8px;
font-weight: bold;
font-size: 12px;
}
.searchOption, .filterOption {
font-size:12px;
display: inline-block;
margin: 0 8px 0 0;
}
#wordFilter {
margin: 10px 0;
}
#filterWordCount {
margin: 10px 10px;
display: block;
font-weight: bold;
font-style: italic;
}
entry {
display: block;
width: 90%;
min-width: 200px;
padding: 10px 10px 3px;
margin-bottom: 5px;
}
.wordLink {
text-decoration: none;
float: right;
font-size: 13px;
padding: 2px;
line-height: 10px;
}
word {
font-weight: bold;
font-size: 20px;
}
pronunciation {
font-size: 12px;
margin-left:10px;
}
partofspeech {
font-style: italic;
font-weight: bold;
font-size: 10px;
margin-left:10px;
}
simpledefinition {
display: block;
font-style: italic;
}
longdefinition {
display: block;
margin-left: 20px;
}
longDefinition h1, longDefinition h2, longDefinition h3, longDefinition h4, longDefinition h5, longDefinition h6 {
margin: 5px 0 8px;
font-weight: bold;
}
longDefinition h1 {
font-size: 22px;
}
longDefinition h2 {
font-size: 20px;
}
longDefinition h3 {
font-size: 20px;
font-weight: normal;
}
longDefinition h4 {
font-size: 18px;
}
longDefinition h5 {
font-size: 18px;
font-weight: normal;
}
longDefinition h6 {
font-size: 17px;
}
longDefinition p {
margin: 3px 0 8px;
}
searchTerm {
display: inline;
color: #ff0000;
background: #ffff00;
padding: 1px;
text-decoration: underline;
font-style: italic;
font-weight: bold;
}
.management {
display: block;
right: 5px;
width: 100px;
padding: 3px;
border: inset 3px;
margin: 10px;
}
.editButton, .deleteButton, .deleteConfirmButton, .deleteCancelButton {
display: inline;
font-size: 10px;
margin: 5px;
}
.deleteConfirm {
display: block;
font-size: 10px;
margin: 10px;
}
.fixedFade {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #000000;
opacity: 0.6;
}
.fixedPage {
position: fixed;
top: 5%;
left: 6%;
right: 6%;
bottom: 10%;
min-width: 260px;
min-height: 260px;
padding: 5px 5% 5%;
overflow-y: auto;
overflow-x: hidden;
background: #ffffff;
opacity: 1;
border: none;
-webkit-box-shadow: 5px 5px 7px 0px rgba(0,0,0,0.75);
-moz-box-shadow: 5px 5px 7px 0px rgba(0,0,0,0.75);
box-shadow: 5px 5px 7px 0px rgba(0,0,0,0.75);
}
.rightButton {
float: right;
font-size: 12px;
}
#fullScreenTextboxPage {
padding: 5px 3% 4%;
overflow-y: hidden;
}
#fullScreenTextbox {
position: relative;
width: 100%;
height: 100%;
}
#settingsForm {
width: 100%;
padding: 0;
margin: 0;
}
#publicLink {
font-size:12px;
font-style: italic;
}
#dictionaryDescriptionEdit, #dictionaryPartsOfSpeechEdit {
width: 100%;
max-width: 360px;
min-width: 200px;
}
#dictionaryDescriptionEdit {
height: 200px;
}
#settingsErrorMessage {
float: right;
clear: both;
}
#settingsSaveButtons {
position: absolute;
right: 10%;
bottom: 8%;
font-size: 14px;
display: block;
width: 50%;
}
.settingsCol {
display: block;
float: left;
width: 30%;
min-width: 260px;
max-width: 400px;
margin: 0 30px 0 0;
}