0

I am creating a text editor using contenteditable div. When someone presses the Enter key it creates a new block and now I need to get focus on the new block and also I want to add a new class .is-focused on this new block.

[NOTE]: I used javascript for the new block because It just copies the previous block by default contenteditable behavior. I don't need the previous block but need a brand new block.

let

  root = document.querySelector('.root'),
  old_block = document.querySelectorAll('.block'),
  dummy_id = 2;

root.addEventListener('keydown', (e) => {
  if (e.key !== 'Enter')
    return;

  e.preventDefault();
  dummy_id++;

  let template =
    `<div id="block-${dummy_id}" class="block">Block ${dummy_id}</div>`;
  root.insertAdjacentHTML('beforeend', template);

  document.querySelector(`#block-${dummy_id}`).focus();
})
*,
*::before,
*::after {
  box-sizing: border;
}

body {
  margin: 0;
}

.root {
  max-width: 700px;
  margin: 1rem auto;
}

.root:focus {
  outline: 0;
}

.block {
  font-size: 21px;
  line-height: 1.8;
  color: rgba(0, 0, 0, .83)
}

.is-focused {
  background-color: rgb(240, 254, 255);
}
<div class="root" contenteditable="true">
  <div id="block-1" class="block">Block 1 [Paragraph]</div>
  <div id="block-2" class="block">Block 2 [IMG]</div>
</div>
Tahazzot
  • 1,224
  • 6
  • 27

3 Answers3

1

Had this same sort of problem before, this is a solution I got off geeks for geeks;

let

  root = document.querySelector('.root'),
  old_block = document.querySelectorAll('.block'),
  dummy_id = 2;

root.addEventListener('keydown', (e) => {
  if (e.key !== 'Enter')
    return;

  e.preventDefault();
  dummy_id++;

  let template =
    `<div id="block-${dummy_id}" class="block" contenteditable="true" tabindex="-1">Block ${dummy_id}</div>`;
  root.insertAdjacentHTML('beforeend', template);

  newBlock = document.querySelector(`#block-${dummy_id}`)
  pos = document.createRange();
  s = window.getSelection();
  pos.setStart(newBlock.childNodes[0], `Block-${dummy_id}`.length);
  pos.collapse(true);
  s.removeAllRanges();
  s.addRange(pos);
})

.focus() actually selects the ENTIRE div, use ranges instead. and you can set the position anywhere you want with this by changing

pos.setStart(newBlock.childNodes[0], `Block-${dummy_id}`.length);

you can read more about using ranges; here: https://www.geeksforgeeks.org/how-to-set-cursor-position-in-content-editable-element-using-javascript/

Tochi Bedford
  • 354
  • 1
  • 9
1
  • Yes by focusing, you mean to set a cursor onto the new block.
  • This can be achieved through Selection Range (used for working with cursor position).

Here's a working fiddle: https://jsfiddle.net/hp5L02v7/7/

function placeCursorInRichText(el, selector) {
    var range = document.createRange();
    var sel = window.getSelection();
    range.setStart(el.querySelector(selector), 0);
    range.collapse(true);
    sel.removeAllRanges();
    sel.addRange(range);
}

placeCursorInRichText(root, "#block-3");
Abhilash
  • 2,026
  • 17
  • 21
0

div element by default doesn't receive focus. However, you could give it a tabindex attribute to achieve this behaviour. Read more

tabindex="-1" means the div is only focusable by script. Here's a solution that merely about element focusing.

let

  root = document.querySelector('.root'),
  old_block = document.querySelectorAll('.block'),
  dummy_id = 2;

root.addEventListener('keydown', (e) => {
  if (e.key !== 'Enter')
    return;

  e.preventDefault();
  dummy_id++;

  let template =
    `<div id="block-${dummy_id}" tabindex="-1" class="block">Block ${dummy_id}</div>`;

  root.insertAdjacentHTML('beforeend', template);
  document.querySelector(`#block-${dummy_id}`).focus();
})
*,
*::before,
*::after {
  box-sizing: border;
}

body {
  margin: 0;
}

.root {
  max-width: 700px;
  margin: 1rem auto;
}

.root:focus {
  outline: 0;
}

.block {
  font-size: 21px;
  line-height: 1.8;
  color: rgba(0, 0, 0, .83)
}

.is-focused {
  background-color: rgb(240, 254, 255);
}
<div class="root" contenteditable="true">
  <div id="block-1" class="block">Block 1 [Paragraph]</div>
  <div id="block-2" class="block">Block 2 [IMG]</div>
</div>
dongnhan
  • 1,698
  • 9
  • 12