4

When i write a jQuery plugin i like to specify options for spacings the CSS way. I wrote a function that returns a CSS String as values in a object.

5px 10px returns top: 5px, right: 10px, bottom: 5px, left: 10px

Now i often use the returned values to do some calculations and its not very nice to have to extract the measuring unit every time...

I suck in writing regular expressions could someone help me complete this function:

this.cssMeasure = function(cssString, separateUnits){

    if ( cssString ){
        var values = {}
    }else{
        return errorMsg
    }

    var spacing = cssString.split(' ')
    var errorMsg = 'please format your css values correctly dude'

    if( spacing[4] ) {
        return errorMsg
    } else if ( spacing[3] ) {
        values = {top: spacing[0], right:spacing[1], bottom:spacing[2], left:spacing[3]}
    } else if ( spacing[2] ) {
        values = {top: spacing[0], right:spacing[1], bottom:spacing[2], left:spacing[1]} 
    } else if ( spacing[1] ) {
        values = {top: spacing[0], right:spacing[1], bottom:spacing[0], left:spacing[1]}
    } else {
        values = {top: spacing[0], right:spacing[0], bottom:spacing[0], left:spacing[0]}
    }

    if (separateUnits) {
        $.each(values, function(i, value){
            /*
             at this place i need to extract the measuring unit of each value and return them separately
             something like top: {value: 10, unit: 'px'}, right: {bla} and so on
            */
        })
    }

    return values

}

if you have any idea how to improve this function i am open to your comments.

1
  • 1
    Note that giving three values (e.g. "10px 5px 7px") is perfectly valid; the 1st value is for the top, the 2nd is for the left & right, the 3rd for the bottom. Commented Apr 19, 2010 at 23:01

2 Answers 2

8

According to http://www.w3.org/TR/css3-values/#ltnumbergt , "A number can either be an integer, or it can be zero or more digits followed by a dot (.) followed by one or more digits", in regexp language

\d+|\d*\.\d+

Let's add an optional sign to it, and make the group "non-capturing" to make the parsing simpler

([+-]?(?:\d+|\d*\.\d+))

Enumerating all possible units is tedious, therefore let the unit be any sequence of lowercase letters (including none) or a percent sign

([a-z]*|%)

Putting it all together,

propRe = /^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/

When you apply this to a value

  parts = "+12.34em".match(propRe)

the numeric value will be in parts[1] and the unit in parts[2]

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

Comments

2
switch (spacing.length) {
case 1:
    values = {top: spacing[0], right:spacing[0], bottom:spacing[0], left:spacing[0]};
    break;
case 2:
    values = {top: spacing[0], right:spacing[1], bottom:spacing[0], left:spacing[1]};
    break;
case 3:
    values = {top: spacing[0], right:spacing[1], bottom:spacing[2], left:spacing[1]};
    break;
case 4:
    values = {top: spacing[0], right:spacing[1], bottom:spacing[2], left:spacing[3]};
    break;
default:
    return errorMsg;
}

if (separateUnits) {
    values = $.map(values, function(i, value){
        matches = value.match(/([-+]?[\d.]*)(.*)/);
        return {value: matches[1]+0, 
                unit: matches[2] ? matches[2] : 'px'};
    })
}

2 Comments

the case solution is definitely better. But what if the unit is not px but em or %? And what is the "?" doing (matches[2] ? matches[2])
The unit group (.*) will match any characters. In particular, the first group will match all the digits and the remaining characters will be the unit. The ? isn't alone; it's part of the lone ternary operator, ?:. It's like an 'if-else', but as an expression rather than a statement. It ensures that the value has valid units; if no units were specified, the units default to 'px'. Search SO for "ternary" for more information.

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.