我有一個 div 充當 WYSIWYG 編輯器。這充當文本框,但在其中呈現降價語法,以顯示實時更改。
問題:鍵入字母時,插入符號位置重置為 div 的開頭。
const editor = document.querySelector('div');
editor.innerHTML = parse('**dlob** *cilati*');
editor.addEventListener('input', () => {
editor.innerHTML = parse(editor.innerText);
});
function parse(text) {
return text
.replace(/\*\*(.*)\*\*/gm, '**<strong>$1</strong>**') // bold
.replace(/\*(.*)\*/gm, '*<em>$1</em>*'); // italic
}
div {
height: 100vh;
width: 100vw;
}
<div contenteditable />
代碼筆:https : //codepen.io/ADAMJR/pen/MWvPebK
像 QuillJS 這樣的 Markdown 編輯器似乎可以在不編輯父元素的情況下編輯子元素。這避免了這個問題,但我現在確定如何使用此設定重新創建該邏輯。
問題:如何在打字時使插入符號位置不重置?
更新:我已經設法在每個輸入上將插入符號位置發送到 div 的末尾。然而,這仍然基本上重置了位置。https://codepen.io/ADAMJR/pen/KKvGNbY
uj5u.com熱心網友回復:
大多數富文本編輯器的做法是保持它們自己的內部狀態,在按鍵事件時更新它并呈現自定義可視層。例如像這樣:
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;}
}
<div class="editor"></div>
uj5u.com熱心網友回復:
您需要保持位置的狀態并在每個輸入上恢復它。沒有其他辦法。您可以查看在我的專案jQuery Terminal中如何處理可編輯的內容(鏈接指向源代碼中的特定行并使用提交哈希,在我撰寫本文時使用當前主控,因此它們將始終指向這些行)。
- 用戶鍵入內容(或復制粘貼)時使用的插入方法。
- fix_textarea - 在我添加了可編輯的內容后,該功能沒有改變。該函式確保 textarea 或 contenteditable (隱藏的)與可見游標具有相同的狀態。
- 剪輯物件(即 textarea 或內容可編輯 - 另一個未重構的名稱,一開始僅用于剪貼板)。
對于位置,我使用jQuery Caret,它是移動游標的核心。您可以輕松修改此代碼并使其按需要作業。jQuery 插件可以很容易地重構為一個函式move_cursor。
這應該讓您了解如何在您的專案中自己實作這一點。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/360417.html
標籤:javascript html 形式 dom 文本
上一篇:表格形式內的欄位組
