Liyuan Li 5 years ago
parent
commit
ec9613bad9

+ 1 - 0
CHANGELOG.md

@@ -51,6 +51,7 @@
 
 ### v3.0.7 / 2020-03-xx
 
+* [251](https://github.com/Vanessa219/vditor/issues/251) 所见即所得模式下,光标后图片工具层会遮挡文字 `改进功能`
 * [249](https://github.com/Vanessa219/vditor/issues/249) 代码块语言选择优化 `改进功能`
 * [211](https://github.com/Vanessa219/vditor/issues/211) Heading when backspace (Windows Firefox) `修复缺陷`
 * [239](https://github.com/Vanessa219/vditor/issues/239) be converted after spaces in FF `修复缺陷`

+ 1 - 1
src/ts/util/fixBrowserBehavior.ts

@@ -936,7 +936,7 @@ export const fixDelete = (vditor: IVditor, range: Range, event: KeyboardEvent, p
     }
     // table 后删除 https://github.com/Vanessa219/vditor/issues/243
     const tableElement = pElement.previousElementSibling;
-    if (event.key === "Backspace" && tableElement.tagName === "TABLE" &&
+    if (tableElement && event.key === "Backspace" && tableElement.tagName === "TABLE" &&
         getSelectPosition(pElement, range).start === 0) {
         const lastCellElement = tableElement.lastElementChild.lastElementChild.lastElementChild;
         lastCellElement.innerHTML = lastCellElement.innerHTML.trimLeft() + "<wbr>" + pElement.textContent.trim();

+ 69 - 76
src/ts/wysiwyg/highlightToolbar.ts

@@ -21,7 +21,6 @@ import {
 } from "../util/hasClosest";
 import {getEditorRange, selectIsEditor, setRangeByWbr, setSelectionFocus} from "../util/selection";
 import {afterRenderEvent} from "./afterRenderEvent";
-import {nextIsImg} from "./inlineTag";
 import {processCodeRender} from "./processCodeRender";
 
 export const highlightToolbar = (vditor: IVditor) => {
@@ -459,80 +458,6 @@ export const highlightToolbar = (vditor: IVditor) => {
             setPopoverPosition(vditor, footnotesRefElement);
         }
 
-        // img popover
-        let imgElement = nextIsImg(range) as HTMLElement;
-        if ((range.startContainer.nodeType !== 3 && range.startContainer.childNodes.length > range.startOffset &&
-            range.startContainer.childNodes[range.startOffset].nodeName === "IMG") || imgElement) {
-            // 光标在图片前面,或在文字后面
-            if (!imgElement) {
-                imgElement = range.startContainer.childNodes[range.startOffset] as HTMLElement;
-            }
-            vditor.wysiwyg.popover.innerHTML = "";
-            const updateImg = () => {
-                imgElement.setAttribute("src", input.value);
-                imgElement.setAttribute("alt", alt.value);
-                if (aHref.value === "") {
-                    if (imgElement.parentElement.nodeName === "A") {
-                        imgElement.parentElement.replaceWith(imgElement);
-                    }
-                } else {
-                    if (imgElement.parentElement.nodeName === "A") {
-                        imgElement.parentElement.setAttribute("href", aHref.value);
-                    } else {
-                        const link = document.createElement("a");
-                        link.innerHTML = imgElement.outerHTML;
-                        link.setAttribute("href", aHref.value);
-
-                        const linkElement = imgElement.parentNode.insertBefore(link, imgElement);
-                        imgElement.remove();
-                        imgElement = linkElement.querySelector("img");
-                    }
-                }
-            };
-
-            const inputWrap = document.createElement("span");
-            inputWrap.setAttribute("aria-label", i18n[vditor.options.lang].imageURL);
-            inputWrap.className = "vditor-tooltipped vditor-tooltipped__n";
-            const input = document.createElement("input");
-            inputWrap.appendChild(input);
-            input.className = "vditor-input";
-            input.setAttribute("placeholder", i18n[vditor.options.lang].imageURL);
-            input.value = imgElement.getAttribute("src") || "";
-            input.oninput = () => {
-                updateImg();
-            };
-            const altWrap = document.createElement("span");
-            altWrap.setAttribute("aria-label", i18n[vditor.options.lang].alternateText);
-            altWrap.className = "vditor-tooltipped vditor-tooltipped__n";
-            const alt = document.createElement("input");
-            altWrap.appendChild(alt);
-            alt.className = "vditor-input";
-            alt.setAttribute("placeholder", i18n[vditor.options.lang].alternateText);
-            alt.style.width = "52px";
-            alt.value = imgElement.getAttribute("alt") || "";
-            alt.oninput = () => {
-                updateImg();
-            };
-
-            const aHrefWrap = document.createElement("span");
-            aHrefWrap.setAttribute("aria-label", i18n[vditor.options.lang].link);
-            aHrefWrap.className = "vditor-tooltipped vditor-tooltipped__n";
-            const aHref = document.createElement("input");
-            aHrefWrap.appendChild(aHref);
-            aHref.className = "vditor-input";
-            aHref.setAttribute("placeholder", i18n[vditor.options.lang].link);
-            aHref.value =
-                imgElement.parentElement.nodeName === "A" ? imgElement.parentElement.getAttribute("href") : "";
-            aHref.oninput = () => {
-                updateImg();
-            };
-            vditor.wysiwyg.popover.insertAdjacentElement("beforeend", inputWrap);
-            vditor.wysiwyg.popover.insertAdjacentElement("beforeend", altWrap);
-            vditor.wysiwyg.popover.insertAdjacentElement("beforeend", aHrefWrap);
-
-            setPopoverPosition(vditor, imgElement);
-        }
-
         const blockRenderElement = hasClosestByClassName(typeElement, "vditor-wysiwyg__block");
         if (blockRenderElement) {
             // block popover: math-inline, math-block, html-block, html-inline, code-block
@@ -643,7 +568,7 @@ export const highlightToolbar = (vditor: IVditor) => {
             genAPopover(vditor, aElement);
         }
 
-        if (!blockquoteElement && !imgElement && !topListElement && !tableElement && !blockRenderElement && !aElement
+        if (!blockquoteElement && !topListElement && !tableElement && !blockRenderElement && !aElement
             && !linkRefElement && !footnotesRefElement && !headingElement && !tocElement) {
             vditor.wysiwyg.popover.style.display = "none";
         }
@@ -811,3 +736,71 @@ export const genAPopover = (vditor: IVditor, aElement: HTMLElement) => {
     vditor.wysiwyg.popover.insertAdjacentElement("beforeend", input2Wrap);
     setPopoverPosition(vditor, aElement);
 };
+
+export const genImagePopover = (event: Event, vditor: IVditor) => {
+    let imgElement = event.target as HTMLImageElement
+    vditor.wysiwyg.popover.innerHTML = "";
+    const updateImg = () => {
+        imgElement.setAttribute("src", inputElement.value);
+        imgElement.setAttribute("alt", alt.value);
+        if (aHref.value === "") {
+            if (imgElement.parentElement.nodeName === "A") {
+                imgElement.parentElement.replaceWith(imgElement);
+            }
+        } else {
+            if (imgElement.parentElement.nodeName === "A") {
+                imgElement.parentElement.setAttribute("href", aHref.value);
+            } else {
+                const link = document.createElement("a");
+                link.innerHTML = imgElement.outerHTML;
+                link.setAttribute("href", aHref.value);
+
+                const linkElement = imgElement.parentNode.insertBefore(link, imgElement);
+                imgElement.remove();
+                imgElement = linkElement.querySelector("img");
+            }
+        }
+    };
+
+    const inputWrap = document.createElement("span");
+    inputWrap.setAttribute("aria-label", i18n[vditor.options.lang].imageURL);
+    inputWrap.className = "vditor-tooltipped vditor-tooltipped__n";
+    const inputElement = document.createElement("input");
+    inputWrap.appendChild(inputElement);
+    inputElement.className = "vditor-input";
+    inputElement.setAttribute("placeholder", i18n[vditor.options.lang].imageURL);
+    inputElement.value = imgElement.getAttribute("src") || "";
+    inputElement.oninput = () => {
+        updateImg();
+    };
+    const altWrap = document.createElement("span");
+    altWrap.setAttribute("aria-label", i18n[vditor.options.lang].alternateText);
+    altWrap.className = "vditor-tooltipped vditor-tooltipped__n";
+    const alt = document.createElement("input");
+    altWrap.appendChild(alt);
+    alt.className = "vditor-input";
+    alt.setAttribute("placeholder", i18n[vditor.options.lang].alternateText);
+    alt.style.width = "52px";
+    alt.value = imgElement.getAttribute("alt") || "";
+    alt.oninput = () => {
+        updateImg();
+    };
+
+    const aHrefWrap = document.createElement("span");
+    aHrefWrap.setAttribute("aria-label", i18n[vditor.options.lang].link);
+    aHrefWrap.className = "vditor-tooltipped vditor-tooltipped__n";
+    const aHref = document.createElement("input");
+    aHrefWrap.appendChild(aHref);
+    aHref.className = "vditor-input";
+    aHref.setAttribute("placeholder", i18n[vditor.options.lang].link);
+    aHref.value =
+        imgElement.parentElement.nodeName === "A" ? imgElement.parentElement.getAttribute("href") : "";
+    aHref.oninput = () => {
+        updateImg();
+    };
+    vditor.wysiwyg.popover.insertAdjacentElement("beforeend", inputWrap);
+    vditor.wysiwyg.popover.insertAdjacentElement("beforeend", altWrap);
+    vditor.wysiwyg.popover.insertAdjacentElement("beforeend", aHrefWrap);
+
+    setPopoverPosition(vditor, imgElement);
+}

+ 8 - 10
src/ts/wysiwyg/index.ts

@@ -13,10 +13,9 @@ import {
     insertHTML,
     setRangeByWbr,
     setSelectionByPosition,
-    setSelectionFocus,
 } from "../util/selection";
 import {afterRenderEvent} from "./afterRenderEvent";
-import {highlightToolbar} from "./highlightToolbar";
+import {genImagePopover, highlightToolbar} from "./highlightToolbar";
 import {getRenderElementNextNode, modifyPre} from "./inlineTag";
 import {input} from "./input";
 import {processCodeRender, showCode} from "./processCodeRender";
@@ -295,12 +294,13 @@ class WYSIWYG {
             input(vditor, range, event);
         });
 
-        this.element.addEventListener("click", (event: MouseEvent & { target: HTMLInputElement }) => {
+        this.element.addEventListener("click", (event: MouseEvent & { target: HTMLElement }) => {
             if (event.target.tagName === "INPUT") {
-                if (event.target.checked) {
-                    event.target.setAttribute("checked", "checked");
+                const checkElement = event.target as HTMLInputElement;
+                if (checkElement.checked) {
+                    checkElement.setAttribute("checked", "checked");
                 } else {
-                    event.target.removeAttribute("checked");
+                    checkElement.removeAttribute("checked");
                 }
                 this.preventInput = true;
                 afterRenderEvent(vditor);
@@ -308,10 +308,8 @@ class WYSIWYG {
             }
 
             if (event.target.tagName === "IMG") {
-                const range = this.element.ownerDocument.createRange();
-                range.selectNode(event.target);
-                range.collapse(true);
-                setSelectionFocus(range);
+                genImagePopover(event, vditor)
+                return;
             }
 
             highlightToolbar(vditor);

+ 0 - 14
src/ts/wysiwyg/inlineTag.ts

@@ -28,20 +28,6 @@ export const nextIsCode = (range: Range) => {
     return false;
 };
 
-export const nextIsImg = (range: Range) => {
-    if (range.startContainer.nodeType === 3 && range.startContainer.textContent.length === range.startOffset) {
-        let nextNode: HTMLElement = range.startContainer.nextSibling as HTMLElement;
-        while (nextNode && nextNode.textContent === "" && nextNode.nodeType === 3) {
-            nextNode = nextNode.nextSibling as HTMLElement;
-        }
-        if (nextNode && nextNode.nodeType !== 3 && nextNode.tagName === "IMG") {
-            return nextNode;
-        }
-        return false;
-    }
-    return false;
-};
-
 export const getNextHTML = (node: Node) => {
     let html = "";
     let nextNode = node.nextSibling;