What is the best approach for handling nested conditional statements?

I have a complex set of nested conditional checks that I am working on refining to avoid getting stuck in a nested if{}else{} loop. To provide context, I am dealing with two objects, CACHE_FILE_AGE_LIMIT and CACHE_FILE_CURRENT_AGE, and I am trying to navigate through a nested age comparison structure:

first check the days,
    then check hours,
       then check minutes,
           then check seconds

The objective is to progressively move from one time unit to the next, such as days to hours, and stop once a greater value is encountered. For instance, if the day values are equal, we move on to comparing hours, and if an hour value surpasses the limit, we terminate the evaluation.

For a clearer understanding, please refer to the provided example.

const CACHE_FILE_AGE_LIMIT = {
  days: 3,
  hours: 6,
  minutes: 15,
  seconds: 57
}

const CACHE_FILE_CURRENT_AGE = {
  days: 3,
  hours: 5,
  minutes: 14,
  seconds: 57
}

// Function to calculate time difference
function timeDiff(ageObj1, ageObj2) {
  // Inserted logic for comparison...
}

// Additional code for populating and evaluating limits
// Please refer to the actual example for more details

As illustrated, the evaluation process ceases once it is determined that the age can be discerned based purely on the hours.

Feel free to modify the values in CACHE_FILE_CURRENT_AGE to experiment with different scenarios.

--- UPDATE ---

Appreciation to all those who offered solutions. I will need to select one answer to mark the question as resolved.

Check out the demo of the solution here:

https://i.sstatic.net/HkNuS.gif

Answer №1

To optimize the handling of properties in a time-like object, consider using a UNITS array with the text representation of each property. Then, iterate over this array with a while loop to sequentially update each DOM element.

const CACHE_FILE_AGE_LIMIT = {
  days: 3,
  hours: 6,
  minutes: 15,
  seconds: 57
}, CACHE_FILE_CURRENT_AGE = {
  days: 3,
  hours: 5,
  minutes: 17, 
  seconds: 57
  
}, UNITS = ["days", "hours","minutes","seconds"]

function timeDiff(ageObj1, ageObj2) {
  let unitsIndex = 0;
  
  while(unitsIndex <= UNITS.length){
    currentEl = document.getElementById(`current_${UNITS[unitsIndex]}`),
    limitEl = document.getElementById(`limit_${UNITS[unitsIndex]}`);

    console.log(UNITS[unitsIndex],ageObj1[UNITS[unitsIndex]],ageObj2[UNITS[unitsIndex]]) 
    currentEl.innerHTML = ageObj2[UNITS[unitsIndex]];
    limitEl.innerHTML = ageObj1[UNITS[unitsIndex]];
    
    if (ageObj1[UNITS[unitsIndex]] < ageObj2[UNITS[unitsIndex]]) {
       console.info(`The current ${UNITS[unitsIndex]} is stale.`)
      currentEl.classList.add("red");  
      return false;
    } else if(ageObj1[UNITS[unitsIndex]] > ageObj2[UNITS[unitsIndex]]){
       console.info(`The current ${UNITS[unitsIndex]} is more than a full unit to the good.`)
      return true;
    }
         
    unitsIndex++;
  }
  return true;
}

var limit_fields = document.querySelectorAll(".limit");
for(i=0; i < limit_fields.length; i++){
        let id = limit_fields[i].id.split("_")[1];
        let val = CACHE_FILE_AGE_LIMIT[id]
        limit_fields[i].innerHTML = val;
    }

document.getElementById("output").innerHTML = timeDiff(CACHE_FILE_AGE_LIMIT, CACHE_FILE_CURRENT_AGE) ? "up to date" : "old";
.tg {
  border-collapse: collapse;
  border-spacing: 0;
}

.tg td {
  font-family: Arial, sans-serif;
  font-size: 12px;
  padding: 10px 5px;
  border-style: solid;
  border-width: 1px;
  overflow: hidden;
  word-break: normal;
  border-color: black;
}
// CSS styling continues...

<table class="tg" style="undefined;table-layout: fixed; width: 265px">
  <colgroup>
    // table columns
  </colgroup>
  <tr>
    <th class="empty"></th>
    <th class="header">CURRENT</th>
    <th class="header">LIMITS</th>
  </tr>
  // table rows and cells
</table>

Template literals can simplify the element IDs by dynamically generating them using the UNITS array. This approach minimizes hardcoded values and simplifies the logic flow. The updated code handles multiple scenarios within the if statement, enhancing clarity and efficiency.

`current_${UNITS[unitIndex] }`

If the current surpasses the limit, return false immediately. If the limit exceeds the current by a full unit, return true. If they are equal, move to the next unit. The code has been adjusted to reflect these cases.

Answer №2

To simplify nested conditions into a linear code representation, one can extract individual conditions into functions and utilize the some method for quick run exit. However, storing a flag is necessary when a return value is needed, as the return value of some alone is insufficient.

This method allows for the addition of numerous conditions, easy breakage as needed, and returns a boolean value for further processing.

Nonetheless, a drawback lies in the requirement for understanding data, the nested structure, and the realization that the next condition or function is repeatedly called until a true is returned, disregarding the flag value.

const CACHE_FILE_AGE_LIMIT = {
  days: 3,
  hours: 6,
  minutes: 15,
  seconds: 57
}

const CACHE_FILE_CURRENT_AGE = {
  days: 3,
  hours: 5,
  minutes: 14,
  seconds: 57
}

function timeDiff(ageObj1, ageObj2) {
    var flag;
    [
        () => {
            document.getElementById("current_days").innerHTML = ageObj2.days;
            if (ageObj1.days < ageObj2.days) {
                document.getElementById("current_days").classList.add("red");
                return flag = true;
            }
        },
        // other conditions...
    ].some(fn => fn());
    return flag;
}


// Populate Limits
var limit_fields = document.querySelectorAll(".limit");
for(i=0; i < limit_fields.length; i++){
//console.log('--->', i)
        let id = limit_fields[i].id.split("_")[1];
        let val = CACHE_FILE_AGE_LIMIT[id]
        //console.log('\tid:', id, 'val:', val);
        limit_fields[i].innerHTML = val;
    }

// Evaluate Age
document.getElementById("output").innerHTML = timeDiff(CACHE_FILE_AGE_LIMIT, CACHE_FILE_CURRENT_AGE) ? "old" : "up to date";
.tg {
  border-collapse: collapse;
  // CSS styles...
}
<table class="tg" style="undefined;table-layout: fixed; width: 265px">
  <colgroup>
    <col style="width: 92px">
    <col style="width: 92px">
    <col style="width: 92px">
  </colgroup>
  <tr>
    <th class="empty"></th>
    <th class="header">CURRENT</th>
    <th class="header">LIMITS</th>
  </tr>
  <tr>
    // table rows...
  </tr>
</table>

An alternate approach involves using an array with keys and iteratively processing until a certain condition returns true.

function timeDiff(ageObj1, ageObj2) {
    var flag;

    ['days', 'hours', 'minutes', 'seconds'].some((key, index, keys) => {
        var nextKey = keys[index + 1],
            element = document.getElementById("current_" + key),
            nextElement = document.getElementById("current_" + nextKey);

        element.innerHTML = ageObj2[key];
        if (ageObj1[key] < ageObj2[key]) {
            element.classList.add("red");
            return flag = true;
        }
        if (ageObj1[key] == ageObj2[key] && nextKey) {
            nextElement.innerHTML = ageObj2[nextKey];
        } else {
            element.classList.add("blue");
            flag = false;
            return true;
        }
    });

    return flag;
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

I need help getting my Vue.JS project to function properly when it is deployed on a server

After creating a new VueJS project using the Vue UI, I noticed that everything runs smoothly locally at http://localhost:8080/ with no errors. However, when I build the project and upload the files from the dist folder to my hosting package via FTP, I end ...

JavaScript - Attempting to insert a value into a text field by clicking a button

I am struggling to get my function to properly add the value of the button to the text field when clicked by the user. HTML <form name="testing" action="test.php" method="get">Chords: <textarea name="field"& ...

What steps should I take to resolve the "Module Not Found" issue that occurs when I use the command "npm start" after setting up a new React project with npm?

Just starting out with React.js and npm and encountered an issue. After using the command: npm create react-app my-test-npm-react-app I waited for the project to be created successfully. However, when I tried running: npm start I received the followin ...

JavaScript can be used to open several tabs simultaneously within a single browser window

Looking to open multiple tabs in the main browser? Check out this code snippet: function openSM() { window.open("http://www.google.com","_blank"); window.open("http://www.yahoo.com","_blank"); window.open("http://www.bing.c ...

The existing session persists when a new user logs in, instead of being destroyed

Security measures will be implemented at a later time Currently, I have a login script that operates in two scenarios. It either returns a message in JSON format, indicating issues such as incorrect login credentials or empty fields, or it initiates a ses ...

Attempting to include a standard VAT rate of 5% on the invoice

/* The code format is correct and I don't see any issues on my end, I hope it works well for you. */ I need assistance in adding a fixed VAT (tax) rate of 5%. The tax amount should be displayed on the row, while the total tax should reflect the sum o ...

The ajax method is encountering an issue when trying to perform an action: It is unable to find the necessary anti-forgery form field "__RequestVerificationToken" required for the operation

I am encountering an issue with my ajax method that triggers the action method from the controller. When I run this method, I receive an error stating: The required anti-forgery form field "__RequestVerificationToken" is not present. However, upon inspecti ...

Using ant-design with react-draggable for modals: A step-by-step guide

Trying to implement a modal window using ant-design with the react-draggable npm package has been quite challenging. For those unfamiliar, react-draggable is a simple component for enabling drag functionality on elements. However, I encountered an issue wh ...

Extract information from a URL using Regular Expressions

On my page, I have a list of blog post links: <ul class="postlist"> <li><a href="http://someblog.it/blogpost/7/-----.aspx">Post One</a></li> <li><a href="http://someblog.it/blogpost/32/----------.aspx">Post Two< ...

What could be causing the shake effect on the MUI dialog to not work when clicking away?

I am trying to implement a shake effect when the user clicks outside the MUI dialog to indicate that clicking away is not allowed. However, the code I have so far does not seem to be working as the effect is not being applied. Can someone please help me ...

The passport authentication process is malfunctioning as there seems to be an issue with the _verify function

Having an issue and could use some assistance. I am currently implementing passport in my express application. While I am able to successfully register a user, I encounter an error when trying to log in. TypeError: this._verify is not a function at Str ...

Issues with implementing KoGrid within the Durandal JS framework

How do I properly bind a koGrid in my Durandal JS view page? The code provided below is not functioning as expected. View (HTML) <div id="functiontable" class="form-actions"> <div style="height: 200px" data-bind="koGrid: ...

What is the best way to switch from rows to cards in Bootstrap version 5.3?

In my current project, Next JS is the framework I am working with. I am faced with the challenge of creating a card layout that adapts based on device size - for smaller devices, I want a plain card with the image on top and text below, similar to Bootstra ...

I need assistance improving my poor JavaScript patterns and practices. Where should I turn for help?

After focusing primarily on back-end tasks for the past few years, it's become apparent to me that JavaScript (and CoffeeScript) projects have evolved significantly in my absence. Working mainly in a rails environment, my previous JavaScript/jQuery i ...

Ways to transfer information from a function within one element to another element

I have two components: one that logs the indexes of a carousel and I need to pass these indexes into the second component. First Component <template> <div class="container container--white"> <Header /> <carousel-3d @a ...

Development and staging setups tailored specifically for a JavaScript SDK

Currently, I am working with a Javascript SDK that is available on NPM. Alongside this, I have a Vue application utilizing the SDK and it's crucial for me to test them together across various pre-production environments (such as staging). Here are the ...

Using Vue Js to bind two values to an href attribute in a tag

As a Vue.js beginner, I am encountering an issue where I need to update two values simultaneously during rendering. <ul class="category-list"> <li v-for="category in categories"> <a v-bind:href="location/category.slug/all" v-tex ...

The issues of cross-origin domains arise when utilizing iframes with src links originating from the server side

Encountering a cross-origin domain issue, receiving the following error while working with an iframe: candidateInterviewCtrl.js:39 Uncaught SecurityError: Blocked a frame with origin "http://localhost:9000" from accessing a frame with origin "http://local ...

Bookmarklet does not successfully inject jQuery on a specific webpage

Trying to utilize a certain bookmarklet: javascript:void((function(doc){if(typeof jQuery=='undefined'){var script_jQuery=document.createElement('script');script_jQuery.setAttribute('src','https://code.jquery.com/jquery ...

Transform the size and convert an object from a picture into text based on the user's scrolling

I've been intrigued by the scrolling effects used on websites like Google SketchUp and Google Plus. It's fascinating how elements can transform as you scroll down the page. For example, on Google SketchUp's site, the banner starts off integr ...