Compare commits

..

11 Commits

Author SHA1 Message Date
Robbie Antenesse bfeea0da55 Make the default theme use Lexiconga colors! 2019-05-30 17:06:57 -06:00
Robbie Antenesse 602a5a136f Enable changing themes 2019-05-30 17:05:59 -06:00
Robbie Antenesse ca43c05b60 Split all colors into a _defaultTheme.scss 2019-05-30 15:47:50 -06:00
Robbie Antenesse ca1bb63295 Update footer styling 2019-05-30 14:59:38 -06:00
Robbie Antenesse f545f5c786 Show/remove share link if turning off Make Public 2019-05-30 14:21:09 -06:00
Robbie Antenesse 47964bcd53 Fix IPA field help rendering; Use arrows in usage.html 2019-05-30 14:11:06 -06:00
Robbie Antenesse 7221a094bc Add prominent share links if logged in or viewing 2019-05-30 14:01:34 -06:00
Robbie Antenesse b4687cd992 Parse references on backend for view 2019-05-30 13:59:53 -06:00
Robbie Antenesse cbe1099a5c Correctly link public word references 2019-05-30 12:18:59 -06:00
Robbie Antenesse d820aa87cc Add public word view 2019-05-30 11:20:02 -06:00
Robbie Antenesse afea58de6a Make parseReferences() parse its own references 2019-05-30 11:18:16 -06:00
23 changed files with 618 additions and 197 deletions

View File

@ -7,7 +7,7 @@
<title>Lexiconga</title> <title>Lexiconga</title>
<script src="src/index.js"></script> <script src="src/index.js"></script>
</head> </head>
<body> <body id="defaultTheme">
<header id="top"> <header id="top">
<h1 id="title">Lexiconga</h1> <h1 id="title">Lexiconga</h1>
@ -136,7 +136,7 @@
<a href="https://blog.lexicon.ga" target="_blank" class="small button">Blog</a> <a href="https://blog.lexicon.ga" target="_blank" class="small button">Blog</a>
<a href="https://github.com/Alamantus/Lexiconga/issues" target="_blank" class="small button">Issues</a> <a href="https://github.com/Alamantus/Lexiconga/issues" target="_blank" class="small button">Issues</a>
<a href="https://github.com/Alamantus/Lexiconga/releases" target="_blank" class="small button">Updates</a> <a href="https://github.com/Alamantus/Lexiconga/releases" target="_blank" class="small button">Updates</a>
| <span class="separator">|</span>
<a class="button" id="helpInfoButton">Help</a> <a class="button" id="helpInfoButton">Help</a>
<a class="button" id="termsInfoButton">Terms</a> <a class="button" id="termsInfoButton">Terms</a>
<a class="button" id="privacyInfoButton">Privacy</a> <a class="button" id="privacyInfoButton">Privacy</a>
@ -162,8 +162,8 @@
</label> </label>
<label>Theme <label>Theme
<select disabled> <select id="settingsTheme">
<option selected value="default">Default</option> <option value="default">Default</option>
<option value="dark">Dark</option> <option value="dark">Dark</option>
<option value="light">Light</option> <option value="light">Light</option>
<option value="blue">Blue</option> <option value="blue">Blue</option>

View File

@ -57,6 +57,7 @@ export const DEFAULT_DICTIONARY = {
export const DEFAULT_SETTINGS = { export const DEFAULT_SETTINGS = {
useIPAPronunciationField: true, useIPAPronunciationField: true,
useHotkeys: true, useHotkeys: true,
theme: 'default',
}; };
export const DEFAULT_PAGE_SIZE = 50; export const DEFAULT_PAGE_SIZE = 50;

View File

@ -9,17 +9,17 @@ that allow you to type any IPA symbol with only a standard keyboard.</p>
<li> <li>
<p>Many symbols that look similar to letters of the English alphabet (such as <p>Many symbols that look similar to letters of the English alphabet (such as
small caps) can be produced by doubling the capital letter:</p> small caps) can be produced by doubling the capital letter:</p>
<pre><code> GG -&gt; ɢ ?? -&gt; ʔ NN -&gt; ɴ BB -&gt; ʙ RR -&gt; ʀ XX -&gt; χ <pre><code> GG &rarr; ɢ ?? &rarr; ʔ NN &rarr; ɴ BB &rarr; ʙ RR &rarr; ʀ XX &rarr; χ
LL -&gt; ʟ II -&gt; ɪ YY -&gt; ʏ UU -&gt; ʊ EE -&gt; ɛ OO -&gt; ɞ LL &rarr; ʟ II &rarr; ɪ YY &rarr; ʏ UU &rarr; ʊ EE &rarr; ɛ OO &rarr; ɞ
AA -&gt; ɑ '' -&gt; ˈ ,, -&gt; ˌ :: -&gt; ː AA &rarr; ɑ '' &rarr; ˈ ,, &rarr; ˌ :: &rarr; ː
</code></pre> </code></pre>
</li> </li>
<li> <li>
<p>The slash is used to &quot;reflect,&quot; &quot;rotate,&quot; or otherwise flip around a given <p>The slash is used to &quot;reflect,&quot; &quot;rotate,&quot; or otherwise flip around a given
symbol:</p> symbol:</p>
<pre><code> ʀ/ -&gt; ʁ ʔ/ -&gt; ʕ ?/ -&gt; ʕ r/ -&gt; ɹ y/ -&gt; ʎ m/ -&gt; ɯ <pre><code> ʀ/ &rarr; ʁ ʔ/ &rarr; ʕ ?/ &rarr; ʕ r/ &rarr; ɹ y/ &rarr; ʎ m/ &rarr; ɯ
o/ -&gt; ø e/ -&gt; ə ɛ/ -&gt; ɜ c/ -&gt; ɔ a/ -&gt; ɐ ɑ/ -&gt; ɒ o/ &rarr; ø e/ &rarr; ə ɛ/ &rarr; ɜ c/ &rarr; ɔ a/ &rarr; ɐ ɑ/ &rarr; ɒ
w/ -&gt; ʍ h/ -&gt; ɥ k/ -&gt; ʞ !/ -&gt; ¡ v/ -&gt; ʌ w/ &rarr; ʍ h/ &rarr; ɥ k/ &rarr; ʞ !/ &rarr; ¡ v/ &rarr; ʌ
</code></pre> </code></pre>
<p>Also note that for any digraph, if either of the two characters that <p>Also note that for any digraph, if either of the two characters that
compose it are not &quot;standard&quot; letters you can find on your keyboard, the compose it are not &quot;standard&quot; letters you can find on your keyboard, the
@ -35,26 +35,26 @@ visual <code>o|</code> and <code>|o</code>.</p>
characters, or two characters next to each other. This includes &quot;hooked&quot; characters, or two characters next to each other. This includes &quot;hooked&quot;
letters (such as ŋ), produced with the original letter and a comma, and letters (such as ŋ), produced with the original letter and a comma, and
&quot;stroked&quot; letters (such as ɟ), produced with the original letter and a dash:</p> &quot;stroked&quot; letters (such as ɟ), produced with the original letter and a dash:</p>
<pre><code> m, -&gt; ɱ n, -&gt; ŋ ŋ, -&gt; ɲ v, -&gt; ⱱ c, -&gt; ç j, -&gt; ʝ <pre><code> m, &rarr; ɱ n, &rarr; ŋ ŋ, &rarr; ɲ v, &rarr; ⱱ c, &rarr; ç j, &rarr; ʝ
x, -&gt; ɣ ɣ, -&gt; χ h, -&gt; ɦ w, -&gt; ɰ x, &rarr; ɣ ɣ, &rarr; χ h, &rarr; ɦ w, &rarr; ɰ
j- -&gt; ɟ h- -&gt; ħ l- -&gt; ɬ i- -&gt; ɨ u- -&gt; ʉ e- -&gt; ɘ j- &rarr; ɟ h- &rarr; ħ l- &rarr; ɬ i- &rarr; ɨ u- &rarr; ʉ e- &rarr; ɘ
o- -&gt; ɵ ʕ- -&gt; ʢ ?- -&gt; ʡ ʔ- -&gt; ʡ o- &rarr; ɵ ʕ- &rarr; ʢ ?- &rarr; ʡ ʔ- &rarr; ʡ
LZ -&gt; ɮ OX -&gt; ɤ XO -&gt; ɤ OE -&gt; œ EB -&gt; ɞ AE -&gt; æ LZ &rarr; ɮ OX &rarr; ɤ XO &rarr; ɤ OE &rarr; œ EB &rarr; ɞ AE &rarr; æ
CE -&gt; ɶ RL -&gt; ɺ LR -&gt; ɺ ɾl -&gt; ɺ lɾ -&gt; ɺ CE &rarr; ɶ RL &rarr; ɺ LR &rarr; ɺ ɾl &rarr; ɺ lɾ &rarr; ɺ
w| -&gt; ɰ o/ -&gt; ø ɜ( -&gt; ɞ /\ -&gt; ʌ o| -&gt; ɑ a| -&gt; ɑ w| &rarr; ɰ o/ &rarr; ø ɜ( &rarr; ɞ /\ &rarr; ʌ o| &rarr; ɑ a| &rarr; ɑ
|o -&gt; ɒ |a -&gt; ɒ |o &rarr; ɒ |a &rarr; ɒ
o. -&gt; ʘ |= -&gt; ǂ || -&gt; ‖ /^ -&gt; ↗ /&gt; -&gt; ↗ \v -&gt; ↘ o. &rarr; ʘ |= &rarr; ǂ || &rarr; ‖ /^ &rarr; ↗ /&gt; &rarr; ↗ \v &rarr; ↘
\&gt; -&gt; ↘ \&gt; &rarr; ↘
</code></pre> </code></pre>
</li> </li>
<li> <li>
<p>Others are based on pronunciation:</p> <p>Others are based on pronunciation:</p>
<pre><code> PH -&gt; ɸ BH -&gt; β TH -&gt; θ DH -&gt; ð SH -&gt; ʃ ZH -&gt; ʒ <pre><code> PH &rarr; ɸ BH &rarr; β TH &rarr; θ DH &rarr; ð SH &rarr; ʃ ZH &rarr; ʒ
SJ -&gt; ɕ ZJ -&gt; ʑ ʃx -&gt; ɧ xʃ -&gt; ɧ SJ &rarr; ɕ ZJ &rarr; ʑ ʃx &rarr; ɧ xʃ &rarr; ɧ
</code></pre> </code></pre>
<p>It may be worth noting at this point that digraphs of two lowercase letters <p>It may be worth noting at this point that digraphs of two lowercase letters
were intentionally avoided to prevent interference with regular typing. If were intentionally avoided to prevent interference with regular typing. If
@ -66,7 +66,7 @@ to the second character.</p>
</li> </li>
<li> <li>
<p>A few digraphs are based on shape:</p> <p>A few digraphs are based on shape:</p>
<pre><code> rO -&gt; ɾ r0 -&gt; ɾ vO -&gt; ʋ v0 -&gt; ʋ <pre><code> rO &rarr; ɾ r0 &rarr; ɾ vO &rarr; ʋ v0 &rarr; ʋ
</code></pre> </code></pre>
<p>Another related point: digraphs that contain a lowercase letter can also be <p>Another related point: digraphs that contain a lowercase letter can also be
typed with that letter as uppercase. So, if <code>RO</code> is easier to type than typed with that letter as uppercase. So, if <code>RO</code> is easier to type than
@ -75,35 +75,35 @@ typed with that letter as uppercase. So, if <code>RO</code> is easier to type th
<li> <li>
<p>Retroflex and nonpulmonic symbols have their own categories:</p> <p>Retroflex and nonpulmonic symbols have their own categories:</p>
<pre><code> retroflex: ) looks like the shape of the tongue <pre><code> retroflex: ) looks like the shape of the tongue
t) -&gt; ʈ d) -&gt; ɖ n) -&gt; ɳ r) -&gt; ɽ ɾ) -&gt; ɽ s) -&gt; ʂ t) &rarr; ʈ d) &rarr; ɖ n) &rarr; ɳ r) &rarr; ɽ ɾ) &rarr; ɽ s) &rarr; ʂ
z) -&gt; ʐ ɹ) -&gt; ɻ l) -&gt; ɭ ɗ) -&gt; ᶑ z) &rarr; ʐ ɹ) &rarr; ɻ l) &rarr; ɭ ɗ) &rarr; ᶑ
clicks: clicking noise reminiscent of a * clicks: clicking noise reminiscent of a *
o* -&gt; ʘ |* -&gt; ǀ !* -&gt; ǃ =* -&gt; ǁ o* &rarr; ʘ |* &rarr; ǀ !* &rarr; ǃ =* &rarr; ǁ
implosives and ejective marker: direction of airflow implosives and ejective marker: direction of airflow
b( -&gt; ɓ d( -&gt; ɗ j( -&gt; ʄ ɟ( -&gt; ʄ g( -&gt; ɠ ɢ( -&gt; ʛ b( &rarr; ɓ d( &rarr; ɗ j( &rarr; ʄ ɟ( &rarr; ʄ g( &rarr; ɠ ɢ( &rarr; ʛ
ɖ( -&gt; ᶑ ') -&gt; ʼ ɖ( &rarr; ᶑ ') &rarr; ʼ
</code></pre> </code></pre>
</li> </li>
<li> <li>
<p>Superscripts and diacritics that go above the letter use <code>^</code>, diacritics that <p>Superscripts and diacritics that go above the letter use <code>^</code>, diacritics that
go below use <code>_</code>, and miscellaneous &quot;moved&quot; symbols go below use <code>_</code>, and miscellaneous &quot;moved&quot; symbols
use <code>&lt;</code> or <code>&gt;</code>:</p> use <code>&lt;</code> or <code>&gt;</code>:</p>
<pre><code> ^h -&gt; ʰ ^n -&gt; ⁿ ^m -&gt; ᵐ ^ŋ -&gt; ᵑ ^l -&gt; ˡ ^w -&gt; ʷ <pre><code> ^h &rarr; ʰ ^n &rarr; ⁿ ^m &rarr; ᵐ ^ŋ &rarr; ᵑ ^l &rarr; ˡ ^w &rarr; ʷ
^j -&gt; ʲ ^ɥ -&gt; ᶣ ^ʋ -&gt; ᶹ ^ɣ -&gt; ˠ ^ʕ -&gt; ˤ ^j &rarr; ʲ ^ɥ &rarr; ᶣ ^ʋ &rarr; ᶹ ^ɣ &rarr; ˠ ^ʕ &rarr; ˤ
_| -&gt; ◌̩ ^| -&gt; ◌̍ _o -&gt; ◌̥ ^o -&gt; ◌̊ _v -&gt; ◌̬ ^v -&gt; ◌̌ _| &rarr; ◌̩ ^| &rarr; ◌̍ _o &rarr; ◌̥ ^o &rarr; ◌̊ _v &rarr; ◌̬ ^v &rarr; ◌̌
_^ -&gt; ◌̯ _: -&gt; ◌̤ _~ -&gt; ◌̰ _[ -&gt; ◌̪ _] -&gt; ◌̺ _{ -&gt; ◌̼ _^ &rarr; ◌̯ _: &rarr; ◌̤ _~ &rarr; ◌̰ _[ &rarr; ◌̪ _] &rarr; ◌̺ _{ &rarr; ◌̼
_+ -&gt; ◌̟ __ -&gt; ◌̠ _) -&gt; ◌̹ _( -&gt; ◌̜ _# -&gt; ◌̻ [] -&gt; ◌̻ _+ &rarr; ◌̟ __ &rarr; ◌̠ _) &rarr; ◌̹ _( &rarr; ◌̜ _# &rarr; ◌̻ [] &rarr; ◌̻
^&gt; -&gt; ◌̚ ^: -&gt; ◌̈ ^x -&gt; ◌̽ ^~ -&gt; ◌̃ ^&gt; &rarr; ◌̚ ^: &rarr; ◌̈ ^x &rarr; ◌̽ ^~ &rarr; ◌̃
-' -&gt; ˔ _˔ -&gt; ◌̝ -, -&gt; ˕ _˕ -&gt; ◌̞ &lt;| -&gt; ⊣ _⊣ -&gt; ◌̘ -' &rarr; ˔ _˔ &rarr; ◌̝ -, &rarr; ˕ _˕ &rarr; ◌̞ &lt;| &rarr; ⊣ _⊣ &rarr; ◌̘
&gt;| -&gt; ⊢ _⊢ -&gt; ◌̙ &gt;| &rarr; ⊢ _⊢ &rarr; ◌̙
~~ -&gt; ◌̴ &gt;r -&gt; ˞ ~~ &rarr; ◌̴ &gt;r &rarr; ˞
</code></pre> </code></pre>
<p>Note that all of these sequences can be flipped in order—that is, <code>^h</code> <p>Note that all of these sequences can be flipped in order—that is, <code>^h</code>
produces the same thing as <code>h^</code>. This allows usage such as <code>|&lt;_</code> to produce produces the same thing as <code>h^</code>. This allows usage such as <code>|&lt;_</code> to produce
@ -111,16 +111,16 @@ produces the same thing as <code>h^</code>. This allows usage such as <code>|&lt
</li> </li>
<li> <li>
<p>Tonal countours use numbers plus <code>|</code>:</p> <p>Tonal countours use numbers plus <code>|</code>:</p>
<pre><code> 5| -&gt; ˥ 4| -&gt; ˦ 3| -&gt; ˧ 2| -&gt; ˨ 1| -&gt; ˩ <pre><code> 5| &rarr; ˥ 4| &rarr; ˦ 3| &rarr; ˧ 2| &rarr; ˨ 1| &rarr; ˩
+| -&gt; ꜛ -| -&gt; ꜜ +| &rarr; ꜛ -| &rarr; ꜜ
</code></pre> </code></pre>
</li> </li>
<li> <li>
<p>Finally, some digraphs simply have unique mnemonics:</p> <p>Finally, some digraphs simply have unique mnemonics:</p>
<pre><code> ː- -&gt; ˑ &quot;chop off&quot; the bottom triangle <pre><code> ː- &rarr; ˑ &quot;chop off&quot; the bottom triangle
(( -&gt; ◌͡◌ two parens for a tie that connects 2 chars (( &rarr; ◌͡◌ two parens for a tie that connects 2 chars
)) -&gt; ◌͜◌ )) &rarr; ◌͜◌
◌͜◌) -&gt; ‿ one more paren to make it a little bit longer ◌͜◌) &rarr; ‿ one more paren to make it a little bit longer
</code></pre> </code></pre>
</li> </li>
</ul> </ul>

View File

@ -1,4 +1,4 @@
import { renderDictionaryDetails, renderPartsOfSpeech, renderAll } from "./render"; import { renderDictionaryDetails, renderPartsOfSpeech, renderAll, renderWords } from "./render";
import { removeTags, cloneObject, getTimestampInSeconds, download, slugify } from "../helpers"; import { removeTags, cloneObject, getTimestampInSeconds, download, slugify } from "../helpers";
import { LOCAL_STORAGE_KEY, DEFAULT_DICTIONARY, MIGRATE_VERSION } from "../constants"; import { LOCAL_STORAGE_KEY, DEFAULT_DICTIONARY, MIGRATE_VERSION } from "../constants";
import { addMessage, getNextId, hasToken } from "./utilities"; import { addMessage, getNextId, hasToken } from "./utilities";
@ -63,7 +63,10 @@ export function saveEditModal() {
window.currentDictionary.settings.caseSensitive = document.getElementById('editCaseSensitive').checked; window.currentDictionary.settings.caseSensitive = document.getElementById('editCaseSensitive').checked;
const needsReSort = window.currentDictionary.settings.sortByDefinition !== document.getElementById('editSortByDefinition').checked; const needsReSort = window.currentDictionary.settings.sortByDefinition !== document.getElementById('editSortByDefinition').checked;
window.currentDictionary.settings.sortByDefinition = document.getElementById('editSortByDefinition').checked; window.currentDictionary.settings.sortByDefinition = document.getElementById('editSortByDefinition').checked;
let needsWordRender = false;
if (hasToken()) { if (hasToken()) {
needsWordRender = window.currentDictionary.settings.isPublic !== document.getElementById('editIsPublic').checked;
window.currentDictionary.settings.isPublic = document.getElementById('editIsPublic').checked; window.currentDictionary.settings.isPublic = document.getElementById('editIsPublic').checked;
} else { } else {
window.currentDictionary.settings.isPublic = false; window.currentDictionary.settings.isPublic = false;
@ -74,7 +77,7 @@ export function saveEditModal() {
renderDictionaryDetails(); renderDictionaryDetails();
renderPartsOfSpeech(); renderPartsOfSpeech();
if (needsReSort) { if (needsReSort || needsWordRender) {
sortWords(true); sortWords(true);
} }

View File

@ -36,7 +36,25 @@ export function renderDictionaryDetails() {
export function renderName() { export function renderName() {
const dictionaryName = removeTags(window.currentDictionary.name) + ' ' + removeTags(window.currentDictionary.specification); const dictionaryName = removeTags(window.currentDictionary.name) + ' ' + removeTags(window.currentDictionary.specification);
document.getElementById('dictionaryName').innerHTML = dictionaryName; const name = document.getElementById('dictionaryName');
name.innerHTML = dictionaryName;
const isPublic = hasToken() && window.currentDictionary.settings.isPublic;
const shareLinkElement = document.getElementById('dictionaryShare');
if (isPublic && !shareLinkElement) {
const shareLink = document.createElement('a');
shareLink.id = 'dictionaryShare';
shareLink.classList.add('button');
shareLink.style.float = 'right';
shareLink.href = window.location.pathname.match(new RegExp(window.currentDictionary.externalID + '$')) ? window.location.pathname
: window.location.pathname.substring(0, window.location.pathname.indexOf(window.currentDictionary.externalID)) + window.currentDictionary.externalID;
shareLink.target = '_blank';
shareLink.title = 'Public Link to Dictionary';
shareLink.innerHTML = '&#10150;';
name.parentElement.insertBefore(shareLink, name);
} else if (!isPublic && shareLinkElement) {
shareLinkElement.parentElement.removeChild(shareLinkElement);
}
} }
export function renderDescription() { export function renderDescription() {
@ -179,10 +197,10 @@ export function renderWords() {
<h4 class="word">${word.name}${homonymnNumber > 0 ? ' <sub>' + homonymnNumber.toString() + '</sub>' : ''}</h4> <h4 class="word">${word.name}${homonymnNumber > 0 ? ' <sub>' + homonymnNumber.toString() + '</sub>' : ''}</h4>
<span class="pronunciation">${word.pronunciation}</span> <span class="pronunciation">${word.pronunciation}</span>
<span class="part-of-speech">${word.partOfSpeech}</span> <span class="part-of-speech">${word.partOfSpeech}</span>
${isPublic ? `<a class="small button share-link" href="${shareLink}" target="_blank" title="Public Link to Word">&#10150;</a>` : ''}
<span class="small button word-option-button">Options</span> <span class="small button word-option-button">Options</span>
<div class="word-option-list" style="display:none;"> <div class="word-option-list" style="display:none;">
<div class="word-option" id="edit_${word.wordId}">Edit</div> <div class="word-option" id="edit_${word.wordId}">Edit</div>
${isPublic ? `<a class="word-option" href="${shareLink}" target="_blank">Share</a>` : ''}
<div class="word-option" id="delete_${word.wordId}">Delete</div> <div class="word-option" id="delete_${word.wordId}">Delete</div>
</div> </div>
</header> </header>
@ -278,6 +296,12 @@ export function renderEditForm(wordId = false) {
} }
} }
export function renderIPAHelp() {
import('./KeyboardFire/phondue/usage.html').then(html => {
renderInfoModal(html);
});
}
export function renderIPATable(ipaTableButton) { export function renderIPATable(ipaTableButton) {
ipaTableButton = typeof ipaTableButton.target === 'undefined' || ipaTableButton.target === '' ? ipaTableButton : ipaTableButton.target; ipaTableButton = typeof ipaTableButton.target === 'undefined' || ipaTableButton.target === '' ? ipaTableButton : ipaTableButton.target;
const label = ipaTableButton.parentElement.innerText.replace(/(Field Help|IPA Chart)/g, '').trim(); const label = ipaTableButton.parentElement.innerText.replace(/(Field Help|IPA Chart)/g, '').trim();

View File

@ -8,6 +8,7 @@ import { enableHotKeys, disableHotKeys } from "./hotkeys";
export function loadSettings() { export function loadSettings() {
const storedSettings = window.localStorage.getItem(SETTINGS_KEY); const storedSettings = window.localStorage.getItem(SETTINGS_KEY);
window.settings = storedSettings ? JSON.parse(storedSettings) : cloneObject(DEFAULT_SETTINGS); window.settings = storedSettings ? JSON.parse(storedSettings) : cloneObject(DEFAULT_SETTINGS);
updateTheme();
toggleIPAPronunciationFields(); toggleIPAPronunciationFields();
} }
@ -16,11 +17,17 @@ export function saveSettings() {
addMessage('Settings Saved!'); addMessage('Settings Saved!');
} }
export function updateTheme() {
const { theme } = window.settings;
document.body.id = theme + 'Theme';
}
export function openSettingsModal() { export function openSettingsModal() {
const { useIPAPronunciationField, useHotkeys } = window.settings; const { useIPAPronunciationField, useHotkeys, theme } = window.settings;
document.getElementById('settingsUseIPA').checked = useIPAPronunciationField; document.getElementById('settingsUseIPA').checked = useIPAPronunciationField;
document.getElementById('settingsUseHotkeys').checked = useHotkeys; document.getElementById('settingsUseHotkeys').checked = useHotkeys;
document.getElementById('settingsTheme').value = theme;
document.getElementById('settingsModal').style.display = ''; document.getElementById('settingsModal').style.display = '';
} }
@ -28,6 +35,7 @@ export function openSettingsModal() {
export function saveSettingsModal() { export function saveSettingsModal() {
window.settings.useIPAPronunciationField = document.getElementById('settingsUseIPA').checked; window.settings.useIPAPronunciationField = document.getElementById('settingsUseIPA').checked;
window.settings.useHotkeys = document.getElementById('settingsUseHotkeys').checked; window.settings.useHotkeys = document.getElementById('settingsUseHotkeys').checked;
window.settings.theme = document.getElementById('settingsTheme').value;
if (hasToken()) { if (hasToken()) {
import('./account/index.js').then(account => { import('./account/index.js').then(account => {
@ -49,6 +57,7 @@ export function saveSettingsModal() {
} }
saveSettings(); saveSettings();
updateTheme();
toggleHotkeysEnabled(); toggleHotkeysEnabled();
toggleIPAPronunciationFields(); toggleIPAPronunciationFields();
} }

View File

@ -1,5 +1,5 @@
import {showSection, hideDetailsPanel} from './displayToggles'; import {showSection, hideDetailsPanel} from './displayToggles';
import { renderWords, renderEditForm, renderMaximizedTextbox, renderInfoModal, renderIPATable } from './render'; import { renderWords, renderEditForm, renderMaximizedTextbox, renderInfoModal, renderIPATable, renderIPAHelp } from './render';
import { confirmEditWord, cancelEditWord, confirmDeleteWord, submitWordForm } from './wordManagement'; import { confirmEditWord, cancelEditWord, confirmDeleteWord, submitWordForm } from './wordManagement';
import { openEditModal, saveEditModal, saveAndCloseEditModal, exportDictionary, exportWords, importDictionary, importWords, confirmDeleteDictionary } from './dictionaryManagement'; import { openEditModal, saveEditModal, saveAndCloseEditModal, exportDictionary, exportWords, importDictionary, importWords, confirmDeleteDictionary } from './dictionaryManagement';
import { goToNextPage, goToPreviousPage, goToPage } from './pagination'; import { goToNextPage, goToPreviousPage, goToPage } from './pagination';
@ -287,11 +287,6 @@ export function setupIPAButtons() {
button.addEventListener('click', renderIPATable); button.addEventListener('click', renderIPATable);
}); });
const renderIPAHelp = () => {
import('./KeyboardFire/phondue/usage.html').then(html => {
renderInfoModal(html);
});
}
Array.from(ipaFieldHelpButtons).forEach(button => { Array.from(ipaFieldHelpButtons).forEach(button => {
button.removeEventListener('click', renderIPAHelp); button.removeEventListener('click', renderIPAHelp);
button.addEventListener('click', renderIPAHelp); button.addEventListener('click', renderIPAHelp);

View File

@ -4,6 +4,7 @@ import { getWordsStats, wordExists } from '../utilities';
import { getMatchingSearchWords, highlightSearchTerm, getSearchFilters, getSearchTerm } from '../search'; import { getMatchingSearchWords, highlightSearchTerm, getSearchFilters, getSearchTerm } from '../search';
import { showSection } from '../displayToggles'; import { showSection } from '../displayToggles';
import { setupSearchFilters, setupInfoModal } from './setupListeners'; import { setupSearchFilters, setupInfoModal } from './setupListeners';
import { parseReferences } from '../wordManagement';
export function renderAll() { export function renderAll() {
renderDictionaryDetails(); renderDictionaryDetails();
@ -25,6 +26,9 @@ export function renderDictionaryDetails() {
export function renderName() { export function renderName() {
const dictionaryName = removeTags(window.currentDictionary.name) + ' ' + removeTags(window.currentDictionary.specification); const dictionaryName = removeTags(window.currentDictionary.name) + ' ' + removeTags(window.currentDictionary.specification);
document.getElementById('dictionaryName').innerHTML = dictionaryName; document.getElementById('dictionaryName').innerHTML = dictionaryName;
const shareLink = window.location.pathname.match(new RegExp(window.currentDictionary.externalID + '$')) ? window.location.pathname
: window.location.pathname.substring(0, window.location.pathname.indexOf(window.currentDictionary.externalID)) + window.currentDictionary.externalID;
document.getElementById('dictionaryShare').href = shareLink;
} }
export function renderDescription() { export function renderDescription() {
@ -134,18 +138,8 @@ export function renderWords() {
} }
words.forEach(originalWord => { words.forEach(originalWord => {
let detailsMarkdown = removeTags(originalWord.details); let detailsMarkdown = originalWord.details;
const references = detailsMarkdown.match(/\{\{.+?\}\}/g); detailsMarkdown = parseReferences(detailsMarkdown);
if (references && Array.isArray(references)) {
new Set(references).forEach(reference => {
const wordToFind = reference.replace(/\{\{|\}\}/g, '');
const existingWordId = wordExists(wordToFind, true);
if (existingWordId !== false) {
const wordMarkdownLink = `[${wordToFind}](#${existingWordId})`;
detailsMarkdown = detailsMarkdown.replace(new RegExp(reference, 'g'), wordMarkdownLink);
}
});
}
const word = highlightSearchTerm({ const word = highlightSearchTerm({
name: removeTags(originalWord.name), name: removeTags(originalWord.name),
pronunciation: removeTags(originalWord.pronunciation), pronunciation: removeTags(originalWord.pronunciation),
@ -154,11 +148,13 @@ export function renderWords() {
details: detailsMarkdown, details: detailsMarkdown,
wordId: originalWord.wordId, wordId: originalWord.wordId,
}); });
const shareLink = window.location.pathname + (window.location.pathname.match(new RegExp(word.wordId + '$')) ? '' : '/' + word.wordId);
wordsHTML += `<article class="entry" id="${word.wordId}"> wordsHTML += `<article class="entry" id="${word.wordId}">
<header> <header>
<h4 class="word">${word.name}</h4> <h4 class="word">${word.name}</h4>
<span class="pronunciation">${word.pronunciation}</span> <span class="pronunciation">${word.pronunciation}</span>
<span class="part-of-speech">${word.partOfSpeech}</span> <span class="part-of-speech">${word.partOfSpeech}</span>
<a href="${shareLink}" target="_blank" class="small button word-option-button" title="Link to Word">&#10150;</a>
</header> </header>
<dl> <dl>
<dt class="definition">${word.definition}</dt> <dt class="definition">${word.definition}</dt>

View File

@ -46,43 +46,46 @@ export function sortWords(render) {
} }
} }
export function parseReferences(detailsMarkdown, references) { export function parseReferences(detailsMarkdown) {
new Set(references).forEach(reference => { const references = detailsMarkdown.match(/\{\{.+?\}\}/g);
let wordToFind = reference.replace(/\{\{|\}\}/g, ''); if (references && Array.isArray(references)) {
let homonymn = 0; new Set(references).forEach(reference => {
let wordToFind = reference.replace(/\{\{|\}\}/g, '');
let homonymn = 0;
if (wordToFind.includes(':')) { if (wordToFind.includes(':')) {
const separator = wordToFind.indexOf(':'); const separator = wordToFind.indexOf(':');
homonymn = wordToFind.substr(separator + 1); homonymn = wordToFind.substr(separator + 1);
wordToFind = wordToFind.substring(0, separator); wordToFind = wordToFind.substring(0, separator);
if (homonymn && homonymn.trim() if (homonymn && homonymn.trim()
&& !isNaN(parseInt(homonymn.trim())) && parseInt(homonymn.trim()) > 0) { && !isNaN(parseInt(homonymn.trim())) && parseInt(homonymn.trim()) > 0) {
homonymn = parseInt(homonymn.trim()); homonymn = parseInt(homonymn.trim());
} else { } else {
homonymn = false; homonymn = false;
}
} }
}
let existingWordId = false; let existingWordId = false;
const homonymnIndexes = getHomonymnIndexes({ name: wordToFind, wordId: -1 }); const homonymnIndexes = getHomonymnIndexes({ name: wordToFind, wordId: -1 });
if (homonymn !== false && homonymn > 0) { if (homonymn !== false && homonymn > 0) {
if (typeof homonymnIndexes[homonymn - 1] !== 'undefined') { if (typeof homonymnIndexes[homonymn - 1] !== 'undefined') {
existingWordId = window.currentDictionary.words[homonymnIndexes[homonymn - 1]].wordId; existingWordId = window.currentDictionary.words[homonymnIndexes[homonymn - 1]].wordId;
}
} else if (homonymn !== false) {
existingWordId = wordExists(wordToFind, true);
} }
} else if (homonymn !== false) {
existingWordId = wordExists(wordToFind, true);
}
if (existingWordId !== false) { if (existingWordId !== false) {
if (homonymn < 1 && homonymnIndexes.length > 0) { if (homonymn < 1 && homonymnIndexes.length > 0) {
homonymn = 1; homonymn = 1;
}
const homonymnSubHTML = homonymn > 0 ? '<sub>' + homonymn.toString() + '</sub>' : '';
const wordMarkdownLink = `[${wordToFind}${homonymnSubHTML}](#${existingWordId})`;
detailsMarkdown = detailsMarkdown.replace(new RegExp(reference, 'g'), wordMarkdownLink);
} }
const homonymnSubHTML = homonymn > 0 ? '<sub>' + homonymn.toString() + '</sub>' : ''; });
const wordMarkdownLink = `[${wordToFind}${homonymnSubHTML}](#${existingWordId})`; }
detailsMarkdown = detailsMarkdown.replace(new RegExp(reference, 'g'), wordMarkdownLink);
}
});
return detailsMarkdown; return detailsMarkdown;
} }

View File

@ -9,6 +9,8 @@
@import 'scss/mobile/structure'; @import 'scss/mobile/structure';
@import 'scss/mobile/elements'; @import 'scss/mobile/elements';
@import 'scss/themes/default';
html, body { html, body {
font-family: $font; font-family: $font;

View File

@ -1,12 +1,12 @@
RewriteEngine On # Turn on the rewriting engine RewriteEngine On # Turn on the rewriting engine
RewriteRule ^view/([0-9]+)/([0-9]+)/?$ api/router.php?view=publicview&dict=$1&word=$2 [NC,L] # Handle word ids. RewriteRule ^view/([0-9]+)/([0-9]+)/?$ api/router.php?view=word&dict=$1&word=$2 [NC,L] # Handle word ids.
RewriteRule ^([0-9]+)/([0-9]+)/?$ api/router.php?view=publicview&dict=$1&word=$2 [NC,L] # Handle word ids. RewriteRule ^([0-9]+)/([0-9]+)/?$ api/router.php?view=word&dict=$1&word=$2 [NC,L] # Handle word ids.
RewriteRule ^view/([0-9]+)/?$ api/router.php?view=publicview&dict=$1 [NC,L] # Handle dictionary ids. RewriteRule ^view/([0-9]+)/?$ api/router.php?view=dictionary&dict=$1 [NC,L] # Handle dictionary ids.
RewriteRule ^([0-9]+)/?$ api/router.php?view=publicview&dict=$1 [NC,L] # Handle dictionary ids. RewriteRule ^([0-9]+)/?$ api/router.php?view=dictionary&dict=$1 [NC,L] # Handle dictionary ids.
#RewriteRule ^issues/?$ https://github.com/Alamantus/Lexiconga/issues [R=301,L] # Shorten issues url. #RewriteRule ^issues/?$ https://github.com/Alamantus/Lexiconga/issues [R=301,L] # Shorten issues url.

View File

@ -143,13 +143,13 @@ VALUES ($new_id, ?, ?, ?, ?)";
$query = "SELECT words.* FROM words JOIN dictionaries ON id = dictionary WHERE dictionary=? AND is_public=1"; $query = "SELECT words.* FROM words JOIN dictionaries ON id = dictionary WHERE dictionary=? AND is_public=1";
$results = $this->db->query($query, array($dictionary))->fetchAll(); $results = $this->db->query($query, array($dictionary))->fetchAll();
if ($results) { if ($results) {
return array_map(function ($row) { return array_map(function ($row) use ($dictionary) {
return array( return array(
'name' => $row['name'], 'name' => $row['name'],
'pronunciation' => $row['pronunciation'], 'pronunciation' => $row['pronunciation'],
'partOfSpeech' => $row['part_of_speech'], 'partOfSpeech' => $row['part_of_speech'],
'definition' => $row['definition'], 'definition' => $row['definition'],
'details' => $row['details'], 'details' => $this->parseReferences($row['details'], $dictionary),
'lastUpdated' => is_null($row['last_updated']) ? intval($row['created_on']) : intval($row['last_updated']), 'lastUpdated' => is_null($row['last_updated']) ? intval($row['created_on']) : intval($row['last_updated']),
'createdOn' => intval($row['created_on']), 'createdOn' => intval($row['created_on']),
'wordId' => intval($row['word_id']), 'wordId' => intval($row['word_id']),
@ -160,6 +160,87 @@ VALUES ($new_id, ?, ?, ?, ?)";
return array(); return array();
} }
public function getSpecificPublicDictionaryWord ($dictionary, $word) {
if (is_numeric($dictionary) && is_numeric($word)) {
$query = "SELECT words.* FROM words JOIN dictionaries ON id = dictionary WHERE dictionary=? AND word_id=? AND is_public=1";
$result = $this->db->query($query, array($dictionary, $word))->fetch();
if ($result) {
return array(
'name' => $result['name'],
'pronunciation' => $result['pronunciation'],
'partOfSpeech' => $result['part_of_speech'],
'definition' => $result['definition'],
'details' => $this->parseReferences($result['details'], $dictionary),
'lastUpdated' => is_null($result['last_updated']) ? intval($result['created_on']) : intval($result['last_updated']),
'createdOn' => intval($result['created_on']),
'wordId' => intval($result['word_id']),
);
}
}
return false;
}
private function parseReferences($details, $dictionary_id) {
$details = strip_tags($details);
if (preg_match_all('/\{\{.+?\}\}/', $details, $references) !== false) {
$references = array_unique($references[0]);
foreach($references as $reference) {
$word_to_find = preg_replace('/\{\{|\}\}/', '', $reference);
$homonymn = 0;
if (strpos($word_to_find, ':') !== false) {
$separator = strpos($word_to_find, ':');
$homonymn = substr($word_to_find, $separator + 1);
$word_to_find = substr($word_to_find, 0, $separator);
if ($homonymn && trim($homonymn) && intval(trim($homonymn)) > 0) {
$homonymn = intval(trim($homonymn));
} else {
$homonymn = false;
}
}
$target_id = false;
$reference_ids = $this->getWordIdsWithName($dictionary_id, $word_to_find);
if (count($reference_ids) > 0) {
if ($homonymn !== false && $homonymn > 0) {
if (isset($reference_ids[$homonymn - 1])) {
$target_id = $reference_ids[$homonymn - 1];
}
} else if ($homonymn !== false) {
$target_id = $reference_ids[0];
}
if ($target_id !== false) {
if ($homonymn < 1) {
$homonymn = 1;
}
$homonymn_sub_html = $homonymn > 0 ? '<sub>' . $homonymn . '</sub>' : '';
$site_root = substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], $dictionary_id));
$markdown_link = '<a href="' . $site_root . $dictionary_id . '/' . $target_id .'" target="_blank" title="Link to Reference">'
. $word_to_find . $homonymn_sub_html . '</a>';
$details = str_replace($reference, $markdown_link, $details);
}
}
}
}
return $details;
}
private function getWordIdsWithName($dictionary, $word_name) {
if (is_numeric($dictionary)) {
$query = "SELECT word_id FROM words WHERE dictionary=? AND name=?";
$results = $this->db->query($query, array($dictionary, $word_name))->fetchAll();
if ($results) {
return array_map(function ($row) {
return intval($row['word_id']);
}, $results);
}
}
return array();
}
public function getDetails ($user, $dictionary) { public function getDetails ($user, $dictionary) {
$query = "SELECT * FROM dictionaries JOIN dictionary_linguistics ON dictionary = id WHERE user=$user AND id=$dictionary"; $query = "SELECT * FROM dictionaries JOIN dictionary_linguistics ON dictionary = id WHERE user=$user AND id=$dictionary";
$result = $this->db->query($query)->fetch(); $result = $this->db->query($query)->fetch();

View File

@ -2,7 +2,7 @@
$view = isset($_GET['view']) ? $_GET['view'] : false; $view = isset($_GET['view']) ? $_GET['view'] : false;
switch ($view) { switch ($view) {
case 'publicview': { case 'dictionary': {
$html = file_get_contents('../view.html'); $html = file_get_contents('../view.html');
$dict = isset($_GET['dict']) ? $_GET['dict'] : false; $dict = isset($_GET['dict']) ? $_GET['dict'] : false;
if ($dict !== false) { if ($dict !== false) {
@ -26,4 +26,43 @@ switch ($view) {
} }
break; break;
} }
case 'word': {
$html = file_get_contents('../view.html');
$dict = isset($_GET['dict']) ? $_GET['dict'] : false;
$word = isset($_GET['word']) ? $_GET['word'] : false;
if ($dict !== false && $word !== false) {
require_once('./Dictionary.php');
$dictionary = new Dictionary();
$dictionary_data = $dictionary->getPublicDictionaryDetails($dict);
if ($dictionary_data !== false) {
$dictionary_name = $dictionary_data['name'] . ' ' . $dictionary_data['specification'];
$word_data = $dictionary->getSpecificPublicDictionaryWord($dict, $word);
if ($word_data === false) {
$word_data = array(
'name' => 'Error: Word Not Found',
'pronunciation' => '',
'partOfSpeech' => '',
'definition' => 'No word with the id ' . $word . ' was found in the ' . $dictionary_name,
'details' => '',
'lastUpdated' => null,
'createdOn' => null,
'wordId' => null,
);
}
$dictionary_data['words'] = array($word_data);
$html = str_replace('{{dict}}', $dict, $html);
$html = str_replace('{{dict_name}}', $word_data['name'] . ' in the ' . $dictionary_name, $html);
$html = str_replace('{{public_name}}', $dictionary_data['createdBy'], $html);
$dictionary_json = json_encode($dictionary_data);
$html = str_replace('{{dict_json}}', addslashes($dictionary_json), $html);
} else {
$html = str_replace('{{dict}}', 'error', $html);
$html = str_replace('{{dict_name}}', 'Error: Dictionary Not Found', $html);
$html = str_replace('{{public_name}}', 'Error', $html);
$html = str_replace('{{dict_json}}', '{"name": "Error:", "specification": "Dictionary Not Found", "words": []}', $html);
}
echo $html;
}
break;
}
} }

View File

@ -14,3 +14,9 @@
} }
} }
} }
.share-link {
margin-left: $general-padding !important;
line-height: 16px !important;
padding: 1px 3px 3px !important;
}

View File

@ -1,7 +1,6 @@
header { header {
display: block; display: block;
padding: 5px $general-padding; padding: 5px $general-padding;
border-bottom: 1px solid $mid;
margin: 0 0 5px; margin: 0 0 5px;
&#top { &#top {
@ -14,7 +13,7 @@ main {
width: 90%; width: 90%;
max-width: 1000px; max-width: 1000px;
min-height: 400px; min-height: 400px;
margin: 0 auto; margin: 0 auto ($header-height * 1.25);
#sideColumn, #sideColumn,
#mainColumn { #mainColumn {
@ -29,13 +28,12 @@ main {
#mainColumn { #mainColumn {
width: 64%; width: 64%;
margin: 0; margin: $general-padding 0 0;
} }
article { article {
width: 95%; width: 95%;
margin: 10px auto; margin: 10px auto;
border: $border;
dl { dl {
padding: 0 $general-padding; padding: 0 $general-padding;
@ -46,6 +44,5 @@ main {
footer { footer {
display: block; display: block;
padding: $general-padding; padding: $general-padding;
border-top: 1px solid $mid;
margin: 5px 0 0; margin: 5px 0 0;
} }

View File

@ -1,8 +1,8 @@
p, span { a {
&.red { text-decoration: underline;
color: $red; }
}
p, span {
&.bold { &.bold {
font-weight: bold; font-weight: bold;
} }
@ -34,24 +34,42 @@ label {
} }
.label-button { .label-button {
@extend .button; display: inline-block;
padding: 3px 9px;
border-radius: 3px;
line-height: 30px;
cursor: pointer;
user-select: none;
font-size: 80%; font-size: 80%;
font-weight: normal; font-weight: normal;
float: right; float: right;
cursor: pointer; cursor: pointer;
line-height: 80% !important; line-height: 80% !important;
padding: 3px 3px 5px; padding: 3px 3px 5px;
&.small {
font-size: 80%;
line-height: 25px;
}
} }
.label-help-button { .label-help-button {
@extend .button; display: inline-block;
padding: 3px 9px;
border-radius: 3px;
line-height: 30px;
cursor: pointer;
user-select: none;
font-size: 70%; font-size: 70%;
font-weight: normal; font-weight: normal;
cursor: pointer; cursor: pointer;
line-height: 70% !important; line-height: 70% !important;
padding: 2px 2px 4px; padding: 2px 2px 4px;
&.small {
font-size: 80%;
line-height: 25px;
}
} }
} }
@ -62,9 +80,21 @@ ul {
.tag { .tag {
display: inline-block; display: inline-block;
padding: 3px 9px; padding: 3px 9px;
border: $border;
border-radius: 3px; border-radius: 3px;
background-color: $light; line-height: 30px;
&.small {
font-size: 80%;
line-height: 25px;
}
}
span .tag {
border-radius: 3px 0 0 3px;
display: inline-block;
padding: 3px 9px;
border-radius: 3px;
line-height: 30px; line-height: 30px;
&.small { &.small {
@ -72,28 +102,24 @@ ul {
line-height: 25px; line-height: 25px;
} }
&.red {
background-color: $red;
color: $white;
}
}
span .tag {
@extend .tag;
border-radius: 3px 0 0 3px;
&+.tag { &+.tag {
border-left: none; border-left: none;
border-radius: 0 3px 3px 0; border-radius: 0 3px 3px 0;
background-color: $white;
} }
} }
.button { .button {
@extend .tag; display: inline-block;
padding: 3px 9px;
border-radius: 3px;
line-height: 30px;
cursor: pointer; cursor: pointer;
user-select: none; user-select: none;
&.small {
font-size: 80%;
line-height: 25px;
}
} }
.modal { .modal {
@ -109,7 +135,6 @@ span .tag {
left: 0; left: 0;
bottom: 0; bottom: 0;
right: 0; right: 0;
background-color: #000000;
opacity: 0.5; opacity: 0.5;
} }
@ -122,8 +147,6 @@ span .tag {
max-width: 100%; max-width: 100%;
height: 600px; height: 600px;
max-height: 100%; max-height: 100%;
background-color: $white;
border: $border;
border-radius: 5px; border-radius: 5px;
.close-button { .close-button {
@ -139,25 +162,13 @@ span .tag {
} }
.tabs { .tabs {
ul {
border-bottom: $border;
}
li { li {
display: inline-block; display: inline-block;
list-style: none; list-style: none;
margin: 0 2px -1px; margin: 0 2px -1px;
padding: 10px $general-padding; padding: 10px $general-padding;
border-top: $border;
border-left: $border;
border-right: $border;
border-radius: 5px 5px 0 0; border-radius: 5px 5px 0 0;
background-color: $mid;
cursor: pointer; cursor: pointer;
&.active {
background-color: $white;
border-bottom: 1px solid $white;
}
} }
} }

View File

@ -42,7 +42,6 @@
left: unset; left: unset;
bottom: unset; bottom: unset;
right: unset; right: unset;
background-color: $white;
padding: ($general-padding / 2) $general-padding ($general-padding * 0.25); padding: ($general-padding / 2) $general-padding ($general-padding * 0.25);
font-size: 90%; font-size: 90%;
@ -100,16 +99,13 @@
#wordForm { #wordForm {
position: fixed; position: fixed;
top: auto; top: $header-height + $general-padding;
width: 31%; width: 31%;
max-width: 320px; max-width: 320px;
padding: 10px; padding: 10px;
background-color: $light;
border: $border;
border-radius: 5px; border-radius: 5px;
max-height: 80%; max-height: 80%;
overflow-y: auto; overflow-y: auto;
box-shadow: 4px 4px 5px 0px rgba(50, 50, 50, 0.75);
} }
.edit-form { .edit-form {
@ -117,11 +113,12 @@
max-width: 500px; max-width: 500px;
} }
#detailsSection { #mainColumn {
padding: $general-padding;
background-color: $white;
border: $border;
border-radius: 5px; border-radius: 5px;
}
#detailsSection {
padding: $general-padding $general-padding 0;
#dictionaryName { #dictionaryName {
margin-top: 0; margin-top: 0;
@ -135,8 +132,6 @@
list-style: none; list-style: none;
margin: 0; margin: 0;
padding: 10px $general-padding; padding: 10px $general-padding;
border: $border;
background-color: $light;
cursor: pointer; cursor: pointer;
&:first-child { &:first-child {
@ -148,15 +143,10 @@
&:not(:first-child) { &:not(:first-child) {
border-left: none; border-left: none;
} }
&.active {
background-color: #bababa;
}
} }
} }
#detailsPanel { #detailsPanel {
background-color: $white;
padding: $general-padding; padding: $general-padding;
max-height: 400px; max-height: 400px;
overflow-y: auto; overflow-y: auto;
@ -170,8 +160,6 @@
.entry { .entry {
background-color: $light;
.word { .word {
display: inline-block; display: inline-block;
margin: 3px 0; margin: 3px 0;
@ -202,15 +190,12 @@
position: absolute; position: absolute;
top: 3px; top: 3px;
right: 3px; right: 3px;
background-color: $white;
border: $border;
border-radius: 5px; border-radius: 5px;
.word-option { .word-option {
padding: 10px 25px;; padding: 10px 25px;;
&:hover { &:hover {
background-color: $light;
cursor: pointer; cursor: pointer;
} }
} }
@ -339,13 +324,12 @@ $nav-font-height: 16px;
bottom: $general-padding; bottom: $general-padding;
right: $general-padding; right: $general-padding;
max-width: 300px; max-width: 300px;
z-index: 10;
.message { .message {
position: relative; position: relative;
display: block; display: block;
padding: $general-padding ($general-padding * 2) $general-padding $general-padding; padding: $general-padding ($general-padding * 2) $general-padding $general-padding;
background-color: $light;
border: $border;
border-radius: 5px; border-radius: 5px;
margin-bottom: 5px; margin-bottom: 5px;
@ -353,10 +337,6 @@ $nav-font-height: 16px;
margin-bottom: 0; margin-bottom: 0;
} }
&.error {
background-color: lighten($red, 0.75);
}
.close-button { .close-button {
position: absolute; position: absolute;
top: 5px; top: 5px;
@ -372,7 +352,6 @@ $nav-font-height: 16px;
right: -2px; right: -2px;
width: 20px; width: 20px;
height: 20px; height: 20px;
background-color: #455455;
opacity: 0.5; opacity: 0.5;
transform-origin: center left; transform-origin: center left;
transform: scaleX(0); transform: scaleX(0);
@ -391,10 +370,19 @@ $nav-font-height: 16px;
} }
#bottom { #bottom {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 5;
text-align: center; text-align: center;
padding: $general-padding / 2;
a { a {
color: #000000;
text-decoration: none; text-decoration: none;
} }
.separator {
display: inline;
}
} }

View File

@ -2,12 +2,12 @@ $font: BlinkMacSystemFont, -apple-system, "Segoe UI", "Roboto", "Oxygen", "Ubunt
$header-height: 60px; $header-height: 60px;
$dark: #bababa; // $dark: #bababa;
$mid: #dedede; // $mid: #dedede;
$light: #efefef; // $light: #efefef;
$white: #ffffff; // $white: #ffffff;
$red: #d42932; // $red: #d42932;
$border: 1px solid $dark; // $border: 1px solid $dark;
$general-padding: 20px; $general-padding: 20px;

View File

@ -12,6 +12,8 @@ header {
} }
main { main {
margin-bottom: $general-padding;
#sideColumn { #sideColumn {
display: block; display: block;
width: 0; width: 0;

View File

@ -1,21 +1,21 @@
@media (max-width: 750px) { @media (max-width: 750px) {
.tag { // .tag {
padding: 2px 6px; // padding: 2px 6px;
font-size: 90%; // font-size: 90%;
line-height: 120%; // line-height: 120%;
&.small { // &.small {
font-size: 70%; // font-size: 70%;
line-height: 100%; // line-height: 100%;
} // }
} // }
.button { // .button {
@extend .tag; // @extend .tag;
cursor: pointer; // cursor: pointer;
user-select: none; // user-select: none;
} // }
.tabs { .tabs {
li { li {

View File

@ -34,10 +34,7 @@
width: 32px; width: 32px;
height: 32px; height: 32px;
display: block; display: block;
background-color: #00de00;
border: $border;
border-radius: 0 3px 3px 0; border-radius: 0 3px 3px 0;
color: $white;
font-size: 30px; font-size: 30px;
line-height: 24px; line-height: 24px;
font-weight: bold; font-weight: bold;
@ -88,4 +85,14 @@
} }
} }
#bottom {
position: relative;
bottom: unset;
.separator {
display: block;
visibility: hidden;
}
}
} }

View File

@ -0,0 +1,255 @@
#defaultTheme {
$dark: #bababa;
$mid: #dedede;
$light: #efefef;
$white: #ffffff;
$red: #b42032;
$header-color: #eacc9d;
$background-color: #e6cfaa;
$footer-color: #cb6318;
$link-color: #a01000;
$button-color: #dcb078;
$message-color: #c0c088;
$word-form-color: #ba5536;
$dictionary-color: #bd7251;
$entry-color: #d7ad7d;
$input-color: #efdfc0;
$details-color: #f2d5b2;
$modal-color: #f2d5b2;
$border: 1px solid $dark;
background-color: $background-color;
a {
color: $link-color;
}
p, span {
&.red {
color: $red;
}
}
label {
.label-button {
border: 1px solid darken($button-color, 2);
background-color: $button-color;
color: #000000;
text-decoration: none;
}
.label-help-button {
border: 1px solid darken($button-color, 2);
background-color: $button-color;
color: #000000;
text-decoration: none;
}
}
input, textarea, select, option {
background-color: $input-color;
}
.tag {
border: $border;
background-color: $button-color;
&.red {
background-color: $red;
color: $white;
}
}
span .tag {
border: $border;
background-color: $button-color;
&+.tag {
background-color: lighten($button-color, 25);
border-left: none;
}
}
.button {
border: 1px solid darken($button-color, 2);
background-color: $button-color;
color: #000000;
text-decoration: none;
font-weight: bold;
&.red {
background-color: $red;
color: $white;
}
}
.modal {
.modal-background {
background-color: #000000;
}
.modal-content {
background-color: $modal-color;
border: 1px solid darken($modal-color, 10);
}
}
.tabs {
ul {
border-bottom: $border;
}
li {
border-top: $border;
border-left: $border;
border-right: $border;
background-color: $button-color;
&.active {
background-color: $modal-color;
border-bottom: 1px solid $modal-color;
}
}
}
header {
border-bottom: 1px solid $mid;
}
main {
article {
border: $border;
}
}
footer {
border-top: 1px solid $mid;
}
#top {
background-color: $header-color;
border-bottom: 1px solid darken($header-color, 2);
box-shadow: 0px 4px 5px 0px rgba(50, 50, 50, 0.75);
#title {
display: inline-block;
margin: 3px $general-padding 3px 0;
}
#openSearchModal {
cursor: pointer;
}
#searchModal {
.modal-content {
section+footer {
background-color: $modal-color;
}
}
}
}
#wordForm {
background-color: $word-form-color;
border: 1px solid darken($word-form-color, 2);
box-shadow: 4px 4px 5px 0px rgba(50, 50, 50, 0.75);
}
#mainColumn {
background-color: $dictionary-color;
border: 1px solid darken($dictionary-color, 2);
box-shadow: 4px 4px 5px 0px rgba(50, 50, 50, 0.75);
}
#detailsSection {
nav ul {
li {
border: 1px solid darken($button-color, 20);
background-color: $button-color;
&.active {
background-color: lighten($button-color, 15);
}
}
}
#detailsPanel {
background-color: $details-color;
}
}
.entry {
background-color: $entry-color;
border: 1px solid darken($entry-color, 20);
header {
border-bottom: 1px solid darken($entry-color, 20);
.word-option-button {
background-color: darken($entry-color, 10);
border: 1px solid darken($entry-color, 20);
}
.word-option-list {
background-color: darken($entry-color, 5);
border: 1px solid darken($entry-color, 10);
.word-option {
&:hover {
background-color: lighten($entry-color, 5);
}
}
}
}
.edit-form {
.button {
background-color: darken($button-color, 10);
}
}
}
#messagingSection {
.message {
background-color: $message-color;
border: $border;
&.error {
background-color: lighten($red, 0.75);
}
.close-button {
&:before {
background-color: #455455;
}
}
}
}
#bottom {
background-color: $footer-color;
border-top: 1px solid darken($footer-color, 2);
box-shadow: 0px -4px 5px 0px rgba(50, 50, 50, 0.75);
a {
color: #000000;
}
}
}
@media (max-width: 750px) {
#defaultTheme {
$dark: #bababa;
$mid: #dedede;
$light: #efefef;
$white: #ffffff;
$red: #b42032;
$border: 1px solid $dark;
#mobileWordFormShow {
background-color: #00de00;
border: $border;
color: $white;
}
}
}

View File

@ -109,7 +109,9 @@
<section id="mainColumn"> <section id="mainColumn">
<section id="detailsSection"> <section id="detailsSection">
<h2 id="dictionaryName">Dictionary Name</h2> <a id="dictionaryShare" href="./" class="button" title="Link to Dictionary" style="float:right;">&#10150;</a>
<h2 id="dictionaryName">{{dict_name}}</h2>
<h4>Created by {{public_name}}</h4>
<nav> <nav>
<ul> <ul>
<li>Description</li><li>Details</li><li>Stats</li><!-- li id="editDictionaryButton">Edit</li --> <li>Description</li><li>Details</li><li>Stats</li><!-- li id="editDictionaryButton">Edit</li -->