From 0d4a29bb5ba8b62ac11a09d3f814abcb1fcf46be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=A6=8F=E6=9C=8B?= Date: Thu, 8 Jul 2021 14:12:45 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20readOnly=20=E6=97=B6=E8=8F=9C=E5=8D=95?= =?UTF-8?q?=E8=BF=98=E5=8F=AF=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/create/create-editor.ts | 7 +------ packages/core/src/editor/dom-editor.ts | 4 ++-- packages/core/src/editor/plugins/with-dom.ts | 8 +++++++- packages/core/src/menus/bar-item/BaseButton.ts | 10 ++++++++-- packages/core/src/menus/bar-item/Select.ts | 9 +++++++-- packages/core/src/menus/bar-item/index.ts | 2 +- packages/core/src/menus/bar/HoverBar.ts | 6 +++--- packages/core/src/menus/bar/Toolbar.ts | 8 ++++---- packages/core/src/text-area/TextArea.ts | 6 +++--- packages/core/src/utils/weak-maps.ts | 1 - packages/editor/examples/index.html | 6 +++++- 11 files changed, 41 insertions(+), 26 deletions(-) diff --git a/packages/core/src/create/create-editor.ts b/packages/core/src/create/create-editor.ts index be44c0537..c4ccc7840 100644 --- a/packages/core/src/create/create-editor.ts +++ b/packages/core/src/create/create-editor.ts @@ -21,7 +21,6 @@ import { EDITOR_TO_CONFIG, HOVER_BAR_TO_EDITOR, EDITOR_TO_HOVER_BAR, - IS_READ_ONLY, } from '../utils/weak-maps' type PluginFnType = (editor: T) => T @@ -93,7 +92,7 @@ export default function (option: ICreateOption) { } else { editor.children = genDefaultContent() } - textarea.onEditorChange() // 初始化时触发一次,以便能初始化 textarea DOM 和 selection + textarea.changeViewState() // 初始化时触发一次,以便能初始化 textarea DOM 和 selection // 触发生命周期 const { onCreated, onChange, onDestroyed } = editorConfig @@ -107,10 +106,6 @@ export default function (option: ICreateOption) { editor.on('destroyed', () => onDestroyed(editor)) } - // 记录编辑状态 - const { readOnly } = editorConfig - IS_READ_ONLY.set(editor, !!readOnly) - // 创建完毕,异步触发 created promiseResolveThen(() => editor.emit('created')) diff --git a/packages/core/src/editor/dom-editor.ts b/packages/core/src/editor/dom-editor.ts index e31d12526..0819e55d3 100644 --- a/packages/core/src/editor/dom-editor.ts +++ b/packages/core/src/editor/dom-editor.ts @@ -14,7 +14,6 @@ import { EDITOR_TO_ELEMENT, ELEMENT_TO_NODE, IS_FOCUSED, - IS_READ_ONLY, KEY_TO_ELEMENT, NODE_TO_INDEX, NODE_TO_KEY, @@ -114,7 +113,8 @@ export const DomEditor = { * Check if the editor is in read-only mode. */ isReadOnly(editor: IDomEditor): boolean { - return !!IS_READ_ONLY.get(editor) + const config = editor.getConfig() + return config.readOnly }, /** diff --git a/packages/core/src/editor/plugins/with-dom.ts b/packages/core/src/editor/plugins/with-dom.ts index 76f028720..c775d1d60 100644 --- a/packages/core/src/editor/plugins/with-dom.ts +++ b/packages/core/src/editor/plugins/with-dom.ts @@ -347,7 +347,13 @@ export const withDOM = (editor: T) => { // 手动更新试图 e.updateView = () => { const textarea = DomEditor.getTextarea(e) - textarea.onEditorChange() + textarea.changeViewState() + + const toolbar = DomEditor.getToolbar(e) + toolbar && toolbar.changeToolbarState() + + const hoverbar = DomEditor.getHoverbar(e) + hoverbar && hoverbar.changeHoverbarState() } // destroy diff --git a/packages/core/src/menus/bar-item/BaseButton.ts b/packages/core/src/menus/bar-item/BaseButton.ts index 759b89df5..eb4aa34e7 100644 --- a/packages/core/src/menus/bar-item/BaseButton.ts +++ b/packages/core/src/menus/bar-item/BaseButton.ts @@ -9,6 +9,7 @@ import { IBarItem, getEditorInstance } from './index' import { clearSvgStyle } from '../helpers/helpers' import { promiseResolveThen } from '../../utils/util' import { addTooltip } from './tooltip' +import { DomEditor } from '../../editor/dom-editor' abstract class BaseButton implements IBarItem { readonly $elem: Dom7Array = $(`
`) @@ -99,7 +100,12 @@ abstract class BaseButton implements IBarItem { private setDisabled() { const editor = getEditorInstance(this) const { $button } = this - const disabled = this.menu.isDisabled(editor) + let disabled = this.menu.isDisabled(editor) + + if (editor.selection == null || DomEditor.isReadOnly(editor)) { + // 未选中,或者 readOnly ,强行设置为 disabled + disabled = true + } const className = 'disabled' if (disabled) { @@ -113,7 +119,7 @@ abstract class BaseButton implements IBarItem { this.disabled = disabled // 记录下来 } - onSelectionChange() { + changeMenuState() { this.setActive() this.setDisabled() } diff --git a/packages/core/src/menus/bar-item/Select.ts b/packages/core/src/menus/bar-item/Select.ts index 26e7fd97f..9301f9bdb 100644 --- a/packages/core/src/menus/bar-item/Select.ts +++ b/packages/core/src/menus/bar-item/Select.ts @@ -130,9 +130,14 @@ class BarItemSelect implements IBarItem { private setDisabled() { const editor = getEditorInstance(this) const menu = this.menu - const disabled = menu.isDisabled(editor) + let disabled = menu.isDisabled(editor) const $button = this.$button + if (editor.selection == null || DomEditor.isReadOnly(editor)) { + // 未选中,或者 readOnly ,强行设置为 disabled + disabled = true + } + const className = 'disabled' if (disabled) { // 设置为 disabled @@ -145,7 +150,7 @@ class BarItemSelect implements IBarItem { this.disabled = disabled // 记录下来 } - onSelectionChange() { + changeMenuState() { this.setSelectedValue() this.setDisabled() } diff --git a/packages/core/src/menus/bar-item/index.ts b/packages/core/src/menus/bar-item/index.ts index 6d9280e37..ba34b51a4 100644 --- a/packages/core/src/menus/bar-item/index.ts +++ b/packages/core/src/menus/bar-item/index.ts @@ -18,7 +18,7 @@ type MenuType = IButtonMenu | ISelectMenu | IDropPanelMenu | IModalMenu export interface IBarItem { $elem: Dom7Array menu: MenuType - onSelectionChange: () => void + changeMenuState: () => void } // menu -> barItem diff --git a/packages/core/src/menus/bar/HoverBar.ts b/packages/core/src/menus/bar/HoverBar.ts index a5e58f77e..eba9610ed 100644 --- a/packages/core/src/menus/bar/HoverBar.ts +++ b/packages/core/src/menus/bar/HoverBar.ts @@ -37,7 +37,7 @@ class HoverBar { textarea.$textAreaContainer.append($elem) // 绑定 editor onchange - editor.on('change', this.onEditorChange) + editor.on('change', this.changeHoverbarState) // 滚动时隐藏 const hideAndClean = this.hideAndClean.bind(this) @@ -68,7 +68,7 @@ class HoverBar { private changeItemsState() { promiseResolveThen(() => { this.hoverbarItems.forEach(item => { - item.onSelectionChange() + item.changeMenuState() }) }) } @@ -190,7 +190,7 @@ class HoverBar { /** * editor onChange 时触发(涉及 DOM 操作,加防抖) */ - private onEditorChange = debounce(() => { + changeHoverbarState = debounce(() => { // 获取选中的 node ,以及对应的 menu keys const { isShow } = this const { node = null, menuKeys = [] } = this.getSelectedNodeAndMenuKeys() || {} diff --git a/packages/core/src/menus/bar/Toolbar.ts b/packages/core/src/menus/bar/Toolbar.ts index 068d60be3..766566ce0 100644 --- a/packages/core/src/menus/bar/Toolbar.ts +++ b/packages/core/src/menus/bar/Toolbar.ts @@ -41,11 +41,11 @@ class Toolbar { this.registerItems() // 创建完,先模拟一次 onchange - this.onEditorChange() + this.changeToolbarState() // 监听 editor onchange const editor = this.getEditorInstance() - editor.on('change', this.onEditorChange) + editor.on('change', this.changeToolbarState) }) } @@ -151,9 +151,9 @@ class Toolbar { /** * editor onChange 时触发(涉及 DOM 操作,加防抖) */ - private onEditorChange = debounce(() => { + changeToolbarState = debounce(() => { this.toolbarItems.forEach(toolbarItem => { - toolbarItem.onSelectionChange() + toolbarItem.changeMenuState() }) }, 200) diff --git a/packages/core/src/text-area/TextArea.ts b/packages/core/src/text-area/TextArea.ts index 854534f68..3df8b76ab 100644 --- a/packages/core/src/text-area/TextArea.ts +++ b/packages/core/src/text-area/TextArea.ts @@ -52,7 +52,7 @@ class TextArea { const editor = this.editorInstance // 监听 editor onchange - editor.on('change', this.onEditorChange.bind(this)) + editor.on('change', this.changeViewState.bind(this)) // editor 销毁时,解绑 selection change editor.on('destroyed', () => { @@ -134,9 +134,9 @@ class TextArea { } /** - * editor.onchange 时触发 + * 修改 view 状态 */ - onEditorChange() { + changeViewState() { const editor = this.editorInstance // 更新 DOM diff --git a/packages/core/src/utils/weak-maps.ts b/packages/core/src/utils/weak-maps.ts index d370c9c87..95f860091 100644 --- a/packages/core/src/utils/weak-maps.ts +++ b/packages/core/src/utils/weak-maps.ts @@ -57,7 +57,6 @@ export const NODE_TO_KEY: WeakMap = new WeakMap() /** * Weak maps for storing editor-related state. */ -export const IS_READ_ONLY: WeakMap = new WeakMap() export const IS_FOCUSED: WeakMap = new WeakMap() export const IS_DRAGGING: WeakMap = new WeakMap() export const IS_CLICKING: WeakMap = new WeakMap() diff --git a/packages/editor/examples/index.html b/packages/editor/examples/index.html index 24a166436..90fdfccc5 100644 --- a/packages/editor/examples/index.html +++ b/packages/editor/examples/index.html @@ -184,7 +184,11 @@ console.log(`如果页面没有编辑器,点击 'create' 按钮创建`) // toggle readOnly - document.getElementById('btn-toggle-readOnly').addEventListener('click', () => { + document.getElementById('btn-toggle-readOnly').addEventListener('mousedown', (e) => { + // 使用 mousedown ,且 preventDefault ,否则触发编辑器 blur ,导致无法正确 focus + // TODO 文档中说明(以及其他的 editState) + e.preventDefault() + editorConfig.readOnly = !editorConfig.readOnly editor.setConfig({ readOnly: editorConfig.readOnly }) })