Difference between revisions of "Show a text grid and a single question in the same page"

From Catglobe Wiki
Jump to: navigation, search
 
(6 intermediate revisions by one other user not shown)
Line 35: Line 35:
 
<source lang="javascript" line="1">
 
<source lang="javascript" line="1">
 
var SingleQuestion = {
 
var SingleQuestion = {
onInit: function(_label, _answerOptionValues, _answerOptionTexts)
+
onInit: function(_label, _answerOptionValues, _answerOptionTexts)
{
+
{
this.label = "QUESTION." + _label;
+
this.label = "QUESTION." + _label;
this.aoValues = _answerOptionValues;
+
this.aoValues = _answerOptionValues;
this.aoTexts = _answerOptionTexts;  
+
this.aoTexts = _answerOptionTexts;
this.selectedValue = "";  
+
this.selectedValue = "";
},
+
},
optClick: function(value)
+
optClick: function(value)
{
+
{
if (this.selectedValue == value)//click the checkbox twice => unchecked
+
if (this.selectedValue == value)//click the checkbox twice => unchecked
{
+
{
this.selectedValue = "";
+
this.selectedValue = "";
$("input:text").attr("disabled", "");
+
$("input:text").attr("disabled", "");
$("input:checkbox").attr("checked", "");  
+
$("input:checkbox").attr("checked", "");
}  
+
}
else
+
else
{
+
{
//disable all other inputs
+
//disable all other inputs
this.selectedValue = value;
+
this.selectedValue = value;
$("input:text").attr("disabled", "disabled");
+
$("input:text").attr("disabled", "disabled");
+
$("input:checkbox").each(
+
$("input:checkbox").each(
function(i)
+
function(i)
{
+
{
if ($(this).val() == value)
+
if ($(this).val() == value)
$(this).attr("checked", "checked");  
+
$(this).attr("checked", "checked");
else  
+
else
$(this).attr("checked", "");  
+
$(this).attr("checked", "");
}
+
}
);
+
);
}
+
}
},
+
},
getHTML: function()
+
getHTML: function()
{
+
{
var t = $("<table>");
+
var t = $("<table>");
var n = this.aoValues.length;
+
var n = this.aoValues.length;
for (var i = 0; i<n; i++)
+
for (var i = 0; i<n; i++)
{
+
{
t.append(this.getHTML_AO(i));
+
t.append(this.getHTML_AO(i));
}
+
}
t.append($("<input type = \"hidden\">").attr("name", this.label).val(""));
+
t.append($("<input type = \"hidden\">").attr("name", this.label).val(""));
return t;
+
return t;
},
+
},
getHTML_AO: function(index)
+
getHTML_AO: function(index)
{
+
{
var value = this.aoValues[index];
+
var value = this.aoValues[index];
var text = this.aoTexts[index];
+
var text = this.aoTexts[index];
return $("<tr>")  
+
return $("<tr>")
.append(
+
.append(
$("<td>").width("16px").attr("valign", "top")
+
$("<td>").width("16px").attr("valign", "top")
.append(
+
.append(
$("<input type=\"checkbox\">").attr("name", this.label).val(value).click(
+
$("<input type=\"checkbox\">").attr("name", this.label).val(value).click(
function()
+
function()
{
+
{
SingleQuestion.optClick(value);
+
SingleQuestion.optClick(value);
}
+
}
)
+
)
)
+
)
)
+
)
.append(
+
.append(
$("<td>").append($("<a class=\"option_link\" href=\"javascript:SingleQuestion.optClick(" + value + ");\">" + text + "</a>"))
+
$("<td>").append($("<a class=\"option_link\" href=\"javascript:SingleQuestion.optClick(" + value + ");\">" + text + "</a>"))
);
+
);
}
+
}
 
}
 
}
</source>  
+
</source>
  
 
===== TextGridQuestion object is created, storing the code of validating its value before clicking Next  =====
 
===== TextGridQuestion object is created, storing the code of validating its value before clicking Next  =====
Line 106: Line 106:
 
var TextGridQuestion =  
 
var TextGridQuestion =  
 
{
 
{
onInit: function(_quest)
+
onInit: function(_quest)
{
+
{
this.quest = _quest;
+
this.quest = _quest;
},
+
},
questionCheck: function()
+
questionCheck: function()
{
+
{
acont = new Array();
+
acont = new Array();
msg = "";
+
    msg = "";
cont = true;
+
    cont = true;
  
for (i=0; i < this.quest.questions.length; i++)
+
for (i=0; i < this.quest.questions.length; i++)
acont[i] = (trim(document["query"][this.quest.questions[i].label].value) != "");
+
acont[i] = (trim(document["query"][this.quest.questions[i].label].value) != "");
  
msg = this.quest.ingridrequiredtext+"\n";
+
msg = this.quest.ingridrequiredtext+"\n";
for (i = 0; i < this.quest.questions.length; i++)
+
for (i = 0; i < this.quest.questions.length; i++)
{
+
{
// If the sub question is not visible or answering this
+
// If the sub question is not visible or answering this
// sub question is not answered and not required to be
+
// sub question is not answered and not required to be
// then we continue with the next sub question
+
// then we continue with the next sub question
if(!this.quest.questions[i].visible || (!this.quest.questions[i].required && !acont[i]))
+
if(!this.quest.questions[i].visible || (!this.quest.questions[i].required && !acont[i]))
continue;
+
continue;
  
if(this.quest.questions[i].required && !acont[i])
+
if(this.quest.questions[i].required && !acont[i])
{
+
{
tmp = this.quest.questions[i].text;
+
tmp = this.quest.questions[i].text;
tmp = tmp.replace(/(<!\-\-|\-\->)/ig, "");
+
tmp = tmp.replace(/(<!\-\-|\-\->)/ig, "");
tmp = tmp.replace(/&nbsp;/ig, " ");
+
tmp = tmp.replace(/&nbsp;/ig, " ");
msg += " - '"+trim(tmp.replace(/<[^>]*>/ig, ""))+"'\n";
+
msg += " - '"+trim(tmp.replace(/<[^>]*>/ig, ""))+"'\n";
cont = false;
+
cont = false;
continue;
+
continue;
}  
+
}
}
+
}
  
if (!cont)
+
if (!cont)
{  
+
{
ErrorMessages.getInstance().showErrorMessage(msg);
+
ErrorMessages.getInstance().showErrorMessage(msg);
return false;
+
return false;
}
+
}
return true;
+
return true;
}
+
}
 
}
 
}
</source>  
+
</source>
  
 
===== We also need to override questioncheck function in order not to use the default check of questionnaire viewer, which will give an error when no sub question in the text grid is answered, which is not correct in our case  =====
 
===== We also need to override questioncheck function in order not to use the default check of questionnaire viewer, which will give an error when no sub question in the text grid is answered, which is not correct in our case  =====
Line 154: Line 154:
 
this.questioncheck = function()
 
this.questioncheck = function()
 
{
 
{
ErrorMessages.getInstance().clearErrorMessages();
+
ErrorMessages.getInstance().clearErrorMessages();
if (SingleQuestion.selectedValue != "")
+
if (SingleQuestion.selectedValue != "")
return true;
+
return true;
+
return TextGridQuestion.questionCheck();  
+
return TextGridQuestion.questionCheck();
 
}
 
}
</source>  
+
</source>
  
 
===== Finally, we need to override quest.onInit function to execute the changes  =====
 
===== Finally, we need to override quest.onInit function to execute the changes  =====
Line 167: Line 167:
 
quest.onInit = function()
 
quest.onInit = function()
 
{
 
{
var single = "{{Single.Value}}";
+
var single = "{{Single.Value}}";
var aoV = new Array();
+
var aoV = new Array();
aoV[0] = 1;
+
aoV[0] = 1;
aoV[1] = 2;
+
aoV[1] = 2;
var aoT = new Array();
+
var aoT = new Array();
aoT[0] = "I do not want to give those information";
+
aoT[0] = "I do not want to give those information";
aoT[1] = "I do not have time for this"
+
aoT[1] = "I do not have time for this"
SingleQuestion.onInit("Single", aoV, aoT);
+
SingleQuestion.onInit("Single", aoV, aoT);
+
//look for the outer grid
+
//look for the outer grid
$(".grid_outer").append(
+
$(".grid_outer").append(
$("<tr>").css("background-color", "white").append($("<td>").append(SingleQuestion.getHTML()))  
+
$("<tr>").css("background-color", "white").append($("<td>").append(SingleQuestion.getHTML()))
);
+
);
+
if (single != "")
+
if (single != "")
{
+
{
SingleQuestion.optClick(single);
+
SingleQuestion.optClick(single);
}
+
}
+
TextGridQuestion.onInit(this);
+
TextGridQuestion.onInit(this);
$("input:text").width("200px");
+
$("input:text").width("200px");
 
}
 
}
 
</source>
 
</source>
 +
 +
== Code sample ==
 +
 +
Open the qnaire "Js demo - some js samples" (Resource Id: 159684). View the Question "Q_TextGrid"

Latest revision as of 05:39, 10 February 2012

Challenge

In order to allow the respondent to skip a text grid question

As a questionnaire creator

I want to show several options at the end of a text grid question, on which the respondents can click to skip the text grid question.

(This is quite similar to question of Open type)

Example

When there is no checkbox checked, the text boxes in the grid are enabled so that we can enter the texts.

QuestionTips TextGrid Enabled.jpg 

When a checkbox is checked, the textboxes are disabled.

QuestionTips TextGrid Disabled.jpg 

Solution

  • Create 2 questions: TextGrid and Single
  • Single is set as a dummy question
  • Add javascript to TextGrid to include Single's HTML to the question's HTML
  • Make sure when clicking a checkbox, other checkboxes are unchecked and the textboxes are disabled
  • Check if there is an option selected or no textbox is left empty when clicking Next
  • Load the saved value when loading the question
  • Save the value entered to the two questions

Code

We should create a SingleQuestion object containing functions to generate its own HTML and handle its checkbox click events.
 1 var SingleQuestion = {
 2 	onInit: function(_label, _answerOptionValues, _answerOptionTexts)
 3 	{
 4 		this.label = "QUESTION." + _label;
 5 		this.aoValues = _answerOptionValues;
 6 		this.aoTexts = _answerOptionTexts;		
 7 		this.selectedValue = "";		
 8 	},
 9 	optClick: function(value)
10 	{
11 		if (this.selectedValue == value)//click the checkbox twice => unchecked
12 		{
13 			this.selectedValue = "";
14 			$("input:text").attr("disabled", "");
15 			$("input:checkbox").attr("checked", "");			
16 		}		
17 		else
18 		{
19 			//disable all other inputs
20 			this.selectedValue = value;
21 			$("input:text").attr("disabled", "disabled");
22 			
23 			$("input:checkbox").each(
24 				function(i)
25 				{
26 					if ($(this).val() == value)
27 						$(this).attr("checked", "checked");														
28 					else					
29 						$(this).attr("checked", "");						
30 				}
31 			);
32 		}
33 	},
34 	getHTML: function()
35 	{
36 		var t = $("<table>");
37 		var n = this.aoValues.length;
38 		for (var i = 0; i<n; i++)
39 		{
40 			t.append(this.getHTML_AO(i));
41 		}
42 		t.append($("<input type = \"hidden\">").attr("name", this.label).val(""));
43 		return t;
44 	},
45 	getHTML_AO: function(index)
46 	{
47 		var value = this.aoValues[index];
48 		var text = this.aoTexts[index];
49 		return $("<tr>")		
50 			.append(
51 				$("<td>").width("16px").attr("valign", "top")
52 					.append(
53 						$("<input type=\"checkbox\">").attr("name", this.label).val(value).click(
54 							function()
55 							{
56 								SingleQuestion.optClick(value);
57 							}
58 						)
59 					)
60 			)
61 			.append(
62 				$("<td>").append($("<a class=\"option_link\" href=\"javascript:SingleQuestion.optClick(" + value + ");\">" + text + "</a>"))
63 			);
64 	}
65 }
TextGridQuestion object is created, storing the code of validating its value before clicking Next
 1 var TextGridQuestion = 
 2 {
 3 	onInit: function(_quest)
 4 	{
 5 		this.quest = _quest;
 6 	},
 7 	questionCheck: function()
 8 	{
 9 		acont = new Array();
10 	    msg = "";
11 	    cont = true;
12 
13 		for (i=0; i < this.quest.questions.length; i++)
14 			acont[i] = (trim(document["query"][this.quest.questions[i].label].value) != "");
15 
16 		msg = this.quest.ingridrequiredtext+"\n";
17 		for (i = 0; i < this.quest.questions.length; i++)
18 		{
19 			// If the sub question is not visible or answering this
20 			// sub question is not answered and not required to be
21 			// then we continue with the next sub question
22 			if(!this.quest.questions[i].visible || (!this.quest.questions[i].required && !acont[i]))
23 				continue;
24 
25 			if(this.quest.questions[i].required && !acont[i])
26 			{
27 				tmp = this.quest.questions[i].text;
28 				tmp = tmp.replace(/(<!\-\-|\-\->)/ig, "");
29 				tmp = tmp.replace(/&nbsp;/ig, " ");
30 				msg += " - '"+trim(tmp.replace(/<[^>]*>/ig, ""))+"'\n";
31 				cont = false;
32 				continue;
33 			}			
34 		}
35 
36 		if (!cont)
37 		{	
38 			ErrorMessages.getInstance().showErrorMessage(msg);
39 			return false;
40 		}
41 		return true;
42 	}
43 }
We also need to override questioncheck function in order not to use the default check of questionnaire viewer, which will give an error when no sub question in the text grid is answered, which is not correct in our case
1 this.questioncheck = function()
2 {
3 	ErrorMessages.getInstance().clearErrorMessages();
4 	if (SingleQuestion.selectedValue != "")
5 		return true;
6 	
7 	return TextGridQuestion.questionCheck();	
8 }
Finally, we need to override quest.onInit function to execute the changes
 1 quest.onInit = function()
 2 {
 3 	var single = "{{Single.Value}}";
 4 	var aoV = new Array();
 5 	aoV[0] = 1;
 6 	aoV[1] = 2;
 7 	var aoT = new Array();
 8 	aoT[0] = "I do not want to give those information";
 9 	aoT[1] = "I do not have time for this"
10 	SingleQuestion.onInit("Single", aoV, aoT);
11 		
12 	//look for the outer grid
13 	$(".grid_outer").append(
14 		$("<tr>").css("background-color", "white").append($("<td>").append(SingleQuestion.getHTML()))	
15 	);
16 	
17 	if (single != "")
18 	{
19 		SingleQuestion.optClick(single);
20 	}
21 	
22 	TextGridQuestion.onInit(this);
23 	$("input:text").width("200px");
24 }

Code sample

Open the qnaire "Js demo - some js samples" (Resource Id: 159684). View the Question "Q_TextGrid"