676 lines
19 KiB
JavaScript
676 lines
19 KiB
JavaScript
console.log('JavaScript se izvaja...');
|
|
|
|
// DOM elementi
|
|
const songNumberInput = document.getElementById('song-number');
|
|
const loadBtn = document.getElementById('load-btn');
|
|
const displayArea = document.getElementById('display-area');
|
|
const prevBtn = document.getElementById('prev-btn');
|
|
const nextBtn = document.getElementById('next-btn');
|
|
const darkBtn = document.getElementById('dark-btn');
|
|
const splitBtn = document.getElementById('split-btn');
|
|
const pageInfo = document.getElementById('page-info');
|
|
const clearBtn = document.getElementById('clear-btn');
|
|
const aboutBtn = document.getElementById('about-btn');
|
|
const aboutModal = document.getElementById('about-modal');
|
|
const aboutCloseBtn = document.getElementById('about-close-btn');
|
|
const keypadButtons = document.querySelectorAll('.btn-key');
|
|
const keypadWrapper = document.getElementById('keypad-wrapper');
|
|
const toggleKeypadBtn = document.getElementById('toggle-keypad-btn');
|
|
const menuToggle = document.getElementById('menu-toggle');
|
|
const menuDropdown = document.getElementById('menu-dropdown');
|
|
const searchInput = document.getElementById('search-input');
|
|
const searchResults = document.getElementById('search-results');
|
|
const editSongBtn = document.getElementById('edit-song-btn');
|
|
const editModal = document.getElementById('edit-modal');
|
|
const editTitleInput = document.getElementById('edit-title');
|
|
const editLyricsInput = document.getElementById('edit-lyrics');
|
|
const saveEditBtn = document.getElementById('save-edit-btn');
|
|
const cancelEditBtn = document.getElementById('cancel-edit-btn');
|
|
const editSongNumberDisplay = document.getElementById('edit-song-number-display');
|
|
|
|
// Prompt Modal elementi
|
|
const promptModal = document.getElementById('prompt-modal');
|
|
const promptInput = document.getElementById('prompt-input');
|
|
const promptEditBtn = document.getElementById('prompt-edit-btn');
|
|
const promptCancelBtn = document.getElementById('prompt-cancel-btn');
|
|
const promptNewBtn = document.getElementById('prompt-new-btn');
|
|
|
|
// Info Modal elementi
|
|
const infoModal = document.getElementById('info-modal');
|
|
const infoMessage = document.getElementById('info-message');
|
|
const infoOkBtn = document.getElementById('info-ok-btn');
|
|
|
|
let capsMode = false;
|
|
let splitByStanza = false;
|
|
let wakeLock = null;
|
|
let lastStateSignature = "";
|
|
let lastPageInfo = "";
|
|
|
|
// vibracija telefona
|
|
function vibrate() {
|
|
if (navigator.vibrate && /Android|iPhone|iPad|iPod/i.test(navigator.userAgent)) {
|
|
navigator.vibrate([25, 30, 25]);
|
|
}
|
|
}
|
|
|
|
// poskus, da se zaslon ne ugaša
|
|
async function requestWakeLock() {
|
|
try {
|
|
if ('wakeLock' in navigator) {
|
|
wakeLock = await navigator.wakeLock.request('screen');
|
|
console.log('Wake lock aktiviran');
|
|
|
|
wakeLock.addEventListener('release', () => {
|
|
console.log('Wake lock sproščen');
|
|
});
|
|
}
|
|
} catch (err) {
|
|
console.log('Wake lock ni uspel:', err);
|
|
}
|
|
}
|
|
|
|
// ob vrnitvi v zavihek ponovno zahtevaj wake lock
|
|
document.addEventListener('visibilitychange', async () => {
|
|
if (document.visibilityState === 'visible') {
|
|
await requestWakeLock();
|
|
}
|
|
});
|
|
|
|
// posodobi stanje
|
|
async function updateState(force = false) {
|
|
try {
|
|
const response = await fetch('/api/state', { cache: 'no-store' });
|
|
const data = await response.json();
|
|
|
|
const signature = JSON.stringify({
|
|
current_text: data.current_text || '',
|
|
page_info: data.page_info || '',
|
|
caps_mode: data.caps_mode || false,
|
|
split_by_stanza: data.split_by_stanza || false,
|
|
can_prev: !!data.can_prev
|
|
});
|
|
|
|
if (!force && signature === lastStateSignature) {
|
|
return;
|
|
}
|
|
|
|
lastStateSignature = signature;
|
|
|
|
displayArea.textContent = data.current_text || 'Pripravljeno. Vpiši številko pesmi ali drugega besedila.';
|
|
lastPageInfo = data.page_info || '';
|
|
updatePageInfoDisplay();
|
|
|
|
capsMode = data.caps_mode || false;
|
|
|
|
if (capsMode) {
|
|
darkBtn.classList.add('active');
|
|
} else {
|
|
darkBtn.classList.remove('active');
|
|
}
|
|
|
|
splitByStanza = data.split_by_stanza || false;
|
|
if (splitByStanza) {
|
|
splitBtn.classList.add('active');
|
|
} else {
|
|
splitBtn.classList.remove('active');
|
|
}
|
|
|
|
prevBtn.disabled = !data.can_prev;
|
|
} catch (error) {
|
|
console.error('Napaka pri posodabljanju stanja:', error);
|
|
displayArea.innerHTML = '<span class="status-message">Napaka: ni povezave do strežnika</span>';
|
|
}
|
|
}
|
|
|
|
// Posodobi prikaz v page-info (vključno z vnosom številke)
|
|
function updatePageInfoDisplay() {
|
|
const songNumber = songNumberInput.value;
|
|
if (songNumber) {
|
|
pageInfo.textContent = 'Vnos: ' + songNumber;
|
|
pageInfo.classList.add('input-active');
|
|
} else {
|
|
pageInfo.textContent = lastPageInfo;
|
|
pageInfo.classList.remove('input-active');
|
|
}
|
|
}
|
|
|
|
// dodaj številko
|
|
function addDigit(digit) {
|
|
songNumberInput.value += digit;
|
|
updatePageInfoDisplay();
|
|
}
|
|
|
|
// počisti vnos
|
|
function clearInput() {
|
|
songNumberInput.value = '';
|
|
updatePageInfoDisplay();
|
|
}
|
|
|
|
// Enter:
|
|
// - če je številka -> naloži pesem
|
|
// - če ni številke -> naslednja kitica
|
|
async function loadSong() {
|
|
const songNumber = songNumberInput.value.trim();
|
|
|
|
try {
|
|
if (songNumber) {
|
|
await fetch('/api/load_song', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ song_number: songNumber })
|
|
});
|
|
|
|
songNumberInput.value = '';
|
|
updatePageInfoDisplay();
|
|
} else {
|
|
await fetch('/api/next_page', { method: 'POST' });
|
|
}
|
|
|
|
await updateState(true);
|
|
} catch (error) {
|
|
console.error('Napaka:', error);
|
|
displayArea.innerHTML = '<span class="status-message">Napaka: ni povezave do strežnika</span>';
|
|
}
|
|
}
|
|
|
|
// Iskanje besedil po naslovu
|
|
async function searchSongs() {
|
|
const query = searchInput.value.trim();
|
|
if (!query) {
|
|
searchResults.innerHTML = '';
|
|
searchResults.classList.remove('show');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await fetch('/api/search_songs', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ query: query })
|
|
});
|
|
const data = await response.json();
|
|
|
|
if (data.results && data.results.length > 0) {
|
|
searchResults.innerHTML = '';
|
|
data.results.forEach(song => {
|
|
const item = document.createElement('div');
|
|
item.className = 'search-item';
|
|
item.innerHTML = `
|
|
<span class="song-id">${song[0]}</span>
|
|
<span class="song-title">${song[1]}</span>
|
|
`;
|
|
item.addEventListener('click', () => {
|
|
songNumberInput.value = song[0];
|
|
updatePageInfoDisplay();
|
|
loadSong();
|
|
searchInput.value = '';
|
|
searchResults.innerHTML = '';
|
|
searchResults.classList.remove('show');
|
|
});
|
|
searchResults.appendChild(item);
|
|
});
|
|
searchResults.classList.add('show');
|
|
} else {
|
|
searchResults.innerHTML = '<div class="search-item"><span class="song-title">Ni zadetkov</span></div>';
|
|
searchResults.classList.add('show');
|
|
}
|
|
} catch (error) {
|
|
console.error('Napaka pri iskanju:', error);
|
|
}
|
|
}
|
|
|
|
// prejšnja kitica
|
|
async function prevPage() {
|
|
try {
|
|
await fetch('/api/prev_page', { method: 'POST' });
|
|
await updateState(true);
|
|
} catch (error) {
|
|
console.error('Napaka pri navigaciji:', error);
|
|
}
|
|
}
|
|
|
|
// Zatemnitev ekrana
|
|
async function clearScreen() {
|
|
try {
|
|
await fetch('/api/clear_screen', {method: 'POST'});
|
|
await updateState(true);
|
|
} catch (error) {
|
|
console.error('Napaka pri zatamnitvi ekrana:', error);
|
|
displayArea.innerHTML = '<span class="status-message">Napaka: ni povezave do strežnika</span>';
|
|
}
|
|
}
|
|
|
|
// Preklop VELIKIH ČRK
|
|
async function toggleCaps() {
|
|
try {
|
|
await fetch('/api/toggle_caps', { method: 'POST' });
|
|
await updateState(true);
|
|
} catch (error) {
|
|
console.error('Napaka pri preklopu velikih črk:', error);
|
|
}
|
|
}
|
|
|
|
// Preklop načina preloma po kiticah
|
|
async function toggleSplit() {
|
|
try {
|
|
await fetch('/api/toggle_split', { method: 'POST' });
|
|
await updateState(true);
|
|
} catch (error) {
|
|
console.error('Napaka pri preklopu načina preloma:', error);
|
|
}
|
|
}
|
|
|
|
// Odpri urejevalnik
|
|
async function openEditor(songId = null) {
|
|
try {
|
|
if (songId === 'new') {
|
|
editTitleInput.value = '';
|
|
editLyricsInput.value = '';
|
|
editModal.dataset.songId = 'new';
|
|
editSongNumberDisplay.textContent = '';
|
|
editModal.style.display = 'block';
|
|
menuDropdown.classList.remove('show');
|
|
return;
|
|
}
|
|
|
|
const url = songId ? `/api/get_song_details?id=${songId}` : '/api/get_song_details';
|
|
const response = await fetch(url);
|
|
const data = await response.json();
|
|
|
|
if (data.status === 'ok') {
|
|
editTitleInput.value = data.song.title;
|
|
editLyricsInput.value = data.song.lyrics;
|
|
editModal.dataset.songId = data.song.id;
|
|
editSongNumberDisplay.textContent = data.song.id;
|
|
editModal.style.display = 'block';
|
|
menuDropdown.classList.remove('show');
|
|
} else {
|
|
if (!songId) {
|
|
// Če ni naložene pesmi, pokaži prompt
|
|
promptModal.style.display = 'block';
|
|
promptInput.value = '';
|
|
menuDropdown.classList.remove('show');
|
|
} else {
|
|
alert(data.message || 'Napaka pri pridobivanju podatkov.');
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Napaka pri pridobivanju podatkov:', error);
|
|
alert('Napaka pri povezavi s strežnikom.');
|
|
}
|
|
}
|
|
|
|
function showInfo(message) {
|
|
infoMessage.textContent = message;
|
|
infoModal.style.display = 'block';
|
|
}
|
|
|
|
// Zapri urejevalnik
|
|
function closeEditor() {
|
|
editModal.style.display = 'none';
|
|
}
|
|
|
|
// Shrani spremembe
|
|
async function saveSongEdit() {
|
|
const songId = editModal.dataset.songId;
|
|
const title = editTitleInput.value.trim();
|
|
const lyrics = editLyricsInput.value.trim();
|
|
|
|
if (!title || !lyrics) {
|
|
alert('Naslov in besedilo ne smeta biti prazna.');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await fetch('/api/update_song', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
id: songId,
|
|
title: title,
|
|
lyrics: lyrics
|
|
})
|
|
});
|
|
const data = await response.json();
|
|
|
|
if (data.status === 'ok') {
|
|
closeEditor();
|
|
if (data.new_id) {
|
|
showInfo(`Nova pesem je bila shranjena pod številko: ${data.new_id}`);
|
|
}
|
|
await updateState(true);
|
|
} else {
|
|
alert('Napaka pri shranjevanju: ' + data.message);
|
|
}
|
|
} catch (error) {
|
|
console.error('Napaka pri shranjevanju besedila:', error);
|
|
alert('Napaka pri povezavi s strežnikom.');
|
|
}
|
|
}
|
|
|
|
// Odpri About dialog
|
|
async function openAbout() {
|
|
try {
|
|
const response = await fetch('/api/app_info');
|
|
const data = await response.json();
|
|
|
|
if (data.error) {
|
|
alert('Napaka pri pridobivanju informacij o programu.');
|
|
return;
|
|
}
|
|
|
|
document.getElementById('about-name').textContent = data.name;
|
|
document.getElementById('about-version').textContent = 'Verzija ' + data.version;
|
|
document.getElementById('about-description').textContent = data.description;
|
|
|
|
// Dodaj število pesmi
|
|
if (data.song_count !== undefined) {
|
|
document.getElementById('about-description').innerHTML += `<br><br>Število pesmi v bazi: <strong>${data.song_count}</strong>`;
|
|
}
|
|
|
|
const authorsList = document.getElementById('about-authors');
|
|
authorsList.innerHTML = '';
|
|
data.authors.forEach(author => {
|
|
const li = document.createElement('li');
|
|
li.textContent = author;
|
|
authorsList.appendChild(li);
|
|
});
|
|
|
|
aboutModal.classList.add('show');
|
|
menuDropdown.classList.remove('show');
|
|
} catch (error) {
|
|
console.error('Napaka pri pridobivanju informacij o programu:', error);
|
|
}
|
|
}
|
|
|
|
// skrij/pokaži tipkovnico
|
|
function toggleKeypad() {
|
|
if (!keypadWrapper || !toggleKeypadBtn) return;
|
|
|
|
keypadWrapper.classList.toggle('hidden');
|
|
|
|
if (keypadWrapper.classList.contains('hidden')) {
|
|
toggleKeypadBtn.textContent = 'Pokaži tipkovnico';
|
|
} else {
|
|
toggleKeypadBtn.textContent = 'Skrij tipkovnico';
|
|
}
|
|
}
|
|
|
|
// ============================
|
|
// EVENT LISTENERJI
|
|
// ============================
|
|
|
|
// številke na zaslonu
|
|
keypadButtons.forEach(btn => {
|
|
btn.addEventListener('click', () => {
|
|
vibrate();
|
|
const key = btn.dataset.key;
|
|
if (key !== undefined) {
|
|
addDigit(key);
|
|
}
|
|
});
|
|
});
|
|
|
|
// Enter
|
|
loadBtn.addEventListener('click', () => {
|
|
vibrate();
|
|
loadSong();
|
|
});
|
|
|
|
// C
|
|
clearBtn.addEventListener('click', () => {
|
|
vibrate();
|
|
clearInput();
|
|
});
|
|
|
|
// Nazaj
|
|
prevBtn.addEventListener('click', () => {
|
|
vibrate();
|
|
prevPage();
|
|
});
|
|
|
|
// Zastri
|
|
nextBtn.addEventListener('click', () => {
|
|
vibrate();
|
|
clearScreen();
|
|
});
|
|
|
|
// AAaa
|
|
darkBtn.addEventListener('click', () => {
|
|
vibrate();
|
|
toggleCaps();
|
|
});
|
|
|
|
// Prelom po kiticah
|
|
if (splitBtn) {
|
|
splitBtn.addEventListener('click', () => {
|
|
vibrate();
|
|
toggleSplit();
|
|
});
|
|
}
|
|
|
|
// Skrij/Pokaži tipkovnico
|
|
if (toggleKeypadBtn) {
|
|
toggleKeypadBtn.addEventListener('click', (e) => {
|
|
toggleKeypad();
|
|
menuDropdown.classList.remove('show');
|
|
});
|
|
}
|
|
|
|
// O programu
|
|
if (aboutBtn) {
|
|
aboutBtn.addEventListener('click', () => {
|
|
vibrate();
|
|
openAbout();
|
|
});
|
|
}
|
|
|
|
if (aboutCloseBtn) {
|
|
aboutCloseBtn.addEventListener('click', () => {
|
|
aboutModal.classList.remove('show');
|
|
});
|
|
}
|
|
|
|
// Uredi besedilo
|
|
if (editSongBtn) {
|
|
editSongBtn.addEventListener('click', () => {
|
|
vibrate();
|
|
openEditor();
|
|
});
|
|
}
|
|
|
|
// Prekliči urejanje
|
|
if (cancelEditBtn) {
|
|
cancelEditBtn.addEventListener('click', () => {
|
|
vibrate();
|
|
closeEditor();
|
|
});
|
|
}
|
|
|
|
// Posodobi (Shrani) urejanje
|
|
if (saveEditBtn) {
|
|
saveEditBtn.addEventListener('click', () => {
|
|
vibrate();
|
|
saveSongEdit();
|
|
});
|
|
}
|
|
|
|
// Prompt Modal dogodki
|
|
if (promptEditBtn) {
|
|
promptEditBtn.addEventListener('click', () => {
|
|
const id = promptInput.value.trim();
|
|
if (id) {
|
|
promptModal.style.display = 'none';
|
|
openEditor(id);
|
|
} else {
|
|
alert('Vnesite številko pesmi.');
|
|
}
|
|
});
|
|
}
|
|
|
|
if (promptCancelBtn) {
|
|
promptCancelBtn.addEventListener('click', () => {
|
|
promptModal.style.display = 'none';
|
|
});
|
|
}
|
|
|
|
if (promptNewBtn) {
|
|
promptNewBtn.addEventListener('click', () => {
|
|
promptModal.style.display = 'none';
|
|
openEditor('new');
|
|
});
|
|
}
|
|
|
|
// Info Modal dogodki
|
|
if (infoOkBtn) {
|
|
infoOkBtn.addEventListener('click', () => {
|
|
infoModal.style.display = 'none';
|
|
});
|
|
}
|
|
|
|
// Hamburger menu toggle
|
|
if (menuToggle) {
|
|
menuToggle.addEventListener('click', (e) => {
|
|
e.stopPropagation();
|
|
menuDropdown.classList.toggle('show');
|
|
});
|
|
}
|
|
|
|
// Zapri menu ob kliku drugam
|
|
document.addEventListener('click', (e) => {
|
|
if (menuDropdown && !menuDropdown.contains(e.target) && e.target !== menuToggle) {
|
|
menuDropdown.classList.remove('show');
|
|
}
|
|
// Zapri About modal ob kliku izven vsebine
|
|
if (e.target === aboutModal) {
|
|
aboutModal.classList.remove('show');
|
|
}
|
|
});
|
|
|
|
// Iskanje dogodki
|
|
if (searchInput) {
|
|
searchInput.addEventListener('input', () => {
|
|
searchSongs();
|
|
});
|
|
|
|
searchInput.addEventListener('focus', () => {
|
|
if (searchInput.value.trim()) {
|
|
searchResults.classList.add('show');
|
|
}
|
|
});
|
|
}
|
|
|
|
// Zapri rezultate iskanja ob kliku drugam
|
|
document.addEventListener('click', (e) => {
|
|
if (searchResults && !searchResults.contains(e.target) && e.target !== searchInput) {
|
|
searchResults.classList.remove('show');
|
|
}
|
|
});
|
|
|
|
// fizična tipkovnica
|
|
document.addEventListener('keydown', (e) => {
|
|
// Če smo v iskalnem polju, ne procesiraj bližnjic za numerično tipkovnico
|
|
if (document.activeElement === searchInput) {
|
|
if (e.key === 'Escape') {
|
|
searchInput.blur();
|
|
searchResults.classList.remove('show');
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Če smo v urejevalniku, ne procesiraj bližnjic za numerično tipkovnico
|
|
if (editModal && editModal.style.display === 'block') {
|
|
if (e.key === 'Escape') {
|
|
closeEditor();
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Če smo v promptu za številko, ne procesiraj bližnjic za numerično tipkovnico
|
|
if (promptModal && promptModal.style.display === 'block') {
|
|
if (e.key === 'Escape') {
|
|
promptModal.style.display = 'none';
|
|
}
|
|
return;
|
|
}
|
|
|
|
// na telefonu ni potrebe; na velikih ekranih pa naj dela
|
|
if (window.innerWidth < 901) return;
|
|
|
|
// da ne ponavlja pri držanju tipke
|
|
if (e.repeat) return;
|
|
|
|
// številke
|
|
if (e.key >= '0' && e.key <= '9') {
|
|
e.preventDefault();
|
|
addDigit(e.key);
|
|
return;
|
|
}
|
|
|
|
// Enter
|
|
if (e.key === 'Enter' || e.code === 'NumpadEnter') {
|
|
e.preventDefault();
|
|
loadSong();
|
|
return;
|
|
}
|
|
|
|
// C
|
|
if (e.key === 'Backspace' || e.key === 'Delete') {
|
|
e.preventDefault();
|
|
clearInput();
|
|
return;
|
|
}
|
|
|
|
// Zastri
|
|
if (e.key === '+' || e.code === 'NumpadAdd') {
|
|
e.preventDefault();
|
|
clearScreen();
|
|
return;
|
|
}
|
|
|
|
// Nazaj
|
|
if (e.key === '-' || e.code === 'NumpadSubtract') {
|
|
e.preventDefault();
|
|
prevPage();
|
|
return;
|
|
}
|
|
|
|
// preklopi prelom
|
|
if (e.key === '*' || e.code === 'NumpadMultiply') {
|
|
e.preventDefault();
|
|
toggleSplit();
|
|
return;
|
|
}
|
|
|
|
// numpad številke
|
|
if (e.code.startsWith('Numpad') && /\d/.test(e.key)) {
|
|
e.preventDefault();
|
|
addDigit(e.key);
|
|
}
|
|
});
|
|
|
|
// začetno stanje
|
|
updateState(true);
|
|
requestWakeLock();
|
|
|
|
// SSE osveževanje za sinhronizacijo med več napravami
|
|
function setupSSE() {
|
|
const evtSource = new EventSource("/api/events");
|
|
|
|
evtSource.onmessage = function(event) {
|
|
console.log("SSE dogodek:", event.data);
|
|
if (event.data === "refresh content") {
|
|
updateState(false);
|
|
}
|
|
};
|
|
|
|
evtSource.onerror = function(err) {
|
|
console.error("SSE napaka, ponovni poskus čez 5s...", err);
|
|
evtSource.close();
|
|
setTimeout(setupSSE, 5000);
|
|
};
|
|
}
|
|
|
|
setupSSE();
|
|
|
|
console.log('JavaScript inicializacija zaključena'); |