feat: add onselectionchange api

This commit is contained in:
q378532364 2021-06-28 22:01:51 +08:00
parent 0de9eb6f6a
commit afa36a833e
6 changed files with 98 additions and 264 deletions

View File

@ -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
}

View File

@ -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
}

View File

@ -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>

View File

@ -49,6 +49,7 @@ export type ConfigType = {
pasteTextHandle: Function
styleWithCSS: boolean
linkImgCallback: Function
onSelectionChange: Function
placeholder: string
zIndexFullScreen: number

View File

@ -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

View File

@ -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,
})
}
}
}