regular expression for replacing only alphanumeric strings

I'm currently developing a tool that tags alphanumeric words based on the option selected from the right-click context menu. However, I am facing issues when a group of words containing special characters is selected.

I have been using the following RegEx that I came across on this very site: /(\s[a-zA-Z0-9]+)/g

To demonstrate the problem, try selecting 123b @#$@#$ or @#$@#$ a from the text, and then right-click and choose an option. The expected outcome should be [TAG] 123b @#$@#$ or @#$@#$ [TAG] a respectively.

There is also an issue when trying to tag the entire string:

<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="71031019041d31161c10181d5f121e1c">[email protected]</a> 123a % / ! @$# % % %^* && ^ Lorem ipsum

The expected output should be:
[TAG] <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="01736069746d41666c60686d2f626e6c">[email protected]</a>  [TAG] 123a % / ! @$# % % %^* && ^  [TAG] Lorem  [TAG] ipsum
.

The goal is to tag strings like 123abc, abc123, 12ab3 - regardless of the number of digits and letters. Additionally, if an email address is selected, it should also be tagged.

Any suggestions on how to resolve this issue?

jsFiddle

HTML:

<p contenteditable="true"><a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="dba9bab3aeb79bbcb6bab2b7f5b8b4b6">[email protected]</a> 123a % / ! @$# % % %^* && ^ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer augue tortor, dictum a turpis non, dapibus vehicula neque. 123b @#$@#$ a quam vel cursus. Duis at mattis quam, ornare consequat enim. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer augue tortor, dictum a turpis non, dapibus vehicula neque. Aliquam dictum a quam vel cursus. Duis at mattis quam, ornare consequat enim. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.</p>

JS:

function replaceText(selectedText, selectedTag){
    if(selectedText == "")
        return false;
    if(selectedText.match(/^[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/))
        replacedText = selectedText.replace(/(\s[a-zA-Z0-9]+)/g, " " + selectedTag + " " + "$1");
    else
        replacedText = selectedTag + " " + selectedText.replace(/(\s[a-zA-Z0-9]+)/g, " " + selectedTag + " " + "$1");
    originalText = $('p').html();
    newText = originalText.replace( new RegExp(selectedText,"g") , replacedText);
    $('p').html(newText);
}

Answer №1

Check out the revised code snippet below.

Important: The else condition has been modified to first eliminate all special characters and then substitute all instances of a string with [tag] + string.

HTML:

<p contenteditable="true"><a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7406151c0118341319151d185a171b19">[email protected]</a> 123a % / ! @$# % % %^* && ^ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer augue tortor, dictum a turpis non, dapibus vehicula neque. 123b @#$@#$ a quam vel cursus. Duis at mattis quam, ornare consequat enim. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer augue tortor, dictum a turpis non, dapibus vehicula neque. Aliquam dictum a quam vel cursus. Duis at mattis quam, ornare consequat enim. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.</p>

JavaScript:

var selectedTag, selectedText, originalText, newText, replacedText, selectedTextArray;

function getSelectedText() {
    var text = "";
    if (window.getSelection) {
        text = window.getSelection().toString();
    } else if (document.selection && document.selection.type != "Control") {
        text = document.selection.createRange().text;
    }
    return text;
}

function replaceText(selectedText, selectedTag){
    if(selectedText == "") {
        return false;
    }
    else {
        selectedText = selectedText.replace(/[^a-zA-Z0-9 ]/g,'');
        selectedText = selectedText.replace(/\s{2,}/g, ' ');
        selectedTextArray = selectedText.split(" ");
    }
    if(selectedTextArray.length > 0) {
        var selectedTextPart = '';
        originalText = $('p').html();
        newText = originalText;
        for(var i=0; i<selectedTextArray.length; i++) {
            selectedTextPart = selectedTextArray[i];
            selectedTextPart = new RegExp("\\b"+selectedTextPart+"\\b", "g");
            replacedText = selectedTag+' '+'$&';
            newText = newText.replace( selectedTextPart , replacedText);
        }
        $('p').html(newText);
    }
}

$.contextMenu({
    selector: 'p', 
    callback: function(key, options) {
        selectedTag = key;
        selectedText = $.trim(getSelectedText());
        replaceText(selectedText, selectedTag);
    },
    items: {
        "[ORG]": {name: "[ORG]"},
        "[PER]": {name: "[PER]"},
        "[LOC]": {name: "[LOC]"}
    }
});

Answer №2

They recommended keeping it simple.

I categorized every word into the following groups:

  1. containing only letters and numbers
  2. containing letters, numbers, periods, or commas
  3. emails

After that, I assigned a tag and inserted it back into the main text. That's all there is to it!

function updateText(selectedText, selectedTag){
    if(selectedText == "") {
        return false;
    }
    else{
        var selectedTextArray = selectedText.split(" ");

        originalText = $('p').html();

        selectedTextArray.forEach(function(item){
            if(item.match(/^[a-zA-Z0-9]+$/) // letters and numbers only
               || item.match(/^[a-zA-Z0-9.,]+$/) // letters, numbers, periods, or commas
               || item.match(/([a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+))/) // emails               
                ){
                    originalText = originalText.replace(new RegExp("\\b" + item + "\\b","g") , selectedTag + " " + item);

                }                 
        });
        newText = originalText;
    }

    $('p').html(newText);
}

Link to jsFiddle

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

Pattern: locate a sequence of three numerical digits within the provided whole number

As I am relatively new to Regexp, my current method involves using Regexp along with a loop: boolean match = false; int number = 0; String Str1 = String.valueOf(451999277); for (int i=0;match == false;i++) { //check the pattern through loop matc ...

Retrieving image source from JSON data using AngularJS

I am attempting to retrieve an image from an API using AngularJS. The approach I'm taking involves triggering the $http function with a link and attempting to extract the image URL from the JSON response to display it in the HTML. However, despite re ...

Invoke actions when clicking outside of components

Currently, I have a HeaderSubmenu component that is designed to show/hide a drop-down menu when a specific button is clicked. However, I am now trying to implement a solution where if the user clicks anywhere else in the application other than on this drop ...

Creating a Like button using react.js

How can I make only the selected button change, instead of all at the same time when clicked? I have implemented a function that includes a Boolean state and toggles it const [like, setLike] = useState(false); const handleLike=()=> { setLike(! ...

Having issues with AngularJS where ng-table/ng-repeat rows are failing to load properly

I've been following a tutorial on using ng-Table, which can be found Here. When I download the example from Git, it loads without any issues. However, when I try to replicate even the simplest example myself, the column headers and filters load but th ...

Troubleshooting HTTP requests in Angular JS when dealing with nested scopes

This particular question is derived from a previous answer found at this link. In my current scenario, I am attempting to initiate an http request where one of the data values that needs to be sent is represented in the view as {{selectedCountry.shippin ...

Automate the execution of webdriver/selenium tests when a form is submitted

I am currently faced with a challenge in setting up an application that will automate some basic predefined tests to eliminate manual testing from our workflow. The concept is to input a URL via a user-friendly form, which will then execute various tests ...

Changing the value within a deeply nested object

I am facing an issue with a nested object in my code: { id: "id", name: "Name", type: "SC", allgemein: { charname: "Name", spieler: "Jon", }, eigenschaften: { lebenspunkte: "30", }, talente: {}, zauber ...

Remove all $.ajax requests from content that has been loaded using $.ajax in jQuery

I'm currently working on a page where users can click a link to load content using $.ajax into a designated container div. However, I've encountered an issue with multiple clicks causing an increase in the number of $.ajax requests and resulting ...

developing a dropdown menu feature

I'm struggling with a small issue related to my drop-down menu function. My goal is to hide the visibility of a menu tab after it has been clicked for the second time. Below is the code snippet I've been working on: HTML:- <nav class="clea ...

Update issue with Material UI table rows when using setState method

Currently, I am facing an issue with passing content to my Material UI table using props. When props are passed explicitly, it works fine. However, I need to retrieve the props from a Firestore database and then pass them to the table. To achieve this, I a ...

The z-index overlapping problem in webkit browsers is a result of Angular 7 animations

I have implemented staggered animations in my Angular 7 application to bring elements to life upon page load. However, I am facing a strange z-index problem with one of my components. Here is the animation code: @Component({ selector: 'track-page& ...

Image carousel with interactive buttons

I've taken over management of my company's website, which was initially created by someone else at a cost of $24,000. We recently made some edits to the slideshow feature on the site, adding buttons that allow users to navigate to corresponding p ...

Unable to retrieve all the necessary data from the LinkedIn API

I have attempted the following: Code Snippet in HTML: <a id="li_ui_li_gen_1432549871566_0-link" class="" href="javascript:void(0);" onclick="onLinkedInLoad();" style="margin-bottom: 20px;"> Javascript Function: function onLinkedInLoad(logintype) ...

Using a Javascript for loop to extract the initial event date from a Google Calendar

In my home.html file, the script below is responsible for: Connecting the website to a Google Calendar API Fetching dates and names of rocket launches My concern arises when a calendar for the same rocket has multiple launches in a single month. I aim fo ...

The attempt to decode the string from POST using json_decode failed due to a hang-up in

I'm currently learning about PHP, JSON, and JavaScript. I am facing an issue with using the json_decode function in PHP after receiving a JSON string from JavaScript. I am able to save the JSON string to a file without any problem, but when I try to ...

What methods are available for updating the href color of an element using the DOM?

I am looking to update the color of a tab (Mathematics-tab) based on the value of 'aria-selected' changing to true in Bootstrap. I have multiple tabs, including one for mathematics, and I want to visually differentiate between selected and unsele ...

The ng-model binding does not automatically update another ng-model within the same object

Check out this code snippet: http://plnkr.co/edit/aycnNVoD96UMbsC7rFmg?p=preview <div data-ng-app="" data-ng-init="names=['One']"> <input type="text" ng-model="names[0]"> <p>Using ng-repeat to loop:</p> <ul> ...

Conceal the title attribute when hovering over a link using javascript/jquery

I have implemented the title attribute for all my links, but I want it to be hidden during mouse hover while still accessible to screen readers. var linkElements = document.getElementsByTagName('a'); for (var index = 0; index < linkElements. ...

The uiGmapGoogleMapApi.then function is failing to execute on Android devices

I successfully incorporated angular-google-maps into my Ionic project - in index.html, I included the following scripts: <script src="lib/lodash.min.js"></script> <script src="lib/angular-google-maps.min.js"></script> Within my vi ...