skip to Main Content

I have a simple HTML page with different elements which are being hidden or displayed because of choosing some options before.

I have different options (radiobuttons) which have to be clicked before, they should control and hide or show the elements:

  1. Household or Nohousehold (Household = 1, Nohousehold = 2)
  2. Household or Nohousehold and Monument (Monument = 1 or 2)
  3. Household and Monument
  4. Nohousehold
  5. Nohousehold and Zones (Zones = 1 or 2)
  6. Nohousehold and Monument
  7. Nohousehold and Zones and Monument

I called the div classes on html after the numbers above (for example: 1 = class1, 2 = class2,.. and so on), each class should be visible by selecting from the options above. This is my edit_outerwalls.jsp which is included in edit.jsp.

<div class="class1"> //This should be displayed only if Household = 1 or 2
...
</div>

<div class="class2"> //This should be displayed only if Household = 1 or 2 and Monument = 1
...
</div>

<div class="class3"> //This should be displayed only if Household = 1 and Monument = 1
...
</div>

<div class="class4"> //This should be displayed only if Household = 2
...
</div>

<div class="class5"> //This should be displayed only if Household = 2 and Zones = 1
...
</div>

<div class="class6"> //This should be displayed only if Household = 2 and Monument = 1
...
</div>

<div class="class7"> //This should be displayed only if Household = 2 and Zones = 1 and Monument = 1
...
</div>

<div class="class2">
...
</div>

<div class="class5">
...
</div>

My jQuery Code looks like this:

function checkClass1234() {
    let household = $('input:radio[name="household"]:checked').val(); //this are the radiobuttons on the html page
    let zones = $('input:radio[name="zones"]:checked').val();
    let monument = $('input:radio[name="monument"]:checked').val();

    if (household === '1' || household === '2') {
        $('.class1').show();
    } else if ((household === '1' || household === '2') && (monument === '1')) {
        $('.class2').show();
    } else {
        $('.class1').hide();
        clearValues('.class1');
        $('.class2').hide();
        clearValues('.class2');
    }

    if (household === '1' && monument === '1') {
        $('.class3').show();
        $('.class2').hide();
        clearValues('.class2');
    } else {
        $('.class3').hide();
        clearValues('.class3');
    }

    if (household === '2') {
        $('.class4').show();
        $('.class3').hide();
        clearValues('.class3');
    } else {
        $('.class4').hide();
        clearValues('.class4');
    }

    if (household === '2' && zones === '1' && monument === '1') {
        $('.class7').show();
        $('.class2').hide();
        clearValues('.class2');
        $('.class3').hide();
        clearValues('.class3');
    } else if (household === '2' && monument === '1') {
        $('.class6').show();
        $('.class2').hide();
        clearValues('.class2');
        $('.class3').hide();
        clearValues('.class3');
    } else if (household === '2' && zones === '1') {
        $('.class5').show();
        $('.class2').hide();
        clearValues('.class2');
        $('.class3').hide();
        clearValues('.class3');
    } else {
        $('.class4').hide();
        clearValues('.class4');
        $('.class5').hide();
        clearValues('.class5');
        $('.class6').hide();
        clearValues('.class6');
        $('.class7').hide();
        clearValues('.class7');
    }
}

My edit.jsp looks like this (in here i include all my pages):

<%@page contentType="text/html" pageEncoding="UTF-8" %>
<jsp:directive.include file="/WEB-INF/sitemesh-decorators/include.jsp"/>
<fmt:setBundle basename="bundles.${orderName}-resources"/>
<c:set var="order" value="${order}" scope="request"/>

<head>
    <!-- All Scripts -->
</head>

<jsp:include page="/WEB-INF/jspf/crumb1to4/edit.jsp"/>

<section id="content">
    <header>
        <h1><fmt:message key="title"/></h1>
        <h3>
            <fmt:bundle basename="bundles.household-resources">
                <fmt:message key="title.comment"/>
            </fmt:bundle>
        </h3>
    </header>

    <jsp:include page="/WEB-INF/jspf/edit/mandatory.jsp"/>

    <spring:url var="attachmentsUrl" value="/${orderName}/attachments"/>
    <form:form method="post" modelAttribute="order" action="${attachmentsUrl}">
        <jsp:include page="/WEB-INF/jspf/edit/errors.jsp"/>

        <jsp:include page="edit_consultant.jsp"/>

        <jsp:include page="edit_household.jsp"/>
        
        <fieldset>
            <fmt:bundle basename="bundles.order-resources">
                <legend>
                    <jsp:include page="/WEB-INF/jspf/edit_elem/checkbox.jsp">
                        <jsp:param name="label" value="caption.buildingshell"/>
                        <jsp:param name="field" value="buildingshell"/>
                        <jsp:param name="bundle" value="order"/>
                        <jsp:param name="tooltip" value="buildingshell.info"/>
                    </jsp:include>
                </legend>

                <div id="blockBuildingshell">
                    <div class="haupttext">
                        <fmt:message key="buildingshell.comment"/>
                    </div>

                    <jsp:include page="edit_outerwalls.jsp"/> <!-- In here i have all the elements with class1, class2, class3... -->

                </div>
            </fmt:bundle>
        </fieldset>

        <jsp:include page="edit_machines.jsp"/>

        <!-- ...Another Included JSP Pages... -->

        <!-- include next button -->
        <jsp:include page="/WEB-INF/jspf/edit/next2.jsp">
            <jsp:param name="next">
                <jsp:attribute name="value">
                    <fmt:message key="next.comment"/>
                </jsp:attribute>
            </jsp:param>
        </jsp:include>
    </form:form>
</section>

And my Household.jsp looks like this (here are the 3 RadioButtons):

<%@ page pageEncoding="UTF-8" %>
<jsp:directive.include file="/WEB-INF/sitemesh-decorators/include.jsp"/>

<fmt:bundle basename="bundles.order-resources">

    <!-- Household -->
    <fieldset>
        <legend>
            <fmt:message key="caption.household"/>
        </legend>

        <div class="formclear"></div>

        <h3>
            <fmt:message key="caption.location"/>
        </h3>

        <div class="label">
            <form:label path="household.type">
                <fmt:message key="household.type"/>
            </form:label>
            <span class="formAsterics">*</span>
            <jsp:include page="/WEB-INF/jspf/edit/tooltip.jsp">
                <jsp:param name="tooltip" value="household.type.tooltip"/>
                <jsp:param name="bundle" value="order"/>
            </jsp:include>
        </div>
        <div class="field fieldRadio">
            <form:radiobutton path="household.type" value="1"/>
            <fmt:message key="household.type1"/>
            &nbsp;
            <form:radiobutton path="household.type" value="2"/>
            <fmt:message key="household.type2"/>
            <form:errors path="household.type" cssClass="error"/>
        </div>

        <div class="formclear"></div>

        <div class="blockNohousehold">
            <!-- household.zones -->
            <jsp:include page="/WEB-INF/jspf/edit_elem/radio_yes_no.jsp">
                <jsp:param name="label" value="household.zones"/>
                <jsp:param name="field" value="household.zones"/>
                <jsp:param name="bundle" value="order"/>
                <jsp:param name="mandatory" value="true"/>
            </jsp:include>
        </div>

        <div id="blockMonument">
            <!-- household.monument -->
            <div class="label">
                <form:label path="household.monument">
                    <span class="blockHousehold"><fmt:message key="household.monument1"/></span>
                    <span class="blockNohousehold"><fmt:message key="household.monument2"/></span>
                    <span class="formAsterics">*</span>
                </form:label>
            </div>
            <div class="field fieldRadio">
                <fmt:bundle basename="bundles.application-resources">
                    <form:radiobutton path="household.monument" cssClass="inputCheck" value="1"/>
                    <fmt:message key="yes"/>
                    <form:radiobutton path="household.monument" cssClass="inputCheck" value="0"/>
                    <fmt:message key="no"/>
                </fmt:bundle>
                <form:errors path="household.monument" cssClass="error"/>
            </div>

            <div class="formclear"></div>
        </div>
    </fieldset>
</fmt:bundle>

And as last here is my DTO Object Household.java:

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@XmlAccessorType(XmlAccessType.FIELD)
public class Household implements Serializable {
    @Range(min = 1, max = 2)
    private Integer type;
    @Range(min = 0, max = 1)
    private Integer zones;
    @Range(min = 0, max = 1)
    private Integer monument;
}

Im sorry for my english and sorry if there is something missing in my question, just let me know!
Thanks!

My problem is, when i select the options first time, it works pretty good except the class7. When i change the selected options or switch only one then nothing happens anymore. It looks like its frozen. I tried different ways to sort the if´s but this is the best result until now. Im pretty new to jQuery and i would appreciate someones help! 🙂

3

Answers


  1. check the below sample code to show and hide element.

    <div class="class1" > Household 
    ...
    </div>
    
    
    <input type="checkbox" onclick="checkClass1234()" id="household" name="vehicle1" value="1" >
    <label> Hide & Show Household</label><br>
    <script>
    function checkClass1234() {
    var rate_value;
      if (document.getElementById('household').checked) {
      rate_value = document.getElementById('household').value;
      if(rate_value != "undefined"){
      document.getElementsByClassName('class1')[0].style.display = 'none';
      }
    }else{
       document.getElementsByClassName('class1')[0].style.display = 'block';
      }
    }
    </script>
    Login or Signup to reply.
  2. Here is one way of doing it with minimal code. But it requires that the visibility settings are done per element in an extra data-show attribute. This attribute contains a string with at most three characters, one for each of the radio buttons for household, monument and zones. The characters are checked one by one in the .every() loop: if v=="x" then the i-th radio button value must be non-zero, if v=="-" then nothing is required and if v is anything else then the i-th radio button’s value must match exactly that.

    const toggledivs = document.querySelectorAll("[data-show]");
    const RBs = [ frm.household, frm.monument, frm.zones ];
    toggledivs.forEach(d=>d.style.display="none");
    
    document.body.onclick = ev => {
      if (ev.target.tagName == "INPUT")
        toggledivs.forEach(d=>d.style.display=d.dataset.show.split("").every((v,i)=>v=="-"||(v=="x"&&RBs[i].value>0)||v==RBs[i].value) ? "" : "none" )
    }
    <form name="frm">
      <fieldset><label><input type="radio" name="household" value="0" checked>0</label>
        <label><input type="radio" name="household" value="1">1</label><label><input type="radio" name="household" value="2">2</label> Household</fieldset>
      <fieldset><label><input type="radio" name="monument" value="0" checked>0</label>
        <label><input type="radio" name="monument" value="1">1</label> Monument</fieldset>
      <fieldset><label><input type="radio" name="zones" value="0" checked>0</label>
        <label><input type="radio" name="zones" value="1">1</label> Zones</fieldset>
    </form>
    <div class="class1" data-show="x">1 //This should be displayed only if Household = 1 or 2 ...
    </div>
    
    <div class="class2" data-show="x1">2 //This should be displayed only if Household = 1 or 2 and Monument = 1 ...
    </div>
    
    <div class="class3" data-show="11">3 //This should be displayed only if Household = 1 and Monument = 1 ...
    </div>
    
    <div class="class4" data-show="2">4 //This should be displayed only if Household = 2 ...
    </div>
    
    <div class="class5" data-show="2-1">5 //This should be displayed only if Household = 2 and Zones = 1 ...
    </div>
    
    <div class="class6" data-show="21">6 //This should be displayed only if Household = 2 and Monument = 1 ...
    </div>
    
    <div class="class7" data-show="211">7 //This should be displayed only if Household = 2 and Zones = 1 and Monument = 1 ...
    </div>
    
    <div class="class2" data-show="x1">
     2 again ...
    </div>
    
    <div class="class5" data-show="2-1">
     5 again ...
    </div>
    Login or Signup to reply.
  3. In this kind of code where the logic is convoluted, it is necessary to use logical tools to represent the decision system.

    Otherwise you end up with a spaghetti code where you will sink, you and all those who will have to manage this code.

    My advice: use "talking" words, not X,Y,Z names that will make everyone lose the thread of logic.

    Here, there is only a simple decision grid to maintain, whose logic is modeled on the description of the ins and outs, in a generic way. any change in the logic just requires modifying only this grid, you can even add new classes or new radio buttons, add to them or change their values. the JS could stay the same.

    Code point of view, it is of course necessary to bother to establish an interpreter of this grid; for any computer scientist it is a noble part to achieve…

    Actualy your decision grid is something like that :

    Household Monument Zones
    class1 1,2 . .
    class2 1,2 1 .
    class3 1 1 .
    class4 2 . .
    class5 2 . 1,2
    class6 2 1 .
    class7 2 1 1

    Changed in a JS object it does :

    const decisionGid = 
      { class1 : { household : [1,2]                              }
      , class2 : { household : [1,2], monument: [1]               }
      , class3 : { household : [1],   monument: [1]               }
      , class4 : { household : [  2],                             }
      , class5 : { household : [  2],                zones: [1,2] }
      , class6 : { household : [  2], monument: [1]               }
      , class7 : { household : [  2], monument: [1], zones: [1]   }
      }
    

    once the code is established, it is much easier to update the decision grid than to revise your nested if cascades

    So your code should be :

    const
      myForm  = document.querySelector('#my-form')
    , decisionGid = 
      { class1 : { household : [1,2]                              }
      , class2 : { household : [1,2], monument: [1]               }
      , class3 : { household : [1],   monument: [1]               }
      , class4 : { household : [  2],                             }
      , class5 : { household : [  2],                zones: [1,2] }
      , class6 : { household : [  2], monument: [1]               }
      , class7 : { household : [  2], monument: [1], zones: [1]   }
      };
    
    myForm.onsubmit = e => e.preventDefault(); // disable form submit for testing
    
    f_update_show_hide();
    myForm.addEventListener('input',f_update_show_hide);
    
    function f_update_show_hide()
      {
      for ( let classVal in decisionGid )   
        {
        let test = true
        for (let elm in decisionGid[classVal])  
          {
          test &&= decisionGid[classVal][elm].includes( Number(myForm[elm].value) )
          }
        if (test)  $(`.${classVal}`).show();
        else       $(`.${classVal}`).hide();        
        }
      }
    
    myForm.onclick = ({target: btn}) =>
      {
      if (!btn.matches('button[data-elm]'))  return;
      myForm[btn.dataset.elm].value = 0;
      f_update_show_hide();
      }
    
    // set display info conditions (for demo control)
    for (let classVal in decisionGid )
      {
      $(`.${classVal}`).text(`${classVal} -> ${JSON.stringify(decisionGid[classVal])}` );
      }
    body {
      font-family : Arial, Helvetica, sans-serif;
      font-size   : 16px;
      }
    label {
      display    : inline-block;
      width      : 2.6em;
      background : lightgreen;
      }
    input[value="0"] {
      display : none;
      }
    fieldset {
      display : inline-block;
      width   : fit-content;
      padding : .4em;
      }
    fieldset label:last-of-type {
      background : orange;
      }
    div {
      margin     : .4em;
      padding    : .1em .4em;
      background : lightblue;
      }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <form id="my-form">
      <fieldset>
        <legend>household</legend>
        <label> <input type="radio" name="household" value="1">  1 </label>
        <label> <input type="radio" name="household" value="2">  2 </label>
        <input type="radio" name="household" value="0" selected>
        <button type="button" data-elm="household">none</button>
      </fieldset>
      <fieldset>
        <legend>monument</legend>
        <label> <input type="radio" name="monument" value="1">  1 </label>
        <label> <input type="radio" name="monument" value="2">  2 </label>
        <input type="radio" name="monument" value="0" selected>
        <button type="button" data-elm="monument">none</button>
      </fieldset>
      <fieldset>
        <legend>zones</legend>
        <label> <input type="radio" name="zones" value="1">  1 </label>
        <label> <input type="radio" name="zones" value="2">  2 </label>
        <input type="radio" name="zones" value="0" selected>
        <button type="button" data-elm="zones">none</button>
      </fieldset>
    </form>  
    
    <div class="class1"> class 1</div>
    <div class="class2"> class 2</div>
    <div class="class3"> class 3</div>
    <div class="class4"> class 4</div>
    <div class="class5"> class 5</div>
    <div class="class6"> class 6</div>
    <div class="class7"> class 7</div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search