// Get the link element var md = null; var references = {}; var tabs = []; let saved = false; let textDirty = false; let saveTimeout = 10000; document.addEventListener('keyup', function (event) { if (event.key == "F3") { openRef(false); } }); document.querySelector('#notes').addEventListener('keyup', function (event) { let key = event.keyCode; if (key >= 48 && key <= 90 || key >= 96 && key <= 111 || key >= 186 && key <= 222) { textDirty = true; document.querySelector('#note-header-left h2').classList.add('dirty'); } }); function setHeight() { md = new markdownit({ html: true, linkify: true, breaks: true }); body = document.querySelector('body'); body.style.height = window.innerHeight + 'px'; cont = document.querySelector('#main'); cont.style.height = (window.innerHeight) + 'px'; tabs = document.querySelector('.ref-tab'); tabs.style.height = (window.innerHeight - 13) + 'px'; ref = document.querySelector('.ref'); ref.style.height = (window.innerHeight - 50) + 'px'; noteList = document.querySelector('#note-list'); noteList.style.height = (window.innerHeight - 50) + 'px'; notes = document.querySelector('.notes'); notes.style.height = (window.innerHeight - 50) + 'px'; notePreview = document.querySelector('#notePreview'); notePreview.style.height = (window.innerHeight - 50) + 'px'; date = document.querySelector('#noteDate'); dt = new Date(); date.value = dt.getFullYear() + '-' + ((dt.getMonth() < 9) ? '0' + (dt.getMonth() + 1) : (dt.getMonth() + 1)) + '-' + (dt.getDate() < 10 ? '0' + dt.getDate() : dt.getDate()); setTimeout(saveNote, saveTimeout); } function newNote() { notes = document.querySelector('#notes'); notes.text = ''; notes.value = ''; references = {}; saved = true; textDirty = false; document.querySelector('#note-header-left h2').classList.remove('dirty'); dt = new Date(); document.querySelector('#noteDate').value = dt.getFullYear() + '-' + (dt.getMonth() < 9 ? '0' + (dt.getMonth() + 1) : (dt.getMonth() + 1)) + '-' + (dt.getDate() < 10 ? '0' + dt.getDate() : dt.getDate()); document.querySelector('#noteTitle').value = ''; document.querySelector('#speaker').value = 0; document.querySelector('#series').value = 0; document.querySelector('#template').value = 0; document.querySelector('#passage').value = ''; document.querySelector('#noteId').value = uuidv4(); //document.querySelector('#noteSearch').style.display = 'none'; document.querySelector('#ref-list').innerHTML = ''; document.querySelector('#ref').innerHTML = ''; document.querySelector('.toggle').click(); } /** * Save a note by sending it to the server for storage. * * @param {Event} event - The event object triggering the save action. * @return {void} No explicit return value. */ function saveNote(event) { if (event) { event.preventDefault(); } if (!textDirty || !validateNote()) { setTimeout(saveNote, saveTimeout); return; } var note = { id: document.querySelector("#noteId").value, date: document.querySelector('#noteDate').value, title: document.querySelector('#noteTitle').value, speaker: document.querySelector('#speaker').value, series: document.querySelector('#series').value, passage: document.querySelector('#passage').value, note: document.querySelector('#notes').value, refs: references }; fetch('/index.php/save-note', { method: 'POST', headers: { "Content-Type": 'application/json' }, body: JSON.stringify(note) }) .then(response => response.json()) .then(data => { if (data.msg == 'saved' && !saved) { showSave(); saved = true; textDirty = false; document.querySelector('#note-header-left h2').classList.remove('dirty'); } }) .catch(error => console.log(error)) .finally(() => setTimeout(saveNote, saveTimeout)); } function validateNote() { const note = document.querySelector('#notes'); const date = document.querySelector('#noteDate'); const speaker = document.querySelector('#speaker'); const series = document.querySelector('#series'); const title = document.querySelector('#noteTitle'); const id = document.querySelector('#noteId'); const psg = document.querySelector('#passage'); if (!isUuidV4Valid(id.value)) { return false; } if (!title.value.length) { return false; } if (!date.value) { return false; } if (!parseInt(speaker.value)) { return false; } if (!parseInt(series.value)) { return false; } if (!psg.value) { return false; } if (!note.value.length) { return false; } return true; } function isUuidV4Valid(uuid) { const regex = /^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[8|9|a|b][a-f0-9]{3}-[a-f0-9]{12}$/i; return regex.test(uuid); } /** * Displays a checkmark animation on the screen. * * @param {none} - This function does not take any parameters. * @return {none} - This function does not return any value. */ function showSave() { if (saved) { return; } var checkmark = document.getElementById("save-check"); // Schedule the animation to run every 1 second (which is equivalent to a 1-second delay between each iteration) var si = setInterval(function () { // Increment the opacity of the checkmark by 0.01 each time op = parseFloat(checkmark.style.opacity); checkmark.style.opacity = op + 0.1; // If the opacity is greater than or equal to 1, reset it back to 0 and stop the animation if (checkmark.style.opacity >= 1) { checkmark.style.opacity = 0; clearInterval(si); saved = false; } }, 100); } /** * Function to discard the note by clearing all input fields and closing the menu. */ function discardNote() { document.querySelector('#noteTitle').value = ''; document.querySelector('#speaker').value = 0; document.querySelector('#series').value = 0; document.querySelector('#template').value = 0; document.querySelector('#passage').value = ''; document.querySelector('#notes').value = ''; fetch('/index.php/discard-note', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ 'id': document.querySelector('#noteId').value }) .then(response => response.json()) .then(data => { if (data.msg == 'deleted') { alert('Note deleted.'); } }) }); openRef(); } function newSpeaker() { if (document.querySelector('#speaker').value == 'new') { document.querySelector('#newSpeaker').style.display = 'inline-block'; document.querySelector('#speaker').style.display = 'none'; } saved = false; textDirty = true; } function saveSpeaker(event) { if (event.keyCode == 13) { fetch('/index.php/save-speaker', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ 'speakerName': document.querySelector('#newSpeaker').value }) }) .then(response => response.json()) .then(results => { var newSpeaker = document.createElement('option'); newSpeaker.text = document.querySelector('#newSpeaker').value; newSpeaker.value = results.id; document.querySelector('#speaker').add(newSpeaker); alert(results.msg); document.querySelector('#newSpeaker').style.display = 'none'; document.querySelector('#speaker').style.display = 'inline-block'; document.querySelector('#newSpeaker').value = ''; document.querySelector('#speaker').value = results.id; }); } } function newSeries() { if (document.querySelector('#series').value == 'new') { document.querySelector('#newSeries').style.display = 'inline-block'; document.querySelector('#series').style.display = 'none'; } saved = false; textDirty = true; } function saveSeries(event) { if (event.keyCode == 13) { fetch('/index.php/save-series', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ 'seriesName': document.querySelector('#newSeries').value }) }) .then(response => response.json()) .then(results => { var newSeries = document.createElement('option'); newSeries.text = document.querySelector('#newSeries').value; newSeries.value = results.id; document.querySelector('#series').add(newSeries); alert(results.msg); document.querySelector('#newSeries').style.display = 'none'; document.querySelector('#series').style.display = 'inline-block'; document.querySelector('#newSeries').value = ''; document.querySelector('#series').value = results.id; }); } } function openRef(closeSidebar = true) { refQuery = document.querySelector('#refQuery'); refQuery.style.display = 'block'; ref = document.querySelector('#ref'); refQuery.style.left = ref.offsetLeft + 'px'; refQuery.style.top = ref.offsetTop + 'px'; if (closeSidebar) { document.querySelector('.toggle').click(); } } function closeRef() { refQuery = document.querySelector('#refQuery'); refQuery.style.display = 'none'; } function queryRef() { var input = document.querySelector('#refQuery #search'); var type = document.querySelector('#referenceType'); var book = document.querySelector('#referenceBook'); fetch('/index.php/retrieve-reference', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ 'type': type.value, 'book': book.value, 'reference': input.value, }) }) .then(response => response.json()) .then(results => { const list = document.querySelector('#ref-list'); var newList = document.createElement('li'); newList.className = 'tab'; button = makeButton(results.title); newList.appendChild(button); list.appendChild(newList); const ref = document.querySelector('#ref'); ref.innerHTML = md.render(results.text); references[results.title] = results.text; input.value = ''; document.querySelector('#referenceType').value = ''; document.querySelector('#referenceBook').value = ''; document.querySelector('#referenceBook').style.display = 'none'; closeRef(); saved = false; textDirty = true; saveNote(); findRefLinks(); }); } function makeButton(title) { var btn = document.createElement('button'); btn.innerText = title; btn.addEventListener('click', function () { removeActiveRef(); document.querySelector('#ref').innerHTML = md.render(references[title]); this.classList.add('activeRef'); findRefLinks(); }); btn.addEventListener('dblclick', function () { document.querySelector('#ref').innerHTML = ''; delete references[title]; var list = this.parentElement; list.remove(); saved = false; textDirty = true; saveNote(); }); removeActiveRef(); btn.classList.add('activeRef'); return btn; } function removeActiveRef() { tabs = document.querySelectorAll('.activeRef'); for (var t in tabs) { if (isFinite(parseInt(t))) { tabs[t].classList.remove('activeRef'); } } } function retrieveTemplate(orig, dest) { const temp = document.querySelector('#' + orig); if (temp.value == '0') { document.querySelector('#' + dest).value = ''; return; } fetch('/index.php/retrieve-template', { method: 'POST', headers: { 'Content-Type': 'plain/text' }, body: JSON.stringify({ 'template': temp.value }) }) .then(response => response.text()) .then(results => { const div = document.querySelector('#' + dest); div.value = results; }); } /** * Saves the template by sending a POST request to the server with template data. */ function saveTemplate() { fetch('/index.php/save-template', { method: 'POST', headers: { 'Content-Type': 'plain/text' }, body: JSON.stringify({ 'template_id': document.querySelector('#template_id').value, 'template_name': document.querySelector('#template_name').value, 'template_value': document.querySelector('#template_value').value, }) }) .then(response => response.text()) .then(results => { alert(results); }); } function toggleFields() { const fieldsContainer = document.getElementById('fields-container'); const showHideBtn = document.getElementById('show-hide-btn'); if (fieldsContainer.classList.contains('show')) { // Hide the fields when the button says "Show Fields" fieldsContainer.classList.remove('show'); fieldsContainer.style.display = 'none'; showHideBtn.textContent = 'Show'; } else { // Show the fields when the button says "Hide Fields" fieldsContainer.classList.add('show'); fieldsContainer.style.display = 'block'; showHideBtn.textContent = 'Hide'; } setHeight(); } function retrieveBooks() { const selectedType = document.querySelector('#referenceType').value; if (!selectedType) { return; } var bookList = document.querySelector('#referenceBook'); bookList.style.display = "block"; bookList.innerHTML = ''; if (selectedType == 'bible') { var none = document.createElement("option"); none.value = ''; none.text = '-- Select --'; bookList.appendChild(none); for (var x in BOOKS.bible) { var newBook = document.createElement("option"); newBook.text = BOOKS.bible[x]; bookList.appendChild(newBook); } } else if (selectedType == 'creed') { var none = document.createElement('option'); none.value = ''; none.text = '-- Select --'; bookList.appendChild(none); for (var x in BOOKS.creed) { var newBook = document.createElement('option'); newBook.value = x; newBook.text = BOOKS.creed[x]; bookList.appendChild(newBook); } } else if (selectedType == 'cd') { var none = document.createElement("option"); none.value = ''; none.text = '-- Select --'; bookList.appendChild(none); for (var x in BOOKS.cd) { var newBook = document.createElement("option"); newBook.text = BOOKS.cd[x]; bookList.appendChild(newBook); } } else { var min = BOOKS[selectedType][0]; var max = BOOKS[selectedType][1]; var none = document.createElement("option"); none.value = ''; none.text = '-- Select --'; bookList.appendChild(none); for (var x = min; x <= max; x++) { var newBook = document.createElement("option"); newBook.value = x; newBook.text = x; bookList.appendChild(newBook); } } } function retrieveReference(el) { fetch('/index.php/get-reference', { method: "POST", header: { "Content-Type": "application/json" }, body: JSON.stringify({ file: el.value, type: el.options[el.selectedIndex].getAttribute('type') }) }) .then(response => response.json()) .then(results => { document.querySelector('#reference').value = results.text; }); } function saveReference() { var select = document.querySelector('#references'); fetch('/index.php/save-reference', { method: 'POST', header: { 'Content-Type': 'application/json' }, body: JSON.stringify({ type: select.options[select.selectedIndex].getAttribute('type'), file: select.value, text: document.querySelector('#reference').value }) }) .then(response => response.json()) .then(results => { alert(results.msg); document.querySelector('#reference').value = ''; document.querySelector('#references').value = ''; }); } function previewNote() { var noteText = document.querySelector('#notes'); var notePreview = document.querySelector('#notePreview'); var previewButton = document.querySelector('#previewBtn'); const title = document.querySelector('#noteTitle'); const speaker = document.querySelector('#speaker'); const passage = document.querySelector('#passage'); const markdownPreview = "# " + title.value + " - " + speaker.options[speaker.selectedIndex].text + " - " + passage.value + "\n\n" + noteText.value; notePreview.innerHTML = md.render(markdownPreview); if (previewButton.value == 'Preview') { previewButton.value = 'Hide Preview'; noteText.style.display = 'none'; notePreview.style.display = 'block'; } else { previewButton.value = 'Preview'; noteText.style.display = 'block'; notePreview.style.display = 'none'; } findLinks(); } function findLinks() { var links = document.querySelector('#notePreview').querySelectorAll('a'); for (var i = 0; i < links.length; i++) { links[i].addEventListener('mouseover', function (e) { e.preventDefault(); if (!this.href.contains('notes\.rkprather\.com')) { return; } var passage = this.href.split('/'); passage = passage[passage.length - 1]; fetch(this.href, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ 'passage': passage }) }) .then(response => response.text()) .then(result => { passage = passage.replace(/\+/g, ' '); psg = passage.split(' '); if (psg.length > 2) { book = psg[0] + ' ' + psg[1]; cv = psg[2]; } else { book = psg[0]; cv = psg[1]; } showPassage( e, "  " + "
" + result); }); }); } } function findRefLinks() { var links = document.querySelector('#ref').querySelectorAll('a'); for (var i = 0; i < links.length; i++) { links[i].addEventListener('mouseover', function (e) { e.preventDefault(); if (!this.href.contains('get-passage')) { return; } var passage = this.href.split('/'); passage = passage[passage.length - 1]; fetch(this.href, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ 'passage': passage }) }) .then(response => response.text()) .then(result => { passage = passage.replace(/\+/g, ' '); psg = passage.split(' '); if (psg.length > 2) { book = psg[0] + ' ' + psg[1]; cv = psg[2]; } else { book = psg[0]; cv = psg[1]; } showPassage( e, "  " + "
" + result); }); }); } } function showPassage(event, text) { // Create a new div element for the popup const popup = document.querySelector('#passage-popup'); popup.innerHTML = md.render(text); // Position the popup relative to the cursor let x = event.clientX + window.pageXOffset; let y = event.clientY + window.pageYOffset; // Set the position of the popup element popup.style.top = `${y}px`; popup.style.left = `${x}px`; popup.style.display = 'block'; } function closePopup() { const popup = document.querySelector('#passage-popup'); popup.innerHTML = ''; popup.style.display = 'none'; } function openNote() { const noteList = document.querySelector('#note-list'); const refs = document.querySelector('#ref'); if (noteList.style.display == 'block') { noteList.style.display = 'none'; refs.style.display = 'block'; } else { noteList.style.display = 'block'; refs.style.display = 'none'; } document.querySelector('.toggle').click(); } function retrieveNote(id) { fetch('/index.php/get-note', { method: 'POST', header: { 'Content-Type': 'application/json' }, body: JSON.stringify({ 'id': id }) }) .then(response => response.json()) .then(result => { var dt = new Date(result.date); document.querySelector('#notes').value = result.text; document.querySelector('#passage').value = result.passage; document.querySelector('#series').value = result.series.id; document.querySelector('#speaker').value = result.speaker.id; document.querySelector('#noteTitle').value = result.title; document.querySelector('#noteDate').value = dt.getFullYear() + '-' + (dt.getMonth() < 9 ? '0' + (dt.getMonth() + 1) : (dt.getMonth() + 1)) + '-' + (dt.getDate() < 10 ? '0' + dt.getDate() : dt.getDate()); document.querySelector('#noteId').value = result.id; if (result.references) { references = result.references; } const list = document.querySelector('#ref-list'); var newList = null; for (var x in references) { var newList = document.createElement('li'); newList.className = 'tab'; var button = makeButton(x); newList.appendChild(button); list.appendChild(newList); } openNote(); }); } function increaseFont() { var currentSize = document.querySelector('#ref').style.fontSize; document.querySelector('#ref').style.fontSize = (parseInt(currentSize) + 1) + 'pt'; } function decreaseFont() { var currentSize = document.querySelector('#ref').style.fontSize; document.querySelector('#ref').style.fontSize = (parseInt(currentSize) - 1) + 'pt'; } /** * Generates a random UUIDv4 string. * * @return {string} The generated UUIDv4 string. */ function uuidv4() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' .replace(/[xy]/g, function (c) { const r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); }