JavaScript causing display issues with Unicode characters

convert.onclick =
  function() {
    for (var i = 0; i < before.value.length; i++) {
      after.value += "'" + before.value.charAt(i) + "', ";
    }
  }
<textarea id="before" type="text" name="input" style="width:100%;">*𝟑(𝟘)-_=+π•’β„šπ•¨π•Žπ•–π”Όπ•£β„π•₯𝕋π•ͺπ•π•¦π•Œ</textarea><br />
<textarea id="after" cols="50" rows="10" name="output" style="width:100%;"></textarea>
<button id="convert" name="convert" type="button">convert</button>

After running the code, I observed different results with a successful conversion of some letters. However, most Unicode characters did not display correctly. How can this issue be resolved?

Answer β„–1

Encountering an issue known as surrogate pairs is what you're facing right now. Some unicode characters consist of two bytes instead of one, and if they are separated, they will not be displayed correctly.

If ES6 is available to you, utilizing the spread operator or for..of syntax when iterating through a string takes into consideration surrogate pairs, making it easier to obtain accurate results. Other solutions in this thread demonstrate how to achieve this.

For those unable to utilize ES6, MDN provides an example of how to handle these situations using the charAt method, which can be found here. The code snippet below demonstrates this approach.

function getWholeChar(str, i) {
  var code = str.charCodeAt(i);

  if (Number.isNaN(code)) return '';
  if (code < 0xD800 || code > 0xDFFF) return str.charAt(i);

  if (0xD800 <= code && code <= 0xDBFF) {
    if (str.length <= (i + 1)) throw 'High surrogate without following low surrogate';
    var next = str.charCodeAt(i + 1);
    if (0xDC00 > next || next > 0xDFFF) throw 'High surrogate without following low surrogate';
    return str.charAt(i) + str.charAt(i + 1);
  }
  
  if (i === 0) throw 'Low surrogate without preceding high surrogate';
  var prev = str.charCodeAt(i - 1);

  if (0xD800 > prev || prev > 0xDBFF) throw 'Low surrogate without preceding high surrogate';
  return false;
}

convert.onclick =
  function() {
    for (var i = 0, chr; i < before.value.length; i++) {
      if(!(chr = getWholeChar(before.value, i))) continue;
      after.value += "'" + chr + "', ";
    }
  }
<textarea id="before" type="text" name="input" style="width:100%;">*𝟑(𝟘)-_=+π•’β„šπ•¨π•Žπ•–π”Όπ•£β„π•₯𝕋π•ͺπ•π•¦π•Œ</textarea><br />
<textarea id="after" cols="50" rows="10" name="output" style="width:100%;"></textarea>
<button id="convert" name="convert" type="button">convert</button>

Answer β„–2

If you want to create an array of unicode characters, you can utilize the spread operator (...)

convert.onclick = function () {
after.value = [...before.value].map(s => `'${s}'`).join(",");
};
<textarea id="before" type="text" name="input" style="width:100%;">*𝟑(𝟘)-_=+π•’β„šπ•¨π•Žπ•–π”Όπ•£β„π•₯𝕋π•ͺπ•π•¦π•Œ</textarea><br />
<textarea id="after" cols="50" rows="10" name="output" style="width:100%;"></textarea>
<button id="convert" name="convert" type="button">convert</button>

Answer β„–3

The reason for this is that in UTF-8, characters can have a length greater than 1 once you reach a certain point.

console.log("9".length);
console.log("𝟑".length);

console.log("𝟑".charAt(0));
console.log(String.fromCodePoint("𝟑".codePointAt(0)));

To solve this issue, use codePoint and codePointAt instead of charAt:

convert.onclick =
  function() {
    for (const char of before.value) {
      after.value += `'${String.fromCodePoint(char.codePointAt(0))}'`;
    }
  }
<textarea id="before" type="text" name="input" style="width:100%;">*𝟑(𝟘)-_=+π•’β„šπ•¨π•Žπ•–π”Όπ•£β„π•₯𝕋π•ͺπ•π•¦π•Œ</textarea><br />
<textarea id="after" cols="50" rows="10" name="output" style="width:100%;"></textarea>
<button id="convert" name="convert" type="button">convert</button>

You can also traverse based on index, but you'll need to adjust the index variable within the loop based on the length of the currently traversed character:

convert.onclick =
  function() {
    for (let i = 0; i < before.value.length; ) {
      after.value += `'${String.fromCodePoint(before.value.codePointAt(i))}'`;
      i+= String.fromCodePoint(before.value.codePointAt(i)).length;
    }
  }
<textarea id="before" type="text" name="input" style="width:100%;">*𝟑(𝟘)-_=+π•’β„šπ•¨π•Žπ•–π”Όπ•£β„π•₯𝕋π•ͺπ•π•¦π•Œ</textarea><br />
<textarea id="after" cols="50" rows="10" name="output" style="width:100%;"></textarea>
<button id="convert" name="convert" type="button">convert</button>

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

Update the scrollspy navigation in a div with overflow by toggling the active class

Struggling to implement a navigation menu within a self-scrolling div using html/css/jquery. Looking for the menu items to toggle the active class when in view or at the top of the scrolling div. I'm essentially trying to achieve something like this ...

Create a new modal design by keeping the structure but updating the text and images for

Is there a way to simplify the process of creating multiple modals on my website without having to duplicate and adjust the code each time? I would appreciate any assistance in achieving this! I have a specific modal template that I want to replicate, wit ...

Using HTTPS, you can access Flask from AJAX

I have encountered numerous inquiries concerning this issue, but none have proven effective for me. I recently switched my domain from HTTP to HTTPS. Everything was functioning properly on HTTP. The main issue lies in the fact that my javascript and flask ...

angular 4+ dynamically assign @Input for components created using ngComponentOutlet

If you are using Angular 4 and need to dynamically generate a component, you can utilize the ngComponentOutlet directive. Here is a reference link for more information: https://angular.io/docs/ts/latest/api/common/index/NgComponentOutlet-directive.html Fo ...

Securing uploaded documents and limiting access to approved individuals

Currently, I am utilizing Multer for file uploads and I am contemplating the ideal approach to secure access to these files post-upload. In my system, there are two user roles: admin and regular user. Users can only upload photos while only admins have ac ...

Issue with Google Maps API - Error: google object is undefined

Currently, I am in the process of learning how to develop Google Maps by analyzing some basic examples provided by Google. In my Angular 9 application, I utilize Angular Google Maps to showcase a Google Map. However, as I implement this feature, I encounte ...

Adding an AngularJS directive dynamically that utilizes a $http request for fetching data

Currently facing an intriguing issue, I am attempting to create something like this: input key 1 , input value 1 input key 2 , input value 2 < button to add more > < submit button > Essentially, a user can click submit and send a Get req ...

Step-by-step guide on achieving a radiant glow effect using React Native

I am looking to add a glowing animation effect to both my button and image elements in React Native. Is there a specific animation technique or library that can help achieve this effect? While I have this CSS style for the glow effect, I am uncertain if ...

How can I replace any non-alphanumeric characters in a string with an underscore using JavaScript or TypeScript?

There is a unique string generated from an external data source that I cannot manage. The system above me necessitates the IDs to adhere to this rule: "Field names should start with a letter and can solely consist of letters, numbers, or underscores (&apos ...

One of the components in React failed to render even though data was successfully passed to both

I utilized React to create a submenu list. The parent component receives JSON data and passes it down to two child components. However, only one of the child components successfully displays the data while the other fails to do so. Both child components ...

Utilizing setColumns() function within Google Charts for JSON data tables

Is there a feature in the Google Charts API that functions similar to setColumns() for working with JSON data? I'm aiming to reduce PHP calls by consolidating my data into a single array and then specifying which columns Google Charts should utilize. ...

There are no HTTP methods being exported in this specific file. Remember to export a named export for each individual HTTP method

Currently, I am working on a React.js/Next.js project that incorporates Google reCAPTCHA. The frontend appears to be functioning properly as I have implemented print statements throughout the code. However, I am encountering an error in the backend display ...

Struggling to repair the unresponsive on-click event even after thorough debugging efforts

i am working on a project where i have to create a datatable, but I am facing an issue with the edit event not firing on click. Even after debugging, it is not pointing towards any error. function GetLoginData() { $.ajax({ url: '/LoginMas ...

Functionality issue with Datatables within JQuery-UI Tabs

I'm experiencing an issue with the compatibility of jQuery-UI tabs and Datatables. My goal is to create a scrollable table that displays information fetched from a database. Upon initially loading the page, the table appears like this. It looks like ...

What is the best way to display items using Typeahead.js in combination with the Bloodhound engine?

I am struggling to showcase a collection of items using typeahead with a JSON file as the data source. Unfortunately, none of my information is appearing on the screen. My objective is to list the names and utilize the other attributes for different purpo ...

Performing a bulk upsert operation by utilizing the $in operator in the update criteria

As I create a procedure to handle an array of strings like var mywords = ["cat", "dog", "fish"] and insert them into the 'words' collection in MongoDb, I aim to keep track of the insertion count for each word. Some words may already exist in t ...

Exploring the power of Firebase with Vue Js lifecycle methods

I am attempting to retrieve data from a specific user in Firebase and push that data into designated input fields. The path in Firebase is located here: var query = db.ref('Clients/'+ clientName +'/form/'); I retrieve the data in the ...

What is the process for assigning one file input to another file input?

Quite an unusual question, I admit. The crux of the matter is my utilization of a fantastic tool known as cropit. With this tool, we have the ability to upload an image, preview it, and then manipulate it according to our preferences. HTML: <div align ...

Tips for retaining spaces in a multiline string when setting a helm value using cdktf

Currently, I am utilizing CDKTF to facilitate the deployment of the datadog helm chart into a kubernetes cluster. My objective is to assign a specific value to confd, however, the issue arises when the spaces in my typescript multiline string do not mainta ...

Trigger controller redirection in AngularJS 1.5.0 by clicking on <tr> tag

Currently, I am facing an issue with my web page where I use the ng-repeat directive to populate a table with a list of companies. My goal is to have a functionality where clicking on a table row opens another page with a form to edit the selected company. ...