100 lines
2.9 KiB
JavaScript
100 lines
2.9 KiB
JavaScript
|
|
(function() {
|
||
|
|
const API_URL = '<your-url>';
|
||
|
|
const form = document.getElementById('gb-form');
|
||
|
|
const list = document.getElementById('gb-entries');
|
||
|
|
const status = document.getElementById('gb-status');
|
||
|
|
|
||
|
|
function escapeHtml(text) {
|
||
|
|
if (!text) return "";
|
||
|
|
return text
|
||
|
|
.replace(/&/g, "&")
|
||
|
|
.replace(/</g, "<")
|
||
|
|
.replace(/>/g, ">")
|
||
|
|
.replace(/"/g, """)
|
||
|
|
.replace(/'/g, "'");
|
||
|
|
}
|
||
|
|
|
||
|
|
async function loadComments() {
|
||
|
|
try {
|
||
|
|
const res = await fetch(API_URL);
|
||
|
|
if (!res.ok) throw new Error("Failed to load");
|
||
|
|
|
||
|
|
const data = await res.json();
|
||
|
|
|
||
|
|
if (data.length === 0) {
|
||
|
|
list.innerHTML = "<p>No entries yet. Be the first!</p>";
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
list.innerHTML = data.map(c => {
|
||
|
|
let nameDisplay = escapeHtml(c.name);
|
||
|
|
if (c.website) {
|
||
|
|
const safeUrl = c.website.replace(/["<>;]/g, "");
|
||
|
|
nameDisplay = `${escapeHtml(c.name)} (<a href="${safeUrl}" target="_blank" style="">${safeUrl}</a>)`;
|
||
|
|
}
|
||
|
|
|
||
|
|
return `
|
||
|
|
<div style="margin-bottom: 20px;">
|
||
|
|
<div class="title-bar grey">
|
||
|
|
<div style="font-size:15px;" class="title-bar-text">
|
||
|
|
<span>${nameDisplay}</span>
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<span style="font-size:15px;" class="title-bar-text">${c.date}</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="window main-left gbComments" style="padding: 10px;">
|
||
|
|
${escapeHtml(c.message)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
`;
|
||
|
|
}).join('');
|
||
|
|
|
||
|
|
} catch (err) {
|
||
|
|
console.error(err);
|
||
|
|
list.innerHTML = "<p style='color: red;'>Error loading guestbook.</p>";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
form.onsubmit = async (e) => {
|
||
|
|
e.preventDefault();
|
||
|
|
const btn = form.querySelector('button');
|
||
|
|
const nameInput = document.getElementById('gb-name');
|
||
|
|
const msgInput = document.getElementById('gb-msg');
|
||
|
|
const siteInput = document.getElementById('gb-site');
|
||
|
|
|
||
|
|
if (btn.disabled) return;
|
||
|
|
|
||
|
|
btn.disabled = true;
|
||
|
|
btn.innerText = "Sending...";
|
||
|
|
status.innerText = "";
|
||
|
|
|
||
|
|
try {
|
||
|
|
const res = await fetch(API_URL, {
|
||
|
|
method: 'POST',
|
||
|
|
headers: { 'Content-Type': 'application/json' },
|
||
|
|
body: JSON.stringify({
|
||
|
|
name: nameInput.value,
|
||
|
|
message: msgInput.value,
|
||
|
|
website: siteInput.value
|
||
|
|
})
|
||
|
|
});
|
||
|
|
|
||
|
|
const data = await res.json();
|
||
|
|
|
||
|
|
if (!res.ok) {
|
||
|
|
alert(data.error || "Error posting comment");
|
||
|
|
} else {
|
||
|
|
form.reset();
|
||
|
|
loadComments();
|
||
|
|
}
|
||
|
|
} catch (err) {
|
||
|
|
alert("Network error.");
|
||
|
|
} finally {
|
||
|
|
btn.disabled = false;
|
||
|
|
btn.innerText = "Post Comment";
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
loadComments();
|
||
|
|
})();
|