thetallweeks
thetallweeks

Reputation: 7395

Prevent text from being inserted inside html in contenteditable

I have a div with contenteditable, and inside of it is a link:

<div contenteditable>
  <a id="a">[$special.value$]</a>
</div>

If the user clicks into the field at the end and starts typing, the new text is inserted inside the <a> rather than after it.

<div contenteditable>
  <a id="a">[$special.value$] new text added here</a> instead of here
</div>

How can I make sure that new text gets added outside the <a>?

I've tried adding contenteditable="false" on the <a> but this adds a number of other quirks.

Right now, the best I can come up with is to use a &zwnj; before and after links - this prevents the text from being added inside the <a> but it makes the cursor movement a little odd (you have to move left/right an extra time)

div[contenteditable] {
  border: 1px solid #aaa;
}

a {
  color: red;
}
Normal
<div contenteditable>
  <a id="a">[$special.value$]</a>
</div>

With zwnj
<div contenteditable>
  <a id="a">[$special.value$]</a>&zwnj;
</div>

Upvotes: 1

Views: 1103

Answers (2)

Scott Marcus
Scott Marcus

Reputation: 65808

Have you considered temporarily removing the a element when the contenteditable gets the focus and then pre-pending it back in when it loses the focus?

let old = "";
document.querySelector("div[contenteditable]").addEventListener("focus", function(){
  old = this.innerHTML; // Store the current data
  this.innerHTML = "";  // clear out the element
});

document.querySelector("div[contenteditable]").addEventListener("blur", function(){
  // Set the new content to the old concatenated with the current
  this.innerHTML = old + this.textContent;
});
div[contenteditable] {
  border: 1px solid #aaa;
}

a { color: red; }
<div contenteditable>
  <a id="a">[$special.value$]</a>
</div>
<p>...Hit [TAB] or click outside of element after typing...</p>

Upvotes: 0

Wais Kamal
Wais Kamal

Reputation: 6180

Create another element (a <span> for example) inside the <div> and set its contenteditable to true. Then set the <div> to float to the left and the <span> to display as a block element.

div.container {
  border: 1px solid #aaa;
}

a {
  float: left;
  color: red;
}

span[contenteditable] {
  display: block;
  width:   100%;
}
<div class="container">
  <a href="#" id="a">[$special.value$]</a>
  <span contenteditable></span>
</div>

Upvotes: 1

Related Questions