add: new js files for simplicity
This commit is contained in:
@@ -0,0 +1,412 @@
|
||||
import { state } from './state.js';
|
||||
import { toggleFields } from './home.js';
|
||||
|
||||
/**
|
||||
* Toggles the visibility of the note list and reference elements.
|
||||
*
|
||||
* @param {boolean} [openSidebar=true] - Whether to open the sidebar after toggling the visibility.
|
||||
* @return {void}
|
||||
*/
|
||||
export function openNote(openSidebar = true) {
|
||||
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';
|
||||
}
|
||||
|
||||
if (openSidebar) {
|
||||
document.querySelector('.toggle').click();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the save process by updating the save-check element's classList, removing error, fa-times-circle, and fa-save classes,
|
||||
* adding the 'saving' and 'fa-save' classes, and setting the opacity to 1.
|
||||
*
|
||||
* @return {void} This function does not return anything.
|
||||
*/
|
||||
export function startSave() {
|
||||
document.querySelector('#save-check').classList.remove('error', 'fa-times-circle', 'fa-save');
|
||||
document.querySelector('#save-check').classList.add('saving', 'fa-save');
|
||||
document.querySelector('#save-check').style.opacity = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
export function showSave() {
|
||||
if (state.saved) { return; }
|
||||
|
||||
var checkmark = document.getElementById("save-check");
|
||||
checkmark.classList.add('fa-save');
|
||||
|
||||
// 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 == 0.1) {
|
||||
checkmark.style.opacity = 0;
|
||||
clearInterval(si);
|
||||
state.saved = false;
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* function to discard the note by clearing all input fields and closing the menu.
|
||||
*/
|
||||
export function deleteNote(noteId, link) {
|
||||
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 = '';
|
||||
document.querySelector('#recording').value = '';
|
||||
document.querySelector('#noteDate').value = '';
|
||||
document.querySelector('#noteId').value = '';
|
||||
|
||||
var row = link.parentElement.parentElement;
|
||||
|
||||
fetch('/delete-note', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
'id': noteId
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.msg != 'deleted') {
|
||||
return;
|
||||
}
|
||||
|
||||
alert('Note deleted.');
|
||||
row.remove();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a note by checking if all required fields are filled.
|
||||
*
|
||||
* @return {boolean} Returns true if all required fields are filled, false otherwise.
|
||||
*/
|
||||
export 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 psg = document.querySelector('#passage');
|
||||
|
||||
let ret = true;
|
||||
|
||||
if (!title.value.length) { title.classList.add('input-error'); ret = false; }
|
||||
if (!date.value) { date.classList.add('input-error'); ret = false; }
|
||||
if (!parseInt(speaker.value)) { speaker.classList.add('input-error'); ret = false; }
|
||||
if (!parseInt(series.value)) { series.classList.add('input-error'); ret = false; }
|
||||
if (!psg.value) { psg.classList.add('input-error'); ret = false; }
|
||||
if (!note.value.length) { note.classList.add('input-error'); ret = false; }
|
||||
|
||||
if (!ret) {
|
||||
toggleFields(null, true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the state of the note editor by clearing the text and form fields,
|
||||
* resetting the references, and removing any dirty classes. It also sets the
|
||||
* date to the current date, clears the speaker, series, template, passage,
|
||||
* recording, and note ID fields. Finally, it clears the reference list and
|
||||
* reference display.
|
||||
*
|
||||
* @return {void} This function does not return anything.
|
||||
*/
|
||||
export function newNote() {
|
||||
notes = document.querySelector('#notes');
|
||||
notes.text = '';
|
||||
notes.value = '';
|
||||
state.references = {};
|
||||
state.saved = true;
|
||||
state.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('#recording').value = '';
|
||||
document.querySelector('#noteId').value = '';
|
||||
|
||||
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.
|
||||
*/
|
||||
export function saveNote(event) {
|
||||
console.debug('called saveNote '+new Date());
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
if (!state.textDirty) {
|
||||
clearTimeout(state.to);
|
||||
state.to = setTimeout(saveNote, state.saveInterval);
|
||||
return;
|
||||
}
|
||||
|
||||
document.querySelector('#noteTitle').classList.remove('input-error');
|
||||
document.querySelector('#noteDate').classList.remove('input-error');
|
||||
document.querySelector('#speaker').classList.remove('input-error');
|
||||
document.querySelector('#series').classList.remove('input-error');
|
||||
document.querySelector('#passage').classList.remove('input-error');
|
||||
document.querySelector('#notes').classList.remove('input-error');
|
||||
|
||||
if (!validateNote()) {
|
||||
clearTimeout(state.to);
|
||||
state.to = setTimeout(saveNote, state.saveInterval);
|
||||
return;
|
||||
}
|
||||
|
||||
let saveCheck = document.querySelector('#save-check');
|
||||
var noteText = document.querySelector('#notes').value;
|
||||
|
||||
startSave();
|
||||
|
||||
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,
|
||||
recording: document.querySelector('#recording').value,
|
||||
refs: references
|
||||
};
|
||||
$.ajax({
|
||||
url: '/save-note',
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(note),
|
||||
dataType: 'json',
|
||||
timeout: state.saveTimeout
|
||||
})
|
||||
.done(function (data) {
|
||||
if (data.msg == 'saved' && !state.saved) {
|
||||
state.saveFailureCount = SAVE_FAILURE_LIMIT;
|
||||
saveCheck.classList.remove('saving', 'error', 'fa-times-circle', 'fa-save');
|
||||
showSave();
|
||||
if (noteText == document.querySelector('#notes').value) {
|
||||
state.saved = true;
|
||||
state.textDirty = false;
|
||||
document.querySelector('note-header h2').classList.remove('dirty');
|
||||
document.querySelector('mobile-note-header h2').classList.remove('dirty');
|
||||
}
|
||||
|
||||
if (data.new) {
|
||||
document.querySelector('#noteId').value = data.id;
|
||||
}
|
||||
}
|
||||
})
|
||||
.fail(function (xhr, status, error) {
|
||||
state.saveFailureCount--;
|
||||
saveCheck.classList.remove('saving', 'fa-save');
|
||||
saveCheck.classList.add('fa-times-circle', 'error');
|
||||
console.error(error);
|
||||
})
|
||||
.always(function (xhr, status) {
|
||||
if (status == 'timeout') {
|
||||
saveCheck.classList.remove('saving', 'fa-save');
|
||||
saveCheck.classList.add('error', 'fa-times-circle');
|
||||
}
|
||||
clearTimeout(to);
|
||||
if (state.saveFailureCount > 0) {
|
||||
state.to = setTimeout(saveNote, state.saveInterval);
|
||||
} else {
|
||||
state.saveFailureCount = SAVE_FAILURE_LIMIT;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that finds reference links and fetches passage data when clicked.
|
||||
*/
|
||||
export function findRefLinks() {
|
||||
var links = document.querySelector('#ref-text').querySelectorAll('a');
|
||||
|
||||
for (var i = 0; i < links.length; i++) {
|
||||
links[i].addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
if (!this.href.includes('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> " +
|
||||
"<button onclick=\"queryRef('bible', '" + book + "', '" + cv + "')\">Open Ref</button><br/>" +
|
||||
result);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all links in the note preview and adds event listeners to them.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
export function findLinks() {
|
||||
var links = document.querySelector('#notePreview').querySelectorAll('a');
|
||||
|
||||
for (var i = 0; i < links.length; i++) {
|
||||
links[i].addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
if (!this.href.includes('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='home.closePopup()'>Close</button> " +
|
||||
"<button onclick=\"home.queryRef('bible', '" + book + "', '" + cv + "')\">Open Ref</button><br/>" +
|
||||
result);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the share note functionality.
|
||||
*/
|
||||
export function openShareNote() {
|
||||
var id = document.querySelector('#noteId').value;
|
||||
if (!id) {
|
||||
alert('No Open Note Found');
|
||||
return;
|
||||
}
|
||||
|
||||
bd = document.querySelector('#modal-backdrop');
|
||||
bd.style.display = 'block';
|
||||
cont = document.querySelector('#modal-container');
|
||||
cont.style.display = bd.style.display;
|
||||
|
||||
emailCont = document.querySelector('#modal-container');
|
||||
emailCont.style.left = ((window.innerWidth / 2) - (emailCont.clientWidth / 2)) + 'px';
|
||||
emailCont.style.top = ((window.innerHeight / 2) - (emailCont.clientHeight / 2)) + 'px';
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the share note modal by hiding the backdrop and container,
|
||||
* and clears the email input value.
|
||||
*/
|
||||
export function closeShareNote() {
|
||||
var bd = document.querySelector('#modal-backdrop');
|
||||
var cont = document.querySelector('#modal-container');
|
||||
bd.style.display = 'none';
|
||||
cont.style.display = 'none';
|
||||
document.querySelector('#shareEmail').value = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to share a note by sending the note ID and email to the server.
|
||||
*/
|
||||
export function shareNote(event) {
|
||||
var id = document.querySelector('#noteId').value;
|
||||
var email = document.querySelector('#shareEmail').value;
|
||||
if (!id || !email) {
|
||||
alert('Invalid Input');
|
||||
return;
|
||||
}
|
||||
|
||||
fetch('/share-note', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
'id': id,
|
||||
'email': email
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
if (result) {
|
||||
alert(result.msg);
|
||||
}
|
||||
});
|
||||
|
||||
closeShareNote();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user