1
0
Fork 0
mirror of https://github.com/Alamantus/Lexiconga.git synced 2025-04-29 14:53:16 +02:00

Remove everything to start a full rewrite.

This commit is contained in:
Robbie Antenesse 2017-04-03 22:24:14 -06:00
parent 09626a9e0f
commit a3437771f5
76 changed files with 669 additions and 13400 deletions

View file

@ -1,4 +0,0 @@
{
"presets": [ "es2015" ],
"plugins": [ "inferno" ]
}

7
.gitignore vendored
View file

@ -1,4 +1,5 @@
php/google/
node_modules/
public/
.idea/
node_modules/
public/*.js
public/*.map

View file

@ -1,18 +0,0 @@
<h2>Export</h2>
<div id="exportOptions">
<div class="settingsCol">
<label>
<span>Word List</span>
</label>
<p style="font-size:12px;">This process exports all of the words in the dictionary as a CSV format file.</p>
<p style="font-size:12px;">You can either use the exported file to re-import them into a different dictionary in Lexiconga, or taken and used somewhere else you might need them!</p>
<button type="button" onclick="ExportWords(); return false;">Export Words</button>
</div>
<div class="settingsCol">
<label>
<span>Full Dictionary</span>
<p style="font-size:12px;">This process exports the full dictionary, words and all information, in a ".dict" format to be re-imported back into Lexiconga as a new dictionary.</p>
<button type="button" onclick="ExportDictionary(); return false;">Export Dictionary</button>
</label>
</div>
</div>

View file

@ -1,10 +0,0 @@
<div class="settingsCol"><form id="forgotForm" method="post" action="?forgot">
<h2>Forgot Password</h2>
<label><span>Email</span>
<input type="email" id="forgotEmailField" name="email" />
</label>
<div id="forgotError" style="font-weight:bold;color:red;"></div>
<button type="submit" id="forgotSubmitButton" onclick="ValidateForgot(); return false;">Email Password Reset Key</button>
<div id="dictionaryWarn"></div>
<span id="forgotPassword" class="clickable" onclick="ShowInfo('loginForm')">Log In/Create Account</span>
</form></div>

View file

@ -1,23 +0,0 @@
<h2>Import</h2>
<div id="importOptions">
<div class="settingsCol">
<label>
<span>Word List</span>
</label>
<p style="font-size:12px;">This process imports words in a CSV format to the currently loaded dictionary. <small>(Note: You can save an Excel file as a CSV)</small></p>
<p style="font-size:12px;">The CSV file must have a header line in this order: word,pronunciation,part of speech,definition,explanation. Your word data must be in the appropriate order according to the headers. You can use <span class="clickable inline-button" onclick="download('import_template.csv','word,pronunciation,part of speech,definition,explanation\n');">this CSV file as a template</span> if you need help.</p>
<p style="font-size:12px;">Make sure the parts of speech for each word correspond to your dictionary's parts of speech or else you won't be able to find it using a filter. If a part of speech is left blank, you can find the blanks using the "Blank" option in the Filter so you can clean up.</p>
<p style="font-size:12px;">At a minimum, all of your words <em>must</em> have the "word" field <em>and</em> either the "definition" or "explanation" field filled out in the CSV file.</p>
<input type="file" id="importWordsCSV" />
<button type="button" onclick="ImportWords(); return false;">Import Words</button>
</div>
<div class="settingsCol">
<label>
<span>Full Dictionary</span>
<p style="font-size:12px;">This process imports a full dictionary previously exported from Lexiconga in a .dict format.</p>
<p style="font-size:12px;">All imported dictionaries are set to not be public by default, even if the source dictionary was public. Be sure to check the settings after importing to make sure everything is how you want it after importing.</p>
<input type="file" id="importFile" />
<button type="button" onclick="ImportDictionary(); return false;">Import Dictionary</button>
</label>
</div>
</div>

View file

@ -1,36 +0,0 @@
<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>

View file

@ -1,49 +0,0 @@
## Privacy Policy
This document was last updated on November 02, 2015.
This Privacy Policy governs the manner in which Lexiconga Dictionary Builder collects, uses, maintains and discloses information collected from users (each, a "User") of the http://lexicon.ga website ("Site") and its accounts ("Account").
### Personal identification information
We may collect personal identification information from Users in a variety of ways, including, but not limited to, when Users visit our site, register on the site, and in connection with other activities, services, features or resources we make available on our Site. Users may be asked for, as appropriate, their name and email address. Users may, however, use our Site anonymously. We will collect personal identification information from Users only if they voluntarily submit such information to us. Users can always refuse to supply personal identification information, except that it may prevent them from engaging in certain Site-related activities.
### Non-personal identification information
We may collect non-personal identification information about Users whenever they interact with our Site through website analytics tools. Non-personal identification information may include the browser name, the type of computer and technical information about Users means of connection to our Site, such as the operating system and the Internet service providers utilized and other similar information.
### Web browser cookies
Our Site does not use "cookies" to enhance User experience, but it does use "local storage". User's web browser places local storage on their hard drive for record-keeping purposes and sometimes to track information about them, but we only use this to store your current dictionary. User may choose to set their web browser to refuse local storage usage, but if they do so, the Site will not function properly.
### How we use collected information
Lexiconga Dictionary Builder may collect and use Users personal information for the following purposes:
- **To run and operate our Site and personalize user experience:** We need your input to display content on the Site correctly, because it is a tool built entirely to display the content that you enter.
### How we protect your information
If you are utilizing an Account, we protect your information by keeping your information on a trusted database server provided by the Site's web host. All data you save from an Account is uploaded to this database server from your browser.
If you utilize the ability to make dictionaries associated with an Account visible to the public, you accept all responsibility for its content being visible to anyone who might find it. We cannot protect what you willingly put in public, and we do not accept liability if information you place online is used against you somehow. Never put personal information online!
If you are not using an Account, then all of your information remains right on your own computer where it belongs. As mentioned previously, all data is stored in your browser's "local storage".
### Sharing your personal information
We do not sell, trade, or rent Users personal identification information to others. We may share generic aggregated demographic information not linked to any personal identification information regarding visitors and users with our business partners, trusted affiliates and advertisers for the purposes outlined above.
### Electronic newsletters
If User decides to opt-in to our mailing list, they will receive emails that may include company news, updates, related product or service information, etc. We may use third party service providers like MailChimp to help us operate our business and the Site or administer activities on our behalf, such as sending out newsletters or surveys. We may share your information with these third parties for those limited purposes provided that you have given us your permission.
### Third party websites
Users may find advertising or other content on our Site that link to the sites and services of our partners, suppliers, advertisers, sponsors, licencors and other third parties. We do not control the content or links that appear on these sites and are not responsible for the practices employed by websites linked to or from our Site. In addition, these sites or services, including their content and links, may be constantly changing. These sites and services may have their own privacy policies and customer service policies. Browsing and interaction on any other website, including websites which have a link to our Site, is subject to that website's own terms and policies.
### Advertising
Ads appearing on our site may be delivered to Users by advertising partners, who may set cookies. These cookies allow the ad server to recognize your computer each time they send you an online advertisement to compile non personal identification information about you or others who use your computer. This information allows ad networks to, among other things, deliver targeted advertisements that they believe will be of most interest to you. This privacy policy does not cover the use of cookies by any advertisers.
### Google Adsense
Some of the ads may be served by Google. Google's use of the DART cookie enables it to serve ads to Users based on their visit to our Site and other sites on the Internet. DART uses "non personally identifiable information" and does NOT track personal information about you, such as your name, email address, physical address, etc. You may opt out of the use of the DART cookie by visiting the Google ad and content network privacy policy at [http://www.google.com/policies/technologies/ads/](http://www.google.com/policies/technologies/ads/)
### Changes to this privacy policy
Lexiconga Dictionary Builder has the discretion to update this privacy policy at any time. When we do, we will post a notification on the main page of our Site. We encourage Users to frequently check this page for any changes to stay informed about how we are helping to protect the personal information we collect. You acknowledge and agree that it is your responsibility to review this privacy policy periodically and become aware of modifications.
### Your acceptance of these terms
By using this Site, you signify your acceptance of this policy. If you do not agree to this policy, please do not use our Site. Your continued use of the Site following the posting of changes to this policy will be deemed your acceptance of those changes. This policy was originally generated using PrivacyPolicies.com and modified for our use.
### Contacting us
If you have any questions about this Privacy Policy, the practices of this site, or your dealings with this site, please contact us by email at help (at) lexicon (dot) ga or follow us Twitter @alamantus.

View file

@ -1,40 +0,0 @@
## Terms of Service ("Terms")
Last updated: November 1, 2015.
Please read these Terms of Service ("Terms", "Terms of Service") carefully before using the http://lexicon.ga website (the "Service") or the cloud account service (an "Account") operated by Robbie Antenesse and Alamantus GameDev ("us", "we", or "our").
Your access to and use of the Service is conditioned on your acceptance of and compliance with these Terms. These Terms apply to all visitors, users and others who access or use the Service. By accessing or using the Service you agree to be bound by these Terms. If you disagree with any part of the terms then you may not access the Service.
### Usage
You may use our Service free of charge, and you are free to stop using our Service at any time. If you are utilizing an Account with our Service, you agree to never attempt maliciously dismantling the Service in any way or to use the Service in a way that is unlawful. If you are found in violation of this, your Account and access to the Service may be terminated without warning.
If you stop using our Service, your data will remain unless you request its removal. When data is removed from an Account in our Service, it becomes permanently irretrievable. You agree that you understand the implications of deleting or requesting the deletion of your data and that we are not liable for its loss.
Instructions for use are visible through the "About Lexiconga" button on the site.
### Public Dictionaries
Any dictionaries created and associated with an Account are private by default and only visible to the owner of the Account. You may make your dictionaries visible to the public at any time by utilizing the appropriate dictionarys setting.
If you utilize the ability to make dictionaries associated with an Account visible to the public, you accept all responsibility for any and all damages that may come as a result of the information you place online and acknowledge that we are not liable in any way. Do not put any personal information online. We cannot protect what you deliberately make publicly visible.
### Termination
We may terminate or suspend access to our Service immediately, without prior notice or liability, for any reason whatsoever, including without limitation if you breach the Terms. All provisions of the Terms which by their nature should survive termination shall survive termination, including, without limitation, ownership provisions, warranty disclaimers, indemnity and limitations of liability.
### Links To Other Web Sites
Our Service may contain links to third-party web sites or services that are not owned or controlled by Robbie Antenesse and Alamantus GameDev.
Robbie Antenesse and Alamantus GameDev has no control over, and assumes no responsibility for, the content, privacy policies, or practices of any third party web sites or services. You further acknowledge and agree that Robbie Antenesse and Alamantus GameDev shall not be responsible or liable, directly or indirectly, for any damage or loss caused or alleged to be caused by or in connection with use of or reliance on any such content, goods or services available on or through any such web sites or services.
We strongly advise you to read the terms and conditions and privacy policies of any third-party web sites or services that you visit.
### Governing Law
These Terms shall be governed and construed in accordance with the laws of the United States of America, without regard to its conflict of law provisions. Our failure to enforce any right or provision of these Terms will not be considered a waiver of those rights. If any provision of these Terms is held to be invalid or unenforceable by a court, the remaining provisions of these Terms will remain in effect. These Terms constitute the entire agreement between us regarding our Service, and supersede and replace any prior agreements we might have between us regarding the Service.
### Changes
We reserve the right, at our sole discretion, to modify or replace these Terms at any time. If a revision is material we will try to provide at least 5 days notice prior to any new terms taking effect. What constitutes a material change will be determined at our sole discretion.
By continuing to access or use our Service after those revisions become effective, you agree to be bound by the revised terms. If you do not agree to the new terms, please stop using the Service.
### Contact Us
If you have any questions about these Terms, please contact us by email at help (at) lexicon (dot) ga or follow us on Twitter @alamantus.

View file

@ -1 +0,0 @@
<i><small>[Release Date]</small></i> | So much has been updated! Check the <a href="/updates" target="_blank">Updates page</a> to see all the changes!

View file

@ -1,149 +0,0 @@
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);
}

View file

@ -1,134 +0,0 @@
/* 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%;
}
}

View file

@ -1,453 +0,0 @@
* {
-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;
}

View file

@ -1,4 +0,0 @@
word,pronunciation,part of speech,equivalent,explanation
test0, [tehst], ,dah,
test1, [tehst], a ,dah,
test2, [tehst], a ,dah,
1 word pronunciation part of speech equivalent explanation
2 test0 [tehst] dah
3 test1 [tehst] a dah
4 test2 [tehst] a dah

459
index.php
View file

@ -1,459 +0,0 @@
<?php
require_once('required.php');
session_start();
$current_user = isset($_SESSION['user']) ? $_SESSION['user'] : 0;
$dictionary_to_load = (isset($_GET['dict'])) ? intval($_GET['dict']) : 0;
$the_public_dictionary = '"That dictionary doesn\'t exist."';
$dictionary_name = 'ERROR';
$dictionary_creator = 'nobody';
$word_to_load = (isset($_GET['word'])) ? intval($_GET['word']) : 0;
$the_public_word = '"That word doesn\'t exist."';
$word_name = 'ERROR';
$is_owner = false;
$display_mode = ($dictionary_to_load > 0) ? (($word_to_load > 0) ? "word" : "view") : "build";
$announcement = get_include_contents(SITE_LOCATION . '/announcement.php');
$notificationMessage = "";
if ($current_user > 0 || !isset($_SESSION['loginfailures']) || (isset($_SESSION['loginlockouttime']) && time() - $_SESSION['loginlockouttime'] >= 3600)) {
// If logged in, never failed, or more than 1 hour has passed, reset login failures.
$_SESSION['loginfailures'] = 0;
} else {
$alertlockoutmessage = "You failed logging in 10 times. To prevent request flooding and hacking attempts, you may not log in or create an account for 1 hour.\\n\\nThe last time this page was loaded, you had been locked out for " . time_elapsed(time() - $_SESSION['loginlockouttime']) . "\\n\\nRefresh the page once the hour has passed.";
$hoverlockoutmessage = str_replace("\\n", "\n", $alertlockoutmessage);
}
require_once(SITE_LOCATION . '/php/notificationconditiontree.php');
if ($display_mode != "build") {
$dbconnection = new PDO('mysql:host=' . DATABASE_SERVERNAME . ';dbname=' . DATABASE_NAME . ';charset=utf8', DATABASE_USERNAME, DATABASE_PASSWORD);
$dbconnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbconnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
$dbconnection->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$dictionary_query = "SELECT `d`.`id`, `d`.`user`, `d`.`name`, `d`.`description`, `u`.`public_name`, `d`.`parts_of_speech`, `d`.`is_complete` ";
$dictionary_query .= "FROM `dictionaries` AS `d` LEFT JOIN `users` AS `u` ON `d`.`user`=`u`.`id`";
$dictionary_query .= "WHERE `d`.`is_public`=1 AND `d`.`id`=" . $dictionary_to_load . ";";
$word_query = "SELECT `w`.`word_id`, `w`.`name`, `w`.`pronunciation`, `w`.`part_of_speech`, `w`.`simple_definition`, `w`.`long_definition` ";
$word_query .= "FROM `words` AS `w` LEFT JOIN `dictionaries` AS `d` ON `w`.`dictionary`=`d`.`id` ";
$word_query .= "WHERE `d`.`is_public`=1 AND `w`.`dictionary`=" . $dictionary_to_load . (($display_mode == "word") ? " AND `w`.`word_id`=" . $word_to_load : "") . " ";
$word_query .= "ORDER BY IF(`d`.`sort_by_equivalent`, `w`.`simple_definition`, `w`.`name`) COLLATE utf8_unicode_ci;";
try {
$dictionary_results = $dbconnection->prepare($dictionary_query);
$dictionary_results->execute();
if ($dictionary_results) {
$word_results = $dbconnection->prepare($word_query);
$word_results->execute();
$dictionary_words = "[";
if ($word_results) {
$words_counted = 0;
$words_total = num_rows($word_results);
while ($word = fetch($word_results)) {
$words_counted++;
$word_name = $word['name'];
$dictionary_words .= '{"name":"' . $word['name'] . '",';
$dictionary_words .= '"pronunciation":"' . $word['pronunciation'] . '",';
$dictionary_words .= '"partOfSpeech":"' . $word['part_of_speech'] . '",';
$dictionary_words .= '"simpleDefinition":"' . $word['simple_definition'] . '",';
$dictionary_words .= '"longDefinition":"' . $word['long_definition'] . '",';
$dictionary_words .= '"wordId":"' . $word['word_id'] . '"';
$dictionary_words .= '}';
if ($words_counted < $words_total) {
$dictionary_words .= ',';
}
}
}
$dictionary_words .= "]";
if (num_rows($dictionary_results) === 1) {
while ($dict = fetch($dictionary_results)) {
$dictionary_name = $dict['name'];
$dictionary_creator = $dict['public_name'];
$is_owner = $current_user == $dict['user'];
$the_public_dictionary = '{"name":"' . $dict['name'] . '",';
$the_public_dictionary .= '"description":"' . $dict['description'] . '",';
$the_public_dictionary .= '"createdBy":"' . $dict['public_name'] . '",';
$the_public_dictionary .= '"words":' . $dictionary_words . ',';
$the_public_dictionary .= '"settings":{';
$the_public_dictionary .= '"partsOfSpeech":"' . $dict['parts_of_speech'] . '",';
$the_public_dictionary .= '"isComplete":' . (($dict['is_complete'] == 1) ? 'true' : 'false') . '},';
$the_public_dictionary .= '"id":"' . $dictionary_to_load . '"';
$the_public_dictionary .= '}';
}
}
}
}
catch (PDOException $ex) {}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php if ($display_mode != "build") { ?>
<title><?php echo (($display_mode == "word") ? ($word_name . " | ") : "") . $dictionary_name; ?> Dictionary on Lexiconga</title>
<meta property="og:url" content="http://lexicon.ga/<?php echo $dictionary_to_load . (($display_mode == "word") ? ("/" . $word_to_load) : ""); ?>" />
<meta property="og:type" content="article" />
<meta property="og:title" content="<?php echo (($display_mode == "word") ? ("\"" . $word_name . "\" in the ") : "") . $dictionary_name; ?> Dictionary" />
<meta property="og:description" content="A Lexiconga dictionary by <?php echo $dictionary_creator; ?>" />
<meta property="og:image" content="http://lexicon.ga/images/logo.svg" />
<script>var publicDictionary = <?php echo $the_public_dictionary; ?></script>
<?php } else { ?>
<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" />
<?php } ?>
<link href="/css/styles.css" rel="stylesheet" />
<link href="/css/lexiconga.css" rel="stylesheet" />
<link href="/css/mobile.css" rel="stylesheet" />
</head>
<body>
<header>
<div id="headerPadder">
<a href="/" id="siteLogo">Lexiconga Dictionary Builder</a>
<div style="float:right;margin: 16px 8px;font-size:12px;">
<span id="aboutButton" class="clickable" onclick="ShowInfo('aboutText')">About Lexiconga</span>
</div>
<div id="loginoutArea" style="font-size:12px;">
<?php if ($display_mode == "build") { ?>
<?php if ($current_user > 0) { //If logged in, show the log out button. ?>
<span id="accountSettings" class="clickable" onclick="ShowAccountSettings()">Account Settings</span> <a href="?logout" id="logoutLink" class="clickable">Log Out</a>
<?php } elseif (!isset($_SESSION['loginfailures']) || (isset($_SESSION['loginfailures']) && $_SESSION['loginfailures'] < 10)) { ?>
<span id="loginLink" class="clickable" onclick="ShowInfo('loginForm')">Log In/Create Account</span>
<?php } else { ?>
<span id="loginLink" class="clickable" title="<?php echo $hoverlockoutmessage; ?>" onclick="alert('<?php echo $alertlockoutmessage; ?>');">Can't Login</span>
<?php }
} else { ?>
<h3 style="display:inline; margin:0 5px;">Viewing</h3>
<?php if ($is_owner) { ?>
<span class="clickable" onclick="ChangeDictionaryToId(<?php echo $dictionary_to_load; ?>, function(response) {if (response.length >= 60) window.location.href = '/';});">&laquo; Edit Dictionary</span>
<?php } else { ?>
<a class="clickable" href="/">&laquo; Go Home to Lexiconga</a>
<?php }?>
<?php } ?>
</div>
</div>
</header>
<contents>
<?php if ($display_mode == "build") { ?>
<div id="announcementArea" style="display:<?php echo (($announcement) ? "block" : "none"); ?>;">
<span id="announcementCloseButton" class="clickable rightButton" onclick="document.getElementById('announcementArea').style.display='none';">Close</span>
<div id="announcement"><?php echo $announcement; ?></div>
</div>
<div id="notificationArea" style="display:<?php echo (($notificationMessage) ? "block" : "none"); ?>;">
<span id="notificationCloseButton" class="clickable rightButton" onclick="document.getElementById('notificationArea').style.display='none';">Close</span>
<div id="notificationMessage"><?php echo $notificationMessage; ?></div>
</div>
<div id="leftColumn">
<form id="wordEntryForm">
<div id="formLockButton" class="clickable" onclick="ToggleWordFormLock()" title="Lock/unlock form from the top of the page">&#128274;</div>
<label><span>Word</span>
<input type="text" id="word" 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" onkeydown="SubmitWordOnCtrlEnter(this)" />
</label>
<label><span>Part of Speech</span>
<select id="partOfSpeech" onkeydown="SubmitWordOnCtrlEnter(this)"></select>
</label>
<label><span>Definition/<wbr><b class=wbr></b>Equivalent Word(s)</span>
<input type="text" id="simpleDefinition" onkeydown="SubmitWordOnCtrlEnter(this)" />
</label>
<label><span>Explanation/<wbr><b class=wbr></b>Long Definition <span id="showFullScreenTextbox" class="clickable inline-button" onclick="ShowFullScreenTextbox('longDefinition', 'Explanation/Long Definition')">Maximize</span></span>
<textarea id="longDefinition" class="longDefinition" onkeydown="SubmitWordOnCtrlEnter(this)"></textarea>
</label>
<input type="hidden" id="editIndex" />
<span id="errorMessage"></span>
<div id="newWordButtonArea" style="display: block;">
<button type="button" onclick="AddWord(); return false;">Add Word</button>
</div>
<div id="editWordButtonArea" style="display: none;">
<button type="button" onclick="AddWord(); return false;">Edit Word</button> <button type="button" onclick="ClearForm(); window.scroll(savedScroll.x, savedScroll.y); return false;">Cancel</button>
</div>
<div id="updateConflict" style="display: none;"></div>
</form>
</div>
<div id="mobileWordFormPullout" onclick="MobileToggleWordForm();" style="display:none;">+</div>
<?php } ?>
<div id="dictionaryColumn"><div id="dictionaryContent">
<?php if ($display_mode == "build") { ?>
<span id="settingsButton" class="clickable rightButton" onclick="ShowSettings()">Settings</span>
<?php } ?>
<h1 id="dictionaryName"></h1>
<?php if ($display_mode != "build") { ?>
<h4 id="dictionaryBy"></h4>
<div id="incompleteNotice"></div>
<?php } ?>
<?php if ($display_mode == "word") { ?>
<a class="clickable toggleButton" href="/<?php echo $dictionary_to_load; ?>">View Full Dictionary</a>
<?php } ?>
<span id="descriptionToggle" class="clickable toggleButton" onclick="ToggleDescription();"><?php if ($display_mode == "view") { ?>Hide<?php } else { ?>Show<?php } ?> Description</span>
<div id="dictionaryDescription" style="display:<?php if ($display_mode == "view") { ?>block<?php } else { ?>none<?php } ?>;"></div>
<?php if ($display_mode != "word") { ?>
<span id="searchFilterToggle" class="clickable toggleButton" onclick="ToggleSearchFilter();"><?php if ($display_mode == "view") { ?>Hide <?php } ?>Search/Filter Options</span>
<div id="searchFilterArea" style="display:<?php if ($display_mode == "view") { ?>block<?php } else { ?>none<?php } ?>;">
<div id="searchArea" style="display:block;">
<label style="margin-top:10px;">
<span>Search</span>
<div style="display:block;">
<input type="text" id="searchBox" onclick="this.select();" onchange="<?php Show_Dictionary_Function($display_mode == "view") ?>" style="display:inline;" />&nbsp;
<span class="clickable inline-button" onclick="document.getElementById('searchBox').value='';<?php Show_Dictionary_Function($display_mode == "view") ?>;">Clear Search</span>
</div>
<div id="searchOptions">
<label class="searchOption">Word <input type="checkbox" id="searchOptionWord" checked="checked" onchange="<?php Show_Dictionary_Function($display_mode == "view") ?>" /></label>
<label class="searchOption">Definition <input type="checkbox" id="searchOptionSimple" checked="checked" onchange="<?php Show_Dictionary_Function($display_mode == "view") ?>" /></label>
<label class="searchOption">Explanation <input type="checkbox" id="searchOptionLong" checked="checked" onchange="<?php Show_Dictionary_Function($display_mode == "view") ?>" /></label>
<br />
<label class="searchOption">Search Case-Sensitive <input type="checkbox" id="searchCaseSensitive" onchange="<?php Show_Dictionary_Function($display_mode == "view") ?>" /></label>
<label class="searchOption" title="Note: Matching diacritics will appear but may not highlight.">Ignore Diacritics/Accents <input type="checkbox" id="searchIgnoreDiacritics" onchange="<?php Show_Dictionary_Function($display_mode == "view") ?>" /></label>
</div>
</label>
</div>
<label style="display:block;margin-bottom:0;"><b>Filter Words</b></label>
<div id="filterOptions" style="display:block"></div>
<div style="display:block;">
<span class="clickable inline-button" onclick="ToggleAllFilters(true);<?php Show_Dictionary_Function($display_mode == "view") ?>;">
Check All
</span>
&nbsp;
<span class="clickable inline-button" onclick="ToggleAllFilters(false);<?php Show_Dictionary_Function($display_mode == "view") ?>;">
Uncheck All
</span>
</div>
</div>
<div id="filterWordCount"></div>
<?php } ?>
<div id="theDictionary"></div>
</div></div>
<div id="rightColumn" class="googleads" style="float:right;width:20%;max-width:300px;min-width:200px;overflow:hidden;">
<?php if ($_GET['adminoverride'] != "noadsortracking") { include_once("php/google/adsense.php"); } ?>
</div>
<?php if ($display_mode == "build") { ?>
<div id="settingsScreen" style="display:none;">
<div id="settingsBackgroundFade" class="fixedFade" onclick="HideSettings()"></div>
<div id="settingsOptions" class="fixedPage">
<span id="settingsScreenCloseButton" class="clickable rightButton" onclick="HideSettings()">Close</span>
<h2>Dictionary Settings</h2>
<form id="settingsForm">
<div class="settingsCol">
<div id="hideIfComplete">
<label>
<span>Dictionary Name</span>
<input type="text" id="dictionaryNameEdit" />
</label>
<label><span>Dictionary Details <span id="showFullScreenTextbox" class="clickable inline-button" onclick="ShowFullScreenTextbox('dictionaryDescriptionEdit', 'Dictionary Details')">Maximize</span></span>
<textarea id="dictionaryDescriptionEdit"></textarea>
</label>
<label>
<span>Parts of Speech</span>
<input type="text" id="dictionaryPartsOfSpeechEdit" />
</label>
<label>
<span class="checkboxlabel">Allow Duplicates</span>
<input type="checkbox" id="dictionaryAllowDuplicates" onchange="ToggleCaseSensitiveOption()" />
<label>
<span class="checkboxlabel">Case-Sensitive</span>
<input type="checkbox" id="dictionaryCaseSensitive" />
</label>
</label>
<label class="inline">
<span class="checkboxlabel">Sort by Definition/Equivalent Word</span>
<input type="checkbox" id="dictionarySortByEquivalent" />
</label> <span class="clickable inline-button" onclick='alert("By default, your dictionary is organized alphabetically by word. Checking this box will organize it by the \"Definition/Equivalent Word\" field instead");'>?</span>
</div>
<br>
<label>
<span class="checkboxlabel">Dictionary is Complete</span>
<input type="checkbox" id="dictionaryIsComplete" />
</label>
<?php if ($current_user > 0) { //If logged in, show the log out button. ?>
<label class="inline">
<span class="checkboxlabel">Dictionary is Public</span>
<input type="checkbox" id="dictionaryIsPublic" onchange="TogglePublicLink()" />
</label> <span class="clickable inline-button" onclick='alert("If you save your settings with this checked, your dictionary will be viewable by anyone if they have the public link.");'>?</span>
<div id="publicLink"></div>
<?php } ?>
</div>
<div class="settingsCol">
<label>
<b>Total Entries:</b> <i id="numberOfWordsInDictionary"></i>
</label>
<br>
<?php if ($current_user > 0) { //If logged in, show the special options. ?>
<label><span>Change Dictionaries</span>
<select id="userDictionaries" onchange="ChangeDictionary();"></select>
</label>
<br>
<label><button type="button" onclick="CreateNewDictionary()" style="cursor:pointer;">Create a New Dictionary</button></label>
<?php } ?>
<label style="display:inline-block;margin-right:8px;"><button type="button" onclick="ShowInfo('exportForm')">Export...</button></label>
<label style="display:inline-block;"><button type="button" onclick="ShowInfo('importForm')">Import...</button></label>
<br><br>
<?php if ($current_user > 0) { //If logged in, show the log out button. ?>
<label><button type="button" onclick="DeleteCurrentDictionary()" style="cursor:pointer;">Delete Current Dictionary</button></label>
<?php } else { //If logged in, show the log out button. ?>
<label><button type="button" onclick="EmptyWholeDictionary()" style="cursor:pointer;">Empty Current Dictionary</button></label>
<?php } ?>
</div>
<div id="settingsSaveButtons">
<span id="settingsErrorMessage"></span><br>
<button type="button" class="rightButton" onclick="SaveSettings(); HideSettings(); return false;">Save and Close</button>
<button type="button" class="rightButton" onclick="SaveSettings(); return false;" style="margin-right:2px;">Save</button>
</div>
</form>
</div>
</div>
<div id="fullScreenTextboxScreen" style="display:none;">
<div id="fullScreenTextboxBackgroundFade" class="fixedFade" onclick="HideFullScreenTextbox()"></div>
<div id="expandedTextboxId" style="display:none;width:0px;height:0px;"></div>
<div id="fullScreenTextboxPage" class="fixedPage">
<span id="fullScreenTextboxScreenCloseButton" class="clickable rightButton" onclick="HideFullScreenTextbox()">Minimize</span>
<label><span id="fullScreenTextboxLabel"></span></label>
<textarea id="fullScreenTextbox"></textarea>
</div>
</div>
<?php } ?>
<div id="infoScreen" style="display:none;">
<div id="infoBackgroundFade" class="fixedFade" onclick="HideInfo()"></div>
<div id="infoPage" class="fixedPage">
<span id="infoScreenCloseButton" class="clickable rightButton" onclick="HideInfo()">Close</span>
<div id="infoText"></div>
</div>
</div>
<?php if ($current_user > 0) {
$user_email = Get_User_Email($current_user);
?>
<div id="accountSettingsScreen" style="display:none;">
<div id="accountSettingsBackgroundFade" class="fixedFade" onclick="HideAccountSettings()"></div>
<div id="accountSettingsPage" class="fixedPage">
<span id="accountSettingsScreenCloseButton" class="clickable rightButton" onclick="HideAccountSettings()">Close</span>
<div class="settingsCol"><form id="accountSettingsForm" method="post" action="?accountsettings">
<h2>Account Settings</h2>
<label><span>Email</span>
<input type="email" id="accountSettingsEmailField" name="email" value="<?php echo $user_email; ?>" onchange="WarnEmailChange()" />
<input type="hidden" id="accountSettingsPreviousEmailField" name="previousemail" value="<?php echo $user_email; ?>" />
</label>
<div id="accountSettingsEmailChangeWarning" style="display:none;font-weight:bold;color:#dd5500;font-size:11px;margin-bottom:10px;">If you change your email address, please note that you will no longer be able to log in with your old email address, <?php echo $user_email; ?>.<br>Change it back unless you are completely sure that you want to change your email address!</div>
<label><span>Public Name <span class="clickable inline-button" onclick="ExplainPublicName()">?</span></span>
<input type="text" id="accountSettingsPublicNameField" name="publicname" value="<?php echo Get_Public_Name_By_Id($current_user); ?>" />
</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="accountSettingsError" style="font-weight:bold;color:red;"></div>
<button type="submit" id="accountSettingsSubmitButton" onclick="ValidateAccountSettings(); return false;">Save Settings</button>
<br>
</form></div>
<div class="settingsCol">
<br>
<h2>Reset Your Password</h2>
<p style="font-size: 12px;">Click the button below to reload the page and show the Reset Password form. Filling out this form will instantly change your password, and you will need to log in using the new password from that point forward.</p>
<span id="resetPassword" class="clickable" onclick="this.innerHTML='Loading...';LoggedInResetPassword();" style="margin-top:20px;">Reset Password</span>
</div>
</div>
</div>
<?php
}
?>
<?php if ($display_mode == "build") { ?>
<div id="loadAfterDeleteScreen" style="display:none;">
<div id="loadAfterDeleteFade" class="fixedFade"></div>
<div id="loadAfterDeletePage" class="fixedPage">
<div class="settingsCol">
<h1>Dictionary Deleted</h1>
<label>Select dictionary to load:<br />
<select id="loadAfterDelete" onchange="ChangeDictionary(this);document.getElementById('loadAfterDeleteScreen').style.display = 'none';"></select>
</label>
<p>Or</p>
<label><button type="button" onclick="CreateNewDictionary();document.getElementById('loadAfterDeleteScreen').style.display = 'none';">Create a New Dictionary</button></label>
</div>
</div>
</div>
<?php } ?>
</contents>
<footer>
<div id="footer-content">
Dictionary Builder only guaranteed to work with most up-to-date HTML5 browsers. <a href="/issues" class="clickable inline-button" target="_blank">Issues</a> <a href="/updates" class="clickable inline-button" target="_blank">Updates</a> | <span class="clickable inline-button" onclick="ShowInfo('termsText')" style="font-size:12px;">Terms</span> <span class="clickable inline-button" onclick="ShowInfo('privacyText')" style="font-size:12px;">Privacy</span>
</div>
</footer>
<!-- Markdown Parser -->
<script src="/js/marked.js"></script>
<!-- CSV Parser -->
<script src="/js/papaparse.js"></script>
<!-- JSON Search -->
<script src="/js/defiant.js"></script>
<!-- Diacritics Removal for Exports -->
<script src="/js/removeDiacritics.js"></script>
<!-- Helper Functions -->
<script src="/js/helpers.js"></script>
<!-- Main Functions -->
<script src="/js/dictionaryBuilder.js"></script>
<!-- UI Functions -->
<script src="/js/ui.js"></script>
<?php if ($display_mode != "build") { ?>
<!-- Public View Functions -->
<script src="/js/publicView.js"></script>
<?php } ?>
<?php if ($_GET['adminoverride'] != "noadsortracking") { include_once("php/google/analytics.php"); } ?>
<script>
var aboutText = termsText = privacyText = loginForm = forgotForm = exportForm = importForm = "Loading...";
<?php if ($display_mode != "build") { ?>
window.onload = function () {
ShowPublicDictionary(<?php if ($display_mode == "word") echo "true"; ?>);
<?php
if ($display_mode != "word") { // don't try to set the filters
echo "SetPublicPartsOfSpeech()";
} ?>
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);
}
<?php } else { ?>
ready(function() {
Initialize();
});
<?php } ?>
var loggedIn = <?php echo ($current_user > 0) ? "true" : "false"; ?>;
</script>
</body>
</html>

View file

@ -1,687 +0,0 @@
/*
* Defiant.js v1.2.5
* Serch JSON structures plus smart templating with XSLT and XPath.
* http://defiantjs.com
*
* Copyright (c) 2013-2015, Hakan Bilgin <hbi@longscript.com>
* Licensed under the MIT License
*
* NOTE:
* Robbie Antenesse edited line 165's RegExp to search global and case-insensitive in case of multiple contains() groups.
*/
if (typeof module === "undefined") {
var module = { exports: undefined };
} else {
// Node env adaptation goes here...
}
module.exports = Defiant = (function(window, undefined) {
'use strict';
var Defiant = {
is_ie : /msie/i.test(navigator.userAgent),
is_safari : /safari/i.test(navigator.userAgent),
env : 'production',
xml_decl : '<?xml version="1.0" encoding="utf-8"?>',
namespace : 'xmlns:d="defiant-namespace"',
tabsize : 4,
render: function(template, data) {
var processor = new XSLTProcessor(),
span = document.createElement('span'),
opt = {match: '/'},
tmpltXpath,
scripts,
temp,
sorter;
// handle arguments
switch (typeof(template)) {
case 'object':
this.extend(opt, template);
if (!opt.data) opt.data = data;
break;
case 'string':
opt.template = template;
opt.data = data;
break;
default:
throw 'error';
}
opt.data = JSON.toXML(opt.data);
tmpltXpath = '//xsl:template[@name="'+ opt.template +'"]';
if (!this.xsl_template) this.gatherTemplates();
if (opt.sorter) {
sorter = this.node.selectSingleNode(this.xsl_template, tmpltXpath +'//xsl:for-each//xsl:sort');
if (sorter) {
if (opt.sorter.order) sorter.setAttribute('order', opt.sorter.order);
if (opt.sorter.select) sorter.setAttribute('select', opt.sorter.select);
sorter.setAttribute('data-type', opt.sorter.type || 'text');
}
}
temp = this.node.selectSingleNode(this.xsl_template, tmpltXpath);
temp.setAttribute('match', opt.match);
processor.importStylesheet(this.xsl_template);
span.appendChild(processor.transformToFragment(opt.data, document));
temp.removeAttribute('match');
if (this.is_safari) {
scripts = span.getElementsByTagName('script');
for (var i=0, il=scripts.length; i<il; i++) scripts[i].defer = true;
}
return span.innerHTML;
},
gatherTemplates: function() {
var scripts = document.getElementsByTagName('script'),
str = '',
i = 0,
il = scripts.length;
for (; i<il; i++) {
if (scripts[i].type === 'defiant/xsl-template') str += scripts[i].innerHTML;
}
this.xsl_template = this.xmlFromString('<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" '+ this.namespace +'>'+ str.replace(/defiant:(\w+)/g, '$1') +'</xsl:stylesheet>');
},
getSnapshot: function(data) {
return JSON.toXML(data, true);
},
xmlFromString: function(str) {
var parser,
doc;
str = str.replace(/>\s{1,}</g, '><');
if (str.trim().match(/<\?xml/) === null) {
str = this.xml_decl + str;
}
if (this.is_ie) {
doc = new ActiveXObject('Msxml2.DOMDocument');
doc.loadXML(str);
if (str.indexOf('xsl:stylesheet') === -1) {
doc.setProperty('SelectionLanguage', 'XPath');
}
} else {
parser = new DOMParser();
doc = parser.parseFromString(str, 'text/xml');
}
return doc;
},
extend: function(src, dest) {
for (var content in dest) {
if (!src[content] || typeof(dest[content]) !== 'object') {
src[content] = dest[content];
} else {
this.extend(src[content], dest[content]);
}
}
return src;
},
node: {}
};
return Defiant;
})(this);
if (typeof(XSLTProcessor) === 'undefined') {
// emulating XSLT Processor (enough to be used in defiant)
var XSLTProcessor = function() {};
XSLTProcessor.prototype = {
importStylesheet: function(xsldoc) {
this.xsldoc = xsldoc;
},
transformToFragment: function(data, doc) {
var str = data.transformNode(this.xsldoc),
span = document.createElement('span');
span.innerHTML = str;
return span;
}
};
}
// extending STRING
if (!String.prototype.fill) {
String.prototype.fill = function(i,c) {
var str = this;
c = c || ' ';
for (; str.length<i; str+=c){}
return str;
};
}
if (!String.prototype.trim) {
String.prototype.trim = function () {
return this.replace(/^\s+|\s+$/gm, '');
};
}
if (!String.prototype.xTransform) {
String.prototype.xTransform = function () {
var str = this;
if (this.indexOf('translate(') === -1) {
str = this.replace(/contains\(([^,]+),([^\\)]+)\)/gi, function(c,h,n) {
var a = 'abcdefghijklmnopqrstuvwxyz',
q = n.trim().slice(-1);
return "contains(translate("+ h +", "+ q + a.toUpperCase() + q +", "+ q + a + q +"),"+ n.toLowerCase() +")";
});
}
return str.toString();
};
}
if (typeof(JSON) === 'undefined') {
window.JSON = {
parse: function (sJSON) { return eval("(" + sJSON + ")"); },
stringify: function (vContent) {
if (vContent instanceof Object) {
var sOutput = "";
if (vContent.constructor === Array) {
for (var nId = 0; nId < vContent.length; sOutput += this.stringify(vContent[nId]) + ",", nId++);
return "[" + sOutput.substr(0, sOutput.length - 1) + "]";
}
if (vContent.toString !== Object.prototype.toString) {
return "\"" + vContent.toString().replace(/"/g, "\\$&") + "\"";
}
for (var sProp in vContent) {
sOutput += "\"" + sProp.replace(/"/g, "\\$&") + "\":" + this.stringify(vContent[sProp]) + ",";
}
return "{" + sOutput.substr(0, sOutput.length - 1) + "}";
}
return typeof vContent === "string" ? "\"" + vContent.replace(/"/g, "\\$&") + "\"" : String(vContent);
}
};
}
/* jshint ignore:end */
if (!JSON.toXML) {
JSON.toXML = function(tree, snapshot) {
'use strict';
var interpreter = {
map : [],
rx_validate_name : /^(?!xml)[a-z_][\w\d.:]*$/i,
rx_node : /<(.+?)( .*?)>/,
rx_constructor : /<(.+?)( d:contr=".*?")>/,
rx_namespace : / xmlns\:d="defiant\-namespace"/,
rx_data : /(<.+?>)(.*?)(<\/d:data>)/i,
rx_function : /function (\w+)/i,
to_xml: function(tree) {
var str = this.hash_to_xml(null, tree);
return Defiant.xmlFromString(str);
},
hash_to_xml: function(name, tree, array_child) {
var is_array = tree.constructor === Array,
elem = [],
attr = [],
key,
val,
val_is_array,
type,
is_attr,
cname,
constr,
cnName,
i;
for (key in tree) {
val = tree[key];
if (val === null || val === undefined || val.toString() === 'NaN') val = null;
is_attr = key.slice(0,1) === '@';
cname = array_child ? name : key;
if (cname == +cname && tree.constructor !== Object) cname = 'd:item';
if (val === null) {
constr = null;
cnName = false;
} else {
constr = val.constructor;
cnName = constr.toString().match(this.rx_function)[1];
}
if (is_attr) {
attr.push( cname.slice(1) +'="'+ this.escape_xml(val) +'"' );
if (cnName !== 'String') attr.push( 'd:'+ cname.slice(1) +'="'+ cnName +'"' );
} else if (val === null) {
elem.push( this.scalar_to_xml( cname, val ) );
} else {
switch (constr) {
case Function:
// if constructor is function, then it's not a JSON structure
// throw ERROR ?
break;
case Object:
elem.push( this.hash_to_xml( cname, val ) );
break;
case Array:
if (key === cname) {
val_is_array = val.constructor === Array;
if (val_is_array) {
i = val.length;
while (i--) {
if (val[i].constructor === Array) val_is_array = true;
if (!val_is_array && val[i].constructor === Object) val_is_array = true;
}
}
elem.push( this.scalar_to_xml( cname, val, val_is_array ) );
break;
}
/* falls through */
case String:
if (typeof(val) === 'string') {
val = val.toString().replace(/\&/g, '&amp;')
.replace(/\r|\n/g, '&#13;');
}
if (cname === '#text') {
// prepare map
this.map.push(tree);
attr.push('d:mi="'+ this.map.length +'"');
attr.push('d:constr="'+ cnName +'"');
elem.push( this.escape_xml(val) );
break;
}
/* falls through */
case Number:
case Boolean:
if (cname === '#text' && cnName !== 'String') {
// prepare map
this.map.push(tree);
attr.push('d:mi="'+ this.map.length +'"');
attr.push('d:constr="'+ cnName +'"');
elem.push( this.escape_xml(val) );
break;
}
elem.push( this.scalar_to_xml( cname, val ) );
break;
}
}
}
if (!name) {
name = 'd:data';
attr.push(Defiant.namespace);
if (is_array) attr.push('d:constr="Array"');
}
if (name.match(this.rx_validate_name) === null) {
attr.push( 'd:name="'+ name +'"' );
name = 'd:name';
}
if (array_child) return elem.join('');
// prepare map
this.map.push(tree);
attr.push('d:mi="'+ this.map.length +'"');
return '<'+ name + (attr.length ? ' '+ attr.join(' ') : '') + (elem.length ? '>'+ elem.join('') +'</'+ name +'>' : '/>' );
},
scalar_to_xml: function(name, val, override) {
var attr = '',
text,
constr,
cnName;
// check whether the nodename is valid
if (name.match(this.rx_validate_name) === null) {
attr += ' d:name="'+ name +'"';
name = 'd:name';
override = false;
}
if (val === null || val.toString() === 'NaN') val = null;
if (val === null) return '<'+ name +' d:constr="null"/>';
if (val.length === 1 && val[0].constructor === Object) {
text = this.hash_to_xml(false, val[0]);
var a1 = text.match(this.rx_node),
a2 = text.match(this.rx_constructor);
a1 = (a1 !== null)? a1[2]
.replace(this.rx_namespace, '')
.replace(/>/, '')
.replace(/"\/$/, '"') : '';
a2 = (a2 !== null)? a2[2] : '';
text = text.match(this.rx_data);
text = (text !== null)? text[2] : '';
return '<'+ name + a1 +' '+ a2 +' d:type="ArrayItem">'+ text +'</'+ name +'>';
} else if (val.length === 0 && val.constructor === Array) {
return '<'+ name +' d:constr="Array"/>';
}
// else
if (override) {
return this.hash_to_xml( name, val, true );
}
constr = val.constructor;
cnName = constr.toString().match(this.rx_function)[1];
text = (constr === Array) ? this.hash_to_xml( 'd:item', val, true )
: this.escape_xml(val);
attr += ' d:constr="'+ cnName +'"';
// prepare map
this.map.push(val);
attr += ' d:mi="'+ this.map.length +'"';
return (name === '#text') ? this.escape_xml(val) : '<'+ name + attr +'>'+ text +'</'+ name +'>';
},
escape_xml: function(text) {
return String(text) .replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/&nbsp;/g, '&#160;');
}
},
doc = interpreter.to_xml.call(interpreter, tree);
// snapshot distinctly improves performance
if (snapshot) {
return {
doc: doc,
src: tree,
map: interpreter.map
};
}
this.search.map = interpreter.map;
return doc;
};
}
if (!JSON.search) {
JSON.search = function(tree, xpath, single) {
'use strict';
var isSnapshot = tree.doc && tree.doc.nodeType,
doc = isSnapshot ? tree.doc : JSON.toXML(tree),
map = isSnapshot ? tree.map : this.search.map,
src = isSnapshot ? tree.src : tree,
xres = Defiant.node[ single ? 'selectSingleNode' : 'selectNodes' ](doc, xpath.xTransform()),
ret = [],
mapIndex,
i;
if (single) xres = [xres];
i = xres.length;
while (i--) {
switch(xres[i].nodeType) {
case 2:
case 3:
ret.unshift( xres[i].nodeValue );
break;
default:
mapIndex = +xres[i].getAttribute('d:mi');
if (map[mapIndex-1]) ret.unshift( map[mapIndex-1] );
}
}
// if environment = development, add search tracing
if (Defiant.env === 'development') {
this.trace = JSON.mtrace(src, ret, xres);
}
return ret;
};
}
if (!JSON.mtrace) {
JSON.mtrace = function(root, hits, xres) {
'use strict';
var win = window,
stringify = JSON.stringify,
sroot = stringify( root, null, '\t' ).replace(/\t/g, ''),
trace = [],
i = 0,
il = xres.length,
od = il ? xres[i].ownerDocument.documentElement : false,
map = this.search.map,
hstr,
cConstr,
fIndex = 0,
mIndex,
lStart,
lEnd;
for (; i<il; i++) {
switch (xres[i].nodeType) {
case 2:
cConstr = xres[i].ownerElement ? xres[i].ownerElement.getAttribute('d:'+ xres[i].nodeName) : 'String';
hstr = '"@'+ xres[i].nodeName +'": '+ win[ cConstr ]( hits[i] );
mIndex = sroot.indexOf(hstr);
lEnd = 0;
break;
case 3:
cConstr = xres[i].parentNode.getAttribute('d:constr');
hstr = win[ cConstr ]( hits[i] );
hstr = '"'+ xres[i].parentNode.nodeName +'": '+ (hstr === 'Number' ? hstr : '"'+ hstr +'"');
mIndex = sroot.indexOf(hstr);
lEnd = 0;
break;
default:
if (xres[i] === od) continue;
if (xres[i].getAttribute('d:constr') === 'String') {
cConstr = xres[i].getAttribute('d:constr');
hstr = win[ cConstr ]( hits[i] );
hstr = '"'+ xres[i].nodeName +'": '+ (hstr === 'Number' ? hstr : '"'+ hstr +'"');
mIndex = sroot.indexOf(hstr, fIndex);
lEnd = 0;
fIndex = mIndex + 1;
} else {
hstr = stringify( hits[i], null, '\t' ).replace(/\t/g, '');
mIndex = sroot.indexOf(hstr);
lEnd = hstr.match(/\n/g).length;
}
}
lStart = sroot.substring(0,mIndex).match(/\n/g).length+1;
trace.push([lStart, lEnd]);
}
return trace;
};
}
Defiant.node.selectNodes = function(XNode, XPath) {
if (XNode.evaluate) {
var ns = XNode.createNSResolver(XNode.documentElement),
qI = XNode.evaluate(XPath, XNode, ns, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null),
res = [],
i = 0,
il = qI.snapshotLength;
for (; i<il; i++) {
res.push( qI.snapshotItem(i) );
}
return res;
} else {
return XNode.selectNodes(XPath);
}
};
Defiant.node.selectSingleNode = function(XNode, XPath) {
if (XNode.evaluate) {
var xI = this.selectNodes(XNode, XPath);
return (xI.length > 0)? xI[0] : null;
} else {
return XNode.selectSingleNode(XPath);
}
};
Defiant.node.prettyPrint = function(node) {
var root = Defiant,
tabs = root.tabsize,
decl = root.xml_decl.toLowerCase(),
ser,
xstr;
if (root.is_ie) {
xstr = node.xml;
} else {
ser = new XMLSerializer();
xstr = ser.serializeToString(node);
}
if (root.env !== 'development') {
// if environment is not development, remove defiant related info
xstr = xstr.replace(/ \w+\:d=".*?"| d\:\w+=".*?"/g, '');
}
var str = xstr.trim().replace(/(>)\s*(<)(\/*)/g, '$1\n$2$3'),
lines = str.split('\n'),
indent = -1,
i = 0,
il = lines.length,
start,
end;
for (; i<il; i++) {
if (i === 0 && lines[i].toLowerCase() === decl) continue;
start = lines[i].match(/<[A-Za-z_\:]+.*?>/g) !== null;
//start = lines[i].match(/<[^\/]+>/g) !== null;
end = lines[i].match(/<\/[\w\:]+>/g) !== null;
if (lines[i].match(/<.*?\/>/g) !== null) start = end = true;
if (start) indent++;
lines[i] = String().fill(indent, '\t') + lines[i];
if (start && end) indent--;
if (!start && end) indent--;
}
return lines.join('\n').replace(/\t/g, String().fill(tabs, ' '));
};
Defiant.node.toJSON = function(xnode, stringify) {
'use strict';
var interpret = function(leaf) {
var obj = {},
win = window,
attr,
type,
item,
cname,
cConstr,
cval,
text,
i, il, a;
switch (leaf.nodeType) {
case 1:
cConstr = leaf.getAttribute('d:constr');
if (cConstr === 'Array') obj = [];
else if (cConstr === 'String' && leaf.textContent === '') obj = '';
attr = leaf.attributes;
i = 0;
il = attr.length;
for (; i<il; i++) {
a = attr.item(i);
if (a.nodeName.match(/\:d|d\:/g) !== null) continue;
cConstr = leaf.getAttribute('d:'+ a.nodeName);
if (cConstr && cConstr !== 'undefined') {
if (a.nodeValue === 'null') cval = null;
else cval = win[ cConstr ]( (a.nodeValue === 'false') ? '' : a.nodeValue );
} else {
cval = a.nodeValue;
}
obj['@'+ a.nodeName] = cval;
}
break;
case 3:
type = leaf.parentNode.getAttribute('d:type');
cval = (type) ? win[ type ]( leaf.nodeValue === 'false' ? '' : leaf.nodeValue ) : leaf.nodeValue;
obj = cval;
break;
}
if (leaf.hasChildNodes()) {
i = 0;
il = leaf.childNodes.length;
for(; i<il; i++) {
item = leaf.childNodes.item(i);
cname = item.nodeName;
attr = leaf.attributes;
if (cname === 'd:name') {
cname = item.getAttribute('d:name');
}
if (cname === '#text') {
cConstr = leaf.getAttribute('d:constr');
if (cConstr === 'undefined') cConstr = undefined;
text = item.textContent || item.text;
cval = cConstr === 'Boolean' && text === 'false' ? '' : text;
if (!cConstr && !attr.length) obj = cval;
else if (cConstr && il === 1) {
obj = win[cConstr](cval);
} else if (!leaf.hasChildNodes()) {
obj[cname] = (cConstr)? win[cConstr](cval) : cval;
} else {
if (attr.length < 3) obj = (cConstr)? win[cConstr](cval) : cval;
else obj[cname] = (cConstr)? win[cConstr](cval) : cval;
}
} else {
if (obj[cname]) {
if (obj[cname].push) obj[cname].push( interpret(item) );
else obj[cname] = [obj[cname], interpret(item)];
continue;
}
cConstr = item.getAttribute('d:constr');
switch (cConstr) {
case 'null':
if (obj.push) obj.push(null);
else obj[cname] = null;
break;
case 'Array':
//console.log( Defiant.node.prettyPrint(item) );
if (item.parentNode.firstChild === item && cConstr === 'Array' && cname !== 'd:item') {
if (cname === 'd:item' || cConstr === 'Array') {
cval = interpret(item);
obj[cname] = cval.length ? [cval] : cval;
} else {
obj[cname] = interpret(item);
}
}
else if (obj.push) obj.push( interpret(item) );
else obj[cname] = interpret(item);
break;
case 'String':
case 'Number':
case 'Boolean':
text = item.textContent || item.text;
cval = cConstr === 'Boolean' && text === 'false' ? '' : text;
if (obj.push) obj.push( win[cConstr](cval) );
else obj[cname] = interpret(item);
break;
default:
if (obj.push) obj.push( interpret( item ) );
else obj[cname] = interpret( item );
}
}
}
}
if (leaf.nodeType === 1 && leaf.getAttribute('d:type') === 'ArrayItem') {
obj = [obj];
}
return obj;
},
node = (xnode.nodeType === 9) ? xnode.documentElement : xnode,
ret = interpret(node),
rn = ret[node.nodeName];
// exclude root, if "this" is root node
if (node === node.ownerDocument.documentElement && rn && rn.constructor === Array) {
ret = rn;
}
if (stringify && stringify.toString() === 'true') stringify = '\t';
return stringify ? JSON.stringify(ret, null, stringify) : ret;
};
// check if jQuery is present
if (typeof(jQuery) !== 'undefined') {
(function ( $ ) {
'use strict';
$.fn.defiant = function(template, xpath) {
this.html( Defiant.render(template, xpath) );
return this;
};
}(jQuery));
}

View file

@ -1,880 +0,0 @@
/* global markdown */
/* global Defiant */
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();
}
}
}

View file

@ -1,256 +0,0 @@
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);
}

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,16 +0,0 @@
/*
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.
*/
function removeDiacritics(e){return e.replace(/[^\u0000-\u007E]/g,function(e){return diacriticsMap[e]||e})}for(var defaultDiacriticsRemovalap=[{base:"A",letters:"AⒶÀÁÂẦẤẪẨÃĀĂẰẮẴẲȦǠÄǞẢÅǺǍȀȂẠẬẶḀĄȺⱯ"},{base:"AA",letters:"Ꜳ"},{base:"AE",letters:"ÆǼǢ"},{base:"AO",letters:"Ꜵ"},{base:"AU",letters:"Ꜷ"},{base:"AV",letters:"ꜸꜺ"},{base:"AY",letters:"Ꜽ"},{base:"B",letters:"BⒷḂḄḆɃƂƁ"},{base:"C",letters:"CⒸĆĈĊČÇḈƇȻꜾ"},{base:"D",letters:"DⒹḊĎḌḐḒḎĐƋƊƉꝹ"},{base:"DZ",letters:"DZDŽ"},{base:"Dz",letters:"DzDž"},{base:"E",letters:"EⒺÈÉÊỀẾỄỂẼĒḔḖĔĖËẺĚȄȆẸỆȨḜĘḘḚƐƎ"},{base:"F",letters:"FⒻḞƑꝻ"},{base:"G",letters:"GⒼǴĜḠĞĠǦĢǤƓꞠꝽꝾ"},{base:"H",letters:"HⒽĤḢḦȞḤḨḪĦⱧⱵꞍ"},{base:"I",letters:"IⒾÌÍÎĨĪĬİÏḮỈǏȈȊỊĮḬƗ"},{base:"J",letters:"JⒿĴɈ"},{base:"K",letters:"KⓀḰǨḲĶḴƘⱩꝀꝂꝄꞢ"},{base:"L",letters:"LⓁĿĹĽḶḸĻḼḺŁȽⱢⱠꝈꝆꞀ"},{base:"LJ",letters:"LJ"},{base:"Lj",letters:"Lj"},{base:"M",letters:"MⓂḾṀṂⱮƜ"},{base:"N",letters:"NⓃǸŃÑṄŇṆŅṊṈȠƝꞐꞤ"},{base:"NJ",letters:"NJ"},{base:"Nj",letters:"Nj"},{base:"O",letters:"OⓄÒÓÔỒỐỖỔÕṌȬṎŌṐṒŎȮȰÖȪỎŐǑȌȎƠỜỚỠỞỢỌỘǪǬØǾƆƟꝊꝌ"},{base:"OI",letters:"Ƣ"},{base:"OO",letters:"Ꝏ"},{base:"OU",letters:"Ȣ"},{base:"OE",letters:"ŒŒ"},{base:"oe",letters:"œœ"},{base:"P",letters:"PⓅṔṖƤⱣꝐꝒꝔ"},{base:"Q",letters:"QⓆꝖꝘɊ"},{base:"R",letters:"RⓇŔṘŘȐȒṚṜŖṞɌⱤꞦꞂ"},{base:"S",letters:"SⓈẞŚṤŜṠŠṦṢṨȘŞⱾꞨꞄ"},{base:"T",letters:"TⓉṪŤṬȚŢṰṮŦƬƮȾꞆ"},{base:"TZ",letters:"Ꜩ"},{base:"U",letters:"UⓊÙÚÛŨṸŪṺŬÜǛǗǕǙỦŮŰǓȔȖƯỪỨỮỬỰỤṲŲṶṴɄ"},{base:"V",letters:"VⓋṼṾƲꝞɅ"},{base:"VY",letters:"Ꝡ"},{base:"W",letters:"WⓌẀẂŴẆẄẈⱲ"},{base:"X",letters:"XⓍẊẌ"},{base:"Y",letters:"YⓎỲÝŶỸȲẎŸỶỴƳɎỾ"},{base:"Z",letters:"ZⓏŹẐŻŽẒẔƵȤⱿⱫꝢ"},{base:"a",letters:"aⓐẚàáâầấẫẩãāăằắẵẳȧǡäǟảåǻǎȁȃạậặḁąⱥɐ"},{base:"aa",letters:"ꜳ"},{base:"ae",letters:"æǽǣ"},{base:"ao",letters:"ꜵ"},{base:"au",letters:"ꜷ"},{base:"av",letters:"ꜹꜻ"},{base:"ay",letters:"ꜽ"},{base:"b",letters:"bⓑḃḅḇƀƃɓ"},{base:"c",letters:"cⓒćĉċčçḉƈȼꜿↄ"},{base:"d",letters:"dⓓḋďḍḑḓḏđƌɖɗꝺ"},{base:"dz",letters:"dzdž"},{base:"e",letters:"eⓔèéêềếễểẽēḕḗĕėëẻěȅȇẹệȩḝęḙḛɇɛǝ"},{base:"f",letters:"fⓕḟƒꝼ"},{base:"g",letters:"gⓖǵĝḡğġǧģǥɠꞡᵹꝿ"},{base:"h",letters:"hⓗĥḣḧȟḥḩḫẖħⱨⱶɥ"},{base:"hv",letters:"ƕ"},{base:"i",letters:"iⓘìíîĩīĭïḯỉǐȉȋịįḭɨı"},{base:"j",letters:"jⓙĵǰɉ"},{base:"k",letters:"kⓚḱǩḳķḵƙⱪꝁꝃꝅꞣ"},{base:"l",letters:"lⓛŀĺľḷḹļḽḻſłƚɫⱡꝉꞁꝇ"},{base:"lj",letters:"lj"},{base:"m",letters:"mⓜḿṁṃɱɯ"},{base:"n",letters:"nⓝǹńñṅňṇņṋṉƞɲʼnꞑꞥ"},{base:"nj",letters:"nj"},{base:"o",letters:"oⓞòóôồốỗổõṍȭṏōṑṓŏȯȱöȫỏőǒȍȏơờớỡởợọộǫǭøǿɔꝋꝍɵ"},{base:"oi",letters:"ƣ"},{base:"ou",letters:"ȣ"},{base:"oo",letters:"ꝏ"},{base:"p",letters:"pⓟṕṗƥᵽꝑꝓꝕ"},{base:"q",letters:"qⓠɋꝗꝙ"},{base:"r",letters:"rⓡŕṙřȑȓṛṝŗṟɍɽꝛꞧꞃ"},{base:"s",letters:"sⓢßśṥŝṡšṧṣṩșşȿꞩꞅẛ"},{base:"t",letters:"tⓣṫẗťṭțţṱṯŧƭʈⱦꞇ"},{base:"tz",letters:"ꜩ"},{base:"u",letters:"uⓤùúûũṹūṻŭüǜǘǖǚủůűǔȕȗưừứữửựụṳųṷṵʉ"},{base:"v",letters:"vⓥṽṿʋꝟʌ"},{base:"vy",letters:"ꝡ"},{base:"w",letters:"wⓦẁẃŵẇẅẘẉⱳ"},{base:"x",letters:"xⓧẋẍ"},{base:"y",letters:"yⓨỳýŷỹȳẏÿỷẙỵƴɏỿ"},{base:"z",letters:"zⓩźẑżžẓẕƶȥɀⱬꝣ"}],diacriticsMap={},i=0;i<defaultDiacriticsRemovalap.length;i++)for(var letters=defaultDiacriticsRemovalap[i].letters,j=0;j<letters.length;j++)diacriticsMap[letters[j]]=defaultDiacriticsRemovalap[i].base;

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -1,194 +0,0 @@
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);
}
}

View file

@ -1,118 +0,0 @@
/*
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.
*/
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;
}
}
// "what?" version ... http://jsperf.com/diacritics/12
function removeDiacritics(str) {
return str.replace(/[^\u0000-\u007E]/g, function(a){
return diacriticsMap[a] || a;
});
}

714
js/ui.js
View file

@ -1,714 +0,0 @@
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();
}

View file

@ -1,11 +1,11 @@
{
"name": "lexiconga",
"title": "Lexiconga",
"version": "1.0.0",
"version": "2.0.0",
"description": "A tool to build simple dictionaries using JSON.",
"main": "src/app.js",
"scripts": {
"start": "node start-server.js",
"serve": "node start-server.js",
"pack": "node ./node_modules/webpack/bin/webpack.js -d --progress --display-error-details",
"watch": "node ./node_modules/webpack/bin/webpack.js -d --progress --watch",
"build": "node ./node_modules/webpack/bin/webpack.js -p --progress"
@ -14,38 +14,33 @@
"type": "git",
"url": "git+https://Alamantus@github.com/Alamantus/Lexiconga.git"
},
"author": "Robbie Antenesse <gamedev@alamantus.com>",
"author": "Robbie Antenesse <dev@alamantus.com>",
"license": "ISC",
"bugs": {
"url": "https://github.com/Alamantus/Lexiconga/issues"
},
"homepage": "https://github.com/Alamantus/Lexiconga#readme",
"dependencies": {
"babel-polyfill": "^6.13.0",
"bulma": "^0.2.3",
"dexie": "^1.5.1",
"inferno": "^1.5.6",
"inferno-component": "^1.0.3",
"json-query": "^2.2.0",
"marked": "^0.3.6",
"papaparse": "^4.1.2",
"react": "^15.3.2",
"react-dom": "^15.3.2",
"react-select": "^1.0.0-rc.2"
},
"devDependencies": {
"babel-core": "^6.14.0",
"babel-loader": "^6.2.5",
"babel-plugin-inferno": "^1.4.0",
"babel-preset-es2015": "^6.14.0",
"babel-preset-react": "^6.11.1",
"css-loader": "^0.25.0",
"express": "^4.14.0",
"file-loader": "^0.9.0",
"html-minify-loader": "^1.1.0",
"node-sass": "^3.10.0",
"sass-loader": "^4.0.2",
"style-loader": "^0.13.1",
"webpack": "^1.13.2"
"babel-core": "^6.24.0",
"babel-loader": "^6.4.1",
"babel-plugin-inferno": "^3.1.0",
"babel-preset-es2016": "^6.22.0",
"css-loader": "^0.28.0",
"express": "^4.15.2",
"file-loader": "^0.11.1",
"node-sass": "^4.5.2",
"sass-loader": "^6.0.3",
"style-loader": "^0.16.1",
"url-loader": "^0.5.8",
"webpack": "^2.3.3"
},
"dependencies": {
"babel-polyfill": "^6.23.0",
"bulma": "^0.4.0",
"dexie": "^1.5.1",
"inferno": "^1.6.0",
"inferno-component": "^1.6.0",
"marked": "^0.3.6",
"papaparse": "^4.2.0"
}
}

View file

@ -1,13 +0,0 @@
<?php
// require_once("../required.php");
require_once('config.php');
require_once(SITE_LOCATION . '/php/functions.php');
$email = htmlspecialchars($_GET['email']);
if (EmailExists($email)) {
echo "email exists";
} else {
echo "ok";
}
?>

View file

@ -1,345 +0,0 @@
<?php
// require_once("../required.php");
require_once('config.php');
require_once(SITE_LOCATION . '/php/functions.php');
session_start();
if ($_SESSION['user'] > 0) {
if ($_GET['action'] == 'getall') {
Get_Dictionaries(true);
}
elseif ($_GET['action'] == 'load') {
Load_Current_Dictionary();
}
elseif ($_GET['action'] == 'new') {
Save_Current_DictionaryAsNew();
}
elseif ($_GET['action'] == 'update') {
Update_Current_Dictionary();
}
elseif ($_GET['action'] == 'wordall') {
Save_New_Word(true);
}
elseif ($_GET['action'] == 'wordnew') {
Save_New_Word(false);
}
elseif ($_GET['action'] == 'wordupdate') {
Update_Word();
}
elseif ($_GET['action'] == 'switch') {
Switch_Current_Dictionary($_POST['newdictionaryid'], true);
}
elseif ($_GET['action'] == 'delete') {
Delete_Current_Dictionary();
}
elseif ($_GET['action'] == 'worddelete') {
Delete_Word();
}
} else {
echo "not signed in";
}
function Get_Dictionaries($return_list = true) {
$query = "SELECT `id`, `name` FROM `dictionaries` WHERE `user`=" . $_SESSION['user'] . " ORDER BY `name` ASC;";
$dictionaries = query($query);
if ($dictionaries) {
if (num_rows($dictionaries) > 0) {
if ($return_list) {
$list = "";
$_SESSION['dictionaries'] = [];
while ($dict = fetch($dictionaries)) {
$_SESSION['dictionaries'][] = $dict['id']; // Save a list of all dictionaries user has.
//list for the switch dictionaries dropdown.
$list .= $dict['id'] . '_IDNAMESEPARATOR_' . $dict['name'] . '_DICTIONARYSEPARATOR_';
}
echo $list;
}
return true;
} else {
echo "no dictionaries";
}
} else {
echo "could not load";
}
return false;
}
function Load_Current_Dictionary() {
$query = "SELECT `d`.`id`, `d`.`name`, `d`.`description`, `u`.`public_name`, `d`.`words`, `d`.`next_word_id`, `d`.`allow_duplicates`, `d`.`case_sensitive`, `d`.`parts_of_speech`, `d`.`sort_by_equivalent`, `d`.`is_complete`, `d`.`is_public` ";
$query .= "FROM `dictionaries` AS `d` LEFT JOIN `users` AS `u` ON `user`=`u`.`id` WHERE `d`.`id`=`u`.`current_dictionary` AND `user`=" . $_SESSION['user'] . ";";
$dictionary = query($query);
if ($dictionary) {
if (num_rows($dictionary) > 0) {
if (num_rows($dictionary) === 1) {
while ($dict = fetch($dictionary)) {
$_SESSION['dictionary'] = $dict['id'];
$json = '{"name":"' . $dict['name'] . '",';
$json .= '"description":"' . $dict['description'] . '",';
$json .= '"createdBy":"' . $dict['public_name'] . '",';
$json .= '"words":[' . Get_Dictionary_Words($_SESSION['dictionary']) . '],';
$json .= '"nextWordId":' . $dict['next_word_id'] . ',';
$json .= '"settings":{';
$json .= '"allowDuplicates":' . (($dict['allow_duplicates'] == 1) ? 'true' : 'false') . ',';
$json .= '"caseSensitive":' . (($dict['case_sensitive'] == 1) ? 'true' : 'false') . ',';
$json .= '"partsOfSpeech":"' . $dict['parts_of_speech'] . '",';
$json .= '"sortByEquivalent":' . (($dict['sort_by_equivalent'] == 1) ? 'true' : 'false') . ',';
$json .= '"isComplete":' . (($dict['is_complete'] == 1) ? 'true' : 'false') . ',';
$json .= '"isPublic":' . (($dict['is_public'] == 1) ? 'true' : 'false') . '},';
$json .= '"externalID":' . $dict['id'] . '}';
echo $json;
return true;
}
} else {
echo "more than 1 returned";
}
} else {
echo "no dictionaries";
}
} else {
echo "could not load";
}
return false;
}
function Get_Dictionary_Words($dictionary) {
$query = "SELECT `w`.`word_id`, `w`.`name`, `w`.`pronunciation`, `w`.`part_of_speech`, `w`.`simple_definition`, `w`.`long_definition` ";
$query .= "FROM `words` AS `w` LEFT JOIN `dictionaries` AS `d` ON `w`.`dictionary`=`d`.`id` WHERE `w`.`dictionary`=" . $dictionary . " ";
$query .= "ORDER BY IF(`d`.`sort_by_equivalent`, `w`.`simple_definition`, `w`.`name`) COLLATE utf8_unicode_ci;";
$words = query($query);
$results = "";
$processed = 0;
if ($words) {
if (num_rows($words) > 0) {
while ($word = fetch($words)) {
$results .= '{"name":"' . $word['name'] . '",';
$results .= '"pronunciation":"' . $word['pronunciation'] . '",';
$results .= '"partOfSpeech":"' . $word['part_of_speech'] . '",';
$results .= '"simpleDefinition":"' . $word['simple_definition'] . '",';
$results .= '"longDefinition":"' . $word['long_definition'] . '",';
$results .= '"wordId":' . $word['word_id'] . '}';
// If it's the last one, then don't add a comma.
if (++$processed < num_rows($words)) {
$results .= ",";
}
}
}
}
return $results;
}
function Save_Current_DictionaryAsNew() {
$dbconnection = new PDO('mysql:host=' . DATABASE_SERVERNAME . ';dbname=' . DATABASE_NAME . ';charset=utf8', DATABASE_USERNAME, DATABASE_PASSWORD);
$dbconnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbconnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbconnection->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$query = "INSERT INTO `dictionaries`(`user`, `name`, `description`, `next_word_id`, `allow_duplicates`, `case_sensitive`, `parts_of_speech`, `sort_by_equivalent`, `is_complete`, `is_public`) ";
$query .= "VALUES (" . $_SESSION['user'] . ",'" . $_POST['name'] . "','" . $_POST['description'] . "'," . $_POST['nextwordid'] . "," . $_POST['allowduplicates'] . "," . $_POST['casesensitive'] . ",'" . $_POST['partsofspeech'] . "'," . $_POST['sortbyequivalent'] . "," . $_POST['iscomplete'] . "," . $_POST['ispublic'] . ")";
try {
$update = $dbconnection->prepare($query);
$update->execute();
$_SESSION['dictionary'] = $dbconnection->lastInsertId();
$_SESSION['dictionaries'][] = $_SESSION['dictionary']; //Add new id to valid dictionaries.
echo $_SESSION['dictionary'];
Switch_Current_Dictionary($_SESSION['dictionary'], false);
return true;
}
catch (PDOException $ex) {
$errorMessage = $dbconnection->errorInfo();
echo "could not update:\n" . $errorMessage[2] . "\n" . $query;
}
return false;
}
function Update_Current_Dictionary() {
if (isset($_SESSION['dictionary'])) {
$query = "UPDATE `dictionaries` SET ";
if (isset($_POST['name'])) {
$query .= "`name`='" . $_POST['name'] . "', ";
}
if (isset($_POST['description'])) {
$query .= "`description`='" . $_POST['description'] . "', ";
}
if (isset($_POST['nextwordid'])) {
$query .= "`next_word_id`=" . $_POST['nextwordid'] . ", ";
}
if (isset($_POST['allowduplicates'])) {
$query .= "`allow_duplicates`=" . $_POST['allowduplicates'] . ", ";
}
if (isset($_POST['casesensitive'])) {
$query .= "`case_sensitive`=" . $_POST['casesensitive'] . ", ";
}
if (isset($_POST['partsofspeech'])) {
$query .= "`parts_of_speech`='" . $_POST['partsofspeech'] . "', ";
}
if (isset($_POST['sortbyequivalent'])) {
$query .= "`sort_by_equivalent`='" . $_POST['sortbyequivalent'] . "', ";
}
if (isset($_POST['iscomplete'])) {
$query .= "`is_complete`=" . $_POST['iscomplete'] . ", ";
}
if (isset($_POST['ispublic'])) {
$query .= "`is_public`=" . $_POST['ispublic'] . ", ";
}
$query .= "`last_updated`='" . date("Y-m-d H:i:s") . "'";
$query .= " WHERE `id`=" . $_SESSION['dictionary'] . " AND `user`=" . $_SESSION['user'] . ";";
$update = query($query);
if ($update) {
echo "updated successfully";
return true;
} else {
echo "could not update";
}
} else {
Save_Current_DictionaryAsNew();
}
return false;
}
function Save_New_Word($multiple = false) {
if (in_array($_GET['dict'], $_SESSION['dictionaries'])) { // Make sure that the given dictionary is valid before using it in the query.
// Allows users to update previously open dictionaries if they accidentally change dictionaries while in another window and go back.
$worddata = json_decode(file_get_contents("php://input"), true);
$dbconnection = new PDO('mysql:host=' . DATABASE_SERVERNAME . ';dbname=' . DATABASE_NAME . ';charset=utf8', DATABASE_USERNAME, DATABASE_PASSWORD);
$dbconnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbconnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
$dbconnection->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$query = "UPDATE `dictionaries` SET `next_word_id`=" . $_GET['nextwordid'] . ", `last_updated`='" . date("Y-m-d H:i:s") . "' WHERE `id`=" . $_GET['dict'] . "; ";
$query .= "INSERT IGNORE INTO `words`(`dictionary`, `word_id`, `name`, `pronunciation`, `part_of_speech`, `simple_definition`, `long_definition`) ";
$query .= "VALUES ";
if ($multiple) {
for ($i = 0; $i < count($worddata); $i++) {
if ($i > 0) {
$query .= ", ";
}
$query .= "(" . $_GET['dict'] . "," . $worddata[$i]['wordId'] . ",'" . $worddata[$i]['name'] . "','" . $worddata[$i]['pronunciation'] . "','" . $worddata[$i]['partOfSpeech'] . "','" . $worddata[$i]['simpleDefinition'] . "','" . $worddata[$i]['longDefinition'] . "')";
}
} else {
$query .= "(" . $_GET['dict'] . "," . $worddata['wordId'] . ",'" . $worddata['name'] . "','" . $worddata['pronunciation'] . "','" . $worddata['partOfSpeech'] . "','" . $worddata['simpleDefinition'] . "','" . $worddata['longDefinition'] . "')";
}
$query .= ";";
try {
$update = $dbconnection->prepare($query);
$update->execute();
echo "added successfully";
return true;
}
catch (PDOException $ex) {
echo "could not update:\n" . $ex->getMessage() . "\n" . $query;
}
} else {
echo "specified dictionary is not owned by user";
}
return false;
}
function Update_Word() {
if (in_array($_GET['dict'], $_SESSION['dictionaries'])) { // Make sure that the given dictionary is valid before using it in the query.
// Allows users to update previously open dictionaries if they accidentally change dictionaries while in another window and go back.
$worddata = json_decode(file_get_contents("php://input"), true);
$query = "UPDATE `words` SET ";
$query .= "`name`='" . $worddata['name'] . "', ";
$query .= "`pronunciation`='" . $worddata['pronunciation'] . "', ";
$query .= "`part_of_speech`='" . $worddata['partOfSpeech'] . "', ";
$query .= "`simple_definition`='" . $worddata['simpleDefinition'] . "', ";
$query .= "`long_definition`='" . $worddata['longDefinition'] . "', ";
$query .= "`last_updated`='" . date("Y-m-d H:i:s") . "'";
$query .= " WHERE `dictionary`=" . $_GET['dict'] . " AND `word_id`=" . $worddata['wordId'] . ";";
$update = query($query);
if ($update) {
echo "updated successfully";
return true;
} else {
echo "could not update";
}
} else {
echo "specified dictionary is not owned by user";
}
return false;
}
function Switch_Current_Dictionary($newdictionaryid, $returndictionary = true) {
if (isset($newdictionaryid)) {
if (in_array($newdictionaryid, $_SESSION['dictionaries'])) {
//Clear is_current from all user's dictionaries and then update the one they chose, only if the chosen dictionary is valid.
$query .= "UPDATE `users` SET `current_dictionary`=" . $newdictionaryid . " WHERE `id`=" . $_SESSION['user'] . ";";
$update = query($query);
if ($update) {
if ($returndictionary) {
Load_Current_Dictionary();
} else {
echo "dictionary switched";
}
// return true;
} else {
echo "could not update";
}
} else {
echo "invalid dictionary";
}
} else {
echo "no info provided";
}
return false;
}
function Delete_Current_Dictionary() {
if (isset($_SESSION['dictionary'])) {
if (in_array($_SESSION['dictionary'], $_SESSION['dictionaries'])) {
//Clear is_current from all user's dictionaries and then update the one they chose, only if the chosen dictionary is valid.
$query = "DELETE FROM `dictionaries` WHERE `id`=" . $_SESSION['dictionary'] . " AND `user`=" . $_SESSION['user'] . ";";
$update = query($query);
if ($update) {
Get_Dictionaries(true);
} else {
echo "could not delete";
}
} else {
echo "invalid dictionary";
}
} else {
echo "no current dictionary";
}
return false;
}
function Delete_Word() {
if (isset($_SESSION['dictionary'])) {
if (in_array($_POST['dict'], $_SESSION['dictionaries'])) { // Make sure that the given dictionary is valid before using it in the query.
// Allows users to update previously open dictionaries if they accidentally change dictionaries while in another window and go back.
//Clear is_current from all user's dictionaries and then update the one they chose, only if the chosen dictionary is valid.
$query = "DELETE FROM `words` WHERE `dictionary`=" . $_POST['dict'] . " AND `word_id`=" . $_POST['word'] . ";";
$update = query($query);
if ($update) {
echo "deleted successfully";
} else {
echo "could not delete: " . $_POST['dict'] . "-" . $_POST['word'] . " caused a problem";
}
} else {
echo "invalid dictionary";
}
} else {
echo "no current dictionary";
}
return false;
}
?>

View file

@ -1,13 +0,0 @@
<?php
// require_once("../required.php");
require_once('config.php');
require_once(SITE_LOCATION . '/php/functions.php');
$email = htmlspecialchars($_GET['email']);
if (EmailExists($email)) {
echo "email exists";
} else {
echo "bad email";
}
?>

View file

@ -1,13 +0,0 @@
<?php
define("ROOT", $_SERVER["DOCUMENT_ROOT"]);
define("SITE_NAME", "Lexiconga");
define("SITE_LOCATION", ROOT . "/.Lexiconga"); // For absolute file paths: SITE_LOCATION . "/whatever.php"
define("DATABASE_TYPE", "mysql"); //sqlite, mysql, pgsql
define("DATABASE_SERVERNAME", "host");
define("DATABASE_USERNAME", "username");
define("DATABASE_PASSWORD", "password");
define("DATABASE_NAME", "databasename");
?>

View file

@ -1,11 +0,0 @@
<?php
function Show_Dictionary_Function($prevent_edit) {
// Used to determine which JavaScript display function to use.
// $prevent_edit is a boolean value.
if ($prevent_edit) {
echo "ShowPublicDictionary()";
} else {
echo "ShowDictionary()";
}
}
?>

View file

@ -1,10 +0,0 @@
<?php
// Put your function files here, and they'll be added everywhere require.php is!
require_once(SITE_LOCATION . '/php/helpers.php');
require_once(SITE_LOCATION . '/php/plugins/easycrypt.php');
require_once(SITE_LOCATION . '/php/validation.php');
require_once(SITE_LOCATION . '/php/passwordreset.php');
require_once(SITE_LOCATION . '/php/display.php');
?>

View file

@ -1,85 +0,0 @@
<?php
// Simplified PHP functions
function query ($query_string) {
$dbconnection = new PDO('mysql:host=' . DATABASE_SERVERNAME . ';dbname=' . DATABASE_NAME . ';charset=utf8', DATABASE_USERNAME, DATABASE_PASSWORD);
$dbconnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbconnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
$dbconnection->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
try {
$queryResults = $dbconnection->prepare($query_string);
$queryResults->execute();
return $queryResults;
}
catch (PDOException $ex) {
return false;
}
}
function num_rows ($query_results) {
try {
$rowcount = $query_results->rowcount();
return $rowcount;
}
catch (PDOException $ex) {
return false;
}
}
function fetch ($query_results) {
try {
$fetchassoc = $query_results->fetch();
return $fetchassoc;
}
catch (PDOException $ex) {
return false;
}
}
function get_include_contents($filename) {
if (is_file($filename)) {
ob_start();
include $filename;
return ob_get_clean();
}
return false;
}
function ordinal($number) {
// Retrieved from http://stackoverflow.com/a/3110033/3508346
$ends = array('th','st','nd','rd','th','th','th','th','th','th');
if ((($number % 100) >= 11) && (($number%100) <= 13))
return $number. 'th';
else
return $number. $ends[$number % 10];
}
function time_elapsed($secs){
// Retrieved from http://php.net/manual/en/function.time.php#108581
$bit = array(
// ' year' => $secs / 31556926 % 12,
// ' week' => $secs / 604800 % 52,
// ' day' => $secs / 86400 % 7,
// ' hour' => $secs / 3600 % 24,
' minute' => $secs / 60 % 60,
' second' => $secs % 60
);
foreach($bit as $k => $v){
if($v > 1 || $v < 1)$ret[] = $v . $k . 's';
if($v == 1)$ret[] = $v . $k;
}
array_splice($ret, count($ret)-1, 0, 'and');
//$ret[] = 'ago.';
return join(' ', $ret);
}
function random_string($length = 10) {
// Retrieved from http://stackoverflow.com/a/4356295/3508346
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
?>

View file

@ -1,211 +0,0 @@
<?php
// Notification messages based on status.
if (isset($_SESSION['current_status']) && $_SESSION['current_status'] != "") {
switch ($_SESSION['current_status']) {
case "couldnotcreate":
$notificationMessage = "Could not create account.<br>Please try again later.";
break;
case "emailcreateinvalid":
$notificationMessage = "The email address used to create your account didn't work.<br>Please try another.";
break;
case "createemailorpasswordblank":
$notificationMessage = "The create account form somehow got submitted without some essential information.<br>Please try filling it out again.";
break;
case "couldnotsendresetemail":
$notificationMessage = "For some reason, the reset email could not be sent.<br>Please try again later.";
break;
case "couldnotsetresetlink":
$notificationMessage = "The email address specified for password reset does not have an account.";
break;
case "emailresetinvalid":
$notificationMessage = "The email address specified for password reset didn't work.<br>Please try again.";
break;
case "resetemailblank":
$notificationMessage = "The password reset form somehow got submitted without some essential information.<br>Please try filling it out again.";
break;
case "loginfailed":
$notificationMessage = "We couldn't log you in because your email or password was incorrect.<br>";
$_SESSION['loginfailures'] += 1;
if ($_SESSION['loginfailures'] < 10) {
$notificationMessage .= "This is your <strong>" . ordinal($_SESSION['loginfailures']) . "</strong> failed attempt.<br>After 10 failures, you will not be able to log in for 1 hour.<br>Please try again.";
} else {
$_SESSION['loginlockouttime'] = time();
$notificationMessage .= "Since you failed to log in successfully 10 times, you may not try again for 1 hour.";
}
break;
case "emaildoesnotexist":
$notificationMessage = "The email address you entered doesn't have an account.<br>Would you like to <span class='clickable' onclick='ShowInfo(\"loginForm\")'>create an account</span>?";
break;
case "emailinvalid":
$notificationMessage = "The email address you entered didn't work.<br>Please try another.";
break;
case "resetlinkfailed":
$notificationMessage = "The reset link used is not valid. Please make sure you have copied it correctly.";
break;
case "resetlinkinvalid":
$notificationMessage = "The reset link used is not valid. Please make sure you have copied it correctly.";
break;
case "couldnotresetpassword":
$notificationMessage = "Your password could not be reset at this time. Please try again later.<br>If you remember your old password, you may still use it to log in.";
break;
case "passwordresetinvalid":
$notificationMessage = "Something went wrong in the password reset process. Please try again.";
break;
case "newpasswordblank":
$notificationMessage = "All the necessary information did not make it through for your password reset. Please try again.";
break;
case "couldnotupdatesettings":
$notificationMessage = "Could not update your account settings. Please try again.";
break;
case "accountsettingsinvalid":
$notificationMessage = "The email address you entered was either not valid or is already in use by another user. Please choose a different email address if you want to update your account email.";
break;
case "createdaccountsuccessfully":
$notificationMessage = "Your account was created successfully!<br>Please log in using the email address and password you used to create it and you can start accessing your dictionaries anywhere!";
break;
case "resetemailsent":
$notificationMessage = "The password reset link has been sent to the email you specified.<br>If you do not see it in your inbox, please check your junk mail box just in case!<br>Be sure to use the link before the end of today or else you will need to request a new one.";
break;
case "showresetform":
$notificationMessage = '<script>document.getElementById("notificationCloseButton").style.display = "none";</script>
<form id="resetPasswordForm" method="post" action="?resetpassword" style="text-align:left;">
<h2 style="margin-top: 3px;">Reset Your Password</h2>
<label><span>New Password</span>
<input type="password" id="newPasswordField" name="password" />
</label>
<label><span>Confirm Password</span>
<input type="password" id="newPasswordConfirmField" name="confirmpassword" />
</label>
<input type="hidden" name="account" value="' . Get_User_Email($_SESSION['reset_account']) . '" />
<div id="resetPasswordError" style="font-weight:bold;color:red;"></div>
<button type="submit" id="createAccountSubmitButton" onclick="ValidateResetPassword(); return false;">Set New Password</button>
</form>';
break;
case "passwordresetsuccessfully":
$notificationMessage = "Your password has been successfully reset. You may now log in using your new password.";
break;
case "accountsettingsupdated":
$notificationMessage = "Your settings have been updated.";
break;
}
$_SESSION['current_status'] = "";
}
if (isset($_GET['logout']) && $current_user > 0) {
session_destroy();
header('Location: ./?loggedout');
}
elseif (isset($_GET['login']) && $current_user <= 0) {
if (isset($_POST['email']) && isset($_POST['password'])) {
if (filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
if (EmailExists($_POST['email'])) {
if (Validate_Login($_POST['email'], $_POST['password'])) {
$_SESSION['user'] = Get_User_Id($_POST['email']);
query("UPDATE `users` SET `last_login`='" . date("Y-m-d H:i:s") . "' WHERE `id`=" . $_SESSION['user'] . ";");
} else {
$_SESSION['current_status'] = "loginfailed";
}
} else {
$_SESSION['current_status'] = "emaildoesnotexist";
}
} else {
$_SESSION['current_status'] = "emailinvalid";
}
} else {
$_SESSION['current_status'] = "loginemailorpasswordblank";
}
header('Location: ./');
}
elseif (isset($_GET['createaccount'])) {
if (isset($_POST['email']) && isset($_POST['password'])) {
if (filter_var($_POST['email'], FILTER_VALIDATE_EMAIL) && !EmailExists($_POST['email'])) {
if (query("INSERT INTO users (email, password, public_name, allow_email) VALUES ('" . $_POST['email'] . "','" . crypt($_POST['password'], $_POST['email']) . "','" . htmlspecialchars($_POST['publicname'], ENT_QUOTES) . "'," . (($_POST['allowemails'] != "on") ? 0 : 1) . ")")) {
$_SESSION['current_status'] = "createdaccountsuccessfully";
} else {
$_SESSION['current_status'] = "couldnotcreate";
}
} else {
$_SESSION['current_status'] = "emailcreateinvalid";
}
} else {
$_SESSION['current_status'] = "createemailorpasswordblank";
}
header('Location: ./');
}
elseif (isset($_GET['forgot'])) {
if (isset($_POST['email'])) {
if (filter_var($_POST['email'], FILTER_VALIDATE_EMAIL) && EmailExists($_POST['email'])) {
$reset_email = Set_Password_Reset($_POST['email']);
if ($reset_email === true) {
$_SESSION['current_status'] = "resetemailsent";
} elseif ($reset_email === "could not send") {
$_SESSION['current_status'] = "couldnotsendresetemail";
} else {
$_SESSION['current_status'] = "couldnotsetresetlink";
}
} else {
$_SESSION['current_status'] = "emailresetinvalid";
}
} else {
$_SESSION['current_status'] = "resetemailblank";
}
header('Location: ./');
}
elseif (isset($_GET['passwordreset'])) {
if (isset($_GET['account']) && isset($_GET['code'])) {
$reset_email = Check_Password_Reset($_GET['account'], $_GET['code']);
if ($reset_email == true) {
$_SESSION['current_status'] = "showresetform";
$_SESSION['reset_account'] = $_GET['account'];
} else {
$_SESSION['current_status'] = "resetlinkfailed";
}
} else {
$_SESSION['current_status'] = "resetlinkinvalid";
}
header('Location: ./');
}
elseif (isset($_GET['resetpassword'])) {
if (isset($_POST['account']) && isset($_POST['password'])) {
if (filter_var($_POST['account'], FILTER_VALIDATE_EMAIL) && EmailExists($_POST['account'])) {
$reset_password_success = Reset_Password($_POST['password'], $_POST['account']);
if ($reset_password_success == true) {
$_SESSION['current_status'] = "passwordresetsuccessfully";
} else {
$_SESSION['current_status'] = "couldnotresetpassword";
}
} else {
$_SESSION['current_status'] = "passwordresetinvalid";
}
} else {
$_SESSION['current_status'] = "newpasswordblank";
}
header('Location: ./');
}
elseif (isset($_GET['accountsettings'])) {
if (filter_var($_POST['email'], FILTER_VALIDATE_EMAIL) &&
($_POST['email'] == Get_User_Email($current_user) || !EmailExists($_POST['email'])))
{
$public_name = (isset($_POST['publicname']) && $_POST['publicname'] != "") ? $_POST['publicname'] : "Someone";
if (query("UPDATE `users` SET `email`='" . $_POST['email'] . "', `public_name`='" . htmlspecialchars($public_name, ENT_QUOTES) . "', `allow_email`=" . (($_POST['allowemails'] != "on") ? 0 : 1) . " WHERE `id`=" . $current_user . ";")) {
$_SESSION['current_status'] = "accountsettingsupdated";
} else {
$_SESSION['current_status'] = "couldnotupdatesettings";
}
} else {
$_SESSION['current_status'] = "accountsettingsinvalid";
}
header('Location: ./');
}
elseif (isset($_GET['loggedout']) && $current_user <= 0) {
$notificationMessage = "You have been successfully logged out.<br>You will only be able to use the dictionary saved to your browser.";
} elseif ($current_user > 0) {
if ($notificationMessage != "") {
$notificationMessage = "Welcome back, " . Get_Public_Name_By_Id($current_user) . "!<br>" . $notificationMessage;
} else {
$notificationMessage = "Welcome back, " . Get_Public_Name_By_Id($current_user) . "!";
}
}
?>

View file

@ -1,53 +0,0 @@
<?php
function Set_Password_Reset($email) {
$date = date("Y-m-d H:i:s");
$reset_code = random_string(20);
$query = "UPDATE `users` SET `password_reset_code`='" . $reset_code . "', `password_reset_date`='" . $date . "' WHERE `email`='" . $email . "';";
$reset = query($query);
if ($reset) {
$to = $email;
$subject = "Here's your Lexiconga password reset link";
$message = "Hello " . Get_Public_Name_By_Email($email) . "\r\n\r\nSomeone has requested a password reset link for your Lexiconga account. If it was you, you can reset your password by going to the link below and entering a new password for yourself:\r\n";
$message .= "http://lexicon.ga/?passwordreset&account=" . Get_User_Id($email) . "&code=" . $reset_code . "\r\n\r\n";
$message .= "If it wasn't you who requested the link, you can ignore this email since it was only sent to you, but you might want to consider changing your password when you have a chance.\r\n\r\n";
$message .= "The password link will only be valid for today until you use it.\r\n\r\n";
$message .= "Thanks!\r\nThe Lexiconga Admins";
$header = "From: Lexiconga Password Reset <donotreply@lexicon.ga>\r\n" .
"Reply-To: help@lexicon.ga\r\n" .
"X-Mailer: PHP/" . phpversion();
if (mail($to, $subject, $message, $header)) {
return true;
} else {
return "could not send";
}
} else {
return false;
}
}
function Check_Password_Reset($id, $code) {
$date = date("Y-m-d");
$daterange = "'" . $date . " 00:00:00' AND '" . $date . " 23:59:59'";
$query = "SELECT * FROM `users` WHERE `id`='" . $id . "' AND `password_reset_code`='" . $code . "' AND `password_reset_date` BETWEEN " . $daterange . ";";
$users = query($query);
if ($users && num_rows($users) === 1) {
return true;
} else {
return false;
}
}
function Reset_Password($password, $email) {
$query = "UPDATE `users` SET `password`='" . crypt($password, $email) . "', `password_reset_date`='0000-00-00 00:00:00' WHERE `email`='" . $email . "';";
$reset = query($query);
if ($reset) {
return true;
} else {
return false;
}
}
?>

View file

@ -1,43 +0,0 @@
<?php
/**
* simple method to encrypt or decrypt a plain text string
* initialization vector(IV) has to be the same when encrypting and decrypting
* PHP 5.4.9
*
* Retrieved from:
* https://naveensnayak.wordpress.com/2013/03/12/simple-php-encrypt-and-decrypt/
*
* this is a beginners template for simple encryption decryption
* before using this in production environments, please read about encryption
*
* @param string $action: can be 'encrypt' or 'decrypt'
* @param string $string: string to encrypt or decrypt
* @param string $key: encryption key
* @param string $iv: encryption iv
*
* @return string
*/
function easy_crypt($action, $string, $key = "Encryption-Key", $iv="What-even-is-an-IV?") {
$output = false;
$encrypt_method = "AES-256-CBC";
$secret_key = $key;
$secret_iv = $iv;
// hash
$key = hash('sha256', $secret_key);
// iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
$iv = substr(hash('sha256', $secret_iv), 0, 16);
if( $action == 'encrypt' ) {
$output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
$output = base64_encode($output);
}
else if( $action == 'decrypt' ){
$output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
}
return $output;
}
?>

View file

@ -1,104 +0,0 @@
<?php
function EmailExists($email) {
$query = "SELECT * FROM `users` WHERE `email`='" . $email . "'";
$users = query($query);
if ($users && num_rows($users) > 0) {
return true;
} else {
return false;
}
}
function Validate_Login($email, $password) {
$hashed_pw = crypt($password, $email);
$query = "SELECT * FROM `users` WHERE `email`='" . $email . "' AND `password`='" . $hashed_pw . "'";
$users = query($query);
if ($users && num_rows($users) === 1) {
return true;
} else {
return false;
}
}
function Get_User_Id($email) {
$query = "SELECT `id` FROM `users` WHERE `email`='" . $email . "'";
$users = query($query);
if ($users && num_rows($users) > 0) {
if (num_rows($users) === 1) {
$user = fetch($users);
return $user["id"];
} else {
return "More than one user id returned!";
}
} else {
return "No User";
}
}
function Get_User_Email($id) {
$query = "SELECT `email` FROM `users` WHERE `id`='" . $id . "'";
$users = query($query);
if ($users && num_rows($users) > 0) {
if (num_rows($users) === 1) {
$user = fetch($users);
return $user["email"];
} else {
return "More than one user id returned!";
}
} else {
return "No User";
}
}
function Get_Public_Name_By_Id($id) {
$query = "SELECT `public_name` FROM `users` WHERE `id`=" . $id . ";";
$users = query($query);
if ($users && num_rows($users) > 0) {
if (num_rows($users) === 1) {
$user = fetch($users);
return $user["public_name"];
} else {
return "More than one public name returned!";
}
} else {
return "No User";
}
}
function Get_Public_Name_By_Email($email) {
$query = "SELECT `public_name` FROM `users` WHERE `email`='" . $email . "';";
$users = query($query);
if ($users && num_rows($users) > 0) {
if (num_rows($users) === 1) {
$user = fetch($users);
return $user["public_name"];
} else {
return "More than one public name returned!";
}
} else {
return "No User";
}
}
function Get_Allow_Email_By_Id($id) {
$query = "SELECT `allow_email` FROM `users` WHERE `id`=" . $id . ";";
$users = query($query);
if ($users && num_rows($users) > 0) {
if (num_rows($users) === 1) {
$user = fetch($users);
return $user["allow_email"];
} else {
return "More than one user returned!";
}
} else {
return "No User";
}
}
?>

View file

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

17
public/index.html Normal file
View file

@ -0,0 +1,17 @@
<!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">
</head>
<body>
<div id="site"></div>
<script src="lexiconga.js"></script>
</body>
</html>

View file

@ -1,5 +0,0 @@
<?php
// Include this on every page with require_once('required.php'), and you shouldn't need to have any others.
require_once('php/config.php');
require_once(SITE_LOCATION . '/php/functions.php');
?>

View file

@ -1,81 +0,0 @@
// import React from 'react';
import Inferno from 'inferno';
import Component from 'inferno-component';
import {Button} from '../input/Button';
// Creates a page that floats above other elements when a connected button is clicked.
// export class FixedPage extends React.Component {
export class FixedPage extends Component {
constructor(props) {
super(props);
this.state = {
display: false
};
// Bind each instance to its own show/hide watchers.
this.show = this.show.bind(this);
this.hide = this.hide.bind(this);
}
conditionalDisplay() {
if (this.state.display) {
let contentClass = 'modal-content fixed-page-content';
if (this.props.contentClass) {
contentClass += ' ' + this.props.contentClass;
}
return (
<div id={this.props.id} className='modal is-active'>
<div className='modal-background' onClick={this.hide}></div>
<div className={contentClass}>
<div className='box'>
<Button classes='modal-close'
action={this.hide}
label='Close' />
{this.props.children}
</div>
</div>
</div>
);
} else {
return (
<Button classes={this.props.buttonClasses}
action={this.show}
label={this.props.buttonText} />
);
}
}
show() {
this.setState({
display: true
});
}
hide() {
if (this.props.onHide) {
this.props.onHide();
}
this.setState({
display: false
});
}
render() {
return (
<div className='inline'>
{this.conditionalDisplay()}
</div>
);
}
}

View file

@ -1,121 +0,0 @@
// import React from 'react';
import Inferno from 'inferno';
import Component from 'inferno-component';
import marked from 'marked';
import {WordForm} from '../forms/WordForm';
import {Button} from '../input/Button';
const saveIcon = <i>&#128190;</i>;
const editIcon = <i>&#128393;</i>;
// A component to show dictionary information in a tabbed interface.
// export class InfoDisplay extends React.Component {
export class InfoDisplay extends Component {
constructor(props) {
super(props);
this.state = {
isDisplayed: props.startDisplayed || false,
tabDisplay: 0
};
}
showTabbedInterface() {
if (this.state.isDisplayed) {
return (
<div className='dictionary-info'>
<Button classes={'inline-button' + ((this.state.tabDisplay === 0) ? ' selected-tab' : '')}
action={() => this.changeTab(0)}
label='Description' />
<Button classes={'inline-button' + ((this.state.tabDisplay === 1) ? ' selected-tab' : '')}
action={() => this.changeTab(1)}
label='Details' />
<div className='tabbed-interface'>
{this.displaySelectedTab()}
</div>
</div>
);
}
}
toggleDisplay() {
this.setState({
isDisplayed: !this.state.isDisplayed
});
}
displaySelectedTab() {
switch(this.state.tabDisplay) {
case 1: {
return (
<div>
{this.showDetails()}
</div>
);
break;
}
default: {
return (
<div>
{this.showDescription()}
</div>
);
break;
}
}
}
showDescription() {
return (
<div dangerouslySetInnerHTML={{__html: marked(this.props.details.description)}} />
);
}
showDetails() {
return (
<div>
<h4 className='created-by'>
Created By {this.props.details.createdBy}
</h4>
<h5 className='total-words'>
{this.props.numberOfWords} Total Word{(this.props.numberOfWords !== 1) ? 's' : ''}
</h5>
<h5 className='incopmlete-notice'>
{(!this.props.isComplete) ? 'Note: This dictionary is not yet complete and is likely to change.' : ''}
</h5>
</div>
);
}
changeTab(tabNumber) {
this.setState({
tabDisplay: tabNumber
});
}
render() {
return (
<div>
<Button
action={() => this.toggleDisplay()}
label={((this.state.isDisplayed) ? 'Hide' : 'Show') + ' Info'} />
{this.showTabbedInterface()}
</div>
);
}
}
InfoDisplay.defaultProps = {
isEditing: false
}

View file

@ -1,174 +0,0 @@
// import React from 'react';
import Inferno from 'inferno';
import Component from 'inferno-component';
import marked from 'marked';
import {WordForm} from '../forms/WordForm';
import {Button} from '../input/Button';
const saveIcon = <i>&#128190;</i>;
const editIcon = <i>&#128393;</i>;
// export class Word extends React.Component {
export class Word extends Component {
constructor(props) {
super(props);
this.state = {
editWord: false,
editName: false,
editPronunciation: false,
editPartOfSpeech: false,
editSimpleDefinition: false,
editLongDefinition: false
};
}
/*
{
name: word,
pronunciation: pronunciation,
partOfSpeech: ((partOfSpeech.length > 0) ? partOfSpeech : " "),
simpleDefinition: simpleDefinition,
longDefinition: longDefinition,
wordId: currentDictionary.nextWordId++
}
*/
showName() {
return (
<div className='title is-4 name is-inline'>
{this.props.name}
</div>
);
}
showPronunciation() {
if (this.props.pronunciation !== '') {
return (
<div className='pronunciation is-inline'>
{this.props.pronunciation}
</div>
);
}
}
showPartOfSpeech() {
if (this.props.partOfSpeech !== '') {
return (
<div className='part-of-speech is-inline'>
{this.props.partOfSpeech}
</div>
);
}
}
showSimpleDefinition() {
if (this.props.simpleDefinition !== '') {
return (
<div className='simple-definition'>
{this.props.simpleDefinition}
</div>
);
}
}
showLongDefinition() {
if (this.props.longDefinition !== '') {
return (
<div className='long-definition' dangerouslySetInnerHTML={{__html: marked(this.props.longDefinition)}} />
);
}
}
showWordOrEdit() {
if (this.state.editWord) {
return (
<WordForm
partsOfSpeech={this.props.dictionary.props.settings.partsOfSpeech}
updateWord={(wordObject) => this.updateWord(wordObject)}
wordValues={this.packageThisWordIntoObject()}
submitLabel='Update' />
);
} else {
return (
<div className='content'>
<div className='hero'>
{this.showName()}
{this.showPronunciation()}
{this.showPartOfSpeech()}
</div>
<div className='section'>
{this.showSimpleDefinition()}
{this.showLongDefinition()}
</div>
</div>
);
}
}
showManagementArea() {
if (this.props.isEditing) {
if (this.state.editWord) {
return (
<Button
action={() => this.setState({editWord: false})}
label='Cancel' />
);
} else {
return (
<Button
action={() => this.setState({editWord: true})}
label='Edit Word' />
);
}
}
}
updateWord(wordObject) {
this.props.updateWord(this.props.wordId, {
name: wordObject.name || this.props.name,
pronunciation: wordObject.pronunciation || this.props.pronunciation,
partOfSpeech: wordObject.partOfSpeech || this.props.partOfSpeech,
simpleDefinition: wordObject.simpleDefinition || this.props.simpleDefinition,
longDefinition: wordObject.longDefinition || this.props.longDefinition
});
this.setState({editWord: false});
}
packageThisWordIntoObject() {
return {
name: this.props.name,
pronunciation: this.props.pronunciation,
partOfSpeech: this.props.partOfSpeech,
simpleDefinition: this.props.simpleDefinition,
longDefinition: this.props.longDefinition
};
}
render() {
return (
<div id={'entry' + this.props.wordId} className='box word'>
{this.showWordOrEdit()}
<div className='management'>
{this.showManagementArea()}
</div>
</div>
);
}
}
Word.defaultProps = {
isEditing: false
}

View file

@ -1,100 +0,0 @@
// import React from 'react';
import Inferno from 'inferno';
import Component from 'inferno-component';
import {Input} from '../input/Input';
import {TextArea} from '../input/TextArea';
import {Checkbox} from '../input/Checkbox';
import {Button} from '../input/Button';
import {FixedPage} from '../display/FixedPage';
// A component that allows you to edit the dictionary's details and settings.
// export class EditDictionaryForm extends React.Component {
export class EditDictionaryForm extends Component {
constructor(props) {
super(props);
// Declare local variables as null until mounted.
this.nameField = null;
this.descriptionField = null;
this.partsOfSpeechField = null;
this.allowDuplicatesField = null;
this.caseSensitiveField = null;
this.sortByEquivalentField = null;
this.isCompleteField = null;
this.isPublicField = null;
}
// Pass the changes to the saveChanges function provided in the component props.
saveOnClose() {
this.props.saveChanges({
name: this.nameField.state.value
, listTypeName: this.listTypeNameField.state.value
, description: this.descriptionField.state.value
, partsOfSpeech: this.partsOfSpeechField.state.value
, allowDuplicates: this.allowDuplicatesField.state.value
, caseSensitive: this.caseSensitiveField.state.value
, sortByEquivalent: this.sortByEquivalentField.state.value
, isComplete: this.isCompleteField.state.value
, isPublic: this.isPublicField.state.value
});
}
// Displays the form inside of a FixedPage component, which provides a button to click before displaying its contents.
render() {
return (
<FixedPage buttonClasses='right' buttonText='Edit Dictionary' onHide={() => this.saveOnClose()}>
<h2>Edit Dictionary</h2>
<div className='columns'>
<div className='column'>
<Input name='Dictionary Name'
value={this.props.details.name}
ref={(inputComponent) => this.nameField = inputComponent} />
<TextArea name='Dictionary Details'
value={this.props.details.description}
ref={(inputComponent) => this.descriptionField = inputComponent} />
<Input name='Parts of Speech'
value={this.props.settings.partsOfSpeech}
ref={(inputComponent) => this.partsOfSpeechField = inputComponent} />
<Input name='Classification'
value={this.props.details.listTypeName}
helperLink={{
action: () => alert('The word used to describe the list of words represented by this dictionary. By default, it is "Dictionary", but it could be "Lexicon" or some other classification.')
}}
ref={(inputComponent) => this.listTypeNameField = inputComponent} />
<Checkbox name='Allow Duplicates'
value={this.props.settings.allowDuplicates}
ref={(inputComponent) => this.allowDuplicatesField = inputComponent} />
<Checkbox name='Case-Sensitive'
value={this.props.settings.caseSensitive}
ref={(inputComponent) => this.caseSensitiveField = inputComponent} />
<Checkbox name='Sort by Definition'
value={this.props.settings.sortByEquivalent}
ref={(inputComponent) => this.sortByEquivalentField = inputComponent} />
<Checkbox name='Dictionary Is Complete'
value={this.props.settings.isComplete}
ref={(inputComponent) => this.isCompleteField = inputComponent} />
<Checkbox name='Dictionary Is Public'
value={this.props.settings.isPublic}
ref={(inputComponent) => this.isPublicField = inputComponent} />
</div>
</div>
</FixedPage>
);
}
}

View file

@ -1,28 +0,0 @@
// import React from 'react';
import Inferno from 'inferno';
import Component from 'inferno-component';
import {Input} from '../input/Input';
import {TextArea} from '../input/TextArea';
import {WordForm} from './WordForm';
// A component that allows you to edit a word
// export class EditWordForm extends React.Component {
export class EditWordForm extends Component {
constructor(props) {
super(props);
}
render() {
return (
<WordForm action='edit'>
<Input name='Word' />
<Input name='Pronunciation' helperLink={{url: "http://r12a.github.io/pickers/ipa/", label: 'IPA Characters', hover:"IPA Character Picker located at http://r12a.github.io/pickers/ipa/"}} />
<Input name='Part of Speech' />
<Input name='Definition/<wbr><b class=wbr></b>Equivalent Word(s)' />
<TextArea name='Explanation/<wbr><b class=wbr></b>Long Definition' />
</WordForm>
);
}
}

View file

@ -1,139 +0,0 @@
// import React from 'react';
import Inferno from 'inferno';
import Component from 'inferno-component';
import {keyCodeFor} from '../../js/helpers'
import {Input} from '../input/Input';
import {Dropdown} from '../input/Dropdown';
import {TextArea} from '../input/TextArea';
import {Button} from '../input/Button';
// export class WordForm extends React.Component {
export class WordForm extends Component {
constructor(props) {
super(props);
this.state = {
errorMessage: '',
updateConflictMessage: ''
};
// Declare local variables as null until mounted.
this.wordField = null;
this.pronunciationField = null;
this.partOfSpeechField = null;
this.simpleDefinitionField = null;
this.longDefinitionField = null;
}
submitWordOnCtrlEnter(event) {
var keyCode = (event.which ? event.which : event.keyCode);
//Windows and Linux Chrome accept ctrl+enter as keyCode 10.
if (keyCode === keyCodeFor('ctrlEnter') || (keyCode == keyCodeFor('enter') && event.ctrlKey)) {
event.preventDefault();
this.handleSubmit();
}
}
handleSubmit() {
if (this.formIsValid()) {
let word = {
name: this.wordField.state.value,
pronunciation: this.pronunciationField.state.value,
partOfSpeech: this.partOfSpeechField.state.value,
simpleDefinition: this.simpleDefinitionField.state.value,
longDefinition: this.longDefinitionField.state.value
};
if (this.props.updateWord) {
this.props.updateWord(word);
} else {
this.props.addWord(word);
}
this.clearForm();
}
}
formIsValid() {
let errorMessage = '';
if (this.wordField.state.value.length <= 0) {
errorMessage += 'The word field cannot be blank';
}
if (this.simpleDefinitionField.state.value.length <= 0
&& this.longDefinitionField.state.value.length <= 0) {
errorMessage += ((errorMessage.length > 0) ? ', and there' : 'There')
+ ' must be a value in at least one of the definition fields';
}
if (errorMessage.length > 0) {
errorMessage += '!';
}
this.setState({errorMessage: errorMessage});
return (errorMessage <= 0);
}
clearForm() {
this.wordField.clearField();
this.pronunciationField.clearField();
this.partOfSpeechField.clearField();
this.simpleDefinitionField.clearField();
this.longDefinitionField.clearField();
}
render() {
let nameDefaultValue = (this.props.wordValues) ? this.props.wordValues.name : '';
let pronunciationDefaultValue = (this.props.wordValues) ? this.props.wordValues.pronunciation : '';
let partOfSpeechDefaultValue = (this.props.wordValues) ? this.props.wordValues.partOfSpeech : ' ';
let simpleDefinitionDefaultValue = (this.props.wordValues) ? this.props.wordValues.simpleDefinition : '';
let longDefinitionDefaultValue = (this.props.wordValues) ? this.props.wordValues.longDefinition : '';
return (
<div className='form'>
<Input name='Word'
value={nameDefaultValue}
onKeyDown={(event) => this.submitWordOnCtrlEnter(event)}
ref={(inputComponent) => this.wordField = inputComponent} />
<Input name='Pronunciation'
helperLink={{
url: "http://r12a.github.io/pickers/ipa/",
label: "IPA Characters",
hover: "IPA Character Picker located at http://r12a.github.io/pickers/ipa/"
}}
value={pronunciationDefaultValue}
onKeyDown={(event) => this.submitWordOnCtrlEnter(event)}
ref={(inputComponent) => this.pronunciationField = inputComponent} />
<Dropdown name='Part of Speech'
optionsList={this.props.partsOfSpeech}
value={partOfSpeechDefaultValue}
ref={(inputComponent) => this.partOfSpeechField = inputComponent} />
<Input name={<div style={{display: 'inline'}}>Definition/<wbr /><b className="wbr"></b>Equivalent Word(s)</div>}
value={simpleDefinitionDefaultValue}
onKeyDown={(event) => this.submitWordOnCtrlEnter(event)}
ref={(inputComponent) => this.simpleDefinitionField = inputComponent} />
<TextArea id='newWordForm'
name={<div style={{display: 'inline'}}>Explanation/<wbr /><b className="wbr"></b>Long Definition</div>}
value={longDefinitionDefaultValue}
onKeyDown={(event) => this.submitWordOnCtrlEnter(event)}
ref={(inputComponent) => this.longDefinitionField = inputComponent} />
<span id="errorMessage">{this.state.errorMessage}</span>
<Button classes={(this.props.updateWord) ? 'edit-button' : 'add-button'} action={() => this.handleSubmit()} label={this.props.submitLabel} />
<div id="updateConflict">{this.state.updateConflictMessage}</div>
</div>
);
}
}

View file

@ -1,37 +0,0 @@
// import React from 'react';
import Inferno from 'inferno';
import Component from 'inferno-component';
// Creates a clickable <span> tag with an onclick action.
// export class Button extends React.Component {
export class Button extends Component {
constructor(props) {
super(props);
}
// Always give the Button a 'clickable' class and then add any others.
processClasses() {
var classes = 'button';
if (this.props.classes) {
classes += ' ' + this.props.classes;
}
return classes;
}
render() {
return (
<a
id={this.props.id}
className={this.processClasses()}
onClick={this.props.action}>
{this.props.label}
</a>
);
}
}
Button.defaultProps = {
action: () => console.log('no action bound to button')
}

View file

@ -1,37 +0,0 @@
// import React from 'react';
import Inferno from 'inferno';
import {Input} from './Input';
export class Checkbox extends Input {
constructor(props) {
super(props);
this.state = {
value: props.value || false
, isDisabled: props.isDisabled || false
};
}
// Whenever the input changes, update the value state of this component
handleOnChange(event) {
this.setState({
value: event.target.checked
});
}
render() {
return (
<label className='checkbox'>
<span>
{this.props.name}
{this.showHelperLink()}
</span>
<input type="checkbox" onInput={this.handleOnChange} checked={(this.state.value) ? 'checked' : null} disabled={(this.state.isDisabled) ? 'disabled' : null} />
</label>
);
}
}
Checkbox.defaultProps = {
doValidate: false
};

View file

@ -1,74 +0,0 @@
// import React from 'react';
import Inferno from 'inferno';
import {Input} from './Input';
import {htmlEntities} from '../../js/helpers';
export class Dropdown extends Input {
constructor(props) {
super(props);
this.state = {
value: props.value || ' '
, isDisabled: props.isDisabled || false
};
}
// Whenever the input changes, update the value state of this component
handleOnChange(event) {
this.setState({
value: event.currentTarget.value
});
}
parseOptions (optionsString) {
let results = [];
let options = optionsString.split(',');
options.forEach((option, index) => {
let optionValue = htmlEntities(option.trim());
results.push(
<option key={`o:${index}v:${optionValue}`} value={optionValue}>
{option.trim()}
</option>
);
});
return results;
}
render() {
return (
<div className='control'>
<div className='level is-marginless'>
<div className='level-item'>
<label className='label' for={this.generatedId}>
{this.props.name}
</label>
</div>
<div className='level-item'>
{this.showHelperLink()}
</div>
</div>
<p className='control'>
<span className='select'>
<select value=' ' onChange={this.handleOnChange} disabled={(this.state.isDisabled) ? 'disabled' : null}>
<option value=' '></option>
{this.parseOptions(this.props.optionsList)}
</select>
</span>
</p>
</div>
);
}
}
Dropdown.defaultProps = {
doValidate: false
};

View file

@ -1,116 +0,0 @@
// import React from 'react';
import Inferno, {linkEvent} from 'inferno';
import Component from 'inferno-component';
import {Button} from './Button';
function handleOnChange(instance, event) {
console.log('changing');
instance.setState({
isValid: !(instance.props.doValidate && event.currentTarget.value === ''),
value: event.currentTarget.value
});
}
// export class Input extends React.Component {
export class Input extends Component {
constructor(props) {
super(props);
// this.defaultProps = {
// name: props.name || 'Field',
// helperLink: props.helperLink || {url: '#', label: '', hover: ''},
// doValidate: props.doValidate || true
// };
this.generatedId = 'input' + window.idManager.nextStr;
this.state = {
value: props.value || '',
isDisabled: props.isDisabled || false
};
// Bind listeners
// this.handleOnChange = this.handleOnChange.bind(this);
this.handleOnKeyDown = this.handleOnKeyDown.bind(this);
}
// Whenever the input changes we update the value state of this component
handleOnChange(instance, event) {
instance.setState({
isValid: !(instance.props.doValidate && event.currentTarget.value === ''),
value: event.currentTarget.value
});
}
handleOnKeyDown(instance, event) {
if (instance.props.onKeyDown) {
instance.props.onKeyDown(event);
}
}
showHelperLink() {
if (this.props.helperLink) {
if (this.props.helperLink.url) {
return (
<a className='button is-small' href={this.props.helperLink.url} target='_blank' title={this.props.helperLink.hover}>
{this.props.helperLink.label}
</a>
);
} else {
return (
<Button classes='is-small'
action={this.props.helperLink.action}
label={this.props.helperLink.label || '?'} />
);
}
}
}
clearField() {
this.setState({value: ''});
}
toggleFieldEnabled() {
this.setState({
isDisabled: !this.state.isDisabled
})
}
render() {
return (
<div className='control'>
<div className='level is-marginless'>
<div className='level-item'>
<label className='label' for={this.generatedId}>
{this.props.name}
</label>
</div>
<div className='level-item'>
{this.showHelperLink()}
</div>
</div>
<p className='control'>
<input
className='input'
id={this.generatedId}
type="text"
onInput={linkEvent(this, this.handleOnChange)}
onKeyDown={linkEvent(this, this.handleOnKeyDown)}
disabled={(this.state.isDisabled) ? 'disabled' : null} />
</p>
</div>
);
}
}
Input.defaultProps = {
name: '',
doValidate: false
};

View file

@ -1,70 +0,0 @@
// import React from 'react';
import Inferno, {linkEvent} from 'inferno';
import {Input} from './Input';
import {getInputSelection, setSelectionRange} from '../../js/helpers';
import {Button} from './Button';
import {FixedPage} from '../display/FixedPage';
export class TextArea extends Input {
constructor(props) {
super(props);
this.mainTextarea = null;
this.maximizedTextarea = null;
}
handleMaximizedTextboxClose (instance, event) {
instance.mainTextarea.value = event.currentTarget.value;
}
handleMaximizedTextboxOpen (instance, event) {
instance.maximizedTextarea.value = event.currentTarget.value;
}
// Use a FixedPage for TextArea's fullscreen mode.
render() {
return (
<div className='control'>
<div className='level is-marginless'>
<div className='level-item'>
<label className='label' for={this.generatedId}>
{this.props.name}
</label>
</div>
<div className='level-item'>
<FixedPage id={this.generatedId + '_textbox'}
contentClass='no-scroll'
buttonClasses='is-small'
buttonText='Maximize'>
<header className='header'>
<h3 className='title'>
{this.props.name}
</h3>
</header>
<section className='section'>
<p className='control'>
<textarea id={this.generatedId} className='textarea'
onChange={linkEvent(this, this.handleMaximizedTextboxClose)}
onKeyDown={linkEvent(this, this.handleOnKeyDown)}
ref={(textarea) => {this.maximizedTextarea = textarea}} />
</p>
</section>
</FixedPage>
</div>
</div>
<textarea className='textarea' id={this.generatedId}
onInput={linkEvent(this, this.handleOnChange)}
onChange={linkEvent(this, this.handleMaximizedTextboxOpen)}
onKeyDown={linkEvent(this, this.handleOnChange)} disabled={(this.state.isDisabled) ? 'disabled' : null}
ref={(textarea) => {this.mainTextarea = textarea}} />
</div>
);
}
}

View file

@ -1,36 +0,0 @@
<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>

View file

@ -1,44 +0,0 @@
// import React from 'react';
import Inferno from 'inferno';
import Component from 'inferno-component';
import {Word} from '../display/Word';
// A component for showing just the list of words provided to it as a prop.
// export class Dictionary extends React.Component {
export class Dictionary extends Component {
constructor(props) {
super(props);
}
// Take the word list, given as a component prop, map its values to a Word component, and return it in a div tag.
showWords() {
if (this.props.words.length > 0) {
let words = this.props.words.map((word) => {
return (
<Word key={'d:' + this.props.details.name + this.props.details.externalID.toString() + 'w:' + word.wordId.toString()} isEditing={true}
name={word.name}
pronunciation={word.pronunciation}
partOfSpeech={word.partOfSpeech}
simpleDefinition={word.simpleDefinition}
longDefinition={word.longDefinition}
wordId={word.wordId}
dictionary={this}
updateWord={(wordId, wordObject) => this.props.updateWord(wordId, wordObject)} />
);
});
return <div>{words}</div>;
} else {
return <h3 className='title is-3'>No words yet!</h3>;
}
}
render() {
return (
<div className='container' id="theDictionary">
{this.showWords()}
</div>
);
}
}

View file

@ -1,48 +0,0 @@
// import React from 'react';
import Inferno from 'inferno';
import Component from 'inferno-component';
import marked from 'marked';
import {FixedPage} from '../display/FixedPage';
// A component for the site footer
// export class Footer extends React.Component {
export class Footer extends Component {
constructor(props) {
super(props);
this.termsText = '# Terms \nTesting the terms';
this.privacyText = '# Privacy \nTesting the privacy';
}
render() {
return (
<footer>
<div id="footer-content">
Dictionary Builder only guaranteed to work with most up-to-date HTML5 browsers.
<a href="/issues" className="clickable inline-button" target="_blank">
Issues
</a>
<a href="/updates" className="clickable inline-button" target="_blank">
Updates
</a>
&nbsp;|&nbsp;
<FixedPage buttonClasses='inline-button' buttonText='Terms'>
<div dangerouslySetInnerHTML={{__html: marked(this.termsText)}} />
</FixedPage>
<FixedPage buttonClasses='inline-button' buttonText='Privacy'>
<div dangerouslySetInnerHTML={{__html: marked(this.privacyText)}} />
</FixedPage>
</div>
</footer>
);
}
}

View file

@ -1,114 +0,0 @@
// import React from 'react';
import Inferno from 'inferno';
import Component from 'inferno-component';
import marked from 'marked';
import {Button} from '../input/Button';
import {FixedPage} from '../display/FixedPage';
// A component for the site header
// export class Header extends React.Component {
export class Header extends Component {
constructor(props) {
super(props);
this.state = {
loggedIn: false,
lockedOut: false
}
this.aboutText = '# About \nGet this later.';
}
logUserIn() {
this.setState({
loggedIn: true
});
}
logUserOut() {
this.setState({
loggedIn: false
});
}
lockUserOut() {
this.setState({
loggedIn: false,
lockedOut: true
});
}
unlockUser() {
this.setState({
lockedOut: false
});
}
showAccountButtons() {
var buttons;
if (this.state.loggedIn) {
buttons = [
<Button key='accountbutton1'
id='accountSettings'
classes='level-item'
action={() => this.lockUserOut()}
label='Account Settings' />,
<Button key='accountbutton2'
id='logoutLink'
classes='level-item'
action={() => this.logUserOut()}
label='Log Out' />
];
} else if (this.state.lockedOut) {
buttons = [
<Button key='accountbutton3'
id='logoutLink'
classes='level-item'
action={() => this.unlockUser()}
label='Can&apos;t Log In' />
];
} else {
buttons = [
<Button key='accountbutton4'
id='loginLink'
classes='level-item'
action={() => this.logUserIn()}
label='Log In/Create Account' />
];
}
return buttons;
}
render() {
return (
<header className='header'>
<div className='hero'>
<nav className='level' id="headerPadder">
<div className='level-left'>
<a className='level-item' href="/" id="siteLogo">
Lexiconga Dictionary Builder
</a>
</div>
<div className='level-right'>
{this.showAccountButtons()}
<div className='level-item'>
<FixedPage id='aboutButton' buttonText='About Lexiconga'>
<div dangerouslySetInnerHTML={{__html: marked(this.aboutText)}} />
</FixedPage>
</div>
</div>
</nav>
</div>
</header>
);
}
}

View file

@ -1,17 +0,0 @@
<!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" />
</head>
<body>
<div id="site"></div>
<script src="lexiconga.js"></script>
</body>
</html>

View file

@ -1,330 +1,108 @@
// Import the HTML file and sass for Webpack to handle.
import './index.html';
import './sass/main.scss';
// Import React for the React.Component class and ReactDOM for rendering.
// import React from 'react';
// import ReactDOM from 'react-dom';
import Inferno from 'inferno';
import Component from 'inferno-component';
// Import the necessary components.
import {Header} from './components/structure/Header';
import {Footer} from './components/structure/Footer';
import {WordForm} from './components/forms/WordForm';
import {Button} from './components/input/Button';
import {InfoDisplay} from './components/display/InfoDisplay';
import {EditDictionaryForm} from './components/forms/EditDictionaryForm';
import {Dictionary} from './components/structure/Dictionary';
// Import the helper functions needed for this file.
import {dynamicSort} from './js/helpers';
import {IDManager} from './js/IDManager';
// Declare the values of the default empty dictionary.
const defaultDictionaryName = 'New'
, defaultListTypeName = 'Dictionary'
, defaultDictionaryDescription = 'A new dictionary.'
, defaultDictionaryCreatedBy = 'Someone'
, defaultDictionaryPartsOfSpeech = 'Noun,Adjective,Verb,Adverb,Preposition,Pronoun,Conjunction'
;
// Create global IDManager.
window.idManager = window.idManager || new IDManager();
// Create the Lexiconga component just for rendering the whole site.
// class Lexiconga extends React.Component {
class Lexiconga extends Component {
constructor(props) {
class App extends Component {
constructor (props) {
super(props);
// This could probably be a global constant instead.
this.showConsoleMessages = this.props.showConsoleMessages || false;
// Put the dictionary details, settings, and words into the state so modifications will affect display.
this.state = {
scroll: {
x: 0
, y: 0
}
, details: {
name: defaultDictionaryName
, listTypeName: defaultListTypeName
, description: defaultDictionaryDescription
, createdBy: defaultDictionaryCreatedBy
, nextWordId: 1
, externalID: 0
}
, words: []
, settings: {
allowDuplicates: false
, caseSensitive: false
, partsOfSpeech: defaultDictionaryPartsOfSpeech
, sortByEquivalent: false
, isComplete: false
, isPublic: false
}
};
//Saves a stringifyed default dictionary. Actually does nothing because this value doesn't exist.
this.defaultDictionaryJSON = JSON.stringify(this.state.dictionaryDetails);
this.previousDictionary = {};
}
// Receive an object containing changes to the dictionary details and settings, apply them to the state,
// and save the local dictionary after the state is updated.
saveChanges(changesObject) {
let updatedDetails = this.state.details;
let updatedSettings = this.state.settings;
updatedDetails.name = changesObject.name;
updatedDetails.listTypeName = changesObject.listTypeName;
updatedDetails.description = changesObject.description;
updatedSettings.partsOfSpeech = changesObject.partsOfSpeech;
updatedSettings.allowDuplicates = changesObject.allowDuplicates;
updatedSettings.caseSensitive = changesObject.caseSensitive;
updatedSettings.sortByEquivalent = changesObject.sortByEquivalent;
updatedSettings.isComplete = changesObject.isComplete;
updatedSettings.isPublic = changesObject.isPublic;
this.setState({
details: updatedDetails,
settings: updatedSettings
}, () => {
this.saveLocalDictionary();
});
}
// Sort the given array of word objects in the state according to the sortByEquivalent setting.
sortWords(wordsArray) {
let sortMethod;
if (this.state.settings.sortByEquivalent) {
sortMethod = ['simpleDefinition', 'partOfSpeech'];
} else {
sortMethod = ['name', 'partOfSpeech'];
}
return wordsArray.sort(dynamicSort(sortMethod));
}
// Receive a word object, process it, and update the words state array with the new word.
addWord(wordObject) {
let newWord = {
name: wordObject.name || 'errorWord'
, pronunciation: wordObject.pronunciation || ''
, partOfSpeech: wordObject.partOfSpeech || ''
, simpleDefinition: wordObject.simpleDefinition || ''
, longDefinition: wordObject.longDefinition || ''
, wordId: this.state.details.nextWordId
};
let updatedWords = this.state.words.concat([newWord]);
updatedWords = this.sortWords(updatedWords);
let updatedDetails = this.state.details;
updatedDetails.nextWordId += 1;
this.setState({
words: updatedWords,
details: updatedDetails
}, () => {
if (this.showConsoleMessages) {
console.log('New word ' + newWord.name + ' added successfully');
}
});
}
// Search the words list for the first word with the given idea and return its index in the array.
firstIndexWordWithId(id) {
this.state.words.forEach((word, index) => {
console.log('given id: ' + typeof id + ' ' + id + '\n' + typeof word.wordId + ' ' + word.wordId + ' ' + word.name);
if (word.wordId === id) {
return index;
}
});
return -1;
}
// Receive a wordId and a wordObject, find the index of the first word in the words state array with
// the given wordId, and set that word's values to the values in the given wordObject.
updateWord(wordId, wordObject) {
let index = this.firstIndexWordWithId(wordId);
if (index >= 0) {
if (this.showConsoleMessages) console.log('Updating ' + this.state.words[index].name + ' to ' + wordObject.name);
let updatedWords = this.state.words;
updatedWords[index].name = wordObject.name;
updatedWords[index].pronunciation = wordObject.pronunciation;
updatedWords[index].partOfSpeech = wordObject.partOfSpeech;
updatedWords[index].simpleDefinition = wordObject.simpleDefinition;
updatedWords[index].longDefinition = wordObject.longDefinition;
updatedWords = this.sortWords(updatedWords);
this.setState({words: updatedWords}, () => {
if (this.showConsoleMessages) {
console.log('Updated successfully');
}
});
} else {
console.log('Could not update. No word with id of ' + wordId.toString());
}
}
// Return true if the given dictionary reference has no words and its name and description are the same as the defaults.
dictionaryIsDefault(dictionary) {
if (this.showConsoleMessages) {
console.log('Name: ' + dictionary.name
+ '\nDescription: ' + dictionary.description
+ '\n# Words: ' + dictionary.words.length);
}
return dictionary.words.length <= 0 && dictionary.description === defaultDictionaryDescription && dictionary.name === defaultDictionaryName;
}
// Put the state details, words, and settings into an object, stringify it, and save it to the browser's localStorage as 'dictionary' if
// the dictionary in the state is not the default dictionary.
saveLocalDictionary() {
let saveDictionary = {
name: this.state.details.name
, listTypeName: this.state.details.listTypeName
, description: this.state.details.description
, createdBy: this.state.details.createdBy
, words: this.state.words
, nextWordId: this.state.details.nextWordId
, settings: this.state.settings
, externalID: this.state.details.externalID
};
if (!this.dictionaryIsDefault(saveDictionary)) {
localStorage.setItem('dictionary', JSON.stringify(saveDictionary));
console.log('Saved "' + this.state.details.name + '" dictionary locally');
} else {
if (this.showConsoleMessages) console.log('Current dictionary is default, so it wasn\'t saved');
}
}
// If there is a saved 'dictionary' JSON string in localStorage, parse it, and set the state with its values.
loadLocalDictionary() {
if (localStorage.getItem('dictionary')){
let localDictionary = JSON.parse(localStorage.getItem('dictionary'));
if (!this.dictionaryIsDefault(localDictionary)) {
this.setState({
details: {
name: localDictionary.name
, listTypeName: localDictionary.listTypeName || defaultListTypeName
, description: localDictionary.description
, createdBy: localDictionary.createdBy
, nextWordId: localDictionary.nextWordId
, externalID: localDictionary.externalID
}
, words: localDictionary.words.slice()
, settings: {
allowDuplicates: localDictionary.settings.allowDuplicates
, caseSensitive: localDictionary.settings.caseSensitive
, partsOfSpeech: localDictionary.settings.partsOfSpeech
, sortByEquivalent: localDictionary.settings.sortByEquivalent
, isComplete: localDictionary.settings.isComplete
, isPublic: localDictionary.settings.isPublic
}
}, () => {
if (this.showConsoleMessages) {
console.log('Loaded local "' + this.state.details.name + '" dictionary successfully');
}
});
} else {
if (this.showConsoleMessages) console.log('Locally saved dictionary is default');
}
} else {
if (this.showConsoleMessages) console.log('No saved local dictionary');
}
}
// Put all of the components together.
render() {
render () {
return (
<div>
<Header />
<nav className='nav'>
<div className='nav-left'>
<a href='/' className='nav-item'>
<img src='images/logo.svg' alt='Lexiconga' />
</a>
</div>
<div className='nav-right'>
<a href='/' className='nav-item'>
Login
</a>
<a href='/' className='nav-item'>
About
</a>
</div>
</nav>
<section className='section'>
<div className='columns'>
<div className='column is-one-quarter'>
<div className='box'>
<WordForm
partsOfSpeech={this.state.settings.partsOfSpeech}
addWord={(wordObject) => this.addWord(wordObject)}
submitLabel='Add Word' />
</div>
</div>
<div className='column is-half'>
<div className='hero'>
<div className='container is-fluid'>
<Button
action={() => this.saveLocalDictionary()}
label='Save Dictionary' />
<Button
action={() => this.loadLocalDictionary()}
label='Load Dictionary' />
<EditDictionaryForm
details={this.state.details}
settings={this.state.settings}
saveChanges={(changesObject) => this.saveChanges(changesObject)} />
<h1 className="title is-1 dictionary-name">
{this.state.details.name} {this.state.details.listTypeName}
</h1>
<InfoDisplay
details={this.state.details}
numberOfWords={this.state.words.length}
isComplete={this.state.settings.isComplete} />
<div className='container'>
<div className='columns'>
<div className='column is-one-quarter'>
<div className='box'>
<div className='field'>
<label className='label'>Word</label>
<p className='control'>
<input className='input' type='text' placeholder='Text input' />
</p>
</div>
<div className='field'>
<label className='label'>Pronunciation</label>
<p className='control'>
<input className='input' type='text' placeholder='Text input' />
</p>
</div>
<div className='field'>
<label className='label'>Part of Speech</label>
<p className='control'>
<span className='select'>
<select>
<option>Select dropdown</option>
<option>With options</option>
</select>
</span>
</p>
</div>
<div className='field'>
<label className='label'>Definition / Equivalent Word(s)</label>
<p className='control'>
<input className='input' type='text' placeholder='Text input' />
</p>
</div>
<div className='field'>
<label className='label'>Explanation / Long Definition</label>
<p className='control'>
<textarea className='textarea' placeholder='Textarea' />
</p>
</div>
</div>
</div>
<div className='section'>
<Dictionary
details={this.state.details}
words={this.state.words}
settings={this.state.settings}
updateWord={(wordId, wordObject) => this.updateWord(wordId, wordObject)} />
<div className='column is-half'>
<div className='card'>
<header className='card-header'>
<p className='card-header-title'>
Dictionary Name
</p>
<a className='card-header-icon button'>
Edit Dictionary
</a>
</header>
<div className='card-content'>
<div className='content'>
Hello
</div>
</div>
<footer className='card-footer'>
<a className='card-footer-item'>Save</a>
<a className='card-footer-item'>Edit</a>
<a className='card-footer-item'>Delete</a>
</footer>
</div>
</div>
</div>
<div className='column is-one-quarter'>
<div className='column is-one-quarter ad-column'>
<div className='box'>
Advertisements or something.
</div>
</div>
</div>
</section>
<Footer />
</div>
);
}
}
// Put the app on the screen.
// ReactDOM.render(<Lexiconga showConsoleMessages={true} />, document.getElementById('site'));
Inferno.render(<Lexiconga showConsoleMessages={true} />, document.getElementById('site'));
Inferno.render(<App />, document.getElementById('site'));

View file

@ -1,13 +0,0 @@
export class IDManager {
constructor () {
this.nextId = 0;
}
get next () {
return this.nextId++;
}
get nextStr () {
return this.next.toString();
}
}

View file

@ -1,877 +0,0 @@
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

@ -1,118 +0,0 @@
/*
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
export 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;
});
}

View file

@ -1,258 +0,0 @@
import {removeDiacritics} from './dependencies/removeDiacritics';
// 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
export 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;
}
export 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
};
}
export 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();
}
}
export 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;
}
export 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>');
}
export 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');
}
export function htmlEntitiesParseForMarkdown(string) {
return String(string).replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&#92;/g, '\\').replace(/<br>/g, '\n');
}
export 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, '');
}
export function htmlEntitiesParseForSearchEntry(string) {
return String(string).replace(/"/g, '%%%%').replace(/'/g, "````");
}
export function htmlEntitiesParseForSearch(string) {
return String(string).replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '%%%%').replace(/&apos;/g, "````");
}
export function regexParseForSearch(string) {
return String(string).replace(/([\[\\\^\$\.\|\?\*\+\(\)\{\}\]])/g, "\\$1");
}
export 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);
};
}
export 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);
}

View file

@ -1,194 +0,0 @@
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);
}
}

View file

@ -1,714 +0,0 @@
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();
}

View file

@ -1,175 +0,0 @@
body {
background: #e6cfaa;
}
header {
background: #eacc9d;
-webkit-box-shadow: $header-shadow;
-moz-box-shadow: $header-shadow;
box-shadow: $header-shadow;
}
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;
}
}
.floating-form {
background: #ba5536;
-webkit-box-shadow: $box-shadow;
-moz-box-shadow: $box-shadow;
box-shadow: $box-shadow;
border: none;
}
input, textarea, select, option {
background: #efdfc0;
}
#announcementArea {
background: #a0c066;
-webkit-box-shadow: $box-shadow;
-moz-box-shadow: $box-shadow;
box-shadow: $box-shadow;
}
#notificationArea {
background: #c0c088;
-webkit-box-shadow: $box-shadow;
-moz-box-shadow: $box-shadow;
box-shadow: $box-shadow;
}
.center-column {
background: #bd7251;
border: none;
-webkit-box-shadow: $box-shadow;
-moz-box-shadow: $box-shadow;
box-shadow: $box-shadow;
}
.fixed-page-content {
-webkit-box-shadow: $box-shadow;
-moz-box-shadow: $box-shadow;
box-shadow: $box-shadow;
}
.fixed-page-content {
background: #f2d5b2;
}
.management {
border-width: 2px;
border: none;
}
.dictionary-name {
text-shadow: 2px 2px 2px #915337;
}
#dictionaryShareLink {
text-shadow: none;
}
.tabbed-interface {
z-index: 10;
background: $dictionary-info-color;
-webkit-box-shadow: $box-shadow;
-moz-box-shadow: $box-shadow;
box-shadow: $box-shadow;
}
.selected-tab {
z-index: 5;
background: $dictionary-info-color !important;
-webkit-box-shadow: $box-shadow;
-moz-box-shadow: $box-shadow;
box-shadow: $box-shadow;
}
#loginLink, #logoutLink, #descriptionToggle, #searchFilterToggle, #settingsButton, .deleteCancelButton, .deleteConfirmButton, #settingsScreenCloseButton, #infoScreenCloseButton, .clickable, button {
background: $button-color;
}
.word {
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);
.edit-button {
background: #86ac41;
}
.delete-button {
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);
}

View file

@ -1,134 +0,0 @@
/* 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;
}
.maximize-button {
display: none;
}
#settingsSaveButtons {
position: relative;
right: 0;
bottom: 0;
clear: both;
width: 100%;
}
}

View file

@ -1,490 +0,0 @@
* {
// position: relative;
// z-index: 0;
-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: $header-height;
width: 100%;
margin: 0 0 10px;
position: relative;
top: 0px;
left: 0px;
right: 0px;
border: none;
padding: 0;
.button-group {
float: right;
margin: 16px 8px;
font-size:12px;
span {
margin-left: 16px;
}
}
}
footer {
width: 100%;
text-align: center;
vertical-align: middle;
position:fixed;
bottom: 0px;
left: 0px;
background: #aaaaaa;
padding: 0;
max-height: $footer-height;
#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;
}
.right {
float: right;
}
.column {
display: block;
float: left;
margin: $column-margin;
}
.left-column {
@extend .column;
width: 25%;
min-width: $min-column-width;
max-width: $max-column-width / 2;
}
.center-column {
@extend .column;
width: 50%;
margin-bottom: $column-margin + $footer-height;
min-width: $min-column-width;
max-width: $max-column-width;
padding: 15px;
}
.floating-form {
position: fixed;
top: $header-height + $column-margin;
width: 25%;
min-width: $min-column-width - ($column-margin * 2);
max-width: ($max-column-width / 2) - ($column-margin * 2);
}
form {
padding: 15px;
}
.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;
width: 100%;
}
textarea {
min-height: 125px;
}
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;
}
.dictionary-name {
margin: 0 0 5px;
}
#dictionaryShareLink {
margin-left: 10px;
vertical-align: middle;
text-decoration: none;
}
.dictionary-info {
width: 90%;
max-height: 400px;
overflow-y: auto;
padding: 10px;
border: none;
margin: 0;
.selected-tab, .tabbed-interface {
position: relative;
}
.tabbed-interface {
margin: 0;
padding: 5px 10px;
}
}
.clickable, button {
display: inline;
font-weight: bold;
font-size: 13px;
padding: 5px;
border: none;
background: #dddddd;
margin: 0 3px;
}
.clickable, button {
cursor: pointer;
}
.inline-button {
display: inline-block !important;
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;
}
.word {
display: block;
width: 90%;
min-width: 200px;
padding: 10px 10px 3px;
margin-bottom: 5px;
.name {
font-weight: bold;
font-size: 20px;
}
.pronunciation {
font-size: 12px;
margin-left:10px;
}
.part-of-speech {
font-style: italic;
font-weight: bold;
font-size: 10px;
margin-left:10px;
}
.simple-definition {
display: block;
font-style: italic;
}
.long-definition {
display: block;
margin-left: 20px;
h1, h2, h3, h4, h5, h6 {
margin: 5px 0 8px;
font-weight: bold;
}
h1 {
font-size: 22px;
}
h2 {
font-size: 20px;
}
h3 {
font-size: 20px;
font-weight: normal;
}
h4 {
font-size: 18px;
}
h5 {
font-size: 18px;
font-weight: normal;
}
h6 {
font-size: 17px;
}
p {
margin: 3px 0 8px;
}
}
}
.wordLink {
text-decoration: none;
float: right;
font-size: 13px;
padding: 2px;
line-height: 10px;
}
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;
}
.edit-button, .delete-button, .deleteConfirmButton, .deleteCancelButton {
display: inline;
font-size: 10px;
margin: 5px;
}
.deleteConfirm {
display: block;
font-size: 10px;
margin: 10px;
}
.fixed-page-container {
position: relative;
z-index: 999;
.fixed-page-background-fade {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #000000;
opacity: 0.6;
}
.fixed-page-content {
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;
opacity: 1;
border: none;
text-align: left;
}
}
.right-button {
@extend .right;
font-size: 12px;
}
.no-scroll {
padding: 5px 3% 4% !important;
overflow-y: hidden !important;
}
.maximize-button {
@extend .inline-button;
}
.fullscreen-textbox {
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%;
}
.settings-column {
@extend .left-column;
margin-right: $column-margin * 2;
}

View file

@ -1,12 +0,0 @@
$header-height: 50px;
$header-shadow: 0px 3px 10px -1px rgba(0, 0, 0, 0.75);
$box-shadow: 5px 5px 7px 0px rgba(0, 0, 0, 0.75);
$column-margin: 15px;
$min-column-width: 260px;
$max-column-width: 800px;
$button-color: #dcb078;
$dictionary-info-color: #f2d5b2;
$footer-height: 32px;
// Bulma Variables
$radius: 0;

View file

@ -1,6 +1,2 @@
@import 'variables';
@import '../../node_modules/bulma/bulma';
// @import 'styles';
// @import 'lexiconga';
// @import 'mobile';
@import '../../node_modules/react-select/dist/react-select';

View file

@ -4,58 +4,58 @@ const path = require('path');
const BUILD_DIR = path.resolve(__dirname, 'public');
const APP_DIR = path.resolve(__dirname, 'src');
module.exports = {
entry: APP_DIR + '/index.jsx',
output: {
path: BUILD_DIR,
filename: 'lexiconga.js'
},
module: {
loaders: [
{
test: /\.html?$/,
exclude: /node_modules/,
loaders: [
'file?name=[name].html',
'html-minify'
]
},
{
test: /\.scss$/,
exclude: /node_modules/,
loaders: ['style', 'css', 'sass']
},
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
// presets: ['react', 'es2015']
presets: ['es2015'],
plugins: ['inferno']
module.exports = {
entry: APP_DIR + '/index.jsx'
, output: {
path: BUILD_DIR
, filename: 'lexiconga.js'
}
, module: {
rules: [
{
test: /\.scss$/
, exclude: /node_modules/
, use: [
'style-loader'
, 'css-loader'
, {
loader: 'sass-loader'
, options: {
file: './src/sass/styles.scss',
outFile: './public/styles.css',
outputStyle: 'compressed'
}
}
}
]
},
resolve: {
extensions: ['', '.js', '.jsx'],
},
/*plugins: [
// When you're ready to publish, check this article out.
// http://dev.topheman.com/make-your-react-production-minified-version-with-webpack/
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
output: {
comments: false
}
})
],*/
sassLoader: {
file: './src/sass/styles.scss',
// includePaths: ['./node_modules/bootstrap-sass/assets/'],
outFile: './public/styles.css',
outputStyle: 'compressed'
}
};
]
}
, {
test: /\.jsx?$/
, exclude: /node_modules/
, use: [
{
loader: 'babel-loader'
, options: {
presets: ['es2016']
, plugins: ['inferno']
}
}
]
}
]
}
, resolve: {
extensions: ['.js', '.jsx']
}
/*, plugins: [
// When you're ready to publish, check this article out.
// http://dev.topheman.com/make-your-react-production-minified-version-with-webpack/
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
output: {
comments: false
}
})
]*/
};

1383
yarn.lock

File diff suppressed because it is too large Load diff