+$ in jquery. How come not only the basic $ - javascript

I have some jQuery code where +$(...) is used in many places. The code does not work without the + part, when doing just $(...).
I couldn't find any explanation through Google. I'd appreciate any guidance if possible.
function calculate() {
var a = +$('#a').val(); // what is +$ ?
var b = +$('#b').val();
var c = b * 108.40;
//etc
}

+$() is actually two operations, where first $() runs to grab your input and then + coerces whatever the value of the input is into a number.
Here's a breakdown of what is happening:
var valueA = $('#a').val(); // "123"
var numberA = +valueA; // 123
console.log('valueA is a ' + typeof valueA); // 'valueA is a string'
console.log('numberA is a ' + typeof numberA); // 'numberA is a number'
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="a" value="123"/>

Related

JS how to use two arithmetic operators

i want to get data from input fields and do two arithmetic operations at same time (1)multiplication (2) addition. Multiplication is working but when i try to do 2nd operation i get some error. for example 2*2+2=6 but when i try the answer comes 42.
my code is here .
<script type="text/javascript">
$(document).ready(function(){
$('#sfpm,#snom,#bonus').keyup(function(){
var a =$('#sfpm').val();
var b = $('#snom').val();
var c = $("#bonus").val();
var taamount = a*b+c ;
$('#staamount').val(taamount);
});
});
</script>
As you can see in this example the first box will cause multiplication, but the rest will concatenate ( simply append to ) the last digit present, which increases length but doesn't do any mathematical operation.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
sfpm<input id="sfpm">
snom<input id="snom">
bonus<input id="bonus">
<hr/>total<input id="staamount">
<script type="text/javascript">
$(document).ready(function(){
$('#sfpm,#snom,#bonus').keyup(function(){
var a =$('#sfpm').val();
var b = $('#snom').val();
var c = $("#bonus").val();
var taamount = a*b+c ;
$('#staamount').val(taamount);
});
});
</script>
This is because you're adding two strings together instead of numbers. Strings added together look like this:
let str = "Hello ", str2= "world!";
console.log(str + str2);
So it makes sense that they append. Numbers look like this:
console.log(1 + 5);
Which does what you expect, but the important thing to realize is that the + operator has multiple functions. it can either append or perform math. The difference as to what type of operation is performed is based solely on the type of the data you're using.
a string will append
a number will add
So in your code when you get the value using .val() - what's happening is that you're getting string values, not number values. To fix this we can do a few different things.
parseInt or Number methods will convert the values from .val() into integers:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
sfpm<input id="sfpm">
snom<input id="snom">
bonus<input id="bonus">
<hr/>total<input id="staamount">
<script type="text/javascript">
$(document).ready(function(){
$('#sfpm,#snom,#bonus').keyup(function(){
var a = parseInt($('#sfpm').val());
var b = Number($('#snom').val());
var c = parseInt($("#bonus").val());
var taamount = a*b+c ;
$('#staamount').val(taamount || 0);
});
});
</script>
One other way to coerce a string to a number is to simply place the + operator before the value. This will cause the interpreter to automatically try to change the value into a number.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
sfpm<input id="sfpm"> snom
<input id="snom"> bonus
<input id="bonus">
<hr/>total<input id="staamount">
<script type="text/javascript">
$(document).ready(function() {
$('#sfpm,#snom,#bonus').keyup(function() {
var a = +$('#sfpm').val();
var b = +$('#snom').val();
var c = +$("#bonus").val();
var taamount = a * b + c;
$('#staamount').val(taamount || 0);
});
});
</script>
Use parseInt() to ensure you are getting the int version of the value, it looks like it is adding c as a string
You're trying to operate on string.
You're doing something '2' + '0' which will result as '20' not 2.
Because here + operator does the concatenation of two string not arithmetic addition
Change it number.
<script type="text/javascript">
$(document).ready(function(){
$('#sfpm,#snom,#bonus').keyup(function(){
var a =Number($('#sfpm').val());
var b = Number($('#snom').val());
var c = Number($("#bonus").val());
var taamount = a*b+c ;
$('#staamount').val(taamount);
});
});
</script>

Dynamic Regex for Decimal Precision not Working

I have the following hard-coded RegEx expression for decimal precision & scale, which works (in another project):
// This would be a Decimal(2,3)
var regex = /\d{0,2}(\.\d{1,3})?$/;
var result = regex.test(text);
However, I don't want to hard-code multiple variations. And, interestingly, the following fails...but I don't know why.
I "think" the concatenation may (somehow) be effecting the "test"
What am I doing wrong here?
SAMPLE:
var validationRules = {
decimal: {
hasPrecision: function (precision, scale, text) {
var regex = new RegExp('\d{0,' + precision + '}(\.\d{1,' + scale + '})?$');
var result = regex.test(text);
// result is ALWAYS true ????
alert(result);
alert(regex);
}
}
};
FAILING SAMPLE-SNIPPET:
$(document).ready(function () {
var validationRules = {
decimal: {
hasPrecision: function (precision, scale, text) {
var regex = new RegExp('\d{0,' + precision + '}(\.\d{1,' + scale + '})?$');
var result = regex.test(text);
alert(result);
alert(regex);
}
}
};
var masks = {
decimal: function (e) {
// TODO: get Kendo MaskedTextBox to run RegEx
var regex = new RegExp("^([0-9\.])$");
var key = String.fromCharCode(!event.charCode ? event.which : event.charCode);
if (!regex.test(key)) {
event.preventDefault();
return false;
}
}
};
var button = $('.btn');
var textbox = $('.txt');
textbox.on('keypress', masks.decimal);
button.on('click', function () {
var text = textbox.val();
validationRules.decimal.hasPrecision(2, 3, text);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" value="1111" class="txt">
<input type="button" class="btn" value="Run it">
Always look at the result when building dynamic strings. In your case you're building it and just assuming it's turning into the REGEX pattern you want.
What you're actually building is, for example:
d{0,2}(.d{1,3})?$
Why? Because REGEX patterns built via the constructor (as opposed to literals) are built as strings - and in strings \ is interpreted as an escape character.
You, however, need these back slashes to persist into your pattern, so you need to double escape. In effect, you need to escape the escape so the final one is retained.
var regex = new RegExp('\\d{0,' + precision + '}(\\.\\d{1,' + scale + '})?$');
This will result in an equivalent of your hard-coded pattern assuming precision and scale contain the intergers you think they do. Check this too. (If they contain floats, for example, this will ruin your pattern.)
As for your false positives, this is probably down to a missing start-anchor instruction, i.e. ^.
/\d{0,2}(\.\d{1,3})?$/.test("1234"); //true
/^\d{0,2}(\.\d{1,3})?$/.test("1234"); //false, note ^
please try this I have implement on my project and it's working fine
const integer = Number(4)
const decimal=Number(2)
const reg = new RegExp(^[0-9]{0,${integer }}(\\.\\d[0-9]{0,${decimal- 1}})?$)
return value && !reg.test(value) ? Maximum length for integer is ${integer} and for decimal is ${decimal} : undefined;

Regex to separate thousands with comma and keep two decimals

I recently came up with this code while answering another StackOverflow question. Basically, on blur, this code will properly comma separate by thousands and leave the decimal at two digits (like how USD is written [7,745.56]).
I was wondering if there is more concise way of using regex to , separate and cut off excessive decimal places. I recently updated this post with my most recent attempt. Is there a better way of doing this with regex?
Input -> Target Output
7456 -> 7,456
45345 -> 45,345
25.23523534 -> 25.23
3333.239 -> 3,333.23
234.99 -> 234.99
2300.99 -> 2,300.99
23123123123.22 -> 23,123,123,123.22
Current Regex
var result;
var str = []
reg = new RegExp(/(\d*(\d{2}\.)|\d{1,3})/, "gi");
reversed = "9515321312.2323432".split("").reverse().join("")
while (result = reg.exec(reversed)) {
str.push(result[2] ? result[2] : result[0])
}
console.log(str.join(",").split("").reverse().join("").replace(",.","."))
As an alternative to the Regex, you could use the following approach
Number(num.toFixed(2)).toLocaleString('en-US')
or
num.toLocaleString('en-US', {maximumFractionDigits: 2})
You would still have the toFixed(2), but it's quite clean. toFixed(2) though won't floor the number like you want. Same with {maximumFractionDigits: 2} as the second parameter to toLocaleString as well.
var nums = [7456, 45345, 25.23523534, 3333.239, 234.99, 2300.99, 23123123123.22]
for (var num of nums)
console.log(num, '->', Number(num.toFixed(2)).toLocaleString('en-US') )
Flooring the number like you showed is a bit tricky. Doing something like (num * 100 | 0) / 100 does not work. The calculation loses precision (e.g. .99 will become .98 in certain situations). (also |0 wouldn't work with larger numbers but even Math.floor() has the precision problem).
The solution would be to treat the numbers like strings.
function format(num) {
var num = num.toLocaleString('en-US')
var end = num.indexOf('.') < 0 ? num.length : num.indexOf('.') + 3
return num.substring(0, end)
}
var nums = [7456, 45345, 25.23523534, 3333.239, 234.99, 2300.99, 23123123123.22]
for (var num of nums) console.log(num, '->', format(num))
function format(num) {
var num = num.toLocaleString('en-US')
var end = num.indexOf('.') < 0 ? num.length : num.indexOf('.') + 3
return num.substring(0, end)
}
(when changing to another format than 'en-US' pay attention to the . in numbers as some languages use a , as fractal separator)
For Compatibility, according to CanIUse toLocaleString('en-US') is
supported in effectively all browsers (since IE6+, Firefox 2+, Chrome
1+ etc)
If you really insist on doing this purely in regex (and truncate instead of round the fractional digits), the only solution I can think of is to use a replacement function as the second argument to .replace():
('' + num).replace(
/(\d)(?=(?:\d{3})+(?:\.|$))|(\.\d\d?)\d*$/g,
function(m, s1, s2){
return s2 || (s1 + ',');
}
);
This makes all your test cases pass:
function format(num){
return ('' + num).replace(
/(\d)(?=(?:\d{3})+(?:\.|$))|(\.\d\d?)\d*$/g,
function(m, s1, s2){
return s2 || (s1 + ',');
}
);
}
test(7456, "7,456");
test(45345, "45,345");
test(25.23523534, "25.23"); //truncated, not rounded
test(3333.239, "3,333.23"); //truncated, not rounded
test(234.99, "234.99");
test(2300.99, "2,300.99");
test(23123123123.22, "23,123,123,123.22");
function test(num, expected){
var actual = format(num);
console.log(num + ' -> ' + expected + ' => ' + actual + ': ' +
(actual === expected ? 'passed' : 'failed')
);
}
I added another layer where regex that drops the unwanted decimals below hundredths on top of your regex comma adding logic;
val.replace(/(\.\d{2})\d*/, "$1").replace(/(\d)(?=(\d{3})+\b)/g, "$1,")
doIt("7456");
doIt("45345");
doIt("25.23523534");
doIt("3333.239");
doIt("234.99");
doIt("2300.99");
doIt("23123123123.22");
doIt("5812090285.2817481974897");
function doIt(val) {
console.log(val + " -> " + val.replace(/(\.\d{2})\d*/, "$1").replace(/(\d)(?=(\d{3})+\b)/g, "$1,"));
}
If multiple calls of regex replace is OK, this answer should satisfy you, since it is only has regex replace logic and nothing else.
Try:
var n = 5812090285.2817481974897;
n = n.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
console.log(n);
Outputs:
5,812,090,285.28
Note: .toFixed(2) returns a string. So in order to simplify this further you must add a way to turn n into a string before executing your regex. For example:
n.toString.replace(/(\d)(?=(\d{3})+\.)/g, '$1,'); //ofc with the additional regex
Although you would think it wouldn't matter in javascript, it apparently does in this situation. So I dont know how much 'less' messy it would be to not use.
Here is a way to do it without a regular expression:
value.toLocaleString("en-US", { maximumFractionDigits: 2 })
function formatValue() {
var source = document.getElementById("source");
var output = document.getElementById("output");
var value = parseFloat(source.value);
output.innerText = value.toLocaleString("en-US", { maximumFractionDigits: 2 });
}
<input id="source" type="text" />
<button onclick="formatValue()">Format</button>
<div id="output"></div>
RegEx to rescue again!
My solution has two parts :
.toFixed : Used to limit the decimal limit
/(\d)(?=(\d\d\d)+(?!\d))/g : It makes use of back reference with three digits at a time
Here's everything put together :
// .toFixed((/\./g.test(num)) ? 2 : 0) it tests if the input number has any decimal places, if so limits it to 2 digits and if not, get's rid of it altogether by setting it to 0
num.toFixed((/\./g.test(num)) ? 2 : 0).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,"))
You can see it in action here :
var input = [7456, 45345, 25.23523534, 3333.239, 234.99, 2300.99, 23123123123.22]
input.forEach(function(num) {
$('div')
.append(
$('<p>').text(num + ' => ' +
num.toFixed( (/\./g.test(num))?2:0 ).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,"))
);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div> </div>
NOTE: I've only used jQuery to append the results
You can do like this
(parseFloat(num).toFixed(2)).replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,").replace(".00","")
Here just convert number to formatted number with rounded down to 2 decimal places and then remove the .00 if exist.
This can be one approach you can use.
var format = function (num) {
return (parseFloat(num).toFixed(2)).replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,").replace(".00","")
}
$(function () {
$("#principalAmtOut").blur(function (e) {
$(this).val(format($(this).val()));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="principalAmtOut" type="text" />
You can use Intl.NumberFormat with style set to "decimal" and maximumFractionDigits set to 2 at options object passed at second parameter
const nums = [7456, 45345, 25.23523534, 3333.239, 234.99, 2300.99, 23123123123.22];
const formatOptions = {style:"decimal", maximumFractionDigits:2};
const formatter = new Intl.NumberFormat("en-US", formatOptions);
const formatNums = num => formatter.format(num);
let formattedNums = nums.map(formatNums);
console.log(formattedNums);
I found a solution based on #Pierre's answer without using of toFixed:
function format(n) {
n = +n;
var d = Math.round(n * 100) % 100;
return (Math.floor(n) + '').replace(/(\d)(?=(\d{3})+$)/g, '$1,') + (d > 9 ? '.' + d : d > 0 ? '.0' + d : '');
}
console.log(format(7456));
console.log(format(7456.0));
console.log(format(7456.1));
console.log(format(7456.01));
console.log(format(7456.001));
console.log(format(45345));
console.log(format(25.23523534));
console.log(format(3333.239));
console.log(format(234.99));
console.log(format(2300.99));
console.log(format(23123123123.22));
console.log(format('23123123123.22'));

How would I test for a certain digit in a variable?

Lets say I had a variable called test and test = 123456789;. Then I have another variable called anotherTest and anotherTest = 1234;. How would I make a program that can test whether a variable has the digit 5 or not? Then, how could it sort the variables into two groups of which one group of variables has the digit "5" within it and the other without? Is there a easy way to do this?
How would I make a program that can test whether a variable has the digit 5 or not?
You can readily do that with strings and indexOf:
if (String(test).indexOf("5") !== -1) {
// It has a 5 in it
}
Then, how could it sort the variables into two groups of which one group of variables has the digit "5" within it and the other without?
You can't sort the variables into groups, but you can certainly sort values into groups. For example, this loops through an array and adds values to either the with5 or without5 array depending on whether the value contains the digit 5:
var a = [
1234,
12345,
123123,
555555
];
var with5 = [];
var without5 = [];
a.forEach(function(value) {
if (String(value).indexOf("5") === -1) {
without5.push(value);
} else {
with5.push(value);
}
});
snippet.log("with5: " + with5.join(", "));
snippet.log("without5: " + without5.join(", "));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
The above assumes base 10 (decimal) strings, but you can easily do the same with hexadecimal or octal or any other base you like by using Number#toString(base). E.g.:
var s = num.toString(16);
...will assign s the value of num as a hexadecimal (base 16) string.
Loop through each character of variable test, then compare using indexOf() to see if it exists in anotherTest. If so add to one array, otherwise add to array 2.
To see if a number contains the digit "5", you can just convert the numbers to strings and then just use .indexOf("5") on each string.
var test = 123456789;
var anotherTest = 1234;
// reports whether the passed in number or string contains the
// character "5"
function containsDigit5(val) {
// convert number to string
// if already string, then it is left as is
val = "" + val;
return val.indexOf("5") >= 0;
}
containsDigit5(test); // true
containsDigit5(anotherTest); // false
The grouping part of your question is not entirely clear, but you can just call this function on each variable and add the numbers to one of two arrays.
var testNumbers = [123456789, 1234];
var has5 = [];
var doesNotHave5 = [];
// reports whether the passed in number or string contains the
// character "5"
function containsDigit5(val) {
// convert number to string
// if already string, then it is left as is
val = "" + val;
return val.indexOf("5") >= 0;
}
testNumbers.forEach(function(item) {
if (containsDigit5(item)) {
has5.push(testNumbers[i]);
} else {
doesNotHave5.push(testNumbers[i]);
}
});
You can do this with RegExp, or .indexOf. Either works:
RegEx
Everyone hates RegExp for some reason, but I like it. You can use:
var test = 123456789,
anotherTest = 1234;
/5/.test(test);
/5/.test(anotherTest);
var test = 123456789,
anotherTest = 1234;
document.write( 'test (123456789): ' + /5/.test(test) + '<br/>' );
document.write( 'anotherTest (1234): ' + /5/.test(anotherTest) );
indexOf
This can be faster in some situations, but not always, it is also a bit more "complicated", at least in my opinion:
var test = 123456789,
anotherTest = 1234;
(test+'').indexOf(5) > -1;
(anotherTest+'').indexOf(5) > -1;
var test = 123456789,
anotherTest = 1234;
document.write( 'test (123456789): ' + ((test+'').indexOf(5) > -1) + '<br/>' );
document.write( 'anotherTest (1234): ' + ((anotherTest+'').indexOf(5) > -1) + '<br/>' );

Remove NaN when removing text from a linked input field

I've been looking for an answer by looking at other posts but I couldn't find anything directly usable for my script (yet it might also be my ignorance toward JavaScript...)
I'm using this script to transliterate OnBlur from a foreign language's script to the Latin alphabet :
<script>
function separation() {
var str = document.getElementById().value;
var res1 = str.charAt(0);
var res2 = str.charAt(1);
var res3 = str.charAt(2);
document.getElementById().innerHTML = res1+res2+res3;
}
var syllable_1 = {
'김' : 'Kim ',
'이' : 'Lee ',
'야' : 'Ya',
}
var syllable_2 = {
'김' : 'gim',
'이' : 'i',
'야' : 'ya',
}
function hangul_to_roman(hangul) {
return syllable_1[hangul.charAt(0)] + syllable_2[hangul.charAt(1)] + ( hangul.length >= 3 ? "-" + syllable_2[hangul.charAt(2)] : "" );
}
</script>
<input type="text" id="ttt" value="김김이" onBlur="document.getElementById('demo').value = hangul_to_roman(document.getElementById('ttt').value)" style="text-transform: capitalize">
<input type="text" id="demo" readonly>
Here you have the same script in Fiddle : http://jsfiddle.net/LGRAq/6/
The first input field contains what's supposed to be transliterated and the second shows that transliteration; however it prints NaN when removing what's inside the first input field and I'd like to know how to remove it.
Is there anyone who would know how to proceed ?
Thank you very much for your help !
When hangul.charAt(…) is not contained in your syllable map, the property access will yield undefined. Adding two undefineds together will make a NaN. You can prevent that from showing up by using the empty string as a default value for the lookup:
function hangul_to_roman(hangul) {
return (syllable_1[hangul.charAt(0)] || "")
+ (syllable_2[hangul.charAt(1)] || "")
+ (hangul.length >= 3 ? "-" + (syllable_2[hangul.charAt(2)] || "") : "");
}
Bro, We could use this way to remove the NaN from appearing too.
var str = document.getElementById().value;
var res1 = str.charAt(0);
var res2 = str.charAt(1);
var res3 = str.charAt(2);
var res4 = res1+res2+res3;
if(!isNaN(res4))
document.getElementById().innerHTML = res4;

Categories

Resources