feat: add onselectionchange api
This commit is contained in:
parent
0de9eb6f6a
commit
afa36a833e
|
@ -1,133 +0,0 @@
|
|||
import { ListType } from '.'
|
||||
import Editor from '../../editor/index'
|
||||
import $, { DomElement } from '../../utils/dom-core'
|
||||
import { ContainerFragment } from './ListHandle'
|
||||
|
||||
/**
|
||||
* 过滤 选择的 node 节点
|
||||
* @returns { DomElement[] } DomElement[]
|
||||
*/
|
||||
export function filterSelectionNodes($nodes: DomElement[]): DomElement[] {
|
||||
const $listHtml: DomElement[] = []
|
||||
$nodes.forEach(($node: DomElement) => {
|
||||
const targerName = $node.getNodeName()
|
||||
if (targerName !== ListType.OrderedList && targerName !== ListType.UnorderedList) {
|
||||
// 非序列
|
||||
$listHtml.push($node)
|
||||
} else {
|
||||
// 序列
|
||||
if ($node.prior) {
|
||||
$listHtml.push($node.prior)
|
||||
} else {
|
||||
const $children = $node.children()
|
||||
$children?.forEach(($li: HTMLElement) => {
|
||||
$listHtml.push($($li))
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return $listHtml
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新选区
|
||||
* @param $node
|
||||
*/
|
||||
|
||||
export function updateRange(editor: Editor, $node: DomElement, collapsed: boolean) {
|
||||
const selection = editor.selection
|
||||
const range = document.createRange()
|
||||
|
||||
// ===============================
|
||||
// length 大于 1
|
||||
// 代表着转换是一个文档节点多段落
|
||||
// ===============================
|
||||
if ($node.length > 1) {
|
||||
range.setStart($node.elems[0], 0)
|
||||
range.setEnd($node.elems[$node.length - 1], $node.elems[$node.length - 1].childNodes.length)
|
||||
}
|
||||
|
||||
// ===============================
|
||||
// 序列节点 或 单段落
|
||||
// ===============================
|
||||
else {
|
||||
range.selectNodeContents($node.elems[0])
|
||||
}
|
||||
|
||||
// ===============================
|
||||
// collapsed 为 true 代表是光标
|
||||
// ===============================
|
||||
collapsed && range.collapse(false)
|
||||
selection.saveRange(range)
|
||||
selection.restoreSelection()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取起点元素
|
||||
* @param $startElem 开始序列节点
|
||||
*/
|
||||
export function getStartPoint($startElem: DomElement): DomElement {
|
||||
return $startElem.prior
|
||||
? $startElem.prior // 有 prior 代表不是全选序列
|
||||
: $($startElem.children()?.elems[0]) // 没有则代表全选序列
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取结束元素
|
||||
* @param $endElem 结束序列节点
|
||||
*/
|
||||
export function getEndPoint($endElem: DomElement): DomElement {
|
||||
return $endElem.prior
|
||||
? $endElem.prior // 有 prior 代表不是全选序列
|
||||
: $($endElem.children()?.last().elems[0]) // 没有则代表全选序列
|
||||
}
|
||||
|
||||
/**
|
||||
* 在您指定节点的已有子节点之前插入新的子节点。
|
||||
* @param { DomElement } $node 指定节点
|
||||
* @param { ContainerFragment } newNode 插入的新子节点
|
||||
* @param { Node | null } existingNode 指定子节点
|
||||
*/
|
||||
export function insertBefore(
|
||||
$node: DomElement,
|
||||
newNode: ContainerFragment,
|
||||
existingNode: Node | null = null
|
||||
) {
|
||||
$node.parent().elems[0].insertBefore(newNode, existingNode)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建指定的 element 对象
|
||||
*/
|
||||
export function createElement(target: string): HTMLElement {
|
||||
return document.createElement(target)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文档片段
|
||||
*/
|
||||
export function createDocumentFragment(): DocumentFragment {
|
||||
return document.createDocumentFragment()
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 li 标签的元素,并返回 $fragment 文档片段
|
||||
* @param { DomElement[] } $nodes 需要转换成 li 的 dom 元素数组
|
||||
* @param { ContainerFragment } $fragment 用于存储生成后 li 元素的文档片段
|
||||
*/
|
||||
export function createElementFragment(
|
||||
$nodes: DomElement[],
|
||||
$fragment: ContainerFragment,
|
||||
tag: string = 'li'
|
||||
): ContainerFragment {
|
||||
$nodes.forEach(($node: DomElement) => {
|
||||
const $list = createElement(tag)
|
||||
$list.innerHTML = $node.html()
|
||||
console.log('$list', $list)
|
||||
console.log('$fragment', $fragment)
|
||||
$fragment.appendChild($list)
|
||||
$node.remove()
|
||||
})
|
||||
return $fragment
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
import { ListType } from '.'
|
||||
import Editor from '../../editor/index'
|
||||
import $, { DomElement } from '../../utils/dom-core'
|
||||
import { ContainerFragment } from './ListHandle'
|
||||
|
||||
/**
|
||||
* 过滤 选择的 node 节点
|
||||
* @returns { DomElement[] } DomElement[]
|
||||
*/
|
||||
export function filterSelectionNodes($nodes: DomElement[]): DomElement[] {
|
||||
const $listHtml: DomElement[] = []
|
||||
$nodes.forEach(($node: DomElement) => {
|
||||
const targerName = $node.getNodeName()
|
||||
if (targerName !== ListType.OrderedList && targerName !== ListType.UnorderedList) {
|
||||
// 非序列
|
||||
$listHtml.push($node)
|
||||
} else {
|
||||
// 序列
|
||||
if ($node.prior) {
|
||||
$listHtml.push($node.prior)
|
||||
} else {
|
||||
const $children = $node.children()
|
||||
$children?.forEach(($li: HTMLElement) => {
|
||||
$listHtml.push($($li))
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return $listHtml
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新选区
|
||||
* @param $node
|
||||
*/
|
||||
|
||||
export function updateRange(editor: Editor, $node: DomElement, collapsed: boolean) {
|
||||
const selection = editor.selection
|
||||
const range = document.createRange()
|
||||
|
||||
// ===============================
|
||||
// length 大于 1
|
||||
// 代表着转换是一个文档节点多段落
|
||||
// ===============================
|
||||
if ($node.length > 1) {
|
||||
range.setStart($node.elems[0], 0)
|
||||
range.setEnd($node.elems[$node.length - 1], $node.elems[$node.length - 1].childNodes.length)
|
||||
}
|
||||
|
||||
// ===============================
|
||||
// 序列节点 或 单段落
|
||||
// ===============================
|
||||
else {
|
||||
range.selectNodeContents($node.elems[0])
|
||||
}
|
||||
|
||||
// ===============================
|
||||
// collapsed 为 true 代表是光标
|
||||
// ===============================
|
||||
collapsed && range.collapse(false)
|
||||
selection.saveRange(range)
|
||||
selection.restoreSelection()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取起点元素
|
||||
* @param $startElem 开始序列节点
|
||||
*/
|
||||
export function getStartPoint($startElem: DomElement): DomElement {
|
||||
return $startElem.prior
|
||||
? $startElem.prior // 有 prior 代表不是全选序列
|
||||
: $($startElem.children()?.elems[0]) // 没有则代表全选序列
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取结束元素
|
||||
* @param $endElem 结束序列节点
|
||||
*/
|
||||
export function getEndPoint($endElem: DomElement): DomElement {
|
||||
return $endElem.prior
|
||||
? $endElem.prior // 有 prior 代表不是全选序列
|
||||
: $($endElem.children()?.last().elems[0]) // 没有则代表全选序列
|
||||
}
|
||||
|
||||
/**
|
||||
* 在您指定节点的已有子节点之前插入新的子节点。
|
||||
* @param { DomElement } $node 指定节点
|
||||
* @param { ContainerFragment } newNode 插入的新子节点
|
||||
* @param { Node | null } existingNode 指定子节点
|
||||
*/
|
||||
export function insertBefore(
|
||||
$node: DomElement,
|
||||
newNode: ContainerFragment,
|
||||
existingNode: Node | null = null
|
||||
) {
|
||||
$node.parent().elems[0].insertBefore(newNode, existingNode)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建指定的 element 对象
|
||||
*/
|
||||
export function createElement(target: string): HTMLElement {
|
||||
return document.createElement(target)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文档片段
|
||||
*/
|
||||
export function createDocumentFragment(): DocumentFragment {
|
||||
return document.createDocumentFragment()
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 li 标签的元素,并返回 $fragment 文档片段
|
||||
* @param { DomElement[] } $nodes 需要转换成 li 的 dom 元素数组
|
||||
* @param { ContainerFragment } $fragment 用于存储生成后 li 元素的文档片段
|
||||
*/
|
||||
export function createElementFragment(
|
||||
$nodes: DomElement[],
|
||||
$fragment: ContainerFragment,
|
||||
tag: string = 'li'
|
||||
): ContainerFragment {
|
||||
$nodes.forEach(($node: DomElement) => {
|
||||
const $list = createElement(tag)
|
||||
$list.innerHTML = $node.html()
|
||||
$fragment.appendChild($list)
|
||||
$node.remove()
|
||||
})
|
||||
return $fragment
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>wangEditor example</title>
|
||||
<style>
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>
|
||||
wangEditor demo
|
||||
</p>
|
||||
<div id="div1">
|
||||
<p>欢迎使用 <b>wangEditor</b> 富文本编辑器</p>
|
||||
</div>
|
||||
|
||||
<div id="div2">
|
||||
<p>欢迎使用 <b>wangEditor</b> 富文本编辑器</p>
|
||||
</div>
|
||||
|
||||
<script src="../dist/wangEditor.js"></script>
|
||||
<script>
|
||||
// 改为使用var声明,才能在window对象上获取到编辑器实例,方便e2e测试
|
||||
var E = window.wangEditor
|
||||
var editor = new E('#div1')
|
||||
editor.config.onSelectionChange = function (newHtml) {
|
||||
console.log('editor', newHtml)
|
||||
}
|
||||
editor.create()
|
||||
|
||||
// setTimeout(() => {
|
||||
// console.log("摧毁了")
|
||||
// editor.destroy()
|
||||
// }, 3000)
|
||||
|
||||
// var editor2 = new E('#div2')
|
||||
// editor2.config.onSelectionChange = function (newHtml) {
|
||||
// console.log('editor2', newHtml)
|
||||
// }
|
||||
// editor2.create()
|
||||
|
||||
// setTimeout(() => {
|
||||
// console.log("摧毁了")
|
||||
// editor2.destroy()
|
||||
// }, 3000)
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -49,6 +49,7 @@ export type ConfigType = {
|
|||
pasteTextHandle: Function
|
||||
styleWithCSS: boolean
|
||||
linkImgCallback: Function
|
||||
onSelectionChange: Function
|
||||
|
||||
placeholder: string
|
||||
zIndexFullScreen: number
|
||||
|
|
|
@ -20,6 +20,7 @@ import ZIndex from './z-index'
|
|||
import Change from './change/index'
|
||||
import History from './history/index'
|
||||
import disableInit from './disable'
|
||||
import SelectionChange from './selection-change'
|
||||
|
||||
import initPlugins, { RegisterOptions, pluginsListType, registerPlugin } from '../plugins'
|
||||
|
||||
|
@ -70,6 +71,7 @@ class Editor {
|
|||
public change: Change
|
||||
public history: History
|
||||
public isEnable: Boolean
|
||||
public onSelectionChange: SelectionChange
|
||||
|
||||
// 实例销毁前需要执行的钩子集合
|
||||
private beforeDestroyHooks: Function[] = []
|
||||
|
@ -113,6 +115,7 @@ class Editor {
|
|||
this.zIndex = new ZIndex()
|
||||
this.change = new Change(this)
|
||||
this.history = new History(this)
|
||||
this.onSelectionChange = new SelectionChange(this)
|
||||
|
||||
const { disable, enable } = disableInit(this)
|
||||
this.disable = disable
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* @description range变化
|
||||
* @author liuwei
|
||||
*/
|
||||
import Editor from '../index'
|
||||
export default class SelectionChange {
|
||||
constructor(public editor: Editor) {
|
||||
// 绑定的事件
|
||||
const init = () => {
|
||||
const activeElement = document.activeElement
|
||||
if (activeElement === editor.$textElem.elems[0]) {
|
||||
this.emit()
|
||||
}
|
||||
}
|
||||
|
||||
// 选取变化事件监听
|
||||
window.document.addEventListener('selectionchange', init)
|
||||
|
||||
// 摧毁时移除监听
|
||||
this.editor.beforeDestroy(() => {
|
||||
window.document.removeEventListener('selectionchange', init)
|
||||
})
|
||||
}
|
||||
|
||||
public emit(): void {
|
||||
// 执行rangeChange函数
|
||||
const { onSelectionChange } = this.editor.config
|
||||
if (onSelectionChange) {
|
||||
const selection = this.editor.selection
|
||||
selection.saveRange()
|
||||
if (!selection.isSelectionEmpty())
|
||||
onSelectionChange({
|
||||
// 当前文本
|
||||
text: selection.getSelectionText(),
|
||||
// 当前的html
|
||||
html: selection.getSelectionContainerElem()?.elems[0].innerHTML,
|
||||
// select对象
|
||||
selection: selection,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue