1

I'm working with CSS values in my js/jquery application and to make values like "20px" or "100%" or "4.58 em" editable, they need to be separated into value / unit pairs. My regex is patchy and so far I have come up with this after hours of tinkering.

split_unit : function (v) {
    if (typeof v === 'string' && v !== ""){
        var split = v.match(/^(\d+(?:\.\d+)?)(.*)$/);
        return {'value':split[1].trim(),  'unit':split[2].trim()};
    }
    else{
        return { 'value':v, 'unit':"" }
    }
}

"split_unit" is a method that splits a values like "20px", "100%", "4.58 em", "440" or "9.4" to object containing value and unit.

It works nicely with values like "20px", "100%", "4.58 em", "440" or "9.4",

however the regex does not appear to be working with negative values and values that start with a decimal point like so "-40px", ".40em", "-80", ".04" etc.

I can do a replace of the decimal point and the '-' minus/hyphen at the start of the function and then append it to the value string at the end, but there has to be a more elegant way of doing it.

How would I go about tweaking the regex or the function itself so it works with negative values and values starting with decimal points ?

Thank you for answering this and for your time.

Norman
  • 705
  • 1
  • 10
  • 24

3 Answers3

1

Thank you for the comments @Oleg V. Volkov, @Jaromanda X @Teemu I've tried the suggestions and this seems to be working v.match(/^([-.\d]+(?:.\d+)?)(.*)$/); Thanks Oleg ...

I'll run a few more tests and then confirm that this works 100%.

split_unit : function (v) {
    if (typeof v === 'string' && v !== ""){
        var split = v.match(/^([-.\d]+(?:\.\d+)?)(.*)$/);
        return {'value':split[1].trim(),  'unit':split[2].trim()};
    }
    else{
        return { 'value':v, 'unit':"" }
    }
}

Works perfectly with the following strings:

"-.280em", "290px", "100%", "480", "4.80", "20px", "100%", "4.58 em", "-40px", ".40em", "-80", ".04"

Norman
  • 705
  • 1
  • 10
  • 24
0

Use this complete code :

// Getting all unit+value from a string:

var m='40px 80px 45% .30px -25em'.match(/((-?)(\d)*(\.?))(\d)+(%|\w)*/gmi);

// Getting values :
var val1= m[0].match(/((-?)(\d)*(\.?))(\d)+/gmi)[0];

// Getting Unit :
var unit1=m[0].replace(/((-?)(\d)*(\.?))(\d)+/gmi,'')[0];

So based on your code you can use above code(let v be a match returning from my first line of code above) :

    split_unit : function (v) {
        if (typeof v === 'string' && v !== ""){

            return {'value':v.match(/((-?)(\d)*(\.?))(\d)+/gmi)[0], 
                    'unit':v.replace(/((-?)(\d)*(\.?))(\d)+/gmi,'')[0]};
        }
        else{
            return { 'value':v, 'unit':"" }
        }
    }
nAviD
  • 2,784
  • 1
  • 33
  • 54
0

Have a try with:

var re = /(-?\d*(?:\.\d+)?)\s*(\D+)/;
var res = re.exec(".40 %");//  ==> [".40 %", ".40", "%"]

Revision, allow null for unit:

var re = /(-?\d*(?:\.\d+)?)\s*(\D*)/;
var res = re.exec(".40");//  ==> [".40 %", ".40", ""]
Toto
  • 89,455
  • 62
  • 89
  • 125
  • this appears to not work with "4.80", "-80", ".04", in which case the regex should match the whole value and return blank / null unit. ".40" becomes = [".", "", ".", index: 0, input: ".40"] "4.80" becomes = ["4.", "4", ".", index: 0, input: "4.80"] – Norman Feb 09 '16 at 13:34