javascript - Modify the text color of the final word entered

I am currently working on a text editor project and one of the requirements is to change the font color of the last word typed based on whether it is a keyword or not. Despite trying various solutions, I have yet to find one that works as intended. Here is an overview of what I have attempted so far:

function getLastWord() {
        var input = document.getElementById("my_text").value;
        //var input = document.getElementById(textArea.value);

        var inputValue = input.value;
        var lastWordTyped
        var changeColorOfWord;
        var ele = document.querySelector("#my_text");

        //ele.style.color = "blue"

        if (input == null) {
            input == " ";
        }

        lastWordTyped = input.substr(input.trim().lastIndexOf(" ") + 1);
        //lastWordTyped = inputValue.substr(inputValue.trim().lastIndexOf(" ") + 1);

        if (input != null) {

            for (var i = 0; i < reservedKeyWords.length; i++) {
                if ( lastWordTyped == reservedKeyWords[i] ) {

                    //changeColor(lastWordTyped);
                    //my_text.replace(inputValue, lastWordTyped);
                    //ele.fieldNameElement.innerHTML = lastWordTyped;
                    //ele.innerHTML = lastWordTyped;
                    ele.innerHTML.fontcolor = 'Blue';
                    return;

                } else if (lastWordTyped !== reservedKeyWords[i]) {

                    //ele.innerHTML = ele.innerHTML.replace(lastWordTyped, '<span style="color:black"></span>');
                    //resetFontColor();


                }


            }
        }
    }

One function I tried was sourced from SO and looks like this:

function changeColor(word) {
        var ele = document.querySelector("my_text");
        ele.onkeypress = function () {
            setTimeout(function () {
                document.getElementById('view_text').value = ele.textContent;
                if (ele.innerHTML.indexOf(word) !== -1) {
                    ele.innerHTML = ele.innerHTML.replace(word, '<span style="color:blue">' + word + '</span>');
                }
            }, 50);
        }
    }

In addition, I also experimented with the following function:

function colorMyKeyword(keywordColor, text) {

        return '<span style="color:' + keywordColor + '>' + text + '</span>';
    }

Unfortunately, none of these functions have produced the desired outcome. Although I have managed to change the text color to blue, the issue arises when all the text switches to blue after the specified word...

It would be preferable for me to implement this in javascript since I am not well-versed in JQuery, CSS, or script writing in general...

Your valuable responses are greatly appreciated. Thank you.

Answer №1

Code updated based on feedback (changed to div from input field)

Although not perfect, this code should do the job. It is recommended to handle CSS changes by adding a class rather than modifying the style attribute.

<div id="my_text">This text will be altered</div>

var isKeyword = false;
var element = document.getElementById('my_text');
var array = element.innerHTML.split(' ');
var lastWord = array.pop();

/* customize with your keywords */
var reservedKeywords = ['change','this','word', 'too'];


for (var index = 0, length = reservedKeywords.length ; index < length ; index++) {
  if ( lastWord == reservedKeywords[index] ) {
    lastWord = '<span style="color:blue">'+lastWord +'</span>'; //update color
    array.push(lastWord);
    isKeyword = true;
  }
}
if (!isKeyword) { array.push(lastWord); } //retain original word
element.innerHTML = array.join(' ');

Answer №2

UPDATED: Trigger the action on keyup event

Check out this straightforward example to see it in action: DEMO

$('#text').keyup(function(){
    $('#result').html($('#text').val());
    var splittedText=$('#result').html().split(/\s/);
    var lastWord=splittedText[splittedText.length-1]; 
    $('#result').html($('#result').html().replace(lastWord,'<span>'+lastWord+'</span>'));
    $('#result').children('span').css('color',$('#color').val());
});

Enter a sentence in the first input and a hexadecimal color code (starting with #) in the second one.

Answer №3

Trying to address your inquiries:
Referencing @GaryStorey's solution which provided a better foundation compared to my own contributions (I appreciate using pop and push).
The issue with the aforementioned solution was its focus solely on changing colors, without addressing manipulation within an input or contenteditable element.

Therefore, here are my modifications, introducing a setCaret function to manage the scenario where caret repositions to the beginning upon altering the innerHTML of the edited element.

Caution: This code remains prone to bugs and should not be implemented in a production environment,
however, it can offer a strong starting point.

var reservedKeyWords = ['text', 'another', 'word', 'here'];
        var el = document.getElementById('my_text');
        el.addEventListener('keyup', function (evt) {
            if (evt.keyCode == 32 || evt.keyCode == 13) {
                var isKeyword = false;
                var arr = el.innerHTML.split(/\s/);
                var lastWordTyped = arr.pop();
                lastWordTyped = lastWordTyped.replace('&nbsp;', '');
                for (var i = 0, len = reservedKeyWords.length; i < len; i++) {
                    if (lastWordTyped == reservedKeyWords[i]) {
                        lastWordTyped = '<span style="color:blue">' + lastWordTyped + '</span>'; //update color
                        arr.push(lastWordTyped);
                        isKeyword = true;
                    }
                }
                if (!isKeyword) {
                    arr.push(lastWordTyped);
                } //put original back
                el.innerHTML = arr.join(' ') + '&nbsp;';
                setCaret(el);
            }
        });

        function setCaret(el) {
            var range = document.createRange();
            var endNode = el.lastChild;
            range.selectNodeContents(endNode);
            range.setStart(endNode, range.endOffset);
            range.setEnd(endNode, range.endOffset);
            var sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
        }
#my_text {
    min-width: 100%;
    min-height: 2em;
    padding: 0.5em;
    display: block;
    border : dashed 0.5px grey;
}
<p> list of KeyWords : 'text', 'another', 'word', 'here';</p>
<span id="my_text" contenteditable="true">Edit me using "reservedKeyWords" defined in JS</span>

Also, worth noting that I opted for a span over a div due to the latter adding unneeded <br> tags after the textNode.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Accessing/Storing Pictures in MongoDB using Mongoose

I've been struggling with managing images in MongoDB for a while now. Everywhere I look suggests using GridFS because of the 16mb size limit per document. However, the documents I want to store are all <16mb each. Currently, I am storing it like th ...

Is it possible for the box-shadow CSS property to include padding?

Can a red outline like this be created around a shape using the box-shadow property but at a certain distance? ...

Failed to cast to ObjectID due to mongoose error

Hello, I am facing an issue while attempting to add an event to a user's profile upon clicking on the event. The error message I'm encountering is "Cast to ObjectId failed for value "{ event: '600066640807165d042b91dd' }" at path "event ...

Tips for handling special characters in formData when making a jQuery POST request

How can I effectively pass $scope.data.responseFields=CustType,AddedDt? I have attempted to use toString() to convert it into a string value before passing it as data, but the result is being passed as responseFields=CustType%252CAddedDt. I also tried usi ...

How can I create a table without a bottom border?

click here for image instructions on creating a table using CSS I'm struggling to achieve the desired result The goal is to remove borders at the end of the table I can't seem to figure it out I can't seem to figure it out Removing borders ...

Previewing multiple images before uploading them using jQuery

Currently, I am utilizing the following code for my image uploader: HTML: <input type="file" id="files" name="files[]" multiple /> <ul id="list"></ul> JavaScript: function handleFileSelect(evt) { var files = evt.target.files; // FileL ...

jQuery - Show or hide content with a toggle action

Is there a way to toggle the text on a button once certain content is visible? Can the content be hidden if the button is clicked again? To better illustrate, check out this example: JSFiddle I am looking to switch the button text from 'View content ...

When trying to run the "npm start" command, I encountered a syntax error that specifically mentioned the use of

Every time I attempt to run the npm start command, I encounter the following error: I have followed the steps provided in this link: https://github.com/kriasoft/react-starter-kit/blob/master/docs/getting-started.md Could you please advise on how to resolve ...

Is there a way to display the result array in Node.js after a MongoDB find query has been executed?

I'm new to Node.js and I'm trying to pass an array of data to a controller. However, I'm facing some challenges in inserting for loop data into the array and also looking to access the resulting data outside the function. router.get("/list- ...

I'm struggling to grasp how to effectively utilize a JSON Object in this situation

In my coding project, I am looking to utilize Javascript in order to create a JSON or array that will house pairs of data for 'id' and 'ip'. This way, if I need to retrieve the 'ip' for a specific 'id=123', I can eas ...

What is the best method to style a child input element's placeholder using Tailwind CSS?

I'm currently working on a project and trying to translate a CSS style that targets the ::placeholder pseudo-element into Tailwind CSS. However, I have encountered some challenges during this process as I'm not entirely sure of the correct approa ...

The function findOne from Mongoose seems to be non-existent, all while utilizing the Passport library

Whenever I try to implement my local strategy using the passport lib, I keep encountering this error. TypeError: UserModel.findOne is not a function I've spent hours searching for a solution that addresses this issue but haven't been successful ...

Populate the dropdown list with option values based on the selection made in the preceding dropdown menu

I have a coding challenge with two drop-down lists. One is labeled "Specialization" and contains options like General, Cardiologist, Pediatrician, etc. The second one is labeled "Doctor" and includes the names of different doctors as options. What I am try ...

Using Protractor to extract text from multiple paragraphs

How do I retrieve the values of all paragraphs (p) at once? Below is an example of how my inspect view appears: "Testing sample one." "Testing sample two." And here is a snippet of my code to extract the value of id 'run': browser.findElement ...

What is the reason behind frameworks and similar tools choosing to deprecate functions rather than simply updating them?

Take, for instance, the deprecation of jQuery's .live() in favor of .on(), and the transition from mysql_* to mysqli in MySQL. Why do frameworks and programming languages choose to phase out old functions rather than simply updating them? Apologies if ...

Troubleshooting Vue.js rendering problems on Safari_BROWSER

I'm encountering a strange issue with my portfolio website, which is built using Vue and Laravel. The problem arises specifically in Safari - the project thumbnails don't display until the browser window is resized. Here's the relevant code ...

Retrieve data from XML file using ThickBox

How can I dynamically load content from an XML file into a DIV when a user clicks on specific links? I was successful in loading the correct content by matching arguments passed through a function invoked onClick. Now, I am attempting to display this conte ...

Warning Notification in Opencart Design

Currently, I am working on an OpenCart project that is nearing completion. One issue that I am facing is that whenever a user clicks on another tab, Java displays an alert containing an error message. This seems to be happening due to slow internet speed ...

Tips for minimizing deep nesting of asynchronous functions in Node.js

I have a goal to create a webpage that showcases data fetched from a database. To achieve this, I've written functions to retrieve the necessary information from the DB using Node.js. Being relatively new to Node.js, my understanding is that to displa ...

The NGRX state in Angular is not being properly saved by the local storage

Currently, I am utilizing NGRX for state management within my Angular application. While NGRX is functioning correctly, I have encountered an issue with using local storage to persist the NGRX state. Upon refreshing the browser, the NGRX data reverts back ...