Kekalkan kedudukan karet dalam HTML boleh diedit kandungan apabila HTML dalaman berubah
P粉668804228
P粉668804228 2023-11-08 22:38:23
0
2
622

Saya mempunyai div yang bertindak sebagai editor WYSIWYG. Ia bertindak sebagai kotak teks tetapi memaparkan sintaks Markdown di dalamnya untuk menunjukkan perubahan secara langsung.

Masalah: Apabila menaip huruf, kedudukan karet ditetapkan semula ke permulaan div.


const editor = document.querySelector('div'); editor.innerHTML = parse('**dlob** *cilati*'); editor.addEventLis tener('input', () => { editor.innerHTML = parse(editor.innerText); }); function parse(text) { return text .replace(/**(.*)**/gm, '****') // bold .replace(/*(.*)*/gm, '**'); // italic }
div { height: 100vh; width: 100vw; }


Codepen: https://codepen.io/ADAMJR/pen/MWvPebK

Penyunting penurunan harga seperti QuillJS nampaknya boleh mengedit elemen anak tanpa mengedit elemen induk. Ini mengelakkan masalah, tetapi saya kini pasti bagaimana untuk mencipta semula logik itu dengan persediaan ini.

Soalan: Bagaimana untuk mengelakkan kedudukan karet daripada ditetapkan semula semasa menaip?

Kemas kini: Saya telah berjaya menghantar kedudukan karet ke hujung div pada setiap input. Walau bagaimanapun, ini masih pada asasnya menetapkan semula kedudukan. https://codepen.io/ADAMJR/pen/KKvGNbY


P粉668804228
P粉668804228

membalas semua (2)
P粉393030917

Apa yang dilakukan oleh kebanyakan editor teks yang kaya ialah mengekalkan keadaan dalaman mereka sendiri, mengemas kininya pada acara utama dan menghasilkan lapisan visual tersuai. Contohnya:

const $editor = document.querySelector('.editor'); const state = { cursorPosition: 0, contents: 'hello world'.split(''), isFocused: false, }; const $cursor = document.createElement('span'); $cursor.classList.add('cursor'); $cursor.innerText = '᠎'; // Mongolian vowel separator const renderEditor = () => { const $contents = state.contents .map(char => { const $span = document.createElement('span'); $span.innerText = char; return $span; }); $contents.splice(state.cursorPosition, 0, $cursor); $editor.innerHTML = ''; $contents.forEach(el => $editor.append(el)); } document.addEventListener('click', (ev) => { if (ev.target === $editor) { $editor.classList.add('focus'); state.isFocused = true; } else { $editor.classList.remove('focus'); state.isFocused = false; } }); document.addEventListener('keydown', (ev) => { if (!state.isFocused) return; switch(ev.key) { case 'ArrowRight': state.cursorPosition = Math.min( state.contents.length, state.cursorPosition + 1 ); renderEditor(); return; case 'ArrowLeft': state.cursorPosition = Math.max( 0, state.cursorPosition - 1 ); renderEditor(); return; case 'Backspace': if (state.cursorPosition === 0) return; delete state.contents[state.cursorPosition-1]; state.contents = state.contents.filter(Boolean); state.cursorPosition = Math.max( 0, state.cursorPosition - 1 ); renderEditor(); return; default: // This is very naive if (ev.key.length > 1) return; state.contents.splice(state.cursorPosition, 0, ev.key); state.cursorPosition += 1; renderEditor(); return; } }); renderEditor();
.editor { position: relative; min-height: 100px; max-height: max-content; width: 100%; border: black 1px solid; } .editor.focus { border-color: blue; } .editor.focus .cursor { position: absolute; border: black solid 1px; border-top: 0; border-bottom: 0; animation-name: blink; animation-duration: 1s; animation-iteration-count: infinite; } @keyframes blink { from {opacity: 0;} 50% {opacity: 1;} to {opacity: 0;} }
             
    P粉060112396

    Anda perlu mendapatkan kedudukan kursor terlebih dahulu, dan kemudian memproses dan menetapkan kandungan. Kemudian pulihkan kedudukan kursor.

    Memulihkan kedudukan kursor adalah bahagian yang sukar apabila terdapat elemen bersarang. Tambahan pula, anda akan mencipta elemenbaharu setiap kali dan yang lama akan dibuang.

    const editor = document.querySelector(".editor"); editor.innerHTML = parse( "For **bold** two stars.\nFor *italic* one star. Some more **bold**." ); editor.addEventListener("input", () => { //get current cursor position const sel = window.getSelection(); const node = sel.focusNode; const offset = sel.focusOffset; const pos = getCursorPosition(editor, node, offset, { pos: 0, done: false }); if (offset === 0) pos.pos += 0.5; editor.innerHTML = parse(editor.innerText); // restore the position sel.removeAllRanges(); const range = setCursorPosition(editor, document.createRange(), { pos: pos.pos, done: false, }); range.collapse(true); sel.addRange(range); }); function parse(text) { //use (.*?) lazy quantifiers to match content inside return ( text .replace(/\*{2}(.*?)\*{2}/gm, "****") // bold .replace(/(?*") // italic // handle special characters .replace(/\n/gm, "
    ") .replace(/\t/gm, " ") ); } // get the cursor position from .editor start function getCursorPosition(parent, node, offset, stat) { if (stat.done) return stat; let currentNode = null; if (parent.childNodes.length == 0) { stat.pos += parent.textContent.length; } else { for (let i = 0; i = stat.pos) { range.setStart(parent, stat.pos); stat.done = true; } else { stat.pos = stat.pos - parent.textContent.length; } } else { for (let i = 0; i
    .editor { height: 100px; width: 400px; border: 1px solid #888; padding: 0.5rem; white-space: pre; } em, strong{ font-size: 1.3rem; }
                  
      Muat turun terkini
      Lagi>
      kesan web
      Kod sumber laman web
      Bahan laman web
      Templat hujung hadapan
      Tentang kita Penafian Sitemap
      Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!