【问题标题】:Not Removing Child elements in a div with contenteditable set to true不删除 div 中 contenteditable 设置为 true 的子元素
【发布时间】:2020-11-17 09:41:35
【问题描述】:

我有一个 div 标签,其中 contenteditable 设置为 true。我希望用户能够编辑该 div 内的文本,但不能删除其中的任何其他 div 或 span 标签。例如下面的代码。

<div class="container" contenteditable="true">
This Content Should be Editable
<span contenteditable="false"
   style="display: inline;">
   This Should not be Editable</span>
</div>

当我将它的 contenteditable 设置为 false 时,我在 span 标记中得到了所需的结果。但是当我在 div 标签中按退格键时,我也可以删除整个 span 标签。我想锁定 div 中的 span 标签,比如不允许用户删除或编辑它。现在我认为拥有一个可内容编辑的 div 标签允许用户完全删除跨度。是否有解决方法来实现这一目标。而且我不想在另一个跨度中拥有可编辑的文本。

【问题讨论】:

  • 最新的更新 #2 似乎是我在不使用表单字段更改事件或修改您的原始代码的情况下可以摆脱的最好的方法

标签: javascript html jquery css


【解决方案1】:

更新 #2:在这个例子中,似乎综合了一些东西。

首先侦听容器中的“删除”按键事件,然后侦听 contenteditable="false" 跨度以将其从容器中意外删除。

this post 对光标位置的启发和this post 对手动调度键盘事件的启发

const DOMNodeRemoved = 'DOMNodeRemoved';
const DELETE = 'Delete';

const container = document.querySelector(".container");
container.addEventListener('keydown', containerListner, false);

const unEditableSelector = '[contenteditable="false"]';
const unEditable = container.querySelector(unEditableSelector);
unEditable.addEventListener("DOMNodeRemoved", unEditableListner, false)

function containerListner(e) { return e.key === DELETE && manuallyTriggerDeleteKey(e) }

function unEditableListner(e) { return e.type === DOMNodeRemoved && container.append(unEditable) }

function manuallyTriggerDeleteKey(e) {
    const cursorPosition = window.getSelection().getRangeAt(0).startOffset
    const stringToDelete = e.target.textContent.substr(cursorPosition).trim();
    const stripped = unEditable.textContent.trim();
    
    if (stripped === stringToDelete ) { return e.preventDefault(); }
    return new KeyboardEvent('keypress',  { 'key': 'Delete' })
}
<div class="container" contenteditable="true">
This Content Should be Editable
<span contenteditable="false"
   style="display: inline;">
   &nbsp;This Should not be Editable</span>
</div>

您可以尝试利用 focusblur 事件并有选择地隐藏和显示管理跨度。

here's an example

更新 1:问题是,如果用户执行诸如使用删除键而不是退格键之类的操作,则跨度可能会被删除

使用 DOMNodeRemoved 事件侦听器,您可以将节点附加回容器以防意外删除。

here's an examplethis post DOM 突变事件的启发

const DOMNodeRemoved = 'DOMNodeRemoved';

let unEditable = null;

const unEditableSelector = '*[contenteditable="false"]';
const container = document.querySelector(".container");

const appendUneditable = (evt) => unEditable &&
    !evt.relatedNode.querySelector(unEditableSelector) &&
    evt.relatedNode.append(unEditable);

const listener = (evt) => evt.type === DOMNodeRemoved && appendUneditable(evt);

container.addEventListener("focus", focus);
container.addEventListener("blur", blur);

function focus(e) {
  unEditable = e.target.querySelector(unEditableSelector);
  unEditable.addEventListener("DOMNodeRemoved", listener, false);
}

function blur(e) {
  unEditable && e.target.append(unEditable);
  unEditable && unEditable.removeEventListener("DOMNodeRemoved", listener);
}

【讨论】:

  • 如果你一直按退格键,这仍然会删除跨度。它隐藏了跨度,这不是我想要的。
  • 如果没有找到,您可以将跨度附加回 div .. 从这个例子来看,这是一小部分。如果我有更多时间可能会更新更新
猜你喜欢
  • 1970-01-01
  • 2020-11-27
  • 1970-01-01
  • 1970-01-01
  • 2011-01-24
  • 1970-01-01
  • 1970-01-01
  • 2013-03-26
  • 2010-11-05
相关资源
最近更新 更多