jQuery 处理 contentEditable DIV 上的换行符
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6023307/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Dealing with line Breaks on contentEditable DIV
提问by Santiago
I have a problem with contenteditable
line breaks on SAFARI/CHROME. When I press "return" on a contentEditable <div>
, instead of creating a <br>
(like Firefox), they create a new <div>
:
我contenteditable
在 SAFARI/CHROME 上遇到换行符问题。当我在 contentEditable 上按“返回”时<div>
,它们不是创建一个<br>
(如 Firefox),而是创建一个新的<div>
:
<div>Something</div>
<div>Something</div>
That looks like (on the contentEditable DIV):
看起来像(在 contentEditable DIV 上):
Something
Something
But after sanitization (removing <div>
), I get this:
但是经过消毒(删除<div>
)后,我得到了这个:
SomethingSomething
In Firefox, the contenteditable
is:
在 Firefox 中,contenteditable
是:
Something
<br>
Something
And that after sanitization looks the same:
消毒后看起来是一样的:
Something
Something
Is there any solution to "normalize" this across browsers?
是否有任何解决方案可以跨浏览器“规范化”它?
I've found this code on Make a <br> instead of <div></div> by pressing Enter on a contenteditable
我在Make a <br> 而不是 <div></div>上找到了这个代码,方法是在 contenteditable 上按 Enter
$(function(){
$("#editable")
// make sure br is always the lastChild of contenteditable
.live("keyup mouseup", function(){
if (!this.lastChild || this.lastChild.nodeName.toLowerCase() != "br") {
this.appendChild(document.createChild("br"));
}
})
// use br instead of div div
.live("keypress", function(e){
if (e.which == 13) {
if (window.getSelection) {
var selection = window.getSelection(),
range = selection.getRangeAt(0),
br = document.createElement("br");
range.deleteContents();
range.insertNode(br);
range.setStartAfter(br);
range.setEndAfter(br);
range.collapse(false);
selection.removeAllRanges();
selection.addRange(range);
return false;
}
}
});
});
This works, but (in SAFARI and CHROME)I have to press two times the "return" key to get a new line...
这有效,但是(在 SAFARI 和 CHROME 中)我必须按两次“返回”键才能获得新行...
Any idea?
任何的想法?
Edit: With the code I found ( at the bottom of this question) is working fine except the function that "makes sure a <br>
element is always the lastChild... Any idea on how to fix this?
编辑:使用我发现的代码(在这个问题的底部)工作正常,除了“确保<br>
元素始终是 lastChild 的功能......关于如何解决这个问题的任何想法?
Edit 2:I'm getting this error on the console: Uncaught TypeError: Object #<HTMLDocument> has no method 'createChild'
编辑 2:我在控制台上收到此错误:Uncaught TypeError: Object #<HTMLDocument> has no method 'createChild'
Edit 3:Ok, I changed the document.createChild("br");
to document.createElement("br");
and I think I got it working in FF/Safari/Chrome... All return <br>
for new lines...
编辑 3:好的,我将其更改document.createChild("br");
为document.createElement("br");
,我想我可以在 FF/Safari/Chrome 中使用它...所有返回<br>
新行...
The problem is now that when I'm inside an Ordered or Unordered List, I need to get a new line without <br>
...
现在的问题是,当我在有序或无序列表中时,我需要在没有<br>
...
Edit 4:If anyone interested in the solution of the last edit: Avoid createElement function if it's inside a <LI> element (contentEditable)
编辑 4:如果有人对上次编辑的解决方案感兴趣:如果它在 <LI> 元素内,则避免使用 createElement 函数(contentEditable)
回答by Mica?l Félix
This technique appears to avoid the Chrome bug that does show BRs the first time (with the code you mentionned you need to push two times the Enter key).
这种技术似乎可以避免第一次显示 BR 的 Chrome 错误(使用您提到的代码,您需要按两次 Enter 键)。
It's not a perfect hack but it works: it adds a whitespace after your BR so it show properly.
However, you will see that adding only a whitespace " " will NOT change anything, it works with other letters. The browser will not show it, probably because it is like a blank space inside an html page, it simply does not mean anything. To get rid of that bug I created a div with jQuery that includes a
tag, and I take the text()
property to put it in the textnode otherwise it doesn't work.
这不是一个完美的黑客,但它有效:它在您的 BR 之后添加一个空格,以便正确显示。但是,您会看到仅添加一个空格“” 不会改变任何内容,它适用于其他字母。浏览器不会显示它,可能是因为它就像 html 页面中的空白区域,它根本没有任何意义。为了摆脱那个错误,我用包含
标签的jQuery 创建了一个 div ,然后我将该text()
属性放入 textnode 中,否则它不起作用。
$editables = $('[contenteditable=true]');
$editables.filter("p,span").on('keypress',function(e){
if(e.keyCode==13){ //enter && shift
e.preventDefault(); //Prevent default browser behavior
if (window.getSelection) {
var selection = window.getSelection(),
range = selection.getRangeAt(0),
br = document.createElement("br"),
textNode = document.createTextNode("\u00a0"); //Passing " " directly will not end up being shown correctly
range.deleteContents();//required or not?
range.insertNode(br);
range.collapse(false);
range.insertNode(textNode);
range.selectNodeContents(textNode);
selection.removeAllRanges();
selection.addRange(range);
return false;
}
}
});
回答by Kurt
Listening to keystrokes seems like a lot of work. Would something as simple as this be feasible:
听击键似乎需要很多工作。像这样简单的事情是否可行:
var html = $('.content').html().replace(/<div>/gi,'<br>').replace(/<\/div>/gi,'');
JSFiddle demo here.
JSFiddle 演示在这里。
Also, it looks like sanitize.jsallows a custom configuration. Have you tried adding div
as an allowed element?
此外,看起来sanitize.js允许自定义配置。您是否尝试添加div
为允许的元素?
Allowing HTML/CSS is dangerous, so ensure you are being extra cautious.
允许 HTML/CSS 是危险的,因此请确保您格外小心。
EDIT:Removed server side comments. Sanitising occurs at time of usage- if the client wants to bypass this locally it can be done so at their own risk. Thanks Vincent McNabbfor pointing this out.
编辑:删除了服务器端注释。消毒发生在使用时 - 如果客户想在本地绕过它,可以自行承担风险。感谢Vincent McNabb指出这一点。
回答by Karb
You can simply use following command
document.execCommand('insertHTML',false,'<br>');
您可以简单地使用以下命令
document.execCommand('insertHTML',false,'<br>');
This command will prevent default behavior and add a tag you wish. That's all, 1 line of code
此命令将阻止默认行为并添加您希望的标签。就是这样,1行代码
And even easier approach.
甚至更简单的方法。
CSS ONLY.
仅 CSS。
To you contenteditable element apply display:inline-block
rule
and this will add brs only
对你 contenteditable 元素应用display:inline-block
规则,这只会添加brs
回答by Klim Lee
Webkits won't render a single br
if it's the last (non-empty) child of a container. For Safari, the native keystroke to insert a line break is Ctrl + Return. If you look closely, you notice that Safari actually inserts two br
s while only rendering one; however, it will insert a single br
if there is some trailing text, or will get rid of double br
s once you enter some (if there were doubles).
如果 Webkitbr
是容器的最后一个(非空)子代,则它不会呈现单个。对于 Safari,插入换行符的原生按键是 Ctrl + Return。如果仔细观察,您会注意到 Safari 实际上插入了两个br
s 而只渲染了一个;但是,br
如果有一些尾随文本,它会插入一个单曲,或者br
一旦你输入一些(如果有双打)就会去掉 double s。
Apparently, it seems a solution for Webkits is to insert double br
s as they themselves do, and let them handle the rest.
显然,Webkits 的解决方案似乎是br
像他们自己一样插入 double s,然后让他们处理其余的。
回答by B T
You might want to check out the css white-space
property. Setting the style to white-space: pre-wrap
allows you to get rid of all that javascript, because it changes the behavior of whitespace to display instead of collapse.
您可能想查看 csswhite-space
属性。将样式设置为white-space: pre-wrap
允许您摆脱所有 javascript,因为它会更改空白的行为以显示而不是折叠。
And see this answer: HTML - Newline char in DIV content editable?
并看到这个答案:HTML - DIV 内容中的换行符可编辑?