Mik*_*els 6 html javascript css regex contenteditable
我遇到了这篇 Stack Overflow 帖子,其中讨论了我所需要的确切内容:能够将文本粘贴到内容可编辑的区域,只保留一些样式。我在那里运行了代码片段,它工作正常。但是,当我在我的页面上尝试时,所有样式都被删除了,包括我想保留的样式,例如粗体和斜体。在比较代码和一些实验后,我意识到它不起作用的原因是因为我使用的是外部 CSS,而不是内联。
有什么办法可以使它与外部 CSS 一起使用吗?我永远不会知道用户将在该 contenteditable 中发布的文本的来源,以及如何对其应用样式,因此我希望解决所有可能性。
另外,有没有办法让它与拖放的文本一起工作,而不仅仅是粘贴的文本?我尝试将它正在侦听的事件从“粘贴”替换为“丢弃”,但出现错误e.clipboardData is undefined
const el = document.querySelector('p');
el.addEventListener('paste', (e) => {
// Get user's pasted data
let data = e.clipboardData.getData('text/html') ||
e.clipboardData.getData('text/plain');
// Filter out everything except simple text and allowable HTML elements
let regex = /<(?!(\/\s*)?(b|i|em|strong|u)[>,\s])([^>])*>/g;
data = data.replace(regex, '');
// Insert the filtered content
document.execCommand('insertHTML', false, data);
// Prevent the standard paste behavior
e.preventDefault();
});
Run Code Online (Sandbox Code Playgroud)
.editable {
width: 100%;
min-height: 20px;
font-size: 14px;
color: black;
font-family: arial;
line-height: 1.5;
border: solid 1px black;
margin-bottom: 30px;
}
.big {
font-size: 20px;
}
.red {
color: red;
}
.bold {
font-weight: bold;
}
.italic {
text-decoration: italic;
}
Run Code Online (Sandbox Code Playgroud)
<p class="editable" contenteditable></p>
<p class="notEditable">
Try pasting this paragraph into the contenteditable paragraph above. This text includes <b>BOLD</b>, <i>ITALIC</i>, <s>STRIKE</s>, <u>UNDERLINE</u>, a <a href='#'>LINK</a>, and <span style="font-size:30px; color:red; font-family:Times New Roman">a few other styles.</span> All styles are inline, and it works as expected.
</p>
<p>Now, try pasting this paragraph with external styles. <span class="big">Big</span > <span class="red">red</span> <span class="bold">bold</span> <span class="italic">italic</span>. It no longer works.</p>
Run Code Online (Sandbox Code Playgroud)
小智 1
不幸的是,没有办法从外部源保留类的属性。如果您要打印剪贴板的内容,您将看到收到外部页面上的原始 HTML 内容,例如:
<div class="some-class">this is the text</div>
Run Code Online (Sandbox Code Playgroud)
浏览器不会内联类属性!由于内容来自外部来源,因此您无法控制它。
另一方面,如果内容来自您的页面(因此定义了类),您可以解析接收到的 HTML 并过滤 CSS 属性,仅保留您想要的内容。这里有一个使用普通 Javascript 的代码示例,不需要任何库(也可以在Codepen上找到):
<div class="some-class">this is the text</div>
Run Code Online (Sandbox Code Playgroud)
const targetEditable = document.querySelector('p');
targetEditable.addEventListener('paste', (event) => {
let data = event.clipboardData.getData('text/html') ||
event.clipboardData.getData('text/plain');
// Filter the string using your already existing rules
// But allow <p> and <div>
let regex = /<(?!(\/\s*)?(div|b|i|em|strong|u|p)[>,\s])([^>])*>/g;
data = data.replace(regex, '');
const newElement = createElementFromHTMLString(data);
const cssContent = generateFilteredCSS(newElement);
addCssToDocument(cssContent);
document.execCommand('insertHTML', false, newElement.innerHTML);
event.preventDefault();
});
// Scan the HTML elements recursively and generate CSS classes containing only the allowed properties
function generateFilteredCSS(node) {
const newClassName = randomString(5);
let content = `.${newClassName}{\n`;
if (node.className !== undefined && node.className !== '') {
// Get an element that has the class
const elemOfClass = document.getElementsByClassName(node.className)[0];
// Get the computed style properties
const styles = window.getComputedStyle(elemOfClass);
// Properties whitelist, keep only those
const propertiesToKeep = ['font-weight'];
for (const property of propertiesToKeep) {
content += `${property}: ${styles.getPropertyValue(property)};\n`;
}
}
content += '}\n';
node.className = newClassName;
for (const child of node.childNodes) {
content += generateFilteredCSS(child);
}
return content;
}
function createElementFromHTMLString(htmlString) {
var div = document.createElement('div');
div.innerHTML = htmlString.trim();
return div;
}
function addCssToDocument(cssContent) {
var element = document.createElement("style");
element.innerHTML = cssContent;
var header = document.getElementsByTagName("HEAD")[0];
header.appendChild(element);
}
function randomString(length) {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for (var i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
.editable {
width: 100%;
min-height: 20px;
font-size: 14px;
color: black;
font-family: arial;
line-height: 1.5;
border: solid 1px black;
margin-bottom: 30px;
}
.red-bg {
background-color: red;
font-weight: bold;
}
Run Code Online (Sandbox Code Playgroud)
关于拖放功能,你必须event.dataTransfer.getData()
在drop
事件监听器中使用,其余的都是一样的。
参考
归档时间: |
|
查看次数: |
575 次 |
最近记录: |