Home > Enterprise >  How to change active tab back to not active after validation failure in JavaScript
How to change active tab back to not active after validation failure in JavaScript

Time:10-09

I have a Details tab with a dropdown that swaps forms in and out and a Result tab that displays the result in a graph. When the user selects "Result" I want to validate the data entry before going to the result tab.
What happens is that when the Result tab is clicked it becomes active and changes color. I then goes into script.js displayResultContent() which validates the data entry. If the data is not valid I don't want to proceed to the result tab so I only show the result if the data is okay.
The issue I have is that if the data is invalid, error messages are displayed on the form, but the Result tab remains displayed with the active color instead of changing to the non active color. Once the user clicks the mouse on the screen the tab changes color.
Is there any way to make this tab change to the non active color without having to click on the screen? I haven't yet put the media queries in so this looks best on a wide screen, otherwise the tabs are displayed below each other instead of beside. It still works though.

const DATE_TYPE_PAST = 0;
const DATE_TYPE_FUTURE = 1;
const SUCCESS = 0;
const ERROR = 1;

$(function() {
  $('#details-tab').click(displayDetails);
  $('#result-tab').click(displayResultContent);
  $("#your-details-tab").click(displayYourDetailsTab);
  $("#your-superannuation-tab").click(displayYourSuperannuationTab);
});

function displayYourDetailsTab() {
  removeAllForms();
  var form = $("#your-details-form");
  form.show();
  $('#details-tab').html("Your Details");
}

function displayYourSuperannuationTab() {
  removeAllForms();
  var form = document.getElementById("your-superannuation-form");
  form.style.display = 'block';
  $('#details-tab').html("Your Superannuation");
}

function removeAllForms() {
  var forms = document.getElementsByTagName('form');
  for (var i = 0; i < forms.length; i  ) {
    forms[i].style.display = "none";
  }
}

function displayDetails() {
  $('#details').show();
  $('#result').hide();
  $('#result-tab').removeClass('active');
  $('#details-tab').addClass('active');
}

function displayResultContent() {
  // FIRST CHECK DATA ENTRY
  const dateResult = checkDate(document.getElementById("date-of-birth"), DATE_TYPE_PAST);
  const rentResult = checkMandatoryWholeNumber(document.getElementById("fortnightly-rent"), "Fortnightly rent ", 0, 999);
  
  if (dateResult === SUCCESS && rentResult === SUCCESS) {
    $('#result').show();
    $('#details').hide();
    $('#result-tab').addClass('active');
    $('#details-tab').removeClass('active');
  }else {
    $('#result-tab').removeClass('active');
  }
}

const showError = (input, message) => {
    // get the form-field element
    let formField = input.closest(".form-field");

    // add the error class
    formField.classList.remove('success');
    formField.classList.add('error');

    // show the error message
    const error = formField.querySelector('small');
    error.textContent = message;
};

const showSuccess = (input) => {
    // get the form-field element
    let formField = input.closest(".form-field");

    // remove the error class
    formField.classList.remove('error');
    formField.classList.add('success');

    // hide the error message
    const error = formField.querySelector('small');
    error.textContent = '';
};

const yourDetailsForm = document.getElementById("your-details-form");
if (yourDetailsForm != null) {
    yourDetailsForm.addEventListener('input', function(e) {
        switch (e.target.id) {
            case 'date-of-birth':
                 checkDate(document.getElementById(e.target.id), DATE_TYPE_PAST);
                break;
            case 'fortnightly-rent':
                checkMandatoryWholeNumber(document.getElementById(e.target.id), "Fortnightly rent ", 0, 999);
                break;
        }
    });
}


const isRequired = value => value !== '';

const isValidDate = function(date) {
    return (date !== "Invalid Date") && date !== ("Nan");
}

function checkDate(dateElement, dateType) {
    const val = dateElement.value;
    const newDate = new Date(val);
    if (isValidDate(newDate)) {
        const today = new Date();
        today.setHours(0,0,0,0);
        if (dateType === DATE_TYPE_PAST) {
            if (newDate < today) {
                // okay
                showSuccess(dateElement);
        return SUCCESS;
            }else {
                // error
                showError(dateElement, "date must be in the past");
        return ERROR;
            }
        } if (dateType === DATE_TYPE_FUTURE) {
            if (newDate >= today) {
                // okay
                showSuccess(dateElement);
        return SUCCESS;
            }else {
                // error
                showError(dateElement, "date must be in the future");
        return ERROR;
            }
        }
    }else {
        showError(dateElement, "date is mandatory");
    return ERROR;
    }
}

$(document).on("keydown", ".whole-number", function (e) {
    const invalidChars = [
        "-",
        " ",
        "e",
        ".",
    ];
    if (invalidChars.includes(e.key)) {
        e.preventDefault();
    }
});

function checkMandatoryWholeNumber(element, prefix, min, max) {

    if (!isRequired(element.value)) {
        showError(element, prefix   " is mandatory");
        return ERROR;
    }
    const val = parseInt(element.value);
    if (val < min || val > max) {
        showError(element, prefix   " must be between "   min   " and "   max);
        return ERROR;
    }
    showSuccess(element);
  return SUCCESS;
}
html, body {
  height: 100%;
  margin: 0;
  overflow:hidden;
}

.content {
  height:100%;
  margin-left: 15%;
  margin-right: 15%;
  display:flex;
  flex-flow: column;
}

.content .result-content {
  background-color: #FFF;
  flex: 1 1 auto;
  margin-left:1%;
  margin-right:1%;
  display: none;  
}

#tabs {
  width: 70%;
  margin: 0 auto;
  padding: 0;
  border-bottom: 7px solid #FE6D73;
  margin-top: 50px; 
}

.form-container {
  width: 70%; 
  height: 98%;
  background-color: #FFF;
  margin: 0 auto;
  overflow-y: auto;
  overflow-x: hidden;
  padding-bottom: 7px;
  box-sizing: border-box;
  padding-top: 0px;
}


li {
  list-style: none;
}

/*******************************************************************/
/*             NAV TABS                                            */
/******************************************************************/

.nav-link {
  border-radius: 15px 15px 0px 0px !important;
  text-decoration: none;
  height: 40px;
  font-size: 80%;
  background-color: #eeeeee !important;
  color: #aaaaaa;
}

.nav-link.active,
.nav-link:active,
.nav-link:hover,
.nav-link:focus {
  border-radius: 15px 15px 0px 0px !important;
  background-color: #FE6D73 !important;
  color: #FEF9EF !important;
}

.nav-link-left {
  width: 255px; 
}
.nav-link-right {
  width: 100px;
}

.nav-tabs>li>ul>li>a {
  width: 200px;
}

.dropdown-menu {
  z-index: 999999;
}

.nav-tabs>li>ul {
  background-color: #FE6D73 !important;
}

/* Remove border from tabs */
.nav-tabs .nav-link {
  border: 0px solid transparent;
}

/* This is the dropdown link */
.dropdown-item {
  background-color: #FE6D73 !important;
  color: #FEF9EF !important;
}

/* Border at bottom of each item in the drop down list */
.dropdown-menu>li {
  border-bottom: 1px solid #FEF9EF !important;
}

.nav-tabs>li>ul>li.active>a, .nav-tabs>li>ul>li.active>a:focus, .nav-tabs>li>ul>li>a:hover { 
  background-color: #FEF9EF !important;
  color: #FE6D73 !important;
}

.dropdown-menu {
   border-top: 1px solid #FEF9EF;   
}

/*******************************************************************/
/*           FORMS                                                */
/******************************************************************/
input[type="number"] {
  /*80px*/
  width: 5em;
  font-size: 80%;
}

input[type="date"] {
  border: 1px solid #cccccc;
}

input {
  border: 1px solid #cccccc;
}

#your-superannuation-form {
  display: none;
}
form {
  margin-top: 20px;
  background-color: beige;
}
.form-group {
  margin-top: 20px;
}
.disabled-link {
  cursor: not-allowed;
  opacity: 0.5;
}
.disabled-text {
  opacity: 0.5;
}
.enabled-text {
  opacity: 1.0;
}
.enabled-link {
  cursor: pointer;
  opacity: 1.0;
}
.pointer-not-allowed{
  cursor: not-allowed;
}
.pointer-allowed {
  cursor: pointer;
}

form label {
  font-family:  'opensansreg', 'Verdana', 'Arial';
}

.form-text {
  font-family: Georgia;
  align-self: start;
 }

 .button-text {
  font-family: Georgia;
  font-size:80%;
 }

 .input-text {
  font-family: Consolas, Lucida Console, monospace;
 } 

 :root {
  --error-color: #dc3545;
  --success-color: #cccccc;
  --warning-color: #ffc107;
}
.form-field input:focus {
  outline: none;
}

.form-field.error input {
  /* border-color: var(--error-color); */
  border: 1px solid #dc3545;
}

.form-field.success input {
  /* border-color: var(--success-color); */
  border: 1px solid #cccccc;
}

.form-field small {
  color: var(--error-color);
  font-size: 70%;
  display: block;
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
  <link rel="stylesheet" href="style.css"/>
</head>
<body>

  <div id="tabs">
    <ul >
     <li >
        <a  id="details-tab" data-bs-toggle="dropdown" href="#" role="button" aria-expanded="false">Details</a>
       <ul >
         <li><a  id="your-details-tab" href="#">Your Details</a></li>
         <li><a  id="your-superannuation-tab" href="#">Your Superannuation</a></li>
        </ul>
      </li>
      <li >
        <a  id="result-tab" href="#" tabindex="-1">Result</a>
      </li>
    </ul>
  </div>

  <div >

  <div  id="details">
  
    <form id="your-details-form">
      <div >
        <label for="date-of-birth" >Date of Birth</label>
        <div >
            <input type="date"  id="date-of-birth" name="date-of-birth">
            <small></small>
          </div>
      </div>

      <div >
        <label for="fortnightly-rent" >Fortnightly Rent</label>
        <div >
            <input type="text"  size="4" id="fortnightly-rent" name="fortnightly-rent"
            onKeyDown="if (this.value.length == 4) this.value = this.value.slice(0, -1);"/>
            <small></small>
          </div>
      </div>
    </form>

    <form id="your-superannuation-form">
      THIS IS YOUR SUPERANNUATION FORM
    </form>

  </div> <!-- end form-container-->

  <div  id="result">
    THIS IS THE RESULT
 </div> 

</div>
  
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.min.js"></script>
<script type="text/javascript" src="script.js"></script>

</body>
</html>

CodePudding user response:

Please remove the .nav-link:focus selector from this declaration

.nav-link.active,
.nav-link:active,
.nav-link:hover{
  border-radius: 15px 15px 0px 0px !important;
  background-color: #FE6D73 !important;
  color: #FEF9EF !important;
 }

Currently when you click on a tab the focus remains and it goes only after clicking away

.nav-link.active,
.nav-link:active,
.nav-link:hover,
.nav-link:focus  <---- It works properly after removing this
 { 
 border-radius: 15px 15px 0px 0px !important;
 background-color: #FE6D73 !important;
 color: #FEF9EF !important;
 }
  • Related