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!
答案 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)
所以基本上,所搜索的是一个包含单选按钮和结果的简单表单,它应该与无线电选择的组合相匹配。根据问题,问题应该易于维护和改变,而不总是触及脚本或其初始逻辑。 投票支持外包问题和逻辑 - 将其与DOM分开。
在问题标签中提到并且进一步可见的是php和ajax。鉴于可能希望完全外包问题并通过ajax从php中获取它们。 外包投票。
为了简洁,我们可以在下面(但请注意我正在寻找一些可扩展的建议,因为我的网页表格将分别有7个问题和5个答案。我有5个结果div)
为了使其易于维护,问题和答案将被外包到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>
{
"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();
});
答案 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显示所需的选择组合。
我已经用数字引用替换了这些值以保持代码简单,但无论哪种方式都可以。
希望我的要求合适。
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而不用担心脚本本身。