我有一个设置了属性 contentEditable 的 div。
我遇到的问题是我输入的第一行没有被标签包裹,但后面的行会。
所以输入:
qwerty
zxcv
asdfg
结果是:
<div class="editable" contentEditable="true">
qwerty
<div>zxcv</div>
<div>asdfg</div>
</div>
所以我需要这qwerty
条线成为<div>qwerty</div>
我有一个设置了属性 contentEditable 的 div。
我遇到的问题是我输入的第一行没有被标签包裹,但后面的行会。
所以输入:
qwerty
zxcv
asdfg
结果是:
<div class="editable" contentEditable="true">
qwerty
<div>zxcv</div>
<div>asdfg</div>
</div>
所以我需要这qwerty
条线成为<div>qwerty</div>
我在 Chrome 中遇到了问题,只是添加了一个 div。仅当您的 div 包含 br 标签时才有效:
<div class="editable" contentEditable="true">
<div>
<br>
</div>
</div>
@nicholas_r 是对的,删除可编辑 div 中的最后一个字符也会删除开头添加的 div。您可以通过捕获最后一个“退格”来避免这种情况。使用 jquery 的简单解决方案:
$(".editable").on('keydown', function(event) {
if (event.keyCode === 8 && $(this).html() == '<div><br></div>') {
event.preventDefault();
}
}
如果有帮助,运行以下命令将让您包装展开的 divs 。如果您在按键或类似的情况下触发它,即使用户从 div 中删除所有内容,它也会起作用。
$(".editable").contents().filter(function() {
return this.nodeType == 3;
}).wrap('<div></div>');
如果你从一个内部包含 a 的元素开始,div
如下所示:
<div class="editable" contentEditable="true">
<div></div>
</div>
您键入的第一行最终将被包裹在div
.
更新:
这是特定于浏览器的。虽然在发布问题时它在大多数浏览器中都可以使用,但在最新的浏览器版本中不一定可以使用。最好的判断方法是测试它。
我做了这样的事情,它非常适合确保在第一行文本上总是有一个 div 包装器。
这样,如果用户单击该字段及其空白(初始状态),它将在其中放置一个空格,以确保他们的光标位于新 div 内。
$editable.on('focus', function() {
if ($(this).text().trim() === '') {
console.log('editable is blank, insert a div');
$(this).append($('<div> </div>'));
}
});
您可以在保存数据之前删除前导空格(如果重要)。
对于在 2017 年或之后遇到此问题的任何人,这些答案在 Chrome 中都不适合我,而那些试图提出智能解决方案的人并没有涵盖我的所有案例。
虽然只在 Chrome 中测试过,而且有点粗糙,但它涵盖了 3 个主要场景:
contenteditable
div 中的内容。contenteditable
div中的所有内容。ctrl+a Delete
ctrl+a Backspace
contenteditable
替换完整选择来删除 div中的所有内容。ctrl-a
一个JSFiddle演示。
document.getElementById("editor").addEventListener("keydown", function(e){
if(e.which == 8 && document.getElementById("editor").innerHTML=="<div><br></div>"){ // 8 is backspace
e.preventDefault()
}
if (window.getSelection && e.which == 8 || e.which == 46 && window.getSelection){ // 8 is backspace, 46 is delete
let selection = window.getSelection().toString();
let editorText = document.getElementById("editor").innerText;
if (editorText == selection){
document.getElementById("editor").innerHTML="<div><br></div>"
console.log("prevented a ctrl+a delete")
}
else if (window.getSelection){
let selection = window.getSelection().toString();
let editorText = document.getElementById("editor").innerText;
if (editorText == selection){
document.getElementById("editor").innerHTML="<div>"+e.which+"</div>";
console.log("safely did a ctrl+a " + e.which)
}
}
e.preventDefault()
}
})
大多数这些解决方案在 2017 年的 Chrome(版本 61.x)中都不适用于我,而且Kasper 的回答对我来说似乎太混乱了。
据我所知,对事件的""
或<br>
对input
事件的简单检查可以处理所有可能的情况,包括退格、删除和复制粘贴:
$("[contenteditable='true']")
.on("input", function ()
{
var $editable = $(this);
if ($editable.html().trim() === "" || $editable.html().trim() === "<br>")
$editable.html($("<div><br></div>"));
})
.trigger("input");
请注意,我还会input
在初始化时触发事件,以确保正确设置初始内容,但这可能是必要的,也可能不是必要的,具体取决于您的特定需求。
上下文
这是 OP 的解决方案,可确保内容可编辑 div 中的第一行始终被包装并修复常见错误,例如:
它使用事件侦听器来捕捉用户何时关注编辑器以及何时离开。有关更多上下文,请阅读代码中的注释。
下面的代码
是代码的完整工作小提琴。我的原始示例可以在这个JS Fiddle 页面上找到。
// On Dom Ready
document.getElementById('editor').addEventListener('focusin', checkEditor);
document.getElementById('editor').addEventListener('focusout', checkEditor);
function checkEditor() {
// Get the DOM element that the user is in
// Allows you to have multiple editos on one page
// Next 3 lines of code from: https://stackoverflow.com/a/1553668/3193156
var e = event || window.event;
var elem = e.target || e.srcElement;
if (elem.nodeType == 3) {
elem = elem.parentNode;
} // Defeat Safari bug
// Grab the elements inner HTML
var html = elem.innerHTML
// If html is empty or does not start with a div see if we need to fix something
if (html == '' || html.substr(0, 5) != '<div>') {
notify('Running editor checks.');
var index;
// Catch bug where a line break is added after a user uses backspace to wipe the editor
if (html.substr(0, 4) == '<br>') {
notify('Removed line break.');
index = html.indexOf('\n');
// If there are any lines after this line break save them
if (index > -1) {
html = html.substr(html.indexOf('\n') + 1);
} else {
html = '';
}
elem.innerHTML = html;
// If everything is ok return otherwise keep processing
if (html != '' && html.substr(0, 5) == '<div>') {
return;
}
}
// Catch bug where first line after erasing editor does not get wrapped
index = html.indexOf('\n');
if (index > -1) {
notify('Wrapped the fist line, did not check the rest.');
html = html = '<div>' + html.substr(0, html.indexOf('\n') + 1) + '</div>' + html.substr(html.indexOf('\n') + 1);
elem.innerHTML = html;
return;
} else {
html = html.trim();
if (html.length > 0) {
notify('Wrapped the fist line');
html = '<div>' + html.trim() + '</div>';
elem.innerHTML = html;
return;
}
}
// If we made it here the editor shold be considered empty, reset it
notify('Editor reset.');
var div = document.createElement('DIV');
div.innerHTML = '<br>';
elem.appendChild(div);
}
}
function notify(msg) {
var div = document.createElement('DIV');
div.innerHTML = msg;
document.getElementById('messages').appendChild(div);
}
#editor {
width: 90%;
height: 200px;
padding: 1rem;
border: 1px solid #000;
}
<div id="editor" contenteditable="true">
</div>
<div id="messages">
</div>
To-Do / Missing
此解决方案回答了 OP,但不考虑以下用例:
简单<div></div>
是行不通的。
如果您正在寻找 jQuery 解决方案,这里是代码:
$('.contenteditable').on 'focus', ->
if $(@).text().trim() == ''
$(@).append($('<div><br /></div>'))