initial commit

This commit is contained in:
Oleg Belyaev 2025-03-21 14:14:03 +03:00
parent cee3efab31
commit 71219733bd
31 changed files with 9242 additions and 0 deletions

411
static/abaev-html.css Normal file
View file

@ -0,0 +1,411 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Universal
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Apply styling to all elements (including their `::before` and `::after`
pseudo-elements). One common use of this selector is to apply a custom
`box-sizing`. */
*, *::before, *::after {}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Root
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
:root {}
html {}
body {}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Content sectioning
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
h1, h2, h3, h4, h5, h6 {}
h1 {}
h2 {}
h3 {}
h4 {}
h5 {}
h6 {}
body > header {
position: sticky;
top: 0;
background: white;
border-bottom-width: thin;
border-bottom-style: solid;
padding-bottom: 0px !important;
padding-top: 0px !important;
padding-right: 1em !important;
padding-left: 1em !important;
/* color: #f1f1f1; */
}
nav {}
nav ul, nav ol {}
nav li {}
nav a {}
nav a:visited {}
nav a:hover {}
nav a:active {}
nav#entrylist {
height: 90%;
overflow-x: hidden;
overflow-y: scroll;
padding-left: 10px;
}
main {}
article.abv-entry {
display: grid;
grid-template-columns: minmax(0px,15%) 5% minmax(50%,80%);
align-items: baseline;
}
section {}
aside#leftbar {
/* The side navigation menu */
height: 100%; /* 100% Full-height */
width: 250px; /* 0 width - change this with JavaScript */
display: none;
position: fixed; /* Stay in place */
z-index: 1; /* Stay on top */
top: 0;
left: 0;
overflow-x: hidden; /* Disable horizontal scroll */
overflow-y: hidden;
padding-top: 0px; /* Place content 60px from the top */
background-color: #dcdcdc;
transition: 0.5s; /* 0.5 second transition effect to slide in the sidenav */
}
search {}
body > footer {
position: sticky;
bottom: 0;
background: white;
border-top-width: thin;
border-top-style: solid;
padding-top: 0px !important;
padding-bottom: 0px !important;
/* color: #f1f1f1; */
}
address {}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Text block content
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Overall styling, e.g. vertical spacing */
p, ol, ul, pre, blockquote, figure, hr, dl {}
p {}
ol, ul {}
ol {}
ul {}
li {}
ol ol, ol ul, ul ul, ul ol {}
li li {}
pre {}
pre code {}
pre samp {}
blockquote {}
figure {}
figcaption {}
hr {}
dl {}
dt {}
dd {}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Inline text semantics
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
a {}
a:visited {}
a:hover {}
a:active {}
strong {}
b {}
em {}
i {}
q {
quotes: "" "";
}
cite {}
s {}
mark {}
/* If you specify a font size, consider using the `em` unit so that it works
universally, e.g. for both `h1 small` and `p small` */
small {}
sub {}
sup {}
code {}
dfn {}
abbr {}
abbr[title] {}
var {}
kbd {}
kbd kbd {}
samp {}
u {}
data {}
time {}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Demarcating edits
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
del {}
ins {}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Embedded content
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
img {}
svg {}
video {}
canvas {}
audio {}
object {}
noscript {}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Table content
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
table {}
caption {}
col:first-child {}
thead {}
tbody {}
tfoot {}
tr {}
th {}
td {}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Forms
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
fieldset {}
fieldset:disabled {}
legend {}
form {}
label {}
::placeholder {}
:focus::placeholder {}
/* Overall styling, e.g. vertical spacing */
input, textarea, select, button {}
/* `textarea` and `input` elements that share a similar look and similar styling
capabilities */
/* - common styling */
textarea,
input[type="text"],
input[type="password"],
input[type="email"],
input[type="tel"],
input[type="number"],
input[type="search"],
input[type="url"],
input[type="date"],
input[type="datetime-local"],
input[type="month"],
input[type="week"],
input[type="time"] {}
/* - individual styling */
textarea {}
input[type="text"] {}
input[type="password"] {}
input[type="email"] {}
input[type="tel"] {}
input[type="number"] {}
input[type="search"] {}
input[type="url"] {}
input[type="date"] {}
input[type="datetime-local"] {}
input[type="month"] {}
input[type="week"] {}
input[type="time"] {}
/* Tick boxes */
input[type="checkbox"], input[type="radio"] {}
input[type="checkbox"]:checked, input[type="radio"]:checked {}
input[type="checkbox"] {}
input[type="checkbox"]:checked {}
input[type="radio"] {}
input[type="radio"]:checked {}
/* Other input fields, some with limited styling capabilities */
input[type="file"] {}
input[type="color"] {}
input[type="range"] {}
select {}
div.index {
display: grid;
grid-template-columns: 20% 20% 60%;
align-items: baseline;
}
div.index div {
height: 85vh;
}
div.index div select {
height: 90%;
overflow: scroll;
}
optgroup {}
option {}
option:checked {}
datalist {}
button,
input[type="submit"] {}
button:disabled,
input[type="submit"]:disabled {}
button.secondary {}
button.secondary:disabled {}
button#open-leftbar{
position: fixed;
top: 50vh;
left: 0;
/*height: 1ex;*/
/*line-height: 1ex;*/
/*width: 1em;*/
}
button#close-leftbar{
position: fixed;
top: 50vh;
left: 250px;
display: none;
}
/* This matches forms or form elements that are invalid *and* have been
interacted with. Note that:
1) You may need to add the `interacted` class to forms yourself
2) You may need to add the `touched` class to form fields yourself
3) `:user-invalid` is a working draft and not yet supported by most browsers
4) `:-moz-ui-invalid` is non-standard and only works in Firefox
Form validation error messages will appear (in capable browsers) regardless of
this styling. You can omit 1) and 2) and still have working forms. Perfect
example of progressive enhancement. */
/* Applies to invalid forms */
form.interacted:invalid {}
/* Applies to invalid form fields. You would need to repeat your declarations
for the following three groups of selectors individually. Browsers completely
ignore any rule that contains a selector they do not know. */
form.interacted :invalid, form .touched:invalid {}
:user-invalid {}
:-moz-ui-invalid {}
output {}
progress {}
meter {}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Interactive elements
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
details {}
details[open] {}
summary {}
details[open] summary {}
dialog {}
dialog::backdrop {}
dialog#modal_map > article {
width: 75vw !important;
height: 85vh !important;
max-width: 75vw !important;
max-height: 85vh !important;
}
/* Some form fields, `details`, elements with `tabindex`, and possibly other
elements can be focussed. You should use `:focus-visible` instead of `:focus`
whenever possible. As the former is not yet widely supported, you need to do it
as follows:
1) Set styling on focus
2) If browser supports `:focus-visible`, revert/unset the styling from 1)
3) If the element matches `:focus-visible`, apply the styling again */
:focus {}
:focus:not(:focus-visible) {}
:focus-visible {}
[inert], [inert] * {}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Media queries
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@media (prefers-reduced-motion: reduce) {
}
@media (prefers-color-scheme: dark) {
}
@media (orientation: portrait) {
}
@media (orientation: landscape) {
}
@media print {
}
/* CUSTOM: SPANS */
span.abv-text-ul {
text-decoration-line: underline;
}
span.abv-text-sc {
font-variant-caps: small-caps;
}
/*
This file evolved from Natural Selection:
https://github.com/frontaid/natural-selection
*/

61
static/abaev-index.js Normal file
View file

@ -0,0 +1,61 @@
$( document ).ready(function() {
$('#abv-select-lang').on('input', function() {
let $selected = $(this).children('option:selected');
let url = `../api/languages/${$selected.attr('value')}`;
fetch(url)
.then(res => res.json())
.then(out => {
let $select_word = $('#abv-select-word');
let $select_entry = $('#abv-select-entry');
$select_word.empty();
$select_entry.empty();
for (w of out.words) {
$select_word.append(new Option(w.text,w.id))
}
})
.catch(err => console.log(err));
});
$('#abv-select-word').on('input', function() {
let $selected = $(this).children('option:selected');
let wordid = $selected.attr('value');
let lang = $('#abv-select-lang').children('option:selected').attr('value');
let url = `../api/languages/${lang}/words/${wordid}`;
fetch(url)
.then(res => res.json())
.then(out => {
let $select_entry = $('#abv-select-entry');
$select_entry.empty();
for (e of out.entries) {
url_entry = `../api/entries/${e.id}`;
fetch(url_entry)
.then(res => res.json())
.then(out => {
let entrystring = out.form;
let glosses = [];
for (r of e.refs) {
if (r.glosses) {
for(g of r.glosses){
glosses.push(g);
}
}
}
if(glosses.length > 0) {
entrystring += ` (${glosses.join('; ')})`
}
$select_entry.append(new Option(entrystring,out.xmlid))
})
.catch(err => console.log(err));
}
})
.catch(err => console.log(err));
});
$('#abv-select-entry').on("dblclick", function() {
let $selected = $(this).children('option:selected');
let $entry = $selected.attr('value');
window.location.replace('../dict/' + $entry);
});
});

171
static/abaev.js Normal file
View file

@ -0,0 +1,171 @@
$( document ).ready(function() {
function bindMapOpen() {
// $('#modal_map').data('abv-entry',$(this).data('abv-entry'));
// $('#modal_map')[0].showModal();
let url = `../dict/map-info/${$(this).data('abv-entry')}`;
fetch(url)
.then(res => res.json())
.then(out => {
$('#modal_map').data('map',out);
$('#modal_map')[0].showModal();
})
.catch(err => console.log(err));
}
// Event to open map modal. We have to bind it
// when the button is shown, otherwise it will
// not work for newly loaded entries.
$('.abv-map').on("click", bindMapOpen);
// init Infinite Scroll
$('main').infiniteScroll({
path: '.pagination__next',
append: '.abv-entry',
//status: '.scroller-status',
//hideNav: '.pagination',
});
$('main').on( 'append.infiniteScroll', function( event, body, path, response ) {
$('.abv-map').on("click", bindMapOpen);
});
// If the hash is on the page, scroll a little bit above to account for top nav height
if ( $(decodeURI(document.location.hash)).length > 0) {
window.scrollBy(0,-$('header').height());
}
// If the hash is not on the page, go to the right page by using the ID interface
$( window ).on('hashchange', function() {
const hash = decodeURI(document.location.hash);
if ( hash.startsWith('#entry_') ) {
if ( $(hash).length == 0) {
window.location.replace(document.location.pathname + '/' + document.location.hash.substring(1));
}
else {
window.scrollBy(0,-$('header').height());
}
}
});
// Function to scroll the entry list to the selected entry OR to the first entry displayed on the current page if there is no hash in the URL
function scrollView() {
var $container = $('#entrylist')
if (document.location.hash.length > 0) {
var $scrollTo = $(`#link_${$(decodeURI(document.location.hash)).attr('id')}`);
}
else {
var $scrollTo = $(`#link_${$('article:first').attr('id')}`);
}
$container.scrollTop(
$scrollTo.offset().top - $container.offset().top + $container.scrollTop())
}
// Click to open the offcanvas entry list
$( '#open-leftbar' ).on('click', function() {
// $("#leftbar")[0].style.width = "250px";
$("#leftbar").show();
// $("#leftbar")[0].style.paddingLeft = "10px";
$("main")[0].style.marginLeft = "250px";
$("header")[0].style.marginLeft = "250px";
$("footer")[0].style.marginLeft = "250px";
$("#open-leftbar").hide();
$("#close-leftbar").show();
scrollView();
});
// Click to close the offcanvas entry list
$( '#close-leftbar' ).on('click', function() {
$("#leftbar").hide();
// $("#leftbar")[0].style.paddingLeft = null;
$("main")[0].style.marginLeft = null;
$("header")[0].style.marginLeft = null;
$("footer")[0].style.marginLeft = null;
$("#open-leftbar").show();
$("#close-leftbar").hide();
})
// Quick filter functionality
$('#filter-entries').on("keyup", function () {
var value = $(this).val().toLowerCase();
if (value.length > 1) {
$("#entrylist > ul > li").filter(function () {
return $(this).toggle($(this).children('a').text().toLowerCase().indexOf(value) > -1)
});
}
return false;
});
// Close map modal
$('.abv-close-map').on("click", function () {
$('#modal_map')[0].close();
});
// Load map data when dialog opens
$('#modal_map').on("toggle", function () {
map = document.getElementById('map_display');
var layout = {
// title: {
// text: 'Canadian cities',
// font: {
// family: 'Droid Serif, serif',
// size: 16
// }
// },
geo: {
scope: 'world',
resolution: 50,
fitbounds: 'locations',
showrivers: true,
rivercolor: '#fff',
showlakes: true,
lakecolor: '#fff',
showland: true,
landcolor: '#EAEAAE',
showcountries: false,
subunitcolor: '#d3d3d3'
}
};
Plotly.newPlot(map, [$(this).data('map')], layout);
// var data = [{
// type: 'scattergeo',
// mode: 'markers+text',
// text: [
// 'Montreal', 'Toronto', 'Vancouver', 'Calgary', 'Edmonton',
// 'Ottawa', 'Halifax', 'Victoria', 'Winnepeg', 'Regina'
// ],
// hovertext: 'HIMEM.SYS<br>EGAVGA.BGI',
// hoverinfo: 'text',
// lon: [
// -73.57, -79.24, -123.06, -114.1, -113.28,
// -75.43, -63.57, -123.21, -97.13, -104.6
// ],
// lat: [
// 45.5, 43.4, 49.13, 51.1, 53.34, 45.24,
// 44.64, 48.25, 49.89, 50.45
// ],
// marker: {
// size: 7,
// // color: [
// // '#bebada', '#fdb462', '#fb8072', '#d9d9d9', '#bc80bd',
// // '#b3de69', '#8dd3c7', '#80b1d3', '#fccde5', '#ffffb3'
// // ],
// line: {
// width: 1
// }
// },
// name: 'Canadian cities',
// textposition: [
// 'top right', 'top left', 'top center', 'bottom right', 'top right',
// 'top left', 'bottom right', 'bottom left', 'top right', 'top right'
// ],
// }];
});
});

6
static/chevron-left.svg Normal file
View file

@ -0,0 +1,6 @@
<!-- chevron-left icon by Free Icons (https://free-icons.github.io/free-icons/) -->
<svg xmlns="http://www.w3.org/2000/svg" height="1em" fill="currentColor" viewBox="0 0 512 512">
<path
d="M 126.86725663716814 249.20353982300884 Q 122.33628318584071 256 126.86725663716814 262.79646017699116 L 371.53982300884957 507.46902654867256 L 371.53982300884957 507.46902654867256 Q 378.3362831858407 512 385.13274336283183 507.46902654867256 Q 389.6637168141593 500.6725663716814 385.13274336283183 493.87610619469024 L 146.12389380530973 256 L 146.12389380530973 256 L 385.13274336283183 18.123893805309734 L 385.13274336283183 18.123893805309734 Q 389.6637168141593 11.327433628318584 385.13274336283183 4.530973451327434 Q 378.3362831858407 0 371.53982300884957 4.530973451327434 L 126.86725663716814 249.20353982300884 L 126.86725663716814 249.20353982300884 Z"
/>
</svg>

After

Width:  |  Height:  |  Size: 875 B

6
static/chevron-right.svg Normal file
View file

@ -0,0 +1,6 @@
<!-- chevron-right icon by Free Icons (https://free-icons.github.io/free-icons/) -->
<svg xmlns="http://www.w3.org/2000/svg" height="1em" fill="currentColor" viewBox="0 0 512 512">
<path
d="M 385.13274336283183 249.20353982300884 Q 389.6637168141593 256 385.13274336283183 262.79646017699116 L 140.46017699115043 507.46902654867256 L 140.46017699115043 507.46902654867256 Q 133.6637168141593 512 126.86725663716814 507.46902654867256 Q 122.33628318584071 500.6725663716814 126.86725663716814 493.87610619469024 L 365.87610619469024 256 L 365.87610619469024 256 L 126.86725663716814 18.123893805309734 L 126.86725663716814 18.123893805309734 Q 122.33628318584071 11.327433628318584 126.86725663716814 4.530973451327434 Q 133.6637168141593 0 140.46017699115043 4.530973451327434 L 385.13274336283183 249.20353982300884 L 385.13274336283183 249.20353982300884 Z"
/>
</svg>

After

Width:  |  Height:  |  Size: 877 B

14
static/infinite-scroll.pkgd.min.js vendored Normal file

File diff suppressed because one or more lines are too long

2
static/jquery-3.7.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long

6
static/map.svg Normal file
View file

@ -0,0 +1,6 @@
<!-- map icon by Free Icons (https://free-icons.github.io/free-icons/) -->
<svg xmlns="http://www.w3.org/2000/svg" height="1em" fill="currentColor" viewBox="0 0 512 512">
<path
d="M 160.88888888888889 57.77777777777778 Q 163.55555555555554 56.888888888888886 165.33333333333334 56.888888888888886 L 348.44444444444446 113.77777777777777 L 348.44444444444446 113.77777777777777 L 473.77777777777777 67.55555555555556 L 473.77777777777777 67.55555555555556 Q 488 63.111111111111114 499.55555555555554 71.11111111111111 Q 511.1111111111111 79.11111111111111 512 94.22222222222223 L 512 376 L 512 376 Q 511.1111111111111 395.55555555555554 493.3333333333333 402.6666666666667 L 351.1111111111111 455.1111111111111 L 351.1111111111111 455.1111111111111 Q 348.44444444444446 455.1111111111111 346.6666666666667 455.1111111111111 L 163.55555555555554 398.22222222222223 L 163.55555555555554 398.22222222222223 L 38.22222222222222 444.44444444444446 L 38.22222222222222 444.44444444444446 Q 24 448.8888888888889 12.444444444444445 440.8888888888889 Q 0.8888888888888888 432.8888888888889 0 417.77777777777777 L 0 136 L 0 136 Q 0.8888888888888888 116.44444444444444 18.666666666666668 109.33333333333333 L 160.88888888888889 57.77777777777778 L 160.88888888888889 57.77777777777778 Z M 24 122.66666666666667 Q 15.11111111111111 126.22222222222223 14.222222222222221 136 L 14.222222222222221 417.77777777777777 L 14.222222222222221 417.77777777777777 Q 14.222222222222221 424.8888888888889 20.444444444444443 429.3333333333333 Q 25.77777777777778 432.8888888888889 33.77777777777778 431.1111111111111 L 156.44444444444446 385.77777777777777 L 156.44444444444446 385.77777777777777 L 156.44444444444446 73.77777777777777 L 156.44444444444446 73.77777777777777 L 24 122.66666666666667 L 24 122.66666666666667 Z M 341.3333333333333 438.22222222222223 L 341.3333333333333 126.22222222222223 L 341.3333333333333 438.22222222222223 L 341.3333333333333 126.22222222222223 L 170.66666666666666 73.77777777777777 L 170.66666666666666 73.77777777777777 L 170.66666666666666 385.77777777777777 L 170.66666666666666 385.77777777777777 L 341.3333333333333 438.22222222222223 L 341.3333333333333 438.22222222222223 Z M 355.55555555555554 438.22222222222223 L 488.8888888888889 389.3333333333333 L 355.55555555555554 438.22222222222223 L 488.8888888888889 389.3333333333333 Q 496.8888888888889 385.77777777777777 497.77777777777777 376 L 497.77777777777777 94.22222222222223 L 497.77777777777777 94.22222222222223 Q 497.77777777777777 87.11111111111111 491.55555555555554 82.66666666666667 Q 486.22222222222223 79.11111111111111 479.1111111111111 80.88888888888889 L 355.55555555555554 126.22222222222223 L 355.55555555555554 126.22222222222223 L 355.55555555555554 438.22222222222223 L 355.55555555555554 438.22222222222223 Z"
/>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

3879
static/plotly-3.0.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long