McKeene
McKeene

Reputation: 285

Revert event based on if statement in jQuery

I am trying to create a site where a user can choose tickets. There is two types of tickets; an adult admission ticket and a lunch ticket. There are some different conditions for the tickets.

  1. An admission ticket does not require a specific date and the user can therefore go straight to the checkout step.
  2. A lunch ticket requires a specific date, therefore the date step should show next if a lunch ticket is selected.
  3. A lunch ticket cannot be purchased without an admission ticket and an error should therefore be displayed.

I have two problems:

  1. If a user chooses a lunch ticket first the error message is displayed, which is correct. If the user then chooses an adult ticket also the date step is displayed, which is also correct. However, the error message is still displaying, which is wrong.
  2. If a user selects a number of tickets the next step is showing as it should, however if the user sets the number of tickets back to 0 the next step is still showing, but it should not.

My JSFiddle: https://jsfiddle.net/mckeene/ysybh7wk/12/

HTML

<p id="error">
  Please select admission tickets aswell
</p>
<div class="adult">
  <p>
    Adult
  </p>
  <div class="col-xs-2">
    <p id="price-adult" data-price="12.77">€ 12.77</p>
  </div>
  <div class="col-xs-2">
    <select class="tickets-selection form-control" value="0" name="ticket-select-adult" id="ticket-select-adult">
      <option value="0">0</option>
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
  </div>
  <div class="col-xs-3">
    <p id="adult-total" class="text-right">
      <span class="valuta">€</span>
      <span class="total"></span>
    </p>
  </div>
</div>
<br>
<br>
<div class="lunch">
  <p>
    Lunch
  </p>
  <div class="col-xs-2">
    <p id="price-lunch" data-price="10.76">€ 10.76</p>
  </div>
  <div class="col-xs-2">
    <select class="tickets-selection form-control" value="0" name="ticket-select-lunch" id="ticket-select-lunch">
      <option value="0">0</option>
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
  </div>
  <div class="col-xs-3">
    <p id="lunch-total" class="text-right">
      <span class="valuta">€</span>
      <span class="total"></span>
    </p>
  </div>
</div>
<br>
<br>
<div id="date">
  Date
</div>
<div id="checkout">
  Checkout
</div>

jQuery

$('#date').hide();
$('#checkout').hide();
$('#error').hide();

$(function() {
  var $adultTotal = $("#adult-total .total");
  var adultPrice = parseFloat($("#price-adult").data("price"));
  var $lunchTotal = $("#lunch-total .total");
  var lunchPrice = parseFloat($("#price-lunch").data("price"));
  var adultPriceTotal = 0;
  var lunchPriceTotal = 0;
  var adultTicketsFound = false;
  var lunchTicketsFound = false;

  // Fixes NaN and calculates the subtotal price for adult tickets
  $('#ticket-select-adult').change(function() {
    var adultTicketsCount = parseFloat(this.value, 10);
    adultPriceTotal = isNaN(adultTicketsCount) ?
      0 :
      (adultTicketsCount * adultPrice).toFixed(2);
    $adultTotal.text(adultPriceTotal);

    if (adultTicketsCount > 0) {
      adultTicketsFound = true;
    }

  });

  $('#ticket-select-lunch').change(function() {
    var lunchTicketsCount = parseInt(this.value, 10);
    lunchPriceTotal = isNaN(lunchTicketsCount) ?
      0 :
      (lunchTicketsCount * lunchPrice).toFixed(2);
    $lunchTotal.text(lunchPriceTotal);

    if (lunchTicketsCount > 0) {
      lunchTicketsFound = true;
    }
  });

  $("select").change(function() {
    if (lunchTicketsFound && !adultTicketsFound) {
      $('#checkout').hide('slow');
      $('#date').hide('slow');
      $('#error').show('slow');
    }

     else if (lunchTicketsFound) {
      $('#checkout').hide('slow');
      $('#date').show('slow');
    }

    else if (adultTicketsFound) {
      $('#checkout').show('slow');
      $('#error').hide('slow')
    }
  });
});

Upvotes: 3

Views: 98

Answers (1)

James Jensen
James Jensen

Reputation: 731

The problem is in the logic with the last change function. The code will never go to the last statement, because when both conditions lunchTicketsFound and adultTicketsFound are true, the second if statement is executed, because the test is only on lunchTicketsFound.

Having multiple code blocks fire on one event can sometimes confuse things because you have no control over the order of execution. I was able to rework your solution by converting the last JQuery change event definition into a vanilla function called verifyTicket. The code is shown below.

Also, I altered your code that assigns 'true' to the *ticketsFound variables. This takes care of the case when someone clicks everything in order and expected, but then changes one of the values back to '0'. Since the only place these variables are set to 'false' is during initialization, the original code failed to take into account multiple changes:

$('#date').hide();
$('#checkout').hide();
$('#error').hide();

$(function() {
  var $adultTotal = $("#adult-total .total");
  var adultPrice = parseFloat($("#price-adult").data("price"));
  var $lunchTotal = $("#lunch-total .total");
  var lunchPrice = parseFloat($("#price-lunch").data("price"));
  var adultPriceTotal = 0;
  var lunchPriceTotal = 0;
  var adultTicketsFound = false;
  var lunchTicketsFound = false;

  // Fixes NaN and calculates the subtotal price for adult tickets
  $('#ticket-select-adult').change(function() {
    var adultTicketsCount = parseFloat(this.value, 10);
    adultPriceTotal = isNaN(adultTicketsCount) ?
      0 :
      (adultTicketsCount * adultPrice).toFixed(2);
    $adultTotal.text(adultPriceTotal);

    // Notice that this is shorthand for its equivalent if-then-else statement
    adultTicketsFound = (adultTicketsCount > 0);

    validateTickets();
  });

  $('#ticket-select-lunch').change(function() {
    var lunchTicketsCount = parseInt(this.value, 10);
    lunchPriceTotal = isNaN(lunchTicketsCount) ?
      0 :
      (lunchTicketsCount * lunchPrice).toFixed(2);
    $lunchTotal.text(lunchPriceTotal);

    lunchTicketsFound = (lunchTicketsCount > 0);

    validateTickets();
  });

  // Changed the JQuery event into a vanilla function
  validateTickets = function() {
    if (lunchTicketsFound && !adultTicketsFound) {
      $('#checkout').hide('slow');
      $('#date').hide('slow');
      $('#error').show('slow');
    } else if (!lunchTicketsFound && adultTicketsFound) {
      $('#checkout').hide('slow');
      $('#date').show('slow');
    } else if (!lunchTicketsFound && !adultTicketsFound) {
      $("#checkout").hide("slow");
      $("#error").hide("slow");
      $("#date").hide("slow");
    } else {
      $('#checkout').show('slow');
      $('#error').hide('slow');
    }
  }
});

Upvotes: 4

Related Questions