强制 IE contentEditable 元素在 Enter 键上创建换行符,而不破坏撤消

发布于 2024-08-20 10:52:49 字数 511 浏览 4 评论 0原文

在 Internet Explorer 上,每次按 Enter 时,contentEditable DIV 都会创建一个新段落 (

),而 Firefox 则会创建一个
> 标签。

正如所讨论的 here,可以使用 JavaScript 拦截 Enter keyPress 并使用 range.pasteHTML 创建一个
来代替。但这样做会破坏撤消菜单;一旦按下 Enter 键,您将无法再撤消该点之后的操作。

如何强制 contentEditable 元素在 Enter 上创建单行中断而不破坏 Undo?

On Internet Explorer, a contentEditable DIV creates a new paragraph (<p></p>) each time you press Enter whereas Firefox creates a <br/> tag.

As discussed here, it is possible to use JavaScript to intercept the Enter keyPress and use range.pasteHTML to create a <br/> instead. But doing this breaks the Undo menu; once you hit Enter, you can no longer Undo past that point.

How can I force the contentEditable element to create single line breaks on Enter without breaking Undo?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

青巷忧颜 2024-08-27 10:52:49

不是确切的解决方案,而是另一种解决方法。如果您使用标记:

<div contenteditable="true">
<div>
content
</div>
<div>

那么按 enter 将创建新的 div 标记,而不是 p 标记。

Not an exact solution, but another workaround. If you use the markup:

<div contenteditable="true">
<div>
content
</div>
<div>

Then pressing enter will create new div tags instead of p tags.

迷路的信 2024-08-27 10:52:49

当您按 Enter 键进行中断时,请按住 Shift 键,不要按住它来显示整个段落。默认情况下,此行为在 Firefox 中是相同的,假设内容可编辑区域包含一个段落:即

<div contenteditable="true">
    <p>If you are typing here</p>
<div>

Hold down shift when you press enter for breaks, don't hold it down for full paragraphs. This behaviour is the same by default in Firefox, given a contenteditable area containing a paragraph: i.e.

<div contenteditable="true">
    <p>If you are typing here</p>
<div>
水波映月 2024-08-27 10:52:49

想必您要将可编辑的内容发布回服务器。因此,您不应该真正关心用户编辑时是否有段落或分隔标记,因为您可以在提交之前(或在服务器上,如果您愿意)解析 HTML 并用分隔符替换段落实例。这可以让 UNDO 队列保持对用户的运行状态,同时让您的 HTML 变得如您所愿地干净。

我将进一步假设您将确切地知道哪些 DIV 元素将是内容可编辑的。在提交表单之前,您可以通过这样的函数运行每个 contentEditable div:

function cleanContentEditableDiv(div) {
  var htmlString = div.innerHTML;
  htmlString     = htmlString.replace(/<\/p>/gim,"<br/>");
  htmlString     = htmlString.replace(/<p>/gim,"");
  return htmlString;
}

然后在循环中调用它(它迭代所有 contentEditable DIV,使用一个我将称为 ceDivs 的数组),如下所示:

ceDivs[i].contentEditable = false; // to make sure IE doesn't try to coerce the contents again

ceDivs[i].innerHTML = cleanContentEditableDiv(ceDivs[i]);

然后 对此(特别是如果您不想在提交时正确执行此操作),可能是在您喜欢的任何其他时间(onblur,无论如何)清理每个此类 div 的内容,并将每个 ceDiv 的内容分配给其自己的不可见内容供以后提交的表单元素。与上面您自己的 CSS 建议结合使用,这可能对您有用。它不会保留您的字面要求(即,它不会让 Javascript 使 IE 的行为不同于它在幕后编码的行为),但对于所有实际目的,效果是相同的。用户得到他们想要的,你也得到你想要的。

当您这样做时,您可能还想清除 IE 中的空格字符串。如果用户输入多个空格(有些人在句号后仍然这样做),IE 插入的不是 [space][space] 而是 [space] ,一个初始空格字符 (String.fromCharCode(32)) 加上尽可能多空间运行中剩余的实体。

Presumably you are going to post the editable content back to a server. Therefore, you shouldn't really care whether you have paragraph or break tags in place while the user is editing, because you can parse the HTML before submission (or on the server, if you like) and replace instances of paragraphs with breaks. This keeps the UNDO queue in operation for the user, but lets you have your HTML as clean as you want it.

I'll further presume that you're going to know exactly which DIV elements are going to be contentEditable. Before the form is submitted, you can run each contentEditable div through a function like this:

function cleanContentEditableDiv(div) {
  var htmlString = div.innerHTML;
  htmlString     = htmlString.replace(/<\/p>/gim,"<br/>");
  htmlString     = htmlString.replace(/<p>/gim,"");
  return htmlString;
}

And you call this in a loop (which iterates through all contentEditable DIVs, using an array I will call ceDivs), like this:

ceDivs[i].contentEditable = false; // to make sure IE doesn't try to coerce the contents again

and then:

ceDivs[i].innerHTML = cleanContentEditableDiv(ceDivs[i]);

An improvement on this (especially if you don't want to do this right at submit time), might be to clean the contents of each such div any other time you like (onblur, whatever) and assign the contents of each ceDiv to its own invisible form element for later submission. Used in combination with your own CSS suggestion above, this might work for you. It doesn't preserve your literal requirements to the letter (i.e., it doesn't get Javascript to make IE behave differently than it has been coded under the covers to behave) but for all practical purposes the effect is the same. The users get what they want and you get what you want.

While you're at it you may also want to clean space strings in IE as well. If the user types multiple spaces (as some still do after periods), what is inserted by IE is not [space][space] but [space] , an initial space character (String.fromCharCode(32)) plus as many   entities as there are left in the space run.

月棠 2024-08-27 10:52:49

使用
代替

(在IE9中测试。在<之后的旧版本中可能需要nbsp; ;BR> (pasteHTML("
 "))
)

在 keydown 事件上使用它:

if (e.keyCode == 13) {
 var range = document.selection.createRange();
 range.pasteHTML("<br> ");
 range.moveStart("character", 0);
 range.moveEnd("character", -1);
 range.select();
 return false;
}

Use <BR> instead of <P> (Tested in IE9. Maybe nbsp; is needed in older versions after <BR> (pasteHTML("<br> ")) )

Use it on keydown event:

if (e.keyCode == 13) {
 var range = document.selection.createRange();
 range.pasteHTML("<br> ");
 range.moveStart("character", 0);
 range.moveEnd("character", -1);
 range.select();
 return false;
}
栖迟 2024-08-27 10:52:49

要做到这一点可能是不可能的。 ,通过使用 CSS 删除段落标签周围的内置边距,可以使

标签看起来像单个换行符:

p { margin: 0; }

但是 这种方法的缺点:如果用户需要在 contentEditable 元素中复制/粘贴文本,则文本可能在元素内部显示为单倍行距,但在元素外部显示为双倍行距。

更糟糕的是,至少在某些情况下,IE 会在粘贴过程中自动检测双换行符,并将其替换为

标签;这会弄乱粘贴文本的格式。

It may be impossible to get this right. However, it is possible to make the <p> tags look like single line breaks, by removing the built-in margin around paragraph tags, using CSS:

p { margin: 0; }

There is a drawback to this approach: if the user needs to copy/paste text in the contentEditable element, the text may appear to be single-spaced inside the element but double-spaced outside the element.

Worse, in at least some cases, IE will automatically detect double-line breaks during paste, replacing them with <p> tags; this will mess up the formatting of the pasted text.

骄兵必败 2024-08-27 10:52:49

IE 在按 Enter 按键时将文本节点与

标记绑定。要实现换行Shift+Enter。 Firefox 在 Enter 按键上添加了一个
标记。要使行为在两个浏览器中通用,您可以执行以下操作:

假设以下标记:

<div id="editableDiv" contentEditable="true"></div>

Javascript [假设以下代码位于函数闭包中,这样就不会使用全局变量使页面膨胀]:

 (function () {
     //Initialize _shiftKeyPressed to false
     var _shiftKeyPressed = false;
     $('#editableDiv').live('keydown', function (e) {
         if (e.keyCode == 16) {
             // SHIFT key is pressed
             _shiftKeyPressed = true;
         }
     }).live('keyup', function (e) {
         if (e.keyCode == 16) {
             // SHIFT key is release
             _shiftKeyPressed = false;
         }
     }).live('keypress', function (e) {
         if (e.keyCode == 13 && !_shiftKeyPressed && !jQuery.browser.msie) {
             // Insert a PARAGRAPH in Firefox instead of a BR
             // Ignores SHIFT + ENTER
             document.execCommand("insertParagraph", false, true);
         }
     })
 })();

注意: 这个脚本早于 jQuery < 1.9 使用已弃用的 $.browser

IE binds the text node with a <p> tag on Enter key press. To achieve a line break Shift+Enter. Firefox adds a <br> tag on Enter key press. To make the behavior common across both the browsers, you can do the following:

Assume the following markup:

<div id="editableDiv" contentEditable="true"></div>

Javascript [assume the below code is in a function closure so that you don't bloat the page with globals]:

 (function () {
     //Initialize _shiftKeyPressed to false
     var _shiftKeyPressed = false;
     $('#editableDiv').live('keydown', function (e) {
         if (e.keyCode == 16) {
             // SHIFT key is pressed
             _shiftKeyPressed = true;
         }
     }).live('keyup', function (e) {
         if (e.keyCode == 16) {
             // SHIFT key is release
             _shiftKeyPressed = false;
         }
     }).live('keypress', function (e) {
         if (e.keyCode == 13 && !_shiftKeyPressed && !jQuery.browser.msie) {
             // Insert a PARAGRAPH in Firefox instead of a BR
             // Ignores SHIFT + ENTER
             document.execCommand("insertParagraph", false, true);
         }
     })
 })();

Note: this script is prior to jQuery < 1.9 for the use of the deprecated $.browser

不再让梦枯萎 2024-08-27 10:52:49

使用 Internet Explorer 时,请考虑使用 。您可能不想在 Chrome 中执行此操作,因为焦点看起来很有趣。您可能想要实现自己的 onfocusonblur 代码。

Consider using <span contenteditable="true"></span> when using Internet Explorer. You may not want to do this with Chrome because the focus looks funny. You will probably want to implement your own onfocus and onblur code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文