add: new js files for simplicity
This commit is contained in:
@@ -0,0 +1,439 @@
|
||||
import * as note from './note.js';
|
||||
import { state } from './state.js';
|
||||
import * as ref from './reference.js';
|
||||
|
||||
// Get the link element
|
||||
var tabs = [];
|
||||
let controller;
|
||||
|
||||
// Function to change the CSS file based on checkbox state
|
||||
/**
|
||||
* Method to toggle dark/light mode
|
||||
*
|
||||
* @param {*} event
|
||||
*/
|
||||
export function toggleDarkMode(event) {
|
||||
let mainCssLink = $('link[data-css="mode"');
|
||||
if(mainCssLink.length > 0) {
|
||||
mainCssLink[0].href = (event.target.checked ? mainCssLink.data('dark') : mainCssLink.data('light'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the visibility of the fields container and updates the active state of the show/hide button.
|
||||
*
|
||||
* @param Event e
|
||||
* @param boolean forceShow
|
||||
* @return {void}
|
||||
*/
|
||||
export function toggleFields(e, forceShow = false) {
|
||||
const fieldsContainer = document.querySelector('.fields-container');
|
||||
let showHideBtn = document.getElementById('show-hide-btn');
|
||||
let mobileShowHideBtn = document.getElementById('mobile-show-hide-btn');
|
||||
|
||||
if (forceShow || !fieldsContainer.classList.contains('show')) {
|
||||
fieldsContainer.classList.add('show');
|
||||
fieldsContainer.style.display = 'flex';
|
||||
showHideBtn.classList.add('active');
|
||||
mobileShowHideBtn.classList.add('active');
|
||||
} else {
|
||||
fieldsContainer.classList.remove('show');
|
||||
fieldsContainer.style.display = 'none';
|
||||
showHideBtn.classList.remove('active');
|
||||
mobileShowHideBtn.classList.remove('active');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the font size of the element with the id 'ref' by 1 point.
|
||||
*
|
||||
* @return {void} This function does not return a value.
|
||||
*/
|
||||
export function increaseFont() {
|
||||
var currentSize = document.querySelector('#ref-text').style.fontSize;
|
||||
const newSize = parseInt(currentSize) + 1;
|
||||
document.querySelector('#ref-text').style.fontSize = newSize + 'pt';
|
||||
document.querySelector('#notes').style.fontSize = newSize + 'pt';
|
||||
document.querySelector('#notePreview').style.fontSize = newSize + 'pt';
|
||||
}
|
||||
|
||||
/**
|
||||
* Decreases the font size of the element with the id 'ref' by 1 point.
|
||||
*
|
||||
* @return {void} This function does not return a value.
|
||||
*/
|
||||
export function decreaseFont() {
|
||||
var currentSize = document.querySelector('#ref-text').style.fontSize;
|
||||
const newSize = parseInt(currentSize) - 1;
|
||||
document.querySelector('#ref-text').style.fontSize = newSize + 'pt';
|
||||
document.querySelector('#notes').style.fontSize = newSize + 'pt';
|
||||
document.querySelector('#notePreview').style.fontSize = newSize + 'pt';
|
||||
}
|
||||
|
||||
/**
|
||||
* Previews a note by rendering the markdown content of the note in a preview section.
|
||||
* Toggles between the note text and preview sections.
|
||||
*
|
||||
* @return {void} This function does not return anything.
|
||||
*/
|
||||
export 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 = state.md.render(markdownPreview);
|
||||
|
||||
if (previewButton.classList.contains('active')) {
|
||||
document.querySelector('.note-text').style.display = 'block';
|
||||
notePreview.style.display = 'none';
|
||||
previewButton.classList.remove('active');
|
||||
} else {
|
||||
document.querySelector('.note-text').style.display = 'none';
|
||||
notePreview.style.display = 'block';
|
||||
previewButton.classList.add('active');
|
||||
}
|
||||
|
||||
note.findLinks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets event listeners for keyup events on the document and the '#notes' element.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
export function setEventListeners() {
|
||||
document.addEventListener('keyup', function (event) {
|
||||
if (event.key == "F3") {
|
||||
openRef(false);
|
||||
}
|
||||
});
|
||||
|
||||
document.querySelector('#notes').addEventListener('keyup', function (event) {
|
||||
let key = event.keyCode;
|
||||
|
||||
if (key == 8 || key >= 48 && key <= 90 || key >= 96 && key <= 111 || key >= 186 && key <= 222) {
|
||||
state.textDirty = true;
|
||||
document.querySelector('.mobile-note-header h2').classList.add('dirty');
|
||||
document.querySelector('.note-header h2').classList.add('dirty');
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('dark-mode-checkbox').addEventListener('click', toggleDarkMode);
|
||||
document.getElementById('mobile-dark-mode-checkbox').addEventListener('click', toggleDarkMode);
|
||||
|
||||
document.getElementById('show-hide-btn').addEventListener('click', toggleFields);
|
||||
document.getElementById('mobile-show-hide-btn').addEventListener('click', toggleFields);
|
||||
|
||||
document.getElementById('increaseFont').addEventListener('click', increaseFont);
|
||||
document.getElementById('decreaseFont').addEventListener('click', decreaseFont);
|
||||
document.getElementById('open-ref').addEventListener('click', openRef, {closeSidebar: false});
|
||||
document.getElementById('mobile-open-ref').addEventListener('click', openRef, {closeSidebar: false});
|
||||
document.getElementById('previewBtn').addEventListener('click', previewNote);
|
||||
|
||||
document.getElementById('searchBtn').addEventListener('click', ref.queryRef);
|
||||
document.getElementById('closeSearch').addEventListener('click', closeRef);
|
||||
}
|
||||
|
||||
export function initHome() {
|
||||
setBooks();
|
||||
setEventListeners();
|
||||
|
||||
$('sidebar-link').on('click', function(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
$('#sidebar').toggleClass('inactive');
|
||||
});
|
||||
|
||||
$('sidebar').on('click', 'a', function(event) {
|
||||
var $a = $(this), href = $a.attr('href'), target = $a.attr('target');
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
$('sidebar').addClass('inactive');
|
||||
|
||||
setTimeout(function() {
|
||||
if (target == '_blank')
|
||||
window.open(href);
|
||||
else
|
||||
window.location.href = href;
|
||||
}, 500);
|
||||
});
|
||||
|
||||
$('#note-table').DataTable({
|
||||
paging: false,
|
||||
ajax: {
|
||||
url: '/get-notes',
|
||||
type: 'POST'
|
||||
},
|
||||
columns: [
|
||||
{ data: 'link' },
|
||||
{ data: 'speaker.name' },
|
||||
{ data: 'passage' },
|
||||
{
|
||||
data: 'date.date',
|
||||
render: DataTable.render.date("L")
|
||||
},
|
||||
]
|
||||
});
|
||||
$('#shareBtn').on('click', note.openShareNote);
|
||||
$('#modal-backdrop').on('click', note.closeShareNote);
|
||||
|
||||
state.md = new markdownit({
|
||||
html: true,
|
||||
linkify: true,
|
||||
breaks: true
|
||||
});
|
||||
|
||||
if ($('#noteDate')) {
|
||||
$('#noteDate').datepicker();
|
||||
}
|
||||
|
||||
if ($('#query')) {
|
||||
document.querySelector('#query').addEventListener('keyup', function (event) {
|
||||
if (event.key == "Enter") {
|
||||
search();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Assuming 'to' and 'saveInterval' are declared globally elsewhere in your script
|
||||
if (typeof state.to === 'undefined' || !state.to) {
|
||||
state.to = setTimeout(note.saveNote, state.saveInterval);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches data from '/js/data.json', assigns it to BOOKS, and handles errors.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
export function setBooks() {
|
||||
fetch('js/data.json')
|
||||
.then((res) => {
|
||||
if (!res.ok) {
|
||||
throw new Error('HTTP Error: Status: ${res.status}');
|
||||
}
|
||||
return res.json();
|
||||
})
|
||||
.then((data) => {
|
||||
state.BOOKS = data;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the reference with the option to close the sidebar.
|
||||
*
|
||||
* @param {boolean} closeSidebar - Indicates whether to close the sidebar when opening the reference.
|
||||
*/
|
||||
export function openRef(e, closeSidebar = true) {
|
||||
document.querySelector('#open-ref').classList.add('active');
|
||||
document.querySelector('#mobile-open-ref').classList.add('active');
|
||||
|
||||
let refQuery = document.querySelector('#refQuery');
|
||||
refQuery.style.display = 'block';
|
||||
|
||||
let ref = document.querySelector('#ref-text');
|
||||
refQuery.style.left = ref.offsetLeft + 'px';
|
||||
refQuery.style.top = ref.offsetTop + 'px';
|
||||
if (closeSidebar) {
|
||||
document.querySelector('.toggle').click();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the reference query and resets the reference search form.
|
||||
*
|
||||
* @return {void} This function does not return anything.
|
||||
*/
|
||||
export function closeRef() {
|
||||
document.querySelector('#referenceSearch').value = '';
|
||||
document.querySelector('#referenceSearch').style.display = '';
|
||||
document.querySelector('#referenceType').value = '';
|
||||
document.querySelector('#referenceBook').value = '';
|
||||
document.querySelector('#referenceBook').style.display = 'none';
|
||||
document.querySelector('#chapter-range').innerText = '';
|
||||
document.querySelector('#verse-range').innerText = '';
|
||||
|
||||
document.querySelector('#refQuery').style.display = 'none';
|
||||
document.querySelector('#open-ref').classList.remove('active');
|
||||
document.querySelector('#mobile-open-ref').classList.remove('active');
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a note from the server based on the provided ID.
|
||||
*
|
||||
* @param {string} id - The ID of the note to retrieve.
|
||||
* @param {boolean} [runOpen=true] - Whether to open the note sidebar after retrieving the note.
|
||||
* @return {Promise<void>} A promise that resolves when the note is successfully retrieved and the UI is updated.
|
||||
*/
|
||||
export function retrieveNote(id, runOpen = true) {
|
||||
fetch('/get-note', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
'id': id
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
var dt = new Date(result.date.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 = '';
|
||||
document.querySelector('#noteDate').value =
|
||||
(dt.getMonth() < 9 ? '0' + (dt.getMonth() + 1) : (dt.getMonth() + 1)) + '/' +
|
||||
(dt.getDate() < 10 ? '0' + dt.getDate() : dt.getDate()) + '/' +
|
||||
dt.getFullYear();
|
||||
document.querySelector('#noteId').value = result.id;
|
||||
|
||||
if (result.refs) {
|
||||
references = result.refs;
|
||||
}
|
||||
|
||||
const list = document.querySelector('#ref-list');
|
||||
list.innerHTML = '';
|
||||
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);
|
||||
}
|
||||
|
||||
if (runOpen) {
|
||||
note.openNote(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* A function to create a button element with the specified title and event listeners for click and double click actions.
|
||||
*
|
||||
* @param {string} title - The title to be displayed on the button.
|
||||
* @return {Element} The created button element.
|
||||
*/
|
||||
export function makeButton(title) {
|
||||
var btn = document.createElement('button');
|
||||
btn.innerText = title;
|
||||
btn.class = 'button';
|
||||
btn.style = 'line-height:normal;'
|
||||
btn.addEventListener('click', function () {
|
||||
removeActiveRef();
|
||||
document.querySelector('#ref-text').innerHTML = state.md.render(state.references[title]);
|
||||
this.classList.add('active');
|
||||
note.findRefLinks();
|
||||
});
|
||||
|
||||
btn.addEventListener('dblclick', function () {
|
||||
document.querySelector('#ref-text').innerHTML = '';
|
||||
delete state.references[title];
|
||||
var list = this.parentElement;
|
||||
list.remove();
|
||||
state.saved = false;
|
||||
state.textDirty = true;
|
||||
note.saveNote();
|
||||
});
|
||||
|
||||
removeActiveRef();
|
||||
btn.classList.add('active');
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the 'active' class from all elements with the class 'active'.
|
||||
*
|
||||
* @return {void} This function does not return a value.
|
||||
*/
|
||||
export function removeActiveRef() {
|
||||
tabs = document.querySelectorAll('#ref-list .active');
|
||||
for (var t in tabs) {
|
||||
if (isFinite(parseInt(t))) {
|
||||
tabs[t].classList.remove('active');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random UUIDv4 string.
|
||||
*
|
||||
* @return {string} The generated UUIDv4 string.
|
||||
*/
|
||||
export 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);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for notes based on the query entered in the search field.
|
||||
* Sends a POST request to the '/search' endpoint with the query as a JSON payload.
|
||||
* Updates the '#old-notes' element with the search results.
|
||||
*
|
||||
* @return {Promise} A Promise that resolves with the search results.
|
||||
*/
|
||||
export function search() {
|
||||
query = document.querySelector('#query').value;
|
||||
fetch('/search', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
'query': query
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(results => {
|
||||
var oldNotes = document.querySelector('#old-notes');
|
||||
oldNotes.innerHTML = '';
|
||||
for (var n in results) {
|
||||
var link = document.createElement('a');
|
||||
link.href = '#';
|
||||
link.setAttribute('onclick', "note.retrieveNote('" + results[n].id + "');note.openNote();");
|
||||
link.innerHTML = results[n].title;
|
||||
|
||||
var p = document.createElement('p');
|
||||
p.innerHTML = results[n].passage;
|
||||
|
||||
var article = document.createElement('article');
|
||||
article.appendChild(link);
|
||||
article.appendChild(p);
|
||||
|
||||
oldNotes.append(article);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the passage popup by clearing its content and hiding it.
|
||||
*
|
||||
* @return {void} This function does not return anything.
|
||||
*/
|
||||
export function closePopup() {
|
||||
const popup = document.querySelector('#passage-popup');
|
||||
popup.innerHTML = '';
|
||||
popup.style.display = 'none';
|
||||
}
|
||||
Reference in New Issue
Block a user