Guest_Book/script.js

199 lines
5.7 KiB
JavaScript

// Enable debug mode if the URL contains the debug parameter
let debug = false;
if (window.location.href.includes('debug')) {
console.log('Debug mode enabled');
debug = true;
}
// Initialize the EventSource and the HTML elements
const eventSource = new EventSource('https://ntfy.example.org/guestbook/sse?since=all');
const entryText = document.getElementById('entryText');
const name = document.getElementById('name');
const submitEntry = document.getElementById('submitEntry');
const entryTable = document.getElementById('entryTable');
const errorMessage = document.getElementById('error-message');
const bell = new Audio('/resources/sounds/notification.ogg');
// Disable the notification sound for the first 2 seconds until the guestbook is loaded initially
let bellEnabled = false;
// Event listener for the Enter key
function handleKeydown(event) {
if (event.key === 'Enter') {
sendMessage();
}
}
// Check if the name is valid
function checkName(name) {
if (name.match(/:\s/)) {
errorMessage.classList.add('visible');
console.error('Invalid name');
return false;
}
return true;
}
// Send new entry to the ntfy server
function sendMessage() {
const text = entryText.value.trim();
const author = name.value.trim() ? name.value.trim() : 'Anonymous';
if (checkName(author)) {
errorMessage.classList.remove('visible');
const message = author + ': ' + text;
if (text.length > 0) {
fetch('https://ntfy.example.org/guestbook', {
method: 'POST',
body: message
})
.then(() => {
// Empty the input field
entryText.value = '';
// Save the name in the local storage
localStorage.setItem('name', author);
})
.catch(error => console.error(error));
}
}
}
// Calculate time passed since the message was sent
function timeSince(date) {
let seconds = Math.floor(Date.now() / 1000 - date);
let interval = Math.floor(seconds / 3600);
if (interval >= 2) {
return interval + " hours ago";
}
if (interval === 1) {
return "1 hour ago"
}
interval = Math.floor(seconds / 60);
if (interval > 1) {
return interval + " minutes ago";
}
if (interval === 1) {
return "1 minute ago"
}
if (seconds > 10) {
return Math.floor(seconds) + " seconds ago";
}
if (seconds > -10) {
return "just now"
}
if (seconds > -60) {
return "in " + Math.floor(-seconds) + " seconds";
}
interval = Math.floor(-seconds / 60);
if (interval === 1) {
return "in 1 minute";
}
if (interval < 60) {
return "in " + interval + " minutes";
}
interval = Math.floor(-seconds / 3600);
if (interval === 1) {
return "in 1 hour";
}
if (interval > 1) {
return "in " + interval + " hours";
}
}
// Parse the time from the message
function parseTimeString(data) {
return ` | ${timeSince(data.time)}, expires in ${timeSince(data.expires)}`
}
// Update time
function updateTime() {
const timeElements = document.getElementsByClassName('time');
for (let i = 0; i < timeElements.length; i++) {
const time = timeElements[i];
time.textContent = parseTimeString(time.dataset);
}
}
// Add a new entry to the list
function addEntry(data) {
const row = document.createElement('tr');
// Create a new cell for the author
const authorCell = document.createElement('td');
authorCell.classList.add('author');
authorCell.style.fontWeight = 'italic';
// Create a new cell for the message
const messageCell = document.createElement('td');
messageCell.classList.add('message');
// Split the message into author and text
const [name, message] = data.message.split(/:\s(.*)/);
// Create span with the time that passed since the message was sent
// and when the message will expire
const time = document.createElement('span');
time.classList.add('time');
time.dataset.time = data.time;
time.dataset.expires = data.expires;
time.textContent = parseTimeString(data);
// Set the cell content
authorCell.textContent = name + ':';
messageCell.innerHTML = message + time.outerHTML;
// Append the cells to the row and the row to the table
row.appendChild(authorCell);
row.appendChild(messageCell);
entryTable.appendChild(row);
}
// Connect to the server to receive new entries
function streamEntries() {
eventSource.onmessage = (m) => {
if (debug) {
console.log(m.data);
}
const data = JSON.parse(m.data)
addEntry(data);
// Play a notification sound for new entries
try {
if (bellEnabled) {
bell.play();
}
} catch (DOMException) {
console.log('The notification sound was blocked by the browser');
}
};
}
// Initialize the page
function setup() {
// Add event listeners
submitEntry.addEventListener('click', sendMessage);
entryText.addEventListener('keydown', handleKeydown);
// Start streaming the entries
streamEntries();
// Update the time values every 10 seconds
setInterval(updateTime, 10000);
// Load the name from the local storage
name.value = localStorage.getItem('name');
// Enable the notification sound after 2 seconds
setTimeout(() => {
bellEnabled = true;
}, 2000);
// Close the connection when the page is closed
window.addEventListener('beforeunload', function (e) {
e.preventDefault();
eventSource.close();
});
}
window.addEventListener('load', setup)