Precise width of a monospace character - javascript

I'm working on a code editor with syntax highlighting and I need to know the precise width of a monospace character. I use this value to calculate the position of a character on a line, which I need to know so I can place various GUI elements, such as text cursors (there can be multiple), selection rectangles, warning tooltips, etc. Up until now I've been using the following function:
function getCharacterWidth(char, fontFamily, fontSize) {
let span = document.createElement("span");
span.style.fontFamily = fontFamily;
span.style.fontSize = fontSize;
span.style.position = "absolute";
span.style.visibility = "hidden";
span.style.width = "auto";
span.style.whiteSpace = "nowrap";
span.style.padding = "0";
span.style.margin = "0";
span.style.letterSpacing = "0px";
span.style.wordSpacing = "0px";
span.innerText = char;
document.body.appendChild(span);
let width = span.getBoundingClientRect().width;
span.remove();
return width;
}
It has been working great, but then I noticed a problem on Google Chrome. When my text editor is rendering a large line, with thousands of characters, the character position is not being properly calculated because of rounding issues. It seems that on Google Chrome, the width returned by getBoundingClientRect() has a precision of at most 5 decimal places, which is not ideal for my use case. On Firefox, the precision seems to be much higher, going up to 15 decimal places, which is why I never had this problem there.
After some digging, I heard about this idea of calculating the width of a character based on the width of a span containing thousands of that character (https://stackoverflow.com/a/56379770/2197150). So, in my original function I replaced span.innerText = char with span.innerText = char.repeat(10000) and returned width / 10000. It helped, but the calculation is still perceptibly off when I'm dealing with large lines.
So here I am. How can I calculate the width of a character with high precision, like Firefox does, in other browsers?

This is not a clean solution, but I suspect there is no really clean solution.
You could keep a "column map", based on the syntax formatting <span>s you already have flying around. Say your highlighter gives you:
<div class="line">
var long_line_of_variables = <span class="number">123</span>;
</div>
you could measure this span's left offset + the column it appears in (= length of textContent of the siblings before it = 29) and arrive at
colums = {
'29': 290.456
}
Now you can interpolate that column 14 is at 290.456*14/29=140.22 pixels.
The more spans we add, the better we can guess:
colums = {
'29': 290.456,
'2900': 28997.000 // whoops, not what we would have calculated!
}
This method is heuristic, so you'll need to find a strategy, which will work across browsers, zoom/font-scale settings etc., including
adding more and more spans to this "map"
but maybe "cleaning" it once in a while?
keep a global map or one per line?
be smart about interpolation: pick the nearest map entry (in the best interval between entries)
add more "span probes"
split long lines without any formatting into chunks of N characters, wrapping them in spans, or inserting empty spans in between
maybe just a probe span right at the end of each line?
Having worked on similar problems and heuristics, my advice would be: don't. :)
It involves lots of tweaking and testing, and probably is a cross-platform nightmare (e.g. compare font rendering and rounding in Firefox on Win vs Linux vs MacOS vs iOS). Instead, try to attach anything to a localized span. I understand that this is probably way harder -- lots of text editors struggle with long lines, esp. when it comes to MB-size compiled JS...

I came up with a solution that has been working well for my use case. The idea is to calculate the width of a character based on the largest line of my editor. My line elements look something like this:
<div class="line"><span class="keyword">let</span><span class="space"> </span><span class="identifier">foo</span></div>
If we want to calculate the width of a character based on that line, here is what we do:
let lineElement = document.querySelector(".line");
let lineWidth = lineElement.getBoundingClientRect().width;
let charWidth = lineWidth / lineElement.textContent.length;
I keep track of the largest line I've rendered in my editor. Whenever I render a new largest line, I update charWidth based on that new line.
This allows me to calculate the position of a character at any given column within a line by doing a simple multiplication column * charWidth. It has been working pretty well so far, even for lines with 100000+ characters.
There is, however, one last thing I had to do to handle even larger lines. It seems that there is a bug on Google Chrome where, when you try to render a line with a huge text node, e.g. <span>many many characters...</span>, it will not give you the correct width of the element (see Inaccurate width of large element on Chrome). To overcome this issue, whenever I have to render a huge text, I split it into multiple spans, e.g. <span>many many </span><span>characters...</span>.
Now I can render 500000 characters long lines with font size 48 with no problems. Above that, things start to get weird again, with miscalculations and other weird browser behaviors. So I decided to set a hard limit of 500000 characters rendered in a line. Everything beyond the 500000nth characters is hidden from the user.

Related

Can you force a string to split into 'n' lines?

On a website I'm designing, I have a page with rows of categories thumbnails and their titles.
The problem is : some category titles are long, other are shorts... depending on the monitor width some will take 2 lines of text, or even 3, but not the others, creating ugly staircases.
I've managed to identify the highest title and min-height every other one accordingly with javascript.
But, it's still ugly. To make it better, I'd want every title to break into as many lines than the longest one.
That's where I come short... I couldn't find a way to do that so far.
Here's how it is now :
Here's the intended result :
Any idea how I could accomplish this ?
If you want to do that with a javascript solution you can count characters or words and add <br> after n amount. Here is a sample that will add a line break after every 20 characters:
var string = document.getElementById('text');
string.innerHTML = string.textContent.replace(/(.{20})/g, "$1<be>");
Then you can create a function with a loop for each element and do some if statement logic there. For example - add a break if the character count is more than...

How to get the number of lines in a text file without opening it?

I'm developing this code that, after the user selects a directory, it display a table of the files contained in that location with their details (name, type, size ...).
A directory may contain a lot of files.
I succeeded to achieve that. But, my problem is that I want to display the number of lines in each file. I can get the number of lines using this JavaScript code :
var reader = new FileReader();
var textFile = $("#file").get(0).files[0];
reader.readAsText(textFile);
$(reader).on('load', processFile);
/*And in processFile() i use this line to get the number of lines :*/
nbLines = (file.split("\n")).length;
The above code work as expected and it give me what I want, but it may a heavy process if there is so many files in the selected directory!
The Question : Is there a way to get the number of lines in a text file without reading it?
Regards!
You can't count the number of lines in a file without reading it. The operating systems your code runs on do not store the number of lines as some kind of metadata. They don't even generally distinguish between binary and text files! You just have to read the file and count the newlines.
However, you can probably do this faster than you are doing it now, if your files have a large number of lines.
This line of code is what I'm worried about:
nbLines = (file.split("\n")).length;
Calling split here creates a large number of memory allocations, one for each line in the file.
My hunch is that it would be faster to count the newlines directly in a for loop:
function lineCount( text ) {
var nLines = 0;
for( var i = 0, n = text.length; i < n; ++i ) {
if( text[i] === '\n' ) {
++nLines;
}
}
return nLines;
}
This counts the newline characters without any memory allocations, and most JavaScript engines should do a good job of optimizing this code.
You may also want to adjust the final count slightly depending on whether the file ends with a newline or not, according to how you want to interpret that. But don't do that inside the loop, do it afterward.
There is not way to know the number of lines without opening the document. Regarding the performance issues that you are having it comes from the .split() most probably.
You are loading the file as a string in memory and then generating as many strings as lines are in this files.
If a file contains 1000 lines of code the resulting ram usage will be
1 String (whole files)
1000 Strings (1 string per line)
I would recommend chaging this for a evaluation using RegEx. Here's an example
var file = ("this\nis a string\n with new\nlines");
var match = file.match(/\r?\n/g);
alert(match.length);
Keep in mind that a different regex might be required depending on your files.
This will surely improve the performance.
Update for 2021:
Reading the file as text is always a bad idea. With current optimised languages, almost all languages are super fast in processing loops, so looping will always be faster than loading the text into memory and splitting.
for NodeJS, please see ReadLine. Although not recommended to do such operations in node, being Single Threaded, I can read Big CSVs pretty fast using ReadLine.
A text file usually contains an operation line at the bottom of the screen which allows you to place the cursor on the screen and shows the line and location of the character it is located. In which case if the cursor is at the last character the total lines would be indicated.

Split Long Filename string in two Lines with Adobe Javascript

I am newbie using Javascript in Adobe. I have written script that catch the file name and add it as a title in the document, but problem is it doesn't split in 2 lines long file names. So long text file names are out of the page border.
For example file name is
"This is a text that I need to split in two lines How to write the script in order to split the long text and fit in the page"
This is just a sample. What I need to edit? And is it possible?
var trFileName = this.documentFileName.replace(/.*\/|\.pdf$/ig,""); //remove .pdf extension
var pageAmount = this.numPages; //define how many pages are there
this.addWatermarkFromText({
cText: trFileName,
nStart: 0,
nEnd: pageAmount,
nFontSize: 18,
aColor: color.blue,
cFont: "Helvetica-Bold",
nTextAlign: app.constants.align.center,
nHorizAlign: app.constants.align.center,
nVertAlign: app.constants.align.top,
//nHorizValue: -25,
nVertValue: -87.87
})
So looking at the documentation for Acrobat the quick way to do this is to add and use the bPercentage: -1 property which ought to scale the watermark to fit the page with a max of 100%. Obviously, the longer the text, the smaller the the typesize, but it ought to only scale when needed.
The big problem here is "how big is too big?" Since most fonts are not fixed-width. So if you do not have some function to check the size of the type in that font, you would need to set up a temp image, set the type, then measure the dimensions of the image, then decide how much to break the text.
The worst case for English though is probably going to be an endless string of W, so if you want to hard code the font size and some reasonable character limit, you can get a reasonable max character count by counting how many Ws it takes to go out of bounds.
Once you have that number you can split the string.
One way to split a string is to use substring:
var cDisplayText = trFilename;
var nMaxChars = 10;
var cAdobeNewline = '\r';
var cLineBreakChar = '-';
if (cDisplayText.length > nMaxChars && cDisplayText.length > 0) {
cDisplayText = cDisplayText.substring(0, nMaxChars)
+ cLineBreakChar
+ cAdobeNewline
+ cDisplayText.substring(nMaxChars);
}
And then replace cText: trFileName, with cText: cDisplayText,
I have not tested this and my javascript has atrophied a little, but the idea is to test the string length and insert a hyphen and a line break.
This (obviously) does not account for case where there is more than 1 line break required.

Ensure fixed number of decimal points when using Kendo formatting

I have played around with Kendo formatting. Specifically I am using kendo.format and kendo.toString()
I would like to fix the number of decimal points.
kendo.format("{0:#.#%}",22) works well, but it doesn't include a trailing zero for whole numbers. Ex: It doesn't give me 22.0%.
kendo.toString(22,"p1") can be used to ensure the decimal point, but it adds an undesirable space between the number and the percentage sign.(e.g.22 %).
Is there a way to ensure the trailing 0 in the formatted value (with no space before the percentage sign)? Or do I have to add code to remove the space manually?
I can easily remove it using a simple .replace(" ", ""), but I am just curious if there is a built in way to control it.
You can use zeros instad of the sharp symbols. Thus you ensure there will be a digit rendered even if it is not needed.
e.g.
kendo.format("{0:0.0%}",0.22)
Here is live example, Here is the documentation.

Numbers localization in Web applications

How can I set the variant of Arabic numeral without changing character codes?
Eastern Arabic ۰ ۱ ۲ ۳ ٦ ٥ ٤ ۷ ۸ ۹
Persian variant ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹
Western Arabic 0 1 2 3 4 5 6 7 8 9
(And other numeral systems)
Here is a sample code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div lang="fa">0123456789</div>
<div lang="ar">0123456789</div>
<div lang="en">0123456789</div>
</body>
</html>
How can I do this using only client-side technologies (HTML,CSS,JS)?
The solution should have no negative impact on page's SEO score.
Note that in Windows text boxes (e.g. Run) numbers are displayed correctly according to language of surrounding text.
See also: Numbers localization in desktop applications
Note: Localisation of numbers are super easy on backend using this PHP package https://github.com/salarmehr/cosmopolitan
Here is an approach with code shifting:
// Eastern Arabic (officially "Arabic-Indic digits")
"0123456789".replace(/\d/g, function(v) {
return String.fromCharCode(v.charCodeAt(0) + 0x0630);
}); // "٠١٢٣٤٥٦٧٨٩"
// Persian variant (officially "Eastern Arabic-Indic digits (Persian and Urdu)")
"0123456789".replace(/\d/g, function(v) {
return String.fromCharCode(v.charCodeAt(0) + 0x06C0);
}); // "۰۱۲۳۴۵۶۷۸۹"
DEMO: http://jsfiddle.net/bKEbR/
Here we use Unicode shift, since numerals in any Unicode group are placed in the same order as in latin group (i.e. [0x0030 ... 0x0039]). So, for example, for Arabic-Indic group shift is 0x0630.
Note, it is difficult for me to distinguish Eastern characters, so if I've made a mistake (there are many different groups of Eastern characters in Unicode), you could always calculate the shift using any online Unicode table. You may use either official Unicode Character Code Charts, or Unicode Online Chartable.
One has to decide if this is a question of appearance or of transformation. One must also decide if this is a question involving character-level semantics or numeral representations. Here are my thoughts:
The question would have entirely different semantics, if we had a situation where Unicode had not sparated out the codes for numeric characters.
Then, displaying the different glyphs as appropriate would simply be a matter of using the appropriate font. On the other hand, it would not have been possible to simply write out the different characters as I did below without changing fonts. (The situation is not exactly perfect as fonts do not necessarily cover the whole range of the 16-bit Unicode set, let alone the 32-bit Unicode set.)
9, ٩ (Arabic), ۹ (Urdu), 玖 (Chinese, complex), ๙ (Thai), ௯ (Tamil) etc.
Now, assuming we accept Unicode semantics i.e. that '9' ,'٩', and '۹' are distinct characters, we may conclude that the question is not about appearance (something that would have been in the purview of CSS), but of transformation -- a few thoughts about this later, for now let us assume this is the case.
When focusing on character-level semantics, the situation is not too dissimilar with what happens with alphabets and letters. For instance, Greek 'α' and Latin 'a' are considered distinct, even though the Latin alphabet is nearly identical to the Greek alphabet used in Euboea. Perhaps even more dramatically, the corresponding capital variants, 'Α' (Greek) and 'A' (Latin) are visually identical in practically all fonts supporting both scripts, yet distinct as far as Unicode is concerned.
Having stated the ground rules, let us see how the question can be answered by ignoring them, and in particular ignoring (character-level) Unicode semantics.
(Horrible, nasty and non-backwards compatible) Solution: Use fonts that map '0' to '9' to the desired glyphs. I am not aware of any such fonts. You would have to use #font-face and some font that has been appropriately hacked to do what you want.
Needless to say, I am not particularly fond of this solution. However, it is the only simple solution I am aware of that does what the question asks "without changing character codes" on either the server or the client side. (Technically speaking the Cufon solution I propose below does not change the character codes either, but what it does, drawing text into canvases is vastly more complex and also requires tweaking open-source code).
Note: Any transformational solution i.e. any solution that changes the DOM and replaces characters in the range '0' to '9' to, say, their Arabic equivalents will break code that expects numerals to appear in their original form in the DOM. This problem is, of course, worst when discussing forms and inputs.
An example of an answer taking the transformational approach is would be:
$("[lang='fa']").find("*").andSelf().contents().each(function() {
if (this.nodeType === 3)
{
this.nodeValue = this.nodeValue.replace(/\d/g, function(v) {
return String.fromCharCode(v.charCodeAt(0) + 0x0630);
});
}
});
Note: Code taken from VisioN's second jsFiddle. If this is the only part of this answer that you like, make sure you upvote VisioN's answer, not mine!!! :-)
This has two problems:
It messes with the DOM and as a result may break code that used to work assuming it would find numerals in the "standard" form (using digits '0' to '9'). See the problem here: http://jsfiddle.net/bKEbR/10/ For instance, if you had a field containing the sum of some integers the user inputs, you might be in for a surprise when you try to get its value...
It does not address the issue of what goes on inside input (and textarea) elements. If an input field is initialised with, say, "42", it will retail that value. This can be fixed easily, but then there is the issue of actual input... One may decide to change characters as they come, convert the values when they changes and so on and so forth. If such conversion is made then both the client side and the server side will need to be prepared to deal with different kinds of numeral. What comes out of the box in Javascript, jQuery and even Globalize (client-side), and ASP.NET, PHP etc. (server-side) will break if fed with numerals in non-standard formats ...
A slightly more comprehensive solution (taking care also of input/textarea elements, both their initial values and user input) might be:
//before the DOM change, test1 holds a numeral parseInt can understand
alert("Before: test holds the value:" +parseInt($("#test1").text()));
function convertNumChar(c) {
return String.fromCharCode(c.charCodeAt(0) + 0x0630);
}
function convertNumStr(s) {
return s.replace(/\d/g, convertNumChar);
}
//the change in the DOM
$("[lang='fa']").find("*").andSelf().contents()
.each(function() {
if (this.nodeType === 3)
this.nodeValue = convertNumStr(this.nodeValue);
})
.filter("input:text,textarea")
.each(function() {
this.value = convertNumStr(this.value)
})
.change(function () {this.value = convertNumStr(this.value)});
//test1 now holds a numeral parseInt cannot understand
alert("After: test holds the value:" +parseInt($("#test1").text()))
The entire jsFiddle can be found here: http://jsfiddle.net/bKEbR/13/
Needless to say, this only solves the aforementioned problems partially. Client-side and/or server-side code will have to recognise the non-standard numerals and convert them appropriately either to the standard format or to their actual values.
This is not a simple matter that a few lines of javascript will solve. And this is but the simplest case of such possible conversion since there is a simple character-to-character mapping that needs to be applied to go from one form of numeral to the other.
Another go at an appearance-based approach:
Cufon-based Solution (Overkill, Non-Backwards Compatible (requires canvas), etc.): One could relatively easily tweak a library like Cufon to do what is envisaged. Cufon can do its thing and draw glyphs on a canvas object, except that the tweak will ensure that when elements have a certain property, the desired glyphs will be used instead of the ones normally chosen. Cufon and other libraries of the kind tend to add elements to the DOM and alter the appearance of existing elements but not touch their text, so the problems with the transformational approaches should not apply. In fact it is interesting to note that while (tweaked) Cufon provides a clearly transformational apprroach as far as the overall DOM is concerned, it is an appearance-based solution as far as its mentality goes; I would call it a hybrid solution.
Alternative Hybrid-Solution: Create new DOM elements with the arabic content, hide the old elements but leave their ids and content intact. Synchronize the arabic content elements with their corresponding, hidden, elements.
Let's try to think outside the box (the box being current web standards).
The fact that certain characters are unique does not mean they are unrelated. Moreover, it does not necessarily mean that their difference is one of appearance. For instance, 'a' and 'A' are the same letter; in some contexts they are considered to be the same and in others to be different. Having, the distinction in Unicode (and ASCII and ISO-Latin-1 etc. before it) means that some effort is required to overcome it.
CSS offers a quick and easy way for changing the case of letters. For instance, body {text-transform:uppercase} would turn all letters in the text in the body of the page into upper case. Note that this is also a case of appearance-change rather than transformation: the DOM of the body element does not change, just the way it is rendered.
Note: If CSS supported something like numerals-transform: 'ar' that would probably have been the ideal answer to the question as it was phrased.
However, before we rush to tell the CSS committee to add this feature, we may want to consider what that would mean. Here, we are tackling a tiny little problem, but they have to deal with the big picture.
Output:
Would this numerals-transform feature work allow '10' (2-characters) to appear as 十(Chinese, simple), 拾 (Chinese, complex), X (Latin) (all 1-character) and so on if instead of 'ar', the appropriate arguments were given?
Input:
Would this numerals-transform feature change '十'(Chinese, simple) into its Arabic equivalent, or would it simply target '10'? Would it somehow cleverly detect that "MMXI" (Latin numeral for 2012) is a number and not a word and convert it accordingly?
The question of number representation is not as simple as one might imagine just looking at this question.
So, where does all this leave us:
There is no simple presentation-based solution. If one appears in the future, it will not be backwards compatible.
There can be a transformational "solution" here and now, but even if this is made to work also with form elements as I have done (http://jsfiddle.net/bKEbR/13/) there need to be server-side and client-side awareness of the non-standard format used.
There may be complex hybrid solutions. They are complex but offer some of the advantages of the presentation-based approaches in some cases.
A CSS solution would be nice, but actually the problem is big and complex when one looks at the big picture which involves other numeric systems (with less trivial conversions from and to the standard system), decimal points,signs etc.
At the end of the day, the solution I see as realistic and backwards compatible would be an extension of Globalize (and server-side equivalents) possibly with some additional code to take care of user input. The idea is that this is not a problem at the character-level (because once you consider the big picture it is not) and that it will have to be treated in the same way that differences with thousands and decimal separators have been dealt with: as formatting/parsing issues.
I imagine the best way is to use a regexp to search what numeric characters should be changed via adding a class name to the div that needs a different numeric set.
You can do this using jQuery fairly easy.
jsfiddle DEMO
EDIT: And if you don't want to use a variable, then see this revised demo:
jsfiddle DEMO 2
I have been working on a general web page localization technique that does more than just numbers (its similar to .po files)
The localization files are simple (the strings can contain html if needed)
/* Localization file - save as document_url.lang.js ... index.html.en.js: */
items=[
{"id":"string1","value":"Localized text of string1 here."},
{"id":"string2", "value":"۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ "}
];
rtl=false; /* set to true for rtl languages */
This format is useful to separate out for translators (or mechanical turk)
and a basic page template
<html><meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<head><title>My title</title>
<style>.txt{float:left;margin-left:10px}</style>
</head>
<body onload='setLang()'>
<div id="string1" class="txt">This is the default text of string1.</div>
<div id="string2" class="txt">0 1 2 3 4 5 6 7 8 9 </div>
</body></html>
<script>
function setLang(){
for(var i=0;i<items.length;i++){
term=document.getElementById(items[i].id)
if(term)term.innerHTML=items[i].value
if(rtl){ /* for rtl languages */
term.style.styleFloat="right"
term.style.cssFloat="right"
term.style.textAlign="right"
}
}
}
var lang=navigator.userLanguage || navigator.language;
var script=document.createElement("script");
script.src=document.URL+"-"+lang.substring(0,2)+".js"
var head = document.getElementsByTagName('head')[0]
head.insertBefore(script,head.firstChild)
</script>
I tried to keep it pretty simple, yet cover as many locales as possible so additional css is likely required (I have to admit a lack of exposure to rtl languages, so many more styles may need to be set)
I do have font checking code that would be useful if you know what fonts support your character codes well
function hasFont(f){
var s=document.createElement("span")
s.style.fontSize="72px"
s.innerHTML="MWMWM"
s.style.visibility="hidden"
s.style.fontFamily=[(f=="monospace")?'':'monospace','sans-serif','serif']
document.body.appendChild(s)
var w=s.offsetWidth
s.style.fontFamily=[f,'monospace','sans-serif','serif']
document.body.lastChild=s
return s.offsetWidth!=w
}
usage: if(hasFont("myfont"))myelement.style.fontFamily="myfont"
A new (to date) and simple JS solution would be to use Intl.NumberFormat. It supports numeral localization, formatting variations as well as local currencies (see documentation for more examples).
To use an example very similar to MDN's own:
const val = 1234567809;
console.log('Eastern Arabic (Arabic-Egyptian)', new Intl.NumberFormat('ar-EG').format(val));
console.log('Persian variant (Farsi)',new Intl.NumberFormat('fa').format(val));
console.log('English (US)',new Intl.NumberFormat('en-US').format(val));
Intl.NumberFormat also seems to support string numeric values as well as indicates when it's not a number in the local language.
const val1 = '456';
const val2 = 'Numeric + string example, 123';
console.log('Eastern Arabic', new Intl.NumberFormat('ar-EG').format(val1));
console.log('Eastern Arabic', new Intl.NumberFormat('ar-EG').format(val2));
console.log('Persian variant',new Intl.NumberFormat('fa').format(val1));
console.log('Persian variant',new Intl.NumberFormat('fa').format(val2));
console.log('English',new Intl.NumberFormat('en-US').format(val1));
console.log('English', new Intl.NumberFormat('en-US').format(val2));
For the locale identifier (string passed to NumberFormat constructor indicating locale), I experimented with the values above and they seemed fine. I tried finding a list for all possible values, and through MDN came across this documentation and this list that could be helpful.
I'm not familiar with SEO, and am thus unsure how this answers that part of the question.
you can try this:
This is CSS source code:
#font-face
{
font-family: A1Tahoma;
src: url(yourfont.eot) format('eot')
, url(yourfont.ttf) format('truetype')
, url(yourfont.woff) format('woff')
, url(yourfont.svg) format('svg');
}
p{font-family:A1Tahoma; font-size:30px;}
And this is HTML code:
<p>سلام به همه</p>
<p>1234567890</p>
And finally you will see your result.remember that 4 font types use for any browser such as IE,FIREFOX and so on.
"salam reza ,to mituni in karo anjam bedi ta un fonte dekhaheto be site ezafe koni."
I have created a jquery plugin that can convert Western Arabic numbers to Eastern ones (Persian only). But it can be extended to convert a number to any desired numeral system. My jQuery plugin has two advantages:
Detect and convert numbers properly in child nodes.
Detect and convert point characters appropriately.
You can clone this plugin from github.
My plugin code:
(function( $ ){
$.fn.persiaNumber = function() {
var groupSelection = this;
for(i=0; i< groupSelection.length ; i++){
var htmlTxt = $(groupSelection[i]).html();
var trueTxt = convertDecimalPoint(htmlTxt);
trueTxt = convertToPersianNum(trueTxt);
$(groupSelection[i]).html(trueTxt);
}
function convertToPersianNum(htmlTxt){
var otIndex = htmlTxt.indexOf("<");
var ctIndex = htmlTxt.indexOf(">");
if(otIndex == -1 && ctIndex == -1 && htmlTxt.length > 0){
var trueTxt = htmlTxt.replace(/1/gi, "۱").replace(/2/gi, "۲").replace(/3/gi, "۳").replace(/4/gi, "۴").replace(/5/gi, "۵").replace(/6/gi, "۶").replace(/7/gi, "۷").replace(/8/gi, "۸").replace(/9/gi, "۹").replace(/0/gi, "۰");
return trueTxt;
}
var tag = htmlTxt.substring(otIndex,ctIndex + 1);
var str = htmlTxt.substring(0,otIndex);
str = convertDecimalPoint(str);
str = str.replace(/1/gi, "۱").replace(/2/gi, "۲").replace(/3/gi, "۳").replace(/4/gi, "۴").replace(/5/gi, "۵").replace(/6/gi, "۶").replace(/7/gi, "۷").replace(/8/gi, "۸").replace(/9/gi, "۹").replace(/0/gi, "۰");
var refinedHtmlTxt = str + tag;
var htmlTxt = htmlTxt.substring(ctIndex + 1, htmlTxt.length);
if(htmlTxt.length > 0 && otIndex != -1 || ctIndex != -1){
var trueTxt = refinedHtmlTxt;
var trueTxt = trueTxt + convertToPersianNum(htmlTxt);
}else{
return refinedHtmlTxt+ htmlTxt;
}
return trueTxt;
}
function convertDecimalPoint(str){
for(j=1;j<str.length - 1; j++){
if(str.charCodeAt(j-1) > 47 && str.charCodeAt(j-1) < 58 && str.charCodeAt(j+1) > 47 && str.charCodeAt(j+1) < 58 && str.charCodeAt(j) == 46)
str = str.substring(0,j) + '٫' + str.substring(j+1,str.length);
}
return str;
}
};
})( jQuery );
http://jsfiddle.net/VPWmq/2/
You can convert numbers in this way:
const persianDigits = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'];
const number = 44653420;
convertedNumber = String(number).replace(/\d/g, function(digit) {
return persianDigits[digit]
})
console.log(convertedNumber) // ۴۴۶۵۳۴۲۰
If anyone is looking for localizing into Bangla numbers using this code shifting method:
$("[lang='bang']").text(function(i, val) {
return val.replace(/\d/g, function(v) {
return String.fromCharCode(v.charCodeAt(0) + 0x09B6);
});
});
You can also visit here to see the UNICODE of ASCII Hexadecimal codes of Bangla

Categories

Resources