Shadow DOM中的Quill编辑器



在本例中,编辑器是在Shadow Root内部创建的。

https://codepen.io/artemiusgreat/pen/XWMPdWG

到目前为止,主要关注的问题是当通过单击面板上的BoldItalic按钮从Toolbar模块启动时,内联格式不起作用

原因是window.getSelection总是在阴影根中返回空选择。

好的一面是,当从键盘模块通过按下CTRL+BCTRL+I启动内联格式化时,它会以某种方式工作。

我正在深入研究代码,但如果有人已经解决了这个问题,我将感谢一些指导。

完成。

此修复程序不包括Safari中丢失的shadow.getSelection,但所有其他浏览器都可以工作。就我而言,我只需要Chrome。

var quill = new Quill(editorControl, {
modules: {
toolbar: [
[{ header: [1, 2, false] }],
['bold', 'italic', 'underline'],
['image', 'code-block']
]
},
placeholder: 'Compose an epic...',
theme: 'snow' 
});
const normalizeNative = (nativeRange) => {
// document.getSelection model has properties startContainer and endContainer
// shadow.getSelection model has baseNode and focusNode
// Unify formats to always look like document.getSelection 
if (nativeRange) {
const range = nativeRange;

if (range.baseNode) {  
range.startContainer = nativeRange.baseNode;
range.endContainer = nativeRange.focusNode;
range.startOffset = nativeRange.baseOffset;
range.endOffset = nativeRange.focusOffset;
if (range.endOffset < range.startOffset) {
range.startContainer = nativeRange.focusNode;
range.endContainer = nativeRange.baseNode;    
range.startOffset = nativeRange.focusOffset;
range.endOffset = nativeRange.baseOffset;
}
}
if (range.startContainer) {

return {
start: { node: range.startContainer, offset: range.startOffset },
end: { node: range.endContainer, offset: range.endOffset },
native: range
};
}
}
return null
};
// Hack Quill and replace document.getSelection with shadow.getSelection 
quill.selection.getNativeRange = () => {

const dom = quill.root.getRootNode();
const selection = dom.getSelection();
const range = normalizeNative(selection);

return range;
};
// Subscribe to selection change separately, 
// because emitter in Quill doesn't catch this event in Shadow DOM
document.addEventListener("selectionchange", (...args) => {
// Update selection and some other properties
quill.selection.update()
});

完整HTML文件

<html>
<head>
<meta charset="utf-8">
<title>CKEditor</title>
<script type="text/javascript" src="https://cdn.quilljs.com/1.3.6/quill.js"></script>
</head>
<body>
<div class="container" name="NewEditor"></div>
<script>
let container = document.querySelector(".container");
let shadow = container.attachShadow({ mode: 'open' });
const ele = document.createElement('div');
console.log(shadow.getRootNode())
shadow.innerHTML = `<link href="https://cdn.quilljs.com/1.0.0/quill.snow.css" rel="stylesheet" />
<link rel="stylesheet" type="text/css" href="https://cdn.quilljs.com/1.3.6/quill.bubble.css">
`;
shadow.appendChild(ele);
var quill = new Quill(ele, {
"modules": {
"toolbar": [
[
"bold",
"italic",
"underline",
"strike",
"blockquote",
"code-block",
{
"list": "ordered"
},
{
"list": "bullet"
},
{
"script": "sub"
},
{
"script": "super"
},
{
"indent": -1
},
{
"indent": "+1"
},
{
"direction": "rtl"
},
{
"size": [
"small",
false,
"large",
"huge"
]
},
{
"color": []
},
{
"background": []
},
{
"font": []
},
{
"align": []
},
"clean",
"link",
"image",
"video"
]
]
},
"placeholder": "",
"readOnly": false,
"theme": "snow",
"value": {
"ops": [
{
"attributes": {
"bold": true
},
"insert": "Bold"
}
]
}
});
const normalizeNative = (nativeRange) => {
if (nativeRange) {
const range = nativeRange;
if (range.baseNode) {  
range.startContainer = nativeRange.baseNode;
range.endContainer = nativeRange.focusNode;
range.startOffset = nativeRange.baseOffset;
range.endOffset = nativeRange.focusOffset;
if (range.endOffset < range.startOffset) {
range.startContainer = nativeRange.focusNode;
range.endContainer = nativeRange.baseNode;    
range.startOffset = nativeRange.focusOffset;
range.endOffset = nativeRange.baseOffset;
}
}
if (range.startContainer) {
return {
start: { node: range.startContainer, offset: range.startOffset },
end: { node: range.endContainer, offset: range.endOffset },
native: range
};
}
}
return null
};
quill.selection.getNativeRange = () => {
const dom = quill.root.getRootNode();
const selection = dom.getSelection();
const range =  normalizeNative(selection);
// if(selection.focusOffset !== selection.baseOffset){
//       range.length = 0;
//       document.activeElement.shadowRoot.querySelector('.ql-editor').focus();
// }
return range;
};
document.addEventListener("selectionchange", (...args) => {
quill.selection.update()
});
</script>
</body>
</html>

但"泡沫"主题仍然无法正常工作。获取document.activeElement问题

此iamage 中的错误行

我刚刚在WebComponent中实现了一个很好的方法——在ShadowDOM中使用iframe标记,并用Quill加载另一个HTML页面。

最新更新