Katie Reed
Katie Reed

Reputation: 107

jQuery - Radio Buttons - Variables - OnClick

I have a table of data on the right that starts out with certain values and is modified through the use of radio buttons and a slider on the left.

I would like the first radio button for the "pay in full" option to increase the estimated discount on the right by 6%. Once the estimated discount changes, I would like the "new amount" and "estimated savings" values to change as well since the estimated discount directly affects all of them.

I was able to update the percent correctly in the last jQuery paragraph but I think I have a problem with declaring "newPercent" as a local variable and not a global variable?

I also made a JSFiddle: https://jsfiddle.net/4K2R7/43/

Any help would be greatly appreciated!

HTML

<label><input type="radio" name="payment" value="6" id="hide" id="hide-2"> Pay the full amount*</label>
<p>
<label><input type="radio" name="payment" value="0" id="show"> Payment plan</label>

Javascript/jQuery

// Bill starting amount
var originalAmount = 1850;

// The amount taken off the bill based upon the starting discount
var discountAmount = originalAmount *.22;

// The new bill amount: the original bill amount minus the previous savings
var newAmount = originalAmount - discountAmount;

// Discount starting point
var discountPercent = 22;

// To display numbers with decimals
var displayedDiscount = discountPercent;
var displayedOriginalAmount = originalAmount.toFixed(2);
var displayedDiscountAmount = discountAmount.toFixed(2);
var displayedNewAmount = newAmount.toFixed(2);


$(document).ready(function(){
    $("#option").hide();
    $("#hide").click(function(){
        $("#option").hide();
    });
    $("#show").click(function(){
        $("#option").show();
    });
    $("#estimated-discount-div").html(displayedDiscount);
    $("#new-amount-div").html(displayedNewAmount);
    $("#savings-amount-div").html(displayedDiscountAmount);
});


$(document).ready(function(){
    $("input[name='payment']").click(function() {
        add = this.value;
        var newPercent = (+discountPercent) + (+add);
        $("#estimated-discount-div").html(newPercent);
        var discount = originalAmount * newPercent;
        var updateAmount = originalAmount - discount;
        $("#new-amount-div").html(updateAmount);
    });
});

enter image description here

Upvotes: 0

Views: 1034

Answers (1)

Oka
Oka

Reputation: 26345

One of the biggest issues with your code right now is that it is hard to read. You should strive to write code as legibly as possible, so that when errors do occur you know where to look, and you can understand the parts more clearly. Breaking things up into separate functions is one of the easiest ways to split your logic up, so it is less condensed and more reusable.

The main issue is math related. You're over complicating things by using an additive bonus, instead of just a flat discount rate and adjusting properly for the percentage multiplier. Coupled with strange signing this leads to wild results.

Let's refactor this into something cleaner, and easier on the eyes. There is one semi-advanced JS technique in this example, but everything else is basic.

DEMO

JS:

var paymentInfo = (function () {
  var original = 1850,
      basePercent = 22;

  return (function (percent) {
    percent = percent || basePercent;

    var discount = original * (percent / 100),
        current = original - discount;

    return {
      original: original,
      percent: percent,
      discount: discount,
      current: current
    };
  });
}());


function setInfo(info) {
  $('.original').text(info.original.toFixed(2));
  $('.percent').text(info.percent);
  $('.savings').text(info.discount.toFixed(2));
  $('.amount').text(info.current.toFixed(2));
}

$('input[name="payment"]').on('change', function () {
  var val = $(this).val(),
      info = paymentInfo(parseInt(val));

  setInfo(info);
});

setInfo(paymentInfo());

HTML:

<div>
  <label>
    <input type="radio" name="payment" value="22" checked />
    Base
  </label>
  <label>
    <input type="radio" name="payment" value="28" />
    Full
  </label>

  <div>
    Original: $<span class="original"></span>
  </div>

  <div>
    Discount: <span class="percent"></span>%
  </div>

  <div>
    Savings: $<span class="savings"></span>
  </div>

  <div>
    Price: $<span class="amount"></span>
  </div>
</div>

In this example we use a flat value from either radio button, instead of trying to add our extra discount on top of the existing one.

So now you ask, what's up with the function returning a function? That's an IIFE. This pattern allows us to encapsulate some variables that don't need to change, and don't need to be outside the scope of the function. We immediately invoke that function, create those variables, and return a function that now has access to those variables.

Without the IIFE we would write it like this

var original = 1850,
    basePercent = 22;

var paymentInfo = function (percent) {
  percent = percent || basePercent;

  var discount = original * (percent / 100),
      current = original - discount;

  return {
    original: original,
    percent: percent,
    discount: discount,
    current: current
  };
};

but that's less fun! (Also leaves our variables out in the cold, cold global scope.)

The actual return value from paymentInfo function is an object containing our appropriate properties. You can see how we access those properties inside the setInfo function.

Expanding on your discounts is now as simple as adding new radio buttons, with the discount percentage inside the value attribute.

Hopefully this helps as a crash course into writing more maintainable code. If you need some reading material, here are a few articles on the topics involved:

Upvotes: 2

Related Questions