2

I need convert "100% - 1" to 300 - 1 where 300 - canvas width? How to eval (batch) this operation?

//for example:
var value = batch("100% - 1", canvas.width); //Must 299, because canvas.width is 300
var secondary = batch("50% + 10", canvas.width); //Must 160
//where first argument - arithmetic operation, second - relativity value.

This question is not from the scope of science fiction, but a very serious and real issue.

Update! But if need just convert percentage?

var value = hack("75%", 300); //Must 255
var operation = hack("30%", 100) + 10; //Must 40
var end = hack("1em", somearg); //EM?

Update2! What a will, if i use new Function("a", "b", "return (%%Expression%%)") instead of eval?

For example:

var operation = "90% - 10";

To:

new Function("a", "return ((a * 90 / 100) - 10)");

How to made it?

1
  • 2
    Why don't you just use var anything = (canvas.width * (percent / 100)) + somenumber; ? Commented Dec 24, 2012 at 12:27

4 Answers 4

2

If you have two parts in the batch and the first is always a percentage and second a value then you could do

function batch(operation, value){
    var values = operation.match(/\d+|[+-/*]/g),
        percent = parseFloat(values[0])/100,
        relative = parseFloat(values[2]),
        math = values[1],
        applied = percent*value;

     switch(math){
         case '+': return applied + relative; 
         case '-': return applied - relative;
         case '/': return applied / relative;
         case '*': return applied * relative;
     }
}
Sign up to request clarification or add additional context in comments.

Comments

1

you can use a replace and simple mat rule,

what 100% of width actually is (100 / 100 * width) so you can do following.

function batch(calcStr, objWidth)
{
calcStr = calcStr.replace("%", "/100*" + objWidth);
var newWidth = eval(calcStr); 
// The + 10 or -1 are already there...
}

Comments

0

For example,

expr = expr.replace(/(\d+)%/g, function($0, $1) { return width * parseInt($1) / 100 })
result = eval(expr)

If your expressions are always if form xxx% + yyy you can also get along without eval:

expr = expr.replace(/(\d+)%/g, function($0, $1) { return width * parseInt($1) / 100 })
result = expr.replace(/(\d+)\s*([+-*/])\s*(\d+)/g, function($0, $1, $2, $3) { 
    $1 = parseInt($1);
    $3 = parseInt($3);
    switch($2) {
        case '+': return $1 + $2;
        etc.....

Comments

0

If you really want to compute that, you can use a regular expression to search for all occurences of a number followed by a percent sign:

expression = "30% + 10";
m = /(\d+)%/.exec( expression );

this will give you the whole match (30%) as m[0] and just the numbers (30) as m1.

You can use this to calculate the new value

v = width_100_percent * parseInt(m[1]) / 100;

and then replace it for real, and eval the resulting mathemtatical expression.

See this jsfiddle for a working example.

But!

Evaling and expression that might have been user input at some point opens up the whole subject of security ... so you shouls think really, really, really hard about how to avoid this situation.

My Guess

You are going to all this trouble because you want to do some calculation for CSS layouts. So here are my to suggestions of how you might avoid the calculation:

1) box-sizing: border-box

the classical box model makes it practically impossible to do stuff like "split this div into three equal columns with borders of 1px each".

look into the new "border-box" which make this really simple: with border-box the padding + border count as part of the width, so

  width: 30%
  border: 1px;

actually adds up to 100%.

See Paul Irish's article for a more detailed explanation.

2) CSS preprocessors like SASS or LESS

if you want to do computations in your CSS you can use a preprocessor to do that for you. Both SASS and LESS support variables and mathematical expression, with a slight difference in syntax:

  padding: $x / 2;

  padding: (@x / 2);

So there you are: one way to implement what you wanted, and two ways to avoid it.

Comments

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.