2

I have a calculation app that I am building, and I have it where the input displays comma's and the calculation can still run despite the commas, but now I cannot get the output to display with thousand separator commas. I have tried almost everything I can think of. Can someone show me where I may be off.

Here is my script:

    jQuery( document ).ready( function( $ ) {
            // SHOW OUTPUT DIV ONLY WHEN ALL FIELDS ARE COMPLETED
            $( '#calc-top' ).bind( 'keyup change', function() {
                var orderAmount = $( '#orderAmt' ).val().replace( '', ',' );
                if ( orderAmount !== "" && $( "#duration option:selected" ).val() !== "" && $( "#debitFreq option:selected" ).val() !== "" ) {
                    $( 'div#calc-bottom' ).css( 'display', 'block' );
                } else {
                    $( 'div#calc-bottom' ).css( 'display', 'none' );
                }
            } );
        } );

    jQuery(document).ready(function($){
        $("#orderAmt").keyup(function(event) {
            // skip for arrow keys
            if (event.which >= 37 && event.which <= 40) {
                event.preventDefault();
            }
            var $this = $(this);
            var num = $this.val().replace(/,/gi, "");
            var num2 = num.split(/(?=(?:[0-9]{3})+$)/).join(",");
            console.log(num2);
            // the following line has been simplified. Revision history contains original.
            $this.val(num2);
        });
        });
      // end jQuery

        // CALCULATE USER INPUT AND WRITE OUTPUT TO HTML ELEMENTS
        function calculate() {
            var orderAmt = parseFloat(document.getElementById( "orderAmt" ).value.replace(/,/g, ''));
            var duration = document.getElementById( "duration" ).value || 0;
            var debitFreq = document.getElementById( "debitFreq" ).value || 0;
            var outputAmt = document.getElementById( 'outputAmt' ) || 0;
            var numPayments = document.getElementById( 'numPayments' ) || 0;

            // CALCULATE NUMBER OF PAYMENTS
            if ( debitFreq == 7 ) {
                numPayments = Math.floor( duration / 7 );
            } else if ( debitFreq == 30 ) {
                numPayments = Math.floor( duration / 30 );
            }
            document.getElementById( 'numPayments' ).innerHTML = numPayments;

            // CALCULATE PAYMENT AMOUNT
            var stepA = (orderAmt / numPayments);
            var stepB = Math.floor( (((15 / 1000) * (duration / 360)) * 12) * orderAmt ) || 0;
            var stepC;
            if ( debitFreq == 7 ) {
                stepC = 0.10;
                //} else if (debitFreq == 30) {
                //stepC = 0.05;
            } else {
                stepC = 0;
            }
            var stepD = 0;
            //if ((duration == 30) && (debitFreq == 30)) {
            //stepD = 0.05;
            //} else {
            //stepD = 0;
            //}
            var stepE = stepC - stepD;
            var stepF = Math.floor( (((15 / 1000) * (duration / 360)) * 12) * orderAmt ) || 0;
            var stepG = Math.ceil( stepE * stepF );
            var stepH = stepB - stepG;
            var stepI = stepH / numPayments;
            var monthlyPayments = stepI + stepA;
            outputAmt.innerHTML = monthlyPayments.toFixed( 2 ) || 0;

            // OUTPUT WILL SHOW CORRECT DEBIT FORMATS BASED ON USER INPUT (i.e. 'week', 'weeks', 'month', 'months')
            var outputDefault1;
            if ( document.getElementById( "debitFreq" ).value == 7 ) {
                outputDefault1 = "week";
            } else if ( document.getElementById( "debitFreq" ).value == 30 ) {
                outputDefault1 = "month";
            }
            document.getElementById( "outputTerm1" ).innerHTML = outputDefault1;

            var outputDefault2;
            if ( document.getElementById( "debitFreq" ).value == 7 ) {
                outputDefault2 = "weeks";
            } else if ( document.getElementById( "debitFreq" ).value == 30 ) {
                outputDefault2 = "months";
            }
            document.getElementById( "outputTerm2" ).innerHTML = outputDefault2;

        }
        // end calculate function

        // ONLY ALLOW NUMERIC INPUT, NO ALPHA OR SPECIAL CHARACTERS EXCEPT COMMAS
        function isNumberKey( evt ) {
            var theEvent = evt || window.event;
            var key = theEvent.keyCode || theEvent.which;
            key = String.fromCharCode( key );
            var regex = /^[0-9.,]+$/;
            if ( !regex.test( key ) ) {
                theEvent.returnValue = false;
                if ( theEvent.preventDefault ) {
                    theEvent.preventDefault();
                }
            }
        }

        // TRIGGER EVENTS WHEN THE USER ENTERS DATA
        var userinputNum = document.getElementById( "orderAmt" );
        userinputNum.oninput = calculate;
        userinputNum.onkeypress = isNumberKey;

        var userinputDays = document.getElementById( "duration" );
        userinputDays.onchange = calculate;

        var userinputFreq = document.getElementById( "debitFreq" );
        userinputFreq.onchange = calculate;

Here is my fiddle: http://jsfiddle.net/qo5b7z93/

Any help is greatly appreciated!

Louys Patrice Bessette
  • 33,375
  • 6
  • 36
  • 64
AaronS
  • 131
  • 13
  • You could use http://numeraljs.com/, if you don't want to do that, then divide your result by 1000 and trunc this, then modulus the rest by 1000. something like Math.trunc(value/1000)+','+(value % 1000).toFixed(2) – Keith Sep 30 '16 at 21:21
  • You could also see this : http://plugins.jquery.com/df-number-format/ – Louys Patrice Bessette Sep 30 '16 at 21:58

3 Answers3

0

Try this:

Note: The below function is very verbose for readability/understandability purposes. You would probably want to simplify it for production

You would change outputAmt.innerHTML = monthlyPayments.toFixed( 2 ) || 0
-->outputAmt.innerHTML = placeCommas(monthlyPayments);

function placeCommas(number) {
  if (number !== null && number !== undefined) {
    number = number.toFixed(2);
    var splitNum = number.split(".");
    var num = splitNum[0];
    var decimals = splitNum[1];

    var numArr = num.split("").reverse();
    var commaArr = [];
    for (var i = 0; i < numArr.length; i++) {
      commaArr.push(numArr[i]);
      if (i !== numArr.length - 1 && i % 3 === 2) {
        commaArr.push(",");
      }
    }
    num = commaArr.reverse().join("");
    number = num + "." + decimals;
    return number;
  }
}
console.log(placeCommas(0));
console.log(placeCommas(10));
console.log(placeCommas(100));
console.log(placeCommas(1000));
console.log(placeCommas(10000));
console.log(placeCommas(100000));
console.log(placeCommas(1000000));
console.log(placeCommas(10000000));
console.log(placeCommas(100000000));
console.log(placeCommas(1000000000));
mhodges
  • 10,938
  • 2
  • 28
  • 46
0

Please have a look at this updated FIDDLE, I think this should do what you need.

function FormatNumber(nStr) {
    nStr += '';
    x = nStr.split('.');
    x1 = x[0];
    x2 = x.length > 1 ? '.' + x[1] : '';
    var pattern = /(\d+)(\d{3})/;
    while (pattern.test(x1)) {
        x1 = x1.replace(pattern, '$1' + ',' + '$2');
    }
    return x1 + x2;
}
Devnsyde
  • 1,297
  • 1
  • 13
  • 34
  • That worked perfectly! When I was testing previously to this, I was off on the var pattern. Thank you so much for the insight! – AaronS Nov 11 '16 at 16:11
0

It is not so user-friendly to block the use of arrow keys, or even any key for that matter. Your restrictions also remove the possibility to select text with shift-arrow, to remove input with backspace. And when they do move the cursor position with the mouse, as soon as they type, the cursor flips to the end. This is abnormal behaviour and will make users frustrated.

Let them type what they want, and just clean-up when they exit the input box. That is much more user-friendly.

So I would suggest to apply the number format only when the focus leaves the input field, and to remove all formatting as soon as focus enters again.

Here is also a regular expression replace to apply the formatting in one go:

$(this).val()
    .replace(/[^\d.]/gi, "") // clean-up
    .replace(/\B(\d{3})(?=(?:\d{3})*(?:\.|$))/g, ',$1'); // format

Here is the updated fiddle.

trincot
  • 317,000
  • 35
  • 244
  • 286