0

I am very new to JavaScript and i'm struggling to find a solution to simplify my JavaScript code. I have working code, but it's very bulky and i feel like it can be made smaller or easier. Do you guys think it's possible?

I have went online and tried to see if i can implement what people have done, but most of the stuff either don't work or works but is not what i'm looking for.

<html>
    <script>
        window.onload = function () {

    document.getElementById("Yes1").onclick = function () {
    document.getElementById("Question1").style.display = 'None';
    document.getElementById("Question2").style.display = 'inline';
    }
    document.getElementById("No1").onclick = function () {

    document.getElementById("Question1").style.display = 'None';
    document.getElementById("Question3").style.display = 'inline';
    }      
    document.getElementById("Yes2").onclick = function () {

    document.getElementById("Question2").style.display = 'None';
    document.getElementById("Question4").style.display = 'inline';
    }

    document.getElementById("No2").onclick = function () {

    document.getElementById("Question2").style.display = 'None';
    document.getElementById("Question5").style.display = 'inline';
    }

    document.getElementById("Yes3").onclick = function () {

    document.getElementById("Question3").style.display = 'None';
    document.getElementById("Question6").style.display = 'inline';
    }

    document.getElementById("No3").onclick = function () {

    document.getElementById("Question3").style.display = 'None';
    document.getElementById("Question6").style.display = 'inline';
    }

    document.getElementById("Yes4").onclick = function () {

    document.getElementById("Question4").style.display = 'None';
    document.getElementById("Question10").style.display = 'inline';
    }
    document.getElementById("No4").onclick = function () {

    document.getElementById("Question4").style.display = 'None';
    document.getElementById("Question10").style.display = 'inline';
    }
    document.getElementById("Yes5").onclick = function () {

    document.getElementById("Question5").style.display = 'None';
    document.getElementById("Question10").style.display = 'inline';
    }
    document.getElementById("No5").onclick = function () {

    document.getElementById("Question5").style.display = 'None';
    document.getElementById("Question10").style.display = 'inline';
    }
    document.getElementById("Yes6").onclick = function () {

    document.getElementById("Question6").style.display = 'None';
    document.getElementById("Question7").style.display = 'inline';
    }
    document.getElementById("No6").onclick = function () {

    document.getElementById("Question6").style.display = 'None';
    document.getElementById("Question8").style.display = 'inline';
    }
    document.getElementById("Yes7").onclick = function () {

    document.getElementById("Question7").style.display = 'None';
    document.getElementById("Question9").style.display = 'inline';
    }
    document.getElementById("No7").onclick = function () {

    document.getElementById("Question7").style.display = 'None';
    document.getElementById("Question9").style.display = 'inline';
    }
    document.getElementById("Yes8").onclick = function () {

    document.getElementById("Question8").style.display = 'None';
    document.getElementById("Question9").style.display = 'inline';
    }
    document.getElementById("No8").onclick = function () {

    document.getElementById("Question8").style.display = 'None';
    document.getElementById("Question9").style.display = 'inline';
    }
    document.getElementById("No9").onclick = function () {

    document.getElementById("Question9").style.display = 'None';
    document.getElementById("Question10").style.display = 'inline';
    }
    document.getElementById("No9").onclick = function () {

    document.getElementById("Question9").style.display = 'None';
    document.getElementById("Question10").style.display = 'inline';
    }

           }
    </script>
    <body>
        <section>
            <article>
                <hgroup>
                   <h1>Dynamic Questionnaire</h1>
                    <h2>Question disappear after clicked</h2>
                </hgroup>
              <div id="Test1" >
                1.1. ...
                    <input type='radio' id='Yes1' name='answer1'> Yes
                    <input type='radio' id='No1' name='answer1'> No
              </div>
              <div id="Test2" >
                1.2. ...
                    <input type='radio' id='Yes1' name='answer1'> Yes
                    <input type='radio' id='No1' name='answer1'> No
              </div>
                <div id="Question1">
                    1. ....
                    <input type='radio' id='Yes1' name='answer1'> Yes
                    <input type='radio' id='No1' name='answer1'> No
                </div>
                <div id="Question2" style='display:none' >
                    2. ....
                    <input type='radio' id='Yes2' name='answer1'> Yes
                    <input type='radio' id='No2' name='answer1'> No
                </div>
                <div id="Question3" style='display: none'>
                    3. ....
                    <input type='radio' id='Yes3' name='answer1'> Yes
                    <input type='radio' id='No3' name='answer1'> No
                </div>
                <div id="Question4" style='display: none'>
                    4. ....
                    <input type='radio' id='Yes4' name='answer1'> Yes
                    <input type='radio' id='No4' name='answer1'> No
                </div>
                <div id="Question5" style='display: none'>
                    5. ....
                    <input type='radio' id='Yes5' name='answer1'> Yes
                    <input type='radio' id='No5' name='answer1'> No
                </div>
                <div id="Question6" style='display: none'>
                    6. ....
                    <input type='radio' id='Yes6' name='answer1'> Yes
                    <input type='radio' id='No6' name='answer1'> No
                </div>
                <div id="Question7" style='display: none'>
                    7. ....
                    <input type='radio' id='Yes7' name='answer1'> Yes
                    <input type='radio' id='No7' name='answer1'> No
                </div>
                <div id="Question8" style='display: none'>
                    8. ....
                    <input type='radio' id='Yes8' name='answer1'> Yes
                    <input type='radio' id='No8' name='answer1'> No
                </div>
                <div id="Question9" style='display: none'>
                    9. ....
                    <input type='radio' id='Yes9' name='answer1'> Yes
                    <input type='radio' id='No9' name='answer1'> No
                </div>
                <div id="Question10" style='display: none'>
                    10. ....
                    <input type='radio' id='Yes10' name='answer1'> Yes
                    <input type='radio' id='No10' name='answer1'> No
                </div>
            </article>
        </section>
    </body>
</html>

[Sorry if i pasted too much code, can still barely use StackOverflow] So, when i run my html file, when the first Question appears, it has 'yes' and 'no' radio buttons.And when i click yes it should go to question 2 but hide question 1. And if i click no, it should hide question 1 as well but go to question 3. PS: I removed some html tags

  • So are you basically saying: You have a question with yes/no. If yes then show the next question. If no then skip the next question and go to the one after that. – John Feb 17 '19 at 16:22
  • Well, i have a path i want to follow, but yes, if yes, show next question and hide current one, if no, show another question and hide current one. – John Clarkson Feb 17 '19 at 17:29

2 Answers2

0

Welcome to Javascript! Don't worry about being new, everyone was new once :)

A few pointers that should help learn too

You can only have 1 element with a paricular id, so

<input type='radio' id='Yes1' name='answer1'> Yes
<input type='radio' id='No1' name='answer1'> No

is fine but

 <input type='radio' id='Yes1' name='answer1'> Yes
 <input type='radio' id='No1' name='answer1'> No
</div>
<div id="Test2" >
 1.2. ...
  <input type='radio' id='Yes1' name='answer1'> Yes
  <input type='radio' id='No1' name='answer1'> No

would need to be changed to (difference in the id fields)

 <input type='radio' id='Yes11' name='answer1'> Yes
 <input type='radio' id='No11' name='answer1'> No
</div>
<div id="Test2" >
 1.2. ...
  <input type='radio' id='Yes12' name='answer1'> Yes
  <input type='radio' id='No12' name='answer1'> No

Now this makes things more complex! We have to address each individually in the code...far from helpful...enter classes.

Assign each 'set' of answers (or block) a class to help differentiate the semantics of each set.

          <div id="Test1" >
            1.1. ...
                <input type='radio' class='test1 answer-yes' name='answer1'> Yes
                <input type='radio' class='test1 answer-no' name='answer1'> No
          </div>
          <div id="Test2" >
            1.2. ...
                <input type='radio'  class='test2 answer-yes' name='answer1'> Yes
                <input type='radio' class='test2 answer-no' name='answer1'> No
          </div>

In this case, without using libraries, it's probably useful to store the required "action" on the "event input". For this we can use the data- attribute on an HTML element, and access it from the Javascript (we can also use something semantic, like the name):

          <div id="Test1" >
            1.1. ...
                <input type='radio' data-action="1"  class='test1 answer-action answer-yes' name='answer1' data> Yes
                <input type='radio' data-action="1"  class='test1 answer-action answer answer-no' name='answer1'> No
          </div>

Also the answer class name has been added to suggest that this answer provides some action. To find all our answers with actions, in your javascript you can generically address all of the elements (pulled from question https://stackoverflow.com/a/40956816/5746996:

var elementsArray = document.querySelectorAll('answer-action');

elementsArray.forEach(function(elem) {
    elem.addEventListener("click", function() {
        //do something 
        elem.dataset.action // gives you the relevant action
    });
});
Tobin
  • 1,698
  • 15
  • 24
0

First, id values must be unique within a document and you are reusing the same ones for each set of radio buttons, so you'll need to correct that. Now, the name attribute on each of the radio buttons within a set should be the same, but the next set need a different name so that the answer from one question doesn't get overridden by the answer to the next. You also need to give each radio button a value so that if it is selected, that selection will have meaning. (I've used "Yes" and "No" below, but more specific values that relate to the question should be used when appropriate.).

But, frankly, the best way to create better code here is to not rely in inline styles and ids in the first place. It bulks up the HTML and forces you to deal with each id separately.

Instead, just assign CSS classes to each question element and style the elements dynamically with that class. See the comments inline below and note how much simpler the code is.

I've wrapped the actual text of each question in a span element to make it easy to gain access to the question text later if desired.

Also, instead of setting up a window.onload event handler, just move your script to the bottom of the HTML, just prior to the closing body tag (</body>). That way, by the time the HTML parser encounters your script, all of the HTML will have been loaded.

Lastly, the hgroup element is part of the WHAT WG HTML5 standard, but it is not part of the W3C HTML5 standard and as such, you should probably avoid using it.

.hidden { display:none; }
.question { border:1px dashed #e0e0e0; }
.results { border:1px solid #909090; background-color:rgba(0,0,0,.25);}
<html>
    <body>
        <section>
            <article>
                <h1>Dynamic Questionnaire</h1>
                <h2>Question disappear after clicked</h2>
                <div class="question">
                    <span class="questionText">1. ....</span>
                    <input type='radio' name='answer1' value="Yes"> Yes
                    <input type='radio' name='answer1' value="No"> No
                </div>
                <div class="question hidden">
                    <span class="questionText">2. ....</span>
                    <input type='radio' name='answer2' value="Yes"> Yes
                    <input type='radio' name='answer2' value="No"> No
                </div>
                <div class="question hidden">
                    <span class="questionText">3. ....</span>
                    <input type='radio' name='answer3' value="Yes"> Yes
                    <input type='radio' name='answer3' value="No"> No
                </div>
                <div class="question hidden">
                    <span class="questionText">4. ....</span>
                    <input type='radio' name='answer4' value="Yes"> Yes
                    <input type='radio' name='answer4' value="No"> No
                </div>
                <div class="question hidden">
                    <span class="questionText">5. ....</span>
                    <input type='radio' name='answer5' value="Yes"> Yes
                    <input type='radio' name='answer5' value="No"> No
                </div>
                <div class="question hidden">
                    <span class="questionText">6. ....</span>
                    <input type='radio' name='answer6' value="Yes"> Yes
                    <input type='radio' name='answer6' value="No"> No
                </div>
                <div class="question hidden">
                    <span class="questionText">7. ....</span>
                    <input type='radio' name='answer7' value="Yes"> Yes
                    <input type='radio' name='answer7' value="No"> No
                </div>
                <div class="question hidden">
                    <span class="questionText">8. ....</span>
                    <input type='radio' name='answer8' value="Yes"> Yes
                    <input type='radio' name='answer8' value="No"> No
                </div>
                <div class="question hidden">
                    <span class="questionText">9. ....</span>
                    <input type='radio' name='answer9' value="Yes"> Yes
                    <input type='radio' name='answer9' value="No"> No
                </div>
                <div class="question hidden">
                    <span class="questionText">10. ....</span>
                    <input type='radio' name='answer10' value="Yes"> Yes
                    <input type='radio' name='answer10' value="No"> No
                </div>
            </article>
        </section>
        
        <section class="results hidden"><div>Summary of Answers:</div></section>
        
        <script>
          // Get all the question elements into an array
          let questions = Array.prototype.slice.call(document.querySelectorAll(".question"));

          // Loop through the questions
          questions.forEach(function(question){
          
            // Set up a click event handler for the question
            question.addEventListener("click", function(){
              this.classList.add("hidden");  // Hide the current question
    
              // Show the next question (if there is one)
              if(this.nextElementSibling){
                this.nextElementSibling.classList.remove("hidden");
              } else {
                // All questions have been answered at this point.
                // Proceed as you see fit. Here, I'm just displaying
                // a summary of each question with the supplied answer
                // for demonstration:
                
                let output = document.querySelector(".results");  // Get reference to the results area
                let outputString = "";  // <-- Will hold output to be written to results area
                
                // Loop through the questions
                questions.forEach(function(quest){
                   // Build up a string consisting of the question itself a colon, the value
                   // of the selected radio button for that question and an HTML break tag
                   outputString += quest.firstElementChild.textContent + " : " +
                                   quest.querySelector("input[type='radio']:checked").value + "<br>";
                });
         
                output.innerHTML += outputString;  // Inject the output string into the resluts area
                output.classList.remove("hidden"); // Show the results area
              }
            });
         });
      </script>
    </body>
</html>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • Thank you, this helps a lot, last question tho...So is it not possible to only use html and JavaScript only? – John Clarkson Feb 17 '19 at 17:36
  • @JohnClarkson The only way to cut pre-made CSS classes out of the picture is to revert back to hard-coding inline styles into the HTML and then modify those inline styles with JavaScript. This will bulk up the HTML and the JavaScript and create a much more brittle code base for you to work with and maintain. We want to implement the [Separation of Concerns](https://softwareengineering.stackexchange.com/questions/32581/how-do-you-explain-separation-of-concerns-to-others) in modern web development: – Scott Marcus Feb 17 '19 at 17:44
  • HTML only cares about document structure & semantics, CSS only cares about layout & style and JavaScript only cares about behavior. We keep these three languages as separate as we can. – Scott Marcus Feb 17 '19 at 17:44
  • Ok, thank you very much for explaining. It makes sense. – John Clarkson Feb 17 '19 at 17:48