diff --git a/app/src/block/util.ts b/app/src/block/util.ts index 08043c275..b9ee773ef 100644 --- a/app/src/block/util.ts +++ b/app/src/block/util.ts @@ -5,12 +5,15 @@ import {genListItemElement, updateListOrder} from "../protyle/wysiwyg/list"; import {transaction, updateTransaction} from "../protyle/wysiwyg/transaction"; import {scrollCenter} from "../util/highlightById"; import {Constants} from "../constants"; +import {hideElements} from "../protyle/ui/hideElements"; export const cancelSB = (protyle: IProtyle, nodeElement: Element) => { const doOperations: IOperation[] = []; const undoOperations: IOperation[] = []; let previousId = nodeElement.previousElementSibling ? nodeElement.previousElementSibling.getAttribute("data-node-id") : undefined; nodeElement.classList.remove("protyle-wysiwyg--select"); + nodeElement.removeAttribute("select-start"); + nodeElement.removeAttribute("select-end"); const id = nodeElement.getAttribute("data-node-id"); const sbElement = genSBElement(nodeElement.getAttribute("data-sb-layout"), id, nodeElement.lastElementChild.outerHTML); undoOperations.push({ @@ -85,9 +88,7 @@ export const insertEmptyBlock = (protyle: IProtyle, position: InsertPosition, id } else { blockElement = selectElements[selectElements.length - 1]; } - selectElements.forEach(item => { - item.classList.remove("protyle-wysiwyg--select"); - }); + hideElements(["select"], protyle); } else { blockElement = hasClosestBlock(range.startContainer) as HTMLElement; blockElement = getTopAloneElement(blockElement); diff --git a/app/src/protyle/gutter/index.ts b/app/src/protyle/gutter/index.ts index ebf4d86da..d80b54c42 100644 --- a/app/src/protyle/gutter/index.ts +++ b/app/src/protyle/gutter/index.ts @@ -1333,7 +1333,7 @@ export class Gutter { label: window.siyuan.languages["insert-before"], accelerator: window.siyuan.config.keymap.editor.general.insertBefore.custom, click() { - nodeElement.classList.remove("protyle-wysiwyg--select"); + hideElements(["select"], protyle); countBlockWord([], protyle.block.rootID); insertEmptyBlock(protyle, "beforebegin", id); } @@ -1343,7 +1343,7 @@ export class Gutter { label: window.siyuan.languages["insert-after"], accelerator: window.siyuan.config.keymap.editor.general.insertAfter.custom, click() { - nodeElement.classList.remove("protyle-wysiwyg--select"); + hideElements(["select"], protyle); countBlockWord([], protyle.block.rootID); insertEmptyBlock(protyle, "afterend", id); } @@ -1353,7 +1353,7 @@ export class Gutter { label: window.siyuan.languages.jumpToParentNext, accelerator: window.siyuan.config.keymap.editor.general.jumpToParentNext.custom, click() { - nodeElement.classList.remove("protyle-wysiwyg--select"); + hideElements(["select"], protyle); jumpToParentNext(protyle, nodeElement); } }).element); diff --git a/app/src/protyle/ui/hideElements.ts b/app/src/protyle/ui/hideElements.ts index 2a6a2cf2a..d7595629e 100644 --- a/app/src/protyle/ui/hideElements.ts +++ b/app/src/protyle/ui/hideElements.ts @@ -38,6 +38,8 @@ export const hideElements = (panels: string[], protyle?: IProtyle, focusHide = f if (panels.includes("select")) { protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select").forEach(item => { item.classList.remove("protyle-wysiwyg--select"); + item.removeAttribute("select-start"); + item.removeAttribute("select-end"); }); } }; diff --git a/app/src/protyle/util/editorCommonEvent.ts b/app/src/protyle/util/editorCommonEvent.ts index 5a22f37e3..a6527bf17 100644 --- a/app/src/protyle/util/editorCommonEvent.ts +++ b/app/src/protyle/util/editorCommonEvent.ts @@ -597,6 +597,8 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => { }); sourceElements.forEach(item => { item.classList.remove("protyle-wysiwyg--select", "protyle-wysiwyg--hl"); + item.removeAttribute("select-start"); + item.removeAttribute("select-end"); // 反链提及有高亮,如果拖拽到正文的话,应移除 item.querySelectorAll('[data-type="search-mark"]').forEach(markItem => { markItem.outerHTML = markItem.innerHTML; @@ -778,6 +780,8 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => { if (nodeElement) { if ((window.siyuan.dragElement?.getAttribute("data-selected-ids") || "").indexOf(nodeElement.getAttribute("data-node-id")) === -1) { nodeElement.classList.remove("protyle-wysiwyg--select"); + nodeElement.removeAttribute("select-start"); + nodeElement.removeAttribute("select-end"); } nodeElement.classList.remove("dragover__top", "dragover__bottom", "dragover__left", "dragover__right"); } diff --git a/app/src/protyle/util/paste.ts b/app/src/protyle/util/paste.ts index d59e36331..7fae69baf 100644 --- a/app/src/protyle/util/paste.ts +++ b/app/src/protyle/util/paste.ts @@ -16,6 +16,7 @@ import {isDynamicRef, isFileAnnotation} from "../../util/functions"; import {insertHTML} from "./insertHTML"; import {scrollCenter} from "../../util/highlightById"; import {getContenteditableElement} from "../wysiwyg/getBlock"; +import {hideElements} from "../ui/hideElements"; const filterClipboardHint = (protyle: IProtyle, textPlain: string) => { let needRender = true; @@ -173,8 +174,9 @@ export const paste = async (protyle: IProtyle, event: (ClipboardEvent | DragEven } return; } - protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select, .protyle-wysiwyg--hl").forEach(item => { - item.classList.remove("protyle-wysiwyg--select", "protyle-wysiwyg--hl"); + hideElements(["select"], protyle); + protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--hl").forEach(item => { + item.classList.remove("protyle-wysiwyg--hl"); }); const code = processPasteCode(textHTML, textPlain); const range = getEditorRange(protyle.wysiwyg.element); diff --git a/app/src/protyle/util/selection.ts b/app/src/protyle/util/selection.ts index 034820a9c..361fa58e3 100644 --- a/app/src/protyle/util/selection.ts +++ b/app/src/protyle/util/selection.ts @@ -7,6 +7,7 @@ import { } from "../wysiwyg/getBlock"; import {hasClosestByAttribute, hasClosestByMatchTag} from "./hasClosest"; import {countBlockWord, countSelectWord} from "../../layout/status"; +import {hideElements} from "../ui/hideElements"; const selectIsEditor = (editor: Element, range?: Range) => { if (!range) { @@ -113,9 +114,7 @@ export const selectAll = (protyle: IProtyle, nodeElement: Element, range: Range) if (protyle.wysiwyg.element.childElementCount === selectElements.length && selectElements[0].parentElement.isSameNode(protyle.wysiwyg.element)) { return true; } - selectElements.forEach(item => { - item.classList.remove("protyle-wysiwyg--select"); - }); + hideElements(["select"], protyle); const ids: string [] = []; Array.from(protyle.wysiwyg.element.children).forEach(item => { item.classList.add("protyle-wysiwyg--select"); diff --git a/app/src/protyle/wysiwyg/commonHotkey.ts b/app/src/protyle/wysiwyg/commonHotkey.ts index 80293c256..48641b2e5 100644 --- a/app/src/protyle/wysiwyg/commonHotkey.ts +++ b/app/src/protyle/wysiwyg/commonHotkey.ts @@ -1,11 +1,15 @@ import {matchHotKey} from "../util/hotKey"; import {fetchPost} from "../../util/fetch"; import {writeText} from "../util/compatibility"; -import {focusByOffset, getSelectionOffset} from "../util/selection"; +import {focusByOffset, getSelectionOffset, setFirstNodeRange, setLastNodeRange} from "../util/selection"; import {fullscreen, netImg2LocalAssets} from "../breadcrumb/action"; import {setPadding} from "../ui/initUI"; import {openBacklink, openGraph, openOutline} from "../../layout/dock/util"; import {reloadProtyle} from "../util/reload"; +import {getContenteditableElement} from "./getBlock"; +import {hasClosestByMatchTag} from "../util/hasClosest"; +import {hideElements} from "../ui/hideElements"; +import {countBlockWord} from "../../layout/status"; export const commonHotkey = (protyle: IProtyle, event: KeyboardEvent) => { const target = event.target as HTMLElement; @@ -64,3 +68,123 @@ export const commonHotkey = (protyle: IProtyle, event: KeyboardEvent) => { } } }; + +export const upSelect = (options: { + protyle: IProtyle, + event: KeyboardEvent, + nodeElement: HTMLElement, + editorElement: HTMLElement, + range: Range, + cb: (selectElements: NodeListOf) => void +}) => { + const selectElements = options.protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select"); + if (selectElements.length > 0) { + options.event.stopPropagation(); + options.event.preventDefault(); + } else { + const start = getSelectionOffset(options.nodeElement, options.editorElement, options.range).start; + if (start !== 0) { + const editElement = getContenteditableElement(options.nodeElement); + if (editElement.tagName === "TABLE") { + const cellElement = hasClosestByMatchTag(options.range.startContainer, "TH") || hasClosestByMatchTag(options.range.startContainer, "TD") || editElement.querySelector("th, td"); + if (getSelectionOffset(cellElement, cellElement, options.range).start !== 0) { + setFirstNodeRange(cellElement, options.range); + options.event.stopPropagation(); + options.event.preventDefault(); + return; + } + } else { + const firstIndex = editElement.textContent.indexOf("\n"); + if (firstIndex === -1 || start <= firstIndex || start === editElement.textContent.replace("\n", " ").indexOf("\n")) { + setFirstNodeRange(editElement, options.range); + options.event.stopPropagation(); + options.event.preventDefault(); + return; + } else { + return; + } + } + } + } + options.range.collapse(true); + hideElements(["toolbar"], options.protyle); + if (selectElements.length === 0) { + options.nodeElement.classList.add("protyle-wysiwyg--select"); + } else { + options.cb(selectElements); + } + const ids: string[] = []; + options.protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select").forEach(item => { + ids.push(item.getAttribute("data-node-id")); + }); + countBlockWord(ids, options.protyle.block.rootID); + options.event.stopPropagation(); + options.event.preventDefault(); +} + +export const downSelect = (options: { + protyle: IProtyle, + event: KeyboardEvent, + nodeElement: HTMLElement, + editorElement: HTMLElement, + range: Range, + cb: (selectElement: NodeListOf) => void +}) => { + const selectElements = options.protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select"); + if (selectElements.length > 0) { + options.event.stopPropagation(); + options.event.preventDefault(); + } else { + const editElement = getContenteditableElement(options.nodeElement); + const end = getSelectionOffset(options.nodeElement, options.editorElement, options.range).end; + if (end < editElement.textContent.length) { + if (end > editElement.textContent.lastIndexOf("\n")) { + setLastNodeRange(editElement, options.range, false); + options.event.stopPropagation(); + options.event.preventDefault(); + return; + } else { + return; + } + } + } + options.range.collapse(false); + hideElements(["toolbar"], options.protyle); + if (selectElements.length === 0) { + options.nodeElement.classList.add("protyle-wysiwyg--select"); + } else { + options.cb(selectElements) + } + const ids: string[] = []; + options.protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select").forEach(item => { + ids.push(item.getAttribute("data-node-id")); + }); + countBlockWord(ids, options.protyle.block.rootID); + options.event.stopPropagation(); + options.event.preventDefault(); +} + +export const getStartEndElement = (selectElements: NodeListOf) => { + let startElement + let endElement + selectElements.forEach(item => { + if (item.getAttribute("select-start")) { + startElement = item + } + if (item.getAttribute("select-end")) { + endElement = item + } + }); + if (!startElement) { + startElement = selectElements[0] + startElement.setAttribute("select-start", "true") + } + if (!endElement) { + endElement = selectElements[selectElements.length - 1] + endElement.setAttribute("select-end", "true") + } + return { + startElement, + endElement + } +} diff --git a/app/src/protyle/wysiwyg/enter.ts b/app/src/protyle/wysiwyg/enter.ts index 6a1e50c07..c449a6e52 100644 --- a/app/src/protyle/wysiwyg/enter.ts +++ b/app/src/protyle/wysiwyg/enter.ts @@ -12,6 +12,7 @@ import {breakList, genListItemElement, listOutdent, updateListOrder} from "./lis import {highlightRender} from "../markdown/highlightRender"; import {Constants} from "../../constants"; import {scrollCenter} from "../../util/highlightById"; +import {hideElements} from "../ui/hideElements"; const listEnter = (protyle: IProtyle, blockElement: HTMLElement, range: Range) => { const listItemElement = blockElement.parentElement; @@ -193,7 +194,7 @@ export const enter = (blockElement: HTMLElement, range: Range, protyle: IProtyle if (!disableElement && blockElement.classList.contains("protyle-wysiwyg--select")) { setLastNodeRange(getContenteditableElement(blockElement), range, false); range.collapse(false); - blockElement.classList.remove("protyle-wysiwyg--select"); + hideElements(["select"], protyle); return; } // https://github.com/siyuan-note/siyuan/issues/5471 diff --git a/app/src/protyle/wysiwyg/index.ts b/app/src/protyle/wysiwyg/index.ts index 491f74098..ac0090b5b 100644 --- a/app/src/protyle/wysiwyg/index.ts +++ b/app/src/protyle/wysiwyg/index.ts @@ -1935,15 +1935,21 @@ export class WYSIWYG { ctrlElement = getTopAloneElement(ctrlElement) as HTMLElement; if (ctrlElement.classList.contains("protyle-wysiwyg--select")) { ctrlElement.classList.remove("protyle-wysiwyg--select"); + ctrlElement.removeAttribute("select-start"); + ctrlElement.removeAttribute("select-end"); } else { ctrlElement.classList.add("protyle-wysiwyg--select"); } ctrlElement.querySelectorAll(".protyle-wysiwyg--select").forEach(item => { item.classList.remove("protyle-wysiwyg--select"); + item.removeAttribute("select-start"); + item.removeAttribute("select-end"); }); const ctrlParentElement = hasClosestByClassName(ctrlElement, "protyle-wysiwyg--select"); if (ctrlParentElement && !ctrlElement.isSameNode(ctrlParentElement)) { ctrlParentElement.classList.remove("protyle-wysiwyg--select"); + ctrlParentElement.removeAttribute("select-start"); + ctrlParentElement.removeAttribute("select-end"); } const ids: string[] = []; protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select").forEach(item => { diff --git a/app/src/protyle/wysiwyg/keydown.ts b/app/src/protyle/wysiwyg/keydown.ts index 00ed71009..e31f54935 100644 --- a/app/src/protyle/wysiwyg/keydown.ts +++ b/app/src/protyle/wysiwyg/keydown.ts @@ -43,7 +43,7 @@ import {insertEmptyBlock, jumpToParentNext} from "../../block/util"; import {isLocalPath} from "../../util/pathName"; /// #if !MOBILE import {openBy, openFileById} from "../../editor/util"; -import {commonHotkey} from "./commonHotkey"; +import {commonHotkey, downSelect, getStartEndElement, upSelect} from "./commonHotkey"; /// #endif import {linkMenu, refMenu, setFold, zoomOut} from "../../menus/protyle"; import {removeEmbed} from "./removeEmbed"; @@ -145,9 +145,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { if (selectElements.length > 0) { event.preventDefault(); event.stopPropagation(); - selectElements.forEach(item => { - item.classList.remove("protyle-wysiwyg--select"); - }); + hideElements(["select"], protyle); if (event.key === "ArrowDown") { const currentSelectElement = selectElements[selectElements.length - 1] as HTMLElement; let nextElement = getNextBlock(currentSelectElement) as HTMLElement; @@ -286,109 +284,120 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { } } + if (matchHotKey("⌥⇧↑", event)) { + upSelect({ + protyle, event, nodeElement, editorElement, range, + cb(selectElements) { + const previousElement = selectElements[0].previousElementSibling as HTMLElement; + if (previousElement && previousElement.getAttribute("data-node-id")) { + previousElement.classList.add("protyle-wysiwyg--select"); + selectElements.forEach(item => { + item.removeAttribute("select-end") + }) + previousElement.setAttribute("select-end", "true"); + const top = previousElement.getBoundingClientRect().top - protyle.contentElement.getBoundingClientRect().top; + if (top < 0) { + protyle.contentElement.scrollTop = protyle.contentElement.scrollTop + top; + protyle.scroll.lastScrollTop = protyle.contentElement.scrollTop + 1; + } + } else if (!selectElements[0].parentElement.classList.contains("protyle-wysiwyg")) { + hideElements(["select"], protyle); + selectElements[0].parentElement.classList.add("protyle-wysiwyg--select"); + } + } + }); + return; + } + + if (matchHotKey("⌥⇧↓", event)) { + downSelect({ + protyle, event, nodeElement, editorElement, range, + cb(selectElements) { + const selectLastElement = selectElements[selectElements.length - 1]; + const nextElement = selectLastElement.nextElementSibling as HTMLElement; + if (nextElement && nextElement.getAttribute("data-node-id")) { + nextElement.classList.add("protyle-wysiwyg--select"); + selectElements.forEach(item => { + item.removeAttribute("select-end") + }) + nextElement.setAttribute("select-end", "true"); + const bottom = nextElement.getBoundingClientRect().bottom - protyle.contentElement.getBoundingClientRect().bottom; + if (bottom > 0) { + protyle.contentElement.scrollTop = protyle.contentElement.scrollTop + bottom; + protyle.scroll.lastScrollTop = protyle.contentElement.scrollTop - 1; + } + } else if (!selectLastElement.parentElement.classList.contains("protyle-wysiwyg")) { + hideElements(["select"], protyle); + selectLastElement.parentElement.classList.add("protyle-wysiwyg--select"); + } + } + }) + return; + } + if (matchHotKey("⇧↑", event)) { - const selectElements = protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select"); - if (selectElements.length > 0) { - event.stopPropagation(); - event.preventDefault(); - } else { - const start = getSelectionOffset(nodeElement, editorElement, range).start; - if (start !== 0) { - const editElement = getContenteditableElement(nodeElement); - if (editElement.tagName === "TABLE") { - const cellElement = hasClosestByMatchTag(range.startContainer, "TH") || hasClosestByMatchTag(range.startContainer, "TD") || editElement.querySelector("th, td"); - if (getSelectionOffset(cellElement, cellElement, range).start !== 0) { - setFirstNodeRange(cellElement, range); - event.stopPropagation(); - event.preventDefault(); - return; + upSelect({ + protyle, event, nodeElement, editorElement, range, + cb(selectElements) { + const startEndElement = getStartEndElement(selectElements) + if (startEndElement.startElement.getBoundingClientRect().top >= startEndElement.endElement.getBoundingClientRect().top) { + const previousElement = startEndElement.endElement.previousElementSibling as HTMLElement; + if (previousElement && previousElement.getAttribute("data-node-id")) { + previousElement.classList.add("protyle-wysiwyg--select"); + previousElement.setAttribute("select-end", "true"); + startEndElement.endElement.removeAttribute("select-end"); + const top = previousElement.getBoundingClientRect().top - protyle.contentElement.getBoundingClientRect().top; + if (top < 0) { + protyle.contentElement.scrollTop = protyle.contentElement.scrollTop + top; + protyle.scroll.lastScrollTop = protyle.contentElement.scrollTop + 1; + } + } else if (!startEndElement.endElement.parentElement.classList.contains("protyle-wysiwyg")) { + hideElements(["select"], protyle); + startEndElement.endElement.parentElement.classList.add("protyle-wysiwyg--select"); } } else { - const firstIndex = editElement.textContent.indexOf("\n"); - if (firstIndex === -1 || start <= firstIndex || start === editElement.textContent.replace("\n", " ").indexOf("\n")) { - setFirstNodeRange(editElement, range); - event.stopPropagation(); - event.preventDefault(); - return; - } else { - return; + startEndElement.endElement.classList.remove("protyle-wysiwyg--select"); + startEndElement.endElement.removeAttribute("select-end"); + const previousElement = getPreviousBlock(startEndElement.endElement); + if (previousElement) { + previousElement.setAttribute("select-end", "true") } } } - } - range.collapse(true); - hideElements(["toolbar"], protyle); - if (selectElements.length === 0) { - nodeElement.classList.add("protyle-wysiwyg--select"); - } else { - const previousElement = selectElements[0].previousElementSibling as HTMLElement; - if (previousElement && previousElement.getAttribute("data-node-id")) { - previousElement.classList.add("protyle-wysiwyg--select"); - const top = previousElement.getBoundingClientRect().top - protyle.contentElement.getBoundingClientRect().top; - if (top < 0) { - protyle.contentElement.scrollTop = protyle.contentElement.scrollTop + top; - protyle.scroll.lastScrollTop = protyle.contentElement.scrollTop + 1; - } - } else if (!selectElements[0].parentElement.classList.contains("protyle-wysiwyg")) { - hideElements(["select"], protyle); - selectElements[0].parentElement.classList.add("protyle-wysiwyg--select"); - } - } - const ids: string[] = []; - protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select").forEach(item => { - ids.push(item.getAttribute("data-node-id")); - }); - countBlockWord(ids, protyle.block.rootID); - event.stopPropagation(); - event.preventDefault(); + }) return; } if (matchHotKey("⇧↓", event)) { - const selectElements = protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select"); - if (selectElements.length > 0) { - event.stopPropagation(); - event.preventDefault(); - } else { - const editElement = getContenteditableElement(nodeElement); - const end = getSelectionOffset(nodeElement, editorElement, range).end; - if (end < editElement.textContent.length) { - if (end > editElement.textContent.lastIndexOf("\n")) { - setLastNodeRange(editElement, range, false); - event.stopPropagation(); - event.preventDefault(); - return; + downSelect({ + protyle, event, nodeElement, editorElement, range, + cb(selectElements) { + const startEndElement = getStartEndElement(selectElements) + if (startEndElement.startElement.getBoundingClientRect().top <= startEndElement.endElement.getBoundingClientRect().top) { + const nextElement = startEndElement.endElement.nextElementSibling as HTMLElement; + if (nextElement && nextElement.getAttribute("data-node-id")) { + nextElement.classList.add("protyle-wysiwyg--select"); + nextElement.setAttribute("select-end", "true"); + startEndElement.endElement.removeAttribute("select-end"); + const bottom = nextElement.getBoundingClientRect().bottom - protyle.contentElement.getBoundingClientRect().bottom; + if (bottom > 0) { + protyle.contentElement.scrollTop = protyle.contentElement.scrollTop + bottom; + protyle.scroll.lastScrollTop = protyle.contentElement.scrollTop - 1; + } + } else if (!startEndElement.endElement.parentElement.classList.contains("protyle-wysiwyg")) { + hideElements(["select"], protyle); + startEndElement.endElement.parentElement.classList.add("protyle-wysiwyg--select"); + } } else { - return; + startEndElement.endElement.classList.remove("protyle-wysiwyg--select"); + startEndElement.endElement.removeAttribute("select-end"); + const nextElement = getNextBlock(startEndElement.endElement); + if (nextElement) { + nextElement.setAttribute("select-end", "true") + } } } - } - range.collapse(false); - hideElements(["toolbar"], protyle); - const selectLastElement = selectElements[selectElements.length - 1]; - if (selectElements.length === 0) { - nodeElement.classList.add("protyle-wysiwyg--select"); - } else { - const nextElement = selectLastElement.nextElementSibling as HTMLElement; - if (nextElement && nextElement.getAttribute("data-node-id")) { - nextElement.classList.add("protyle-wysiwyg--select"); - const bottom = nextElement.getBoundingClientRect().bottom - protyle.contentElement.getBoundingClientRect().bottom; - if (bottom > 0) { - protyle.contentElement.scrollTop = protyle.contentElement.scrollTop + bottom; - protyle.scroll.lastScrollTop = protyle.contentElement.scrollTop - 1; - } - } else if (!selectLastElement.parentElement.classList.contains("protyle-wysiwyg")) { - hideElements(["select"], protyle); - selectLastElement.parentElement.classList.add("protyle-wysiwyg--select"); - } - } - const ids: string[] = []; - protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select").forEach(item => { - ids.push(item.getAttribute("data-node-id")); - }); - countBlockWord(ids, protyle.block.rootID); - event.stopPropagation(); - event.preventDefault(); + }) return; } @@ -1121,9 +1130,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { // 防止 ESC 时选中当前块 window.siyuan.menus.menu.remove(); } else { - protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select").forEach(item => { - item.classList.remove("protyle-wysiwyg--select"); - }); + hideElements(["select"], protyle); range.collapse(false); nodeElement.classList.add("protyle-wysiwyg--select"); countBlockWord([nodeElement.getAttribute("data-node-id")], protyle.block.rootID); diff --git a/app/src/protyle/wysiwyg/list.ts b/app/src/protyle/wysiwyg/list.ts index 780fe3a55..c2c84d3e4 100644 --- a/app/src/protyle/wysiwyg/list.ts +++ b/app/src/protyle/wysiwyg/list.ts @@ -50,6 +50,8 @@ export const listIndent = (protyle: IProtyle, liItemElements: Element[], range: range.insertNode(document.createElement("wbr")); liItemElements.forEach(item => { item.classList.remove("protyle-wysiwyg--select"); + item.removeAttribute("select-start"); + item.removeAttribute("select-end"); }); const html = previousElement.parentElement.outerHTML; if (previousElement.lastElementChild.previousElementSibling.getAttribute("data-type") === "NodeList") { @@ -297,6 +299,8 @@ export const listOutdent = (protyle: IProtyle, liItemElements: Element[], range: let previousElement: Element = liElement; liItemElements.forEach(item => { item.classList.remove("protyle-wysiwyg--select"); + item.removeAttribute("select-start"); + item.removeAttribute("select-end"); Array.from(item.children).forEach((blockElement, index) => { const id = blockElement.getAttribute("data-node-id"); if (!id) { @@ -379,6 +383,8 @@ export const listOutdent = (protyle: IProtyle, liItemElements: Element[], range: const previousID = liItemElements[0].previousElementSibling?.getAttribute("data-node-id"); liItemElements.forEach(item => { item.classList.remove("protyle-wysiwyg--select"); + item.removeAttribute("select-start"); + item.removeAttribute("select-end"); }); let startIndex; if (!liItemElements[0].previousElementSibling && liElement.getAttribute("data-subtype") === "o") { diff --git a/app/src/protyle/wysiwyg/remove.ts b/app/src/protyle/wysiwyg/remove.ts index 1775b0370..72f75b801 100644 --- a/app/src/protyle/wysiwyg/remove.ts +++ b/app/src/protyle/wysiwyg/remove.ts @@ -183,8 +183,8 @@ export const removeBlock = (protyle: IProtyle, blockElement: Element, range: Ran let sideElement = selectElements[0].previousElementSibling || selectElements[selectElements.length - 1].nextElementSibling; let listElement: Element; let topParentElement: Element; + hideElements(["select"], protyle); selectElements.find((item: HTMLElement) => { - item.classList.remove("protyle-wysiwyg--select"); const topElement = getTopAloneElement(item); topParentElement = topElement.parentElement; const id = topElement.getAttribute("data-node-id"); diff --git a/app/src/protyle/wysiwyg/transaction.ts b/app/src/protyle/wysiwyg/transaction.ts index 248bce64c..d6960ac49 100644 --- a/app/src/protyle/wysiwyg/transaction.ts +++ b/app/src/protyle/wysiwyg/transaction.ts @@ -638,6 +638,8 @@ export const turnsIntoOneTransaction = (options: { protyle: IProtyle, selectsEle let itemPreviousId: string; options.selectsElement.forEach((item, index) => { item.classList.remove("protyle-wysiwyg--select"); + item.removeAttribute("select-start"); + item.removeAttribute("select-end"); const itemId = item.getAttribute("data-node-id"); undoOperations.push({ action: "move", @@ -741,6 +743,8 @@ export const turnsIntoTransaction = (options: { setFold(options.protyle, item); } item.classList.remove("protyle-wysiwyg--select"); + item.removeAttribute("select-start") + item.removeAttribute("select-end") html += item.outerHTML; const id = item.getAttribute("data-node-id"); undoOperations.push({ @@ -858,6 +862,8 @@ export const updateBatchTransaction = (nodeElements: Element[], protyle: IProtyl nodeElements.forEach((element) => { const id = element.getAttribute("data-node-id"); element.classList.remove("protyle-wysiwyg--select"); + element.removeAttribute("select-start"); + element.removeAttribute("select-end"); undoOperations.push({ action: "update", id,