Display divs results based on web form radio news selection

I would like to just .show()

a div

based on a web form switcher (user) selection.

Let's take a look below for brevity (but note that I'm looking for some scalable advice since my web form will have 7 questions and 5 answers each. And I have 5 results divs

)

Note: // So basically there will be 7 questions and 5 answers each. so I would need an array with 5 possible combinations of responses using a user selectable radio button, ideally using an input field " value

"; so I can just change the values โ€‹โ€‹of which combo values โ€‹โ€‹are equal to what the results screen outputs. The div results screen will be just 5 unique sets of content inside the div that it is.


Mark-Up:

<div class="page1">
  <form class="sampler">
    <input type="radio" name="sex" value="male" checked>Male
    <br>
    <input type="radio" name="sex" value="female">Female
  </form>
</div>

      


<div class="page2">
  <form class="sampler">
    <input type="radio" name="food" value="tacos" checked>Tacos
    <br>
    <input type="radio" name="food" value="spicynuts">Rotten Spicy Peanuts
  </form>
</div>

      


<div id="resultsONE"><!-- one results div is display none by default sample but there would be much more content here  -->
  <p>Congratulations, you are NOT the father</p>
</div>

      

I know below is terrible syntax; but that was the logic I was thinking about starting from the JS side . Note. I will have 5 unique results #divs

.


function resultsdivONE () { 
  if ($input value == "male" & "tacos") {
    $('#resultsONE').show();   
  } else if () {
    // do
  } else {
    // do
  }
}

      


As I mentioned above; I'm looking for a method where I can just use the SELECTED input value=""

; therefore they can be easily changed.

Example.


if ("male" & "tacos" & "nextanswer" & "nextanswerafter") { // etc up to 7
   $('#resultsONE').show(); 
 }  // first results div

      


Can be opened for php options.

Thanks for watching!

+3


source to share


7 replies


display results based on a selection of web form radios

What to achieve?

So, basically, a search is a simple form containing radio buttons and results that must match a combination of radio selections. Due to this, questions should be easily maintainable and changeable without touching the script or its original logic. These are the votes for outsourcing questions and logic - to separate it from the DOM.

How to do it?

Briefly mentioned and also visible in question tags are php and ajax. Considering that there might be a desire to fully convey the answers to the questions and grab them from php ajax. Another vote for outsourcing.

What is needed to achieve this?

  • Is there some kind of infrastructure and / or library? Not required, but it might be helpful
    • To get JSON
    • To create DOM elements
  • Do we need all the questions and answers in the DOM all the time? Not really

Let's take a look below for brevity (but note that I'm looking for some scalable advice, since my webform will have 7 questions and 5 answers each. And I have 5 divs result)

  • I recommend creating the DOM on the fly because - until now - there is no reason to keep it all the time, and it makes the HTML file itself thinner and tidier.
  • It is also possible to separate layout, structure, logic, and data, which ultimately allows you to change the answers and questions by changing a single file.
  • With this method, you can create more forms with different questions, but with the same code.
  • If you are not already using any library / framework, do not add it just for this script.

Conclusion

To make it easy to maintain, the Q&A will be piped into a json file (JSON.js here). With that in mind, it is also possible to retrieve it using php or any web service and / or store it in a database. In addition, it is possible to create several forms with still different questions, all of which use the same code.

Script available

code

<html>
    <head>
        <!-- optional styles -->
        <style>
            #Container{
                left: 50%;
                position: absolute;
                text-align: center;
                top: 50%;
                transform: translate(-50%, -50%);
            }
        </style>

        <script>
            //This is out simple AJAX routine to not overload it by any framework.
            //If you are already using jQuery, just use $.get()
            ;var AJAX = {
                getXmlDoc: function(){return ((window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"))},

                //u:=url, f:=callback, c:=any param to pass to callback
                Get: function(u, f, c){
                    var tDoc = this.getXmlDoc();

                    tDoc.open('GET', u, true);
                    tDoc.onreadystatechange = function(){
                        if (tDoc.readyState === XMLHttpRequest.DONE && tDoc.status === 200) f(tDoc, c);
                    };

                    tDoc.send();
                }
            };

            //This is going to be the namespace holding our functionality.
            //In the end one should outsource this to a script file, yet we leave it here in the example for a better overview.
            ;var Quiz = {
                mContainer: null, //In this container the quiz gets created in
                mCurrent: null, //Stores the current displayed question
                mJSON: null, //In here we are going to store the JSON result

                //Handling logical errors, like missing data or json
                _Error: function(m){
                    console.log(m)
                },

                //The event called on the radio change event
                //e:=element
                _onChange: function(e){
                    if (e && this.mJSON.questions[this.mCurrent]){
                        //We are going to those the result of this question in the JSON
                        this.mJSON.questions[this.mCurrent].value = e.value;

                        //If the question is not the last, we are going to display the next one
                        if (this.mCurrent < this.mJSON.questions.length - 1){
                            this.hideQuestions();
                            this.showQuestion(this.mCurrent + 1)
                        }
                        else{
                            //Else we are going to show the result
                            this.hideQuestions();
                            this.showResult()
                        }
                    }
                    else this._Error('_onChange(): Invalid parameters')
                },

                //The function to initialise our quiz.
                //We are going to grab the json data and analyse it.
                //c:=container element || document.body, l:=link || 'JSON.js'
                Init: function(c, l){
                    this.mContainer = (c || document.body);

                    var tL = (l || 'JSON.js');
                    AJAX.Get(tL, function(r, l){
                        Quiz.mJSON = JSON.parse(r.response);

                        if (Quiz.mJSON && Quiz.mJSON.questions)
                            Quiz.showQuestion(0)
                        else
                            Quiz._Error('Init(): No questions found with "' + l + '"')
                    }, tL)
                },

                //Hiding the previously asked questions (remove from dom)
                hideQuestions: function(){
                    while(this.mContainer.firstChild) this.mContainer.removeChild(this.mContainer.firstChild)
                },

                //Going to show the result according to the asked questions
                showResult: function(){
                    var tValues = []; //Storing our answers
                    for(var i=0, j=this.mJSON.questions.length; i<j; i++)
                        if (this.mJSON.questions[i].value) tValues.push(this.mJSON.questions[i].value)

                    //Going to store the result text
                    var tResult = 'No match for ' + tValues.join(',');

                    //Looping through all requirements to get a match
                    for(var i=0, j=this.mJSON.answers.length; i<j; i++){
                        //The requirements which need to match the values
                        var tR = this.mJSON.answers[i].requirement;

                        //For this we filter all the elements which do not match the requirements
                        var tF = tValues.filter(function(e){return tR.indexOf(e) === -1})

                        //If that list is empty, all elements matched and we can stop
                        if (!tF || tF.length === 0){
                            tResult = this.mJSON.answers[i].message;
                            break;
                        }
                    }

                    //Now we are going to dislpay the result
                    var tH = document.createElement('h1');
                    tH.innerHTML = tResult;
                    this.mContainer.appendChild(tH)
                },

                //This creates and shows a question of our question array
                //i:=JSON.questions array index
                showQuestion: function(i){
                    if (i >= 0 && i<this.mJSON.questions.length){
                        this.mCurrent = i;

                        var tQ = this.mJSON.questions[i];
                        var tN = Object.getOwnPropertyNames(tQ)[0]; //The property name is going to become the radio group name

                        //We are going to create a title (h1) and multiple radios (input & label) for each question
                        var tF = document.createDocumentFragment();

                        //Creating the header
                        var tH = document.createElement('h1');
                        tH.innerHTML = tQ.label;
                        tF.appendChild(tH);

                        //Creating the questions
                        for(var i=0, j=tQ[tN].length; i<j; i++){
                            var tR = document.createElement('input');
                            tR.type = 'radio';
                            tR.value = tQ[tN][i];
                            tR.name = tN;
                            tR.onchange = function(){Quiz._onChange(this)};
                            tF.appendChild(tR);

                            var tL = document.createElement('label');
                            tL.for = tR.name;
                            tL.innerHTML = tR.value;
                            tF.appendChild(tL);
                        }

                        //Now we are going to assign it to the dom.
                        this.mContainer.appendChild(tF)
                    }
                    else{
                        this.mCurrent = null;
                        this._Error('showQuestion(' + i.toString() + '): No such question loaded')
                    }
                }
            };
        </script>
    </head>

    <body onload = "Quiz.Init(document.querySelector('#Container'))">
        <div id = 'Container'>
            <!-- Container for the quiz -->
        </div>
    </body>
</html>

      

And JSON.js

{
    "questions": [
        {"sex": ["male", "female"], "label": "What are you?"},
        {"food": ["tacos", "spicynuts"], "label": "What do you eat?"},
        {"team": ["team a", "team b", "team rocket"], "label": "Where do you belong to?"}
    ],

    "answers": [
        {"requirement": ["male", "tacos", "team a"], "message": "one has chosen male, tacos and team a"},
        {"requirement": ["female", "tacos", "team a"], "message": "one has chosen female, tacos and team a"}
    ]
}

      

Edit:



A small question arose with me while writing my proposal. Given your explanation, "there are seven questions and five results." Do some results have results or not?

Changes

To address the issue with the sharing result, I find the two ways that I think are the easiest to enter and maintain.

We will list the result twice

This solution may seem silly and too simple. But it's easy to maintain and manage. The obvious disadvantage is the lack of data integrity.

{"requirement": ["male", "spicynuts", "team a"], "message": "one has chosen male, spicynuts and team a"},
{"requirement": ["female", "spicynuts", "team a"], "message": "one has chosen male, spicynuts and team a"}

      

We collect lists of requirements

Another way is to set requirements (array in array / object) so that more requirements can be simply listed with the same message. The downfall here is that even if he never needs it, one had to structure it that way.

{
    "requirement": [
        ["male", "tacos", "team rocket"],
        ["male", "spicynuts", "team rocket"],
        ["female", "tacos", "team rocket"],
        ["female", "spicynuts", "team rocket"]
    ],
    "message": "team rocket rocks my socks!"
}

      

Conclusion

In the end, I decided to let the user decide and support both methods and a combination of the initial and second solutions. You can structure it as before, you can repeat replies with equal messages, or you can attach requirements.

What do we need to change?

One function in the main code file

//Going to show the result according to the asked questions
showResult: function(){
    var tValues = []; //Storing our answers
    for(var i=0, j=this.mJSON.questions.length; i<j; i++)
        if (this.mJSON.questions[i].value) tValues.push(this.mJSON.questions[i].value)

    //Going to store the result text
    var tResult = 'No match for ' + tValues.join(',');

    //Looping through all requirements to get a match
    var tBreak = false; //We use this to double break both loops
    for(var i=0, j=this.mJSON.answers.length; i<j && !tBreak; i++){
        //The requirements which need to match the values
        var tR = this.mJSON.answers[i].requirement;

        //We put simple arrays in a nested array to keep the same logic/process
        var tRR = (typeof tR[0] === 'string') ? [tR] : tR;

        for(var k=0, l=tRR.length; k<l && !tBreak; k++){
            //For this we filter all the elements which do not match the requirements
            var tF = tValues.filter(function(e){return tRR[k].indexOf(e) === -1})

            //If that list is empty, all elements matched and we can stop
            if (!tF || tF.length === 0){
                tResult = this.mJSON.answers[i].message;
                tBreak = true;
            }
        }

        //If that list is empty, all elements matched and we can stop
        if (!tF || tF.length === 0){
            tResult = this.mJSON.answers[i].message;
            break;
        }
    }

    //Now we are going to dislpay the result
    var tH = document.createElement('h1');
    tH.innerHTML = tResult;
    this.mContainer.appendChild(tH)
},

      

And here is a JSON example used for testing

{
    "questions": [
        {"sex": ["male", "female"], "label": "What are you?"},
        {"food": ["tacos", "spicynuts"], "label": "What do you eat?"},
        {"team": ["team a", "team b", "team rocket"], "label": "Where do you belong to?"}
    ],

    "answers": [
        {"requirement": ["male", "tacos", "team a"], "message": "one has chosen male, tacos and team a"},
        {"requirement": ["female", "tacos", "team a"], "message": "one has chosen female, tacos and team a"},

        {"requirement": ["male", "spicynuts", "team a"], "message": "one has chosen male, spicynuts and team a"},
        {"requirement": ["female", "spicynuts", "team a"], "message": "one has chosen male, spicynuts and team a"},

        {
            "requirement": [
                ["male", "tacos", "team rocket"],
                ["male", "spicynuts", "team rocket"],
                ["female", "tacos", "team rocket"],
                ["female", "spicynuts", "team rocket"]
            ],
            "message": "team rocket rocks my socks!"
        }
    ]
}

      

+3


source


I think it could be better, but here's a start.

Put all logic in an array.



http://jsfiddle.net/1exsro2b/1/

var logics = {
    idOfDiv: [{idOfInput: valueOfInput ,name:'asd',gender:'female'} , {name:'bbb'}],
    ifn2: [{num:1}],
    ifn3: [{gender:'male'}],
    ifn4: [{name:'zxc'}]
};

/*
basically give ids to divs that you want to show conditionally starting with ifn and in array put logic [{formEleId: value, ...},{...or logic..}]
*/

var rules = Object.keys(logics);
var divs = $('div[class^=ifn]').hide();
var form = $("#inputs");

updateForm();

form.on('input change', function () {
    updateForm();
    console.log($('#gender')[0]);
});

function updateForm() {
    divs.hide();
    rules.forEach(function (k) {
        var ele = divs.filter("." + k);
        logics[k].forEach(function(l) {
            applyRules(l,ele);
        });
    });
}

function applyRules(l, ele){
    var ids = Object.keys(l);
    var valid = true;
    ids.forEach(function(id){
        var input = form.find('#'+id);
        if (input.children('input:radio').length>0){
            input = input.children('input[type=radio]:checked');
        }
        if (input.val() != l[id]) valid = false;
    });
    if (valid) ele.show();
}

      

+3


source


Try the following:

$('input[type=radio]').change(function(){
var val1=$('input[name="sex"]:checked', '#page1').val()
var val2=$('input[name="food"]:checked', '#page1').val()

 if (val1 == "male" && val2== "tacos") {
    $('#resultsONE').show();   
  } else if () {
    // do
  } else {
    // do
  }

});

      

This is just sample logic, it might need adjustment to make it work for you

+2


source


How to use attributes data

to simplify the process?

<div class="page1" data-answer-div="results-one">
    <form class="sampler">
        <input type="radio" name="sex" value="male" checked="checked" data-answer="a1" />Male
        <input type="radio" name="sex" value="female" data-answer="a2" />Female
    </form>
</div>

<div id="results-one">
    <div class="a a1">
        <p>Congratulations, you are NOT the father</p>
    </div>
    <div class="a a2">
        <p>Congratulations, you are NOT the mother</p>
    </div>
</div>

      

Then when the input changes, you can hide any div with a class .a

within answer-div

. So, in the above example, you have to hide div.a

in #results-one

and then show the div with the appropriate class a[n]

.

$('input').change(function () {
    var answerDiv = $(this).closest('div').data('answer-div');
    $('#' + answerDiv).find('div.a').hide();
    $('#' + answerDiv).find('div.' + $(this).data('answer')).show();
});

      

Here is a violin , and here is a violin with several shapes.

+1


source


While there are many ways to answer this question, I'm going to add AngularJS to the mix, mainly because it looks like a library that the OP might be looking for (without asking).

angular.module('angularSolution', []).controller('angularController', function($scope) {

  // initialize values
  $scope.sex = "male";
  $scope.food = "tacos";
  $scope.hideResultsONE = false;

  // function called when a radio button is clicked
  $scope.radioChange = function() {

    // this could be one line of code, but I find it easier to read using all five lines
    if ($scope.sex == "male" && $scope.food == "tacos") {
      $scope.hideResultsONE = false;
    } else {
      $scope.hideResultsONE = true;
    }

  }
});
      

<!doctype HTML>
<html data-ng-app="angularSolution">

<body data-ng-controller="angularController">
  <div class="page1">
    <form class="sampler">
      <input type="radio" name="sex" value="male" data-ng-model="sex" data-ng-change="radioChange()">Male
      <br>
      <input type="radio" name="sex" value="female" data-ng-model="sex" data-ng-change="radioChange()">Female
    </form>
  </div>
  <div class="page2">
    <form class="sampler">
      <input type="radio" name="food" value="tacos" data-ng-model="food" data-ng-change="radioChange()">Tacos
      <br>
      <input type="radio" name="food" value="spicynuts" data-ng-model="food" data-ng-change="radioChange()">Rotten Spicy Peanuts
    </form>
  </div>
  <div id="resultsONE" data-ng-hide="hideResultsONE">
    <!-- one results div is display none by default sample but there would be much more content here  -->
    <p>Congratulations, you are NOT the father</p>
  </div>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</body>

</html>
      

Run codeHide result


If you like, you can put an expression to define whether to show or hide the div inside the data-ng-hide attribute, but I actually prefer it in code. It is less hidden in this way.

Basically this is the same answer as others, but AngularJS has two-way data associated with variables. There are many other things AngularJS will do for you, but that is beyond the scope of this question.

If you look at your source code in the question, it's pretty close. Data binding means the variables in the $ scope are already set up with values, and showing or hiding just means setting another variable rather than calling the function directly, but all that really remains in the function is the logic you described.

+1


source


Instead of using complex if statements, I would suggest adding a data attribute to your divs that includes a combination of the selection that this div show requires.

I replaced the values โ€‹โ€‹with numeric references to keep the code simple, but it works anyway.

Hope I understood your requirements correctly.

http://jsfiddle.net/kxsb00ps/

HTML:

<div class="page">
    <form class="sampler">
        <input type="radio" name="sex" value="1" />Male
        <br/>
        <input type="radio" name="sex" value="2" />Female</form>
</div>
<div class="page">
    <form class="sampler">
        <input type="radio" name="food" value="1" />Tacos
        <br/>
        <input type="radio" name="food" value="2" />Rotten Spicy Peanuts</form>
</div>
<input id="submitBtn" type="button" value="submit"/>
<div class="results">
    <div data-selection="1,1" >
        <p>You are a male who likes Tacos</p>
    </div>
    <div data-selection="2,1">
        <p>You are a female who likes Tacos</p>
    </div>
    <div data-selection="1,2">
        <p>You are a male who likes Rotten Spicy Peanuts</p>
    </div>
    <div data-selection="2,2">
        <p>You are a female who likes Rotten Spicy Peanuts</p>
    </div>    
</div>

      

JavaScript (using jQuery for selectors):

$("#submitBtn").click(function(){
    // create an empty array
    var selectedData = [];
    // iterate each page
    $(".page").each(function(){
        // place the selections in an array
        selectedData.push($(this).find("input[type=radio]:checked").val());
    });

    // clear previous results
    $(".results > div").hide();

    // find the div using the data attribute
    $(".results").find("[data-selection='" + selectedData + "']").show();
});

      

+1


source


One easy way is to concatenate the selected values โ€‹โ€‹with the div name you want to display. For example, if you have values โ€‹โ€‹selected for men and tacos, a div named "male-tacos" is displayed.

<html>
    <head>
        <style>
            .result{display: none}
            .page{margin: 10px}
        </style>

        <script>
            //Binding the radio change even on all radio boxes contained in page classes
            function Init(){
                var tL = document.querySelectorAll('.page input[type="radio"]');
                for(var i=0, j= tL.length; i<j; i++) tL[i].onchange = function(){evalAnswers()}
            };

            function evalAnswers(){
                //Getting all checked radio buttons
                var tL = document.querySelectorAll('.page input[type="radio"]:checked');

                //Combining the values to get the result name
                var tS = [];
                for(var i=0, j=tL.length; i<j; i++) tS.push(tL[i].value);

                //Getting the result div
                var tR = document.querySelector('[name="' + tS.join('-') + '"]');

                //If we have no result for the combination showing the __unhandled named div
                if (!tR) tR = document.querySelector('[name="__unhandled"]');

                //Hiding all results again (might not be needed if no replay option)
                var tL = document.querySelectorAll('.result');
                for(var i=0, j=tL.length; i<j; i++) tL[i].style.display = 'none';

                //Showing the result
                if (tR) tR.style.display = 'block';
            }
        </script>
    </head>

    <body onload = 'Init()'>
        <!-- page1 looks more like an id than a class -->
        <div class = 'page' id = 'page1'>
            <input type = 'radio' name = 'sex' value = 'male' checked>Male
            <br>
            <input type = 'radio' name = 'sex' value = 'female'>Female
        </div>

        <div class = 'page' id = 'page2'>
            <input type = 'radio' name = 'food' value = 'tacos' checked>Tacos
            <br>
            <input type = 'radio' name = 'food' value = 'spicynuts'>Spicynuts
        </div>

        <div class = 'page' id = 'page3'>
            <input type = 'radio' name = 'color' value = 'red' checked>Red
            <br>
            <input type = 'radio' name = 'color' value = 'blue'>Blue
        </div>

        <!-- the name is the combinations of answers, with this we can select the correct div -->
        <div class = 'result' name = 'male-tacos-red'>
            male-tacos-red
        </div>

        <div class = 'result' name = 'female-tacos-blue'>
            male-tacos-red
        </div>

        <div class = 'result' name = '__unhandled'>
            unhandled result
        </div>
    </body>
</html>

      

http://fiddle.jshell.net/31mebxkk/

Likewise, one can simply change the HTML without worrying about the script itself.

0


source







All Articles