当父元素是 contentEditable 时,是不是可以防止子元素被删除?

Posted

技术标签:

【中文标题】当父元素是 contentEditable 时,是不是可以防止子元素被删除?【英文标题】:Is it possible to prevent child elements from being deleted when their parent is contentEditable?当父元素是 contentEditable 时,是否可以防止子元素被删除? 【发布时间】:2019-02-20 06:33:20 【问题描述】:

当元素为contentEditable时,可以删除其子元素。如果这些子元素之一是 not contentEditable,则无法编辑子元素的内容,但仍可以删除元素本身。您可以在以下示例中看到这一点。

是否可以防止这些子元素被删除?

div 
  height: 100px;
  border: 1px solid #CCC;
  margin: 5px;
  padding: 5px;
  width: 300px;


span 
  color: #999;
<div contentEditable="true">Hello <span contentEditable="false">world</span>!</div>

【问题讨论】:

好问题!我唯一能想到的就是实际创建单独的 div,并将外部的 div 标记为 contentEditable:<div><span contentEditable="true">Hello </span><span contentEditable="false">world</span><span contentEditable="true">!</span></div> 感谢您的建议。虽然这在技术上可行,但会导致我希望避免的繁琐用户体验。 【参考方案1】:

如果你可以使用类,那就很容易了。

<div class="contentEditable">Hello <span class="contentNotEditable">world</span>!</div>
<div class="saveContent" style="display: none;"></div>

javascript/Jquery 部分

<script>
$(".contentEditable").on("click",function()
 // make blank .saveContent
 $(".saveContent").html("");

 // copy all contentNotEditable class which inside selected contentEditable class.
 $( this ).find(".contentNotEditable").clone().appendTo( ".saveContent" );

 // make blank contentEditable
 $( this ).html("");

 // clone contentNotEditable to contentEditable
 $( ".saveContent" ).find(".contentNotEditable").clone().appendTo( ".contentEditable" );
);
</script>

【讨论】:

它在我的测试中运行良好。但它需要jquery。当你点击 .contentEditable 区域时,它只显示 contentNotEditable 区域。 @Fatihd 您应该在工作代码 sn-p 中演示它。【参考方案2】:

是否可以防止这些子元素被删除?

不,但这里有一个替代解决方案。

演示:

由于我们不能有直接的子元素,我们需要创建两个独立的元素。

<div class="editor">
  <label class="editor-label">You can't remove me</label>
  <div class="editor-area" contentEditable="true"></div>
</div>

然后,我们从流程中移除 label,使其不会对 area 产生任何影响。

.editor 
  border: solid 1px #CCC;
  position: relative; // context for label
  line-height: 1.5;


.editor-area 
  min-height: 100px;
  padding: 5px;


.editor-label 
  position: absolute; // out of the flow
  padding: 5px 0 0 5px;
  user-select: none;

最后,为了使插入符号在 label 文本之后开始,我们需要知道它的宽度并将其应用于 areatext-indent 值。

var editorLabel = document.querySelector('.editor-label');
var editorArea = document.querySelector('.editor-area');

var editorLabelRect = editorLabel.getBoundingClientRect();

editorArea.style.textIndent = editorLabelRect.width + 'px';
editorArea.innerHTML = '&nbsp';

完整代码:

var editorLabel = document.querySelector('.editor-label');
var editorArea = document.querySelector('.editor-area');

var editorLabelRect = editorLabel.getBoundingClientRect();

editorArea.style.textIndent = editorLabelRect.width + 'px';
editorArea.innerHTML = '&nbsp';
.editor 
  border: solid 1px #CCC;
  position: relative;
  line-height: 1.5;


.editor-area 
  min-height: 100px;
  padding: 5px;


.editor-label 
  position: absolute;
  margin: 5px 0 0 5px;
  user-select: none;
<div class="editor">
  <label class="editor-label">You can't remove me</label>
  <div class="editor-area" contentEditable="true"></div>
</div>

【讨论】:

以上是关于当父元素是 contentEditable 时,是不是可以防止子元素被删除?的主要内容,如果未能解决你的问题,请参考以下文章

contenteditable:使用行/列修饰符时检测元素变化

contenteditable属性

KnockoutJS - 禁用绑定 - 当父元素有值时如何禁用子元素

当父元素可拖动时如何允许文本框插入符号位置(在鼠标单击时)

当父元素和子元素都具有不同的百分比宽度时如何使子 div 居中

将插入符号位置设置为零在 chrome 中的 contenteditable 元素的节点内