javascript – How to change color to specific word of HTML code/format?

Question:

A small functionality that allows to change the color of specific HTML word, but currently it only applies a single color and there is a small cursor stuck at the time of writing it does not flow normally, I think that it can be avoided to create so many case , if some HTML words are going to have the same color, I think you can change for another alternative, say

[P,DIV,SPAN,FONT];

Those words are going to have a tomate color

And so go playing with assignable colors by saying the following:

[BR,H1,H2,H3];

Apply an orange color.

How to make the color change functionality work properly?

$("#editor").on("keydown keyup", function(e){
    if (e.keyCode == 32){
        var text = $(this).text().replace(/[\s]+/g, " ").trim();
        var word = text.split(" ");
        var newHTML = "";

        $.each(word, function(index, value){
            switch(value.toUpperCase()){
                case "DIV":
                case "SPAN":
                case "P":
                    newHTML += "<span class='statement'>" + value + "&nbsp;</span>";
                    break;
                default: 
                    newHTML += "<span class='other'>" + value + "&nbsp;</span>";
            }
        });
      	$(this).html(newHTML);
         
    }
});
#editor {
    width: 400px;
    height: 100px;
    padding: 10px;
    background-color: #444;
    color: white;
    font-size: 14px;
    font-family: monospace;
}
  
.statement {
    color: orange;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="editor" contenteditable="true"></div>

Answer:

For this case, you could use arrays of elements that contain the tags which will be evaluated to apply a certain color. and use includes() to find out if the current element exists in the previously declared array.

In addition, a function would be needed to manipulate the focus of the contenteditable, using Ranges (function commented in the code)

Your code with the mentioned modifications

$(function() {
	let colorTomate = ['P','DIV','SPAN','FONT'];
	let colorAnaranjado =['BR','H1','H2','H3'];
	$("#editor").on("keydown", function(e){
		let key = e.which || e.charCode || e.keyCode;
	    if (key == 32){
	        let text = $(this).text().replace(/[\s]+/g, " ").trim();
	        let words = text.split(" ");
	        let newHTML = "";
	        $.each(words, function(index, value){
	        	if(colorTomate.includes(value.toUpperCase())){
	        		newHTML += "<span class='color2'>" + value + "&nbsp;</span>";
	        	}
	        	else if(colorAnaranjado.includes(value.toUpperCase())){
	        		newHTML += "<span class='statement'>" + value + "&nbsp;</span>";
	        	}
	        	else{
	        		newHTML+= value + "&nbsp;";
	        	}
	        });
	      	$(this).html(newHTML); 
	      	setFocusEndElement(this);

	    }

	});

	function setFocusEndElement(element){
		if(document.createRange)
	    {
	    	// creamos el rango
	        let rango = document.createRange();
	        //Seleccionamos el contenido del elemento, div
	        // para este caso, pasado como parámetro 
	        rango.selectNodeContents(element);
	        // El paso más importante, collapse colocar
	        // el cursor al final del range (fragmento de nodos o texto) , el div 
	        // en este caso
	        rango.collapse(false);
	        //Remover el foco actual en la ventana
	        //obtenemos la selección
	        seleccionaFinal = window.getSelection();
	        //para luego remover los rangos de selección
	        seleccionaFinal.removeAllRanges();
	        // luego añadimos el rango donde queremos que el focus se posicione
	        // que será al final del contenido
	        seleccionaFinal.addRange(rango);
	    }  
	}
});
#editor {
    width: 400px;
    height: 100px;
    padding: 10px;
    background-color: #444;
    color: white;
    font-size: 14px;
    font-family: monospace;
}

.color2 {
    color: yellow;
}

.statement {
    color: orange;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="editor" contenteditable="true"></div>

It will work, but the process is not optimal as it is processing all the content again every time the space key is pressed. For which it would be advisable not to touch the already processed components and only work on the current one. For this we would use the split function through the entity &nbsp; (the insertion of this entity in the if else would be modified)

Possible code explained (To Improve)

$(function() {
	let colorTomate = ['P','DIV','SPAN','FONT'];
	let colorAnaranjado =['BR','H1','H2','H3'];
	$("#editor").on("keydown", function(e){
		let key = e.which || e.charCode || e.keyCode;
	    if (key === 32){
	    	//Todo el contenido HTML
	        let prevHtml =  $(this).html().split("&nbsp;");
	        // obtenemos el último elemento ingresado
	        let value = prevHtml.pop();
	        // Inicializamos la variable con el contenido anterior
	        let newHTML = prevHtml.toString();
	        // Procesamos el contenido o etiqueta ingresada final
        	if(colorTomate.includes(value.toUpperCase().trim())){
        		newHTML += "<span class='color2'>" + value + "</span>&nbsp;";
        	}
        	else if(colorAnaranjado.includes(value.toUpperCase().trim())){
        		newHTML += "<span class='statement'>" + value + "</span>&nbsp;";
        	}
        	else{
        		newHTML+= value + "&nbsp;";
        	}	
		    $(this).html(newHTML);
		    setFocusEndElement(this);
	    }
	});

	function setFocusEndElement(element){
		if(document.createRange)
	    {
	    	// creamos el rango
	        let rango = document.createRange();
	        //Seleccionamos el contenido del elemento, div
	        // para este caso, pasado como parámetro 
	        rango.selectNodeContents(element);
	        // El paso más importante, collapse colocar
	        // el cursor al final del range (fragmento de nodos o texto) , el div 
	        // en este caso
	        rango.collapse(false);
	        //Remover el foco actual en la ventana
	        //obtenemos la selección
	        seleccionaFinal = window.getSelection();
	        //para luego remover los rangos de selección
	        seleccionaFinal.removeAllRanges();
	        // luego añadimos el rango donde queremos que el focus se posicione
	        // que será al final del contenido
	        seleccionaFinal.addRange(rango);
	    }  
	}
});
#editor {
    width: 400px;
    height: 100px;
    padding: 10px;
    background-color: #444;
    color: white;
    font-size: 14px;
    font-family: monospace;
}

.color2 {
    color: blue;
}

.statement {
    color: orange;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="editor" contenteditable="true"></div>
Scroll to Top