From 5bb61de760f7d1a01aff3d8135cd59a6482b9bbe Mon Sep 17 00:00:00 2001 From: satori Date: Thu, 16 Jan 2025 06:05:50 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=93=E6=9E=84=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cursor.js | 69 ++++++++++++++++++++++------------------------------- markdown.js | 50 +++----------------------------------- 2 files changed, 31 insertions(+), 88 deletions(-) diff --git a/cursor.js b/cursor.js index d251ae0..f6afd9f 100644 --- a/cursor.js +++ b/cursor.js @@ -53,65 +53,52 @@ export class Cursor { // 获取当前光标的矩形位置 getBoundingClientRect() { - this.updateRange() + this.range.setStart(this.targetNode, this.insertIndex) + this.range.setEnd(this.targetNode, this.insertIndex) return this.range.getBoundingClientRect() } // 更新光标位置 - updatePosition(rect) { - if (!rect) { - this.hide() - return - } - this.cursorElement.style.left = `${rect.left}px` - this.cursorElement.style.top = `${rect.top}px` + updatePosition({ left, top }) { + this.cursorElement.style.left = `${left}px` + this.cursorElement.style.top = `${top}px` this.cursorElement.style.display = "block" } - // 隐藏光标 - hide() { - this.cursorElement.style.display = "none" - } - // 移除光标元素 remove() { this.cursorElement.remove() } - move(key) { - // 获取目标节点的上下兄弟节点(li元素) - const children = Array.from(this.targetNode.parentNode.parentNode.children) - const siblings = children.filter(node => { - return node !== this.targetNode && node.nodeType === Node.ELEMENT_NODE - }).map(item => { - return Array.from(item.childNodes).find(node => node.nodeType === Node.TEXT_NODE) - }) - const currentIndex = siblings.indexOf(this.targetNode) + oninput({ value }) { + const text = this.targetNode.textContent + const left = text.slice(0, this.insertIndex) + const right = text.slice(this.insertIndex) + this.insertIndex += value.length + this.targetNode.textContent = left + value + right + this.updatePosition(this.getBoundingClientRect()) + } - if (key === "ArrowUp" && currentIndex > 0) { - const prevSibling = siblings[currentIndex - 1] - const index = Math.max(0, Math.min(prevSibling.textContent.length, this.insertIndex)) - this.setTarget(prevSibling, index) // 光标在上一个兄弟元素的起始位置 - return + onkeydown({ key }) { + if (key === "ArrowUp" && this.targetNode.parentNode.previousElementSibling) { + // 先取兄弟元素的最后一个子元素, 没有则取兄弟元素, 没有则向上回溯 + this.targetNode = Array.from(this.targetNode.parentNode.previousElementSibling.childNodes).find(node => node.nodeType === Node.TEXT_NODE) + this.insertIndex = Math.max(0, Math.min(this.targetNode.textContent.length, this.insertIndex)) + this.updatePosition(this.getBoundingClientRect()) } - - if (key === "ArrowDown" && currentIndex >= 0 && currentIndex < siblings.length - 1) { - const nextSibling = siblings[currentIndex + 1] - const index = Math.max(0, Math.min(nextSibling.textContent.length, this.insertIndex)) - this.setTarget(nextSibling, index) // 光标在下一个兄弟元素的起始位置 - return + if (key === "ArrowDown" && this.targetNode.parentNode.nextElementSibling) { + // 先取当前子元素, 没有则取下一个兄弟元素, 没有则向上回溯 + this.targetNode = Array.from(this.targetNode.parentNode.nextElementSibling.childNodes).find(node => node.nodeType === Node.TEXT_NODE) + this.insertIndex = Math.max(0, Math.min(this.targetNode.textContent.length, this.insertIndex)) + this.updatePosition(this.getBoundingClientRect()) } - - if (key === "ArrowLeft" && this.insertIndex > 0) { + if (key === "ArrowLeft") { this.insertIndex = Math.max(0, Math.min(this.targetNode.textContent.length, this.insertIndex - 1)) - this.updateRange() - return + return this.updatePosition(this.getBoundingClientRect()) } - - if (key === "ArrowRight" && this.insertIndex < this.targetNode.textContent.length) { + if (key === "ArrowRight") { this.insertIndex = Math.max(0, Math.min(this.targetNode.textContent.length, this.insertIndex + 1)) - this.updateRange() - return + return this.updatePosition(this.getBoundingClientRect()) } } } diff --git a/markdown.js b/markdown.js index f63d31d..2492dd2 100644 --- a/markdown.js +++ b/markdown.js @@ -33,49 +33,13 @@ document.body.appendChild(textarea) // 处理输入事件 textarea.oninput = () => { - const inputText = textarea.value // 获取用户输入的文本 - if (!inputText) return - - cursors.forEach(cursor => { - if (!cursor.targetNode || cursor.insertIndex === null) return - - // 更新文本节点内容 - cursor.targetNode.textContent = - cursor.targetNode.textContent.slice(0, cursor.insertIndex) + - inputText + - cursor.targetNode.textContent.slice(cursor.insertIndex) - - // 更新插入位置 - cursor.insertIndex += inputText.length - }) - - // 清空输入框 + cursors.forEach(cursor => cursor.oninput(textarea)) textarea.value = "" - updateCursors() } // 处理方向键移动插入点 textarea.onkeydown = (event) => { - cursors.filter(cursor => cursor.targetNode && cursor.insertIndex !== null).forEach(cursor => { - cursor.move(event.key) - updateCursors() - }) -} - -// 更新所有光标的位置 -const updateCursors = () => { - cursors.forEach(cursor => { - if (!cursor.targetNode || cursor.insertIndex === null) { - cursor.hide() - return - } - - // 获取插入点位置 - const rect = cursor.getBoundingClientRect() - - // 更新光标位置 - cursor.updatePosition(rect) - }) + cursors.forEach(cursor => cursor.onkeydown({ key: event.key })) } // 渲染 Markdown 并监听点击事件 @@ -131,18 +95,10 @@ element.onclick = (event) => { } // 更新光标位置 - updateCursors() + cursors.forEach(cursor => cursor.updatePosition(cursor.getBoundingClientRect())) // 聚焦输入框 textarea.value = "" textarea.focus() } -// 按删除键移除光标 -document.addEventListener('keydown', (event) => { - if (event.key === 'Delete' && cursors.length > 0) { - const cursorToRemove = cursors.pop() // 移除最后一个光标 - cursorToRemove.remove() // 移除对应的光标元素 - console.log("移除光标") - } -})