2

I am trying to make a HTML form that accepts a rating through an input field from the user. The rating is to be a number from 0-10, and I want it to allow up to two decimal places. I am trying to use regular expression, with the following

function isRatingGood()
{
    var rating = document.getElementById("rating").value;
    var ratingpattern = new RegExp("^[0-9](\.[0-9][0-9]?)?$");

    if(ratingpattern.test(rating))
    {
        alert("Rating Successfully Inputted");
        return true;
    }
    else
    {
        return rating === "10" || rating === "10.0" || rating === "10.00";
    }
}

However, when I enter any 4 or 3 digit number into the field, it still works. It outputs the alert, so I know it is the regular expression that is failing. 5 digit numbers do not work. I used this previous answer as a basis, but it is not working properly for me.

My current understanding is that the beginning of the expression should be a digit, then optionally, a decimal place followed by 1 or 2 digits should be accepted.

Community
  • 1
  • 1
mojo1mojo2
  • 1,062
  • 1
  • 18
  • 28
  • 4
    Why on earth do you need a rating accurate to two decimals? Assuming the "rating" is a "How did you enjoy our service?" type thing, who would say "6.41"? – nnnnnn Sep 16 '15 at 03:40
  • 1
    Excellent question. Truthfully, I don't, but I was looking at prices which have two decimal places (obviously). This made me think of how to use regular expression to represent an optional decimal representation for a rating. It has no practical purpose for a rating system, but I was dealing with the ratings in my HTML code when I thought of it. All for learning I guess. – mojo1mojo2 Sep 16 '15 at 03:58

5 Answers5

4

You are using a string literal to created the regex. Inside a string literal, \ is the escape character. The string literal

"^[0-9](\.[0-9][0-9]?)?$"

produces the value (and regex):

^[0-9](.[0-9][0-9]?)?$

(you can verify that by entering the string literal in your browser's console)

\. is not valid escape sequence in a string literal, hence the backslash is ignored. Here is similar example:

> "foo\:bar"
"foo:bar"

So you can see above, the . is not escaped in the regex, hence it keeps its special meaning and matches any character. Either escape the backslash in the string literal to create a literal \:

> "^[0-9](\\.[0-9][0-9]?)?$"
"^[0-9](\.[0-9][0-9]?)?$"

or use a regex literal:

/^[0-9](\.[0-9][0-9]?)?$/
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • @MaxZoom: The OP is treating this case separately if you look at the code in the question. There are certainly more concise ways to handle this overall, but I just focused on the actual problem. – Felix Kling Sep 16 '15 at 04:01
  • The regular expression only deals with the first digit before the decimal. That's why I have the else statement. This works for 0.00-9.99. – mojo1mojo2 Sep 16 '15 at 04:01
  • And I agree, there are probably more concise ways to do this. I just can't think of them. – mojo1mojo2 Sep 16 '15 at 04:03
  • @mojo1mojo2: Look at MaxZoom's answer. – Felix Kling Sep 16 '15 at 04:04
2

The regular expression you're using will parsed to

/^[0-9](.[0-9][0-9]?)?$/

Here . will match any character except newline.

To make it match the . literal, you need to add an extra \ for escaping the \.

var ratingpattern = new RegExp("^[0-9](\\.[0-9][0-9]?)?$");

Or, you can simply use

var ratingPattern = /^[0-9](\.[0-9][0-9]?)?$/;

You can also use \d instead of the class [0-9].

var ratingPattern = /^\d(\.\d{1,2})?$/;

Demo

var ratingpattern = new RegExp("^[0-9](\\.[0-9][0-9]?)?$");

function isRatingGood() {
  var rating = document.getElementById("rating").value;

  if (ratingpattern.test(rating)) {
    alert("Rating Successfully Inputted");
    return true;
  } else {
    return rating === "10" || rating === "10.0" || rating === "10.00";
  }
}
<input type="text" id="rating" />

<button onclick="isRatingGood()">Check</button>
Tushar
  • 85,780
  • 21
  • 159
  • 179
2

Below find a regex candidate for your task:

^[0-1]?\d(\.\d{0,2})?$

Demo with explanation

var list = ['03.003', '05.05', '9.01', '10', '10.05', '100', '1', '2.', '2.12'];
var regex = /^[0-1]?\d(\.\d{0,2})?$/;

for (var index in list) {
  var str = list[index];
  var match = regex.test(str);
  console.log(str + ' : ' + match);
}
MaxZoom
  • 7,619
  • 5
  • 28
  • 44
1

This should also do the job. You don't need to escape dots from inside the square brackets:

^((10|\d{1})|\d{1}[.]\d{1,2})$

Also if you want have max rating 10 use

10| ---- accept 10

\d{1})| ---- accept whole numbers from 0-9 replace \d with [1-9]{1} if don't want 0 in this

\d{1}[.]\d{1,2} ---- accept number with two or one numbers after the coma from 0 to 9

LIVE DEMO: https://regex101.com/r/hY5tG4/7

Any character except ^-]\ All characters except the listed special characters are literal characters that add themselves to the character class. [abc] matches a, b or c literal characters

Antoine
  • 800
  • 3
  • 14
  • 29
DevWL
  • 17,345
  • 6
  • 90
  • 86
0

Just answered this myself.

Need to add square brackets to the decimal point, so the regular expression looks like

var ratingpattern = new RegExp("^[0-9]([\.][0-9][0-9]?)?$");
mojo1mojo2
  • 1,062
  • 1
  • 18
  • 28
  • 2
    This may "work", but not for the reason you probably think. – nnnnnn Sep 16 '15 at 03:42
  • Yeah, I'm thinking that. Didn't realise the backslash needed to be escaped, not the full stop. – mojo1mojo2 Sep 16 '15 at 03:43
  • 2
    The full top *does* need to be escaped within the regular expression, which is what the backslash is for, but before you get that far the backslash itself needs to be escaped in the string literal that you are using to create the regular expression. – nnnnnn Sep 16 '15 at 03:45
  • Thank you. I know now that strings and regular expressions need to be treated differently :) – mojo1mojo2 Sep 16 '15 at 03:47