Browse Source

:art: #721 add span

Liyuan Li 5 năm trước cách đây
mục cha
commit
f99ba57360

+ 6 - 3
demo/index.html

@@ -67,12 +67,15 @@
         Light Mode
         Light Mode
     </button>
     </button>
 </div>
 </div>
-<div id="vditor">
+<div style="display: flex">
+    <div id="vditor" style="flex: 1">
 <h1>Vditor</h1>
 <h1>Vditor</h1>
 <ul>
 <ul>
-<li>foo</li>
-<li>bar</li>
+    <li>foo</li>
+    <li>bar</li>
 </ul>
 </ul>
+    </div>
+    <div id="comments" style="width: 300px"></div>
 </div>
 </div>
 </body>
 </body>
 </html>
 </html>

+ 17 - 0
demo/index.js

@@ -49,6 +49,15 @@ if (window.innerWidth < 768) {
     }]
     }]
 }
 }
 
 
+const bindCommentEvent = (input) => {
+  input.addEventListener("blur", () => {
+    if (input.value.trim() === "") {
+      window.vditor.removeCommentIds([input.getAttribute("data-id")])
+      input.remove();
+    }
+  })
+}
+
 window.vditor = new Vditor('vditor', {
 window.vditor = new Vditor('vditor', {
   _lutePath: `http://192.168.0.107:9090/lute.min.js?${new Date().getTime()}`,
   _lutePath: `http://192.168.0.107:9090/lute.min.js?${new Date().getTime()}`,
   // _lutePath: 'src/js/lute/lute.min.js',
   // _lutePath: 'src/js/lute/lute.min.js',
@@ -67,6 +76,14 @@ window.vditor = new Vditor('vditor', {
   },
   },
   comment: {
   comment: {
     enable: true,
     enable: true,
+    add (id, text) {
+      const inputElement = document.createElement("input")
+      inputElement.setAttribute("data-id", id);
+      inputElement.value = text
+      bindCommentEvent(inputElement);
+      document.getElementById("comments").insertAdjacentElement("beforeend", inputElement);
+      inputElement.focus();
+    }
   },
   },
   toolbarConfig: {
   toolbarConfig: {
     pin: true,
     pin: true,

+ 5 - 0
src/assets/scss/_reset.scss

@@ -265,6 +265,11 @@
     }
     }
   }
   }
 
 
+  &-comment {
+    background-color: rgb(250, 241, 209);
+    border-bottom: 2px solid rgb(255, 198, 10);
+  }
+
   &-task {
   &-task {
     list-style: none !important;
     list-style: none !important;
     word-break: break-all;
     word-break: break-all;

+ 5 - 0
src/index.ts

@@ -368,6 +368,11 @@ class Vditor extends VditorMethod {
 
 
     }
     }
 
 
+    /** 删除评论 */
+    public removeCommentIds(ids: string[]) {
+
+    }
+
     /** 评论之后文字添加下划线样式 */
     /** 评论之后文字添加下划线样式 */
     public afterCommentId(id: string) {
     public afterCommentId(id: string) {
 
 

+ 17 - 14
src/ts/util/editorCommonEvent.ts

@@ -25,13 +25,14 @@ export const focusEvent = (vditor: IVditor, editorElement: HTMLElement) => {
 };
 };
 
 
 export const blurEvent = (vditor: IVditor, editorElement: HTMLElement) => {
 export const blurEvent = (vditor: IVditor, editorElement: HTMLElement) => {
-    editorElement.addEventListener("blur", () => {
+    editorElement.addEventListener("blur", (event) => {
         if (vditor.currentMode === "ir") {
         if (vditor.currentMode === "ir") {
             const expandElement = vditor.ir.element.querySelector(".vditor-ir__node--expand");
             const expandElement = vditor.ir.element.querySelector(".vditor-ir__node--expand");
             if (expandElement) {
             if (expandElement) {
                 expandElement.classList.remove("vditor-ir__node--expand");
                 expandElement.classList.remove("vditor-ir__node--expand");
             }
             }
-        } else if (vditor.currentMode === "wysiwyg") {
+        } else if (vditor.currentMode === "wysiwyg" &&
+            !vditor.wysiwyg.selectPopover.contains(event.relatedTarget as HTMLElement)) {
             vditor.wysiwyg.hideComment();
             vditor.wysiwyg.hideComment();
         }
         }
         if (vditor.options.blur) {
         if (vditor.options.blur) {
@@ -199,19 +200,21 @@ export const hotkeyEvent = (vditor: IVditor, editorElement: HTMLElement) => {
 export const selectEvent = (vditor: IVditor, editorElement: HTMLElement) => {
 export const selectEvent = (vditor: IVditor, editorElement: HTMLElement) => {
     editorElement.addEventListener("selectstart", (event: Event) => {
     editorElement.addEventListener("selectstart", (event: Event) => {
         editorElement.onmouseup = () => {
         editorElement.onmouseup = () => {
-            const selectText = getSelectText(vditor[vditor.currentMode].element);
-            if (selectText) {
-                if (vditor.currentMode === "wysiwyg" && vditor.options.comment.enable) {
-                    vditor.wysiwyg.showComment();
-                }
-                if (vditor.options.select) {
-                    vditor.options.select(selectText);
-                }
-            } else {
-                if (vditor.currentMode === "wysiwyg") {
-                    vditor.wysiwyg.hideComment();
+            setTimeout(() => { // 鼠标放开后 range 没有即时更新
+                const selectText = getSelectText(vditor[vditor.currentMode].element);
+                if (selectText.trim()) {
+                    if (vditor.currentMode === "wysiwyg" && vditor.options.comment.enable) {
+                        vditor.wysiwyg.showComment();
+                    }
+                    if (vditor.options.select) {
+                        vditor.options.select(selectText);
+                    }
+                } else {
+                    if (vditor.currentMode === "wysiwyg" && vditor.options.comment.enable) {
+                        vditor.wysiwyg.hideComment();
+                    }
                 }
                 }
-            }
+            })
         };
         };
     });
     });
 };
 };

+ 19 - 1
src/ts/wysiwyg/index.ts

@@ -64,10 +64,28 @@ class WYSIWYG {
         dropEvent(vditor, this.element);
         dropEvent(vditor, this.element);
         copyEvent(vditor, this.element, this.copy);
         copyEvent(vditor, this.element, this.copy);
         cutEvent(vditor, this.element, this.copy);
         cutEvent(vditor, this.element, this.copy);
+
+        if (vditor.options.comment.enable) {
+            this.selectPopover.querySelector("button").onclick = () => {
+                const id = Lute.NewNodeID()
+                const range = getSelection().getRangeAt(0);
+                vditor.options.comment.add(id, range.toString());
+                const contents = range.cloneContents();
+                contents.querySelectorAll("span").forEach((item) => {
+                    console.log(item);
+                });
+                range.deleteContents();
+                const spanElement = document.createElement("span")
+                spanElement.classList.add("comment-id-" + id, "vditor-comment");
+                spanElement.setAttribute("data-cmtid", id);
+                spanElement.append(contents);
+                range.insertNode(spanElement);
+                this.hideComment();
+            }
+        }
     }
     }
 
 
     public showComment() {
     public showComment() {
-        const range = getSelection().getRangeAt(0);
         const position = getCursorPosition(this.element);
         const position = getCursorPosition(this.element);
         this.selectPopover.setAttribute("style", `left:${position.left}px;display:block;top:${Math.max(-8, position.top - 21 - this.element.scrollTop)}px`);
         this.selectPopover.setAttribute("style", `left:${position.left}px;display:block;top:${Math.max(-8, position.top - 21 - this.element.scrollTop)}px`);
     }
     }

+ 4 - 1
types/index.d.ts

@@ -112,6 +112,8 @@ declare class Lute {
 
 
     public static GetHeadingID(node: ILuteNode): string;
     public static GetHeadingID(node: ILuteNode): string;
 
 
+    public static NewNodeID(): string;
+
     private constructor();
     private constructor();
 
 
     public SetJSRenderers(options?: {
     public SetJSRenderers(options?: {
@@ -507,7 +509,7 @@ interface IOptions {
     /** 评论 */
     /** 评论 */
     comment?: {
     comment?: {
         enable: boolean
         enable: boolean
-        add?(id: string): void
+        add?(id: string, text: string): void
         remove?(ids: string[]): void;
         remove?(ids: string[]): void;
     };
     };
     /** 主题。默认值: 'classic' */
     /** 主题。默认值: 'classic' */
@@ -612,6 +614,7 @@ interface IVditor {
     };
     };
     wysiwyg?: {
     wysiwyg?: {
         element: HTMLPreElement,
         element: HTMLPreElement,
+        selectPopover: HTMLDivElement,
         popover: HTMLDivElement,
         popover: HTMLDivElement,
         afterRenderTimeoutId: number,
         afterRenderTimeoutId: number,
         hlToolbarTimeoutId: number,
         hlToolbarTimeoutId: number,