feat(blog): in-content image carousel/slider
Editor: new 🎠 اسلایدر toolbar button — pick multiple images (min 2), uploads them all, inserts a <div class="post-carousel" data-carousel> block at the cursor. Editor preview shows a tidy filmstrip with the non-functional arrows/dots hidden. Public post page: carousel CSS (scroll-snap track) + JS that wires up prev/next arrows, clickable dots, and native touch swipe. Single-image blocks auto-collapse their controls. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -184,6 +184,12 @@ tr:hover td{background:#FAFBFC}
|
||||
.editor-toolbar button{background:none;border:none;padding:.3rem .5rem;border-radius:4px;cursor:pointer;font-size:.82rem;font-family:inherit;color:var(--mid)}
|
||||
.editor-toolbar button:hover{background:var(--gold-pale);color:var(--gold)}
|
||||
.editor-content{border:1.5px solid var(--border);border-radius:0 0 8px 8px;padding:.8rem 1rem;min-height:250px;outline:none;font-size:.9rem;line-height:1.8;direction:rtl}
|
||||
.editor-content img{max-width:100%;height:auto;border-radius:8px;margin:.6rem 0}
|
||||
/* Carousel preview inside the editor: tidy filmstrip, controls hidden */
|
||||
.editor-content .post-carousel{border:1px dashed var(--gold);border-radius:10px;padding:5px;background:#faf7f0;margin:.8rem 0}
|
||||
.editor-content .post-carousel .pc-track{display:flex;gap:6px;overflow-x:auto}
|
||||
.editor-content .post-carousel .pc-track img{flex:0 0 46%;max-height:170px;object-fit:cover;border-radius:6px;margin:0}
|
||||
.editor-content .post-carousel .pc-prev,.editor-content .post-carousel .pc-next,.editor-content .post-carousel .pc-dots{display:none}
|
||||
|
||||
/* ── Pages ── */
|
||||
.page{display:none}
|
||||
@@ -1028,6 +1034,7 @@ tr:hover td{background:#FAFBFC}
|
||||
<button onclick="fmt('insertOrderedList')">۱. لیست</button>
|
||||
<button onclick="insLink()">🔗 لینک</button>
|
||||
<button onclick="insImage()" title="درج تصویر در متن">🖼 تصویر</button>
|
||||
<button onclick="insCarousel()" title="درج اسلایدر چند تصویر">🎠 اسلایدر</button>
|
||||
</div>
|
||||
<div class="editor-content" id="post-content" contenteditable="true" dir="rtl"></div>
|
||||
</div>
|
||||
@@ -2270,6 +2277,38 @@ function insImage(){
|
||||
};
|
||||
fileInput.click();
|
||||
}
|
||||
// Insert a multi-image carousel/slider into the post content
|
||||
function insCarousel(){
|
||||
const editor=document.getElementById('post-content');
|
||||
editor.focus();
|
||||
const sel=window.getSelection();
|
||||
const savedRange=sel.rangeCount?sel.getRangeAt(0):null;
|
||||
const fileInput=document.createElement('input');
|
||||
fileInput.type='file';
|
||||
fileInput.accept='image/jpeg,image/png,image/webp,image/gif';
|
||||
fileInput.multiple=true;
|
||||
fileInput.onchange=async()=>{
|
||||
const files=[...fileInput.files];if(!files.length)return;
|
||||
if(files.length<2){toast('برای اسلایدر حداقل ۲ تصویر انتخاب کنید','error');return;}
|
||||
toast(`در حال آپلود ${files.length} تصویر...`);
|
||||
try{
|
||||
const urls=[];
|
||||
for(const file of files){
|
||||
const fd=new FormData();fd.append('file',file);
|
||||
const r=await fetch('/api/upload',{method:'POST',headers:{'Authorization':`Bearer ${token}`},body:fd});
|
||||
if(!r.ok)throw new Error(await r.text());
|
||||
const {url}=await r.json();urls.push(url);
|
||||
}
|
||||
const imgs=urls.map(u=>`<img src="${u}" alt=""/>`).join('');
|
||||
const html=`<div class="post-carousel" data-carousel><div class="pc-track">${imgs}</div><button class="pc-prev" type="button" contenteditable="false">‹</button><button class="pc-next" type="button" contenteditable="false">›</button><div class="pc-dots" contenteditable="false"></div></div><p><br></p>`;
|
||||
editor.focus();
|
||||
if(savedRange){sel.removeAllRanges();sel.addRange(savedRange);}
|
||||
document.execCommand('insertHTML',false,html);
|
||||
toast(`اسلایدر با ${urls.length} تصویر درج شد ✓`);
|
||||
}catch(e){toast('خطا در آپلود: '+e.message,'error');}
|
||||
};
|
||||
fileInput.click();
|
||||
}
|
||||
|
||||
// ── Modal helpers ─────────────────────────────────────────────────────────────
|
||||
function closeModal(id){document.getElementById(id).classList.add('hidden');}
|
||||
|
||||
Reference in New Issue
Block a user