Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

170
Vistas
Trying to wrap each word a user enters into a contenteditable="true" element in a div

The behavior I'm looking to implement would wrap each word the user types in <div class="word"></div> as they type their message. The parent div they're typing into has contenteditable="true".

One complicating factor is that for this use case one "word" div may contain two words (imagine a name would be considered one "word" so e.g. <div class="word">Bob Smith</div> may occur). This means I can't just grab all of the textContent when the user presses space and split(" ") into an array to build the div.word DOM elements.

I'm thinking when the user presses space I can get all the child nodes of the contenteditable div and loop through them to check which is a textNode and which is not (i.e. a word already wrapped in div.word). Then for the text nodes only I can build a div.word DOM element and append all of these to the contenteditable div.

I hope that's clear. Here's sort of where I'm at:

<div id="editor" contenteditable></div>
#editor {
  border: 1px solid #333;
  padding: 10px;
}

#editor .word {
  background: yellow;
  display: inline-block;
}
const editorElement = document.getElementById('editor');


function handleSpacebarPress() {
  // Get all editor child nodes
  let editorChildNodes = [...editor.childNodes];
  
  // Clear editor of all child nodes
  editor.innerHTML = '';
  
  editorChildNodes.forEach(node => {
    // If node is a text node (not a div.word element)
    if (node.nodeType === 3) {
      // Create div.word
      let wordDiv = document.createElement('div');
      wordDiv.className = 'word';
      wordDiv.textContent = node.textContent;
      
      editor.appendChild(wordDiv);
    } 
    // Else node is already a div.word element
    else {
        editor.appendChild(node);
    }
  });
  
  // Return caret to end of editor
  const editorLength = editor.childNodes.length;
  const lastNode = editor.childNodes[editorLength - 1]; // Last editor node
  
  const range = document.createRange();
  const selection = window.getSelection();
  
  range.setStart(lastNode, 1);
  range.collapse(true);
  selection.removeAllRanges();
  selection.addRange(range);
}


editorElement.addEventListener('keydown', e => {
  if (e.code === 'Space') {
    handleSpacebarPress();
  }
});

You can view this on jsfiddle here.

Right now it seems to just place all words directly into the one div.word element and I can't seem to handle creating a new one for each word.

Any ideas?

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

I guess you want to achieve something like this: Highlighted Words Note how the spaces between the words are not highlighted and therefore have to be inside the main editor. You could fix this (as you pointed out in the comments) by adding spaces after each word in the editor and trim()-ming each word so that there are no spaces at the start or end of inner nodes.

You might to rethink your code, because it has some disadvantages.

  • Basically you are reimplementing what basic editors with custom syntax highlighting already do.
  • Manually setting the cursor position does not work, if you are editing in the middle of the editor.
  • Copy & pasting text wont trigger handleSpacebarPress

If you want to program the editor yourself, I suggest you use a function highlightWords that gets triggered after every change event (maybe with some artificial delay). In that function you can use a regular expression to find all the words according to your criteria and replace them with <span class=word>$1</span>.

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda