toLocaleString() not work on input change - javascript

I want to add thousand separator for numbers as user is typing in. this is my code :
$('.rls').on('input',function (e) {
$(this).val(parseFloat($(this).val()).toLocaleString());
});
It works correctly but when I enter dot character It doesnt add dot to input .what is the problem?

The parseFloat function is always removing the "." so toLocalString will return the number without the "."
You could check if the last character is a "." and place it back. I also added a check for empty string because otherwise it will give a NaN if you delete all the numbers:
$('.rls').on('input',function (e) {
$this = $(this);
const val = $this.val();
if (val === "") {
return;
}
let end = "";
if (val.charAt(val.length-1) === ".") {
end = ".";
}
$this.val(parseFloat($this.val()).toLocaleString() + end);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input class="rls" />
Do bear in mind, some locales use "," as the decimal so I'm not sure if your code will break on them. Also, in my case, my locale uses "," as thousands separator and this breaks the parseFloat and removes everything after the "," if I write a number above 999.
I think it would be better to let the user input whatever numbers they want without changing the input box while they are writing in it.

Learn to do it without jquery, what is in js core, and you will often find the solution.
document.querySelector(".rls")[0].oninput = (function(e){
e.value = +e.value.toLocaleString()
})

This is what works for me:
document.querySelector("#number-input").oninput = (function(e) {
var input = document.getElementById('number-input')
input.name = input.value.replaceAll('.', '')
if (input.value == "" || input.value == undefined || isNaN(parseInt(input.name)) == true) {
input.value = 0
input.name = "0"
} else {
input.value = parseInt(input.name).toLocaleString()
}
})
<input type='text' id='number-input'></input>

Related

How do I prevent the input of a number like 2.2.2 in my calculator?

I have been working on a simple JS calculator using an OOP approach. I am struggling to create a fix that prevents the input of extra decimals. For example, a user can input 3.2.1.5. Ideally, this calculator would display the entire expression on the digital calculator screen before solving it and returning the result. With this in mind, simply preventing a user from adding a second decimal would prevent them from adding(or whatever operator they may choose) multiple decimals together. I have considered using .split() and .join() on operators in the input, but it is beginning to get convoluted as there are multiple operators to consider. Ideally, I want to avoid regex.
const keys = document.querySelector('.calc-buttons');
keys.addEventListener('click', event => {
const {target} = event
const {value} = target
if(!target.matches('button')){
return
}else{
calculator.parseInput(value)
//console.log(value)
}
})
const calculator = {
displayText: '0',
prevTotal: null,
parseInput(value){
//have any of the special buttons(AC, decimal, =) been clicked?
switch(value){
case '=':
//calculate answer
this.calcAnswer(this.displayText)
break
case 'AC':
//clear screen & stored values
this.clearAll()
break
case '.':
//create decimal
if(this.displayText == 0){
//pass'0.'
this.addText('0.')
}else{
//add value to text string
this.addText(value)
}
break
default:
//add value to text string
this.addText(value)
break
}
},
addText(value){
if(this.displayText == '0'){
this.displayText = ''
}else if(this.prevTotal !== null){
this.displayText = this.prevTotal
this.prevTotal = null
}
//check if previous input is a number
if(isNaN(+(value)) && isNaN(+(this.displayText))){
if(isNaN(this.displayText.slice(-1))){
return
}
}else if(value == '.' && this.displayText.slice(-1) == '.'){
return
}
this.displayText += value
//output display text to screen
this.outputText(this.displayText)
},
outputText(text){
document.querySelector('.screen').value = text
},
calcAnswer(equation){
let result = Function("return " + equation)()
this.outputText(result)
//console.log(equation)
//console.log(result)
this.prevTotal = result
},
clearAll(){
this.displayText = '0',
this.prevTotal = null
this.outputText(this.displayText)
}
}
Functions are based on StepUp's answer (which is wrong AFAIK; it should be .length > 2 but I can't comment yet)
const hasManySymbols = (str, symbol) => {
const firstIndex = str.indexOf(symbol) // find the first occurrence of the symbol
if(firstIndex == -1) return false // if there is no first occurrence there are not many symbols
return str.indexOf(symbol, firstIndex + 1) != -1 // whether or not there is a second occurrence
}
const validate = str => hasManySymbols(str, '.') ? 'invalid input' : 'valid input'
console.log(validate('1.23')) // "valid input"
console.log(validate('1.2.3')) // "invalid input"
I'm not sure if this is faster or slower but it should theoretically be faster I guess.
You can create a simple function to avoid repetition of code and hiding unnecessary details in functions. In addition, it helps to reduce convolution.
So create a function which will check eligibility of input and based on result just notify user or remove last incorrect character.
The sketch of function could like this:
const hasManySigns = (str, sign) => str.split(sign).length > 2
An example:
const hasManySigns = (str, sign) => str.split(sign).length > 2
let foo = '1.2.3'
const validate = str => hasManySigns(str, '.') ? 'incorrect input' : 'correct input'
console.log(validate(foo))

Validating phone number with different formats WITHOUT regex

In JavaScript, I need validate phone numbers without using regular expressions (must be with string manipulation). The phone numbers have to be in one of the following formats:
123-456-7890
1234567890
(123)4567890
(123)456-7890
Then I must also provide an alert if the phone number isn't in one of the formats listed above.
I have only been able to manage to get #2 working, which looks something like this:
function len(gth)
{
if (gth.value.length != 10)
{
alert("Telephone numbers MUST be 10 digits!");
}
}
which down in the HTML it would call up to the function:
<p>Phone: <input id = "phone" onblur="len(this)" name = "Phone" size = "20" type = "text" maxlength = "10"> </p>
Since you need a solution without regex, I believe this should work.
const phones = [
'123-456-7890',
'1234567890',
'(123)4567890',
'(123)456-7890',
'+61(123) 456-7890',
'12345',
'))))01/34$89.77(99'
]
function len(gth) {
if (gth.substring(3, 4) == '-' && gth.substring(7, 8) == '-') // 123-456-7890
gth = gth.replace('-', '').replace('-', '');
else if (gth.substring(0, 1) == '(' && gth.substring(4, 5) == ')' && gth.substring(8, 9) == '-') // (123)456-7890
gth = gth.replace('(', '').replace(')', '').replace('-', '');
else if (gth.substring(0, 1) == '(' && gth.substring(4, 5) == ')') // (123)4567890
gth = gth.replace('(', '').replace(')', '');
if (!isNaN(gth) && gth.length == 10) {
return true;
}
alert("Telephone numbers:" + gth + " MUST be 10 digits!");
}
phones.forEach(len)
I would replace the numbers with something like x, then check against predefined patterns:
function check(num) {
let pattern = '';
for (let i = 0; i < num.length; i++) {
pattern += num[i] >= '0' && num[i] <= '9' ? 'x' : num[i];
}
return ['xxx-xxx-xxxx', 'xxxxxxxxxx', '(xxx)xxxxxxx', '(xxx)xxx-xxxx']
.indexOf(pattern) >= 0;
}
For extra credit, find the bug in the above program.
However, you don't really need to do any of this. You should be able to use the pattern attribute on the input element. That will also provide a better user experience. For instance, you can style the input element using the :invalid pseudo-class, by putting a red border around it for example, to give the user real-time feedback that their input is not valid. Yes, that takes a regular expression--what was your reason for not wanting to use a regular expression again?
You can make it manually be:
Checking string size if it is the expected or not
split the string to char array then parse them as integers inside a try block if numberFormatException is thrown it should be a bracket ( ) or -
Basic example of extracting the input data to Array
function test() {
var phnTest = document.getElementById('phone').value;
var strArray = [];
strArray = phnTest.split('');
document.getElementById('p').innerHTML = strArray;
}
<form action="demo_form.asp">
Phone <input id="phone" type="text" name="phone"><br>
<input type="button" value='Submit' onclick="test()">
</form>
<p id='p'></p>
This is dependent on how the data is structured, if you need to search a body of text and so on, but basics would be...
If it's a simple pull from an <input>, grab the data...
Take the input data, and generate an array with each character. You could then test, say strArray[3], for a dash or a dot. If not present, it can continue along to check for seven numbers in a row and so on.
This is going to be extremely consuming and require a number of conditionals to be checked. I assume the "without RegEx" is a requirement for a project or such, if not, recommend learning and using RegEx.
Hope this gets you going.
This is my attempt. The key is creating an array from the string then filtering out any non numerical characters. It would be easier to use regular expression though. just
number.replace(/(\D+)/g, '')
const numbers = [
'123-456-7890',
'1234567890',
'(123)4567890',
'(123)456-7890',
'+61(123) 456-7890',
'12345',
'))))01/34$89.77(99'
]
// validate a phone number
function validate(number) {
const digits = clean(number)
console.log({
number,
digits,
length: digits.length,
pass: digits.length === 10
})
}
// remove any non digits from the number
function clean(number) {
return Array.from(number).filter(char => {
return !isNaN(char) && char !== ' '
}).join('')
}
numbers.forEach(validate)

More than one comma restrict using javascript

In my textbox I allowed only integer value and comma it will control using javascript.Now my doubt how to control more than comma continuously (i.e)1,2,3,4 is to ok then 1,2,3,,4,,5 its need restricted.Its possible in javascript.
<p:inputText onKeyPress="onlyAllowDigitComma(event);"/>
Your answer doesn't show how far you go with your solution. I suppose code bellow is what you wanted, also I suppose you need removing comas from start and end.
<input type="text" onkeypress="onlyAllowDigitComma(event,this);" onkeyup="onlyAllowDigitComma(event,this);"/>
<script>
function onlyAllowDigitComma(e,l){
var k = e.which;
if ((k <= 47 || k >= 58 ) && k!=44 && k!=8 && k!=0) {
e.preventDefault()
};
l.value=l.value.replace(/,,/g,',');
}
</script>
Use a regex to validate your input. If the first match you get is the same as the whole input, then you're good to go.
The regex you're looking for is /(\d,?)*/g (Test Link)
For the sake of simplicity, I did the following code with the 'keyup' event to avoid shortcuts problems. You may also want to check on copy / paste event.
let myInput = document.getElementById('myInput');
let myInputValue = myInput.value;
myInput.addEventListener('keyup', function(event){
if(isPerfectMatch(myInput.value, /(\d,?)*/g)){
console.log('Format is correct.');
myInputValue = myInput.value;
}
else {
console.log('Wrong format');
myInput.value = myInputValue;
}
});
function isPerfectMatch(value, regex){
let match = value.match(regex);
return match !== null && match[0] == value;
}
(Demo JSFiddle)

Javascript Regex to limit Text Field to only Numbers (Must allow non-printable keys)

I have received PHP/JS code from previous developer and I need to add number validation to a Mobile Number field. I already have the HTML validation in place but I need to add that if someone presses an invalid key, that it doesn't get displayed only to highlight the field later in red because it contains invalid input.
I've seen many regex's used and tried them but they had an either/or effect from what I need which is: If a letter or special character is entered, do not accept and do not display, all other input (digits, keys) is accepted (I need the invalid character not be displayed at all, not displayed and then erased). The regex that is working the most now is this:
function filterNonDigits(evt)
{
var event = evt || window.event;
var keyentered = event.keyCode || event.which;
keyentered = String.fromCharCode(keyentered);
//var regex1 = /[0-9]|\./;
var regex2 = /^[a-zA-Z.,;:|\\\/~!##$%^&*_-{}\[\]()`"'<>?\s]+$/;
if( regex2.test(keyentered) ) {
event.returnValue = false;
if(event.preventDefault) event.preventDefault();
}
When I used the commented regex1 (with the IF condition reversed), naturally it limited input to only digits thus preventing all keys such as Delete, BackSpace, etc. When using regex2, I still can't press Delete or the digits from the numpad.
So my question is, can the above code be modified to accept only digits but also allow keys? Another important point is that I need a method that doesn't use keycodes (8, 24 etc) for those key, in order to make sure all keyboard types can be used.
New Update:
So my solution is as follows: If the "oninput" property exists, I use the solution provided by Ehtesham and if it doesn't, the backup uses the solution provided by Rohan Kumar. So it's something like this:
if (obj.hasOwnProperty('oninput') || ('oninput' in obj))
{
$('#mobileno').on('input', function (event) {
this.value = this.value.replace(/[^0-9]/g, '');
});
}
else
{
$('#mobileno').on('keypress',function(e){
var deleteCode = 8; var backspaceCode = 46;
var key = e.which;
if ((key>=48 && key<=57) || key === deleteCode || key === backspaceCode || (key>=37 && key<=40) || key===0)
{
character = String.fromCharCode(key);
if( character != '.' && character != '%' && character != '&' && character != '(' && character != '\'' )
{
return true;
}
else { return false; }
}
else { return false; }
});
}
Thanks.
The best method here is to use input event which handles all your concerns. It is supported in all modern browsers. With jQuery you can do like following. Handles all cases pasting the value with mouse/keyboard backspace etc.
$('.numeric').on('input', function (event) {
this.value = this.value.replace(/[^0-9]/g, '');
});
See it here
You can check if input event is supported by checking if the input has this property if not you can use onkeyup for older browsers.
if (inputElement.hasOwnProperty('oninput')) {
// bind input
} else {
// bind onkeyup
}
A nice solution is described in a previous post:
jQuery('.numbersOnly').keyup(function () {
this.value = this.value.replace(/[^0-9\.]/g,'');
});
Try it like,
CSS
.error{border:1px solid #F00;}
SCRIPT
$('#key').on('keydown',function(e){
var deleteKeyCode = 8;
var backspaceKeyCode = 46;
if ((e.which>=48 && e.which<=57) ||
(e.which>=96 && e.which<=105) || // for num pad numeric keys
e.which === deleteKeyCode || // for delete key,
e.which === backspaceKeyCode) // for backspace
// you can add code for left,right arrow keys
{
$(this).removeClass('error');
return true;
}
else
{
$(this).addClass('error');
return false;
}
});
Fiddle: http://jsfiddle.net/PueS2/
Instead of checking for the event keyCode, why don't you just check for changes inside the actual input and then filter out non-numbers?
This example uses keyup so that it can read what was actually entered, which means the character is briefly displayed and then removed, but hopefully you get my gist. It might even give the user feedback that the character is not allowed. Either way I think this is the easiest setup, let me know if you need more help fleshing this out.
function filterNonDigits(evt)
{
var event = evt || window.event;
var val = event.target.value;
var filtered = val.replace(/[^0-9]/g, '');
if(filtered !== val) {
event.target.value = filtered;
event.target.className += " error";
}
}
http://jsfiddle.net/mEvSV/1/
(jquery used solely to easily bind the keyup function, you won't need it for your actual script)
/\d/ is equivalent to the above described /[0-9]/. src: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#special-digit
This is a bit more concise...
this.value = this.value.replace(/\D/gm, '');

How can I tell between a blank textbox and a textbox with zero in it in JavaScript?

I have the following:
var NewCount = document.getElementById('MainContent_gv_NewCount_' + rowIndex).value;
if (NewCount != "") {
document.getElementById('MainContent_gv_lblTotal_' + rowIndex).innerHTML = "£" + ((originalCount - NewCount) * unitCost).toFixed(2);
} else {
document.getElementById('MainContent_gv_lblTotal_' + rowIndex).innerHTML = "";
}
The calculations I am doing are based on the value in the textbox. (NewCount).
I want the label to update if the value is any number (including 0), but to be wiped if the user clears the textbox. However, at the moment it is treating a blank textbox and a textbox with 0 in it the same.
How can I differentiate between the two?
Use !== in your if statement.
I can't reproduce the behavior you are describing. In my tests a textbox with "0" in it will be considered not blank by Javascript using your comparison logic (!= "").
Here is my attempt:
http://jsfiddle.net/pJgyu/5404/
Any of the following could work
NewCount.length > 0
NewCount !== ''
if ( NewCount.length == 0 ) {
// text-box is empty
} else if ( !isNaN(NewCount) ) {
// the value is a number
}

Categories

Resources