Novice Javascript query about bad input - javascript

I am making a simple tip calculator to help myself learn Javascript. The problem I can't solve is how to compensate for "bad input".
In the code below if the user prefaces the numeric input amount with a dollar sign $, the result is NAN.
function tipAmount(){
var dinner=prompt("How much was dinner?");
result = dinner*.10;
alert("Your tip is " +"$"+result );
}
How do I fix that.

You can try to parse out the numeric value with a regular expression:
var match = dinner.match(/\d+\.?\d*/); // parse with a regular expression
if(!match) { // not able to parse
alert("wrong");
}
var price = +match[0]; // convert to a number
result = price * .10;
The regular expression /\d+\.?\d*/ means: one or more digits, and possibly a dot with other digits following. This means that if e.g. dinner is "$1.23", price will be the number 1.23. The same goes for "$ 1.23" or "1.23 dollar" etc - the number will be parsed out with the pattern defined by the regular expression.

The simplest way would be to parse the input into a float, and see if NaN is returned.
if (isNaN(parseFloat(dinner)))
alert("Bad Input")
Just note that 45.2WWW will return 45.2, and so the above will pass.
If you want to make sure what the user typed in is exactly a number, you could do something like this:
var str = '3.445';
var num = parseFloat(str);
if (isNaN(num) || str.length !== num.toString().length)
alert("Bad Input");

try to parse the input as float or integer depending on your needs:
var dinner = parseFloat(prompt("How much was dinner?"));
or
var dinner = parseInt(prompt("How much was dinner?"));
this functions return 0 whether they unable to parse the input as number

Given your approach of using alerts, the following will work:
function tipAmount() {
var dinner=prompt("How much was dinner?");
//convert "dinner" to a number, stripping out any non numeric data
dinner = Number(dinner.replace(/[^0-9\.]+/g,""));
//any unknown data will convert to 0
if(dinner <= 0) {
alert("Please enter a valid amount");
return false;
}
var result = dinner*.10;
alert("Your tip is " +"$"+result );
return true;
}
Please tip more!

Just check if the value is numeric - Javascript's isNaN:
if (isNaN(dinner)) {
alert('Bad number, bub.');
return;
}

Or, if you want to allow users to type in both - just number or an amount with $ at the beginning, you can check for first char:
if( dinner.charAt(0) == '$' )
{
dinner = dinner.substring(1);
}
This way, whenever user types $, your app will just remove it. If they type a normal number it will calculate the tip for you...

Related

Validate particular range using regex

I want validate text box with particular range having format like :
1-99
I am using regex :
/^(?:100|[1-9]\d|\d)-(?:100|[1-9]\d|\d)$/
It works for me but little problem that is it accept this:
55-50
And it shouldn't, this is wrong.
how can I correct this?
As it has been told early regexp is not the method for validating ranges. The better way is to use if/else statements. But you are not restricted in usage of regexp for validating input string on the particular format.
F.i., if you'd like to enable the end user to enter the range in the format number1-number2, you could check the string for compliance to this format and check its parts for complaince to the condition number1 <= number2. If all these checks are done you could do something useful or decline, if checks are fail.
function validRange(rangeStr, min, max) {
var m = rangeStr.match(/^([0-9]+)-([0-9]+)$/);
if ( m && m[1] >= min && m[2] <= max && m[1] <= m[2] ) {
return true;
}
return false;
}
var s = '1-99';
var s = '55-50';
if ( validRange(s, 1, 99) ) {
// do something useful
}
The code above is just skeleton for the further improvements but it can be used now. But the code could be too complicated, if you or your customers will request to implement something more complex like ability to enter single number, lists of numbers (separated with comma, semicolons etc), mixed ranges or any combination of all of them.
Because you need to check validation between the both number you have to use logical operations to check if the forst number is less than second, so you couldn't use regex in this case instead use if/else statement :
var input = "55-50";
if(input.indexOf('-')){
var input_arr = input.split('-');
if(input_arr.length==2 && parseInt(input_arr[0])<parseInt(input_arr[1]))
alert("Accepted");
else
alert("Not accepted");
}

jQuery Validation, Numeric Value Only

I'm trying to validate a form input value. The function below states is the value of the input is a number below 150, show error. Works as it should. However, I want to add to it. If the value contains ANYTHING other than a numeric value AND/OR is a value under 150, show error...
How can I modify?
if ($('.billboard-height').val() < 150) {
$('.sb-billboardalert').fadeIn(600);
}
Since your more thorough validation should be on the server-side anyway, you could just use parseInt or parseFloat depending on what sort of value you are expecting. Then check if the result is actually a number and that it also meets your constraints:
var number = parseFloat($('.billboard-height').val()); // or parseInt depending on expected input
if (isNaN(number) || number < 150) {
$('.sb-billboardalert').fadeIn(600);
}
EDIT:
Based on your comments, you are entering regex land. I gather you only ever want a natural number (and the way parseInt/parseFloat ignores trailing non-numeric characters like px, em, etc. is not ok). How about:
var val = $('.billboard-height').val();
var number = parseInt(val, 10);
if ( ! val.match(/^[0-9]{3,4}$/) || number < 150) {
$('.sb-billboardalert').fadeIn(600);
}
This should only allow natural numbers 150-9999.
I would suggest using regexes:
var intRegex = /^\d+$/;
var floatRegex = /^((\d+(\.\d *)?)|((\d*\.)?\d+))$/;
var str = $('#myTextBox').val();
if(intRegex.test(str) || floatRegex.test(str)) {
alert('I am a number');
...
}
Or with a single regex as per #Platinum Azure's suggestion:
var numberRegex = /^[+-]?\d+(\.\d+)?([eE][+-]?\d+)?$/;
var str = $('#myTextBox').val();
if(numberRegex.test(str)) {
alert('I am a number');
...
}
ref: checking if number entered is a digit in jquery
Don't forget the radix parameter in parseInt():
if (parseInt($('.billboard-height').val(), 10) < 150) {
It's probably faster than using a regex. Regular expressions are not known for being fast, but they are very powerful. It might be overkill for this scenario.
You can try out HTML5's built in form validation:
<input type="number" min="150">
browser support is still pretty shakey though
Any value from an input or select will be a string in javascript. You need to use parseInt() to use operators like > or <. == can be used if you use it to compare to a string like if ($('.billboard-height').val() == "150")
Try parseInt and isNaN functions for check if value is number and less than 150:
var intVal = parseInt($('.billboard-height').val());
if(!isNaN(intVal)){ //not Number
if (parseInt($('.billboard-height').val()) < 150) { //not less than 150
$('.sb-billboardalert').fadeIn(600);
}
}
If you need to support floating point numbers, you can check if a variable is valid using:
function isNumber (n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
var val = $('.billboard-height').val();
if (isNumber(val) && parseFloat(val) < 150) {
$('.sb-billboardalert').fadeIn(600);
}
If you only need to support integers, use parseInt(n, 10), where 10 is the base to convert the string to.
var val = parseInt($('.billboard-height').val(), 10);
if (val && val < 150) {
$('.sb-billboardalert').fadeIn(600);
}
// Displays an alert if s contains a non-numeric character.
function alertForNonNumeric(s) {
var rgx = /[^0-9]/;
if (s.search(rgx) !== -1) {
alert("Input contains non-numeric characters!");
}
}
JS Fiddle here
NOTE: If you want to check for negative ints as well, you can add a minus sign to the regex:
function alertForNonNumeric(s) {
var rgx = /[^0-9-]/;
if (s.search(rgx) !== -1) {
alert(s + " contains non-numeric characters!");
}
}
I use this solution, I find it quite ellegant - no alerts, user is effectively unable to enter non numeric characters.
This is jQuery example:
function digitsOnly(){
// extract only numbers from input
var num_val = $('#only_numbers').val().match(/\d+/);
$('#only_numbers').val(num_val);
}
Your html:
<input type="text" name="only_numbers" id="only_numbers" on oninput="digitsOnly();"/>

Decomposition of Javascript Class and Function Calls

I am creating a class to convert an integer to a sentence in a natural language. I've got some basic checks going on to ensure that the number given is between -9999 and 9999. I feel like this works for the most part.
However, once the program reaches "this.convertSentence" - past the try/catch block and error checking, I'm wondering what the best practice is now to decompose the problem into the various function calls it will need to run through to get the job done.
What I'm planning on doing with this.convertSentence is doing some checking for number size, etc...and then sending the number off to separate functions to do more work and having them propagate a sentence to return. I'm not sure if I want a variable just within my class to work with or whether I should be passing a variable around for the sentence to build. Things like this I am wondering about.
/**
* A class for converting an integer to a natrual language sentence in Spanish.
* Accepts integers from -9999 to 9999
*
*/
function NumberToWord () {
this.getSentence = function(number) {
// Check for erroneous input. Accepts only -9999 thru 9999 integers
try
{
if(number === parseInt(number) && number > -10000 && number < 10000) {
return this.convertSentence(number);
}
else {
throw new Error("Argument is not an integer between -9999 and 9999");
}
}
catch(e){
console.log(e.name + " " + e.message);
}
};
this.convertSentence = function(number) {
return "This is where I'll start the logic for the sentence";
};
}
var numberToWord = new NumberToWord();
// Tests
console.log(numberToWord.getSentence(9999));
console.log(numberToWord.getSentence(-9999));
console.log(numberToWord.getSentence(10000));
console.log(numberToWord.getSentence(-10000));
console.log(numberToWord.getSentence(0));
console.log(numberToWord.getSentence(1.1));
console.log(numberToWord.getSentence(-9999.1));
console.log(numberToWord.getSentence(10001));
console.log(numberToWord.getSentence(-10001));
console.log(numberToWord.getSentence(5.5));
console.log(numberToWord.getSentence());
There are a few things I found amiss in your code:
You don't need a class. You simply want to convert a number to a sentence. Use a function.
Why are both getSentence and convertSentence public? Only getSentence should be public.
Since your class will (in all probability) only be instatiated once, use the singleton pattern.
Things I would do:
Because you want to make your code modular, I would use the module pattern.
You can delegate specific tasks to different functions, but keep them in a private namespace.
Here's the code:
Number.prototype.toWord = function () {
return function (lang) {
var number = this.valueOf();
if (parseInt(number) === number) {
if (number < 10000 && number > 10000) {
switch (lang) {
case "es":
return toSpanish(number);
case "en":
default:
return toEnglish(number);
}
} else throw new RangeError("Expected an integer between ±10000.");
} else throw new TypeError("Expected an integer.");
};
function toSpanish(number) {
// convert the number to Spanish
}
function toEnglish(number) {
// convert the number to English
}
}();
Then you can use it like this:
var number = 1337;
alert(number.toWord("es"));
Edit: I wrote a simple function which will do what you want. However it's in English. I don't know Spanish so you'll have to implement that yourself. Here's the demo: http://jsfiddle.net/XKYhx/2/
My thinking would be to check how many parts you are going to have to the sentence and build an array to match with the substrings. for example, in English anyway (I don't speak Spanish!)
as natural language you would say (minus) xxx thousand and xxx
since your number has a max / min of ~10000 / ~-10000,
in pseudocode:
var sign = ""
var wholeparts = new Array()
var mantissaparts = new Array()
if number < 0,
sign = "minus"
number = math.abs(number) // turn the number into a positive number now we have the sign
var whole = math.floor(number) //get whole number
var mantissa = number - whole //get the after decimal part if exists
if whole > 1000
wholeparts.push(math.floor(whole/1000)) //get the thousands part
wholeparts.push(whole - parts[0]*1000) // add the hundreds
else
parts.push(whole)
if mantissa.length > 0
do something similar for the mantissa to the mantissaparts array.
At this point you would have the sentence structure broken down then:
string sentance:
foreach (var part in wholeparts)
stringify and check each number, converting to human words depending on index, ie "seven" or "seventy", add each to the string.
if wholeparts.length > 1 : sentence = sentence + " thousand and"
then if you had a mantissa, sentence = sentence + "point" .. then and the mantissa as natural language.
Best breakdown I can think of would be:
method to convert a number (whole or mantissa) to an array,
method to convert the array to natural language, with a parameter saying if it is whole or mantissa for the different wording that would be used.
method that accepts a number in string form and returns the natural language equivalent
Hope that helps .. was thinking on the fly.

Error with validation process by input data

Goal:
I dont wanna retrieving any data if the input data contain any alphabet.
Problem:
If I have input data "23w" in variable ddd, the process on convertion is accceptable to be "23" in the variable currentvalue.
I don't want it to be converted into number if the input data contain
any alphabet.
The sourcecode is writtin in jQuery and if possible it would be great to retreive the new solution in jQuery.
// Fullmetalboy
var ddd = $('#field_hourInput').val();
var currentValue = parseInt(ddd);
// Validating message
if(currentValue <= 0)
{
alert("Value must be positiv");
nonError = false;
}
else if( (isNaN(currentValue)) && (ddd != "") )
{
alert("value must contain numbers");
nonError = false;
}
else if( (isNaN(currentValue)) && (ddd == "") )
{
alert("value must contain value in the textbox");
nonError = false;
}
parseint() will return a number if the string begins with one, even if there is non-numbers following it. For example: http://jsfiddle.net/uQztw/
Probably better to use a regex. Something like
http://jsfiddle.net/uQztw/1/
You can use regex to validate that. Using regex with jquery. And using regex
[\d]
which will match any digit should do the trick.
Another way to convert string to int is Number(ddd), it does what you expect. But you could also check ddd through a regular expression, which feels better to me.
regexp-test: /^\d+$/.test(ddd)

How to store more than 10 digit number in javascript using the var?

First of all,
What am i doing ?
I have to set the limit of emails in our product in webpage.It's handled with the javascript for validation.It handles upto 8 digit numbers fine. But in our QA team enters the more than 17 digit number in the text box of other email field.It throw the negative message.What can i do ???
My sample code is:
if(form.otherEmails) {
if(validEmailArray.endsWith(',')){
var otherEmailLength = validEmailArray.substring(0,validEmailArray.length-1).split(",");
var setLimitOtherEmail = window.parent.document.getElementById('setLimitOtherEmail').value;
if(setLimitOtherEmail == '-1'){
form.otherEmails.value = otherEmailLength;
}
else if(otherEmailLength.length <= setLimitOtherEmail){
form.otherEmails.value = otherEmailLength;
}
else{
alert("More than "+setLimitOtherEmail+ " " +"Recipient emailIds not allowed in this section.\nIf you want to send it to more recipients, Please create a Bulk Contact Group.");
form.otherEmails.focus();
return false;
}
}
else
form.otherEmails.value = validEmailArray;
}
This is due to the limit being a string, and when a string is being compared to a number (length) the number is coerced into a string, not the other way around.
These are then compared lexicographically - and lexicographically "9" is more (>) than "19".
You need to use parseInt(setLimitOtherEmail, 10) to get the value as a number before comparing them.
Try parsing each of the numbers into Integers before performing any comparison operations on them.
var setLimitOtherEmail = parseInt(window.parent.document.getElementById('setLimitOtherEmail').value);
Other than that are you certain otherEmailLength is actually the number that you want? From the looks of it you are taking the substring of validEmail array and splitting it on "," but it doesn't look like you actually get the length of the array. Try adding .length to the end of the value of otherEmailLength.
var otherEmailLength = validEmailArray.substring(0,validEmailArray.length-1).split(",").length;

Categories