UNPKG

wangeditor

Version:

wangEditor - 轻量级 web 富文本编辑器,配置方便,使用简单,开源免费

144 lines (130 loc) 3.96 kB
/** * @description 记录 range 变化 * @author fangzhicong */ import Cache from '../../../../utils/data-structure/cache' import Editor from '../../../index' import { RangeItem } from '../type' import $ from '../../../../utils/dom-core' import { debounce } from '../../../../utils/util' /** * 把 Range 对象转换成缓存对象 * @param range Range 对象 */ function rangeToObject(range: Range): RangeItem { return { start: [range.startContainer, range.startOffset], end: [range.endContainer, range.endOffset], root: range.commonAncestorContainer, collapsed: range.collapsed, } } /** * 编辑区 range 缓存管理器 */ export default class RangeCache extends Cache<[RangeItem, RangeItem]> { /** * 变化前的 Range 数据 */ private lastRange: RangeItem /** * 有效选区的根节点 */ private root: Element public updateLastRange: Function constructor(public editor: Editor) { super(editor.config.historyMaxSize) this.lastRange = rangeToObject(document.createRange()) this.root = editor.$textElem.elems[0] this.updateLastRange = debounce(() => { this.lastRange = rangeToObject(this.rangeHandle) }, editor.config.onchangeTimeout) } /** * 获取 Range 对象 */ public get rangeHandle() { const selection = document.getSelection() return selection && selection.rangeCount ? selection.getRangeAt(0) : document.createRange() } /** * 初始化绑定 */ public observe() { const self = this // 同步节点数据 this.root = this.editor.$textElem.elems[0] this.resetMaxSize(this.editor.config.historyMaxSize) // selection change 回调函数 function selectionchange() { const handle = self.rangeHandle if ( self.root === handle.commonAncestorContainer || self.root.contains(handle.commonAncestorContainer) ) { // 非中文输入状态下才进行记录 if (!self.editor.isComposing) { self.updateLastRange() } } } // backspace 和 delete 手动更新 Range 缓存 function deletecallback(e: KeyboardEvent) { if (e.key == 'Backspace' || e.key == 'Delete') { // self.lastRange = rangeToObject(self.rangeHandle) self.updateLastRange() } } // 绑定事件(必须绑定在 document 上,不能绑定在 window 上) $(document).on('selectionchange', selectionchange) // 解除事件绑定 this.editor.beforeDestroy(function () { $(document).off('selectionchange', selectionchange) }) // 删除文本时手动更新 range self.editor.$textElem.on('keydown', deletecallback) } /** * 保存 Range */ public save() { let current = rangeToObject(this.rangeHandle) super.save([this.lastRange, current]) this.lastRange = current return this } /** * 设置 Range,在 撤销/恢复 中调用 * @param range 缓存的 Range 数据 */ public set(range: RangeItem | undefined) { try { if (range) { const handle = this.rangeHandle handle.setStart(...range.start) handle.setEnd(...range.end) this.editor.menus.changeActive() return true } } catch (err) { return false } return false } /** * 撤销 */ public revoke() { return super.revoke(data => { this.set(data[0]) }) } /** * 恢复 */ public restore() { return super.restore(data => { this.set(data[1]) }) } }