jquery-validation / jquery-validation

jQuery Validation Plugin library sources
https://jqueryvalidation.org/
MIT License
10.35k stars 2.79k forks source link

LessThan and LessThanEqual methods don't work correctly for negative numbers #2164

Open Laura-Guillory opened 6 years ago

Laura-Guillory commented 6 years ago

Subject of the issue

When negative numbers are entered in an input field with a lessThan or lessThanEqual rule applied, the form will pass validation when it shouldn't, and fail validation when it should pass - as if the rule was actually greaterThan. What seems to be happening is that the absolute value is used (-1 is treated as 1, for example). So if we have -2 compared to -1, -1 is treated as being "less than" -2, even though -2 < -1.

Your environment

Steps to reproduce

lessThan with negative numbers:

  1. Open the following HTML file
  2. Enter -2 and -1 in the two input fields respectively
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    </head>
    <body>
    <form id="form">
        <input id="A" name="A" type="number" value="" /><br />
        <input id="B" name="B" type="number" value="" /><br />
        <input type="submit" value="Submit" />
    </form>
    </body>
    </html>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="jquery-validation/jquery.validate.js"></script>
    <script src="jquery-validation/additional-methods.js"></script>
    <script>
    $("#form").validate({
        rules: {
            A: {
                lessThan: "#B"
            }
        }
    });
    </script>

    lessThanEqual with negative numbers:

  3. Open the following HTML file
  4. Enter -2 and -1 in the two input fields respectively
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    </head>
    <body>
    <form id="form">
        <input id="A" name="A" type="number" value="" /><br />
        <input id="B" name="B" type="number" value="" /><br />
        <input type="submit" value="Submit" />
    </form>
    </body>
    </html>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="jquery-validation/jquery.validate.js"></script>
    <script src="jquery-validation/additional-methods.js"></script>
    <script>
    $("#form").validate({
        rules: {
            A: {
                lessThanEquals: "#B"
            }
        }
    });
    </script>

Expected behaviour

In both instances, I would expect validation to pass, since -2 < -1.

Actual behaviour

Validation fails with the message: "Please enter a lesser value." If the numbers are swapped, validation will pass which is incorrect.

Laura-Guillory commented 6 years ago

This is still an issue.

Arkni commented 6 years ago

Hi @Laura-Guillory,

Thanks for opening this issue.

I'll mark this issue as a bug for now. I didn't have any look at it, but will revisit when I get some free time.

RobJohnston commented 6 years ago

I bet that it's always doing a string compare. Somehow, the data type has to be determined (int, float) before a compare is done. This will have to be done to the greaterThanand greaterThanEqualfunctions too.

jlmasson commented 2 years ago

I bet that it's always doing a string compare. Somehow, the data type has to be determined (int, float) before a compare is done. This will have to be done to the greaterThanand greaterThanEqualfunctions too.

You're right. This happens in this example "1000" <= "500", you expect to be false, but JS returns true. That's why this validation fails.

The solution for these validations is:

$.validator.addMethod( "lessThanEqual", function( value, element, param ) {
    var target = $( param );

    if ( this.settings.onfocusout && target.not( ".validate-lessThanEqual-blur" ).length ) {
        target.addClass( "validate-lessThanEqual-blur" ).on( "blur.validate-lessThanEqual", function() {
            $( element ).valid();
        } );
    }

    var referenceValue = target.val();
        if ($.isNumeric(value) && $.isNumeric(referenceValue)) {
            value = parseFloat(value);
            referenceValue = parseFloat(referenceValue);
            return value <= referenceValue;
        }

    return value <= target.val();
}, "Please enter a lesser value." );

In the return section, you only have to change the symbol for the correct one. This is for lessThanEqual, lessThan (<), greaterThan (>) and greaterThanEqual (>=)