I have a large text from which I read data according to the scheme. Key words are placed in the "smallArtName" array. The scheme looks like this:
(key word) xxx (cordX|cordY)
I can't convert the string I received to a number. It seems to me that the reason is white space, visible in the terminal in the picture. I tried to use the replace method which works for sample text, but not for my value.
I'm a beginner and I could probably do it simpler, but the code I wrote works, and this is the most important thing for now.
for (i = 0; i < smallArtName.length; i++) {
var n = art.artPrintScreen.indexOf(smallArtName[i]);
if (n > 0) {
var tempString = art.artPrintScreen.substring(n, n + 100);
betweenChar = tempString.indexOf('|');
for (k = betweenChar - 10; k <= betweenChar + 10; k++) {
if (tempString[k] == '(') {
xStart = k;
}
if (tempString[k] == ')') {
yEnd = k;
}
}
cordX = tempString.slice(xStart + 1, betweenChar);
cordY = tempString.slice(betweenChar + 1, yEnd);
strTest = " t est".replace(/\s/g, '')
var cordY2 = cordY.replace(/\s/g, '')
console.log(typeof (cordY))
console.log(cordY2)
console.log(cordY2[0])
console.log(cordY2[1])
console.log(cordY2[2])
console.log(cordY2[3])
console.log(cordY2[4])
console.log(cordY2[5])
console.log(strTest)
var cordYtest = parseInt(cordY2, 10);
console.log(cordYtest)
}
}
You just need to change the regex so that you replace everything except digits and the negative sign - rather than just whitespace. i.e.
change
var cordY2 = cordY.replace(/\s/g, '')
to
var cordY2 = parseInt(cordY.replace(/[^0-9-]/g, ''), 10);
So that the variable cordY2 contains the number you require.
Related
I am using MikeMcl's big.js for precise accounting which outputs a string when calling toFixed().
I'd like to pretty print decimal results in an internationally aware way much like how the Date Object can automatically print dates and times in a local format.
Is there a way to format string objects that contain decimals internationally?
var myNumber = 123456.78;
console.log(myNumber.toLocaleString());
This should do the job.
function localize(fixed) {
/*Determine decimal symbol and digit grouping symbol.*/
var decimalSymbol = '.';
var digitGroupingSymbol = ',';
var dummy = 1234.5;
testResult = dummy.toLocaleString();
/*Browsers using digit grouping symbol.*/
if (testResult.length === 7) {
decimalSymbol = testResult[5];
digitGroupingSymbol = testResult[1];
}
/*Browsers not using digit grouping symbol.*/
if (testResult.length === 6) {
decimalSymbol = testResult[4];
digitGroupingSymbol = (decimalSymbol === '.'? ',': '.');
}
/*Format the number.*/
var result = '';
var dsIndex = fixed.indexOf('.');
if (dsIndex < 0) {
throw new Error('Expected decimal separator \'.\' in "' + fixed + '".');
}
for (var i = 0; i < dsIndex; ++i) {
if (fixed[i] < '0' || fixed[i] > '9') {
throw new Error('Expected digit, got "' + fixed[i] + '".');
}
if (i > 0 && i%3 === dsIndex%3) result += digitGroupingSymbol ;
result += fixed[i];
}
result += decimalSymbol + fixed.substr(dsIndex + 1);
return result;
}
/*Demonstration*/
var n1 = '123.4567890';
console.assert(localize(n1));
var n2 = '1234.567890';
console.log(localize(n2));
var n3 = '123456789012345678.1234567890';
console.log(localize(n3));
var n4 = '1234567890123456789.1234567890';
console.log(localize(n4));
var n5 = '12345678901234567890.1234567890';
console.log(localize(n5));
Output:
123.4567890
1.234.567890
123.456.789.012.345.678.1234567890
1.234.567.890.123.456.789.1234567890
12.345.678.901.234.567.890.1234567890
I'm currently implementing a substring search. From the algorithm, I get array of substrings occurence positions where each element is in the form of [startPos, endPos].
For example (in javascript array):
[[1,3], [8,10], [15,18]]
And the string to highlight is:
ACGATCGATCGGATCGAGCGATCGAGCGATCGAT
I want to highlight (in HTML using <b>) the original string, so it will highlight or bold the string from position 1 to 3, then 8 to 10, then 15 to 18, etc (0-indexed).
A<b>CGA</b>TCGA<b>TCG</b>GATC<b>GAGC</b>GATCGAGCGATCGAT
This is what I have tried (JavaScript):
function hilightAtPositions(text, posArray) {
var startPos, endPos;
var startTag = "<b>";
var endTag = "</b>";
var hilightedText = "";
for (var i = 0; i < posArray.length; i++) {
startPos = posArray[i][0];
endPos = posArray[i][1];
hilightedText = [text.slice(0, startPos), startTag, text.slice(startPos, endPos), endTag, text.slice(endPos)].join('');
}
return hilightedText;
}
But it highlights just a range from the posArray (and I know it is still incorrect yet). So, how can I highlight a string given multiple occurrences position?
Looking at this question, and following John3136's suggestion of going from tail to head, you could do:
String.prototype.splice = function( idx, rem, s ) {
return (this.slice(0,idx) + s + this.slice(idx + Math.abs(rem)));
};
function hilightAtPositions(text, posArray) {
var startPos, endPos;
posArray = posArray.sort(function(a,b){ return a[0] - b[0];});
for (var i = posArray.length-1; i >= 0; i--) {
startPos = posArray[i][0];
endPos = posArray[i][1];
text= text.splice(endPos, 0, "</b>");
text= text.splice(startPos, 0, "<b>");
}
return text;
}
Note that in your code, you are overwriting hilightedText with each iteration, losing your changes.
Try this:
var stringToHighlight = "ACGATCGATCGGATCGAGCGATCGAGCGATCGAT";
var highlightPositions = [[1,3], [8,10], [15,18]];
var lengthDelta = 0;
for (var highlight in highlightPositions) {
var start = highlightPositions[highlight][0] + lengthDelta;
var end = highlightPositions[highlight][1] + lengthDelta;
var first = stringToHighlight.substring(0, start);
var second = stringToHighlight.substring(start, end + 1);
var third = stringToHighlight.substring(end + 1);
stringToHighlight = first + "<b>" + second + "</b>" + third;
lengthDelta += ("<b></b>").length;
}
alert(stringToHighlight);
Demo: http://jsfiddle.net/kPkk3/
Assuming that you're trying to highlight search terms or something like that. Why not replace the term with the bolding?
example:
term: abc
var text = 'abcdefgabcqq';
var term = 'abc';
text.replace(term, '<b>' + term + '</b>');
This would allow you to avoid worrying about positions, assuming that you are trying to highlight a specific string.
Assuming your list of segments is ordered from lowest start to highest, try doing your array from last to first.
That way you are not changing parts of the string you haven't reached yet.
Just change the loop to:
for (var i = posArray.length-1; i >=0; i--) {
If you want to check for multiple string matches and highlight them, this code snippet works.
function highlightMatch(text, matchString) {
let textArr = text.split(' ');
let returnArr = [];
for(let i=0; i<textArr.length; i++) {
let subStrMatch = textArr[i].toLowerCase().indexOf(matchString.toLowerCase());
if(subStrMatch !== -1) {
let subStr = textArr[i].split('');
let subStrReturn = [];
for(let j=0 ;j<subStr.length; j++) {
if(j === subStrMatch) {
subStrReturn.push('<strong>' + subStr[j]);
} else if (j === subStrMatch + (matchString.length-1)){
subStrReturn.push(subStr[j] + '<strong>');
} else {
subStrReturn.push(subStr[j]);
}
}
returnArr.push(subStrReturn.join(''));
} else {
returnArr.push(textArr[i]);
}
}
return returnArr;
}
highlightMatch('Multi Test returns multiple results', 'multi');
=> (5) ['<strong>Multi<strong>', 'Test', 'returns', '<strong>multi<strong>ple', 'results']
In my code I have a variable myCash, which is printed into an h1 element using javaScript's innerHTML. I found a function online that puts a comma after every third character from the end of the number so that the number is easier to read. I've tried for a couple of hours now sending my variable myCash into the function and then print it on the screen. I CANNOT get it to work.
I've tried just alerting the new variable to the screen after page load or by pressing a button, but I get nothing and the alert doesn't even work. Here's the comma insert function:
function commaFormatted(amount) {
var delimiter = ","; // replace comma if desired
amount = new String(amount);
var a = amount.split('.',2)
var d = a[1];
var i = parseInt(a[0]);
if(isNaN(i)) { return ''; }
var minus = '';
if(i < 0) { minus = '-'; }
i = Math.abs(i);
var n = new String(i);
var a = [];
while(n.length > 3)
{
var nn = n.substr(n.length-3);
a.unshift(nn);
n = n.substr(0,n.length-3);
}
if(n.length > 0) { a.unshift(n); }
n = a.join(delimiter);
if(d.length < 1) { amount = n; }
else { amount = n + '.' + d; }
amount = minus + amount;
return amount;
}
now when I want my variable to change I've tried it a few different ways including this:
var newMyCash = commaFormatted(myCash);
alert(newMyCash);
and this:
alert(commaFormatted(myCash);
Where of course myCash equal some large number;
This does absolutely nothing! What am I doing wrong here??
Also,
Try this as a drop in replacement and try alerting the response:
http://phpjs.org/functions/number_format:481
Do you see any errors in the console of your browser (usually f12)?
This is not my function, but I hope it helps you.
function addCommas(nStr)
{
nStr += '';
x = nStr.split('.');
x1 = x[0];
x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return x1 + x2;
}
Usage:
var newMyCash = addCommas( myCash ); alert( newMyCash );
Source: http://www.mredkj.com/javascript/nfbasic.html
You are most likely not passing in a number that contains a decimal, which the function expects.
Working Demo
This is my integer value
12232445
and i need to get like this.
12,232,445
Using prototype how to get this?
var number = 12232445,
value = number.toString(),
parts = new Array;
while (value.length) {
parts.unshift(value.substr(-3));
value = value.substr(0, value.length - 3);
}
number = parts.join(',');
alert(number); // 12,232,445
It might not be the cleanest solution, but it'll do:
function addCommas(n)
{
var str = String(n);
var result = '';
for(var i = 0; i < str.length; i++)
{
if((i - str.length) % 3 == 0)
result += ',';
result += str[i];
}
return result;
}
Here is the function I use, to format thousands separators and takes into account decimals if any:
function thousands(s) {
var rx = /(-?\d+)(\d{3})/,
intDec = (''+s)
.replace(new RegExp('\\' + $b.localisation.thousandSeparator,'g'), '')
.split('\\' + $b.user.localisation.decimalFormat),
intPart = intDec[0],
decPart = intDec[1] || '';
while (rx.test(intPart)) {
intPart = intPart.replace(rx,'$1'+$b.localisation.thousandSeparator+'$2');
}
return intPart + (decPart && $b.localisation.decimalFormat) + decPart;
}
thousands(1234.56) //--> 1,234.56
$b.localisation is a global variable used for the session.
$b.localisation.thousands can have the values , or . or a space.
And $b.localisation.decimalFormat can have the values , or . depending on the locale of the user
I'm wondering if there's a way to count the words inside a div for example. Say we have a div like so:
<div id="content">
hello how are you?
</div>
Then have the JS function return an integer of 4.
Is this possible? I have done this with form elements but can't seem to do it for non-form ones.
Any ideas?
g
If you know that the DIV is only going to have text in it, you can KISS:
var count = document.getElementById('content').innerHTML.split(' ').length;
If the div can have HTML tags in it, you're going to have to traverse its children looking for text nodes:
function get_text(el) {
ret = "";
var length = el.childNodes.length;
for(var i = 0; i < length; i++) {
var node = el.childNodes[i];
if(node.nodeType != 8) {
ret += node.nodeType != 1 ? node.nodeValue : get_text(node);
}
}
return ret;
}
var words = get_text(document.getElementById('content'));
var count = words.split(' ').length;
This is the same logic that the jQuery library uses to achieve the effect of its text() function. jQuery is a pretty awesome library that in this case is not necessary. However, if you find yourself doing a lot of DOM manipulation or AJAX then you might want to check it out.
EDIT:
As noted by Gumbo in the comments, the way we are splitting the strings above would count two consecutive spaces as a word. If you expect that sort of thing (and even if you don't) it's probably best to avoid it by splitting on a regular expression instead of on a simple space character. Keeping that in mind, instead of doing the above split, you should do something like this:
var count = words.split(/\s+/).length;
The only difference being on what we're passing to the split function.
Paolo Bergantino's second solution is incorrect for empty strings or strings that begin or end with whitespaces. Here's the fix:
var count = !s ? 0 : (s.split(/^\s+$/).length === 2 ? 0 : 2 +
s.split(/\s+/).length - s.split(/^\s+/).length - s.split(/\s+$/).length);
Explanation: If the string is empty, there are zero words; If the string has only whitespaces, there are zero words; Else, count the number of whitespace groups without the ones from the beginning and the end of the string.
string_var.match(/[^\s]+/g).length
seems like it's a better method than
string_var.split(/\s+/).length
At least it won't count "word " as 2 words -- ['word'] rather than ['word', '']. And it doesn't really require any funny add-on logic.
Or just use Countable.js to do the hard job ;)
document.deepText= function(hoo){
var A= [];
if(hoo){
hoo= hoo.firstChild;
while(hoo!= null){
if(hoo.nodeType== 3){
A[A.length]= hoo.data;
}
else A= A.concat(arguments.callee(hoo));
hoo= hoo.nextSibling;
}
}
return A;
}
I'd be fairly strict about what a word is-
function countwords(hoo){
var text= document.deepText(hoo).join(' ');
return text.match(/[A-Za-z\'\-]+/g).length;
}
alert(countwords(document.body))
Or you can do this:
function CountWords (this_field, show_word_count, show_char_count) {
if (show_word_count == null) {
show_word_count = true;
}
if (show_char_count == null) {
show_char_count = false;
}
var char_count = this_field.value.length;
var fullStr = this_field.value + " ";
var initial_whitespace_rExp = /^[^A-Za-z0-9]+/gi;
var left_trimmedStr = fullStr.replace(initial_whitespace_rExp, "");
var non_alphanumerics_rExp = rExp = /[^A-Za-z0-9]+/gi;
var cleanedStr = left_trimmedStr.replace(non_alphanumerics_rExp, " ");
var splitString = cleanedStr.split(" ");
var word_count = splitString.length -1;
if (fullStr.length <2) {
word_count = 0;
}
if (word_count == 1) {
wordOrWords = " word";
} else {
wordOrWords = " words";
}
if (char_count == 1) {
charOrChars = " character";
} else {
charOrChars = " characters";
}
if (show_word_count & show_char_count) {
alert ("Word Count:\n" + " " + word_count + wordOrWords + "\n" + " " + char_count + charOrChars);
} else {
if (show_word_count) {
alert ("Word Count: " + word_count + wordOrWords);
} else {
if (show_char_count) {
alert ("Character Count: " + char_count + charOrChars);
}
}
}
return word_count;
}
The get_text function in Paolo Bergantino's answer didn't work properly for me when two child nodes have no space between them. eg <h1>heading</h1><p>paragraph</p> would be returned as headingparagraph (notice lack of space between the words). So prepending a space to the nodeValue fixes this. But it introduces a space at the front of the text but I found a word count function that trims it off (plus it uses several regexps to ensure it counts words only). Word count and edited get_text functions below:
function get_text(el) {
ret = "";
var length = el.childNodes.length;
for(var i = 0; i < length; i++) {
var node = el.childNodes[i];
if(node.nodeType != 8) {
ret += node.nodeType != 1 ? ' '+node.nodeValue : get_text(node);
}
}
return ret;
}
function wordCount(fullStr) {
if (fullStr.length == 0) {
return 0;
} else {
fullStr = fullStr.replace(/\r+/g, " ");
fullStr = fullStr.replace(/\n+/g, " ");
fullStr = fullStr.replace(/[^A-Za-z0-9 ]+/gi, "");
fullStr = fullStr.replace(/^\s+/, "");
fullStr = fullStr.replace(/\s+$/, "");
fullStr = fullStr.replace(/\s+/gi, " ");
var splitString = fullStr.split(" ");
return splitString.length;
}
}
EDIT
kennebec's word counter is really good. But the one I've found includes a number as a word which is what I needed. Still, that's easy to add to kennebec's. But kennebec's text retrieval function will have the same problem.
This should account for preceding & trailing whitespaces
const wordCount = document.querySelector('#content').innerText.trim().split(/\s+/).length;
string_var.match(/[^\s]+/g).length - 1;