inflectived/static/index.js

260 lines
8.0 KiB
JavaScript
Raw Normal View History

2021-12-26 12:46:40 -05:00
$(document).ready(() => {
2022-01-22 22:24:23 -05:00
let selectedLang = null;
let schema = null;
let langs = null;
2021-12-25 17:30:14 -05:00
2021-12-26 12:46:40 -05:00
$.ajax({
2022-01-22 22:24:23 -05:00
url: `/langs?installed`,
2021-12-26 12:46:40 -05:00
success: data => {
2022-01-22 22:24:23 -05:00
langs = data;
2022-01-23 08:37:38 -05:00
const selectedLangCode = localStorage.selectedLangCode;
2022-01-22 22:24:23 -05:00
2022-01-23 08:37:38 -05:00
let options = '';
langs.forEach(lang => {
if(selectedLangCode && lang.code == selectedLangCode) {
options += `<option value="${lang.code}" selected>${lang.name}</option>`;
} else {
options += `<option value="${lang.code}">${lang.name}</option>`;
}
});
$('#langs').html(options);
2022-01-22 22:24:23 -05:00
setLang($('#langs').val());
2021-12-26 12:46:40 -05:00
}
});
2021-12-25 17:30:14 -05:00
2022-01-23 08:37:38 -05:00
$('#langs').on('change', e => {
setLang(e.target.value);
2022-01-22 22:24:23 -05:00
});
function setLang(code) {
2022-01-23 08:37:38 -05:00
const lang = langs.find(lang => lang.code == code);
2022-01-22 22:24:23 -05:00
2022-01-23 08:37:38 -05:00
localStorage.selectedLangCode = code;
2022-01-22 22:24:23 -05:00
selectedLang = lang;
$.ajax({
url: `/static/schemas/${lang.name}.json`,
success: data => {
polishSchemas = data
if(window.location.hash) {
getWord();
}
}
});
}
2022-01-22 19:58:36 -05:00
const searchBar = $('#search-bar');
const searchForm = $('#search-form');
const ajaxContent = $('#ajax-content');
2021-12-26 12:46:40 -05:00
window.onhashchange = () => {
getWord();
};
2021-12-25 17:30:14 -05:00
2021-12-26 12:46:40 -05:00
searchBar.autocomplete({
2021-12-26 16:33:04 -05:00
appendTo: '#search-form',
2021-12-26 12:46:40 -05:00
source: (request, response) => {
$.ajax({
2022-07-23 08:25:06 -04:00
url: `/langs/${selectedLang.code}/words?like=${request.term.trim()}&limit=20&offset=0`,
2021-12-26 12:46:40 -05:00
success: data => response(data)
})
2021-12-26 15:41:55 -05:00
},
select: (_, ui) => window.location.hash = ui.item.value
2021-12-26 12:46:40 -05:00
});
2021-12-26 11:48:02 -05:00
2021-12-26 13:32:09 -05:00
searchBar.on('focus', e => {
2021-12-26 12:46:40 -05:00
setTimeout(() => e.currentTarget.select(), 100);
});
2021-12-25 17:30:14 -05:00
2022-01-22 19:58:36 -05:00
searchForm.on('submit', e => {
2021-12-26 12:46:40 -05:00
e.preventDefault();
2021-12-25 17:30:14 -05:00
2022-07-23 07:11:10 -04:00
const word = e.target[0].value.trim();
2021-12-25 17:30:14 -05:00
2021-12-26 12:46:40 -05:00
window.location.hash = `#${word}`;
2021-12-25 17:30:14 -05:00
});
2021-12-26 12:46:40 -05:00
function getWord() {
2022-01-23 08:37:38 -05:00
const word = window.location.hash.replace('#', '');
2021-12-26 15:41:55 -05:00
2022-01-12 06:04:19 -05:00
if (word) {
2022-07-23 08:25:06 -04:00
const decodedWord = decodeURIComponent(word);
document.title = `Inflective - ${decodedWord}`;
2022-01-12 06:04:19 -05:00
$.ajax({
2022-01-22 22:24:23 -05:00
url: `/langs/${selectedLang.code}/words/${word}`,
2022-01-12 06:04:19 -05:00
success: (data) => {
2022-01-22 19:58:36 -05:00
ajaxContent.html(generateHtml(word, data));
2022-01-12 06:04:19 -05:00
},
error: err => console.error(err)
})
window.scrollTo(0, 0);
2022-07-23 08:25:06 -04:00
searchBar.val(decodedWord);
2022-01-12 06:04:19 -05:00
searchBar.select();
searchBar.autocomplete('close');
// Sometimes autocomplete opens after close was called
// A better fix should be made
setTimeout(() => searchBar.autocomplete('close'), 1000);
} else {
2022-01-22 19:58:36 -05:00
ajaxContent.html('');
2022-01-12 06:04:19 -05:00
}
2021-12-26 12:46:40 -05:00
}
function getCells(forms, tags) {
if(tags.length === 0)
return undefined;
2021-12-25 17:30:14 -05:00
2021-12-26 12:46:40 -05:00
let cells = forms.filter(form =>
tags.every(value => form.tags.includes(value))
);
2021-12-25 17:30:14 -05:00
2021-12-26 12:46:40 -05:00
cells.forEach(cell =>
cell.used = true
2021-12-25 22:03:45 -05:00
);
2021-12-26 12:46:40 -05:00
if(cells.length === 0)
return undefined;
return cells;
2021-12-25 22:03:45 -05:00
}
2021-12-26 12:46:40 -05:00
function generateList(data) {
let html = '<ul>';
data.forEach(cell =>
html += `<li><strong>${cell.form}</strong> - ${cell.tags.join(', ')}</li>`
);
html += '</ul>';
return html;
2021-12-25 17:30:14 -05:00
}
2021-12-26 12:46:40 -05:00
function generateTable(schemas, pos, forms) {
let schema = schemas.find(schema => schema.pos.includes(pos));
// No schema was provided by the server - fallback to a list
if(!schema)
return generateList(forms);
2021-12-26 11:11:21 -05:00
2021-12-26 12:46:40 -05:00
let html = '<div class="table-responsive">';
html += '<table class="table table-sm table-bordered border-dark text-center align-middle">';
schema.rows.forEach(row => {
html += '<tr>';
row.forEach(cell => {
if('display' in cell) {
html += `<th class="table-light border-dark" colspan="${cell.colspan}" rowspan="${cell.rowspan}">${cell.display}</th>`;
} else {
let cells = getCells(forms, cell.tags);
let content = cells ? cells.map(cell => cell.form).join(', <br>') : '-';
html += `<td colspan="${cell.colspan}" rowspan="${cell.rowspan}">${content}</td>`;
2021-12-26 09:47:57 -05:00
}
2021-12-26 12:46:40 -05:00
});
html += '</tr>';
});
2021-12-25 17:30:14 -05:00
2021-12-26 12:46:40 -05:00
html += '</table>';
html += '</div>';
2021-12-25 17:30:14 -05:00
2021-12-26 12:46:40 -05:00
let unusedCells = forms.filter(cell => !cell.used);
2021-12-25 17:30:14 -05:00
2021-12-26 12:46:40 -05:00
if(schema.ignoreUnused) {
unusedCells = unusedCells.filter(cell =>
!schema.ignoreUnused.map(tags => tags.every(tag => cell.tags.includes(tag)))
);
}
if(unusedCells.length > 0) {
html += '<h3>Other</h3>';
html += generateList(unusedCells);
}
return html;
}
function generateHtml(word, data) {
let html = '';
if(data.length === 0) {
2021-12-31 14:28:46 -05:00
html += `<h1>Not found: <mark>${decodeURIComponent(word)}</mark></h1>`;
2021-12-26 12:46:40 -05:00
} else {
data.forEach(entry => {
2023-03-16 03:58:12 -04:00
html += `<h1>${entry.word} <span class="pos">(${entry.pos})</span></h1>`
if('sounds' in entry) {
html += `<p>${entry.sounds.map(sound => sound.ipa).join(', ')}</p>`;
}
2021-12-26 12:46:40 -05:00
if('senses' in entry) {
let tags = [];
entry.senses.forEach(sense => {
if('tags' in sense) {
tags.push(...sense.tags);
}
});
if(tags.length > 0) {
tags = [...new Set(tags)];
html += '<div class="tags">Tags: '
html += tags.map(tag => `<mark>${tag}</mark>`).join(', ')
html += '</div>'
2021-12-26 09:47:57 -05:00
}
2021-12-25 17:30:14 -05:00
2021-12-26 12:46:40 -05:00
html += '<h2>Senses</h2>';
2021-12-25 17:30:14 -05:00
2021-12-26 12:46:40 -05:00
html += '<ol>';
entry.senses.forEach(sense => {
html += '<li>'
2021-12-25 17:30:14 -05:00
2021-12-26 12:46:40 -05:00
if('form_of' in sense) {
let word = sense.form_of[0].word;
2022-01-09 09:00:59 -05:00
html += sense.glosses[0].replace(new RegExp(`of ${word}.?$`), '');
2021-12-26 12:46:40 -05:00
html += ` of <a href="#${word}" class="link-primary">${word}</a>`;
} else {
2021-12-26 14:38:49 -05:00
let link = ' of <a href="#$1" class="link-primary">$1</a>';
html += sense.glosses[0].replace(/of\s+([\u00BF-\u1FFF\u2C00-\uD7FF\w]+)\s*$/, link);
2021-12-26 12:46:40 -05:00
}
2021-12-25 17:30:14 -05:00
2021-12-30 11:50:39 -05:00
if('tags' in sense) {
html += ' - '
html += sense.tags.map(tag => `<mark>${tag}</mark>`).join(', ')
}
2021-12-26 12:46:40 -05:00
html += '</li>';
})
html += '</ol>';
}
if('forms' in entry) {
if(entry.pos === 'verb') {
let conjugation = entry.forms.filter(form =>
2023-03-16 03:58:12 -04:00
'source' in form && form.source === 'conjugation');
2021-12-26 12:46:40 -05:00
if(conjugation.length > 0) {
html += '<h2>Conjugation</h2>';
html += generateTable(polishSchemas, entry.pos, conjugation);
}
} else {
let declension = entry.forms.filter(form =>
2023-03-16 03:58:12 -04:00
'source' in form && form.source === 'declension');
2021-12-25 17:30:14 -05:00
2021-12-26 12:46:40 -05:00
if(declension.length > 0) {
html += '<h2>Declension</h2>';
2021-12-25 17:30:14 -05:00
2021-12-26 12:46:40 -05:00
html += generateTable(polishSchemas, entry.pos, declension);
}
2021-12-26 09:47:57 -05:00
}
2021-12-25 17:30:14 -05:00
}
2021-12-26 12:46:40 -05:00
});
}
2021-12-26 09:47:57 -05:00
2021-12-26 12:46:40 -05:00
return html;
}
2021-12-26 09:47:57 -05:00
});