2

I am making a text editor, and I want to have a feature, such that while typing, if the user enters some keyword (e.g. happy, sad), the word is automaticly styled (e.g. color changed). How might I go about doing this?

document.getElementById('texteditor').addEventListener('keyup', function(e) {
  styleCode(); //Style the text input
});

//Change the result of pressing Enter and Tab keys
document.getElementById('texteditor').addEventListener('keydown', function(e) {
  switch (e.key) {
            case 'Tab':
                e.preventDefault();
                document.execCommand('insertHTML', false, '    '); //Insert a 4-space tab
                break;

            case 'Enter':
                e.preventDefault();
                document.execCommand("insertLineBreak"); //Insert a new line
                break;
        }
});

function styleCode(){
  //Style the code in the input box
}
#texteditor {
  border: 3px solid black;
  width:100%;
  height: 500px;;
  overflow:auto;
  flex:1;
    word-wrap: break-word;
  word-break: break-all;
    white-space:pre-wrap;
  padding:5px;
  font-family: Consolas,"courier new";
    font-size:14px;
}

.styleA {
  color:red;
}

.styleB {
  color:blue;
}
<div id='texteditor' contenteditable></div>

Basically, when the user fully types "happy" (upon releasing the 'y' key) the word "happy" should turn red (using the styleA CSS class) in the editor. A similar thing should happen when the user finishes typing "sad"; the word "sad" should turn blue using the styleB CSS class.

Thanks in advance for any help.

  • 1
    this seems like a school assignment. What have you tried? – finiteloop Jan 25 '22 at 06:33
  • I tried using `let textElem = document.getElementById('texteditor'); let text = textElem.innerHTML; text.replaceAll('happy', 'happy'); textElem.innerHTML = text` but this placed the cursor back at the beginning of the textbox. Also this felt like a very rudimentary solution, and I am trying to find a way to make a more general/expandable solution. – Bhargava Kanakapura Jan 25 '22 at 07:06
  • Do you exactly want syntax highlighting like code editors or just some words – Neptotech -vishnu Jan 25 '22 at 11:02
  • I just need it for certain words, but it would be nice to see how to do syntax highlighting for code editors. – Bhargava Kanakapura Jan 26 '22 at 02:11

1 Answers1

0

const SpecialWords = [
  "happy",
  "sad"//style word
];
const WordColors = [
  "styleA",
  "styleB"//style class name
];
document.getElementById('texteditor').addEventListener('keyup', function(e) {
  styleCode(); //Style the text input
  
});

//Change the result of pressing Enter and Tab keys
document.getElementById('texteditor').addEventListener('keydown', function(e) {
  switch (e.key) {
    case 'Tab':
      e.preventDefault();
      document.execCommand('insertHTML', false, '    '); //Insert a 4-space tab
      break;

    case 'Enter':
      e.preventDefault();
      document.execCommand("insertLineBreak"); //Insert a new line
      break;
  }
});
var oldWord = "";//initialise
function styleCode() {

  //Style the code in the input box
  var wordList = document.getElementById('texteditor').innerText.split(" ");
/*if old word is same as now then it means we have presed arrow key or caps or so,it do not wan't to style now as no change*/
  if(!(oldWord == document.getElementById('texteditor').innerText)){
var oldPos = getCaretPosition(document.getElementById('texteditor'));//backup old position of cursor
for (let n = 0; n < SpecialWords.length; n++) {
    var res = replaceAll(wordList,SpecialWords[n],`<span class="${WordColors[n]}">${SpecialWords[n]}</span>`).join(" ");//style adding
}
document.getElementById('texteditorS').innerHTML=res;
setCursor(oldPos,document.getElementById('texteditor'));//set back cursor position
}

  oldWord = document.getElementById('texteditor').innerText;//old word for next time's reference

}

function replaceAll(array, find, replace) {
var arr = array;
for (let i = 0; i < arr.length; i++) {
    if (arr[i] == find)
        arr[i] = replace;
}
  return (arr);
}
function getCaretPosition(editableDiv) {
  var caretPos = 0,
    sel, range;
  if (window.getSelection) {
    sel = window.getSelection();
    if (sel.rangeCount) {
      range = sel.getRangeAt(0);
      if (range.commonAncestorContainer.parentNode == editableDiv) {
        caretPos = range.endOffset;
      }
    }
  } else if (document.selection && document.selection.createRange) {
    range = document.selection.createRange();
    if (range.parentElement() == editableDiv) {
      var tempEl = document.createElement("span");
      editableDiv.insertBefore(tempEl, editableDiv.firstChild);
      var tempRange = range.duplicate();
      tempRange.moveToElementText(tempEl);
      tempRange.setEndPoint("EndToEnd", range);
      caretPos = tempRange.text.length;
    }
  }
  return caretPos;
}
function setCursor(pos,editableDiv) {
if(!(pos == 0)){//if 0 it gives unwanted error
            var tag = editableDiv;
              
            // Creates range object
            var setpos = document.createRange();
              
            // Creates object for selection
            var set = window.getSelection();
              
            // Set start position of range
            setpos.setStart(tag.childNodes[0], pos);
              
            // Collapse range within its boundary points
            // Returns boolean
            setpos.collapse(true);
              
            // Remove all ranges set
            set.removeAllRanges();
            // Add range with respect to range object.
            set.addRange(setpos);
              
            // Set cursor on focus
            tag.focus();
            }
        }
.edit {
  border: 3px solid black;
  width: 100%;
  height: 500px;
  ;
  overflow: auto;
  flex: 1;
  word-wrap: break-word;
  word-break: break-all;
  white-space: pre-wrap;
  padding: 5px;
  font-family: Consolas, "courier new";
  font-size: 14px;
}

.styleA {
  color: red;
}

.styleB {
  color: blue;
}
#texteditorS{
pointer-events:none;  /*click through*/
position:relative;
bottom: calc(500px + 2 * (5px + 3px));/*overlay on top of editable div,500px is height,5px is padding,3px is border*/

}
<div id='texteditor'  class="edit" contenteditable></div>
<div id='texteditorS' class="edit"></div>

Features

  • support selection( ctrl-a ), arrow keys ...
  • many word,style support - just define variable
  • scrollable higlight
  • highly commented code

Idea

  • use another editor named texteditorS for style ,it overlaps the main editor,have click-through support for mouse to click the below/underlying editor
  • check whether any change in words has occured as it might be press of ctrl-a or arrow keys
  • sync-scroll of texteditor to texteditorS for scrolling styles
  • save the cursor position and after setting innerHTML set back cursor position.
Neptotech -vishnu
  • 1,096
  • 8
  • 23