[英]Quill editor inside Shadow DOM
In this example, editor is created inside Shadow Root.在这个例子中,编辑器是在 Shadow Root 中创建的。
https://codepen.io/artemiusgreat/pen/XWMPdWG https://codepen.io/artemiusgreat/pen/XWMPdWG
The main concern so far is that inline formatting doesn't work when initiated from Toolbar module by clicking Bold
or Italic
buttons on the panel.到目前为止,主要的问题是当通过单击面板上的
Bold
或Italic
按钮从工具栏模块启动时,内联格式不起作用。
The reason is that window.getSelection
always returns empty selection inside the Shadow Root.原因是
window.getSelection
总是返回 Shadow Root 内的空选择。
The good thing is that it somehow works when inline formatting is initiated from Keyboard module by pressing CTRL + B or CTRL + I .好消息是,当通过按CTRL + B或CTRL + I从键盘模块启动内联格式时,它会以某种方式起作用。
I'm digging into the code, but if somebody already resolved this I would appreciate some guidance.我正在研究代码,但如果有人已经解决了这个问题,我将不胜感激。
Done.完毕。
This fix doesn't cover missing shadow.getSelection
in Safari but all other browsers should work.此修复不涵盖
shadow.getSelection
中缺少的 shadow.getSelection,但所有其他浏览器都应该可以工作。 In my case, I needed only Chrome.就我而言,我只需要 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()
});
I just implemented a nice approach in my WebComponent - use a iframe
tag in your ShadowDOM, and load another HTML page with Quill.我刚刚在我的 WebComponent 中实现了一个不错的方法 - 在 ShadowDOM 中使用
iframe
标记,并使用 Quill 加载另一个 HTML 页面。
Full HTML file完整的 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>
But still 'bubble' theme not working properly.但仍然“泡沫”主题无法正常工作。 Getting document.activeElement problem
获取 document.activeElement 问题
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.