sermon-notes/public/js/script.js

749 lines
24 KiB
JavaScript

// 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,
"<button onclick='closePopup()'>Close</button>&nbsp;&nbsp;" +
"<button onclick=\"getRef('" + book + "', '" + cv + "')\">Open Ref</button><br/>" +
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,
"<button onclick='closePopup()'>Close</button>&nbsp;&nbsp;" +
"<button onclick=\"getRef('" + book + "', '" + cv + "')\">Open Ref</button><br/>" +
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);
});
}