wetjosh
wetjosh

Reputation: 6398

How to prevent values from rounding to zero javascript

I have two buttons, one that makes divs (of varying sizes) larger by a factor of 10 and one that makes them smaller by a factor of 10. After two clicks of the button that makes them smaller, the div is rounded to zero. No matter how many times you click the button that makes it larger it won't get larger because its multiplying the zero value. What is the standard way to fix this? This is necessary because in my application some of the divs are much much bigger than others, so while one div will be less than a pixel wide (and would then rightfully be invisible) others will be thousands of pixels wide.

UPDATE: My divs are actually circles representing planet diameters. I need these to be exact! If I click the smaller button 5 times, I want to be able to click the larger button 5 times and have it return to the exact diameter it was initially.

Also, it is probably not necessary to be able to make the divs smaller or larger an infinite number of times. What is the standard way to put a limit on it? Refer to my jsfiddle for an example of what I am trying to achieve. http://jsfiddle.net/dfjosh/vtxeD/12/

HTML

<a href="javascript:;" class="smaller">smaller</a>
<a href="javascript:;" class="larger">larger</a>
<div></div>

CSS

div {
    width: 50px;
    height: 50px;
    background: cornflowerblue;
}

JavaScript

$('a').click(function() {
    if($(this).hasClass('smaller')) {
        var element = $('div');
        element.animate({
            'width' : element.width() * 0.1,
            'height' : element.height() * 0.1
        });
    } else if($(this).hasClass('larger')) {
        var element = $('div');
        element.animate({
            'width' : element.width() * 10,
            'height' : element.height() * 10
        });
    }
});

Upvotes: 2

Views: 166

Answers (7)

wetjosh
wetjosh

Reputation: 6398

Well, as it turns out, I am going to answer my own question. I appreciate all the help I received. I am certain the reason I didn't find an answer from you guys is because I didn't phrase the question right and I didn't give enough detail. Anyway, this is the solution to my problem:

I was originally scaling all my divs down by a factor of 1000 in css. That means, the div that (when scaled up) should have been 4879.4 px wide, I assigned a value of 4 in the css. Right away it lost 4 significant figures. What I ended up doing was storing the real (100% to scale) value in a javascript variable. That way, when I want to scale it, it uses the full value with all the significant digits. I can scale as far as I want down and up. And if I scale the 4px wide div down by a factor of 10, it rightfully dissapears, but comes right back when I scale back up.

Again, sorry I did such a bad job of asking the question. But I hope this answer helps anyone else wondering about this.

Upvotes: 0

itmitica
itmitica

Reputation: 511

You simply need to check if width has gone under 1 when making the div smaller. Add a restriction for height too if you want ratio preservation.

I'm adding another solution here.

And you won't be able to have exact return values using floats: 0.1. Since you're using decimal numbers, browsers treat rounding differently. For example, IE will only use a precision of tow decimals in CSS for JS calculated floats. Other browsers will use three decimals, but they will decide if the result will be used as is or altered, e.g. FF may turn a computed 13.205 into a used 13.207.

Best if you'll decide upon fixed hardcoded ranges for yourself. Or memorize new calculated widths and heights as you go and apply them when you go back. I imagine this would involve building two arrays, one for smaller, one for larger. Otherwise turn to canvas or svg.

Upvotes: 1

Travis J
Travis J

Reputation: 82267

jsFiddle Demo

One way to prevent it from reaching 0 is to adjust the height and width, check for 0, and then re-adjust back to a cached value if it does go to 0.

var w = element.width();
element.width(w*0.1);
var testWidth = element.width();
element.width(w);

if(testWidth == 0)return;

var h = element.height();
element.height(h*0.1);
var testHeight = element.height();
element.height(h);

if(testHeight == 0)return;

Upvotes: 0

Markus
Markus

Reputation: 202

Just do a check if it is still in some reasonable border, maybe like this:

'width' : ( element.width() > 0.1 ? element.width() * 0.1 : element.width() )
'height' : ( element.height() > 0.1 ? element.height() * 0.1 : element.height() )

This way it can actually get very small. But you should ask yourself which display is capable of displaying a pixel of a size of 0.25? At least one can assume that Apple's retina displays will be able to display a 0.5 pixel.

Upvotes: 0

razz
razz

Reputation: 10110

i think this is what you are looking for:

var element = $('div');
element.animate({
    'width' : Math.max(element.width() * 10), 50),
    'height' : Math.max(element.width() * 10), 50)
});

Upvotes: 0

David Thomas
David Thomas

Reputation: 253308

Given that 0 evaluates as 'falsey' (or false-ish), you can use an || operator to pass 1 in the event that the width() or height() returns 0:

var element = $('div');
element.animate({
    'width' : (element.width() || 1) * 10,
    'height' : (element.height() || 1) * 10
});

JS Fiddle demo.

Upvotes: 6

T.J. Crowder
T.J. Crowder

Reputation: 1074088

It seems to me that the problem isn't so much the divs going to zero as getting them to come away from it again.

That's easily done:

'width' : (element.width() * 10) || 1

How that works: If element.width() returns 0, of course 0 * 10 is also 0. 0 is a falsey value, so the || uses 1 instead.

Or if you prefer:

'width' : (element.width() || 1) * 10

...which just kicks in more quickly. :-)

More: JavaScript's Curiously Powerful OR Operator (||)

Upvotes: 2

Related Questions