i have a simple react application containing a input field i want when the user types string it should not accept and convert arabic digits to english also accept upto 2 decimal digits .curently its doing the conversion but not accepting decimal points
import React, { useState } from "react";
export default function App() {
const [val, setVal] = useState(0);
function ARtoENPrice(input) {
console.log({ stype: typeof input, input });
if (typeof input === "string") {
input = input?.trim();
const arabicNums = ["٠", "١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩"];
let output = "";
let decimal = false;
for (let i = 0; i < input.length; i++) {
if (arabicNums.indexOf(input[i]) !== -1) {
output += arabicNums.indexOf(input[i]);
} else if (input[i] === "." || !isNaN(input[i])) {
if (input[i] === ".") {
if (decimal === true) continue;
decimal = true;
}
output += input[i];
}
}
if (output === "") return "";
if (output === ".") return output;
return parseFloat(output);
} else {
if (input === null || input === undefined || input == NaN) return "";
return Number(input)?.toFixed(2);
}
}
const handleChange = (e) => {
let v = ARtoENPrice(e.target.value);
setVal(v);
};
return (
<input type="text" value={val} onChange={handleChange} />
);
}
Here's a modification to the ARtoENPrice function that only allows two decimal points:
function ARtoENPrice(input) {
if (typeof input === "string") {
input = input.trim();
const arabicNums = ["٠", "١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩"];
let output = "";
let decimalCount = 0;
for (let i = 0; i < input.length; i++) {
if (arabicNums.indexOf(input[i]) !== -1) {
output += arabicNums.indexOf(input[i]);
} else if (input[i] === "." || !isNaN(input[i])) {
if (input[i] === ".") {
decimalCount++;
if (decimalCount > 2) continue;
}
output += input[i];
}
}
return output;
} else {
return Number(input).toFixed(2);
}
}
Related
help !! the console tells me x13. If 2 or more operators are entered consecutively, the operation performed should be the last operator entered (excluding the negative (-) sign. The sequence"5-5"=should produce an output of"-25"expected'-5'to equal¹-25'
AssertionError:The sequence"5-5"=should produce an output of"-25"expected'-5'to equal
I try to use regex because someone tells me I should do that but I don't know how. I do 15 right but one is wrong and I can't pass this test :(
https://codepen.io/mikaelamattos/pen/RwQGeXe
let trailingResult = 0;
let operationOptions = ['divide', 'multiply', 'subtract', 'add'];
let workingOperation = "";
function updateDisplay(input) {
let display = document.getElementById("display");
let secondaryDisplay = document.getElementById("secondaryDisplay");
if (display.innerHTML === "0" && operationOptions.indexOf(input) === -1) {
if (input === "decimal") {
display.innerHTML = "0.";
} else if (input === "negative-value") {
if (display.innerHTML.indexOf("-1") === -1) {
display.innerHTML = "-" + display.innerHTML
} else if (display.innerHTML.indexOf("-1" > -1)) {
display.innerHTML = display.innerHTML.slice(1, display.innerHTML.length);
}
} else {
display.innerHTML = input;
}
} else if (operationOptions.indexOf(input) >= 0) {
if (trailingResult === display.innerHTML) {
workingOperation = input;
} else if (workingOperation === "") {
workingOperation = input;
trailingResult = display.innerHTML;
secondaryDisplay.innerHTML = trailingResult;
display.innerHTML = 0;
} else {
// Dealing with a set operand
// console.log(display.innerHTML, " Dealing with set operand");
trailingResult = calculate(trailingResult, display.innerHTML, workingOperation);
secondaryDisplay.innerHTML = trailingResult;
display.innerHTML = 0;
workingOperation = input;
}
} else if (input === "equals") {
display.innerHTML = calculate(trailingResult, display.innerHTML, workingOperation);
trailingResult = 0;
workingOperation = "";
secondaryDisplay.innerHTML = trailingResult;
} else if (input === "decimal") {
// console.log('decimal clicked');
if (display.innerHTML.indexOf(".") === -1) {
display.innerHTML += ".";
}
// console.log("decimal skipped because decimal already in number.");
} else if (input === "negative-value") {
// console.log("negative-value selected");
if (display.innerHTML.indexOf("-1") === -1) {
display.innerHTML = "-" + display.innerHTML
} else if (display.innerHTML.indexOf("-1" > -1)) {
display.innerHTML = display.innerHTML.slice(1, display.innerHTML.length);
}
} else {
display.innerHTML += input;
}
}
function clearDisplay() {
let display = document.getElementById("display");
let secondaryDisplay = document.getElementById("secondaryDisplay");
trailingResult = 0;
display.innerHTML = 0;
secondaryDisplay.innerHTML = trailingResult;
}
function calculate(firstNumber, secondNumber, operation) {
let result;
firstNumber = parseFloat(firstNumber);
secondNumber = parseFloat(secondNumber);
switch(operation) {
case "add":
result = firstNumber + secondNumber;
break;
case "subtract":
result = firstNumber - secondNumber;
break;
case "multiply":
result = firstNumber * secondNumber;
break;
case "divide":
result = firstNumber / secondNumber;
break;
default:
console.log("Calculate switch statement missed something");
}
return result.toString();
}
As the title says I am using a math-expression library to do my calculations but I am having trouble figuring out the logic for decimals and how to prevent two decimals in one number inside an array. I have highlighted the part that is giving me trouble.
Here is my code sandbox link https://codesandbox.io/s/youthful-frost-2s6v6?file=/src/HookClaculator.js:181-2221
const [input, setInput] = useState([0]);
const [notANum, setNotANum] = useState("");
const [AC, setAC] = useState("");
const handleInputOneClick = (e) => {
let checkInput = input;
checkInput = [...checkInput, parseInt(e, 10)];
console.log(checkInput);
if (checkInput[1] !== 0) {
setInput([...input, parseInt(e, 10)]);
if (input.length > 23) {
console.log("exceeded 23");
setInput(["MAX DIGIT LIMIT REACHED"]);
setTimeout(() => {
setInput([0]);
}, 500);
}
}
};
const handleSymbolClick = (e) => {
if (Number.isInteger(input[input.length - 1])) {
setInput([...input, e]);
} else if (input[input.length - 1] === ".") {
setInput([...input, e]);
} else if (typeof input[input.length - 1] === "string") {
input.pop();
setInput([...input, e]);
}
};
const handleDecimalClick = (e) => {
if (input[input.length - 1] === ".") {
setInput([...input]);
} else if (isNaN(input[input.length - 1])) {
setInput([...input, e]);
} **else if (Number.isInteger(input[input.length - 1])) {
setInput([...input, e]);
}**
};
const handleEqualsClick = (e) => {
let exp = "";
if (input[0] === 0 && input.length <= 1) {
console.log("hell yeah");
setNotANum(["NaN"]);
} else if (input.length > 1) {
console.log("input length is " + input.length);
input.forEach((el) => {
return (exp += el);
});
let value = mexp.eval(exp);
setInput([value]);
}
};
const handleClickReset = (e) => {
setAC(e);
setInput([0]);
};
return (
<div id="calculator-div">
<HookDisplay input={input} notANum={notANum} AC={AC} />
<HookButtons
inputOneClick={handleInputOneClick}
symbolClick={handleSymbolClick}
decimalClick={handleDecimalClick}
handleEqualsButtonClick={handleEqualsClick}
handleClickReset={handleClickReset}
/>
</div>
);
};
return (
<div id="calculator-div">
<HookDisplay input={input} notANum={notANum} AC={AC} />
<HookButtons
inputOneClick={handleInputOneClick}
symbolClick={handleSymbolClick}
decimalClick={handleDecimalClick}
handleEqualsButtonClick={handleEqualsClick}
handleClickReset={handleClickReset}
/>
</div>
);
};
I think before pushing the decimal to the array you can ensure if it'll create a valid expression.
As currently the calculator supports basic operations, a number can never have more than one decimal and operands can only be one more than than the operators, leveraging the stated fact. This condition will work (inside handleDecimalClick):
let lastIndex = -1;
for (let i = input.length - 1; i >= 0; i--) {
if (input[i] === ".") {
lastIndex = i;
} else if (
input[i] === "+" ||
input[i] === "-" ||
input[i] === "*" ||
input[i] === "/"
) {
break;
}
}
if (lastIndex !== -1) return;
Also, for extra protection, added a regex to check if the expression is valid before it goes for evaluation (added the below lines in handleEquals):
const inp = input.join("");
const regex = /(?:(?:^|[-+_*/])(?:\s*-?\d+(\.\d+)?(?:[eE][+-]?\d+)?\s*))+$/;
if (!regex.test(inp)) {
return;
}
I forked your codesandbox and added the fix.
Well, I have an array objects with random values.
Ex.
var value = [
{"name":"ABC","status":"R","city":"Pune"},
{"name":"PQR","status":"R","city":"Nashik"},
{"name":"APR","status":"R","city":"Mumbai"},
{"name":"STY","status":"R","city":"Delhi"},
{"name":"XYZ","status":"R","city":"Ranchi"},
{"name":"LMN","status":"R","city":"Dhule"},
];
Please see below HTML File:
<table>
<thead>
<tr>
<th (click)="changeOrderBy('name')"> Name </th>
<th (click)="changeOrderBy('status')"> Status </th>
<th (click)="changeOrderBy('city')"> City </th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of items | orderBy:orderbyset">
<th>{{item.name}} </th>
<th>{{item.status}} </th>
<th> {{item.city}}</th>
</tr>
</tbody>
</table>
TS File :
export class abc implements OnInit {
private orderbyset:string = 'status';
changeOrderBy(orderby: string) {
let direction = '+'; // default
if (this.orderbyset.indexOf(orderby) !== -1) {
if (this.orderbyset.indexOf('+') !== -1) { direction = '-'; }
}
this.orderbyset = direction + orderby;
}
}
Please see below Orderby Pipe File :
import {
Pipe,
PipeTransform
} from '#angular/core';
#Pipe({
name: 'orderBy',
pure: false
})
export class OrderByConnectedPipe implements PipeTransform {
value: string[] = [];
private static _orderByComparator(a: any, b: any): number {
if ((a === null || a === undefined) && (b === null || b === undefined)) {
return 0;
}
if (a === null || a === undefined) {
a = (isNaN(parseFloat(b)) || !isFinite(b)) ? '' : 0;
}
if (b === null || b === undefined) {
b = (isNaN(parseFloat(a)) || !isFinite(a)) ? '' : 0;
}
if ((isNaN(parseFloat(a)) || !isFinite(a)) || (isNaN(parseFloat(b)) || !isFinite(b))) {
if (a.toLocaleLowerCase() < b.toLocaleLowerCase()) {
return -1;
}
if (a.toLocaleLowerCase() > b.toLocaleLowerCase()) {
return 1;
}
} else {
if (parseFloat(a) < parseFloat(b)) {
return -1;
}
if (parseFloat(a) > parseFloat(b)) {
return 1;
}
}
return 0;
}
transform(input: any, config: string = '+'): any {
//invalid input given
if (!input) return input;
//make a copy of the input's reference
this.value = [...input];
let value = this.value;
if (!Array.isArray(value)) {
return value;
}
if (!Array.isArray(config) || (Array.isArray(config) && config.length == 1)) {
let propertyToCheck: string = !Array.isArray(config) ? config : config[0];
let desc = propertyToCheck.substr(0, 1) == '-';
//Basic array
if (!propertyToCheck || propertyToCheck == '-' || propertyToCheck == '+') {
return !desc ? value.sort() : value.sort().reverse();
} else {
let property: string = propertyToCheck.substr(0, 1) == '+' || propertyToCheck.substr(0, 1) == '-' ?
propertyToCheck.substr(1) :
propertyToCheck;
return value.sort(function(a: any, b: any) {
let aValue = a[property];
let bValue = b[property];
let propertySplit = property.split('.');
if (typeof aValue === 'undefined' && typeof bValue === 'undefined' && propertySplit.length > 1) {
aValue = a;
bValue = b;
for (let j = 0; j < propertySplit.length; j++) {
aValue = aValue[propertySplit[j]];
bValue = bValue[propertySplit[j]];
}
}
return !desc ?
OrderByConnectedPipe._orderByComparator(aValue, bValue) :
-OrderByConnectedPipe._orderByComparator(aValue, bValue);
});
}
} else {
//Loop over property of the array in order and sort
return value.sort(function(a: any, b: any) {
for (let i: number = 0; i < config.length; i++) {
let desc = config[i].substr(0, 1) == '-';
let property = config[i].substr(0, 1) == '+' || config[i].substr(0, 1) == '-' ?
config[i].substr(1) :
config[i];
let aValue = a[property];
let bValue = b[property];
let propertySplit = property.split('.');
if (typeof aValue === 'undefined' && typeof bValue === 'undefined' && propertySplit.length > 1) {
aValue = a;
bValue = b;
for (let j = 0; j < propertySplit.length; j++) {
aValue = aValue[propertySplit[j]];
bValue = bValue[propertySplit[j]];
}
}
let comparison = !desc ?
OrderByConnectedPipe._orderByComparator(aValue, bValue) :
-OrderByConnectedPipe._orderByComparator(aValue, bValue);
//Don't return 0 yet in case of needing to sort by next property
if (comparison != 0) {
return comparison;
}
}
return 0; //equal each other
});
}
}
}
export let ORDERBY_PROVIDERS = [
OrderByConnectedPipe
];
I wanted to sort this resultant array by any column like name,status and city.But what happened is when I sort by column "name" and "city" it is working fine but when I sort by column "status" then resultant set get sorted in different order.Actually as we can see column values in "status" are same in resultant set.Please suggest me best way to get this.
I am trying like this:
function k(){
var x = $('#textArea').val();
for (i = 0; i < x.length; i++)
{
if(x[i].match(/^[0-9]/))
{
if(x[i+1].match(/^[0-9]/) && x[i+2].match(/^[0-9]/) && x[i+3].match(/^[-]/) && x[i+4].match(/^[0-9]/) && x[i+5].match(/^[0-9]/) && x[i+6].match(/^[-]/) && x[i+7].match(/^[0-9]/) && x[i+8].match(/^[0-9]/) && x[i+9].match(/^[0-9]/) && x[i+10].match(/^[0-9]/))
{
if(x[i+11].match(/^[0-9]/))
{
return 'true';
}
else
{
return false;
}
}
else if(x[i+1].match(/^[0-9]/) && x[i+2].match(/^[0-9]/) && x[i+3].match(/^[0-9]/) && x[i+4].match(/^[0-9]/) && x[i+5].match(/^[0-9]/) && x[i+6].match(/^[0-9]/) && x[i+7].match(/^[0-9]/) && x[i+8].match(/^[0-9]/))
{
if(x[i+9].match(/^[0-9]/))
{
return 'true';
}
else
{
return false;
}
}
else
{
continue;
}
}
else
{
continue;
}
}
return 'true';
}
Or simply
var x = $('#textArea').val();
x = x.replace(/\D+/g,""); //first remove all non-digits from x
if (x.length <= 8 )
{
return true;
}
return false;
Or if you only want to allow - and digits
var x = $('#textArea').val();
var matches = x.match( /[0-9-]/g ).length;
if ( !matches || matches.length != x.length )
{
return false;
}
x = x.replace(/\D+/g,""); //first remove all non-digits from x
if (x.length <= 8 )
{
return true;
}
return false;
function myFunc() {
var patt = new RegExp("\d{3}[\-]\d{2}[\-]\d{4}");
var x = document.getElementById("ssn");
var res = patt.test(x.value);
if(!res){
x.value = x.value
.match(/\d*/g).join('')
.match(/(\d{0,3})(\d{0,2})(\d{0,4})/).slice(1).join('-')
.replace(/-*$/g, '');
}
}
<input class="required-input" id="ssn" type="text" name="ssn" placeholder="123-45-6789" onBlur = "myFunc()">
or using pure regexp
to match the 123-45-678 and 12345678 formats:
var x = $('#textArea').val();
if (x.match(/^\d{3}-\d{2}-\d{3}$|^\d{8}$/) {
return true;
} else return false;
to match any number less then 9 digits:
var x = $('#textArea').val();
if (x.match(/^(?:\d-?){1,8}$/) {
return true;
} else return false;
These two Javascript functions are supposed to convert serial numbers (2-9999) for example into a number , but the functions below are not working for some reason .. they were originally written in PHP ... Works in PHP but not for Javascript.
<html>
<head>
<script type="text/javascript">
function my_isnum(str, negative=false, decimal=false)
{
var has_decimal = false;
var len = strlen(str);
if (len > 0) {
var valid = true;
for (var i=0; valid && i < len; i++) {
if (!(str[i] >= "0" && str[i] <= "9")) {
if (str[i] == "-") {
if (!negative || i != 0) {
valid = false;
}
} else if (str[i] == ".") {
if (!decimal || has_decimal) {
valid = false;
}
} else {
valid = false;
}
}
}
} else {
valid = false;
}
return valid;
}
function esn_to_num(esn) {
var tmp = [];
if ((tmp = esn.split("-")) {
if (tmp.length == 2
&& my_isnum(tmp[0])
&& my_isnum(tmp[1])
) {
esn = ((tmp[0] << 23) | tmp[1]);
} else {
esn = -1;
}
} else {
esn = -1;
}
return esn;
}
alert(2-9999);
</script> </head>
</html>
Original PHP functions
<?php
function my_isnum($str, $negative=false, $decimal=false)
{
$has_decimal = false;
$len = strlen($str);
if ($len > 0) {
$valid = true;
for ($i=0; $valid && $i<$len; $i++) {
if (!($str[$i] >= '0' && $str[$i] <= '9')) {
if ($str[$i] == '-') {
if (!$negative || $i != 0) {
$valid = false;
}
} else if ($str[$i] == '.') {
if (!$decimal || $has_decimal) {
$valid = false;
}
} else {
$valid = false;
}
}
}
} else {
$valid = false;
}
return $valid;
}
function esn_to_num($esn)
{
if (($tmp = explode('-', $esn))) {
if (sizeof($tmp) == 2
&& my_isnum($tmp[0])
&& my_isnum($tmp[1])
) {
$esn = (($tmp[0] << 23) | $tmp[1]);
} else {
$esn = -1;
}
} else {
$esn = -1;
}
return $esn;
}
?>
There is no such thing as strlen in Javascript. Use str.length instead.
Also, as Jason Sperske suggested below, change this:
function my_isnum(str, negative=false, decimal=false)
To this:
function my_isnum(str, negative, decimal)
{
if (typeof negative == "undefined") negative = false;
if (typeof decimal == "undefined") decimal = false;
....
}
These two javascript functions are supposed to convert serial numbers (2-9999) for example into a number.
Why not just get rid of the - and parse as a decimal number?
function padToFourDigits(_, digits) {
return "0000".substring(digits.length) + digits;
}
function serialToNum(serialNumStr) {
return +(serialNumStr.replace(/-(\d{1,4})/g, padToFourDigits));
}
Then
serialToNum('2-9999') === 29999
serialToNum('2-999') === 20999