Verify if spacebar is pressed and then use jQuery to add a hashtag with multi-language support

I am attempting to use jQuery to add a hashtag (#) after the user types and presses space. I have created a demonstration on CodePen.

In this demo, when you type something like (how are you), the JavaScript code will change it to (#how #are #you).

To achieve this, I am checking the words for adding the #(hashtag) tag using the function addHashtags(text) { ... }.

1-) Everything works correctly for English characters. However, I want to extend this functionality to support multiple languages. The issue arises when typing Turkish characters like (üğşıöç). For example, when I type the word (üzüm) or (hüseyin), the JavaScript should convert them to (#üzüm #hüseyin) but instead, it adds extra symbols like this: (#ü#zü#m #hü#seyin). (Issue Resolved)

2-) Another challenge is with other languages such as Arabic, Azerbaijan, Japanese, and so on. The JavaScript does not add the #(hashtag) tag when typing in these languages. For instance, typing (

私は家族と一緒に行きます
) or (
ผมไปกับครอบครัวของฉัน
) does not trigger any changes. This is a significant problem that requires a solution. (Issue Resolved)

3-) In the demo, I have used textInput. It works on mobile devices but not on Firefox. If I switch to using keypress, the code functions on Firefox but not on mobile. I need the code to work seamlessly across all devices. (Issue Resolved)

// Your custom JS code goes here...

Answer №1

I have created a solution that is close to perfect for you. Feel free to check it out on Codepen!

Here is the complete code:

var input;

function diez(event){
   var s = event.target.selectionStart;
   var e = event.target.selectionEnd;
   var v = event.target.value;
   var c = v.length;
       v = v.replace(/[^a-z0-9\s]/ig, ""); // line 8
   var a = v.split(" ");
   var b = [];

   /* Remove this if-block if you want undeletable diez */
   if(v == ""){
      event.target.value = v;
      return;
   }
   /* --- */

   for(var i = 0; i < a.length; i++){
      var token = a[i];
      if(i == 0) b.push("#" + token);
      else if(i > 0){
         var previous = a[i-1];
         if(previous.toLowerCase() != token.toLowerCase() && token != "")
            b.push("#" + token);
         else if (token == "")
            b.push(token);
      }
   }

   b = b.join(" ");
   c = b.length - c;
   event.target.value = b;
   event.target.selectionStart = s + c;
   event.target.selectionEnd = e + c;
}

$(document).ready(function() {
   input = document.getElementById("text");
   input.addEventListener("keyup", diez, true);
});
  • Uses jQuery solely for document ready event.
  • Saves user selection and cursor position.
  • Pure Vanilla Javascript code.
  • Swapped content-editable div with a proper <input>.
  • Triggers on keypress rather than space press.

UPDATE

  • You are restricted from typing special characters: only letters a-z, 0-9, and whitespaces are allowed. You can customize permitted characters in line 8 (e.g., Russian, Turkish).

  • Tokens that resemble each other are discarded.

Answer №2

JavaScript Regular Expressions in ES5 do not support Unicode characters out of the box. In order to work with Unicode literals, you need to use \u (Unicode escape sequences) or utilize libraries like XRegExp that provide Unicode properties support.

When you incorporate XRegExp into your project, you can convert traditional Regular Expressions into Unicode-aware patterns. This allows you to utilize Unicode properties such as \p{L} or shorthand \pL.

I made some adjustments to your code to enable this functionality:

text = XRegExp.replaceEach(text, [
            [/#\s*/g, ""],
            [/\s{2,}/g, " "],
            [XRegExp(`(?:\\s|^)([\\p{L}\\p{N}]+)(?=\\s|$)(?=.*\\s\\1(?=\\s|$))`, "gi"), ""],
            [XRegExp(`([\\p{N}\\p{L}]+)`, "g"), "#$1"]
         ]);

The first two regexes are familiar, but the third one may seem complex. By breaking it down, you will see that (?:\\s|^) and (?=\\s|$) equate to \b. However, due to the ASCII-only interpretation of word boundary by \b, I had to structure it that way.

Try the live demo!

Breakdown:

  • \p{L} matches any letter from any language.
  • \p{N} matches any numeric character in any script.

Learn more about Unicode categories.

Answer №3

To improve the code that replaces spaces with dashes, try using the following:

   $("body").on("keyup", "#text", function() {
      $("#ad_text").html($(this).html().replace(/\s/g,"-"));
      go();
   });

This will automatically update your #ad_text by replacing all spaces with dashes. After this change, transitioning to "#" should be relatively simple.

The original code was incorrectly calling .replace on the jQuery return item rather than the .html.

Answer №4

If you want to display the text "#Hi #bro #how #are #you?", you can achieve it using the following code:

$(document).ready(function() {
   $("body").on("keyup", "#text", function(e) {
      // Add space after pressing return
      if(e.keyCode == 13) { 
         $(this).text($(this).text()+' ');
      }
      // Format div content after pressing space or return
      if(e.keyCode == 32 || e.keyCode == 13) {
          var content =  $(this).text();
          // Format content
          content = '#' + content.replace(/#+/g, '').replace(/\s+/g, ' #');
          // Set content
          $(this).html(content);
          // Put cursor at the end of div
          cursorManager.setEndOfContenteditable(this);
      }
   });
});

The solution to move the cursor can be found in cursorManager.setEndOfContenteditable()

1) To detect duplicates, convert the content variable into an array using split(), check for duplicates in this array and then use join() to transform the array back into a string.

2) To prevent entering _-?*/()=&%+^#'<|>.,;! characters, write a function to remove these characters and call it every time a key is pressed. Include your function at the beginning of the keyup event function.

Answer №5

This simple Javascript function efficiently adds a unique tag to each word in a given string:

function addDiszTag(str){
        //  var str = "Hello there how are you?"
        str = str.split(' ');

        //Output will be converted to ["Hello", "there", "how", "are", "you?"]
        var transformedArr = [];
        str.forEach(function(word){transformedArr.push("#"+word) })

        // Resulting array: ["#Hello", "#there", "#how", "#are", "#you?"]

        return transformedArr.join(' '); 

       //Returns "#Hello #there #how #are #you?"

    }

An additional validation could be added to prevent duplicate tags from being generated. I hope this explanation is helpful!

Answer №6

JS does not have a strong understanding of Unicode, so you can use equivalent UTF-16 ranges instead that correspond to the \p{alnum} property.

I suggest pre-compiling this to store it in a global variable.

This regex will match a leading whitespace (or beginning of string) when followed by an alnum character. You can then replace it with the whitespace + #.

The regular expression pattern is for a leading whitespace:

/(^|\s)(?=<see below>/g;

where Rx is used globally like this:

newSrc = strSrc.replace(Rx, "$1#");

The regular expression pattern expressed rawly:

(^|\s)(?=(?:[\u0030-\u0039\u0041-\u005A...]))/g

Answer №7

My belief is that this solution will suffice.

ATTENTION: I find it peculiar why you specifically required hitting the space or enter key. However, doing so can lead to some complications. For instance, if someone changes their mind and deletes input with the backspace key, the output hash tags will remain unchanged as the event does not get triggered without hitting the spacebar. That's why I utilized the keyup function.

    $("body").on("keypress", "#text", function(e) {
        if (e.which > 33 && e.which < 48 || e.which > 57 && e.which < 65 || e.which > 90 && e.which < 96 || e.keyCode === 13)
        {
            e.preventDefault();
        }
    });
    $("body").on("keyup", "#text", function(e) {
        var array = new Array();
        var diez = new Array();

        temparray = $('.addiez').html().split(" ");
        l = temparray.length;
        temparray[l-1] = temparray[l-1].replace(/&nbsp;/gi,'');

        $.each(temparray, function(i, el){
            el = el.replace(/&nbsp;/gi,'');
            el = el.toLowerCase();
            if($.inArray(el, array) === -1) array.push(el);
        });

        for (var i = 0; i < array.length; i++) {
            diez[i] = "#" + array[i] + " ";
        }
        $("#ad_text").html(diez);
    });
  .container {
   position:relative;
   width:100%;
   max-width:600px;
   overflow:hidden;
   padding:10px;
   margin:0px auto;
   margin-top:50px;
}
* {
   box-sizing:border-box;
   -webkit-box-sizing:border-box;
   -moz-box-sizing:border-box;
}
.addiez {
   position:relative;
   width:100%;
   padding:30px;
   border:1px solid #d8dbdf;
   outline:none;
   font-family: helvetica, arial, sans-serif;
   -moz-osx-font-smoothing: grayscale;
   -webkit-font-smoothing: antialiased;
}
.addiez::-webkit-input-placeholder {
   /* Chrome/Opera/Safari */
   color: rgb(0, 0, 1);
}
.addiez[contentEditable=true]:empty:not(:focus):before  {
      content:attr(placeholder);
      color: #444;
    }

.note {
   position:relative;
   width:100%;
   padding:30px;
   font-weight:300;
   font-family: helvetica, arial, sans-serif;
   -moz-osx-font-smoothing: grayscale;
   -webkit-font-smoothing: antialiased;
   line-height:1.8rem;
   font-size:13px;
}
.ad_text {
   position:relative;
   width:100%;
   padding:10px 30px;
   overflow:hidden;
   font-weight:300;
   font-family: helvetica, arial, sans-serif;
   -moz-osx-font-smoothing: grayscale;
   -webkit-font-smoothing: antialiased;
   line-height:1.8rem;
   font-size:13px;
   text-transform: capitalize;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
   <div class="addiez" contenteditable="true" id="text" placeholder="Write something with space"></div>
   <div class="ad_text" id="ad_text"></div>
   
   <div class="note">For example: When you write like: Hi bro how are you? Then jquery should change this text like this:
   #Hi #bro #how #are #you? I meant when user pressed space or pressed enter then add diez tag before the text like my exapmle.</div>
</div>

I included text-transform: capitalize; because I prefer it :) However, you have the option to disable it if desired.

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

implementing HtmlSpanner with an appended css stylesheet

Using HtmlSpanner with CSS for TextView I recently discovered a library called HtmlSpanner that claims to assist in adding an HTML string with CSS to a TextView. However, I am struggling to locate any detailed documentation on how to achieve this, except ...

Is it possible to utilize the useRef Hook for the purpose of storing and accessing previous state values?

If you have already implemented the useState and useEffect Hooks for maintaining previous state, another approach is to utilize the useRef Hook to track previous state values as well. ...

Adjusting the zoom feature in CSS3

I'm looking to have my React app display as if the user has changed the zoom level to 90%. I attempted to tackle this issue using CSS. body { transform: scale(0.9); } However, this method did not result in the screen appearing similar to wh ...

Ways to display the data within a BLOB object

On this page, the user is showcasing a table with three columns - tipo_esame (string), data_esame (string), and uri (BLOB). const archiveItems = this.state.archive.map((archive, i) => { return ( <tr key={archive.hash_referral}> <td ...

Managing the AJAX response from a remote CGI script

I'm currently working on a project that involves handling the response of a CGI script located on a remote machine within a PHP generated HTML page on an apache server. The challenge I am facing relates to user authentication and account creation for ...

Developer server experiencing CSS issues in Django admin interface

Experiencing some odd issues with the Django admin application here. I've got everything up and running on the manage.py runserver development server, but for some reason it looks like this: This obviously isn't what I want, so I'm trying t ...

What is the process for incorporating Material-UI into a JSFiddle project?

I'm having trouble figuring out how to load and use the Material UI script on platforms like JSFiddle or SO's code editor, even though I can add it with NPM. Check out this JSFiddle example <script src="https://unpkg.com/@material-ui/core/um ...

Is there a way to display my array within my React component using JavaScript?

I am working with an element that looks like this: const DropdownElements = [ { key: 1, title: "City", placeholder: "Select City", apiUrl: "https://api.npoint.io/995de746afde6410e3bd", type: "city&qu ...

What could be the reason for the lack of styling on the select element when using PaperProps in the MenuProps of my Select component?

I've been struggling to remove the white padding in this select box for a while now. I've tried countless variations and places to tweak the CSS with no success. Any suggestions on how to make it disappear? The project is using MUI 5, and I even ...

I encountered a response error code 500 from the development server while using my emulator

As I embark on setting up the react-native environment for development, I encounter an error when executing the command react-native run-android. root@pc:~/l3/s2/DevMobMultipltm/Wakapp# ` A series of tasks are carried out including scanning folders for sy ...

The shared hosting environment encountered an error during the Next JS build process

When I execute the command "npm run build" on my shared hosting server, it throws an error message: spawn ENOMEM. Interestingly, this command runs perfectly fine on my localhost and has been running smoothly on the hosting server for a few weeks until yest ...

How can I adjust the border opacity in a React application?

Can we adjust the border color opacity in React when using a theme color that is imported? For example, if our CSS includes: borderBottomColor: theme.palette.primary.main and we are importing the theme with Material UI using makeStyles, is there a way to ...

Using AJAX for form submission and managing the response in a Wordpress site

I have a website built on Wordpress. I have created a contact form that is submitted using AJAX. Below is the code snippet: <script type="text/javascript"> jQuery(document).ready(function(){ $("#error_box").hide(); $('#contact_form&ap ...

What advantages does $sce or Strict Contextual Escaping provide in AngularJS, and why is it unnecessary for React?

I find it perplexing that I am unable to fully grasp the true value of utilizing SCE in AngularJS (even after reviewing the documentation) when it comes to security benefits. It leaves me wondering why React does not require SCE. So, to summarize my quest ...

What is the process for tallying checked checkboxes in a functional component using React Native?

The Whole Code is Right Here Within this code, you will find two flat lists: one displaying category names and the other showing their subcategories with checkboxes. I am looking to implement a feature where if a user checks multiple or just one checkbox ...

Tips on Guaranteeing AJAX Requests are Successfully Called in Sequential Order and Receive Responses in the Same Sequence

What is the best way to guarantee that AJAX requests are executed in a specific order and receive responses in the same order? ...

"Addclass() function successfully executing in the console, yet encountering issues within the script execution

I dynamically created a div and attempted to add the class 'expanded' using jQuery, but it's not working. Interestingly, when I try the same code in the console, it works perfectly. The code looks like this: appending element name var men ...

Provide details on the final parameters

After creating my discord.js bot, I had the idea to implement a translator feature. To achieve this, I need to extract the last argument from incoming messages. client.on("message", async (message, args) => { if (message.content.startsWith(` ...

The jQuery change function appears to be functioning properly, but it is not producing any results

I am facing an issue with my jQuery code that rebuilds a dropdownlist based on the radio buttons selected. Although the code seems correct and the method works properly, the dropdownlist items do not update as expected. Can anyone provide some insight or i ...

Implementing a jQuery for loop to iteratively print my function with increasing values

I'm currently facing a perplexing issue, but the solution should be straightforward. My mind is completely stuck and I can't figure out where I'm going wrong. Simply put, I want to repeat my function three times as illustrated below: If my ...