Enclosing every single word in an <a> tag and giving emphasis to both the start and finish of each word

Every word includes a start, end, and also returns as text. My goal is to enclose each word within an <a> tag while highlighting them individually.

identifyComplexWords(text, words) {
  // list of "complex words"
  const complexWords = words;
  // array to store results
  const results = [];
  // loop through each complex word and search for occurrences in the text
  let match, regexp;

  for (let i = 0; i < complexWords.length; i++) {
    // the current complex word being checked
    const complexWord = complexWords[i];
    regexp = new RegExp(complexWord, 'g');

    while ((match = regexp.exec(text)) !== null) {
      // create result object
      const result = {
        begin: (regexp.lastIndex - complexWords[i].length),
        end: regexp.lastIndex,
        text: complexWord
      };
      // add the result object to the array
      const index = results.length;
      results[index] = result;
      console.log(results[index]);
    }
  }
  // return the results array 
  return results;
}

The output of this function would be:

{begin: 6, end: 11, text: "Lorem"}
{begin: 112, end: 117, text: "Lorem"}
{begin: 218, end: 223, text: "Lorem"}

I have a function that wraps words in an <a> tag and highlights them, here is the function:

highlightSelection() {
  this.identifyComplexWords(this.postIWant, this.theHardWords);
  const userSelection = window.getSelection();
  if (userSelection.toString() === null) {
    return;
  } else {
    for (let i = 0; i < userSelection.rangeCount; i++) {
      this.highlightRange(userSelection.getRangeAt(i));
      this.word = userSelection.toString();
    }
  }
}

guidGenerator() {
  const S4 = () => {
    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
  };
  return (S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4());
}

highlightRange(range) {
  const newNode = document.createElement('a');
  newNode.id = this.guidGenerator();
  newNode.className = 'annotation_class';
  newNode.setAttribute(
      'style',
      'background-color: yellow; display: inline;'
    ),
    range.surroundContents(newNode);
  this.viewAnnotation(newNode.id);
}

Although the above function works manually, I need to automate it when running the identifyComplexWords function for each word to be enclosed within an <a> tag and highlighted.

If anyone has any suggestions on how to achieve this, I would greatly appreciate it. Thank you in advance!

Answer №1

If I don't need a list of all word indexes, the basic String.replace() method would be my choice even if I'm missing some requirements.

const generateGuid = () => {
  const S4 = () => {
    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
  };
  return (S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4());
};
const wordsToHighlight = [
  "Lorem",
  "ipsum",
  "foo",
  "bar",
  "baz"
];
const applyHighlight = (node, words) => {
  const textContent = node.innerHTML;
  const highlightedText = words.reduce((text, word) => {
    return text.replace(new RegExp(word, 'g'), `<a id="${generateGuid()}" class="highlighted">${word}</a>`);
  }, textContent);
  node.innerHTML = highlightedText;
};

applyHighlight(document.querySelector('#text_snippet'), wordsToHighlight);
.highlighted {
  background-color: steelblue;
  color: white;
}
<div id="text_snippet">Lorem ipsum dolor sit amet, pri posse veniam eu. Adhuc appareat argumentum has cu. Vim cu tale moderatius. Eos cu nostrud vocibus offendit.</div>

Answer №2

The solution I found really helped me overcome the problem at hand.

By using the provided method, I was able to automatically enclose the words in an <a> tag and highlight them.

fetchWords(words) {
    this.highlightedWords(words);
}

highlightedWords = (words) => {
    const highlighter = document.getElementById('scrollable');
    const content = highlighter.innerHTML.split(' ');
    const result = [];

    content.map(word => {
        let highlightedWord = word;
        if (words.indexOf(word) > -1) {
            highlightedWord = '<a class="clickable" style="background-color: yellow;">' + word + '</a>';
        }
        result.push(highlightedWord);
    });
    highlighter.innerHTML = result.join(' ');
}

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

What is the best way to send the name of a list item to a different component in React?

Looking for some help with my current project: https://i.sstatic.net/soj4q.jpg I'm working on implementing the 'Comment' feature, but I'm stuck on how to pass the name of a list item to the 'Comment' component header. You c ...

Can you trigger a button click on one HTML page from another HTML page?

I am working on a project with two custom HTML pages: 'first.html' and 'second.html'. In 'second.html', there is a hidden div that I want to unhide when a button on 'first.html' is clicked. Both pages should be open ...

Ways to substitute real Image with a placeholder image if the image is missing

Is there a way to replace an unavailable image with a dummy image in this code snippet? <div className="bg-[#F8F8F8] flex items-center justify-center px-2 py-10"> <Image src={image} alt="course image" width={100} height={10 ...

Tips for implementing JavaScript or jQuery to enable page transitions in a single-page website

Currently, I am in the process of developing a website that encompasses both front-end and back-end elements. One challenge I am facing involves figuring out how to utilize JavaScript/jQuery to transition between pages within a single-page website. The ta ...

Tips for displaying line breaks in a textarea and transferring data from JavaScript to the content of textarea

Seeking user input in a <textarea>, displaying it on the DOM with an edit button and preserving line breaks. When the user clicks edit, the old data is shown in a new <textarea> with breaklines. Adding an item. <form name="add" ...

JavaScript loop to target a specific item

My goal is to animate the correct div under each navigation item, rather than all of them with the "navItemUnder" class. You can see exactly what I mean by hovering over a navigation item in this codePen. I am looking for a solution to target only one lin ...

flexbox used to create a fixed sidebar on the left

I want to create a fixed left sidebar using flexbox. The sidebar should have its own scroll bar if the content is long, and I don't want it to move when I scroll down the main content. Check out this example for reference: http://codepen.io/tedartus ...

What are the steps for generating and implementing shared feature files in Cucumber?

I am currently utilizing Cucumber to define some tests for the project I am working on, but as the application grows larger, I find myself in need of a more efficient structure. project | feature_files | | app1.js | | app2.js | | app3.js ...

The offsets for selecting text are not accurate when multiple values share the same text

I am faced with a text that goes like this -> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type ...

New button attribute incorporated in AJAX response automatically

data-original-text is automatically added in ajax success. Here is my code before: <button type="submit" disabled class="btn btn-primary btn-lg btn-block loader" id="idBtn">Verify</button> $(document).on("sub ...

Locate all inputs containing a specific class that do not contain a value using jQuery

I am trying to implement a basic validation script that will check for any inputs with the class .required. The goal is to return false if the values are either blank or 0 upon form submission. However, the current code I have does not seem to be working a ...

What is causing the elements to not fill the entire width of the page?

How can I make 6 flex items have the same width and occupy the full width with minimal margins between them? Currently, there is too much margin, especially on larger screens. Any suggestions on how to achieve this without excess spacing? Thanks! Example: ...

Button image malfunctions upon submission of form

I've been attempting to switch the src of an image within a button element upon form submission. Strangely, when the form is submitted, the new image src fails to load (appearing as a broken link in Chrome and nothing in FF). However, if I include ret ...

problem with parsing JSON

Here is a JSON string example: {"time":"2011-11-30 04:44","countryName":"Austria","sunset":"2011-11-30 16:32","rawOffset":1,"dstOffset":2,"countryCode":"AT","gmtOffset":1,"lng":10.2,"sunrise":"2011-11-30 07:42","timezoneId":"Europe/Vienna","lat":47.01} I ...

Utilizing a functional component to incorporate a "load more" button in ReactJS

Hey everyone, I've come across this ReactJS code that I need some help with: function DisplaySolutions({solutions}) { const topSolutions = solutions.slice(0, 4); const remainingSolutions = solutions.slice(4); const [isD ...

"Choosing the text within an <a> tag: A step-by

I am dealing with the a tag. <a href="mailto:<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b4c7dbd9d1f4d9d5ddd89ad7dbd9">[email protected]</a>"><a href="/cdn-cgi/l/email-protection" class="__cf_email__" ...

Delete the selected background color from custom drop-down lists in versions of Internet Explorer 9 and earlier

In my asp.net application, I have a dropdown element. I am trying to remove the default blue background color that appears when the dropdown is selected, as shown in the image below. I have tried all the solutions provided in this link, but none of them s ...

Guide on updating a table with query parameters in Html Agility Pack using C#

Struggling with parsing this URL using the Html Agility Pack: " The default table that shows up is always based on the closest contract date and the current date. I can parse the entire page without any issues, but when I try to request a different date ...

Pondering in AngularJS - what is the best way to alter the DOM during an AJAX call?

I'm completely new to AngularJS and trying to transition from a jQuery background. After reading through "Thinking in AngularJS if I have a jQuery background?" on Stack Overflow, I understand the concept but am struggling to implement it without depen ...

What could be the reason for the lack of scrolling on a webpage despite having content in django?

I am experiencing an issue with my code that connects base.html to index.html using Django. Despite adding the overflow css attribute, the content on the page is not scrolling down as expected. Here are the relevant snippets: The base.html file: < ...