1

I'm trying to make a sub-total calculation tool, but I can't continue because I don't know what the problem is. When the form is submitted, or the button is clicked, everything quickly disappears.

Here's the fiddle :: http://jsfiddle.net/xFmBK/

I'm clueless...

    function calcSub(){

        var input = document.getElementById('fld'),
            subTotal = document.getElementById('sub-total'),
            tax = document.getElementById('tax'),
            total = document.getElementById('total');

        var subTotalCalc = input.value / 1.06;

        var flag = true;


        if(input.value == "" || input.value == null){
            alert("Please enter in a total!");
            return false;
        } else {
            subTotal.innerHTML = "Subtotal:" + " " + "$" + subTotalCalc;
            tax.innerHTML = "Tax:" + " " + "$" + input.value - subTotalCalc;
            total.innerHTML = input.value;
            return flag;
        }

    }
Matthew
  • 2,158
  • 7
  • 30
  • 52

5 Answers5

3

That happens because your submit button actually does a form submit on some action and page is being refreshed. There are some ways to fix behavior, such as:

make your submit button just a button: <input type="button"> actually doesn't seem you need a form there

or add return false to onClick handler:

<button type="submit" onclick="calcSub(); return false;">Calculate</button><br>
Sergio
  • 6,900
  • 5
  • 31
  • 55
  • Thank you so much Sergio. Now I know why the page reloads. I thought adding "onclick="return calcSub();" would of done it. Guess not, haha. – Matthew Aug 08 '13 at 07:07
  • @MattKnowsTech Just to clarify: callind function doesn't abandon native behavior, `return false` does :D – Sergio Aug 08 '13 at 07:10
  • @Sergio if the function returns a `false` then the event will stop propogating, the OP is returning `true` –  Aug 08 '13 at 07:14
  • @rps: The event _will not stop propagating!_ That's only if a jQ event callback returs false to the actual event handler. – Elias Van Ootegem Aug 08 '13 at 07:50
1

Be aware of another issue: You have to use parentheses around (input.value - subTotalCalc). Without parentheses, you're trying to add and subtract strings, which results in NaN.

tax.innerHTML = "Tax:" + " " + "$" + (input.value - subTotalCalc);`
tb11
  • 3,056
  • 21
  • 29
  • @MattKnowsTech: Also be weary of the _floating-point percission issue_, you're deviding by `1.06`, which'll return a float. By any means, floats are a pain in a binary system. Check my answer for a way to fix this (second fiddle, last snippet is the code you're after) – Elias Van Ootegem Aug 08 '13 at 07:52
1

Your form is getting submitted when you click on the button, so the values are getting calculated but are disappearing immediately as the page is re-loaded.

Try adding onsubmit='return false;' to your form tag and the page re-load will be prevented.

Alternately you can change the button type to button.

Check this fiddle.

Harry
  • 87,580
  • 25
  • 202
  • 214
0

You need to prevent the form from being submitted. The form might be submitted by the user pressing enter when the form element is in focus, or by clicking the submit button. Even if the onclick event returns false, the submit event isn't altered.
I've taken the liberty of forking your fiddle:

Check the demo

window.addEventListener('load',function()
{
    var input = document.getElementById('fld'),
        subTotal = document.getElementById('sub-total'),
        tax = document.getElementById('tax'),
        total = document.getElementById('total'),
        subTotalCalc;
    document.getElementById('calcForm').addEventListener('submit',function(e)
    {
        e = e || window.event;
        e.preventDefault();//prevent form's default behaviour
        e.stopPropagation();//if submit was sent by clicking submit button, stop the event here
        if (input.value === '' || input.value != +(input.value))
        {
            alert('Please enter valid subtotal (numeric)');
            return;
        }
        subTotalCalc = input.value / 1.06;
        subTotal.innerHTML = "Subtotal:" + " " + "$" + subTotalCalc;
        tax.innerHTML = "Tax:" + " " + "$" + (input.value - subTotalCalc);
        total.innerHTML = input.value;
    },false)
},false);

I'd be happy to explain the code further if needs be...
Note that this doesn't fix the issue JS has with floating-point precision, if you're thinking about asking a follow-up question on that matter, check this fiddle first! I've added a simple toDecimal function here:

var toDecimal = function(num, precision)
{
    precision = precision || 2;
    num = +(num || 0);
    return ( Math.round(num*Math.pow(10, precision))
             / Math.pow(10,precision)
           ).toFixed(precision);
};

So first multiply by 10^n, round and divide to 10^n again to get the desired float. To avoid any issues that might occur still (though there shouldn't be any AFAIKT, I've added a toFixed(n) call, too. This might be useful in case the rounded number is 213.00

Community
  • 1
  • 1
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
0

Just remove all the return from your code and add return false at the end

  • `return false` is bad practice IMO. In jQuery `return false` works, but in VanillaJS, it prevents the default, but doesn't stop the event from bubbling!! Not enough people realize this, because they don't understand the distinct phases an event object goes through. Please _learn about the event models_ – Elias Van Ootegem Aug 08 '13 at 07:49
  • @EliasVanOotegem okay I have read [this](http://stackoverflow.com/questions/1357118/event-preventdefault-vs-return-false) and understood, but then what does `return false` equals?`event.preventDefault()`? because the form doesn't submit on returning `false`. so, everytime I want to cancel an even from happening the best bet is on `event.stopPropogation`?! –  Aug 08 '13 at 08:51
  • 1
    `return false` is the same as calling `preventDefault`, yes. The event object's state is changed, the default behaviour is prevented. The object propagates/bubbles through the DOM, and, if an event handler would be attached to the form element, that handler will be called, too. That's not always desirable (when delegating the event, for example). Other handlers might change the state of the event object back to its default behaviour. That's why you stop the event from propagating, too. Your best bet, therefore is to call both methods – Elias Van Ootegem Aug 08 '13 at 09:01
  • @EliasVanOotegem ahem.. understood.. But that is your answer? I skipped it at first dues to it's length ^_^ –  Aug 08 '13 at 09:51
  • rps: Thanks... just my luck, [here, I was told I was incomplete](http://stackoverflow.com/questions/18120976/what-should-be-the-correct-signature-of-the-given-method/18121014#18121014), and when I try to type up a comprehensive answer, that also points out various other possible issues, add 2 fiddles and fully copy-pastable code, it doesn't get read, because it's too long... ah well, life's a bitch – Elias Van Ootegem Aug 08 '13 at 09:57
  • @EliasVanOotegem That's a given! but hey I don't blame the fiddles! –  Aug 08 '13 at 10:04
  • I'm not blaming the fiddles... just saying that, if you take the time to add 2 fiddles, format and test 2 snippets of code so the OP can just copy-paste them and carry on, _and_ explain every bit of the code, your answer doesn't get read because it's too long, while at the same time, it's too long because you've put all that effort in, but I'm nagging like an old lady, so I'm going for lunch now. thanks for the upvote :) – Elias Van Ootegem Aug 08 '13 at 10:24