Add shareable URLs for posts with copy link button
Hash-based URLs (#resepti/slug) allow sharing individual posts on social media. Modal shows "Kopioi linkki" button, hash auto-opens post on page load. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
44
script.js
44
script.js
@@ -84,6 +84,16 @@ function applyTranslations() {
|
|||||||
// ===========================
|
// ===========================
|
||||||
// HELPERS
|
// HELPERS
|
||||||
// ===========================
|
// ===========================
|
||||||
|
function postSlug(title) {
|
||||||
|
return title.toLowerCase()
|
||||||
|
.replace(/[äå]/g, 'a').replace(/ö/g, 'o').replace(/ü/g, 'u')
|
||||||
|
.replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function findPostBySlug(slug) {
|
||||||
|
return APP.posts.find(p => postSlug(p.title) === slug);
|
||||||
|
}
|
||||||
|
|
||||||
function sortSubcategories(subs) {
|
function sortSubcategories(subs) {
|
||||||
return [...subs].sort((a, b) => {
|
return [...subs].sort((a, b) => {
|
||||||
const aM = a.fi.toLowerCase() === 'muut' ? 1 : 0;
|
const aM = a.fi.toLowerCase() === 'muut' ? 1 : 0;
|
||||||
@@ -343,6 +353,7 @@ async function openPost(id) {
|
|||||||
<div class="modal-like-row">
|
<div class="modal-like-row">
|
||||||
<button class="like-btn ${liked ? 'liked' : ''}" data-like-id="${p.id}" onclick="toggleLike('${p.id}')">${liked ? t('liked_btn') : t('like_btn')}</button>
|
<button class="like-btn ${liked ? 'liked' : ''}" data-like-id="${p.id}" onclick="toggleLike('${p.id}')">${liked ? t('liked_btn') : t('like_btn')}</button>
|
||||||
<span class="like-count" data-like-count="${p.id}">${likeCount}</span>
|
<span class="like-count" data-like-count="${p.id}">${likeCount}</span>
|
||||||
|
<button class="copy-link-btn" onclick="copyPostLink('${postSlug(p.title)}')" style="margin-left:auto;padding:4px 14px;font-size:0.82rem;border:1px solid #ccc;background:#fff;border-radius:20px;cursor:pointer;">🔗 Kopioi linkki</button>
|
||||||
</div>
|
</div>
|
||||||
${bodyHTML}
|
${bodyHTML}
|
||||||
<div class="comments-section">
|
<div class="comments-section">
|
||||||
@@ -365,6 +376,9 @@ async function openPost(id) {
|
|||||||
document.getElementById('modalOverlay').classList.add('open');
|
document.getElementById('modalOverlay').classList.add('open');
|
||||||
document.body.style.overflow = 'hidden';
|
document.body.style.overflow = 'hidden';
|
||||||
|
|
||||||
|
// Update URL hash for shareable link
|
||||||
|
history.replaceState(null, '', '#resepti/' + postSlug(p.title));
|
||||||
|
|
||||||
const qEl = document.getElementById('captcha-question');
|
const qEl = document.getElementById('captcha-question');
|
||||||
if (qEl) qEl.textContent = generateCaptcha();
|
if (qEl) qEl.textContent = generateCaptcha();
|
||||||
}
|
}
|
||||||
@@ -420,9 +434,19 @@ async function submitComment(e, postId) {
|
|||||||
if (headEl) headEl.textContent = `${t('modal_comments')} (${comments.length})`;
|
if (headEl) headEl.textContent = `${t('modal_comments')} (${comments.length})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function copyPostLink(slug) {
|
||||||
|
const url = window.location.origin + window.location.pathname + '#resepti/' + slug;
|
||||||
|
navigator.clipboard.writeText(url).then(() => {
|
||||||
|
const btn = document.querySelector('.copy-link-btn');
|
||||||
|
if (btn) { btn.textContent = '✓ Kopioitu!'; setTimeout(() => { btn.textContent = '🔗 Kopioi linkki'; }, 2000); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function closeModal() {
|
function closeModal() {
|
||||||
document.getElementById('modalOverlay').classList.remove('open');
|
document.getElementById('modalOverlay').classList.remove('open');
|
||||||
document.body.style.overflow = '';
|
document.body.style.overflow = '';
|
||||||
|
// Clear URL hash
|
||||||
|
history.replaceState(null, '', window.location.pathname + window.location.search);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===========================
|
// ===========================
|
||||||
@@ -896,6 +920,26 @@ async function init() {
|
|||||||
renderCategoryFilters();
|
renderCategoryFilters();
|
||||||
renderSubFilters();
|
renderSubFilters();
|
||||||
renderCards();
|
renderCards();
|
||||||
|
|
||||||
|
// Open post from URL hash (e.g. #resepti/pinaattiletut)
|
||||||
|
const hash = window.location.hash;
|
||||||
|
if (hash.startsWith('#resepti/')) {
|
||||||
|
const slug = hash.slice('#resepti/'.length);
|
||||||
|
const post = findPostBySlug(slug);
|
||||||
|
if (post) openPost(post.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle browser back/forward with hash
|
||||||
|
window.addEventListener('hashchange', () => {
|
||||||
|
const hash = window.location.hash;
|
||||||
|
if (hash.startsWith('#resepti/')) {
|
||||||
|
const slug = hash.slice('#resepti/'.length);
|
||||||
|
const post = findPostBySlug(slug);
|
||||||
|
if (post) openPost(post.id);
|
||||||
|
} else {
|
||||||
|
closeModal();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|||||||
Reference in New Issue
Block a user