0

const elementEditing = document.getElementById('example');
elementEditing.addEventListener("keydown", onkeydownInEditable);

function onkeydownInEditable(e, KeyboardEvent) {
  if (e.key === "Enter") {
    e.preventDefault();
  }
  if (e.key === "Backspace") {
  
    console.log('is el[notContentDeletable] just in front cursor and will be deleted ?')
  
  } else if ( e.key === "Delete") {
        
    console.log('is el[notContentDeletable] just behind cursor and will be deleted ?')
    
  }
}
<div id="example" contentEditable="true">
aaaaa 1<input notContentDeletable>2 bbbbb
</div>

I want to prevent that an element with [notContentDeletable] attribute gets deleted by "del" or "backspace".

(in jsfiddle)

  • if im between 1 and input and press del the input will be deleted. I want to prevent this.

  • if im between input and 2 and press backspace the input will be deleted. I want to prevent this.

So how can I get the element next to or after the cursor? Is that possible?

Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
Andre Elrico
  • 10,956
  • 6
  • 50
  • 69
  • `notContentDeletable` is not a valid attribute. – Scott Marcus Feb 02 '21 at 23:31
  • Wouldn't it just be simpler to just have two `contenteditible` areas (one before the `input` and one `after`)? – Scott Marcus Feb 02 '21 at 23:33
  • notContentDeletable is my invention to mark an element as not deleteable. In my usecase it is not possible as its a very dynamic situation where in a contenteditible div there is text and inputs. – Andre Elrico Feb 02 '21 at 23:36
  • 1
    You can’t just make up HTML vocabulary. Use data-* attributes instead. – Scott Marcus Feb 03 '21 at 02:09
  • it will still render prefectly but I aggree with you @ScottMarcus. usng data-* is the better practice. I will change that in my endproduct. – Andre Elrico Feb 03 '21 at 09:54
  • You should understand that how it renders is not a measure of your HTML. You can create extremely invalid HTML and it will still render correctly because there is no such thing as an HTML error message (in a browser). You must take into account other factors, like the semantics and structure of the page, which will cause problems for people who rely on assistive technologies to experience your page. – Scott Marcus Feb 03 '21 at 13:26

2 Answers2

2

Check this question.

It creates a range that starts at the start of the editable element and ends immediately before the caret, gets the range's text and returns the last character of that range.

Saifee
  • 31
  • 5
  • thats cool. somehow this solution works with text nodes :/. I tried adding an input-element but its not recognized. – Andre Elrico Feb 03 '21 at 10:02
1

You can use window.getSelection() to get information about the current cursor position in the currently focused element.

Then based on that, you could implement your desired behaviour.

Note: because getSelection doesn't work well inside of input and textarea tags, but already works correctly with delete and backspace, you could just return if the event target is either of them.

import "./styles.css";
const elementEditing = document.getElementById("example");
elementEditing.addEventListener("keydown", onkeydownInEditable);
function onkeydownInEditable(e, KeyboardEvent) {
  if (e.key === "Enter") {
    e.preventDefault();
  }
  if (e.key === "Backspace") {
    if (
      e.target instanceof HTMLInputElement ||
      e.target instanceof HTMLTextAreaElement
    ) {
      return;
    }
    const selection = getSelection();
    const currentNode = selection.focusNode;
    if (!(currentNode instanceof Text)) {
      e.preventDefault();
    }
  } else if (e.key === "Delete") {
    if (
      e.target instanceof HTMLInputElement ||
      e.target instanceof HTMLTextAreaElement
    ) {
      return;
    }
    const selection = getSelection();
    const offset = selection.focusOffset;
    const currentNode = selection.focusNode;
    if (currentNode.length === offset) {
      e.preventDefault();
    }
  }
}
<div id="example" contentEditable="true">
aaaaa 1<input notContentDeletable>2 bbbbb
</div>

Working CodeSandbox link: https://codesandbox.io/s/cranky-architecture-946p5?file=/src/index.js

deckele
  • 4,623
  • 1
  • 19
  • 25
  • this works already very good. When Im in position 1 (before first a) and I hit `delete` over and over again this will delete the input. Can this be fixed ? – Andre Elrico Feb 11 '21 at 08:33
  • @Andre Elrico good catch, I fixed the bug where deleting from index 0 would delete the input element. See attached link in answer. – deckele Feb 11 '21 at 13:49