Ohjeet: screenshot-upload paste & drag-drop + kuva-lightbox
Screenshottien lisääminen ohjeisiin nyt helpompaa: - Ctrl+V / Cmd+V: liitä kuvakaappaus suoraan leikepöydältä editoriin - Drag & drop: raahaa kuvatiedostoja suoraan textarea-editoriin - Upload-placeholder näkyy latauksen aikana (![Ladataan: ...]()) - Vihjeet editorin alla kertovat käytettävissä olevat tavat - Kuva-lightbox: klikkaa kuvaa lukunäkymässä → avautuu isona - Kuvien hover-efekti (zoom-in kursori, kevyt varjo) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
104
script.js
104
script.js
@@ -3498,6 +3498,20 @@ let guideCategories = [];
|
||||
let currentGuideId = null;
|
||||
|
||||
// Markdown-renderöijä (kevyt, ei ulkoisia kirjastoja)
|
||||
// Kuva-lightbox ohjeissa
|
||||
function openGuideLightbox(src, alt) {
|
||||
let overlay = document.getElementById('guide-lightbox');
|
||||
if (!overlay) {
|
||||
overlay = document.createElement('div');
|
||||
overlay.id = 'guide-lightbox';
|
||||
overlay.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.85);display:flex;align-items:center;justify-content:center;z-index:10000;cursor:zoom-out;padding:2rem;';
|
||||
overlay.addEventListener('click', () => overlay.style.display = 'none');
|
||||
document.body.appendChild(overlay);
|
||||
}
|
||||
overlay.innerHTML = `<img src="${src}" alt="${alt}" style="max-width:95%;max-height:95%;border-radius:8px;box-shadow:0 8px 40px rgba(0,0,0,0.5);">`;
|
||||
overlay.style.display = 'flex';
|
||||
}
|
||||
|
||||
function renderMarkdown(md) {
|
||||
if (!md) return '';
|
||||
let html = esc(md);
|
||||
@@ -3513,8 +3527,8 @@ function renderMarkdown(md) {
|
||||
html = html.replace(/\*\*\*(.+?)\*\*\*/g, '<strong><em>$1</em></strong>');
|
||||
html = html.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
|
||||
html = html.replace(/\*(.+?)\*/g, '<em>$1</em>');
|
||||
// Kuvat (ennen linkkejä!)
|
||||
html = html.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '<img src="$2" alt="$1" style="max-width:100%;border-radius:8px;margin:0.5rem 0;">');
|
||||
// Kuvat (ennen linkkejä!) — klikkaa avataksesi isompana
|
||||
html = html.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '<img src="$2" alt="$1" class="guide-img" onclick="openGuideLightbox(this.src, this.alt)" title="Klikkaa suurentaaksesi">');
|
||||
// Linkit
|
||||
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" rel="noopener">$1</a>');
|
||||
// Lainaukset
|
||||
@@ -3746,13 +3760,15 @@ document.getElementById('btn-guide-preview-toggle')?.addEventListener('click', (
|
||||
}
|
||||
});
|
||||
|
||||
// Kuva-upload
|
||||
document.getElementById('btn-guide-image')?.addEventListener('click', () => {
|
||||
document.getElementById('guide-image-input')?.click();
|
||||
});
|
||||
document.getElementById('guide-image-input')?.addEventListener('change', async (e) => {
|
||||
const file = e.target.files[0];
|
||||
if (!file) return;
|
||||
// Kuva-upload: yhteinen upload-funktio
|
||||
async function guideUploadImage(file) {
|
||||
const ta = document.getElementById('guide-form-content');
|
||||
if (!ta) return;
|
||||
const pos = ta.selectionStart;
|
||||
// Näytä upload-placeholder
|
||||
const placeholder = `![Ladataan: ${file.name}...]()`;
|
||||
ta.value = ta.value.substring(0, pos) + placeholder + ta.value.substring(ta.selectionEnd);
|
||||
ta.focus();
|
||||
const formData = new FormData();
|
||||
formData.append('image', file);
|
||||
try {
|
||||
@@ -3761,16 +3777,70 @@ document.getElementById('guide-image-input')?.addEventListener('change', async (
|
||||
});
|
||||
const result = await res.json();
|
||||
if (!res.ok) throw new Error(result.error || 'Virhe');
|
||||
// Lisää Markdown-kuvatagi editoriin
|
||||
const ta = document.getElementById('guide-form-content');
|
||||
const pos = ta.selectionStart;
|
||||
const mdImg = ``;
|
||||
ta.value = ta.value.substring(0, pos) + mdImg + ta.value.substring(ta.selectionEnd);
|
||||
ta.focus();
|
||||
ta.selectionStart = ta.selectionEnd = pos + mdImg.length;
|
||||
} catch (err) { alert(err.message); }
|
||||
e.target.value = ''; // nollaa input
|
||||
ta.value = ta.value.replace(placeholder, mdImg);
|
||||
} catch (err) {
|
||||
ta.value = ta.value.replace(placeholder, '');
|
||||
alert('Kuvan lataus epäonnistui: ' + err.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Toolbar-nappi
|
||||
document.getElementById('btn-guide-image')?.addEventListener('click', () => {
|
||||
document.getElementById('guide-image-input')?.click();
|
||||
});
|
||||
document.getElementById('guide-image-input')?.addEventListener('change', async (e) => {
|
||||
const file = e.target.files[0];
|
||||
if (file) await guideUploadImage(file);
|
||||
e.target.value = '';
|
||||
});
|
||||
|
||||
// Paste screenshot leikepöydältä (Ctrl+V / Cmd+V)
|
||||
document.getElementById('guide-form-content')?.addEventListener('paste', async (e) => {
|
||||
const items = e.clipboardData?.items;
|
||||
if (!items) return;
|
||||
for (const item of items) {
|
||||
if (item.type.startsWith('image/')) {
|
||||
e.preventDefault();
|
||||
const file = item.getAsFile();
|
||||
if (file) {
|
||||
// Anna tiedostolle nimi aikaleimalla
|
||||
const ext = file.type.split('/')[1] || 'png';
|
||||
const named = new File([file], `screenshot-${Date.now()}.${ext}`, { type: file.type });
|
||||
await guideUploadImage(named);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Drag & drop kuvat editoriin
|
||||
const guideTA = document.getElementById('guide-form-content');
|
||||
if (guideTA) {
|
||||
guideTA.addEventListener('dragover', (e) => {
|
||||
if (e.dataTransfer?.types?.includes('Files')) {
|
||||
e.preventDefault();
|
||||
guideTA.style.borderColor = 'var(--primary-color)';
|
||||
guideTA.style.background = '#f0f7ff';
|
||||
}
|
||||
});
|
||||
guideTA.addEventListener('dragleave', () => {
|
||||
guideTA.style.borderColor = '';
|
||||
guideTA.style.background = '';
|
||||
});
|
||||
guideTA.addEventListener('drop', async (e) => {
|
||||
guideTA.style.borderColor = '';
|
||||
guideTA.style.background = '';
|
||||
const files = e.dataTransfer?.files;
|
||||
if (!files?.length) return;
|
||||
for (const file of files) {
|
||||
if (file.type.startsWith('image/')) {
|
||||
e.preventDefault();
|
||||
await guideUploadImage(file);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Kategorianhallinta
|
||||
document.getElementById('btn-manage-guide-cats')?.addEventListener('click', () => {
|
||||
|
||||
Reference in New Issue
Block a user