diff --git a/.gitignore b/.gitignore index 9b42e40..9dbb225 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ php/google/ -images/favicon.png -images/lexiconga.png +ipa_character_picker/ diff --git a/README.md b/README.md index 7dec896..3bb64a9 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ It accepts Unicode characters so you can utilize whatever typable characters you When you have a brand new, empty dictionary, the first thing you'll probably want to do is change the title to whatever your conlang is called and add at least a little description of what your language is like or how to use it. You can do this by clicking on the Settings button, which will open up the settings screen. Here, you will find all the fields you need to update your dictionary's Name and Description/Rules. The Description/Rules text area uses [Markdown](https://help.github.com/articles/markdown-basics/) to format any text you include, so brush up on how to do basic things in Markdown before you get started _(NOTE: a line break is done by adding 2 or more spaces to the end of the line and then going to the next line!)_. After this, make sure that the Parts of Speech are adequate for your language _(see below for more information about this)_. Update these fields to what you want them to say and click the "Save" button to keep the Settings menu open, or the "Save and Close" button to close the menu and start adding words! To add words, just use the form on the top left side of the window. Hopefully the form is self-explanatory, but if not, here's a little guide: -Enter the word in your language in the "Word" field, an equivalent word or short definition in the "Equivalent Word" field, a longer definition or fuller explanation of the word using [Markdown](https://help.github.com/articles/markdown-basics/) in the "Explanation" text area, choose a part of speech, and click "Add Word". Your word will instantly appear in your dictionary under the dictionary's name! You can add as many words as you want this way. -The only things to remember while adding new words is that the minimum information that you can enter is the Word itself and either the Equivalent Word OR the Explanation. You can have both of these or just one, but you need at least one. If you do not want to use the Parts of Speech, you do not need to, though you will miss out on the handy Filter feature of the dictionary. +Enter the word in your language in the "Word" field, the pronunciation of the word in the "Pronunciation" field, choose a Part of Speech, enter an equivalent word/short definition in the "Equivalent Word(s)" field and/or a longer definition or fuller explanation of the word using [Markdown](https://help.github.com/articles/markdown-basics/) in the "Explanation/Long Definition" text area, and click "Add Word". Your word will instantly appear in your dictionary under the dictionary's name! You can add as many words as you want this way. +The only things to remember while adding new words is that the minimum information that you can enter is the Word itself and either the Equivalent Word OR the Explanation. You can have both of these or just one, but you need at least one. If you do not want to use the Pronunciation or Parts of Speech then you do not need to, though if you leave out Part of Speech, you will miss out on the handy Filter feature of the dictionary. And that's all you need to get started! Everything else should be pretty self-explanatory, but a full explanation of Dictionary Builder and all of its functions continues below. @@ -20,7 +20,9 @@ And that's all you need to get started! Everything else should be pretty self-ex After you enter a markdown-formatted description/rules in the Settings menu, you can view the formatted version by clicking the "Show Description" button under your dictionary's name. You can hide it again by clicking "Hide Description" when the description is displayed. ### Entry Management -After adding some words to your dictionary, you'll notice an "Edit" and "Delete" button attached to each entry. +After adding some words to your dictionary, you'll notice a link icon (🔗) and an "Edit" and "Delete" button attached to each entry. + +The link icon (🔗) is a link to that word. These links only work when there is nothing entered in the search box and no filters are set. Also note that the links are only intended for linking within the same dictionary and will only work properly when your dictionary is loaded, so only share them with friends if your friends also have your dictionary imported. The **Edit** button will scroll to the top of the screen and fill the Word form with the current details of the word you edited. You can make any changes you want and click the "Edit Word" button. You will be asked to confirm your changes, and once you do, your word will be saved. If you do not want to make changes, just click the "Cancel" button. @@ -47,6 +49,9 @@ The **Import Dictionary** form allows you to upload and view any previously-expo The **Empty Current Dictionary** should only be used if you want to completely start over from scratch. It will ask you to confirm that you want to delete, and if you confirm, your dictionary will be gone forever. If you have not exported your dictionary before emptying it, there will be absolutely no way to get it back. Please be careful with this! +## Problems or Requests +Please report any problems you come across to the [Dictionary Builder Issues page](https://github.com/Alamantus/DictionaryBuilder/issues). You can also submit enhancement requests to the same place if you have any requests for new features. + ## Future Plans In the future, I'm planning to add the ability to save more than one dictionary at a time by allowing user accounts. Each account will be able to store a certain number of dictionaries and will be able to switch to any saved dictionary at any time without having to worry about exporting and importing .dict files. Along with this will also come the ability to easily share dictionaries if you want, but all dictionaries will be private by default. @@ -57,4 +62,4 @@ I hope you enjoy Lexiconga and that it helps you build some awesome languages. ### Libraries Used * [Markdown.js](https://github.com/evilstreak/markdown-js) by Dominic Baggott (a.k.a. evilstreak) -* [Defiant.js](http://defiantjs.com) by Hakan Bilgin (a.k.a. hbi99) \ No newline at end of file +* [Defiant.js](http://defiantjs.com) by Hakan Bilgin (a.k.a. hbi99) diff --git a/css/lexiconga.css b/css/lexiconga.css index ccc61b2..56a47b3 100644 --- a/css/lexiconga.css +++ b/css/lexiconga.css @@ -73,6 +73,10 @@ input, textarea, select, option, button { background: #efdfc0; } +#notificationArea { + background:#c0c088; +} + #dictionaryContainer { background: #bd7251; padding: 15px; @@ -100,7 +104,8 @@ input, textarea, select, option, button { #loginLink, #logoutLink, #descriptionToggle, #settingsButton, .deleteCancelButton, .deleteConfirmButton, -#settingsScreenCloseButton, #infoScreenCloseButton { +#settingsScreenCloseButton, #infoScreenCloseButton, +.helperlink { background: #e0c19c; } diff --git a/css/styles.css b/css/styles.css index 73610fc..f9c3785 100644 --- a/css/styles.css +++ b/css/styles.css @@ -22,6 +22,10 @@ footer { max-height: 32px; /* Update Dictionary Container's bottom margin to account for footer */ } +.inline { + display: inline !important; +} + /* Smartphones (portrait and landscape) ----------- */ @media only screen and (min-device-width : 320px) @@ -63,6 +67,10 @@ label span { font-weight: bold; } +label span .helperlink { + font-size: 10px; +} + label label { margin-left: 20px; } @@ -103,6 +111,15 @@ input[type=checkbox] { margin: 0 10px 0 0; } +#notificationArea { + text-align:center; + padding:10px; + border-radius:5px; + margin:0 auto; + width:50%; + min-width:200px; +} + #dictionaryContainer { margin: 15px 0 36px 15px; /* bottom margin must clear footer */ width: 60%; @@ -124,14 +141,18 @@ input[type=checkbox] { margin: 10px; } -.clickable { +.clickable, .helperlink { + display: inline; font-weight: bold; - cursor: pointer; padding: 4px; background: #dddddd; border-radius: 5px; } +.clickable { + cursor: pointer; +} + #descriptionToggle { font-weight: bold; font-size: 12px; @@ -151,14 +172,29 @@ entry { 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 { @@ -263,6 +299,7 @@ searchTerm { border: 1px solid black; } +#notificationCloseButton, #settingsButton, #settingsScreenCloseButton, #settingsSaveButtons button, #infoScreenCloseButton { float: right; diff --git a/index.php b/index.php index e018be6..b84672c 100644 --- a/index.php +++ b/index.php @@ -110,25 +110,27 @@ elseif (isset($_GET['loggedout']) && $current_user <= 0) { - -
- -
- +
;"> + Close +
+
- -

@@ -240,7 +247,7 @@ elseif (isset($_GET['loggedout']) && $current_user <= 0) {
@@ -249,13 +256,19 @@ elseif (isset($_GET['loggedout']) && $current_user <= 0) { - - + + + \ No newline at end of file diff --git a/js/dictionaryBuilder.js b/js/dictionaryBuilder.js index 58fbb16..1d0b586 100644 --- a/js/dictionaryBuilder.js +++ b/js/dictionaryBuilder.js @@ -9,18 +9,17 @@ var currentDictionary = { 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 - }, - externalID: 0, - fileIdentifier: "Lexiconga Dictionary" -}; + } +} var defaultDictionaryJSON = JSON.stringify(currentDictionary); //Saves a stringifyed default dictionary. -var previousDictionary = {}; var savedScroll = { x: 0, @@ -147,10 +146,11 @@ function GetTextFile(filename) { } function AddWord() { - var word = htmlEntities(document.getElementById("word").value); - var simpleDefinition = htmlEntities(document.getElementById("simpleDefinition").value); + 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 partOfSpeech = htmlEntities(document.getElementById("partOfSpeech").value); var editIndex = htmlEntities(document.getElementById("editIndex").value); var errorMessageArea = document.getElementById("errorMessage"); var errorMessage = ""; @@ -160,14 +160,12 @@ function AddWord() { var wordIndex = (!currentDictionary.settings.allowDuplicates) ? WordIndex(word) : -1; if (editIndex != "") { - if (WordAtIndexWasChanged(editIndex, word, simpleDefinition, longDefinition, partOfSpeech)) { + if (WordAtIndexWasChanged(editIndex, word, pronunciation, partOfSpeech, simpleDefinition, longDefinition)) { updateConflictArea.style.display = "block"; updateConflictArea.innerHTML = "Do you really want to change the word \"" + currentDictionary.words[parseInt(editIndex)].name + "\" to what you have set above?"; - updateConflictArea.innerHTML += ''; + updateConflictArea.innerHTML += ''; updateConflictArea.innerHTML += ''; } else { errorMessage = "No change has been made to \"" + word + "\""; @@ -176,7 +174,7 @@ function AddWord() { } } } else if (wordIndex >= 0) { - if (currentDictionary.words[wordIndex].simpleDefinition != simpleDefinition || currentDictionary.words[wordIndex].longDefinition != longDefinition || currentDictionary.words[wordIndex].partOfSpeech != partOfSpeech) { + if (WordAtIndexWasChanged(wordIndex, word, pronunciation, partOfSpeech, simpleDefinition, longDefinition)) { updateConflictArea.style.display = "block"; var updateConflictText = "\"" + word + "\" is already in the dictionary"; @@ -186,11 +184,9 @@ function AddWord() { updateConflictText += "." } updateConflictText += "
Do you want to update it to what you have set above?
"; - updateConflictText += ''; + updateConflictText += ''; updateConflictText += ' '; updateConflictArea.innerHTML = updateConflictText; @@ -201,11 +197,12 @@ function AddWord() { } } } else { - currentDictionary.words.push({name: word, simpleDefinition: simpleDefinition, longDefinition: longDefinition, partOfSpeech: partOfSpeech}); - SaveAndUpdateDictionary(false, true); + currentDictionary.words.push({name: word, pronunciation: pronunciation, partOfSpeech: partOfSpeech, simpleDefinition: simpleDefinition, longDefinition: longDefinition, wordId: currentDictionary.nextWordId++}); + FocusAfterAddingNewWord(); + NewWordNotification(word); + SaveAndUpdateDictionary(false); } - errorMessageArea.innerHTML = ""; } else { if (word == "") { @@ -223,12 +220,13 @@ function AddWord() { errorMessageArea.innerHTML = errorMessage; } -function WordAtIndexWasChanged(indexString, word, simpleDefinition, longDefinition, partOfSpeech) { +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 != partOfSpeech || currentDictionary.words[parseInt(indexString)].simpleDefinition != simpleDefinition || - currentDictionary.words[parseInt(indexString)].longDefinition != longDefinition || - currentDictionary.words[parseInt(indexString)].partOfSpeech != partOfSpeech; + currentDictionary.words[parseInt(indexString)].longDefinition != longDefinition; } function SaveScroll() { @@ -248,18 +246,22 @@ function EditWord(index) { document.getElementById("editIndex").value = index.toString(); document.getElementById("word").value = htmlEntitiesParse(currentDictionary.words[index].name); + document.getElementById("pronunciation").value = htmlEntitiesParse(currentDictionary.words[index].pronunciation); + document.getElementById("partOfSpeech").value = htmlEntitiesParse(currentDictionary.words[index].partOfSpeech); document.getElementById("simpleDefinition").value = htmlEntitiesParse(currentDictionary.words[index].simpleDefinition); document.getElementById("longDefinition").value = htmlEntitiesParse(currentDictionary.words[index].longDefinition); - document.getElementById("partOfSpeech").value = htmlEntitiesParse(currentDictionary.words[index].partOfSpeech); document.getElementById("newWordButtonArea").style.display = "none"; document.getElementById("editWordButtonArea").style.display = "block"; } -function SaveAndUpdateDictionary(keepFormContents, sendWords) { - sendWords = (typeof sendWords !== 'undefined') ? sendWords : false; - currentDictionary.words.sort(dynamicSort("name")); - SaveDictionary(true, sendWords); +function SaveAndUpdateDictionary(keepFormContents) { + if (!currentDictionary.settings.sortByEquivalent) { + currentDictionary.words.sort(dynamicSort("name")); + } else { + currentDictionary.words.sort(dynamicSort("simpleDefinition")); + } + SaveDictionary(); ShowDictionary(); if (!keepFormContents) { ClearForm(); @@ -267,13 +269,14 @@ function SaveAndUpdateDictionary(keepFormContents, sendWords) { CloseUpdateConflictArea(); } -function UpdateWord(wordIndex, word, simpleDefinition, longDefinition, partOfSpeech) { +function UpdateWord(wordIndex, word, pronunciation, partOfSpeech, simpleDefinition, longDefinition) { currentDictionary.words[wordIndex].name = word; + currentDictionary.words[wordIndex].pronunciation = pronunciation; + currentDictionary.words[wordIndex].partOfSpeech = partOfSpeech; currentDictionary.words[wordIndex].simpleDefinition = simpleDefinition; currentDictionary.words[wordIndex].longDefinition = longDefinition; - currentDictionary.words[wordIndex].partOfSpeech = partOfSpeech; - SaveAndUpdateDictionary(false, true); + SaveAndUpdateDictionary(); window.scroll(savedScroll.x, savedScroll.y); } @@ -284,24 +287,7 @@ function DeleteWord(index) { currentDictionary.words.splice(index, 1); - SaveAndUpdateDictionary(true, true); -} - -function CloseUpdateConflictArea() { - document.getElementById("updateConflict").style.display = "none"; -} - -function ClearForm() { - document.getElementById("word").value = ""; - document.getElementById("simpleDefinition").value = ""; - document.getElementById("longDefinition").value = ""; - document.getElementById("partOfSpeech").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"; + SaveAndUpdateDictionary(true); } function UpdateFilter() { @@ -314,28 +300,17 @@ function ShowDictionary() { var searchResults = []; var search = htmlEntities(document.getElementById("searchBox").value); if (search != "") { + var xpath = []; if (document.getElementById("searchOptionWord").checked) { - var wordNameSearch = JSON.search(currentDictionary, '//words[contains(name, "' + search + '")]/name'); - for (var i = 0; i < wordNameSearch.length; i++) { - searchResults.push(wordNameSearch[i]); - } + xpath.push('contains(name, "'+ search +'")'); } if (document.getElementById("searchOptionSimple").checked) { - var simpleDefinitionSearch = JSON.search(currentDictionary, '//words[contains(simpleDefinition, "' + search + '")]/name'); - for (var i = 0; i < simpleDefinitionSearch.length; i++) { - if (searchResults.indexOf(simpleDefinitionSearch[i]) < 0) { - searchResults.push(simpleDefinitionSearch[i]); - } - } + xpath.push('contains(simpleDefinition, "'+ search +'")'); } if (document.getElementById("searchOptionLong").checked) { - var longDefinitionSearch = JSON.search(currentDictionary, '//words[contains(longDefinition, "' + search + '")]/name'); - for (var i = 0; i < longDefinitionSearch.length; i++) { - if (searchResults.indexOf(longDefinitionSearch[i]) < 0) { - searchResults.push(longDefinitionSearch[i]); - } - } + xpath.push('contains(longDefinition, "'+ search +'")'); } + searchResults = JSON.search(currentDictionary, '//words['+ xpath.join(' or ') +']/name'); } var dictionaryNameArea = document.getElementById("dictionaryName"); @@ -350,7 +325,13 @@ function ShowDictionary() { if (currentDictionary.words.length > 0) { for (var i = 0; i < currentDictionary.words.length; i++) { if (filter == "" || (filter != "" && currentDictionary.words[i].partOfSpeech == filter)) { - if (search == "" || (search != "" && searchResults.indexOf(currentDictionary.words[i].name) >= 0)) { + if (search == "" || (search != "" && searchResults.indexOf(htmlEntities(currentDictionary.words[i].name)) >= 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); } } @@ -362,29 +343,20 @@ function ShowDictionary() { dictionaryArea.innerHTML = dictionaryText; } -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 DictionaryEntry(itemIndex) { - var entryText = ""; + var entryText = "🔗"; var searchTerm = htmlEntities(document.getElementById("searchBox").value); var searchRegEx = new RegExp(searchTerm, "gi"); entryText += "" + ((searchTerm != "" && document.getElementById("searchOptionWord").checked) ? currentDictionary.words[itemIndex].name.replace(searchRegEx, "" + searchTerm + "") : currentDictionary.words[itemIndex].name) + ""; - + + if (currentDictionary.words[itemIndex].pronunciation != "") { + entryText += "" + markdown.toHTML(htmlEntitiesParse(currentDictionary.words[itemIndex].pronunciation)).replace("

","").replace("

","") + "
"; + } + if (currentDictionary.words[itemIndex].partOfSpeech != "") { - entryText += " " + currentDictionary.words[itemIndex].partOfSpeech + ""; + entryText += "" + currentDictionary.words[itemIndex].partOfSpeech + ""; } entryText += "
"; @@ -422,43 +394,6 @@ function ManagementArea(itemIndex) { return managementHTML; } -function ShowInfo(text) { - if (text == "terms") { - document.getElementById("infoText").innerHTML = termsText; - } else if (text == "privacy") { - document.getElementById("infoText").innerHTML = privacyText; - } else if (text == "login" || text == "create") { - document.getElementById("infoText").innerHTML = loginForm; - } else { - document.getElementById("infoText").innerHTML = aboutText; - } - document.getElementById("infoPage").scrollTop = 0; - document.getElementById("infoScreen").style.display = "block"; -} - -function HideInfo() { - document.getElementById("infoScreen").style.display = "none"; -} - -function ToggleCaseSensitiveOption() { - if (document.getElementById("dictionaryAllowDuplicates").checked) { - document.getElementById("dictionaryCaseSensitive").disabled = true; - } else { - document.getElementById("dictionaryCaseSensitive").disabled = false; - } -} - -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("dictionaryIsComplete").checked = currentDictionary.settings.isComplete; - document.getElementById("numberOfWordsInDictionary").innerHTML = currentDictionary.words.length.toString(); -} - function SaveSettings() { if (htmlEntities(document.getElementById("dictionaryNameEdit").value) != "") { currentDictionary.name = htmlEntities(document.getElementById("dictionaryNameEdit").value); @@ -471,19 +406,13 @@ function SaveSettings() { 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; HideSettingsWhenComplete(); - SaveAndUpdateDictionary(true, false); -} - -function HideSettingsWhenComplete() { - if (currentDictionary.settings.isComplete) { - document.getElementById("hideIfComplete").style.display = "none"; - } else { - document.getElementById("hideIfComplete").style.display = "block"; - } + SaveAndUpdateDictionary(true); } function CheckForPartsOfSpeechChange () { @@ -495,48 +424,16 @@ function CheckForPartsOfSpeechChange () { } } -function SetPartsOfSpeech () { - var partsOfSpeechSelect = document.getElementById("partOfSpeech"); - var wordFilterSelect = document.getElementById("wordFilter"); - if (partsOfSpeechSelect.options.length > 0) { - for (var i = partsOfSpeechSelect.options.length - 1; i >= 0; i--) { - partsOfSpeechSelect.removeChild(partsOfSpeechSelect.options[i]); - wordFilterSelect.removeChild(wordFilterSelect.options[i + 1]); - } - } - var newPartsOfSpeech = htmlEntitiesParse(currentDictionary.settings.partsOfSpeech).trim().split(","); - for (var j = 0; j < newPartsOfSpeech.length; j++) { - var partOfSpeechOption = document.createElement('option'); - partOfSpeechOption.appendChild(document.createTextNode(newPartsOfSpeech[j].trim())); - partOfSpeechOption.value = newPartsOfSpeech[j].trim(); - partsOfSpeechSelect.appendChild(partOfSpeechOption); - - var wordFilterOption = document.createElement('option'); - wordFilterOption.appendChild(document.createTextNode(newPartsOfSpeech[j].trim())); - wordFilterOption.value = newPartsOfSpeech[j].trim(); - wordFilterSelect.appendChild(wordFilterOption); - } -} - -function HideSettings() { - document.getElementById("settingsScreen").style.display = "none"; - document.getElementById("wordEntryForm").style.display = (currentDictionary.settings.isComplete) ? "none" : "block"; -} - -function ConfirmEmptyWholeDictionary() { - 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?")) { - EmptyWholeDictionary(); - } -} - function EmptyWholeDictionary() { - currentDictionary = JSON.parse(defaultDictionaryJSON); - SaveAndUpdateDictionary(false, true); - SetPartsOfSpeech(); - HideSettings(); + 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?")) { + currentDictionary = JSON.parse(defaultDictionaryJSON); + SaveAndUpdateDictionary(false); + SetPartsOfSpeech(); + HideSettings(); + } } -function SaveDictionary(sendToDatabase, sendWords) { +function SaveDictionary() { localStorage.setItem('dictionary', JSON.stringify(currentDictionary)); //Always save local copy of current dictionary, but if logged in also send to database. @@ -656,6 +553,10 @@ function LoadLocalDictionary() { } function ProcessLoad() { + if (!currentDictionary.hasOwnProperty("nextWordId")) { + currentDictionary.nextWordId = currentDictionary.words.length + 1; + } + HideSettingsWhenComplete(); ShowDictionary(); @@ -690,43 +591,54 @@ function ExportDictionary() { download(downloadName + ".dict", localStorage.getItem('dictionary')); } -function ConfirmImportDictionary() { - if (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?")) { - ImportDictionary(); - } -} - function ImportDictionary() { - 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) { - if (reader.result.substr(reader.result.length - 40) == '"fileIdentifier":"Lexiconga Dictionary"}') { - localStorage.setItem('dictionary', reader.result); - document.getElementById("importFile").value = ""; - LoadLocalDictionary(); - SendDictionary(true); - ProcessLoad(); - HideSettings(); - } else { - alert("Uploaded file is not compatible."); - } - } else { - alert("Upload Failed"); - } - reader = null; + if (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")) + { + localStorage.setItem('dictionary', reader.result); + document.getElementById("importFile").value = ""; + LoadLocalDictionary(); + SendDictionary(true); + ProcessLoad(); + HideSettings(); + } 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."); } - } else { - alert("You must add a file to import."); } } @@ -758,7 +670,7 @@ function dynamicSort(property) { property = property.substr(1); } return function (a, b) { - var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0; + var result = (a[property].toLowerCase() < b[property].toLowerCase()) ? -1 : (a[property].toLowerCase() > b[property].toLowerCase()) ? 1 : 0; return result * sortOrder; } } diff --git a/js/ui.js b/js/ui.js new file mode 100644 index 0000000..9f0589e --- /dev/null +++ b/js/ui.js @@ -0,0 +1,114 @@ +function CloseUpdateConflictArea() { + document.getElementById("updateConflict").style.display = "none"; +} + +function ClearForm() { + 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"; +} + +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 ShowInfo(text) { + if (text == "terms") { + document.getElementById("infoText").innerHTML = termsText; + } else if (text == "privacy") { + document.getElementById("infoText").innerHTML = privacyText; + } else { + document.getElementById("infoText").innerHTML = aboutText; + } + document.getElementById("infoPage").scrollTop = 0; + document.getElementById("infoScreen").style.display = "block"; +} + +function HideInfo() { + document.getElementById("infoScreen").style.display = "none"; +} + +function ToggleCaseSensitiveOption() { + if (document.getElementById("dictionaryAllowDuplicates").checked) { + document.getElementById("dictionaryCaseSensitive").disabled = true; + } else { + document.getElementById("dictionaryCaseSensitive").disabled = false; + } +} + +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; + document.getElementById("numberOfWordsInDictionary").innerHTML = currentDictionary.words.length.toString(); +} + +function HideSettingsWhenComplete() { + if (currentDictionary.settings.isComplete) { + document.getElementById("hideIfComplete").style.display = "none"; + } else { + document.getElementById("hideIfComplete").style.display = "block"; + } +} + +function SetPartsOfSpeech () { + var partsOfSpeechSelect = document.getElementById("partOfSpeech"); + var wordFilterSelect = document.getElementById("wordFilter"); + if (partsOfSpeechSelect.options.length > 0) { + for (var i = partsOfSpeechSelect.options.length - 1; i >= 0; i--) { + partsOfSpeechSelect.removeChild(partsOfSpeechSelect.options[i]); + wordFilterSelect.removeChild(wordFilterSelect.options[i + 1]); + } + } + var newPartsOfSpeech = htmlEntitiesParse(currentDictionary.settings.partsOfSpeech).trim().split(","); + for (var j = 0; j < newPartsOfSpeech.length; j++) { + var partOfSpeechOption = document.createElement('option'); + partOfSpeechOption.appendChild(document.createTextNode(newPartsOfSpeech[j].trim())); + partOfSpeechOption.value = newPartsOfSpeech[j].trim(); + partsOfSpeechSelect.appendChild(partOfSpeechOption); + + var wordFilterOption = document.createElement('option'); + wordFilterOption.appendChild(document.createTextNode(newPartsOfSpeech[j].trim())); + wordFilterOption.value = newPartsOfSpeech[j].trim(); + wordFilterSelect.appendChild(wordFilterOption); + } +} + +function HideSettings() { + document.getElementById("settingsScreen").style.display = "none"; + document.getElementById("wordEntryForm").style.display = (currentDictionary.settings.isComplete) ? "none" : "block"; +} + +function NewWordNotification(word) { + var notificationArea = document.getElementById("notificationArea"); + var notificationMessage = document.getElementById("notificationMessage"); + var wordId = currentDictionary.nextWordId - 1; + notificationArea.style.display = "block"; + notificationMessage.innerHTML = "New Word Added: " + word + ""; +} + +function FocusAfterAddingNewWord() { + document.getElementById("word").focus(); +} \ No newline at end of file diff --git a/notification.php b/notification.php new file mode 100644 index 0000000..e69de29