Browse Source

Merge pull request #233 from NateScarlet/init-with-element

支持直接使用 Element 初始化
Vanesssa 5 years ago
parent
commit
c23feb437a

+ 49 - 9
src/index.ts

@@ -37,9 +37,31 @@ class Vditor extends VditorMethod {
     public readonly version: string;
     public vditor: IVditor;
 
-    constructor(id: string, options?: IOptions) {
+    /**
+     * @param target 要挂载 Vditor 的元素或者元素 ID。
+     * @param options Vditor 参数
+     */
+    constructor(target: string | HTMLElement, options?: IOptions) {
         super();
         this.version = VDITOR_VERSION;
+        const id = typeof target === "string" ? target : undefined;
+        const el =
+            target instanceof HTMLElement
+                ? target
+                : document.getElementById(id);
+
+        let cacheKey: string | undefined;
+        if (options.cache === false) {
+            cacheKey = undefined;
+        } else if (typeof options.cache === "string") {
+            cacheKey = options.cache;
+        } else if (id) {
+            cacheKey = `vditor${id}`;
+        } else if (options.cache === true) {
+            throw new Error(
+                "Options cache must be a string when init without id.",
+            );
+        }
 
         const getOptions = new Options(options);
         const mergedOptions = getOptions.merge();
@@ -50,12 +72,13 @@ class Vditor extends VditorMethod {
         }
 
         this.vditor = {
+            cacheKey,
             currentMode: mergedOptions.mode,
             currentPreviewMode: mergedOptions.preview.mode,
-            id,
+            el,
             lute: undefined,
             options: mergedOptions,
-            originalInnerHTML: document.getElementById(id).innerHTML,
+            originalInnerHTML: el.innerHTML,
             tip: new Tip(),
         };
 
@@ -205,17 +228,34 @@ class Vditor extends VditorMethod {
 
     /** 清除缓存 */
     public clearCache() {
-        localStorage.removeItem("vditor" + this.vditor.id);
+        if (typeof this.vditor.cacheKey !== "string") {
+            return;
+        }
+        localStorage.removeItem(this.vditor.cacheKey);
     }
 
     /** 禁用缓存 */
     public disabledCache() {
-        this.vditor.options.cache = false;
+        this.vditor.cacheKey = undefined;
     }
 
-    /** 启用缓存 */
-    public enableCache() {
-        this.vditor.options.cache = true;
+    /** 启用缓存
+     * @param key 缓存 key,默认和初始化时相同。
+     */
+    public enableCache(key?: string) {
+        if (typeof key === "string") {
+            this.vditor.cacheKey = key;
+            return;
+        }
+        if (this.vditor.cacheKey) {
+            return;
+        }
+
+        if (this.vditor.el.id) {
+            this.vditor.cacheKey = `vditor${this.vditor.el.id}`;
+            return;
+        }
+        throw new Error("Missing cache key.");
     }
 
     /** HTML 转 md */
@@ -309,7 +349,7 @@ class Vditor extends VditorMethod {
         }
 
         if (!markdown) {
-            localStorage.removeItem("vditor" + this.vditor.id);
+            this.clearCache()
         }
     }
 }

+ 2 - 2
src/ts/ir/process.ts

@@ -51,8 +51,8 @@ export const processAfterRender = (vditor: IVditor, options = {
             vditor.counter.render(text.length, vditor.options.counter);
         }
 
-        if (vditor.options.cache) {
-            localStorage.setItem(`vditor${vditor.id}`, text);
+        if (vditor.cacheKey) {
+            localStorage.setItem(vditor.cacheKey, text);
         }
 
         if (vditor.devtools) {

+ 5 - 6
src/ts/resize/index.ts

@@ -15,10 +15,9 @@ export class Resize {
         this.element.addEventListener("mousedown", (event: MouseEvent) => {
 
             const documentSelf = document;
-            const vditorElement = document.getElementById(vditor.id);
             const y = event.clientY;
-            const height = vditorElement.offsetHeight;
-            const minHeight = 63 + vditorElement.querySelector(".vditor-toolbar").clientHeight;
+            const height = vditor.el.offsetHeight;
+            const minHeight = 63 + vditor.el.querySelector(".vditor-toolbar").clientHeight;
             documentSelf.ondragstart = () => false;
 
             if (window.captureEvents) {
@@ -29,9 +28,9 @@ export class Resize {
 
             documentSelf.onmousemove = (moveEvent: MouseEvent) => {
                 if (vditor.options.resize.position === "top") {
-                    vditorElement.style.height = Math.max(minHeight, height + (y - moveEvent.clientY)) + "px";
+                    vditor.el.style.height = Math.max(minHeight, height + (y - moveEvent.clientY)) + "px";
                 } else {
-                    vditorElement.style.height = Math.max(minHeight, height + (moveEvent.clientY - y)) + "px";
+                    vditor.el.style.height = Math.max(minHeight, height + (moveEvent.clientY - y)) + "px";
                 }
                 if (vditor.options.typewriterMode) {
                     vditor.sv.element.style.paddingBottom =
@@ -41,7 +40,7 @@ export class Resize {
 
             documentSelf.onmouseup = () => {
                 if (vditor.options.resize.after) {
-                    vditor.options.resize.after(vditorElement.offsetHeight - height);
+                    vditor.options.resize.after(vditor.el.offsetHeight - height);
                 }
 
                 if (window.captureEvents) {

+ 2 - 2
src/ts/sv/inputEvent.ts

@@ -14,8 +14,8 @@ export const inputEvent = (vditor: IVditor, options = {
     if (vditor.hint && options.enableHint) {
         vditor.hint.render(vditor);
     }
-    if (vditor.options.cache) {
-        localStorage.setItem(`vditor${vditor.id}`, getMarkdown(vditor));
+    if (vditor.cacheKey) {
+        localStorage.setItem(vditor.cacheKey, getMarkdown(vditor));
     }
     if (vditor.preview) {
         vditor.preview.render(vditor);

+ 4 - 5
src/ts/toolbar/Fullscreen.ts

@@ -13,10 +13,9 @@ export class Fullscreen extends MenuItem {
     public _bindEvent(vditor: IVditor, menuItem: IMenuItem) {
         this.element.children[0].addEventListener(getEventName(), function(event) {
             event.preventDefault();
-            const vditorElement = document.getElementById(vditor.id);
-            if (vditorElement.className.indexOf("vditor--fullscreen") > -1) {
+            if (vditor.el.className.indexOf("vditor--fullscreen") > -1) {
                 this.innerHTML = menuItem.icon || fullscreenSVG;
-                vditorElement.classList.remove("vditor--fullscreen");
+                vditor.el.classList.remove("vditor--fullscreen");
                 Object.keys(vditor.toolbar.elements).forEach((key) => {
                     const svgElement = vditor.toolbar.elements[key].firstChild as HTMLElement;
                     if (svgElement) {
@@ -25,7 +24,7 @@ export class Fullscreen extends MenuItem {
                 });
             } else {
                 this.innerHTML = menuItem.icon || contractSVG;
-                vditorElement.classList.add("vditor--fullscreen");
+                vditor.el.classList.add("vditor--fullscreen");
                 Object.keys(vditor.toolbar.elements).forEach((key) => {
                     const svgElement = vditor.toolbar.elements[key].firstChild as HTMLElement;
                     if (svgElement) {
@@ -39,7 +38,7 @@ export class Fullscreen extends MenuItem {
             }
 
             if (menuItem.click) {
-                menuItem.click(vditorElement.classList.contains("vditor--fullscreen"));
+                menuItem.click(vditor.el.classList.contains("vditor--fullscreen"));
             }
         });
     }

+ 13 - 11
src/ts/ui/initUI.ts

@@ -6,20 +6,19 @@ import {renderDomByMd} from "../wysiwyg/renderDomByMd";
 import {setTheme} from "./setTheme";
 
 export const initUI = (vditor: IVditor) => {
-    const vditorElement = document.getElementById(vditor.id);
-    vditorElement.innerHTML = "";
-    vditorElement.classList.add("vditor");
+    vditor.el.innerHTML = "";
+    vditor.el.classList.add("vditor");
     setTheme(vditor);
     if (typeof vditor.options.height === "number") {
-        vditorElement.style.height = vditor.options.height + "px";
+        vditor.el.style.height = vditor.options.height + "px";
     }
     if (typeof vditor.options.width === "number") {
-        vditorElement.style.width = vditor.options.width + "px";
+        vditor.el.style.width = vditor.options.width + "px";
     } else {
-        vditorElement.style.width = vditor.options.width;
+        vditor.el.style.width = vditor.options.width;
     }
 
-    vditorElement.appendChild(vditor.toolbar.element);
+    vditor.el.appendChild(vditor.toolbar.element);
 
     const contentElement = document.createElement("div");
     contentElement.className = "vditor-content";
@@ -56,7 +55,7 @@ export const initUI = (vditor: IVditor) => {
 
     contentElement.appendChild(vditor.tip.element);
 
-    vditorElement.appendChild(contentElement);
+    vditor.el.appendChild(contentElement);
 
     afterRender(vditor, contentElement);
 
@@ -95,13 +94,16 @@ const afterRender = (vditor: IVditor, contentElement: HTMLElement) => {
     });
 
     // set default value
-    let initValue = localStorage.getItem("vditor" + vditor.id);
-    if (!vditor.options.cache || !initValue) {
+    let initValue =
+        typeof vditor.cacheKey === "string"
+            ? localStorage.getItem(vditor.cacheKey)
+            : "";
+    if (!vditor.cacheKey || !initValue) {
         if (vditor.options.value) {
             initValue = vditor.options.value;
         } else if (vditor.originalInnerHTML) {
             initValue = html2md(vditor, vditor.originalInnerHTML);
-        } else if (!vditor.options.cache) {
+        } else if (!vditor.cacheKey) {
             initValue = "";
         }
     }

+ 2 - 3
src/ts/ui/setTheme.ts

@@ -1,14 +1,13 @@
 export const setTheme = (vditor: IVditor) => {
-    const vditorElement = document.getElementById(vditor.id);
     if (vditor.options.theme === "dark") {
-        vditorElement.classList.add("vditor--dark");
+        vditor.el.classList.add("vditor--dark");
         if (vditor.preview) {
             vditor.preview.element.firstElementChild.classList.add("vditor-reset--dark");
         }
         vditor.wysiwyg.element.classList.add("vditor-reset--dark");
         vditor.ir.element.classList.add("vditor-reset--dark");
     } else {
-        vditorElement.classList.remove("vditor--dark");
+        vditor.el.classList.remove("vditor--dark");
         if (vditor.preview) {
             vditor.preview.element.firstElementChild.classList.remove("vditor-reset--dark");
         }

+ 2 - 2
src/ts/wysiwyg/afterRenderEvent.ts

@@ -24,8 +24,8 @@ export const afterRenderEvent = (vditor: IVditor, options = {
             vditor.counter.render(text.length, vditor.options.counter);
         }
 
-        if (vditor.options.cache) {
-            localStorage.setItem(`vditor${vditor.id}`, text);
+        if (vditor.cacheKey) {
+            localStorage.setItem(vditor.cacheKey, text);
         }
 
         if (vditor.devtools) {

+ 19 - 4
types/index.d.ts

@@ -303,8 +303,22 @@ interface IOptions {
     resize?: IResize;
     /** 计数器。默认值: '0' */
     counter?: number;
-    /** 是否使用 localStorage 进行缓存。默认值: 'auto' */
-    cache?: boolean;
+    /** 
+     * 是否使用 localStorage 进行缓存。
+     * 
+     * 为 string 时使用传入值作为 key 。
+     * 
+     * 使用元素 id 初始化时:
+     *    true:  启用,`vditor${id}` 作为 key。
+     *    false: 禁用。
+     *    默认: true
+     * 
+     * 使用元素初始化时:
+     *    true:  报错,必须使用 string。
+     *    false: 禁用。
+     *    默认: false
+     */
+    cache?: boolean | string;
     /** 编辑模式。默认值: 'wysiwyg' */
     mode?: "wysiwyg" | "sv" | "ir";
     /** @link https://hacpai.com/article/1549638745630#options-preview */
@@ -349,8 +363,9 @@ interface IEChart {
 }
 
 interface IVditor {
-    id: string;
-    options: IOptions;
+    el: HTMLElement;
+    cacheKey?: string;
+    options: Omit<IOptions, "cache">;
     originalInnerHTML: string;
     lute: ILute;
     currentMode: "sv" | "wysiwyg" | "ir";