display result divs based on web form radio button selections

时间:2015-06-30 19:27:22

标签: javascript php jquery ajax json

I would like to simply .show() a div based on a web forms radio button (user) selections.

For brevity lets take below (but note I'm looking for somewhat scaleable advice as 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 will need an array with 5 possible answer combinations via user radio button selection, ideally using the input 'value' field; so I can simply change the values of what value combos would equal what div results screen. The div results screens will just be 5 unique sets of content inside the div, that's it.


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 the below is terrible syntax; but this was the logic I was thinking about starting with on 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 simply use the SELECTED input value=""; so they can be changed somewhat easily.

Example.


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

May be open to php options.

Thanks for taking a look!

7 个答案:

答案 0 :(得分:3)

我认为它可能会更好,但这是开始。

将所有逻辑放在数组中。

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();
}

答案 1 :(得分:3)

根据网络表单单选按钮选择显示结果div

取得什么成果?

所以基本上,所搜索的是一个包含单选按钮和结果的简单表单,它应该与无线电选择的组合相匹配。根据问题,问题应该易于维护和改变,而不总是触及脚本或其初始逻辑。 投票支持外包问题和逻辑 - 将其与DOM分开。

如何实现?

在问题标签中提到并且进一步可见的是php和ajax。鉴于可能希望完全外包问题并通过ajax从php中获取它们。 外包投票。

实现这一目标需要什么?

  • 是否需要任何框架和/或库?不一定,但它可能是有用的
    • 检索JSON
    • 创建DOM元素
  • 我们是否一直需要DOM中的所有问题和答案?不是真的
  

为了简洁,我们可以在下面(但请注意我正在寻找一些可扩展的建议,因为我的网页表格将分别有7个问题和5个答案。我有5个结果div)

  1. 我建议动态创建DOM,因为 - 直到现在 - 没有理由一直保留它,这使得HTML文件本身看起来更加纤薄和整洁。
  2. 此外,还可以分离布局,结构,逻辑和数据,最终允许您通过更改一个文件来更改答案和问题。
  3. 使用这样的方法,您可以使用不同的问题创建更多表单,但代码相同。
  4. 如果您尚未使用任何库/框架,请不要仅为此脚本添加一个。
  5. 结论

    为了使其易于维护,问题和答案将被外包到json文件(此处为JSON.js)。鉴于此,还可以通过php或任何web服务检索它和/或将它们存储在数据库中。此外,还提供了创建具有不同问题的多个表单的可能性,这些问题都使用相同的代码。

    There is a Fiddle available for it

    代码

    <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>
    

    和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"}
        ]
    }
    

    编辑:

    在写我的建议时,我遇到了一个小问题。鉴于你的解释“有七个问题和五个结果”。某些结果是分享结果还是没有结果?

    更改

    为了解决共享结果问题,我认为有两种方式我认为输入和维护最简单。

    我们列出结果两次

    这个解决方案可能听起来很愚蠢而且太简单了。但它易于维护和管理。明显的缺点是缺乏数据完整性。

    {"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!"
    }
    

    结论

    最后,我决定让用户决定并支持这两种方法以及初始和解决方案二的组合。人们可以像以前一样构建它,可以用相同的信息重复答案,也可以嵌套要求。

    我们需要改变什么?

    主代码文件中的一个功能

    //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)
    },
    

    以下是用于测试的示例JSON

    {
        "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!"
            }
        ]
    }
    

答案 2 :(得分:2)

试试这个:

$('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
  }

});

这只是示例逻辑,可能需要一些调整以使其适合您

答案 3 :(得分:1)

如何使用data属性来简化流程?

<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>

然后,当输入更改时,您可以隐藏.a内的answer-div类的所有div。因此,在上面的示例中,您隐藏div.a中的#results-one,然后使用相应的a[n]类显示div。

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

Here's a fiddlehere's a fiddle with multiple forms.

答案 4 :(得分:1)

虽然有很多方法可以解决这个问题,但我会将AngularJS添加到组合中,主要是因为它看起来像OP可能正在寻找的库(没有真正要求它)。

false
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;
    }

  }
});

如果你愿意,可以使用表达式来确定是否在data-ng-hide属性中显示或隐藏div,但实际上我更喜欢它在代码中。它不那么隐藏。

基本上,这与其他人给出的答案相同,但AngularJS具有绑定变量的双向数据。 AngularJS还会为您做很多其他事情,但这超出了这个问题的范围。

如果你回头查看问题中的原始代码,那就非常接近了。数据绑定意味着$ scope中的变量已经设置了值,并且显示或隐藏仅仅意味着设置另一个变量,而不是直接调用函数,但实际上留在函数中的所有内容都是您描述的逻辑。

答案 5 :(得分:1)

我建议在div上添加一个数据属性,而不是使用复杂的if语句,其中包括div显示所需的选择组合。

我已经用数字引用替换了这些值以保持代码简单,但无论哪种方式都可以。

希望我的要求合适。

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(使用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();
});

答案 6 :(得分:0)

一种简单的方法是将所选值组合到要显示的div名称。例如,如果选择了male和tacos的值,则会显示名为'male-tacos'的div。

<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/

就像这样,人们可能只是改变HTML而不用担心脚本本身。