
参考快速扩展一个菜单 · wangEditor 用户文档
继承 按钮 菜单样式自定义拓展 格式刷功能菜单按钮
const _this = this
const { $, BtnMenu } = E
// 自定义 格式刷 菜单继F承 BtnMenu class
class FormatPainter extends BtnMenu {
constructor(editor) {
// data-title属性表示当鼠标悬停在该按钮上时提示该按钮的功能简述
const $elem = E.$(
`<div class="w-e-menu" data-title="格式刷">
<i class="el-icon-s-open"></i>
</div>`
)
super($elem, editor)
}
// 菜单点击事件,获取点击格式刷后的下一次点击文本
clickHandler() {
let nodeArray = []
//获取当前选中元素所有父样式
function getAllStyle(dom) {
if (!dom) return
const tagName = dom.tagName.toLowerCase()
if (tagName === 'p') {
nodeArray.push({
tagName: 'span',
attributes: Array.from(dom.attributes).map((i) => {
return {
name: i.name,
value: i.value,
}
}),
})
return
} else {
nodeArray.push({
tagName: tagName,
attributes: Array.from(dom.attributes).map((i) => {
return {
name: i.name,
value: i.value,
}
}),
})
getAllStyle(dom.parentNode)
}
return nodeArray
}
//获取鼠标位置的节点
let containerEle = this.editor.selection.getSelectionStartElem()
.elems[0]
let brushStyle = getAllStyle(containerEle)
if (!!brushStyle) {
//有复制到的格式就开启格式刷
_this.ifBrushed = true //格式刷开启
_this.brushStyle = brushStyle //格式刷样式存储
}
}
// 菜单是否被激活(如果不需要,这个函数可以空着)
tryChangeActive() {}
}
E.registerMenu('FormatPainter', FormatPainter)
//监听鼠标抬起事件
this.$refs['editor'].addEventListener('mouseup', () => {
//延时调用确保富文本编辑器中的选中文本已经该改变
setTimeout(() => {
this.containerEleChange()
})
})
/**
* @description: 监听文本点击事件
* @return void
*/
containerEleChange() {
let containerEle = this.editor.selection.getSelectionContainerElem()
.elems[0] //选区所在的 DOM 节点
let containerEleStart = this.editor.selection.getSelectionStartElem()
.elems[0] //选区开始的 DOM 节点
let containerEleEnd = this.editor.selection.getSelectionEndElem().elems[0] //选区结束的 DOM 节点
let ifEmpty = this.editor.selection.isSelectionEmpty() //判断选区是否为“空”(即没有选中任何文字)
let containerText = this.editor.selection.getSelectionText() //选中的文字
//复制style到选中的文本
function addStyle(text, nodeArray) {
let currentNode = null
nodeArray.forEach((ele, index) => {
let node = document.createElement(ele.tagName)
for (const attr of ele.attributes) {
node.setAttribute(attr.name, attr.value)
}
if (index === 0) {
node.innerText = text
currentNode = node
} else {
node.appendChild(currentNode)
currentNode = node
}
})
return currentNode
}
if (this.ifBrushed) {
// 格式刷开启则开始复制style
let containerEleNew
let containerEleText
if (ifEmpty) {
//判断选区是否为“空”(即没有选中任何文字)
containerEleText = containerEle.innerText
containerEleNew = addStyle(containerEle.innerText, this.brushStyle) //新的样式
} else {
//选中一段文字
containerEleText = containerText
containerEleNew = addStyle(containerText, this.brushStyle) //新的样式
}
if (containerEleStart === containerEleEnd) {
//选区前后相等,选中的区域中间不夹杂其他标签
let innerText = containerEle.innerText
if (ifEmpty) {
// 没有选中的文本直接全部替换掉
containerEle.innerHTML = containerEleNew.innerHTML
} else {
//有选中的文本则替换选中的文本
containerEle.innerHTML = innerText.replace(
containerEleText,
containerEleNew.innerHTML
)
}
} else {
//选区前后不相等,选中的区域中间夹杂其他标签,操作和选区为“空”一样
containerEleNew = addStyle(containerEle.innerText, this.brushStyle) //新的样式
containerEle.innerHTML = containerEleNew.innerHTML
}
}
this.ifBrushed = false
},
//清除监听
beforeDestroy() {
this.$refs['editor'].removeEventListener('click', this.containerEleChange)
},