views:

142

answers:

4

I use jQuery to get the browser version like this:

var x = $.browser.version;

I get a string like this: 1.9.1.1

Now, I want to do an evaluation so if x is >= 1.9.1 then do some stuff. Unfortunately, with multiple decimal points, I cannot do a parseFloat() because it converts 1.9.1.1 to simply 1.9, and the if evaluation would match a 1.9.0 version (which I do not want).

Has someone figured out a way to accomplish turning a version number (with multiple decimals) into something that can be used as a number for evaluation (or some other way to accomplish what I am trying to do here)?

Thanks -

A: 

You could remove all dots and then parse it as an integer. Take note tho, this solution doesn't work in the long term.

henrikh
1.9.10 != 1.9.1.0
Daniel
Already thought of this -- wont work since version may be 2.0 (converts to 20) but 2.0 is greater than 1.9.1.1 (for example).
OneNerd
+7  A: 

You could do something with string.split and then do a digit by digit comparison

// arr[0] = 1
// arr[1] = 9
// arr[2] = 1
// arr[3] = 1
var arr = ($.browser.version).split('.');

The following is taken from this post

This is a function that will parse your version string and give you back a JSON object

function parseVersionString (str) {
    if (typeof(str) != 'string') { return false; }
    var x = str.split('.');

    // parse from string or default to 0 if can't parse 
    var maj = parseInt(x[0]) || 0;
    var min = parseInt(x[1]) || 0;
    var bld = parseInt(x[2]) || 0;
    var rev = parseInt(x[3]) || 0;
    return {
        major: maj,
        minor: min,
        build: bld,
        revision: rev
    }
}

Then you could use the following syntax

var version = parseVersionString($.browser.version);
// version.major == 1
// version.minor == 9
// version.build == 1
// version.revision == 1
Jon Erickson
the build: pat, should be build: bld, and i modified slightly for my use, but worked nicely -- thanks!
OneNerd
A: 

You need to treat each portion of the string as a seperate integer, so split and iterate, and cmp:

// perform cmp(a, b)
// -1 = a is smaller
// 0 = equal
// 1 = a is bigger
function versionCmp(a, b) {
  a = a.split(".");
  b = b.split(".");
  for(var i=0; i < a.length; i++) {
    av = parseInt(a[i]);
    bv = parseInt(b[i]);
    if (av < bv) {
      return -1;
    } else if (av > bv) {
      return 1;
    }
  }
  return 0;    
}

console.log(versionCmp("1.1.2.3", "1.2.1.0"));  // should be -1
console.log(versionCmp("1.19.0.1", "1.2.0.4"));  // should be 1
console.log(versionCmp("1.2.3.4", "1.2.3.4"));  // should be 0
Richard Levasseur
doesn't work correctly if the version numbers differ in the number of digits: you'll have to check `i < a.length || i < b.length` and set `av` or `bv` to `0` on overflow
Christoph
Yeah, i was going to revise it and do the packing you did, but Jon's answer had already been accepted by then; I didn't see much point.
Richard Levasseur
+1  A: 

Here's another version of versionCmp():

function versionCmp(v1, v2) {
    v1 = String(v1).split('.');
    v2 = String(v2).split('.');

    var diff = 0;
    while((v1.length || v2.length) && !diff)
        diff = (+v1.shift() || 0) - (+v2.shift() || 0);

    return (diff > 0) - (diff < 0);
}

Another possibility would be to assign a numeric value to each version number:

function valueOfVersion(ver) {
    ver = String(ver).split('.');

    var value = 0;
    for(var i = ver.length; i--;)
        value += ver[i] / Math.pow(2, i * 8) || 0;

    return value;
}

This only works if each digit is less than 256 (because of the hard-coded divisor) and has a limited precision (ie the version strings can't get arbitrarily long).

Christoph
Excellent. Unary plus. Under-utilized shift method. But why "String"?
Nosredna
`String()` is used to cast the values; otherwise, an error would be thrown for non-string arguments; with the cast present, you may eg supply numeric arguments like `1.5` and still get somewhat meaningful results
Christoph
I wondered if that was it. But since you are willing to do a unary plus to cast a string to a number, you may be willing to use +"" to cast a number to a string. v1 = (v1+"").split('.'); Not saying you should.
Nosredna
using `+ ''` would work, but it's ugly: the explicit cast is far more readable, imo
Christoph
I could make the same argument about your unary plus. :-)
Nosredna
yes, and that's the reason why I normally always use explicit casting; but with the high density of 'funny stuff' packed into the code, I thought it would be appropriate to go with the hackish version as long as it doesn't violate the aesthetic value
Christoph