2019-05-25 02:50:31 +02:00
import md from 'marked' ;
import { removeTags , slugify } from '../../helpers' ;
2019-07-12 01:16:46 +02:00
import { getHomonymnNumber } from './utilities' ;
2019-06-06 19:03:00 +02:00
import { getMatchingSearchWords , highlightSearchTerm , getSearchFilters , getSearchTerm } from './search' ;
import { showSection } from './displayToggles' ;
2019-06-04 19:11:58 +02:00
import { renderAd } from '../ads' ;
2019-07-11 00:13:01 +02:00
import { setupInfoModal } from '../setupListeners/modals' ;
import { setupSearchFilters } from '../setupListeners/search' ;
2019-05-25 02:50:31 +02:00
export function renderAll ( ) {
2019-05-31 21:15:14 +02:00
renderTheme ( ) ;
2019-07-11 00:45:15 +02:00
renderCustomCSS ( ) ;
2019-05-25 02:50:31 +02:00
renderDictionaryDetails ( ) ;
renderPartsOfSpeech ( ) ;
renderWords ( ) ;
}
2019-06-06 19:03:00 +02:00
export function renderTheme ( ) {
const { theme } = window . currentDictionary . settings ;
document . body . id = theme + 'Theme' ;
}
2019-07-11 00:45:15 +02:00
export function renderCustomCSS ( ) {
const { customCSS } = window . currentDictionary . settings ;
const stylingId = 'customCSS' ;
const stylingElement = document . getElementById ( stylingId ) ;
if ( ! stylingElement ) {
const styling = document . createElement ( 'style' ) ;
styling . id = stylingId ;
styling . innerHTML = customCSS ;
document . body . appendChild ( styling ) ;
} else {
stylingElement . innerHTML = customCSS ;
}
}
2019-05-25 02:50:31 +02:00
export function renderDictionaryDetails ( ) {
renderName ( ) ;
2019-07-07 06:20:06 +02:00
showSection ( 'description' ) ;
2019-05-25 02:50:31 +02:00
}
export function renderName ( ) {
const dictionaryName = removeTags ( window . currentDictionary . name ) + ' ' + removeTags ( window . currentDictionary . specification ) ;
document . getElementById ( 'dictionaryName' ) . innerHTML = dictionaryName ;
2019-05-30 22:01:34 +02:00
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 ;
2019-05-25 02:50:31 +02:00
}
export function renderDescription ( ) {
2019-07-07 08:00:32 +02:00
const descriptionHTML = md ( window . currentDictionary . description ) ;
2019-05-25 02:50:31 +02:00
document . getElementById ( 'detailsPanel' ) . innerHTML = '<div class="content">' + descriptionHTML + '</div>' ;
}
export function renderDetails ( ) {
const { partsOfSpeech , alphabeticalOrder } = window . currentDictionary ;
2019-07-07 06:20:06 +02:00
const { phonology , phonotactics , orthography , grammar } = window . currentDictionary . details ;
2019-07-07 06:40:58 +02:00
const partsOfSpeechHTML = ` <p><strong>Parts of Speech</strong><br> ${ partsOfSpeech . map ( partOfSpeech => '<span class="tag">' + partOfSpeech + '</span>' ) . join ( ' ' ) } </div> ` ;
const alphabeticalOrderHTML = ` <p><strong>Alphabetical Order</strong><br> ${
2019-05-25 02:50:31 +02:00
( alphabeticalOrder . length > 0 ? alphabeticalOrder : [ 'English Alphabet' ] ) . map ( letter => ` <span class="tag"> ${ letter } </span> ` ) . join ( ' ' )
2019-07-07 06:20:06 +02:00
} < / d i v > ` ;
2019-05-25 02:50:31 +02:00
const generalHTML = ` <h3>General</h3> ${ partsOfSpeechHTML } ${ alphabeticalOrderHTML } ` ;
2019-07-07 06:20:06 +02:00
const { consonants , vowels , blends } = phonology
2019-07-07 06:40:58 +02:00
const consonantHTML = ` <p><strong>Consonants</strong><br> ${ consonants . map ( letter => ` <span class="tag"> ${ letter } </span> ` ) . join ( ' ' ) } </p> ` ;
const vowelHTML = ` <p><strong>Vowels</strong><br> ${ vowels . map ( letter => ` <span class="tag"> ${ letter } </span> ` ) . join ( ' ' ) } </p> ` ;
const blendHTML = blends . length > 0 ? ` <p><strong>Polyphthongs / Blends</strong><br> ${ blends . map ( letter => ` <span class="tag"> ${ letter } </span> ` ) . join ( ' ' ) } </p> ` : '' ;
2019-07-10 23:11:46 +02:00
const phonologyNotesHTML = phonology . notes . trim ( ) . length > 0 ? '<p><strong>Notes</strong></p><div>' + md ( removeTags ( phonology . notes ) ) + '</div>' : '' ;
2019-05-25 02:50:31 +02:00
const phonologyHTML = ` <h3>Phonology</h3>
< div class = "split two" >
< div > $ { consonantHTML } < / d i v >
< div > $ { vowelHTML } < / d i v >
< / d i v >
2019-07-10 23:11:46 +02:00
$ { blendHTML }
$ { phonologyNotesHTML } ` ;
2019-05-25 02:50:31 +02:00
2019-07-07 06:20:06 +02:00
const { onset , nucleus , coda } = phonotactics ;
2019-07-07 06:40:58 +02:00
const onsetHTML = ` <p><strong>Onset</strong><br> ${ onset . map ( letter => ` <span class="tag"> ${ letter } </span> ` ) . join ( ' ' ) } </p> ` ;
const nucleusHTML = ` <p><strong>Nucleus</strong><br> ${ nucleus . map ( letter => ` <span class="tag"> ${ letter } </span> ` ) . join ( ' ' ) } </p> ` ;
const codaHTML = ` <p><strong>Coda</strong><br> ${ coda . map ( letter => ` <span class="tag"> ${ letter } </span> ` ) . join ( ' ' ) } </p> ` ;
const phonotacticsNotesHTML = phonotactics . notes . trim ( ) . length > 0 ? '<p><strong>Notes</strong></p><div>' + md ( removeTags ( phonotactics . notes ) ) + '</div>' : '' ;
const phonotacticsHTML = onset . length + nucleus . length + coda . length + phonotacticsNotesHTML . length > 0
? ` <h3>Phonotactics</h3>
2019-07-10 23:11:46 +02:00
$ { onset . length > 0 || nucleus . length > 0 || coda . length > 0
? ` <div class="split three">
2019-07-07 06:40:58 +02:00
< div > $ { onsetHTML } < / d i v >
< div > $ { nucleusHTML } < / d i v >
< div > $ { codaHTML } < / d i v >
2019-07-10 23:11:46 +02:00
< / d i v > ` : ' ' }
2019-07-07 06:40:58 +02:00
$ { phonotacticsNotesHTML } `
: '' ;
2019-05-25 02:50:31 +02:00
2019-07-07 06:20:06 +02:00
const { translations } = orthography ;
2019-07-10 23:11:46 +02:00
const translationsHTML = translations . length > 0 ? ` <p><strong>Translations</strong><br> ${ translations . map ( translation => {
2019-07-07 06:20:06 +02:00
translation = translation . split ( '=' ) . map ( value => value . trim ( ) ) ;
if ( translation . length > 1 && translation [ 0 ] !== '' && translation [ 1 ] !== '' ) {
2019-07-07 07:00:09 +02:00
return ` <span><span class="tag"> ${ translation [ 0 ] } </span><span class="tag orthographic-translation"> ${ translation [ 1 ] } </span></span> ` ;
2019-07-07 06:20:06 +02:00
}
return false ;
2019-07-10 23:11:46 +02:00
} ) . filter ( html => html !== false ) . join ( ' ' ) } < / p > ` : ' ' ;
2019-07-07 06:40:58 +02:00
const orthographyNotesHTML = orthography . notes . trim ( ) . length > 0 ? '<p><strong>Notes</strong><br>' + md ( removeTags ( orthography . notes ) ) + '</div>' : '' ;
2019-07-10 23:11:46 +02:00
const orthographyHTML = translations . length + orthographyNotesHTML . length > 0
2019-07-07 06:40:58 +02:00
? ` <h3>Orthography</h3>
2019-07-10 23:11:46 +02:00
$ { translationsHTML }
2019-07-07 06:40:58 +02:00
$ { orthographyNotesHTML } `
: '' ;
2019-07-10 23:11:46 +02:00
const grammarHTML = grammar . notes . trim ( ) . length > 0 ? '<h3>Grammar</h3><div>'
+ ( grammar . notes . trim ( ) . length > 0 ? md ( removeTags ( grammar . notes ) ) : '' )
+ '</div>' : '' ;
2019-05-25 02:50:31 +02:00
detailsPanel . innerHTML = generalHTML + phonologyHTML + phonotacticsHTML + orthographyHTML + grammarHTML ;
}
export function renderStats ( ) {
2019-07-12 01:16:46 +02:00
const { wordStats } = window . currentDictionary ;
2019-05-25 02:50:31 +02:00
const numberOfWordsHTML = ` <p><strong>Number of Words</strong><br> ${ wordStats . numberOfWords . map ( stat => ` <span><span class="tag"> ${ stat . name } </span><span class="tag"> ${ stat . value } </span></span> ` ) . join ( ' ' ) } </p> ` ;
const wordLengthHTML = ` <p><strong>Word Length</strong><br><span><span class="tag">Shortest</span><span class="tag"> ${ wordStats . wordLength . shortest } </span></span>
< span > < span class = "tag" > Longest < / s p a n > < s p a n c l a s s = " t a g " > $ { w o r d S t a t s . w o r d L e n g t h . l o n g e s t } < / s p a n > < / s p a n >
< span > < span class = "tag" > Average < / s p a n > < s p a n c l a s s = " t a g " > $ { w o r d S t a t s . w o r d L e n g t h . a v e r a g e } < / s p a n > < / s p a n > < / p > ` ;
const letterDistributionHTML = ` <p><strong>Letter Distribution</strong><br> ${ wordStats . letterDistribution . map ( stat => ` <span title=" ${ stat . number } ${ stat . letter } 's total"><span class="tag"> ${ stat . letter } </span><span class="tag"> ${ stat . percentage . toFixed ( 2 ) } </span></span> ` ) . join ( ' ' ) } </p> ` ;
const totalLettersHTML = ` <p><strong> ${ wordStats . totalLetters } Total Letters</strong></p> ` ;
detailsPanel . innerHTML = numberOfWordsHTML + wordLengthHTML + letterDistributionHTML + totalLettersHTML ;
}
export function renderPartsOfSpeech ( onlyOptions = false ) {
let optionsHTML = '<option value=""></option>' ,
searchHTML = '<label>Unclassified <input type="checkbox" checked id="searchPartOfSpeech__None"></label>' ;
window . currentDictionary . partsOfSpeech . forEach ( partOfSpeech => {
partOfSpeech = removeTags ( partOfSpeech ) ;
optionsHTML += ` <option value=" ${ partOfSpeech } "> ${ partOfSpeech } </option> ` ;
searchHTML += ` <label> ${ partOfSpeech } <input type="checkbox" checked id="searchPartOfSpeech_ ${ slugify ( partOfSpeech ) } "></label> ` ;
} ) ;
searchHTML += ` <a class="small button" id="checkAllFilters">Check All</a> <a class="small button" id="uncheckAllFilters">Uncheck All</a> ` ;
Array . from ( document . getElementsByClassName ( 'part-of-speech-select' ) ) . forEach ( select => {
const selectedValue = select . value ;
select . innerHTML = optionsHTML ;
select . value = selectedValue ;
} ) ;
if ( ! onlyOptions ) {
document . getElementById ( 'searchPartsOfSpeech' ) . innerHTML = searchHTML ;
}
setupSearchFilters ( ) ;
}
export function renderWords ( ) {
let wordsHTML = '' ;
let words = false ;
if ( window . currentDictionary . words . length === 0 ) {
wordsHTML = ` <article class="entry">
< header >
< h4 class = "word" > No Words Found < / h 4 >
< / h e a d e r >
< dl >
< dt class = "definition" > Either this dictionary has not yet been started , or something prevented words from downloading . < / d t >
< / d l >
< / a r t i c l e > ` ;
} else {
words = getMatchingSearchWords ( ) ;
if ( words . length === 0 ) {
wordsHTML = ` <article class="entry">
< header >
< h4 class = "word" > No Search Results < / h 4 >
< / h e a d e r >
< dl >
< dt class = "definition" > Edit your search or filter to show words . < / d t >
< / d l >
< / a r t i c l e > ` ;
}
2019-06-04 19:11:58 +02:00
words . forEach ( ( originalWord , displayIndex ) => {
2019-05-25 02:50:31 +02:00
const word = highlightSearchTerm ( {
name : removeTags ( originalWord . name ) ,
pronunciation : removeTags ( originalWord . pronunciation ) ,
partOfSpeech : removeTags ( originalWord . partOfSpeech ) ,
definition : removeTags ( originalWord . definition ) ,
2019-07-07 08:00:32 +02:00
details : originalWord . details ,
2019-05-25 02:50:31 +02:00
wordId : originalWord . wordId ,
} ) ;
2019-06-06 23:41:30 +02:00
const homonymnNumber = getHomonymnNumber ( originalWord ) ;
2019-05-30 22:01:34 +02:00
const shareLink = window . location . pathname + ( window . location . pathname . match ( new RegExp ( word . wordId + '$' ) ) ? '' : '/' + word . wordId ) ;
2019-06-04 19:11:58 +02:00
wordsHTML += renderAd ( displayIndex ) ;
2019-05-25 02:50:31 +02:00
wordsHTML += ` <article class="entry" id=" ${ word . wordId } ">
< header >
2019-07-07 08:00:32 +02:00
< h4 class = "word" > < span class = "orthographic-translation" > $ { word . name } < / s p a n > $ { h o m o n y m n N u m b e r > 0 ? ' < s u b > ' + h o m o n y m n N u m b e r . t o S t r i n g ( ) + ' < / s u b > ' : ' ' } < / h 4 >
2019-05-25 02:50:31 +02:00
< span class = "pronunciation" > $ { word . pronunciation } < / s p a n >
< span class = "part-of-speech" > $ { word . partOfSpeech } < / s p a n >
2019-05-30 22:01:34 +02:00
< a href = "${shareLink}" target = "_blank" class = "small button word-option-button" title = "Link to Word" > & # 10150 ; < / a >
2019-05-25 02:50:31 +02:00
< / h e a d e r >
< dl >
< dt class = "definition" > $ { word . definition } < / d t >
< dd class = "details" >
$ { md ( word . details ) }
< / d d >
< / d l >
< / a r t i c l e > ` ;
} ) ;
}
document . getElementById ( 'entries' ) . innerHTML = wordsHTML ;
// Show Search Results
const searchTerm = getSearchTerm ( ) ;
const filters = getSearchFilters ( ) ;
let resultsText = searchTerm !== '' || ! filters . allPartsOfSpeechChecked ? ( words ? words . length : 0 ) . toString ( ) + ' Results' : '' ;
resultsText += ! filters . allPartsOfSpeechChecked ? ' (Filtered)' : '' ;
document . getElementById ( 'searchResults' ) . innerHTML = resultsText ;
}
export function renderInfoModal ( content ) {
const modalElement = document . createElement ( 'section' ) ;
modalElement . classList . add ( 'modal' , 'info-modal' ) ;
modalElement . innerHTML = ` <div class="modal-background"></div>
< div class = "modal-content" >
< a class = "close-button" > & times ; & # xFE0E ; < / a >
< section class = "info-modal" >
< div class = "content" >
$ { content }
< / d i v >
< / s e c t i o n >
< / d i v > ` ;
document . body . appendChild ( modalElement ) ;
setupInfoModal ( modalElement ) ;
}