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

3
我想根据网页表单上用户的选择,通过 .show() 方法显示一个 div
为了简洁起见,我们来看下面的例子(但请注意,我需要的建议是可扩展的,因为我的网络表单将有7个问题和每个问题5个答案。并且我有5个结果 divs)。 注意:基本上会有7个问题,每个问题有5个答案。因此,我将需要一个包含5个可能的答案组合的数组,由用户单选按钮选择,理想情况下使用 "value" 字段;这样我就可以轻松更改哪些值组合将等于哪个 div 结果屏幕。 div 结果屏幕只是 div 内的 5 个唯一内容集。
标记:
<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>

虽然下面的语法很糟糕,但这是我想从JS的角度开始思考的逻辑。请注意,我将拥有5个唯一的结果#divs


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

如我上面所提到的; 我正在寻找一种方法,可以简单地使用 SELECTED 输入 value="" ; 这样它们可以相对容易地更改。 < p > 例如。


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

可能会开放php选项。

感谢您的关注!


结果 div 位于哪里?根据您的函数,我们应该如何知道哪个结果组合应导致显示 div? - j08691
问题已更新。 - Coastal-Cam
你还需要关于这个问题的帮助吗? - Lain
是的,赏金还剩6天。我会在那之前用有效的方法关闭它。 - Coastal-Cam
你能指出当前答案的问题在哪里吗?我看到有不止一个答案似乎回答了更新后的问题。如果不知道为什么当前的答案不符合你的要求,很难给出更好的答案。 - Guy Schalnat
7个回答

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

你可以模拟和、或逻辑,但还没有实现非逻辑,只有范围值。 - Muhammad Umer
1
我想看到这里的所有代码,而不仅仅是其中一部分,但这似乎非常强大(实际上比OP要求的更强大,但这并不是坏事)。我很好奇为什么它没有被OP接受。 - Guy Schalnat
1
@GuySchalnat 应该有一个库可以做到这一点...我一直觉得jQuery不是将大量手动逻辑放入代码的好工具,因为它太混乱了。 - Muhammad Umer

3

基于Web表单单选按钮选择显示结果Div

实现目标

简单来说,所需的是一个包含单选按钮和结果的简单表单,这些结果应该与单选结果的组合匹配。根据问题,问题应该易于维护和更改,而不必总是接触脚本或其初始逻辑。 这就要求将问题和逻辑外包 - 使其与DOM分离。

如何实现?

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

需要什么才能实现?

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

为了简洁起见,让我们采取下面的(但请注意,我正在寻找相对可扩展的建议,因为我的Web表单每个具有7个问题和5个答案。而且我有5个结果divs)

  1. 我建议即兴创建DOM,因为截至目前还没有必要一直保持它,并且它使HTML文件本身看起来更加简洁整洁。
  2. 此外,可以将布局、结构、逻辑和数据分离,最终使您能够通过更改一个文件来更改答案和问题。
  3. 使用这种方法,您可以创建具有不同问题的更多表单,但使用相同的代码。
  4. 如果您尚未使用任何库/框架,则不要添加一个只是为了此脚本。

结论

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

这里提供了可用的Fiddle

代码

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

一些结果可能会共享结果。对此有什么建议吗?我已经接受了您的答案,因为这是我最喜欢的逻辑,但希望“共享结果”不会有问题。有什么想法吗?没有任何结果为零的情况。如果您对答案没有任何简单的编辑建议,这可以分支成一个新问题。 - Coastal-Cam
1
@YourConscious:不幸的是,我还要工作几个小时。但如果你有时间和耐心,我很乐意考虑一个扩展版本。 - JavaScript
@YourConscious:这就是你要的。 - JavaScript

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
  }

});

这只是示例逻辑,可能需要一些调整才能使其适合您的情况。


1

建议您在div上添加数据属性,而不是使用复杂的if语句来显示需要选择的组合。

为了保持代码简单,我已经用数字引用替换了值,但两种方式都可以实现。

希望我理解您的要求正确。

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进行选择器):

$("#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
虽然有许多方法可以回答这个问题,但我打算加入AngularJS,主要是因为它看起来有点像OP可能正在寻找的库(尽管没有真正要求)。

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>

如果你愿意的话,可以把用来决定是否显示或隐藏div的表达式放在data-ng-hide属性中,但我实际上更喜欢把它放在代码中。这样做更加明显一些。 基本上,这与其他人给出的答案相同,但AngularJS双向数据绑定了变量。AngularJS还有很多其他功能,但这超出了本问题的范围。 如果你回顾一下你在问题中的原始代码,这就非常接近了。数据绑定意味着$scope中的变量已经设置了值,显示或隐藏只是设置另一个变量,而不是直接调用函数,但在函数中真正剩下的只是你描述的逻辑。

我已经选择了我偏好的最佳答案,但我认为你的答案在JSON被接受的答案之后排名第二。+1 - Coastal-Cam
我也喜欢被接受的答案。这里总会有不止一个有效的答案,哪一个对你或其他寻求类似解决方案的人最好取决于具体问题的细节(有多少个问题和答案以及逻辑有多复杂),而不是其中一个严格优于另一个。我很高兴我们能提供不同的选择,我自己也点赞了其他几个答案。 - Guy Schalnat

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>

然后,当输入发生变化时,您可以隐藏位于answer-div内具有类.a的任何div。因此,在上面的示例中,您将隐藏#results-one中的div.a,然后显示相应的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();
});

这里有一个示例代码, 而这里有一个包含多个表单的示例代码


我不完全确定,但似乎问题应该被评估为组合(即男性 && 墨西哥卷饼),而不是分开地。至少这是我理解帖子的方式。 - Lain

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而不必担心脚本本身。


1
虽然我会使用数据属性而不是名称(以及库而不是纯JavaScript),但我喜欢这个答案中的概念。它使得控制显示哪些div变得非常容易。不,它没有将逻辑和标记分开,但OP想要简单的东西,而且它很容易控制。 - Guy Schalnat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接