2

Why code fragments that looks similar works in different ways?

<input data-value-max="10">

1. If script gets option from attr, it always updates input with option value:

$('input').keyup(function(e) {

  var $this = $(this);
      option = $this.attr('data-value-max');
      val = $this.val();

  if (val > option){   // ←---
    e.preventDefault();
    $this.val(option);
  }

});

I mean that if I type 3 or 10, script updates input to 10.

2. The second variant works just as I expect—it replaces input value only if it is greater then a number in if statement:

$('input').keyup(function(e) {

  var $this = $(this);
      option = $this.attr('data-value-max');
      val = $this.val();

  if (val > 10){   // ←---
    e.preventDefault();
    $this.val(option);
  }

});

So I can't understand why the first variant replaces input value all the time?

2
  • 3
    Where is val defined in second code ? Commented Feb 25, 2013 at 14:01
  • @dystroy missed a line Commented Feb 25, 2013 at 14:04

4 Answers 4

6

You don't parse the values and attributes.

You should know that "3" > "10" but 3 < "10" (in the latter case, "10" is automatically converted for the comparison).

Use parseInt :

var option = parseInt($this.attr('data-value-max'), 10);

As your attribute has the data prefix, you might also use jQuery data's auto conversion feature :

var option = $this.data('value-max');

But personally I try to avoid it (especially given the bugs in 1.7 version) and I prefer to be explicit. And it wouldn't work for any value that you can parse as numbers : only those that give the same exact string if toString is called on the number (it would fail for "03" or "+03" for example).

Sign up to request clarification or add additional context in comments.

9 Comments

or simply (+val > +option)
or simply option = $this.attr('data-value-max')*1;
or simpler option = +$this.attr('data-value-max') >_>
or even even simpler option = $this.data('value-max') like said in the doc.
@abernier That's what I was mentioning in my answer, but be careful as it wouldn't work for "01" for example. It tests +data+""===data.
|
1

Cleaner:

$('input').keyup(function(e) {

    var max_value = $(this).data('value-max') * 1;

    if( this.value * 1 > max_value )
        this.value = max_value;

});

You are comparing strings in your first example and in your second you are comparing a string to an integer (10). You want to convert your strings to an integer for your expected comparison. One method is the *1 I used above.

Finally e.preventDefault() is not needed.

Comments

0

Your second example is relying on JavaScript's type-coercion to compare.

What you are literally doing is testing if "3" > 10 which JS interpreter realizes you're trying to do a numeric comparison and converts it internally to 3 > 10

This is just fine if you understand what the interpreter will try and coerce....similar examples would be:

var x = 0;
if(x) { /* do stuff */ } //0 is a falsy (but not === false) value so the test will always fail

var y = "10";
console.log(y * 10) //outputs 100;

Comments

-1

I suspect your issue has root in weak typing and type conversion. try this:

 if(parseInt(val) > 10) { ...

2 Comments

right guess, but wrong way around... Your example works, because val is coerced, but not the first one where both values are strings.
My comment actually makes no sense at all because it addresses the second (working) code block and not the non-working first one. the point was parseInt() though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.